/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="<a id='"+S+"'></a><select id='"+S+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(B," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace($,"$1"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[S]&&(v=Ce(v)),y&&!y[S]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace($,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace($," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=A[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=S.split("").sort(D).join("")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[":"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(D(this,e||[],!1))},not:function(e){return this.pushStack(D(this,e||[],!0))},is:function(e){return!!D(this,"string"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var j,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t,n){return h(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return h(e,"nextSibling")},prevAll:function(e){return h(e,"previousSibling")},nextUntil:function(e,t,n){return h(e,"nextSibling",n)},prevUntil:function(e,t,n){return h(e,"previousSibling",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,"template")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[["notify","progress",S.Callbacks("memory"),S.Callbacks("memory"),2],["resolve","done",S.Callbacks("once memory"),S.Callbacks("once memory"),0,"resolved"],["reject","fail",S.Callbacks("once memory"),S.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),S.ready()}S.fn.ready=function(e){return F.then(e)["catch"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var $=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)$(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,"ms-").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(K,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){Q.set(this,n)}):$(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Y.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,te=new RegExp("^(?:([+-])=|)("+ee+")([a-z%]*)$","i"),ne=["Top","Right","Bottom","Left"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&ie(e)&&"none"===S.css(e,"display")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,"")},u=s(),l=n&&n[3]||(S.cssNumber[t]?"":"px"),c=e.nodeType&&(S.cssNumber[t]||"px"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Y.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ue[s]=u)))):"none"!==n&&(l[c]="none",Y.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="<option></option>",y.option=!!ce.lastChild;var ge={thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],"globalEval",!t||Y.get(t[n],"globalEval"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,y.option||(ge.optgroup=ge.option=[1,"<select multiple='multiple'>","</select>"]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}var be=/^key/,we=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ce(){return!0}function Ee(){return!1}function Se(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ee;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Ae(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,Ce)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(P)||[""]).length;while(l--)d=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.hasData(e)&&Y.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(P)||[""]).length;while(l--)if(d=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||S.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,"events")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click",Ce),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Y.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ce:Ee,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Ee,isPropagationStopped:Ee,isImmediatePropagationStopped:Ee,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ce,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ce,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ce,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&be.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&we.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},S.event.addProp),S.each({focus:"focusin",blur:"focusout"},function(e,t){S.event.special[e]={setup:function(){return Ae(this,e,Se),!1},trigger:function(){return Ae(this,e),!0},delegateType:t}}),S.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return ke(this,e,t,n,r)},one:function(e,t,n,r){return ke(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Ee),this.each(function(){S.event.remove(this,e,n,t)})}});var Ne=/<script|<style|<link/i,De=/checked\s*(?:[^=]|=\s*.checked.)/i,je=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function Pe(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&De.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Pe(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ve(e,"script"),Le)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,He),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Y.access(u,"globalEval")&&S.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):b(u.textContent.replace(je,""),u,l))}return n}function Re(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ve(r)),r.parentNode&&(n&&ie(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Oe(o[r],a[r]);else Oe(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Re(this,e,!0)},remove:function(e){return Re(this,e)},text:function(e){return $(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Pe(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||qe(this,e).appendChild(e)})},prepend:function(){return Pe(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=qe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return $(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ne.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Pe(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Me=new RegExp("^("+ee+")(?!px)[a-z%]+$","i"),Ie=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},We=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Fe=new RegExp(ne.join("|"),"i");function Be(e,t,n){var r,i,o,a,s=e.style;return(n=n||Ie(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||ie(e)||(a=S.style(e,t)),!y.pixelBoxStyles()&&Me.test(a)&&Fe.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function $e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement("div"),l=E.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===l.style.backgroundClip,S.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement("table"),t=E.createElement("tr"),n=E.createElement("div"),e.style.cssText="position:absolute;left:-11111px",t.style.height="1px",n.style.height="9px",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=3<parseInt(r.height),re.removeChild(e)),a}}))}();var _e=["Webkit","Moz","ms"],ze=E.createElement("div").style,Ue={};function Xe(e){var t=S.cssProps[e]||Ue[e];return t||(e in ze?e:Ue[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=_e.length;while(n--)if((e=_e[n]+t)in ze)return e}(e)||e)}var Ve=/^(none|table(?!-c[ea]).+)/,Ge=/^--/,Ye={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ke(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?("content"===n&&(u-=S.css(e,"padding"+ne[a],!0,i)),"margin"!==n&&(u-=S.css(e,"border"+ne[a]+"Width",!0,i))):(u+=S.css(e,"padding"+ne[a],!0,i),"padding"!==n?u+=S.css(e,"border"+ne[a]+"Width",!0,i):s+=S.css(e,"border"+ne[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Ie(e),i=(!y.boxSizingReliable()||n)&&"border-box"===S.css(e,"boxSizing",!1,r),o=i,a=Be(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(Me.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||!y.reliableTrDimensions()&&A(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===S.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===S.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?"border":"content"),o,r,a)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Ge.test(t),l=e.style;if(u||(t=Xe(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Ge.test(t)||(t=Xe(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),"normal"===i&&t in Qe&&(i=Qe[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each(["height","width"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ve.test(S.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):We(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Ie(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===S.css(e,"boxSizing",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,"border",!1,i)-.5)),s&&(r=te.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=$e(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,"marginLeft"))||e.getBoundingClientRect().left-We(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),S.each({margin:"",padding:"",border:"Width"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return $(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Ie(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Xe(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ne[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),v=Y.get(e,"fxshow");for(r in n.queue||(null==(a=S._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Y.get(e,"display")),"none"===(c=S.css(e,"display"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,"display"),le([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===S.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Y.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,"fxshow"),d)S.style(e,r,d[r])})),u=ct(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&"object"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Y.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each(["toggle","show","hide"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt("show"),slideUp:lt("hide"),slideToggle:lt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement("input"),it=E.createElement("select").appendChild(E.createElement("option")),rt.type="checkbox",y.checkOn=""!==rt.value,y.optSelected=it.selected,(rt=E.createElement("input")).value="t",rt.type="radio",y.radioValue="t"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return $(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function vt(e){return(e.match(P)||[]).join(" ")}function yt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return $(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,"tabindex");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).addClass(t.call(this,e,yt(this)))});if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).removeClass(t.call(this,e,yt(this)))});if(!arguments.length)return this.attr("class","");if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){S(this).toggleClass(i.call(this,e,yt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=S(this),r=mt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=yt(this))&&Y.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Y.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+vt(yt(n))+" ").indexOf(t))return!0;return!1}});var xt=/\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?"":e+""})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,"value");return null!=t?t:vt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each(["radio","checkbox"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},y.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[S.expando]?e:new S.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,"events")||Object.create(null))[e.type]&&Y.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),y.focusin||S.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\?/;S.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||S.error("Invalid XML: "+e),t};var St=/\[\]$/,kt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function Dt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):Dt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)Dt(n+"["+t+"]",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)Dt(n,e[n],t,i);return r.join("&")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,"elements");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(":disabled")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,"\r\n")}}):{name:t.name,value:n.replace(kt,"\r\n")}}).get()}});var jt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=E.createElement("a");function Ft(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Bt(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function $t(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?$t($t(e,S.ajaxSettings),t):$t(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=S.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?S(y):S.event,x=S.Deferred(),b=S.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Tt.href)+"").replace(Pt,Tt.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(P)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Wt.protocol+"//"+Wt.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=S.param(v.data,v.traditional)),Bt(Rt,v,t,T),h)return T;for(i in(g=S.event&&v.global)&&0==S.active++&&S.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Ot.test(v.type),f=v.url.replace(qt,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(jt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(Et.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Lt,"$1"),o=(Et.test(f)?"&":"?")+"_="+Ct.guid+++o),v.url=f+o),v.ifModified&&(S.lastModified[f]&&T.setRequestHeader("If-Modified-Since",S.lastModified[f]),S.etag[f]&&T.setRequestHeader("If-None-Match",S.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+It+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Bt(Mt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<S.inArray("script",v.dataTypes)&&(v.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(S.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(S.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--S.active||S.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,"json")},getScript:function(e,t){return S.get(e,void 0,t,"script")}}),S.each(["get","post"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();y.cors=!!zt&&"withCredentials"in zt,y.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(y.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),S.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=vt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&S.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?S("<div>").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?"":(e+"").replace(Gt,"")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return S});var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S}); 
/*! jQuery Validation Plugin - v1.19.5 - 7/1/2022
 * https://jqueryvalidation.org/
 * Copyright (c) 2022 Jörn Zaefferer; Licensed MIT */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!(c.settings.submitHandler&&!c.settings.debug)||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0],k="undefined"!=typeof this.attr("contenteditable")&&"false"!==this.attr("contenteditable");if(null!=j&&(!j.form&&k&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}});var b=function(a){return a.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};a.extend(a.expr.pseudos||a.expr[":"],{blank:function(c){return!b(""+a(c).val())},filled:function(c){var d=a(c).val();return null!==d&&!!b(""+d)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");if(!this.form&&c&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name")),d===this.form){var e=a.data(this.form,"validator"),f="on"+b.type.replace(/^validate/,""),g=e.settings;g[f]&&!a(this).is(g.ignore)&&g[f].call(e,this,b)}}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.currentForm,e=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){e[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").trigger("focus").trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name"),e="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),e&&(this.form=a(this).closest("form")[0],this.name=d),this.form===b.currentForm&&(!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0))})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type,g="undefined"!=typeof e.attr("contenteditable")&&"false"!==e.attr("contenteditable");return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=g?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);"function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f&&(j=f.call(b,j),delete g.normalizer);for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=".  Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]},defaultMessage:function(b,c){"string"==typeof c&&(c={method:c});var d=this.findDefined(this.customMessage(b.name,c.method),this.customDataMessage(b,c.method),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c.method],"<strong>Warning: No message defined for "+b.name+"</strong>"),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return void 0===a?"":a.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()&&0===this.pendingRequest?(a(this.currentForm).trigger("submit"),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a["date"===b?"dateISO":c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),""===d&&(d=!0),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(a,d){b[a]="function"==typeof d&&"normalizer"!==a?d(c):d}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var a;b[this]&&(Array.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(a=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(a[0]),Number(a[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:void 0!==b&&null!==b&&b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(){var a=!1;return function(b,c){return a||(a=!0,this.settings.debug&&window.console&&console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")),this.optional(c)||!/Invalid|NaN/.test(new Date(b).toString())}}(),dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d>=c},maxlength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d<=c},rangelength:function(a,b,c){var d=Array.isArray(a)?a.length:this.getLength(a,b);return this.optional(b)||d>=c[0]&&d<=c[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var c,d={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,c){var e=a.port;"abort"===a.mode&&(d[e]&&d[e].abort(),d[e]=c)}):(c=a.ajax,a.ajax=function(b){var e=("mode"in b?b:a.ajaxSettings).mode,f=("port"in b?b:a.ajaxSettings).port;return"abort"===e?(d[f]&&d[f].abort(),d[f]=c.apply(this,arguments),d[f]):c.apply(this,arguments)}),a});
/**
 * @license
 * Unobtrusive validation support library for jQuery and jQuery Validate
 * Copyright (c) .NET Foundation. All rights reserved.
 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 * @version v4.0.0
 */
!function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(s){var a,o=s.validator,d="unobtrusiveValidation";function l(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function u(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function n(a){return a.substr(0,a.lastIndexOf(".")+1)}function m(a,e){return a=0===a.indexOf("*.")?a.replace("*.",e):a}function f(a){var e=s(this),n="__jquery_unobtrusive_validation_form_reset";if(!e.data(n)){e.data(n,!0);try{e.data("validator").resetForm()}finally{e.removeData(n)}e.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),e.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function p(n){function a(a,e){(a=r[a])&&s.isFunction(a)&&a.apply(n,e)}var e=s(n),t=e.data(d),i=s.proxy(f,n),r=o.unobtrusive.options||{};return t||(t={options:{errorClass:r.errorClass||"input-validation-error",errorElement:r.errorElement||"span",errorPlacement:function(){!function(a,e){var e=s(this).find("[data-valmsg-for='"+u(e[0].name)+"']"),n=(n=e.attr("data-valmsg-replace"))?!1!==s.parseJSON(n):null;e.removeClass("field-validation-valid").addClass("field-validation-error"),a.data("unobtrusiveContainer",e),n?(e.empty(),a.removeClass("input-validation-error").appendTo(e)):a.hide()}.apply(n,arguments),a("errorPlacement",arguments)},invalidHandler:function(){!function(a,e){var n=s(this).find("[data-valmsg-summary=true]"),t=n.find("ul");t&&t.length&&e.errorList.length&&(t.empty(),n.addClass("validation-summary-errors").removeClass("validation-summary-valid"),s.each(e.errorList,function(){s("<li />").html(this.message).appendTo(t)}))}.apply(n,arguments),a("invalidHandler",arguments)},messages:{},rules:{},success:function(){!function(a){var e,n=a.data("unobtrusiveContainer");n&&(e=(e=n.attr("data-valmsg-replace"))?s.parseJSON(e):null,n.addClass("field-validation-valid").removeClass("field-validation-error"),a.removeData("unobtrusiveContainer"),e&&n.empty())}.apply(n,arguments),a("success",arguments)}},attachValidation:function(){e.off("reset."+d,i).on("reset."+d,i).validate(this.options)},validate:function(){return e.validate(),e.valid()}},e.data(d,t)),t}return o.unobtrusive={adapters:[],parseElement:function(t,a){var e,i,r,o=s(t),d=o.parents("form")[0];d&&((e=p(d)).options.rules[t.name]=i={},e.options.messages[t.name]=r={},s.each(this.adapters,function(){var a="data-val-"+this.name,e=o.attr(a),n={};void 0!==e&&(a+="-",s.each(this.params,function(){n[this]=o.attr(a+this)}),this.adapt({element:t,form:d,message:e,params:n,rules:i,messages:r}))}),s.extend(i,{__dummy__:!0}),a||e.attachValidation())},parse:function(a){var a=s(a),e=a.parents().addBack().filter("form").add(a.find("form")).has("[data-val=true]");a.find("[data-val=true]").each(function(){o.unobtrusive.parseElement(this,!0)}),e.each(function(){var a=p(this);a&&a.attachValidation()})}},(a=o.unobtrusive.adapters).add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},a.addBool=function(e,n){return this.add(e,function(a){l(a,n||e,!0)})},a.addMinMax=function(a,t,i,r,e,n){return this.add(a,[e||"min",n||"max"],function(a){var e=a.params.min,n=a.params.max;e&&n?l(a,r,[e,n]):e?l(a,t,e):n&&l(a,i,n)})},a.addSingleVal=function(e,n,t){return this.add(e,[n||"val"],function(a){l(a,t||e,a.params[n])})},o.addMethod("__dummy__",function(a,e,n){return!0}),o.addMethod("regex",function(a,e,n){return!!this.optional(e)||(e=new RegExp(n).exec(a))&&0===e.index&&e[0].length===a.length}),o.addMethod("nonalphamin",function(a,e,n){var t;return t=n?(t=a.match(/\W/g))&&t.length>=n:t}),o.methods.extension?(a.addSingleVal("accept","mimtype"),a.addSingleVal("extension","extension")):a.addSingleVal("extension","extension","accept"),a.addSingleVal("regex","pattern"),a.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),a.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),a.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),a.add("equalto",["other"],function(a){var e=n(a.element.name),e=m(a.params.other,e);l(a,"equalTo",s(a.form).find(":input").filter("[name='"+u(e)+"']")[0])}),a.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||l(a,"required",!0)}),a.add("remote",["url","type","additionalfields"],function(t){var i={url:t.params.url,type:t.params.type||"GET",data:{}},r=n(t.element.name);s.each((t.params.additionalfields||t.element.name).replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g),function(a,e){var n=m(e,r);i.data[n]=function(){var a=s(t.form).find(":input").filter("[name='"+u(n)+"']");return a.is(":checkbox")?a.filter(":checked").val()||a.filter(":hidden").val()||"":a.is(":radio")?a.filter(":checked").val()||"":a.val()}}),l(t,"remote",i)}),a.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&l(a,"minlength",a.params.min),a.params.nonalphamin&&l(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&l(a,"regex",a.params.regex)}),a.add("fileextensions",["extensions"],function(a){l(a,"extension",a.params.extensions)}),s(function(){o.unobtrusive.parse(document)}),o.unobtrusive});
/* NUGET: BEGIN LICENSE TEXT
 *
 * Microsoft grants you the right to use these script files for the sole
 * purpose of either: (i) interacting through your browser with the Microsoft
 * website or online service, subject to the applicable licensing or use
 * terms; or (ii) using the files as included with a Microsoft product subject
 * to that product's license terms. Microsoft reserves all other rights to the
 * files not expressly granted by Microsoft, whether by implication, estoppel
 * or otherwise. Insofar as a script file is dual licensed under GPL,
 * Microsoft neither took the code under GPL nor distributes it thereunder but
 * under the terms set out in this paragraph. All notices and licenses
 * below are for informational purposes only.
 *
 * NUGET: END LICENSE TEXT */
/*
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
(function(a){var b="unobtrusiveAjaxClick",d="unobtrusiveAjaxClickTarget",h="unobtrusiveValidation";function c(d,b){var a=window,c=(d||"").split(".");while(a&&c.length)a=a[c.shift()];if(typeof a==="function")return a;b.push(d);return Function.constructor.apply(null,b)}function e(a){return a==="GET"||a==="POST"}function g(b,a){!e(a)&&b.setRequestHeader("X-HTTP-Method-Override",a)}function i(c,b,e){var d;if(e.indexOf("application/x-javascript")!==-1)return;d=(c.getAttribute("data-ajax-mode")||"").toUpperCase();a(c.getAttribute("data-ajax-update")).each(function(f,c){var e;switch(d){case"BEFORE":e=c.firstChild;a("<div />").html(b).contents().each(function(){c.insertBefore(this,e)});break;case"AFTER":a("<div />").html(b).contents().each(function(){c.appendChild(this)});break;case"REPLACE-WITH":a(c).replaceWith(b);break;default:a(c).html(b)}})}function f(b,d){var j,k,f,h;j=b.getAttribute("data-ajax-confirm");if(j&&!window.confirm(j))return;k=a(b.getAttribute("data-ajax-loading"));h=parseInt(b.getAttribute("data-ajax-loading-duration"),10)||0;a.extend(d,{type:b.getAttribute("data-ajax-method")||undefined,url:b.getAttribute("data-ajax-url")||undefined,cache:(b.getAttribute("data-ajax-cache")||"").toLowerCase()==="true",beforeSend:function(d){var a;g(d,f);a=c(b.getAttribute("data-ajax-begin"),["xhr"]).apply(b,arguments);a!==false&&k.show(h);return a},complete:function(){k.hide(h);c(b.getAttribute("data-ajax-complete"),["xhr","status"]).apply(b,arguments)},success:function(a,e,d){i(b,a,d.getResponseHeader("Content-Type")||"text/html");c(b.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(b,arguments)},error:function(){c(b.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(b,arguments)}});d.data.push({name:"X-Requested-With",value:"XMLHttpRequest"});f=d.type.toUpperCase();if(!e(f)){d.type="POST";d.data.push({name:"X-HTTP-Method-Override",value:f})}a.ajax(d)}function j(c){var b=a(c).data(h);return!b||!b.validate||b.validate()}a(document).on("click","a[data-ajax=true]",function(a){a.preventDefault();f(this,{url:this.href,type:"GET",data:[]})});a(document).on("click","form[data-ajax=true] input[type=image]",function(c){var g=c.target.name,e=a(c.target),f=a(e.parents("form")[0]),d=e.offset();f.data(b,[{name:g+".x",value:Math.round(c.pageX-d.left)},{name:g+".y",value:Math.round(c.pageY-d.top)}]);setTimeout(function(){f.removeData(b)},0)});a(document).on("click","form[data-ajax=true] :submit",function(e){var g=e.currentTarget.name,f=a(e.target),c=a(f.parents("form")[0]);c.data(b,g?[{name:g,value:e.currentTarget.value}]:[]);c.data(d,f);setTimeout(function(){c.removeData(b);c.removeData(d)},0)});a(document).on("submit","form[data-ajax=true]",function(h){var e=a(this).data(b)||[],c=a(this).data(d),g=c&&c.hasClass("cancel");h.preventDefault();if(!g&&!j(this))return;f(this,{url:this.action,type:this.method||"GET",data:e.concat(a(this).serializeArray())})})})(jQuery);

var ASPx = ASPx || {};
var dx = dx || {};
(function module(ASPx, dx) {
ASPx.modules = { Utils: module };
if(!ASPx.attachToReady)
 ASPx.attachToReady = function (callback) { ASPx.Evt.AttachEventToElement(window, "load", callback); };
if(!ASPx.attachToLoad)
 ASPx.attachToLoad = function(callback) { ASPx.Evt.AttachEventToDocumentCore("DOMContentLoaded", callback); };
ASPx.EmptyObject = { };
ASPx.FalseFunction = function() { return false; };
ASPx.SSLSecureBlankUrl = '/TransElite.ClientPortal/DXR.axd?r=1_88-rU7Xp';
ASPx.EmptyImageUrl = '/TransElite.ClientPortal/DXR.axd?r=1_89-rU7Xp';
ASPx.VersionInfo = 'Version=\'22.1.6.0\', File Version=\'22.1.6.0\', Date Modified=\'13/12/2022 6:15:36 AM\'';
ASPx.Platform = 'ASP';
ASPx.DoctypeMode = 'Html5';
ASPx.InvalidDimension = -10000;
ASPx.InvalidPosition = -10000;
ASPx.AbsoluteLeftPosition = -10000;
ASPx.EmptyGuid = "00000000-0000-0000-0000-000000000000";
ASPx.CallbackSeparator = ":";
ASPx.ItemIndexSeparator = "i";
ASPx.CallbackResultPrefix = "/*DX*/";
ASPx.StyleValueEncodedSemicolon = "DXsmcln";
ASPx.AccessibilityEmptyUrl = "javascript:;";
ASPx.AccessibilityPronounceTimeout = 500;
ASPx.MaxMobileWindowWidth = 576;
ASPx.PossibleNumberDecimalSeparators = [",", "."];
ASPx.CultureInfo = {
 twoDigitYearMax: 2029,
 ts: ":",
 ds: "/",
 am: "AM",
 pm: "PM",
 monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ""],
 genMonthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ""],
 abbrMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""],
 abbrDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
 invariantCultureDecimalPoint: ".",
 numDecimalPoint: ".",
 numPrec: 2,
 numGroupSeparator: ",", 
 numGroups: [ 3 ],
 numNegPattern: 1,
 numPosInf: "Infinity", 
 numNegInf: "-Infinity", 
 numNan: "NaN",
 currency: "$",
 currDecimalPoint: ".",
 currPrec: 2,
 currGroupSeparator: ",",
 currGroups: [ 3 ],
 currPosPattern: 0,
 currNegPattern: 0,
 percentPattern: 0,
 shortTime: "h:mm tt",
 longTime: "h:mm:ss tt",
 shortDate: "M/d/yyyy",
 longDate: "dddd, MMMM d, yyyy",
 monthDay: "MMMM d",
 yearMonth: "MMMM yyyy"
};
ASPx.CultureInfo.genMonthNames = ASPx.CultureInfo.monthNames;
ASPx.Position = {
 Left: "Left",
 Right: "Right",
 Top: "Top",
 Bottom: "Bottom"
};
ASPx.FOCUS_TIMEOUT = 100;
function setInnerHtmlInternal(el, trustedHtmlString) { 
 el.innerHTML = trustedHtmlString;
}
var DateUtils = { };
DateUtils.GetInvariantDateString = function(date) {
 if(!date)
  return "01/01/0001";
 var day = date.getDate();
 var month = date.getMonth() + 1;
 var year = date.getFullYear();
 var result = "";
 if(month < 10)
  result += "0";
 result += month.toString() + "/";
 if(day < 10)
  result += "0";
 result += day.toString() + "/";
 if(year < 1000)
  result += "0";
 result += year.toString();
 return result;
};
DateUtils.GetInvariantDateTimeString = function(date) {
 var dateTimeString = DateUtils.GetInvariantDateString(date);
 var time = {
  h: date.getHours(),
  m: date.getMinutes(),
  s: date.getSeconds()
 };
 for(var key in time) {
  if(time.hasOwnProperty(key)) {
   var str = time[key].toString();
   if(str.length < 2)
    str = "0" + str;
   time[key] = str;
  }
 }
 dateTimeString += " " + time.h + ":" + time.m + ":" + time.s;
 var msec = date.getMilliseconds();
 if(msec > 0)
  dateTimeString += "." + ("000" + msec.toString()).substr(-3);
 return dateTimeString;
};
DateUtils.ExpandTwoDigitYear = function(value) {
 value += 1900;
 if(value + 99 < ASPx.CultureInfo.twoDigitYearMax)
  value += 100;
 return value;  
};
DateUtils.GetTimeZoneOffsetDifference = function(firstDate, secondDate) {
 if(!secondDate)
  secondDate = DateUtils.GetUtcDate(firstDate);
 return 60000 * (firstDate.getTimezoneOffset() - secondDate.getTimezoneOffset());
};
DateUtils.GetTimeZoneOffset = function(date) {
 var isECMA262Support = (ASPx.Browser.Chrome && ASPx.Browser.Version >= 67) || ASPx.Browser.EdgeWebKit;
 if(!isECMA262Support)
  return date.getTimezoneOffset() * 60000;
 var utcDate = DateUtils.GetUtcDate(date);
 var utcTimezoneOffsetDifference = DateUtils.GetTimeZoneOffsetDifference(date);
 if(utcTimezoneOffsetDifference !== 0)
  utcDate.setTime(utcDate.valueOf() + utcTimezoneOffsetDifference);
 return utcDate - date;
};
DateUtils.GetUtcDate = function(date) {
 var utcFullYear = date.getUTCFullYear();
 var result = new Date(utcFullYear, date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
 if(utcFullYear < 100)
  result.setFullYear(utcFullYear);
 return result;
};
DateUtils.ToUtcTime = function(date) {
 var result = new Date();
 result.setTime(date.valueOf() + ASPx.DateUtils.GetTimeZoneOffset(date));
 return result;
};
DateUtils.ToLocalTime = function(date) {
 var result = new Date();
 result.setTime(date.valueOf() - ASPx.DateUtils.GetTimeZoneOffset(date));
 return result; 
};
DateUtils.AreDatesEqualExact = function(date1, date2) {
 if(date1 == null && date2 == null)
  return true;
 if(date1 == null || date2 == null)
  return false;
 return date1.getTime() == date2.getTime(); 
};
DateUtils.FixTimezoneGap = function(oldDate, newDate) {
 var diff = newDate.getHours() - oldDate.getHours();
 if(diff == 0)
  return;
 var sign = (diff == 1 || diff == -23) ? -1 : 1;
 var trial = new Date(newDate.getTime() + sign * 3600000);
 var isDateChangedAsExpected = newDate.getHours() - trial.getHours() === diff;
 if(isDateChangedAsExpected && (sign > 0 || trial.getDate() == newDate.getDate()))
  newDate.setTime(trial.getTime());
};
DateUtils.GetDecadeStartYear = function(year) {
 return 10 * Math.floor(year / 10);
};
DateUtils.GetCenturyStartYear = function(year) {
 return 100 * Math.floor(year / 100);
};
DateUtils.GetCorrectedYear = function(date, pickerType) {
 var year = date.getFullYear();
 return pickerType != ASPx.DatePickerType.Decades ? year : DateUtils.GetDecadeStartYear(year);
};
DateUtils.GetCorrectedMonth = function(date, pickerType) {
 return pickerType < ASPx.DatePickerType.Years ? date.getMonth() : 0;
};
DateUtils.GetCorrectedDay = function(date, pickerType) {
 return pickerType == ASPx.DatePickerType.Days ? date.getDate() : 1;
};
DateUtils.CorrectDateByPickerType = function(date, pickerType) {
 if(!ASPx.IsExists(pickerType))
  pickerType = ASPx.DatePickerType.Days;
 if(!date || pickerType == ASPx.DatePickerType.Days)
  return date;
 var correctedYear = DateUtils.GetCorrectedYear(date, pickerType);
 var result = new Date(
  correctedYear,
  DateUtils.GetCorrectedMonth(date, pickerType),
  DateUtils.GetCorrectedDay(date, pickerType),
  date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()
 );
 result.setFullYear(correctedYear);
 return result;
};
DateUtils.GetYearRangeFormatString = function(startYear, rangeLength) {
 return startYear + " - " + (startYear + rangeLength - 1);
};
ASPx.DateUtils = DateUtils;
var Timer = { };
Timer.ClearTimer = function(timerID){
 if(timerID > -1)
  window.clearTimeout(timerID);
 return -1;
};
Timer.ClearInterval = function(timerID){
 if(timerID > -1)
  window.clearInterval(timerID);
 return -1;
};
var setControlBoundTimer = function(handler, control, setTimerFunction, clearTimerFunction, delay) {
 var timerId;
 var getTimerId = function() { return timerId; };
 var controlMainElement = control.GetMainElement();
 var boundHandler = function() {
  var controlExists = control && ASPx.GetControlCollection().Get(control.name) === control && control.GetMainElement() === controlMainElement;
  if(controlExists)
   handler.aspxBind(control)();
  else {
   clearTimerFunction(getTimerId());
   controlMainElement = null;
  }
 };
 timerId = setTimerFunction(boundHandler, delay);
 return timerId;
};
Timer.SetControlBoundTimeout = function(handler, control, delay) {
 return setControlBoundTimer(handler, control, window.setTimeout, Timer.ClearTimer, delay);
};
Timer.SetControlBoundInterval = function(handler, control, delay) {
 return setControlBoundTimer(handler, control, window.setInterval, Timer.ClearInterval, delay);
};
Timer.Throttle = function(func, delay) {
 var isThrottled = false,
   savedArgs,
   savedThis = this;
 function wrapper() {
  if(isThrottled) {
   savedArgs = arguments;
   savedThis = this;
   return;
  }
  func.apply(this, arguments);
  isThrottled = true;
  setTimeout(function() {
   isThrottled = false;
   if(savedArgs) {
    wrapper.apply(savedThis, savedArgs);
    savedArgs = null;
   }
  }, delay);
 }
 wrapper.cancel = function() {
  clearTimeout(delay);
  delay = savedArgs = savedThis = null;
 };
 return wrapper;
};
ASPx.Timer = Timer;
var Browser = { };
Browser.UserAgent = navigator.userAgent.toLowerCase();
Browser.Mozilla = false;
Browser.IE = false;
Browser.Firefox = false;
Browser.Netscape = false;
Browser.Safari = false;
Browser.Chrome = false;
Browser.Opera = false;
Browser.Edge = false;
Browser.EdgeWebKit = false;
Browser.Version = undefined; 
Browser.MajorVersion = undefined; 
Browser.WindowsPlatform = false;
Browser.MacOSPlatform = false;
Browser.MacOSMobilePlatform = false;
Browser.AndroidMobilePlatform = false;
Browser.PlaformMajorVersion = false;
Browser.WindowsPhonePlatform = false;
Browser.AndroidDefaultBrowser = false;
Browser.AndroidChromeBrowser = false;
Browser.SamsungAndroidDevice = false;
Browser.WebKitTouchUI = false;
Browser.MSTouchUI = false;
Browser.TouchUI = false;
Browser.WebKitFamily = false; 
Browser.NetscapeFamily = false; 
Browser.VirtualKeyboardSupported = false;
Browser.Info = "";
Browser.IsQuirksMode = document.compatMode === "BackCompat";
function indentPlatformMajorVersion(userAgent) {
 var regex = /(?:(?:windows nt|macintosh|mac os|cpu os|cpu iphone os|android|windows phone|linux) )(\d+)(?:[-0-9_.])*/;
 var matches = regex.exec(userAgent);
 if(matches)
  Browser.PlaformMajorVersion = matches[1];
}
function getIECompatibleVersionString() {
 if(document.compatible) {
  for(var i = 0; i < document.compatible.length; i++)
   if(document.compatible[i].userAgent === "IE" && document.compatible[i].version)
    return document.compatible[i].version.toLowerCase();
 }
 return "";
}
Browser.IdentUserAgent = function(userAgent, ignoreDocumentMode) {
 var browserTypesOrderedList = ["Mozilla", "IE", "Firefox", "Netscape", "Safari", "Chrome", "Opera", "Opera10", "EdgeWebKit", "Edge" ];
 var defaultBrowserType = "IE";
 var defaultPlatform = "Win";
 var defaultVersions = { Safari: 2, Chrome: 0.1, Mozilla: 1.9, Netscape: 8, Firefox: 2, Opera: 9, IE: 6, Edge: 12 };
 if(!userAgent || userAgent.length == 0) {
  fillUserAgentInfo(browserTypesOrderedList, defaultBrowserType, defaultVersions[defaultBrowserType], defaultPlatform);
  return;
 }
 userAgent = userAgent.toLowerCase();
 indentPlatformMajorVersion(userAgent);
 try {
  var platformIdentStrings = {
   "Windows": "Win",
   "Macintosh": "Mac",
   "Mac OS": "Mac",
   "Mac_PowerPC": "Mac",
   "cpu os": "MacMobile",
   "cpu iphone os": "MacMobile",
   "Android": "Android",
   "!Windows Phone": "WinPhone",
   "!WPDesktop": "WinPhone",
   "!ZuneWP": "WinPhone"
  };
  var optSlashOrSpace = "(?:/|\\s*)?";
  var version = "(\\d+)(?:\\.((?:\\d+?[1-9])|\\d)0*?)?";
  var optComma = "(?:,)?";
  var appleVersion = "(\\d+)(?:\\.((?:\\d+?[1-9])|\\d)" + optComma + "0*?)?"; 
  var optVersion = "(?:" + version + ")?";
  var patterns = {
   Safari: "applewebkit(?:.*?(?:version/" + appleVersion + "[\\.\\w\\d]*?(?:\\s+mobile\/\\S*)?\\s+safari))?",
   Chrome: "(?:chrome|crios)(?!frame)" + optSlashOrSpace + optVersion,
   Mozilla: "mozilla(?:.*rv:" + optVersion + ".*Gecko)?",
   Netscape: "(?:netscape|navigator)\\d*/?\\s*" + optVersion,
   Firefox: "firefox" + optSlashOrSpace + optVersion,
   Opera: "(?:opera|\sopr)" + optSlashOrSpace + optVersion,
   Opera10: "opera.*\\s*version" + optSlashOrSpace + optVersion,
   IE: "msie\\s*" + optVersion,
   EdgeWebKit: "edg" + optSlashOrSpace + optVersion,
   Edge: "edge" + optSlashOrSpace + optVersion
  };
  var browserType;
  var version = -1;
  for(var i = 0; i < browserTypesOrderedList.length; i++) {
   var browserTypeCandidate = browserTypesOrderedList[i];
   var regExp = new RegExp(patterns[browserTypeCandidate], "i");
   if(regExp.compile)
    regExp.compile(patterns[browserTypeCandidate], "i");
   var matches = regExp.exec(userAgent);
   if(matches && matches.index >= 0) {
    if(browserType == "IE" && version >= 11 && browserTypeCandidate == "Safari") 
     continue;
    browserType = browserTypeCandidate;
    if(browserType == "Opera10")
     browserType = "Opera";
    var tridentPattern = "trident" + optSlashOrSpace + optVersion;
    version = Browser.GetBrowserVersion(userAgent, matches, tridentPattern, getIECompatibleVersionString());
    if(browserType == "Mozilla" && version >= 11)
     browserType = "IE";
   }
  }
  if(!browserType)
   browserType = defaultBrowserType;
  var browserVersionDetected = version != -1;
  if(!browserVersionDetected)
   version = defaultVersions[browserType];
  var platform;
  var minOccurenceIndex = Number.MAX_VALUE;
  for(var identStr in platformIdentStrings) {
   if(!platformIdentStrings.hasOwnProperty(identStr)) continue;
   var importantIdent = identStr.substr(0,1) == "!";
   var occurenceIndex = userAgent.indexOf((importantIdent ? identStr.substr(1) : identStr).toLowerCase());
   if(occurenceIndex >= 0 && (occurenceIndex < minOccurenceIndex || importantIdent)) {
    minOccurenceIndex = importantIdent ? 0 : occurenceIndex;
    platform = platformIdentStrings[identStr];
   }
  }
  var samsungPattern = "SM-[A-Z]";
  var matches = userAgent.toUpperCase().match(samsungPattern);
  var isSamsungAndroidDevice = matches && matches.length > 0;
  if(platform == "WinPhone" && version < 9)
   version = Math.floor(getVersionFromTrident(userAgent, "trident" + optSlashOrSpace + optVersion));
  if(!ignoreDocumentMode && browserType == "IE" && version > 7 && document.documentMode < version)
   version = document.documentMode;
  if(platform == "WinPhone")
   version = Math.max(9, version);
  if(!platform)
   platform = defaultPlatform;
  if(platform == platformIdentStrings["cpu os"] && !browserVersionDetected) 
   version = 4;
  fillUserAgentInfo(browserTypesOrderedList, browserType, version, platform, isSamsungAndroidDevice);
 } catch(e) {
  fillUserAgentInfo(browserTypesOrderedList, defaultBrowserType, defaultVersions[defaultBrowserType], defaultPlatform);
 }
};
function getVersionFromMatches(matches) {
 var result = -1;
 var versionStr = "";
 if(matches[1]) {
  versionStr += matches[1];
  if(matches[2])
   versionStr += "." + matches[2];
 }
 if(versionStr != "") {
  result = parseFloat(versionStr);
  if(isNaN(result))
   result = -1;
 }
 return result;
}
function getVersionFromTrident(userAgent, tridentPattern) {
 var tridentDiffFromVersion = 4;
 var matches = new RegExp(tridentPattern, "i").exec(userAgent);
 return getVersionFromMatches(matches) + tridentDiffFromVersion;
}
Browser.GetBrowserVersion = function(userAgent, matches, tridentPattern, ieCompatibleVersionString) {
 var version = getVersionFromMatches(matches);
 if(ieCompatibleVersionString) {
  var versionFromTrident = getVersionFromTrident(userAgent, tridentPattern);
  if(ieCompatibleVersionString === "edge" || parseInt(ieCompatibleVersionString) === versionFromTrident)
   return versionFromTrident;
 }
 return version;
};
function fillUserAgentInfo(browserTypesOrderedList, browserType, version, platform, isSamsungAndroidDevice) {
 for(var i = 0; i < browserTypesOrderedList.length; i++) {
  var type = browserTypesOrderedList[i];
  Browser[type] = type == browserType;
 }
 Browser.Version = Math.floor(10.0 * version) / 10.0;
 Browser.MajorVersion = Math.floor(Browser.Version);
 Browser.WindowsPlatform = platform == "Win" || platform == "WinPhone";
 Browser.MacOSPlatform = platform == "Mac";
 var isMacWithTouchSupport = platform == "Mac" && (!!window.ontouchstart || getMaxTouchPoints() > 0); 
 Browser.MacOSMobilePlatform = platform == "MacMobile" || isMacWithTouchSupport;
 if(Browser.MacOSMobilePlatform)
  Browser.MacOSPlatform = false;
 Browser.AndroidMobilePlatform = platform == "Android";
 Browser.WindowsPhonePlatform = platform == "WinPhone";
 Browser.WebKitFamily = Browser.Safari || Browser.Chrome || Browser.Opera && Browser.MajorVersion >= 15 || Browser.EdgeWebKit;
 Browser.NetscapeFamily = Browser.Netscape || Browser.Mozilla || Browser.Firefox;
 Browser.WebKitTouchUI = Browser.MacOSMobilePlatform || Browser.AndroidMobilePlatform;
 var isIETouchUI = Browser.IE && Browser.MajorVersion > 9 && Browser.WindowsPlatform && Browser.UserAgent.toLowerCase().indexOf("touch") >= 0;
 Browser.MSTouchUI = isIETouchUI || ((Browser.Edge || (Browser.EdgeWebKit && !Browser.AndroidMobilePlatform)) && !!getMaxTouchPoints());
 Browser.TouchUI = Browser.WebKitTouchUI || Browser.MSTouchUI;
 Browser.MobileUI = Browser.WebKitTouchUI || Browser.WindowsPhonePlatform;
 Browser.AndroidDefaultBrowser = Browser.AndroidMobilePlatform && !Browser.Chrome;
 Browser.AndroidChromeBrowser = Browser.AndroidMobilePlatform && Browser.Chrome;
 if(isSamsungAndroidDevice)
  Browser.SamsungAndroidDevice = isSamsungAndroidDevice;
 if(Browser.MSTouchUI) {
  var isARMArchitecture = Browser.UserAgent.toLowerCase().indexOf("arm;") > -1;    
  Browser.VirtualKeyboardSupported = isARMArchitecture || Browser.WindowsPhonePlatform;   
 } else {
  Browser.VirtualKeyboardSupported = Browser.MobileUI;
 }
 fillDocumentElementBrowserTypeClassNames(browserTypesOrderedList);
}
function getMaxTouchPoints() { 
 var result = navigator.maxTouchPoints;
 if(window.testingTouchMode)
  result = 10;
 return result;
}
function fillDocumentElementBrowserTypeClassNames(browserTypesOrderedList) {
 var documentElementClassName = "";
 var browserTypeslist = browserTypesOrderedList.concat(["WindowsPlatform", "MacOSPlatform", "MacOSMobilePlatform", "AndroidMobilePlatform",
   "WindowsPhonePlatform", "WebKitFamily", "WebKitTouchUI", "MSTouchUI", "TouchUI", "AndroidDefaultBrowser", "MobileUI"]);
 for(var i = 0; i < browserTypeslist.length; i++) {
  var type = browserTypeslist[i];
  if(Browser[type])
   documentElementClassName += "dx" + type + " ";
 }
 documentElementClassName += "dxBrowserVersion-" + Browser.MajorVersion;
 if(document && document.documentElement) {
  if(document.documentElement.className != "")
   documentElementClassName = " " + documentElementClassName;
  document.documentElement.className += documentElementClassName;
  Browser.Info = documentElementClassName;
 }
}
Browser.SupportsStickyPositioning = function() {
 return this.Chrome && this.MajorVersion >= 56
  || this.Firefox && this.MajorVersion >= 32
  || this.Safari && this.MajorVersion >= 6 && this.Version !== "6"
  || this.Opera && this.MajorVersion >= 42;
};
Browser.IdentUserAgent(Browser.UserAgent);
ASPx.Browser = Browser;
ASPx.BlankUrl = Browser.Opera ? "about:blank" : "";
ASPx.FillDocumentElementDXThemeCssClassName = function(dxThemeName) {
 document.documentElement.className += " dxTheme-" + dxThemeName;
};
var Data = { };
Data.ArrayInsert = function(array, element, position){
 if(0 <= position && position < array.length){
  for(var i = array.length; i > position; i --)
   array[i] = array[i - 1];
  array[position] = element;
 }
 else
  array.push(element);
};
Data.ArrayRemove = function(array, element){
 var index = Data.ArrayIndexOf(array, element);
 if(index > -1) Data.ArrayRemoveAt(array, index);
};
Data.ArrayRemoveAt = function(array, index){
 if(index >= 0  && index < array.length){
  for(var i = index; i < array.length - 1; i++)
   array[i] = array[i + 1];
  array.pop();
 }
};
Data.ArrayClear = function(array){
 while(array.length > 0)
  array.pop();
};
Data.ArrayIndexOf = function(array, element, comparer) {
 if(!comparer) {
  for(var i = 0; i < array.length; i++) {
   if(array[i] == element)
    return i;
  }
 } else {
  for(var i = 0; i < array.length; i++) {
   if(comparer(array[i], element))
    return i;
  }
 }
 return -1;
};
Data.ArrayContains = function(array, element) { 
 return Data.ArrayIndexOf(array, element) >= 0;
};
Data.ArrayEqual = function(array1, array2) {
 var count1 = array1.length;
 var count2 = array2.length;
 if(count1 != count2)
  return false;
 for(var i = 0; i < count1; i++)
  if(array1[i] != array2[i])
   return false;
 return true;
};
Data.ArraySame = function(array1, array2) {
 if(array1.length !== array2.length)
  return false;
 return array1.every(function(elem) { return Data.ArrayContains(array2, elem); });
};
Data.ArrayGetIntegerEdgeValues = function(array) {
 var arrayToSort = Data.CollectionToArray(array);
 Data.ArrayIntegerAscendingSort(arrayToSort);
 return {
  start: arrayToSort[0],
  end: arrayToSort[arrayToSort.length - 1]
 };
};
Data.ArrayIntegerAscendingSort = function(array){
 Data.ArrayIntegerSort(array);
};
Data.ArrayIntegerSort = function(array, desc) {
 array.sort(function(i1, i2) {
  var res = 0;
  if(i1 > i2)
   res = 1;
  else if(i1 < i2)
   res = -1;
  if(desc)
   res *= -1;
  return res;
 });
};
Data.CollectionsUnionToArray = function(firstCollection, secondCollection) {
 var result = [];
 var firstCollectionLength = firstCollection.length;
 var secondCollectionLength = secondCollection.length;
 for(var i = 0; i < firstCollectionLength + secondCollectionLength; i++) {
  if(i < firstCollectionLength)
   result.push(firstCollection[i]);
  else
   result.push(secondCollection[i - firstCollectionLength]);
 }
 return result;
};
Data.CollectionToArray = function(collection) {
 var array = [];
 for(var i = 0; i < collection.length; i++)
  array.push(collection[i]);
 return array;
};
Data.CreateHashTableFromArray = function(array) {
 var hash = [];
 for(var i = 0; i < array.length; i++)
  hash[array[i]] = 1;
 return hash;
};
Data.CreateIndexHashTableFromArray = function(array) {
 var hash = [];
 for(var i = 0; i < array.length; i++)
  hash[array[i]] = i;
 return hash;
};
Data.ArrayToHash = function(array, getKeyFunc, getValueFunc) {
 if(!(array instanceof Array)) 
  return { };
 return array.reduce(function(map, element, index) { 
  var key = getKeyFunc(element, index);
  var value = getValueFunc(element, index);
  map[key] = value;
  return map; 
 }, { });
};
Data.Sum = function(array, getValueFunc) {
 if(!(array instanceof Array)) 
  return 0;
 return array.reduce(function(prevValue, item) {
  var value = getValueFunc ? getValueFunc(item) : item;
  if(!ASPx.IsNumber(value))
   value = 0;
  return prevValue + value;
 }, 0);
};
Data.Min = function(array, getValueFunc) { return CalculateArrayMinMax(array, getValueFunc, false); };
Data.Max = function(array, getValueFunc) { return CalculateArrayMinMax(array, getValueFunc, true); };
var CalculateArrayMinMax = function(array, getValueFunc, isMax) {
 if(!(array instanceof Array)) 
  return 0;
 var startValue = isMax ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
 return array.reduce(function(prevValue, item) {
  var value = getValueFunc ? getValueFunc(item) : item;
  if(!ASPx.IsNumber(value))
   value = startValue;
  var func = isMax ? Math.max : Math.min;
  return func(value, prevValue);
 }, startValue);
};
var defaultBinarySearchComparer = function(array, index, value) {
 var arrayElement = array[index];
 if(arrayElement == value)
  return 0;
 else
  return arrayElement < value ? -1 : 1;
};
Data.NearestLeftBinarySearchComparer = function(array, index, value) { 
 var arrayElement = array[index];
 var leftPoint = arrayElement < value;
 var lastLeftPoint = leftPoint && index == array.length - 1;
 var nearestLeftPoint = lastLeftPoint || (leftPoint && array[index + 1] >= value);
 if(nearestLeftPoint)
  return 0;
 else
  return arrayElement < value ? -1 : 1;
};
Data.ArrayBinarySearch = function(array, value, binarySearchComparer, startIndex, length) {
 if(!binarySearchComparer)
  binarySearchComparer = defaultBinarySearchComparer;
 if(!ASPx.IsExists(startIndex))
  startIndex = 0;
 if(!ASPx.IsExists(length))
  length = array.length - startIndex;
 var endIndex = (startIndex + length) - 1;
 while(startIndex <= endIndex) {
  var middle = (startIndex + ((endIndex - startIndex) >> 1));
  var compareResult = binarySearchComparer(array, middle, value);
  if(compareResult == 0)
   return middle;
  if(compareResult < 0)
   startIndex = middle + 1;
  else
   endIndex = middle - 1;
 }
 return -(startIndex + 1);
};
Data.ArrayFlatten = function(arrayOfArrays) {
 return [].concat.apply([], arrayOfArrays);
};
Data.GetDistinctArray = function(array) {
 var resultArray = [];
 for(var i = 0; i < array.length; i++) {
  var currentEntry = array[i];
  if(Data.ArrayIndexOf(resultArray, currentEntry) == -1) {
   resultArray.push(currentEntry);
  }
 }
 return resultArray;
};
Data.ForEach = function(arr, callback) {
 if(Array.prototype.forEach) {
  Array.prototype.forEach.call(arr, callback);
 } else {
  for(var i = 0, len = arr.length; i < len; i++) {
   callback(arr[i], i, arr);
  }
 }
};
Data.MergeHashTables = function(target, object) {
 if(!object || typeof (object) == "string")
  return target;
 if(!target)
  target = {};
 for(var key in object)
  if(key && !(key in target))
   target[key] = object[key];
 return target;
};
Data.Range = function(count, start) {
 count = parseInt(count) || 0;
 start = parseInt(start) || 0;
 if(count < 0) count = 0;
 if(start < 0) start = 0;
 return Array.apply(null, Array(count)).map(function(val, i) { return start + i; });
};
ASPx.Data = Data;
var Cookie = { };
Cookie.DelCookie = function(name){
 setCookieInternal(name, "", new Date(1970, 1, 1));
};
Cookie.GetCookie = function(name) {
 name = escape(name);
 var cookies = document.cookie.split(';');
 for(var i = 0; i < cookies.length; i++) {
  var cookie = Str.Trim(cookies[i]);
  if(cookie.indexOf(name + "=") == 0)
   return unescape(cookie.substring(name.length + 1, cookie.length));
  else if(cookie.indexOf(name + ";") == 0 || cookie === name)
   return "";
 }
 return null;
};
Cookie.SetCookie = function(name, value, expirationDate){
 if(!ASPx.IsExists(value)) {
  Cookie.DelCookie(name);
  return;
 }
 if(!ASPx.Ident.IsDate(expirationDate)) {
  expirationDate = new Date();
  expirationDate.setFullYear(expirationDate.getFullYear() + 1);
 }
 setCookieInternal(name, value, expirationDate);
};
function setCookieInternal(name, value, date){
 document.cookie = escape(name) + "=" + escape(value.toString()) + "; expires=" + date.toGMTString() + "; path=/";
}
ASPx.Cookie = Cookie;
ASPx.ImageUtils = {
 GetImageSrc: function (image){
  return image.src;
 },
 SetImageSrc: function(image, src){
  image.src = src;
 },
 SetSize: function(image, width, height){
  image.style.width = width + "px";
  image.style.height = height + "px";
 },
 GetSize: function(image, isWidth) {
  return (isWidth ? ASPx.GetElementOffsetWidth(image) : ASPx.GetElementOffsetHeight(image));
 }
};
var Str = { };
Str.ApplyReplacement = function(text, replecementTable) {
 if(typeof(text) != "string")
  text = text.toString();
 for(var i = 0; i < replecementTable.length; i++) {
  var replacement = replecementTable[i];
  text = text.replace(replacement[0], replacement[1]);
 }
 return text;
};
Str.CompleteReplace = function(text, regexp, newSubStr) {
 if(typeof(text) != "string")
  text = text.toString();
 var textPrev;
 do {
  textPrev = text;
  text = text.replace(regexp, newSubStr);
 } while(text != textPrev);
 return text;
};
Str.EncodeHtml = function(html) {
 return Str.ApplyReplacement(html, [
  [ /&amp;/g,  '&ampx;'  ], [ /&/g, '&amp;'  ],
  [ /&quot;/g, '&quotx;' ], [ /"/g, '&quot;' ],
  [ /&lt;/g,   '&ltx;'   ], [ /</g, '&lt;'   ],
  [ /&gt;/g,   '&gtx;'   ], [ />/g, '&gt;'   ]
 ]);
};
Str.DecodeHtml = function(html) {
 return Str.ApplyReplacement(html, [
  [ /&gt;/g,   '>' ], [ /&gtx;/g,  '&gt;'   ],
  [ /&lt;/g,   '<' ], [ /&ltx;/g,  '&lt;'   ],
  [ /&quot;/g, '"' ], [ /&quotx;/g,'&quot;' ],
  [ /&amp;/g,  '&' ], [ /&ampx;/g, '&amp;'  ]
 ]);
};
Str.DecodeHtmlViaTextArea = function(html) {
 var textArea = document.createElement("TEXTAREA");
 setInnerHtmlInternal(textArea, html);
 return textArea.value;
};
Str.TrimStart = function(str) { 
 return trimInternal(str, true);
};
Str.TrimEnd = function(str) { 
 return trimInternal(str, false, true);
};
Str.Trim = function(str) { 
 return trimInternal(str, true, true); 
};
Str.EscapeForRegEx = function(str) {
 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
var whiteSpaces = { 
 0x0009: 1, 0x000a: 1, 0x000b: 1, 0x000c: 1, 0x000d: 1, 0x0020: 1, 0x0085: 1, 
 0x00a0: 1, 0x1680: 1, 0x180e: 1, 0x2000: 1, 0x2001: 1, 0x2002: 1, 0x2003: 1, 
 0x2004: 1, 0x2005: 1, 0x2006: 1, 0x2007: 1, 0x2008: 1, 0x2009: 1, 0x200a: 1, 
 0x200b: 1, 0x2028: 1, 0x2029: 1, 0x202f: 1, 0x205f: 1, 0x3000: 1, 0xfeff: 1
};
var caretWidth = 1;
function trimInternal(source, trimStart, trimEnd) {
 var len = source.length;
 if(!len)
  return source;
 var result = "";
 if(len < 0xBABA1) 
  result = trimSource(source, trimStart, trimEnd);
 else
  result = trimLargeSource(source, len, trimStart, trimEnd);
 return Str.ClearString(result);
}
function trimSource(source, trimStart, trimEnd) {
 var result = source;
 if(trimStart)
  result = result.replace(/^\s+/, "");
 if(trimEnd)
  result = result.replace(/\s+$/, "");
 return result;
}
function trimLargeSource(source, len, trimStart, trimEnd) {
 var start = 0;
 if(trimEnd) {
  while(len > 0 && whiteSpaces[source.charCodeAt(len - 1)]) {
   len--;
  }
 }
 if(trimStart && len > 0) {
  while(start < len && whiteSpaces[source.charCodeAt(start)]) {
   start++;
  }
 }
 return source.substring(start, len);
}
var inlineStringLength = 12;
Str.ClearString = function(str) { 
 if(!ASPx.Browser.Chrome)
  return str;
 return str.length < inlineStringLength ? str : JSON.parse(JSON.stringify(str));
};
Str.Insert = function(str, subStr, index) { 
 var leftText = str.slice(0, index);
 var rightText = str.slice(index);
 return leftText + subStr + rightText;
};
Str.InsertEx = function(str, subStr, startIndex, endIndex) { 
 var leftText = str.slice(0, startIndex);
 var rightText = str.slice(endIndex);
 return leftText + subStr + rightText;
};
var greekSLFSigmaChar = String.fromCharCode(962);
var greekSLSigmaChar = String.fromCharCode(963);
Str.PrepareStringForFilter = function(s){
 s = s.toLowerCase();
 if(ASPx.Browser.WebKitFamily) {
  return s.replace(new RegExp(greekSLFSigmaChar, "g"), greekSLSigmaChar);
 }
 return s;
};
Str.GetCoincideCharCount = function(text, filter, textMatchingDelegate) {
 var coincideText = ASPx.Str.PrepareStringForFilter(filter);
 var originText = ASPx.Str.PrepareStringForFilter(text);
 while(coincideText != "" && !textMatchingDelegate(originText, coincideText)) {
  coincideText = coincideText.slice(0, -1);
 }
 return coincideText.length;
};
Str.EndsWith = function(str, suffix) {
 return str.indexOf(suffix, str.length - suffix.length) !== -1;
};
ASPx.Str = Str;
var Xml = { };
Xml.Parse = function(xmlStr) {
 if(window.DOMParser) {
  var parser = new DOMParser();
  return parser.parseFromString(xmlStr, "text/xml");
 }
 else if(window.ActiveXObject) {
  var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
  if(xmlDoc) {
   xmlDoc.async = false;
   xmlDoc.loadXML(xmlStr);
   return xmlDoc;
  }
 }
 return null;
};
ASPx.Xml = Xml;
ASPx.Key = {
 F1     : 112,
 F2     : 113,
 F3     : 114,
 F4     : 115,
 F5     : 116,
 F6     : 117,
 F7     : 118,
 F8     : 119,
 F9     : 120,
 F10    : 121,
 F11    : 122,
 F12    : 123,
 Ctrl   : 17,
 Shift  : 16,
 Alt    : 18,
 Enter  : 13,
 Home   : 36,
 End    : 35,
 Left   : 37,
 Right  : 39,
 Up     : 38,
 Down   : 40,
 PageUp    : 33,
 PageDown  : 34,
 Esc    : 27,
 Space  : 32,
 Tab    : 9,
 Backspace : 8,
 Delete    : 46,
 Insert    : 45,
 ContextMenu  : 93,
 Windows   : 91,
 Decimal   : 110,
 CapsLock  : 20
};
ASPx.ModifierKey = {
 None: 0,
 Ctrl: 1 << (0 + 16),
 Shift: 1 << (2 + 16),
 Alt: 1 << (4 + 16),
 Meta: 1 << (8 + 16)
};
ASPx.KeyCode = {
 Backspace : 8,
 Tab    : 9,
 Enter  : 13,
 Pause  : 19,
 CapsLock  : 20,
 Esc    : 27,
 Space  : 32,
 PageUp    : 33,
 PageDown  : 34,
 End    : 35,
 Home   : 36,
 Left   : 37,
 Up     : 38,
 Right  : 39,
 Down   : 40,
 Insert    : 45,
 Delete    : 46,
 Key_0  : 48,
 Key_1  : 49,
 Key_2  : 50,
 Key_3  : 51,
 Key_4  : 52,
 Key_5  : 53,
 Key_6  : 54,
 Key_7  : 55,
 Key_8  : 56,
 Key_9  : 57,
 Key_a  : 65,
 Key_b  : 66,
 Key_c  : 67,
 Key_d  : 68,
 Key_e  : 69,
 Key_f  : 70,
 Key_g  : 71,
 Key_h  : 72,
 Key_i  : 73,
 Key_j  : 74,
 Key_k  : 75,
 Key_l  : 76,
 Key_m  : 77,
 Key_n  : 78,
 Key_o  : 79,
 Key_p  : 80,
 Key_q  : 81,
 Key_r  : 82,
 Key_s  : 83,
 Key_t  : 84,
 Key_u  : 85,
 Key_v  : 86,
 Key_w  : 87,
 Key_x  : 88,
 Key_y  : 89,
 Key_z  : 90,
 Windows   : 91,
 ContextMenu  : 93,
 Numpad_0  : 96,
 Numpad_1  : 97,
 Numpad_2  : 98,
 Numpad_3  : 99,
 Numpad_4  : 100,
 Numpad_5  : 101,
 Numpad_6  : 102,
 Numpad_7  : 103,
 Numpad_8  : 104,
 Numpad_9  : 105,
 Multiply  : 106,
 Add    : 107,
 Subtract  : 109,
 Decimal   : 110,
 Divide    : 111,
 F1     : 112,
 F2     : 113,
 F3     : 114,
 F4     : 115,
 F5     : 116,
 F6     : 117,
 F7     : 118,
 F8     : 119,
 F9     : 120,
 F10    : 121,
 F11    : 122,
 F12    : 123,
 NumLock   : 144,
 ScrollLock   : 145,
 Semicolon : 186,
 Equals    : 187,
 Comma  : 188,
 Dash   : 189,
 Period    : 190,
 ForwardSlash : 191,
 GraveAccent  : 192,
 OpenBracket  : 219,
 BackSlash : 220,
 CloseBracket : 221,
 SingleQuote  : 222
};
ASPx.ScrollBarMode = { Hidden: 0, Visible: 1, Auto: 2 };
ASPx.ColumnResizeMode = { None: 0, Control: 1, NextColumn: 2 };
var Selection = { };
Selection.Set = function(input, startPos, endPos, scrollToSelection, isApi) {
 if(!ASPx.IsExistsElement(input))
  return;
 var isInputFocused = ASPx.GetActiveElement() === input;
 var isInputNativeFocusLocked = ASPx.VirtualKeyboardUI.getInputNativeFocusLocked();
 if(!isApi && Browser.VirtualKeyboardSupported && (!isInputFocused || isInputNativeFocusLocked))
  return;
 var textLen = input.value.length;
 startPos = ASPx.GetDefinedValue(startPos, 0);
 endPos = ASPx.GetDefinedValue(endPos, textLen);
 if(startPos < 0)
  startPos = 0;
 if(endPos < 0 || endPos > textLen)
  endPos = textLen;
 if(startPos > endPos)
  startPos = endPos;
 var makeReadOnly = false;
 if(Browser.WebKitFamily && input.readOnly) {
  input.readOnly = false;
  makeReadOnly = true;
 }
 try {
  if(Browser.Firefox && Browser.Version >= 8) 
   input.setSelectionRange(startPos, endPos, "backward");
  else {
   forceScrollToSelectionRange(input, startPos, endPos);
   input.setSelectionRange(startPos, endPos);
  }
  if(Browser.Opera || Browser.Firefox || Browser.Chrome || Browser.Edge || Browser.EdgeWebKit) 
   input.focus();
 } catch(e) { }
 if(scrollToSelection && input.tagName == 'TEXTAREA') {
  var scrollHeight = input.scrollHeight;
  var approxCaretPos = startPos;
  var scrollTop = Math.max(Math.round(approxCaretPos * scrollHeight / textLen  - input.clientHeight / 2), 0);
  input.scrollTop = scrollTop;
 }
 if(makeReadOnly)
  input.readOnly = true;
};
var getTextWidthBeforePos = function(input, pos) {
 return ASPx.GetSizeOfText(input.value.toString().substr(0, pos), ASPx.GetCurrentStyle(input)).width;
};
var forceScrollToSelectionRange = function(input, startPos, endPos) {
 if(endPos === input.value.length)
  input.scrollLeft = input.scrollWidth;
 else if(startPos === 0 && endPos === 0)
  input.scrollLeft = 0;
 else {
  var inputRawWidth = ASPx.GetElementOffsetWidth(input) - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(input);
  if(inputRawWidth < input.scrollWidth) {
   var widthBeforeEndPos = getTextWidthBeforePos(input, endPos) + caretWidth;
   if(input.scrollLeft < widthBeforeEndPos - inputRawWidth)
    input.scrollLeft = widthBeforeEndPos - inputRawWidth;
   else {
    var widthBeforeStartPos = getTextWidthBeforePos(input, startPos) - caretWidth;
    if(input.scrollLeft > widthBeforeStartPos)
     input.scrollLeft = widthBeforeStartPos;
   }
  }
 }
};
Selection.GetInfo = function(input) {
 var start, end;
 try {
  start = input.selectionStart;
  end = input.selectionEnd;
 } catch (e) {
 }
 return { startPos: start, endPos: end };
};
Selection.GetExtInfo = function(input) {
 var start = 0, end = 0;
 try {
  start = input.selectionStart;
  end = input.selectionEnd;
 } catch (e) {
 }
 return {startPos: start, endPos: end}; 
};
Selection.SetCaretPosition = function(input, caretPos) {
 if(typeof caretPos === "undefined" || caretPos < 0)
  caretPos = input.value.length;
 Selection.Set(input, caretPos, caretPos, true);
};
Selection.GetCaretPosition = function(element, isDialogMode) {
 var pos = 0;
 if("selectionStart" in element) {
  pos = element.selectionStart;
 } else if("selection" in document) {
  element.focus();
  var sel = document.selection.createRange(),
   selLength = document.selection.createRange().text.length;
  sel.moveStart("character", -element.value.length);
  pos = sel.text.length - selLength;
 }
 if(isDialogMode && !pos) {
  pos = element.value.length - 1;
 }
 return pos;
};
Selection.Clear = function() {
 try {
  if(window.getSelection) {
   window.getSelection().removeAllRanges();
  }
  else if(document.selection) {
   if(document.selection.empty)
    document.selection.empty();
   else if(document.selection.clear)
    document.selection.clear();
  }
 } catch(e) {
 }
};
Selection.ClearOnMouseMove = function(evt) {
 Selection.Clear();
};
Selection.SetElementSelectionEnabled = function(element, value) {
 var userSelectValue = value ? "" : "none";
 var func = value ? Evt.DetachEventFromElement : Evt.AttachEventToElement;
 if(Browser.Firefox)
  element.style.MozUserSelect = userSelectValue;
 else if(Browser.WebKitFamily)
  element.style.webkitUserSelect = userSelectValue;
 else if(Browser.Edge)
  element.style.msUserSelect = userSelectValue;
 else if(Browser.Opera)
  func(element, "mousemove", Selection.Clear);
 else {
  func(element, "selectstart", ASPx.FalseFunction);
  func(element, "mousemove", Selection.Clear);
 }
};
Selection.SetElementAsUnselectable = function(element, isWithChild, recursive) {
 if(element && element.nodeType == 1) {
  element.unselectable = "on";
  if(Browser.NetscapeFamily)
   element.onmousedown = ASPx.FalseFunction;
  if(Browser.WebKitFamily)
   Evt.AttachEventToElement(element, "mousedown", Evt.PreventEventAndBubble);
  if(isWithChild === true){
   for(var j = 0; j < element.childNodes.length; j ++)
    Selection.SetElementAsUnselectable(element.childNodes[j], (!!recursive ? true : false), (!!recursive));
  }
 }
};
Selection.AreEqual = function(selection1, selection2) {
 return selection1.startPos === selection2.startPos && selection1.endPos === selection2.endPos;
};
ASPx.Selection = Selection;
var MouseScroller = { };
MouseScroller.MinimumOffset = 10;
MouseScroller.Create = function(getElement, getScrollXElement, getScrollYElement, needPreventScrolling, vertRecursive, onMouseDown, onMouseMove, onMouseUp, onMouseUpMissed) {
 var element = getElement();
 if(!element) 
  return;
 if(!element.dxMouseScroller)
  element.dxMouseScroller = new MouseScroller.Extender(getElement, getScrollXElement, getScrollYElement, needPreventScrolling, vertRecursive, onMouseDown, onMouseMove, onMouseUp, onMouseUpMissed);
 return element.dxMouseScroller;
};
MouseScroller.Extender = function(getElement, getScrollXElement, getScrollYElement, needPreventScrolling, vertRecursive, onMouseDown, onMouseMove, onMouseUp, onMouseUpMissed) {
 this.getElement = getElement;
 this.getScrollXElement = getScrollXElement;
 this.getScrollYElement = getScrollYElement;
 this.needPreventScrolling = needPreventScrolling;
 this.vertRecursive = !!vertRecursive;
 this.createHandlers(onMouseDown || function() { }, onMouseMove || function() { }, onMouseUp || function() { }, onMouseUpMissed || function() { });
 this.update();
};
MouseScroller.Extender.prototype = {
 update: function() {
  if(this.element)
   Evt.DetachEventFromElement(this.element, ASPx.TouchUIHelper.touchMouseDownEventName, this.mouseDownHandler);
  this.element = this.getElement();
  Evt.AttachEventToElement(this.element, ASPx.TouchUIHelper.touchMouseDownEventName, this.mouseDownHandler);  
  Evt.AttachEventToElement(this.element, "click", this.mouseClickHandler);   
  if(Browser.MSTouchUI && this.element.className.indexOf(ASPx.TouchUIHelper.msTouchDraggableClassName) < 0)
   this.element.className += " " + ASPx.TouchUIHelper.msTouchDraggableClassName;
  this.scrollXElement = this.getScrollXElement();
  this.scrollYElement = this.getScrollYElement();
 },
 createHandlers: function(onMouseDown, onMouseMove, onMouseUp, onMouseUpMissed) {
  var mouseDownCounter = 0;
  this.onMouseDown = onMouseDown;
  this.onMouseMove = onMouseMove;
  this.onMouseUp = onMouseUp;  
  this.mouseDownHandler = function(e) {
   if(mouseDownCounter++ > 0) {
    this.finishScrolling();
    onMouseUpMissed();
   }
   var eventSource = Evt.GetEventSource(e);
   var requirePreventCustonScroll = ASPx.IsExists(ASPx.TouchUIHelper.RequirePreventCustomScroll) && ASPx.TouchUIHelper.RequirePreventCustomScroll(eventSource, this.element);
   this.requirePreventScroll = requirePreventCustonScroll || this.needPreventScrolling && this.needPreventScrolling(eventSource);
   if(this.requirePreventScroll)
    return;
   this.scrollableTreeLine = this.GetScrollableElements();
   this.firstX = this.prevX = Evt.GetEventX(e);
   this.firstY = this.prevY = Evt.GetEventY(e);
   Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
   Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
   this.onMouseDown(e);
  }.aspxBind(this);
  this.mouseMoveHandler = function(e) {
   if(ASPx.TouchUIHelper.isGesture)
    return;
   var x = Evt.GetEventX(e);
   var y = Evt.GetEventY(e);
   var xDiff = this.prevX - x;
   var yDiff = this.prevY - y;
   if(this.vertRecursive) {
    var isTopDirection = yDiff < 0;
    this.scrollYElement = this.GetElementForVertScrolling(isTopDirection, this.prevIsTopDirection, this.scrollYElement);
    this.prevIsTopDirection = isTopDirection;
   }
   if(this.scrollXElement && xDiff != 0)
    this.scrollXElement.scrollLeft += xDiff;
   if(this.scrollYElement && yDiff != 0) {
    this.scrollYElement.scrollTop += yDiff;
    var isOuterScrollableElement = this.scrollableTreeLine[this.scrollableTreeLine.length - 1] == this.scrollYElement;
    if(isOuterScrollableElement)
     y += yDiff;
   }
   this.prevX = x;
   this.prevY = y;
   Evt.PreventEvent(e);
   this.onMouseMove(e);
  }.aspxBind(this);
  this.mouseUpHandler = function(e) {
   this.finishScrolling();
   this.onMouseUp(e);
  }.aspxBind(this);
  this.mouseClickHandler = function(e){
   if(this.requirePreventScroll || (ASPx.IsExists(e.isTrusted) && !e.isTrusted))
    return;
   var xDiff = this.firstX - Evt.GetEventX(e);
   var yDiff = this.firstY - Evt.GetEventY(e);
   if(xDiff > MouseScroller.MinimumOffset || yDiff > MouseScroller.MinimumOffset)
    return Evt.PreventEventAndBubble(e);
  }.aspxBind(this);
  this.finishScrolling = function() {
   Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
   Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
   this.scrollableTreeLine = [];
   this.prevIsTopDirection = null;
   mouseDownCounter--;
  };
 },
 GetScrollableElements: function() {
  if(!this.vertRecursive) return [ ];
  var isHtmlScrollableElement = !ASPx.Browser.IsQuirksMode && !ASPx.Browser.Safari;
  var outerScrollableElementTag = isHtmlScrollableElement ? "HTML" : "BODY";
  return ASPx.GetElementTreeLine(this.element, null, function(el) { return el == document; })
   .filter(function(el) {
    var tagName = el.tagName;
    if(isHtmlScrollableElement && tagName == "BODY")
     return false;
    return ASPx.IsScrollableElement(el, false, true) || tagName == outerScrollableElementTag || el.dxScrollable;
   }.bind(this));
 },
 GetElementForVertScrolling: function(currentIsTop, prevIsTop, prevElement) {
  if(prevElement && currentIsTop === prevIsTop && this.GetVertScrollExcess(prevElement, currentIsTop) > 0)
   return prevElement;
  for(var i = 0; i < this.scrollableTreeLine.length; i++) {
   var element = this.scrollableTreeLine[i];
   var excess = this.GetVertScrollExcess(element, currentIsTop);
   if(excess > 0)
    return element;
  }
  return null;
 },
 GetVertScrollExcess: function(element, isTop) {
  if(isTop)
   return element.scrollTop;
  var isDocument = element.tagName == "HTML" || ASPx.Browser.Safari && !ASPx.Browser.IsQuirksMode && element.tagName == "BODY";
  var clientHeight = isDocument ? ASPx.GetDocumentClientHeight() : element.clientHeight;
  return element.scrollHeight - clientHeight - element.scrollTop;
 }
};
ASPx.MouseScroller = MouseScroller;
var Evt = { };
Evt.GetEvent = function(evt){
 return evt; 
};
Evt.IsEventPrevented = function(evt) {
 return evt.defaultPrevented || evt.returnValue === false;
};
Evt.PreventEvent = function(evt){
 if(evt.preventDefault) {
  if(evt.cancelable)
   evt.preventDefault();
 }
 else
  evt.returnValue = false;
 return false;
};
Evt.PreventEventAndBubble = function(evt){
 Evt.PreventEvent(evt);
 if(evt.stopPropagation)
  evt.stopPropagation();
 evt.cancelBubble = true;
 return false;
};
Evt.CancelBubble = function(evt){
 evt.stopPropagation();
 return false;
};
Evt.PreventImageDragging = function(image) {
 if(image)
  image.ondragstart = function() { return false; };
};
Evt.PreventDragStart = function(evt) {
 evt = Evt.GetEvent(evt);
 var element = Evt.GetEventSource(evt);
 if(element.releaseCapture)
  element.releaseCapture(); 
 return false;
};
Evt.PreventElementDrag = function(element) {
 Evt.AttachEventToElement(element, "mousedown", Evt.PreventEvent);
};
Evt.PreventElementDragAndSelect = function(element, skipMouseMove, skipIESelect){
 if(Browser.WebKitFamily)
  Evt.AttachEventToElement(element, "selectstart", Evt.PreventEventAndBubble);
};
Evt.GetEventSource = function(evt){
 if(!ASPx.IsExists(evt)) return null; 
 return evt.srcElement ? evt.srcElement : evt.target;
};
Evt.GetKeyCode = function(srcEvt) {
 return Browser.NetscapeFamily || Browser.Opera ? srcEvt.which : srcEvt.keyCode;
};
function clientEventRequiresDocScrollCorrection() {
 var isSafariVerLess3 = Browser.Safari && Browser.Version < 3,
  isMacOSMobileVerLess51 = Browser.MacOSMobilePlatform && Browser.Version < 5.1;
 return Browser.AndroidDefaultBrowser || Browser.AndroidChromeBrowser || !(isSafariVerLess3 || isMacOSMobileVerLess51);
}
Evt.GetEventX = function(evt){
 if(ASPx.TouchUIHelper.isTouchEvent(evt))
  return ASPx.TouchUIHelper.getEventX(evt);
 return evt.clientX + (clientEventRequiresDocScrollCorrection() ? ASPx.GetDocumentScrollLeft() : 0);
};
Evt.GetEventY = function(evt){
 if(ASPx.TouchUIHelper.isTouchEvent(evt))
  return ASPx.TouchUIHelper.getEventY(evt);
 return evt.clientY + (clientEventRequiresDocScrollCorrection() ? ASPx.GetDocumentScrollTop() : 0 );
};
Evt.IsLeftButtonPressed = function(evt) {
 if(ASPx.TouchUIHelper.isTouchEvent(evt))
  return true;
 evt = Evt.GetEvent(evt);
 if(!evt) return false;
 if(Browser.WebKitFamily) {
  if(evt.type === "pointermove")
   return evt.buttons === 1;
  return evt.which == 1;
 } else if(Browser.NetscapeFamily || Browser.Edge) {
  if(evt.type === ASPx.TouchUIHelper.touchMouseMoveEventName)
   return evt.buttons === 1;
  return evt.which == 1;
 } else if(Browser.Opera)
  return evt.button == 0;
 return true;
};
Evt.IsRightButtonPressed = function(evt){
 evt = Evt.GetEvent(evt);
 if(!ASPx.IsExists(evt)) return false;
 if(Browser.IE || Browser.Edge) {
  if(evt.type === "pointermove")
   return evt.buttons === 2;
  return evt.button == 2;
 }
 else if(Browser.NetscapeFamily || Browser.WebKitFamily)
  return evt.which == 3;
 else if (Browser.Opera)
  return evt.button == 1;
 return true;
};
Evt.GetWheelDelta = function(evt) {
 var ret;
 if(Browser.NetscapeFamily && Browser.MajorVersion < 17)
  ret = -evt.detail;
 else if(Browser.Safari)
  ret = evt.wheelDelta;
 else
  ret = -evt.deltaY;
 if(Browser.Opera && Browser.Version < 9)
  ret = -ret;
 return ret;
};
Evt.IsWheelEventWithDirection = function(evt) {
 return ASPx.Data.ArrayContains(["wheel", "mousewheel"], evt.type);
};
Evt.GetWheelDeltaX = function(evt) {
 if(evt.type === "wheel")
  return -evt.deltaX;
 if(evt.type === "mousewheel")
  return evt.wheelDeltaX;
};
Evt.GetWheelDeltaY = function(evt) {
 if(evt.type === "wheel")
  return -evt.deltaY;
 if(evt.type === "mousewheel")
  return evt.wheelDeltaY;
};
Evt.IsPassiveListenersSupported = function() {
 if(Browser.Chrome && Browser.MajorVersion > 69 || Browser.Edge && Browser.MajorVersion > 15 || Browser.Firefox && Browser.MajorVersion > 62)
  return true;
 if(Evt.isPassiveListenersSupported === undefined) {
  Evt.isPassiveListenersSupported = false;
  try {
   var options = Object.defineProperty({}, "passive", { get: function() { Evt.isPassiveListenersSupported = true; } });
   window.addEventListener("test", options, options);
   window.removeEventListener("test", options, options);
  }
  catch(err) { Evt.isPassiveListenersSupported = false; }
 }
 return !!Evt.isPassiveListenersSupported;
};
Evt.AttachEventToElement = function(element, eventName, func, onlyBubbling, passive) {
 if(element.addEventListener)
  element.addEventListener(eventName, func, Evt.IsPassiveListenersSupported() ? { capture: !onlyBubbling, passive: !!passive } : !onlyBubbling);
 else
  element.attachEvent("on" + eventName, func);
};
Evt.DetachEventFromElement = function(element, eventName, func, onlyBubbling) {
 if(element.removeEventListener)
  element.removeEventListener(eventName, func, Evt.IsPassiveListenersSupported() ? { capture: !onlyBubbling } : !onlyBubbling);
 else
  element.detachEvent("on" + eventName, func);
};
Evt.AttachEventToDocument = function(eventName, func) {
 var attachingAllowed = ASPx.TouchUIHelper.onEventAttachingToDocument(eventName, func);
 if(attachingAllowed)
  Evt.AttachEventToDocumentCore(eventName, func);
};
Evt.AttachEventToDocumentCore = function(eventName, func) {
 Evt.AttachEventToElement(document, eventName, func);
};
Evt.DetachEventFromDocument = function(eventName, func) {
 Evt.DetachEventFromDocumentCore(eventName, func);
 ASPx.TouchUIHelper.onEventDettachedFromDocument(eventName, func);
};
Evt.DetachEventFromDocumentCore = function(eventName, func){
 Evt.DetachEventFromElement(document, eventName, func);
};
Evt.GetMouseWheelEventName = function() {
 if(Browser.Safari)
  return "mousewheel";
 if(Browser.NetscapeFamily && Browser.MajorVersion < 17)
  return "DOMMouseScroll";
 return "wheel";
};
Evt.AttachMouseEnterToElement = function (element, onMouseOverHandler, onMouseOutHandler) {
 Evt.AttachEventToElement(element, ASPx.TouchUIHelper.pointerEnabled ? ASPx.TouchUIHelper.pointerOverEventName : "mouseover", function (evt) { mouseEnterHandler(evt, element, onMouseOverHandler, onMouseOutHandler); });
 Evt.AttachEventToElement(element, ASPx.TouchUIHelper.pointerEnabled ? ASPx.TouchUIHelper.pointerOutEventName : "mouseout", function (evt) { mouseEnterHandler(evt, element, onMouseOverHandler, onMouseOutHandler); });
};
Evt.GetEventRelatedTarget = function(evt, isMouseOverEvent) {
 return evt.relatedTarget || (isMouseOverEvent ? evt.srcElement : evt.toElement);
};
function mouseEnterHandler(evt, element, onMouseOverHandler, onMouseOutHandler) {
 var isMouseOverExecuted = !!element.dxMouseOverExecuted;
 var isMouseOverEvent = (evt.type == "mouseover" || evt.type == ASPx.TouchUIHelper.pointerOverEventName);
 if(isMouseOverEvent && isMouseOverExecuted || !isMouseOverEvent && !isMouseOverExecuted)
  return;
 var source = Evt.GetEventRelatedTarget(evt, isMouseOverEvent);
 if(!ASPx.GetIsParent(element, source)) {
  element.dxMouseOverExecuted = isMouseOverEvent;
  if(isMouseOverEvent)
   onMouseOverHandler(element);
  else
   onMouseOutHandler(element);
 }
 else if(isMouseOverEvent && !isMouseOverExecuted) {
  element.dxMouseOverExecuted = true;
  onMouseOverHandler(element);
 }
}
Evt.DispatchEvent = function(target, eventName, canBubble, cancellable) {
 var event = document.createEvent("Event");
 event.initEvent(eventName, canBubble || false, cancellable || false);
 target.dispatchEvent(event);
};
Evt.EmulateDocumentOnMouseDown = function(evt) {
 Evt.EmulateOnMouseDown(document, evt);
};
Evt.EmulateOnMouseDown = function(element, evt) {
 if(!Browser.WebKitFamily){
  var emulatedEvt = document.createEvent("MouseEvents");
  emulatedEvt.initMouseEvent("mousedown", true, true, window, 0, evt.screenX, evt.screenY, 
   evt.clientX, evt.clientY, evt.ctrlKey, evt.altKey, evt.shiftKey, false, 0, null);
  element.dispatchEvent(emulatedEvt);
 }
};
Evt.EmulateOnMouseEvent = function (type, element, evt) {
 evt.type = type;
 var emulatedEvt = document.createEvent("MouseEvents");
 emulatedEvt.initMouseEvent(type, true, true, window, 0, evt.screenX, evt.screenY,
  evt.clientX, evt.clientY, evt.ctrlKey, evt.altKey, evt.shiftKey, false, 0, null);
 emulatedEvt.target = element;
 element.dispatchEvent(emulatedEvt);
};
Evt.EmulateMouseClick = function (element, evt) {
 var x = ASPx.GetElementOffsetWidth(element) / 2;
 var y = ASPx.GetElementOffsetHeight(element) / 2;
 if (!evt)
  evt = {
   bubbles: true,
   cancelable: true,
   view: window,
   detail: 1,
   screenX: 0,
   screenY: 0,
   clientX: x,
   clientY: y,
   ctrlKey: false,
   altKey: false,
   shiftKey: false,
   metaKey: false,
   button: 0,
   relatedTarget: null
  };
 Evt.EmulateOnMouseEvent("mousedown", element, evt);
 Evt.EmulateOnMouseEvent("mouseup", element, evt);
 Evt.EmulateOnMouseEvent("click", element, evt);
};
Evt.DoElementClick = function(element) {
 try{
  element.click();
 }
 catch(e){ 
 }
};
Evt.IsActionKeyPressed = function(evt) {
 return evt.keyCode === ASPx.Key.Space ||
     evt.keyCode === ASPx.Key.Enter ||
    (evt.keyCode === ASPx.Key.Down && evt.altKey);
};
Evt.InvokeMouseClickByKeyDown = function(evt, handler) {
 if(Evt.IsActionKeyPressed(evt)) {
  ASPx.Evt.PreventEvent(evt); 
  if(!handler)
   ASPx.Evt.GetEventSource(evt).onclick();
  else
   handler(evt);
 }
};
Evt.AttachContextMenuToElement = function (element, handler, onlyBubbling) {
 if (ASPx.TouchUIHelper.useLongTapHelper())
  element.detachContextMenuEventHandler = ASPx.TouchUIHelper.attachLongTapHandler(element, handler, onlyBubbling);
 else
  Evt.AttachEventToElement(element, "contextmenu", handler, onlyBubbling);
};
Evt.DetachContextMenuFromElement = function (element, handler) {
 if (element.detachContextMenuEventHandler)
  element.detachContextMenuEventHandler();
 else
  Evt.DetachEventFromElement(element, "contextmenu", handler);
};
Evt.PreventContextMenuOnElement = function(element) {
 Evt.AttachContextMenuToElement(element, function(evt) {
  Evt.PreventEvent(evt);
 });
};
ASPx.Evt = Evt;
var Attr = { };
Attr.GetAttribute = function(obj, attrName){
 if(obj.getAttribute)
  return obj.getAttribute(attrName);
 else if(obj.getPropertyValue) {
  if(Browser.Firefox) { 
   try {
    return obj.getPropertyValue(attrName);
   } catch(e) {
    return obj[attrName];
   }
  }
  return obj.getPropertyValue(attrName);
 }
 return null;
};
Attr.SetAttribute = function(obj, attrName, value){
 if(obj.setAttribute)
  obj.setAttribute(attrName, value);
 else if(obj.setProperty)
  obj.setProperty(attrName, value, "");
};
Attr.ToggleAttribute = function(obj, attrName, value, condition) {
 if(condition)
  Attr.SetAttribute(obj, attrName, value);
 else
  Attr.RemoveAttribute(obj, attrName);
};
Attr.RemoveAttribute = function(obj, attrName){
 if(obj.removeAttribute)
  obj.removeAttribute(attrName);
 else if(obj.removeProperty)
  obj.removeProperty(attrName);
};
Attr.IsExistsAttribute = function(obj, attrName){
 var value = Attr.GetAttribute(obj, attrName);
 return (value != null) && (value !== "");
};
Attr.SetOrRemoveAttribute = function(obj, attrName, value) {
 if(!value)
  Attr.RemoveAttribute(obj, attrName);
 else
  Attr.SetAttribute(obj, attrName, value);
};
Attr.SaveAttribute = function(obj, attrName, savedObj, savedAttrName){
 if(!Attr.IsExistsAttribute(savedObj, savedAttrName)){
  var oldValue = Attr.IsExistsAttribute(obj, attrName) ? Attr.GetAttribute(obj, attrName) : ASPx.EmptyObject;
  Attr.SetAttribute(savedObj, savedAttrName, oldValue);
 }
};
Attr.SaveStyleAttribute = function(obj, attrName){
 Attr.SaveAttribute(obj.style, attrName, obj, "saved" + attrName);
};
Attr.ChangeAttributeExtended = function(obj, attrName, savedObj, savedAttrName, newValue){
 Attr.SaveAttribute(obj, attrName, savedObj, savedAttrName);
 Attr.SetAttribute(obj, attrName, newValue);
};
Attr.ChangeAttribute = function(obj, attrName, newValue){
 Attr.ChangeAttributeExtended(obj, attrName, obj, "saved" + attrName, newValue);
};
Attr.ChangeStyleAttribute = function(obj, attrName, newValue){
 Attr.ChangeAttributeExtended(obj.style, attrName, obj, "saved" + attrName, newValue);
};
Attr.ResetAttributeExtended = function(obj, attrName, savedObj, savedAttrName){
 Attr.SaveAttribute(obj, attrName, savedObj, savedAttrName);
 Attr.SetAttribute(obj, attrName, "");
 Attr.RemoveAttribute(obj, attrName);
};
Attr.ResetAttribute = function(obj, attrName){
 Attr.ResetAttributeExtended(obj, attrName, obj, "saved" + attrName);
};
Attr.ResetStyleAttribute = function(obj, attrName){
 Attr.ResetAttributeExtended(obj.style, attrName, obj, "saved" + attrName);
};
Attr.RestoreAttributeExtended = function(obj, attrName, savedObj, savedAttrName){
 if(Attr.IsExistsAttribute(savedObj, savedAttrName)){
  var oldValue = Attr.GetAttribute(savedObj, savedAttrName);
  if(oldValue != ASPx.EmptyObject)
   Attr.SetAttribute(obj, attrName, oldValue);
  else
   Attr.RemoveAttribute(obj, attrName);
  Attr.RemoveAttribute(savedObj, savedAttrName);
  return true;
 }
 return false;
};
Attr.RestoreAttribute = function(obj, attrName){
 return Attr.RestoreAttributeExtended(obj, attrName, obj, "saved" + attrName);
};
Attr.RestoreStyleAttribute = function(obj, attrName){
 return Attr.RestoreAttributeExtended(obj.style, attrName, obj, "saved" + attrName);
};
Attr.CopyAllAttributes = function(sourceElem, destElement) {
 var attrs = sourceElem.attributes;
 for(var n = 0; n < attrs.length; n++) {
  var attr = attrs[n];
  if(attr.specified) {
   var attrName = attr.nodeName;
   var attrValue = sourceElem.getAttribute(attrName, 2);
   if(attrValue == null)
    attrValue = attr.nodeValue;
   destElement.setAttribute(attrName, attrValue, 0); 
  }
 }
 if(sourceElem.style.cssText !== '')
  destElement.style.cssText = sourceElem.style.cssText;
};
Attr.RemoveAllAttributes = function(element, excludedAttributes) {
 var excludedAttributesHashTable = {};
 if(excludedAttributes)
  excludedAttributesHashTable = Data.CreateHashTableFromArray(excludedAttributes);
 if(element.attributes) {
  var attrArray = element.attributes;
  for(var i = 0; i < attrArray.length; i++) {
   var attrName = attrArray[i].name;
   if(!ASPx.IsExists(excludedAttributesHashTable[attrName.toLowerCase()])) {
    try {
     attrArray.removeNamedItem(attrName);
    } catch (e) { }
   }
  }
 }
};
Attr.RemoveStyleAttribute = function(element, attrName) {
 if(element.style) {
  if(Browser.Firefox && element.style[attrName]) 
   element.style[attrName] = "";
  if(element.style.removeAttribute && element.style.removeAttribute != "")
   element.style.removeAttribute(attrName);
  else if(element.style.removeProperty && element.style.removeProperty != "")
   element.style.removeProperty(attrName);
 }
};
Attr.RemoveAllStyles = function(element) {
 if(element.style) {
  for(var key in element.style)
   Attr.RemoveStyleAttribute(element, key);
    Attr.RemoveAttribute(element, "style");
 }
};
Attr.GetTabIndexAttributeName = function(){
 return "tabindex";
};
Attr.ChangeTabIndexAttribute = function(element){
 var attribute = Attr.GetTabIndexAttributeName(); 
 if(Attr.GetAttribute(element, attribute) != -1)
    Attr.ChangeAttribute(element, attribute, -1);
};
Attr.SaveTabIndexAttributeAndReset = function(element) {
 var attribute = Attr.GetTabIndexAttributeName();
 Attr.SaveAttribute(element, attribute, element, "saved" + attribute);
 Attr.SetAttribute(element, attribute, -1);
};
Attr.RestoreTabIndexAttribute = function(element){
 var attribute = Attr.GetTabIndexAttributeName();
 if(Attr.IsExistsAttribute(element, attribute)) {
  if(Attr.GetAttribute(element, attribute) == -1) {
   if(Attr.IsExistsAttribute(element, "saved" + attribute)){
    var oldValue = Attr.GetAttribute(element, "saved" + attribute);
    if(oldValue != ASPx.EmptyObject)
     Attr.SetAttribute(element, attribute, oldValue);
    else {
     if(Browser.WebKitFamily) 
      Attr.SetAttribute(element, attribute, 0); 
     Attr.RemoveAttribute(element, attribute);   
    }
    Attr.RemoveAttribute(element, "saved" + attribute); 
   }
  }
 }
};
Attr.ChangeAttributesMethod = function(enabled){
 return enabled ? Attr.RestoreAttribute : Attr.ResetAttribute;
};
Attr.InitiallyChangeAttributesMethod = function(enabled){
 return enabled ? Attr.ChangeAttribute : Attr.ResetAttribute;
};
Attr.ChangeStyleAttributesMethod = function(enabled){
 return enabled ? Attr.RestoreStyleAttribute : Attr.ResetStyleAttribute;
};
Attr.InitiallyChangeStyleAttributesMethod = function(enabled){
 return enabled ? Attr.ChangeStyleAttribute : Attr.ResetStyleAttribute;
};
Attr.ChangeEventsMethod = function(enabled){
 return enabled ? Evt.AttachEventToElement : Evt.DetachEventFromElement;
};
Attr.ChangeDocumentEventsMethod = function(enabled){
 return enabled ? Evt.AttachEventToDocument : Evt.DetachEventFromDocument;
};
Attr.ChangeCellSpanCount = function(cell, value, isColumnSpan) {
 if(!cell) return;
 var propertyKey = isColumnSpan ? "colSpan" : "rowSpan";
 var prevValue = cell[propertyKey];
 if(value > 1)
  cell[propertyKey] = value;
 else if(prevValue !== 1)
  Attr.RemoveAttribute(cell, propertyKey);
};
Attr.AppendScriptType = function(script) {
 if(!isHtml5Mode())
  script.type = "text/javascript";
};
Attr.AppendStyleType = function(style) {
 if(!isHtml5Mode())
  style.type = "text/css";
};
function isHtml5Mode() {
 return ASPx.DoctypeMode === "Html5";
}
ASPx.Attr = Attr;
var Aria = {
 atomic: "aria-atomic",
 checked: "aria-checked",
 descendant: "aria-activedescendant",
 described: "aria-describedby",
 disabled: "aria-disabled",
 expanded: "aria-expanded",
 haspopup: "aria-haspopup",
 invalid: "aria-invalid",
 label: "aria-label",
 labelled: "aria-labelledby",
 level: "aria-level",
 owns: "aria-owns",
 posinset: "aria-posinset",
 role: "role",
 selected: "aria-selected",
 setsize: "aria-setsize",
 valuemax: "aria-valuemax",
 valuemin: "aria-valuemin",
 valuenow: "aria-valuenow"
};
Aria.SetOrRemoveDescendant = function(obj, value) {
 ASPx.Attr.SetOrRemoveAttribute(obj, Aria.descendant, value);
};
Aria.SetOrRemoveLabel = function(obj, value) {
 ASPx.Attr.SetOrRemoveAttribute(obj, Aria.label, value);
};
Aria.SetOrRemoveDisabled = function(obj, value) {
 ASPx.Attr.SetOrRemoveAttribute(obj, Aria.disabled, value);
};
Aria.AppendLabel = function(obj, value, checkExists) {
 var currentValue = ASPx.Attr.GetAttribute(obj, Aria.label) || "";
 var resultParts = [ ];
 if(currentValue)
  resultParts.push(currentValue);
 var needAppendValue = value && (!checkExists || currentValue.indexOf(value) == -1);
 if(needAppendValue)
  resultParts.push(value);
 ASPx.Attr.SetAttribute(obj, Aria.label, resultParts.join(" "));
};
Aria.SetOrRemoveLabelled = function(obj, value) {
 ASPx.Attr.SetOrRemoveAttribute(obj, Aria.labelled, value);
};
Aria.SetApplicationRole = function(obj) {
  ASPx.Attr.SetAttribute(obj, Aria.role, "application");
};
Aria.SetSilence = function(obj) {
 ASPx.Attr.SetAttribute(obj, Aria.label, ";");
};
Aria.SetExpanded = function(obj, expanded) {
 if(!obj || !ASPx.Attr.GetAttribute(obj, Aria.expanded)) return;
 Aria.SetBoolAttribute(obj, Aria.expanded, expanded);
};
Aria.SetAtomic = function(obj, value) {
 Aria.SetBoolAttribute(obj, Aria.atomic, value);
};
Aria.SetBoolAttribute = function(obj, attribute, value) {
 if(value)
  ASPx.Attr.SetAttribute(obj, attribute, true);
 else 
  ASPx.Attr.SetAttribute(obj, attribute, false);
};
ASPx.Attr.Aria = Aria;
var Color = { };
function _aspxToHex(d) {
 return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
}
Color.RGBRegexp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
Color.RGBARegexp = /rgba?\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,?\s*([0-9]*\.?[0-9]*)\s*\)/;
Color.ColorToHexadecimal = function(colorValue, isRGBA) {
 if(typeof(colorValue) == "number") {
  var r = colorValue & 0xFF;
  var g = (colorValue >> 8) & 0xFF;
  var b = (colorValue >> 16) & 0xFF;
  return "#" + _aspxToHex(r) + _aspxToHex(g) + _aspxToHex(b);
 }
 if(colorValue && (colorValue.substr(0, 3).toLowerCase() == "rgb")) {
  var regResult = colorValue.toLowerCase().match(isRGBA ? Color.RGBARegexp : Color.RGBRegexp);
  if(regResult) {
   var r = parseInt(regResult[1]);
   var g = parseInt(regResult[2]);
   var b = parseInt(regResult[3]);
   if (isRGBA)
    return { r: r, g: g, b: b, a: regResult[4] !== undefined ? parseFloat(regResult[4]) : 1 };
   return "#" + _aspxToHex(r) + _aspxToHex(g) + _aspxToHex(b);
  }
  return null;
 } 
 if(colorValue && (colorValue.charAt(0) == "#"))
  return colorValue;
 return null;
};
Color.Names = {
 AddColorNames: function(stringResourcesObj) {
  if(stringResourcesObj) {
   for(var key in stringResourcesObj)
    if(stringResourcesObj.hasOwnProperty(key))
     this[key] = stringResourcesObj[key];
  }
 }
};
ASPx.Color = Color;
var Url = { };
Url.Navigate = function(url, target) {
 var javascriptPrefix = "javascript:";
 if(!url || url === "")
  return;
 else if(url.indexOf(javascriptPrefix) != -1)
  eval(url.substr(javascriptPrefix.length));
 else {
  try {
   if(target != "")
    navigateTo(url, target);
   else
    location.href = url;
  }
  catch(e) {
  }
 }
};
Url.NavigateByLink = function(linkElement) {
 Url.Navigate(Attr.GetAttribute(linkElement, "href"), linkElement.target);
};
Url.GetAbsoluteUrl = function(url) {
 if(url)
  url = Url.getURLObject(url).href;
 return url;
};
Url.Redirect = function(url) {
 window.location.href = url;
};
var absolutePathPrefixes = 
 [ "about:", "file:///", "ftp://", "gopher://", "http://", "https://", "javascript:", "mailto:", "news:", "res://", "telnet://", "view-source:" ];
Url.isAbsoluteUrl = function(url) {
 if (url) {
  for (var i = 0; i < absolutePathPrefixes.length; i++) {
   if(url.indexOf(absolutePathPrefixes[i]) == 0)
    return true;
  }
 }
 return false;
};
Url.getURLObject = function(url) {
 var link = document.createElement('A');
 link.href = url || "";
 return { 
  href: link.href,
  protocol: link.protocol,
  host: link.host,
  port: link.port,
  pathname: link.pathname,
  search: link.search,
  hash: link.hash
 }; 
};
Url.getRootRelativeUrl = function(url) {
 return getRelativeUrl(url, !Url.isRootRelativeUrl(url), true); 
};
Url.getPathRelativeUrl = function(url) {
 return getRelativeUrl(url, !Url.isPathRelativeUrl(url), false);
};
function getRelativeUrl(url, isValid, isRootRelative) {
 if(url && !(/data:([^;]+\/?[^;]*)(;charset=[^;]*)?(;base64,)/.test(url)) && isValid) {
  var urlObject = Url.getURLObject(url);
  var baseUrlObject = Url.getURLObject();
  if(!Url.isAbsoluteUrl(url) || urlObject.host === baseUrlObject.host && urlObject.protocol === baseUrlObject.protocol) {
   url = urlObject.pathname;
   if(!isRootRelative)
    url = getPathRelativeUrl(baseUrlObject.pathname, url);
   url = url + urlObject.search + urlObject.hash;
  }
 }
 return url;   
}
function getPathRelativeUrl(baseUrl, url) {
 var requestSegments = getSegments(baseUrl, false);
 var urlSegments = getSegments(url, true);
 return buildPathRelativeUrl(requestSegments, urlSegments, 0, 0, "");
}
function getSegments(url, addTail) {
 var segments = [];
 var startIndex = 0;
 var endIndex = -1;
 while ((endIndex = url.indexOf("/", startIndex)) != -1) {
  segments.push(url.substring(startIndex, ++endIndex));
  startIndex = endIndex;
 }
 if(addTail && startIndex < url.length)
  segments.push(url.substring(startIndex, url.length)); 
 return segments;
}
function buildPathRelativeUrl(requestSegments, urlSegments, reqIndex, urlIndex, buffer) {
 if(urlIndex >= urlSegments.length)
  return buffer;
 if(reqIndex >= requestSegments.length)
  return buildPathRelativeUrl(requestSegments, urlSegments, reqIndex, urlIndex + 1, buffer + urlSegments[urlIndex]);
 if(requestSegments[reqIndex] === urlSegments[urlIndex] && urlIndex === reqIndex)
  return buildPathRelativeUrl(requestSegments, urlSegments, reqIndex + 1, urlIndex + 1, buffer);
 return buildPathRelativeUrl(requestSegments, urlSegments, reqIndex + 1, urlIndex, buffer + "../");
}
Url.isPathRelativeUrl = function(url) {
 return !!url && !Url.isAbsoluteUrl(url) && url.indexOf("/") != 0;  
};
Url.isRootRelativeUrl = function(url) {
 return !!url && !Url.isAbsoluteUrl(url) && url.indexOf("/") == 0 && url.indexOf("//") != 0;
};
function navigateTo(url, target) {
 var lowerCaseTarget = target.toLowerCase();
 if("_top" == lowerCaseTarget)
  top.location.href = url;
 else if("_self" == lowerCaseTarget)
  location.href = url;
 else if("_search" == lowerCaseTarget)
  openInNewWindow(url);
 else if("_media" == lowerCaseTarget)
  openInNewWindow(url);
 else if("_parent" == lowerCaseTarget)
  window.parent.location.href = url;
 else if("_blank" == lowerCaseTarget)
  openInNewWindow(url);
 else {
  var frame = getFrame(top.frames, target);
  if(frame != null)
   frame.location.href = url;
  else
   openInNewWindow(url);
 }
}
function openInNewWindow(url) {
 if(ASPx.Browser.Safari)
  openInNewWindowViaIframe(url);
 else {
  var newWindow = window.open();
  newWindow.opener = null;
  newWindow.location = url;
 }
}
function openInNewWindowViaIframe(url) {
 var iframe = document.createElement('iframe');
 iframe.style.display = 'none';
 document.body.appendChild(iframe);
 var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
 var openArgs = '"' + url + '"';
 var script = iframeDoc.createElement('script');
 script.type = 'text/javascript';
 script.text = 'window.parent = null; ' +
  'window.top = null;' +
  'window.frameElement = null;' +
  'var child = window.open(' + openArgs + ');' +
  'child.opener = null';
 iframeDoc.body.appendChild(script);
 document.body.removeChild(iframe);
}
ASPx.Url = Url;
var Json = { };
function isValid(JsonString) {
 return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(JsonString.replace(/"(\\.|[^"\\])*"/g, '')));
}
Json.Eval = function(jsonString, controlName) {
 if(isValid(jsonString)) {
  return eval("(" + jsonString + ")");
 } else {
  throw new Error(controlName + " received incorrect JSON-data: " + jsonString);
 }
};
Json.ToJson = function(param, skipEncodeHtml){
 var paramType = typeof(param);
 if((paramType == "undefined") || (param == null))
  return null;
 if((paramType == "object") && (typeof(param.__toJson) == "function"))
  return param.__toJson();
 if((paramType == "number") || (paramType == "boolean"))
  return param;
 if(param.constructor == Date)
  return dateToJson(param);
 if(paramType == "string") {
  var result = param.replace(/\\/g, "\\\\");
  result = result.replace(/"/g, "\\\"");
  result = result.replace(/\n/g, "\\n");
  result = result.replace(/\r/g, "\\r");
  if(!skipEncodeHtml) {
   result = result.replace(/</g, "\\u003c");
   result = result.replace(/>/g, "\\u003e");
  }
  return "\"" + result + "\"";
 }
 if(param.constructor == Array){
  var values = [];
  for(var i = 0; i < param.length; i++) {
   var jsonValue = Json.ToJson(param[i], skipEncodeHtml);
   if(jsonValue === null)
    jsonValue = "null";
   values.push(jsonValue);
  }
  return "[" + values.join(",") + "]";
 }
 var exceptKeys = {};
 if(ASPx.Ident.IsArray(param.__toJsonExceptKeys))
  exceptKeys = Data.CreateHashTableFromArray(param.__toJsonExceptKeys);
 exceptKeys["__toJsonExceptKeys"] = 1;
 var values = [];
 for(var key in param) {
  if(param.hasOwnProperty(key)) {
   if(ASPx.IsFunction(param[key]))
    continue;
   if(exceptKeys[key] == 1)
    continue;
   values.push(Json.ToJson(key) + ":" + Json.ToJson(param[key], skipEncodeHtml));
  }
 }
 return "{" + values.join(",") + "}";
};
function dateToJson(date) {
 var result = [ 
  date.getFullYear(),
  date.getMonth(),
  date.getDate()
 ];
 var time = {
  h: date.getHours(),
  m: date.getMinutes(),
  s: date.getSeconds(),
  ms: date.getMilliseconds()
 };
 if(time.h || time.m || time.s || time.ms)
  result.push(time.h);
 if(time.m || time.s || time.ms)
  result.push(time.m);
 if(time.s || time.ms)
  result.push(time.s);
 if(time.ms)
  result.push(time.ms);
 return "new Date(" + result.join() + ")";
}
ASPx.Json = Json;
ASPx.CreateClass = function(parentClass, properties) {
 if(arguments.length == 1) {
  properties = parentClass;
  parentClass = null;
 }
 var ret = function() {
  if(ret.preparing) 
   return delete(ret.preparing);
  if(ret.constr) {
   this.constructor = ret;
   ret.constr.apply(this, arguments);
  }
 };
 ret.prototype = {};
 if(parentClass) {
  parentClass.preparing = true;
  for(var name in parentClass) {
   if(parentClass.hasOwnProperty(name) && name != 'constr' && ASPx.IsFunction(parentClass[name]) && !ret[name])
    ret[name] = parentClass[name].aspxBind(parentClass);
  }
  ret.prototype = new parentClass;
  ret.prototype.constructor = parentClass;
  ret.constr = parentClass;
 }
 if(properties) {
  var constructorName = "constructor";
  for(var name in properties) {
   if(!properties.hasOwnProperty(name)) 
    continue;
   var getter = Object.getOwnPropertyDescriptor(properties, name).get;
   var setter = Object.getOwnPropertyDescriptor(properties, name).set;
   if(getter || setter)
    Object.defineProperty(ret.prototype, name, {
     set: setter,
     get: getter,
     enumerable: true,
     configurable: true
    });
   if(name != constructorName && !getter && !setter)
    ret.prototype[name] = properties[name];
  }
  if(properties[constructorName] && properties[constructorName] != Object)
   ret.constr = properties[constructorName];
 }
 return ret;
};
var registeredMixins = {};
ASPx.GetMixin = function (name, baseClass) {
 var mixinCache = baseClass._mixins || (baseClass._mixins = {});
 var resultClass = mixinCache[name];
 if (!resultClass) {
  var mixinCodeBuilder = registeredMixins[name];
  if (!mixinCodeBuilder)
   throw new Error("mixin with the '" + name + "' is not registered");
  var mixinCode = mixinCodeBuilder(baseClass);
  mixinCode.mixinName = name;
  resultClass = ASPx.CreateClass(baseClass, mixinCode);
  mixinCache[name] = resultClass;
 }
 return resultClass;
};
ASPx.RegisterMixin = function() {
 var name = arguments.length == 1 ? "mixin_" + ASPx.CreateGuid() : arguments[0];
 var mixinCodeBuilder = arguments[arguments.length - 1];
 if (registeredMixins[name])
  throw new Error("mixin with the '" + name + "' name is already defined");
 registeredMixins[name] = mixinCodeBuilder;
 return function(baseClass) { return ASPx.GetMixin(name, baseClass); };
};
ASPx.FormatCallbackArg = function(prefix, arg) {
 if(prefix == null && arg == null)
  return ""; 
 if(prefix == null) prefix = "";
 if(arg == null) arg = "";
 if(arg != null && !ASPx.IsExists(arg.length) && ASPx.IsExists(arg.value))
  arg = arg.value;
 arg = arg.toString();
 return [prefix, '|', arg.length, '|' , arg].join('');
};
ASPx.FormatCallbackArgs = function(callbackData) {
 var sb = [ ];
 for(var i = 0; i < callbackData.length; i++)
  sb.push(ASPx.FormatCallbackArg(callbackData[i][0], callbackData[i][1]));
 return sb.join("");
};
ASPx.ParseShortcutString = function(shortcutString) {
 if(!shortcutString)
  return 0;
 var isCtrlKey = false;
 var isShiftKey = false;
 var isAltKey = false;
 var isMetaKey = false;
 var keyCode = null;
 var shcKeys = shortcutString.toString().split("+");
 if(shcKeys.length > 0) {
  for(var i = 0; i < shcKeys.length; i++) {
   var key = Str.Trim(shcKeys[i].toUpperCase());
   switch (key) {
    case "CONTROL":
    case "CONTROLKEY":
    case "CTRL":
     isCtrlKey = true;
     break;
    case "SHIFT":
    case "SHIFTKEY":
     isShiftKey = true;
     break;
    case "ALT":
     isAltKey = true;
     break;
    case "CMD":
     isMetaKey = true;
     break;
    case "F1": keyCode = ASPx.Key.F1; break;
    case "F2": keyCode = ASPx.Key.F2; break;
    case "F3": keyCode = ASPx.Key.F3; break;
    case "F4": keyCode = ASPx.Key.F4; break;
    case "F5": keyCode = ASPx.Key.F5; break;
    case "F6": keyCode = ASPx.Key.F6; break;
    case "F7": keyCode = ASPx.Key.F7; break;
    case "F8": keyCode = ASPx.Key.F8; break;
    case "F9": keyCode = ASPx.Key.F9; break;
    case "F10":   keyCode = ASPx.Key.F10; break;
    case "F11":   keyCode = ASPx.Key.F11; break;
    case "F12":   keyCode = ASPx.Key.F12; break;
    case "RETURN":
    case "ENTER": keyCode = ASPx.Key.Enter; break;
    case "HOME":  keyCode = ASPx.Key.Home; break;
    case "END":   keyCode = ASPx.Key.End; break;
    case "LEFT":  keyCode = ASPx.Key.Left; break;
    case "RIGHT": keyCode = ASPx.Key.Right; break;
    case "UP": keyCode = ASPx.Key.Up; break;
    case "DOWN":  keyCode = ASPx.Key.Down; break;
    case "PAGEUP": keyCode = ASPx.Key.PageUp; break;
    case "PAGEDOWN": keyCode = ASPx.Key.PageDown; break;
    case "SPACE": keyCode = ASPx.Key.Space; break;
    case "TAB":   keyCode = ASPx.Key.Tab; break;
    case "BACKSPACE": 
    case "BACK": keyCode = ASPx.Key.Backspace; break;
    case "CONTEXT": keyCode = ASPx.Key.ContextMenu; break;
    case "ESCAPE":
    case "ESC":
     keyCode = ASPx.Key.Esc;
     break;
    case "DELETE":
    case "DEL":
     keyCode = ASPx.Key.Delete;
     break;
    case "INSERT":
    case "INS":
     keyCode = ASPx.Key.Insert;
     break;
    case "PLUS":
     keyCode = "+".charCodeAt(0);
     break;
    default:
     keyCode = key.charCodeAt(0);
     break;
   }
  }
 } else
  ASPx.ShowErrorAlert("Invalid shortcut");
 return ASPx.GetShortcutCode(keyCode, isCtrlKey, isShiftKey, isAltKey, isMetaKey);
};
ASPx.GetShortcutCode = function(keyCode, isCtrlKey, isShiftKey, isAltKey, isMetaKey) {
 var value = keyCode;
 value |= isCtrlKey ? ASPx.ModifierKey.Ctrl : 0;
 value |= isShiftKey ? ASPx.ModifierKey.Shift : 0;
 value |= isAltKey ? ASPx.ModifierKey.Alt : 0;
 value |= isMetaKey ? ASPx.ModifierKey.Meta : 0;
 return value;
};
ASPx.GetShortcutCodeByEvent = function(evt) {
 return ASPx.GetShortcutCode(Evt.GetKeyCode(evt), evt.ctrlKey, evt.shiftKey, evt.altKey, ASPx.Browser.MacOSPlatform ? evt.metaKey : false);
};
ASPx.IsPasteShortcut = function(evt) {
 if(evt.type === "paste")
  return true;
 var keyCode = Evt.GetKeyCode(evt);
 if(Browser.NetscapeFamily && evt.which == 0)  
  keyCode = evt.keyCode;
 return (evt.ctrlKey && (keyCode == 118  || (keyCode == 86))) ||
     (evt.shiftKey && !evt.ctrlKey && !evt.altKey &&
     (keyCode == ASPx.Key.Insert)) ;
};
var NotPrintableKeyCodes = null;
ASPx.IsPrintableKey = function(keyCode) {
 if (!NotPrintableKeyCodes)
  NotPrintableKeyCodes = Object.keys(ASPx.Key).map(function(key) { return ASPx.Key[key]; });
 return !ASPx.Data.ArrayContains(NotPrintableKeyCodes, keyCode);
};
ASPx.SetFocus = function(element, selectAction) {
 function focusCore(element, selectAction){
  try {
    element.focus();
    if(selectAction) {
     var currentSelection = Selection.GetInfo(element);
     if(currentSelection.startPos == currentSelection.endPos) {
      switch(selectAction) {
       case "start":
        Selection.SetCaretPosition(element, 0);
        break;
       case "all":
        Selection.Set(element);
        break;
      }
     }
    }
   } catch (e) {
  }
 }
 if(ASPxClientUtils.iOSPlatform || ASPxClientUtils.androidPlatform) 
  focusCore(element, selectAction);
 else {
  window.setTimeout(function() { 
   focusCore(element, selectAction);
  }, ASPx.FOCUS_TIMEOUT);
 }
};
ASPx.IsFocusableCore = function(element, skipContainerVisibilityCheck) {
 var current = element;
 while(current && current.nodeType == 1) {
  if(current == element || !skipContainerVisibilityCheck(current)) {
   var tagName = current.tagName.toUpperCase();
   if(tagName == "BODY")
    return true;
   var disabledElementTags = ["INPUT", "BUTTON", "TEXTAREA", "SELECT", "OPTION"];
   if(disabledElementTags.indexOf(tagName) !== -1 && current.disabled || !ASPx.GetElementDisplay(current) || !ASPx.GetElementVisibility(current))
    return false;
  }
  current = current.parentNode;
 }
 return true;
};
ASPx.IsFocusable = function(element) {
 return ASPx.IsFocusableCore(element, ASPx.FalseFunction);
};
ASPx.RemoveFocus = function(parent) {
 var div = document.createElement('div');
 div.tabIndex = "-1";
 concealDivElement(div);
 parent.appendChild(div);
 if(ASPx.IsFocusable(div))
  div.focus();
 ASPx.RemoveElement(div);
};
function concealDivElement(div){
 div.style.position = "absolute";
 div.style.left = 0;
 div.style.top = 0;
 if(ASPx.Browser.WebKitFamily) {
  div.style.opacity = 0;
  div.style.width = 1;
  div.style.height = 1;
 } else {
  div.style.border = 0;
  div.style.width = 0;
  div.style.height = 0;
 }
}
var ActionElementsCache = ASPx.CreateClass(null, {
 constructor: function() {
  this.usageCounter = 0;
  this.elements = [ ];
  this.values = [ ];
 },
 IsActive: function() { return this.usageCounter > 0; },
 BeginUsage: function() {
  this.usageCounter++;
 },
 EndUsage: function() {
  this.usageCounter--;
  if(this.usageCounter === 0)
   this.Clear();
 },
 Add: function(element, value) {
  var index = this.elements.length;
  this.elements[index] = element;
  this.values[index] = value;
 },
 Get: function(element) { 
  var index = this.elements.indexOf(element);
  var hasValue = index > -1;
  var value = hasValue ? this.values[index] : undefined;
  return { hasValue: hasValue, value: value };
 },
 Clear: function() { 
  this.elements = [ ];
  this.values = [ ];
 }
});
ASPx.ActionElementsCache = new ActionElementsCache();
ASPx.IsActionElement = function(element) {
 if(!ASPx.IsExistsElement(element))
  return false;
 var useCache = ASPx.ActionElementsCache.IsActive();
 if(useCache) {
  var cacheValue = ASPx.ActionElementsCache.Get(element);
  if(cacheValue.hasValue)
   return cacheValue.value;
 }
 var isActionElement = ASPx.IsActionElementCore(element);
 if(useCache)
  ASPx.ActionElementsCache.Add(element, isActionElement);
 return isActionElement;
};
ASPx.IsActionElementCore = function(element) {
 var tabIndex = parseInt(ASPx.Attr.GetAttribute(element, ASPx.Attr.GetTabIndexAttributeName()));
 var hasTabIndex = !isNaN(tabIndex);
 var hasNonNegativeTabIndex = hasTabIndex && tabIndex > -1;
 var hasNegativeTabIndex = hasTabIndex && tabIndex < 0;
 var tagName = element.tagName;
 var focusableElementTags = ["BUTTON", "SELECT", "TEXTAREA", "OPTION", "IFRAME"];
 var isFocusableCore = ASPx.IsFocusable(element);
 var isFocusableTag = focusableElementTags.indexOf(tagName) !== -1;
 var isFocusableLink = tagName === "A" && (!!element.href || hasNonNegativeTabIndex);
 var isFocusableInput = tagName === "INPUT" && element.type.toLowerCase() !== "hidden";
 var isFocusableByTabIndex = tagName !== "INPUT" && hasNonNegativeTabIndex;
 var isEditableDiv = tagName == "DIV" && element.contentEditable === "true";
 return isFocusableCore && !hasNegativeTabIndex && (isFocusableTag || isFocusableLink || isFocusableInput || isFocusableByTabIndex || isEditableDiv);
};
ASPx.GetCanBeActiveElementsInContainer = function(container) {
 var canBeActiveTags = ["INPUT", "A", "UL", "BUTTON", "TEXTAREA", "SELECT", "IFRAME"],
  canBeActiveElements = [];
 Data.ForEach(canBeActiveTags, function(tag) {
  var elements = container.getElementsByTagName(tag);
  canBeActiveElements = canBeActiveElements.concat([].slice.call(elements));
 });
 return canBeActiveElements;
};
function isActionElementAllowedByPredicate(element, predicate) {
  var allowedByPredicate = !predicate || predicate(element);
  return allowedByPredicate && ASPx.IsActionElement(element);
}
ASPx.FindChildActionElements = function(container, predicate) {
 return ASPx.GetNodes(container, function(el) {
  return isActionElementAllowedByPredicate(el, predicate);
 });
};
ASPx.FindAllSortedActionElements = function(container, predicate) {
 var result = [ ];
 if(!container || !container.getElementsByTagName) return result;
 var actionElements = ASPx.FindChildActionElements(container, predicate);
 var getTabOrderValue = function(el) {
  var tabIndex = parseInt(ASPx.Attr.GetAttribute(el, ASPx.Attr.GetTabIndexAttributeName()));
  return isNaN(tabIndex) ? 0 : tabIndex;
 };
 var positiveTabIndexElements = actionElements.filter(function(x) { return getTabOrderValue(x) > 0; });
 var nonPositiveTabIndexElements = actionElements.filter(function(x) { return getTabOrderValue(x) === 0; });
 var sortedTabIndexElements = positiveTabIndexElements.sort(function(x, y) { return getTabOrderValue(x) - getTabOrderValue(y); });
 result = sortedTabIndexElements.concat(nonPositiveTabIndexElements);
 return result;
};
ASPx.FindFirstChildActionElement = function(container, predicate) {
 if(!container || isActionElementAllowedByPredicate(container, predicate))
  return !container ? null : container;
 var sortedActionElements = ASPx.FindAllSortedActionElements(container, predicate);
 return sortedActionElements[0];
};
ASPx.FindLastChildActionElement = function(container, predicate) {
 if(!container)
  return null;
 var sortedActionElements = ASPx.FindAllSortedActionElements(container, predicate);
 var actionElement = sortedActionElements[sortedActionElements.length - 1];
 if(!actionElement && isActionElementAllowedByPredicate(container, predicate))
  actionElement = container;
 return actionElement;
};
ASPx.GetParentClientControls = function(name) {
 var nameParts = name.split("_");
 var result = [ ];
 var controlCollection = ASPx.GetControlCollection();
 for(var i = 1; i <= nameParts.length; i++) {
  var controlName = nameParts.slice(0, i).join("_");
  var control = controlCollection.Get(controlName);
  if(control)
   result.push(control);
 }
 return result;
};
ASPx.GetRootClientControl = function(childControlName) {
 var parentControls = ASPx.GetParentClientControls(childControlName);
 return parentControls[0];
};
ASPx.GetClientControlByElementID = function(elementID) {
 var parentControls = ASPx.GetParentClientControls(elementID);
 return parentControls[parentControls.length - 1];
};
ASPx.IsExists = function(obj){
 return (typeof(obj) != "undefined") && (obj != null);
};
ASPx.IsFunction = function(obj){
 return typeof(obj) == "function";
};
ASPx.IsNumber = function(str) {
 return !isNaN(parseFloat(str)) && isFinite(str);
};
ASPx.GetDefinedValue = function(value, defaultValue){
 return (typeof(value) != "undefined") ? value : defaultValue;
};
ASPx.CorrectJSFloatNumber = function(number) {
 var ret = 21; 
 var numString = number.toPrecision(21);
 numString = numString.replace("-", ""); 
 var integerDigitsCount = numString.indexOf(ASPx.PossibleNumberDecimalSeparators[0]);
 if(integerDigitsCount < 0)
  integerDigitsCount = numString.indexOf(ASPx.PossibleNumberDecimalSeparators[1]);
 var floatDigitsCount = numString.length - integerDigitsCount - 1;
 if(floatDigitsCount < 10)
  return number;
 if(integerDigitsCount > 0) {
  ret = integerDigitsCount + 12;
 }
 var toPrecisionNumber = Math.min(ret, 21);
 var newValueString = number.toPrecision(toPrecisionNumber);
 return parseFloat(newValueString, 10);
};
ASPx.CorrectRounding = function(number, step) { 
 var regex = /[,|.](.*)/,
  isFloatValue = regex.test(number),
  isFloatStep = regex.test(step);
 if(isFloatValue || isFloatStep) {
  var valueAccuracy = (isFloatValue) ? regex.exec(number)[0].length - 1 : 0,
   stepAccuracy = (isFloatStep) ? regex.exec(step)[0].length - 1 : 0,
   accuracy = Math.max(valueAccuracy, stepAccuracy);
  var multiplier = Math.pow(10, accuracy);
  number = Math.round((number + step) * multiplier) / multiplier;
  return number;
 }
 return number + step;
};
ASPx.GetActiveElement = function() {
 try{ return document.activeElement; } catch(e) { return null; }
};
var verticalScrollBarWidth;
ASPx.GetVerticalScrollBarWidth = function() {
 if(typeof(verticalScrollBarWidth) == "undefined") {
  var container = document.createElement("DIV");
  container.style.cssText = "position: absolute; top: 0px; left: 0px; visibility: hidden; width: 200px; height: 150px; overflow: hidden; box-sizing: content-box";
  document.body.appendChild(container);
  var child = document.createElement("P");
  container.appendChild(child);
  child.style.cssText = "width: 100%; height: 200px;";
  var widthWithoutScrollBar = child.offsetWidth;
  container.style.overflow = "scroll";
  var widthWithScrollBar = child.offsetWidth;
  if(widthWithoutScrollBar == widthWithScrollBar)
   widthWithScrollBar = container.clientWidth;
  verticalScrollBarWidth = widthWithoutScrollBar - widthWithScrollBar;
  document.body.removeChild(container);
 }
 return verticalScrollBarWidth;
};
function hideScrollBarCore(element, scrollName) {
 if(element.tagName == "IFRAME") {
  if((element.scrolling == "yes") || (element.scrolling == "auto")) {
   Attr.ChangeAttribute(element, "scrolling", "no");
   return true;
  }
 }
 else if(element.tagName == "DIV") {
  if((element.style[scrollName] == "scroll") || (element.style[scrollName] == "auto")) {
   Attr.ChangeStyleAttribute(element, scrollName, "hidden");
   return true;
  }
 }
 return false;
}
function restoreScrollBarCore(element, scrollName) {
 if(element.tagName == "IFRAME")
  return Attr.RestoreAttribute(element, "scrolling");
 else if(element.tagName == "DIV")
  return Attr.RestoreStyleAttribute(element, scrollName);
 return false;
}
ASPx.SetScrollBarVisibilityCore = function(element, scrollName, isVisible) {
 return isVisible ? restoreScrollBarCore(element, scrollName) : hideScrollBarCore(element, scrollName);
};
ASPx.SetScrollBarVisibility = function(element, isVisible) {
 if(ASPx.SetScrollBarVisibilityCore(element, "overflow", isVisible)) 
  return true;
 var result = ASPx.SetScrollBarVisibilityCore(element, "overflowX", isVisible)
  || ASPx.SetScrollBarVisibilityCore(element, "overflowY", isVisible);
 return result;
};
ASPx.SetInnerHtml = function(element, html) {
 setInnerHtmlInternal(element, html);
};
ASPx.GetInnerText = function(container) {
 if(Browser.Safari && Browser.MajorVersion <= 5) {
  var filter = getHtml2PlainTextFilter();
  setInnerHtmlInternal(filter, container.innerHTML);
  ASPx.SetElementDisplay(filter, true);
  var innerText = filter.innerText;
  ASPx.SetElementDisplay(filter, false);
  return innerText;
 } else if(Browser.NetscapeFamily || Browser.WebKitFamily || (Browser.IE && Browser.Version >= 9) || Browser.Edge) {
  return container.textContent;
 } else
  return container.innerText;
};
ASPx.GetEllipsisTooltipText = function(element) {
 var innerText = ASPx.GetInnerText(element);
 innerText = ASPx.RemoveComment(innerText);
 return innerText;
};
ASPx.RemoveComment = function(text) {
 var result = text;
 var commentStart = "<!--";
 var commentEnd = "//-->";
 var positionStart = result.indexOf(commentStart);
 while(positionStart > -1) {
  var positionEnd = result.indexOf(commentEnd);
  var startStr = result.substring(0, positionStart);
  var endStr = result.substring(positionEnd + commentEnd.length);
  result = startStr + endStr;
  positionStart = result.indexOf(commentStart);
 }
 return result;
};
var html2PlainTextFilter = null;
function getHtml2PlainTextFilter() {
 if(html2PlainTextFilter == null) {
  html2PlainTextFilter = document.createElement("DIV");
  html2PlainTextFilter.style.width = "0";
  html2PlainTextFilter.style.height = "0";
  html2PlainTextFilter.style.overflow = "visible";
  ASPx.SetElementDisplay(html2PlainTextFilter, false);
  document.body.appendChild(html2PlainTextFilter);
 }
 return html2PlainTextFilter;
}
ASPx.CreateHiddenField = function(name, id, parent) {
 var input = document.createElement("INPUT");
 input.setAttribute("type", "hidden");
 if(name)
  input.setAttribute("name", name);
 if(id)
  input.setAttribute("id", id);
 if(parent)
  parent.appendChild(input);
 return input;
};
ASPx.CloneObject = function(srcObject) {
 if(typeof(srcObject) != 'object' || srcObject == null)
  return srcObject;
 var newObject = {};
 for(var i in srcObject)
  newObject[i] = srcObject[i];
 return newObject;
};
ASPx.InsertRowsBefore = function(table, rowsHtml, index) {
 var row = null;
 if(index >= 0 && index < table.rows.length)
  row = table.rows[index];
 insertRowsBefore(table, rowsHtml, row);
};
var insertRowsBefore = function(table, rowsHtml, row) {
 if(!row && table.tBodies.length > 0) {
  row = document.createElement("TR");
  table.tBodies[0].appendChild(row);
  row.shouldRemove = true;
 }
 if(row) {
  row.insertAdjacentHTML("beforeBegin", rowsHtml);
  if(row.shouldRemove)
   ASPx.RemoveElement(row);
 }
};
ASPx.IsPercentageSize = function(size) {
 return size && size.indexOf('%') != -1;
};
ASPx.GetElementById = function(id) {
 if(document.getElementById)
  return document.getElementById(id);
 else
  return document.all[id];
};
ASPx.GetElementByIdInDocument = function(documentObj, id) {
 if(documentObj.getElementById)
  return documentObj.getElementById(id);
 else
  return documentObj.all[id];
};
ASPx.GetIsParent = function(parentElement, element) {
 if(!parentElement || !element)
  return false;
 while(element){
  if(element === parentElement)
   return true;
  if(element.tagName === "BODY")
   return false;
  element = element.parentNode;
 }
 return false;
};
ASPx.GetParentById = function(element, id) {
 element = element.parentNode;
 while(element){
  if(element.id === id)
   return element;
  element = element.parentNode;
 }
 return null;
};
ASPx.GetParentByPartialId = function(element, idPart){
 while(element && element.tagName != "BODY") {
  if(element.id && element.id.match(idPart)) 
   return element;
  element = element.parentNode;
 }
 return null;
};
ASPx.GetParentByTagName = function(element, tagName) {
 tagName = tagName.toUpperCase();
 while(element) {
  if(element.tagName === "BODY")
   return null;
  if(element.tagName === tagName)
   return element;
  element = element.parentNode;
 }
 return null;
};
function getParentByCondition(element, conditionArg, condition) {
 while(element != null) {
  if(element.tagName == "BODY" || element.nodeName == "#document")
   return null;
  if (condition(element, conditionArg))
   return element;
  element = element.parentNode;
 }
 return null;
}
ASPx.GetParentByPartialClassName = function(element, className) {
 return getParentByCondition(element, className, ASPx.ElementContainsCssClass);
};
ASPx.GetParentByClassName = function(element, className) {
 return getParentByCondition(element, className, ASPx.ElementHasCssClass);
};
ASPx.GetParentBySelector = function (element, selector) {
 return getParentByCondition(element, selector, ASPx.ElementMatchesSelector);
};
ASPx.GetParentByTagNameAndAttributeValue = function(element, tagName, attrName, attrValue) {
 tagName = tagName.toUpperCase();
 while(element != null) {
  if(element.tagName == "BODY")
   return null;
  if(element.tagName == tagName && element[attrName] == attrValue)
   return element;
  element = element.parentNode;
 }
 return null;
};
ASPx.GetParent = function(element, testFunc){
 if (!ASPx.IsExists(testFunc)) return null;
 while(element != null && element.tagName != "BODY"){
  if(testFunc(element))
   return element;
  element = element.parentNode;
 }
 return null;
};
ASPx.GetElementTreeLine = function(element, stopTagName, stopFunc) {
 var result = [];
 stopTagName = stopTagName || "BODY";
 while(element != null) {
  if(!stopFunc && element.tagName == stopTagName)
   break;
  if(stopFunc && stopFunc(element))
   break;
  result.push(element);
  element = element.parentNode;
 }
 return result;
};
ASPx.IsScrollableElement = function(element, isHorzScrollable, isVertScrollable) {
 isHorzScrollable = ASPx.IsExists(isHorzScrollable) ? isHorzScrollable : true;
 isVertScrollable = ASPx.IsExists(isVertScrollable) ? isVertScrollable : true;
 var style = ASPx.GetCurrentStyle(element);
 var overflowStyleNames = ["overflow"];
 if(isHorzScrollable)
  overflowStyleNames.push("overflowX");
 if(isVertScrollable)
  overflowStyleNames.push("overflowY");
 for(var i = 0; i < overflowStyleNames.length; i++)
  if(style[overflowStyleNames[i]] == "scroll" || style[overflowStyleNames[i]] == "auto")
   return true;
 return false;
};
ASPx.GetPreviousSibling = function(el) {
 if(el.previousElementSibling) {
  return el.previousElementSibling;
 } else {
  while(el = el.previousSibling) {
   if(el.nodeType === 1)
    return el;
  }
 }
};
ASPx.ElementMatchesSelector = (function (e) {
 return (function (matches) {
  return function (el, selector) { return !!el && !!selector && matches.call(el, selector); };
 })(e.matches || e.matchesSelector || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector || e.oMatchesSelector);
})(Element.prototype);
ASPx.ElementHasCssClass = function(element, className) {
 try {
  var elementClasses;
  var classList = ASPx.GetClassNameList(element);
  if(!classList) {
   var elementClassName = ASPx.GetClassName(element);
   if(!elementClassName) {
    return false;
   }
   elementClasses = elementClassName.split(" ");
  }
  var classNames = className.split(" ");
  for(var i = classNames.length - 1; i >= 0; i--) {
   if(classList) {
    if(classList.indexOf(classNames[i]) === -1)
     return false;
    continue;
   }
   if(Data.ArrayIndexOf(elementClasses, classNames[i]) < 0)
    return false;
  }
  return true;
 } catch(e) {
  return false;
 }
};
ASPx.ElementContainsCssClass = function(element, className) {
 try {
  var elementClassName = ASPx.GetClassName(element);
  if(!elementClassName) {
   return false;
  }
  return elementClassName.indexOf(className) != -1;
 } catch(e) {
  return false;
 }
};
ASPx.AddClassNameToElement = function (element, className) {
 if(!element || typeof(className) !== "string" ) return;
 className = className.trim();
 if(!ASPx.ElementHasCssClass(element, className) && className !== "") {
  var oldClassName = ASPx.GetClassName(element);
  ASPx.SetClassName(element, (oldClassName === "") ? className : oldClassName + " " + className);
 }
};
ASPx.AddClassNamesToElement = function(element, classNames) {
 Data.ForEach(classNames, function(className) { ASPx.AddClassNameToElement(element, className); });
};
ASPx.CombineCssClasses = function() {
 return Array.prototype.slice.call(arguments).join(" ");
};
ASPx.RemoveClassNameFromElement = function(element, className) {
 if(!element) return;
 var elementClassName = ASPx.GetClassName(element);
 var updClassName = " " + elementClassName + " ";
 var newClassName = updClassName.replace(" " + className + " ", " ");
 if(updClassName.length != newClassName.length)
  ASPx.SetClassName(element, Str.Trim(newClassName));  
};
ASPx.RemoveClassNamesFromElement = function(element, classNames) {
 if(!element) return;
 for(var i = 0; i < classNames.length; i++) {
  var className = classNames[i];
  element.classList.remove(className);
 }
};
ASPx.ToggleClassNameToElement = function(element, className, toggleState) {
 if(!toggleState)
  ASPx.RemoveClassNameFromElement(element, className);
 if(toggleState && !ASPx.ElementHasCssClass(element, className))
  ASPx.AddClassNameToElement(element, className);
};
ASPx.GetClassNameList = function(element) {
 var result = [];
 if(element) {
  if(element.tagName === "svg") {
   result = ASPx.GetClassName(element).replace(/^\s+|\s+$/g, '').split(/\s+/);
  }
  else {
   result = element.classList ? [].slice.call(element.classList) : ASPx.GetClassName(element).replace(/^\s+|\s+$/g, '').split(/\s+/);
  }
 }
 return result;
};
ASPx.GetClassName = function(element) {
 var result = "";
 if(element) {
  if(element.tagName === "svg") {
   result = element.className.baseVal;
  }
  else {
   result = element.className ? element.className : "";
  }
 }
 return result;
};
ASPx.SetClassName = function(element, className) {
 if(element.tagName === "svg") {
  element.className.baseVal = Str.Trim(className);
 }
 else {
  element.className = Str.Trim(className);
 }
};
ASPx.GetElementOffsetWidth = function(element) {
 if(element.tagName === "svg") {
  return element.getBoundingClientRect().width;
 }
 else {
  return element.offsetWidth;
 }
};
ASPx.GetElementOffsetHeight = function(element) {
 if(element.tagName === "svg") {
  return element.getBoundingClientRect().height;
 }
 else {
  return element.offsetHeight;
 }
};
function nodeListToArray(nodeList, filter) {
 var result = [];
 for(var i = 0, element; element = nodeList[i]; i++) {
  if(filter && !filter(element))
   continue;
  result.push(element);
 }
 return result;
}
ASPx.NodeListToArray = nodeListToArray;
function getItemByIndex(collection, index) {
 if(!index) index = 0;
 if(collection != null && collection.length > index)
  return collection[index];
 return null;
}
ASPx.GetChildNodesByQuerySelector = function (parent, selector) {
 return nodeListToArray(parent.querySelectorAll(selector), function (el) { return el.parentNode === parent; });
};
ASPx.GetChildNodesByClassName = function(parent, className) {
 if(!parent) return [];
 if(parent.querySelectorAll) {
  var children = parent.querySelectorAll('.' + className);
  return nodeListToArray(children, function(element) { 
   return element.parentNode === parent;
  });
 }
 return ASPx.GetChildNodes(parent, function(elem) { return elem.className && ASPx.ElementHasCssClass(elem, className); });
};
ASPx.GetChildNodesByPartialClassName = function(element, className) {
 return ASPx.GetChildElementNodesByPredicate(element,
  function(child) {
   return ASPx.ElementContainsCssClass(child, className);
  });
};
ASPx.GetChildByPartialClassName = function(element, className, index) {
 if(element != null){    
  var collection = ASPx.GetChildNodesByPartialClassName(element, className);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.GetChildByClassName = function(element, className, index) {
 if(element != null){    
  var collection = ASPx.GetChildNodesByClassName(element, className);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.GetNodesByPartialClassName = function(element, className) {
 if(element.querySelectorAll) {
  var list = element.querySelectorAll('*[class*=' + className + ']');
  return nodeListToArray(list);
 }
 var collection = element.all || element.getElementsByTagName('*');
 var ret = [ ];
 if(collection != null) {
  for(var i = 0; i < collection.length; i ++) {
   if(ASPx.ElementContainsCssClass(collection[i], className))
    ret.push(collection[i]);
  }
 }
 return ret;
};
ASPx.GetNodesByClassName = function(parent, className) {
 if(parent.querySelectorAll) {
  var children = parent.querySelectorAll('.' + className);
  return nodeListToArray(children);
 }
 return ASPx.GetNodes(parent, function(elem) { return elem.className && ASPx.ElementHasCssClass(elem, className); });
};
ASPx.GetNodeByClassName = function(element, className, index) {
 if(element != null){    
  var collection = ASPx.GetNodesByClassName(element, className);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.GetChildById = function(element, id) {
 if(element.all) {
  var child = element.all[id];
  if(!child) {
   child = element.all(id); 
   if(!child)
    return null; 
  } 
  if(!ASPx.IsExists(child.length)) 
   return child;
  else
   return ASPx.GetElementById(id);
 }
 else
  return ASPx.GetElementById(id);
};
ASPx.GetNodesByPartialId = function(element, partialName, list) {
 if(element.id && element.id.indexOf(partialName) > -1) 
  list.push(element);
 if(element.childNodes) {
  for(var i = 0; i < element.childNodes.length; i ++) 
   ASPx.GetNodesByPartialId(element.childNodes[i], partialName, list);
 }
};
ASPx.GetNodesByTagName = function(element, tagName) {
 var tagNameToUpper = tagName.toUpperCase();
 var result = null;
 if(element) {
  if(element.getElementsByTagName) {
   result = element.getElementsByTagName(tagNameToUpper);
   if(result.length === 0) {
    result = element.getElementsByTagName(tagName);
   }
  }
  else if(element.all && element.all.tags !== undefined)
   result = Browser.Netscape ? element.all.tags[tagNameToUpper] : element.all.tags(tagNameToUpper);
 }
 return result;
};
ASPx.GetNodeByTagName = function(element, tagName, index) {
 if(element != null){    
  var collection = ASPx.GetNodesByTagName(element, tagName);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.GetChildNodesByTagName = function(parent, tagName) {
 return ASPx.GetChildNodes(parent, function (child) { return child.tagName === tagName; });
};
ASPx.GetChildByTagName = function(element, tagName, index) {
 if(element != null){    
  var collection = ASPx.GetChildNodesByTagName(element, tagName);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.RetrieveByPredicate = function(scourceCollection, predicate) {
 var result = [];
 for(var i = 0; i < scourceCollection.length; i++) {
  var element = scourceCollection[i];
  if(!predicate || predicate(element)) 
   result.push(element);
 }
 return result;
};
ASPx.GetChildNodes = function(parent, predicate) {
 return ASPx.RetrieveByPredicate(parent.childNodes, predicate);
};
ASPx.GetNodes = function(parent, predicate) {
 var c = parent.all || parent.getElementsByTagName('*');
 return ASPx.RetrieveByPredicate(c, predicate);
};
ASPx.GetChildElementNodes = function(parent) {
 if(!parent) return null;
 return ASPx.GetChildNodes(parent, function(e) { return e.nodeType == 1; });
};
ASPx.GetChildElementNodesByPredicate = function(parent, predicate) {
 if(!parent) return null;
 if(!predicate) return ASPx.GetChildElementNodes(parent);
 return ASPx.GetChildNodes(parent, function(e) { return e.nodeType == 1 && predicate(e); });
};
ASPx.GetTextNode = function(element, index) {
 if(element != null){
  var collection = [ ];
  ASPx.GetTextNodes(element, collection);
  return getItemByIndex(collection, index);
 }
 return null;
};
ASPx.GetTextNodes = function(element, collection) {
 if(element.tagName === "svg")
  return;
 for(var i = 0; i < element.childNodes.length; i ++){
  var childNode = element.childNodes[i];
  if(ASPx.IsExists(childNode.nodeValue))
   collection.push(childNode);
  ASPx.GetTextNodes(childNode, collection);
 }
};
ASPx.GetNormalizedTextNode = function(element, index) {
 var textNode = ASPx.GetTextNode(element, index);
 if(textNode != null)
  ASPx.MergeAdjacentTextNodes(textNode);
 return textNode;
};
ASPx.MergeAdjacentTextNodes = function(firstTextNode) {
 if(!ASPx.IsExists(firstTextNode.nodeValue))
  return;
 var textNode = firstTextNode;
 while(textNode.nextSibling && ASPx.IsExists(textNode.nextSibling.nodeValue)) {
  textNode.nodeValue += textNode.nextSibling.nodeValue;
  textNode.parentNode.removeChild(textNode.nextSibling);
 }
};
ASPx.GetElementDocument = function(element) {
 return element.document || element.ownerDocument;
};
ASPx.RemoveElement = function(element) {
 if(element && element.parentNode)
  element.parentNode.removeChild(element);
};
ASPx.ReplaceTagName = function(element, newTagName, cloneChilds) {
 if(element.nodeType != 1)
  return null;
 if(element.nodeName == newTagName)
  return element;
 cloneChilds = cloneChilds !== undefined ? cloneChilds : true;
 var doc = element.ownerDocument;
 var newElem = doc.createElement(newTagName);
 Attr.CopyAllAttributes(element, newElem);
 if(cloneChilds) {
  for(var i = 0; i < element.childNodes.length; i++)
   newElem.appendChild(element.childNodes[i].cloneNode(true));
 }
 else {
  for(var child; child = element.firstChild; )
   newElem.appendChild(child);
 }
 element.parentNode.replaceChild(newElem, element);
 return newElem;
};
ASPx.RemoveOuterTags = function(element) {
 var docFragment = element.ownerDocument.createDocumentFragment();
 for(var i = 0; i < element.childNodes.length; i++)
  docFragment.appendChild(element.childNodes[i].cloneNode(true));
 element.parentNode.replaceChild(docFragment, element);
};
ASPx.WrapElementInNewElement = function(element, newElementTagName) { 
 var wrapElement = null;
 var docFragment = element.ownerDocument.createDocumentFragment();
 wrapElement = element.ownerDocument.createElement(newElementTagName);
 docFragment.appendChild(wrapElement);
 wrapElement.appendChild(element.cloneNode(true));
 element.parentNode.replaceChild(docFragment, element);
 return wrapElement;
};
ASPx.InsertElementAfter = function(newElement, targetElement) {
 var parentElem = targetElement.parentNode;
 if(parentElem.childNodes[parentElem.childNodes.length - 1] == targetElement)
  parentElem.appendChild(newElement);
 else if(newElement !== targetElement.nextSibling)
  parentElem.insertBefore(newElement, targetElement.nextSibling);
};
ASPx.SetElementOpacity = function(element, value) {
  element.style.opacity = value;
};
ASPx.GetElementOpacity = function(element) {
 return parseFloat(ASPx.GetCurrentStyle(element).opacity);
};
ASPx.HiddenChangable = "dx-hc";
ASPx.DefaultDisplayNoneSelectors = [ "dxmodalSys" ];
ASPx.DefaultDisplaySelectors = ["show"];
function getIsDefaultDisplayNone(element) {
 for(var i = 0; i < ASPx.DefaultDisplayNoneSelectors.length; i++) {
  if(ASPx.ElementHasCssClass(element, ASPx.DefaultDisplayNoneSelectors[i]))
   return true;
 }
 return false;
}
ASPx.GetElementDisplay = function(element, isCurrentStyle) {
 if(isCurrentStyle) {
  var currentStyle = ASPx.GetCurrentStyle(element);
  if(currentStyle)
   return currentStyle.display != "none";
 }
 if(getIsDefaultDisplayNone(element))
  return element.style.display != "none" && element.style.display != "" || ASPx.DefaultDisplaySelectors.some(function(s) { return ASPx.ElementHasCssClass(element, s); });
 return element.style.display != "none" && !ASPx.ElementHasCssClass(element, ASPx.HiddenChangable);
};
ASPx.SetElementDisplay = function(element, value) {
 if(!element) return;
 if(ASPx.ElementHasCssClass(element, ASPx.HiddenChangable))
  ASPx.RemoveClassNameFromElement(element, ASPx.HiddenChangable);
 if(typeof(value) === "string")
  element.style.display = value;
 else if(getIsDefaultDisplayNone(element))
  element.style.display = value ? (element.tagName === "TABLE" ? "table" : "block") : "";
 else if(!value)
  element.style.display = "none";
 else
  element.style.display = "";
};
ASPx.GetElementVisibility = function(element, isCurrentStyle) {
 if(isCurrentStyle) {
  var currentStyle = ASPx.GetCurrentStyle(element);
  if(currentStyle)
   return currentStyle.visibility != "hidden";
 }
 return element.style.visibility != "hidden";
};
ASPx.SetElementVisibility = function(element, value) {
 if(!element) return;
 if(typeof(value) === "string")
  element.style.visibility = value;
 else
  element.style.visibility = value ? "visible" : "hidden";
};
ASPx.IsElementVisible = function(element, isCurrentStyle) {
 if(!element) return false;
 while(element && element.tagName != "BODY") {
  if(!ASPx.GetElementDisplay(element, isCurrentStyle) || (!ASPx.GetElementVisibility(element, isCurrentStyle) && !Attr.IsExistsAttribute(element, "errorFrame")))
     return false;
  element = element.parentNode;
 }
 return true;
};
ASPx.IsElementDisplayed = function(element) {
 if(!element) return false;
 while(element && element.tagName != "BODY") {
  if(!ASPx.GetElementDisplay(element))
     return false;
  element = element.parentNode;
 }
 return true;
};
ASPx.GetElementInitializedFlag = function(element) {
 return element["dxinit"];
};
ASPx.SetElementInitializedFlag = function(element) {
 element["dxinit"] = true;
};
ASPx.AddStyleSheetLinkToDocument = function(doc, linkUrl) {
 var newLink = createStyleLink(doc, linkUrl);
 var head = ASPx.GetHeadElementOrCreateIfNotExist(doc);
 head.appendChild(newLink);
 return newLink;
};
ASPx.GetHeadElementOrCreateIfNotExist = function(doc) {
 var elements = ASPx.GetNodesByTagName(doc, "head");
 var head = null;
 if(elements.length == 0) {
  head = doc.createElement("head");
  head.visibility = "hidden";
  doc.insertBefore(head, doc.body);
 } else
  head = elements[0];
 return head;
};
function createStyleLink(doc, url) {
 var newLink = doc.createElement("link");
 Attr.SetAttribute(newLink, "href", url);
 Attr.SetAttribute(newLink, "rel", "stylesheet");
 Attr.AppendStyleType(newLink);
 return newLink;
}
ASPx.GetCurrentStyle = function(element) {
 if(document.defaultView && document.defaultView.getComputedStyle) { 
  var result = document.defaultView.getComputedStyle(element, null);
  if(!result && Browser.Firefox && window.frameElement) {
   var changes = [];
   var curElement = window.frameElement;
   while(!(result = document.defaultView.getComputedStyle(element, null))) {
    changes.push([curElement, curElement.style.display]);
    ASPx.SetStylesCore(curElement, "display", "block", true);
    curElement = curElement.tagName == "BODY" ? curElement.ownerDocument.defaultView.frameElement : curElement.parentNode;
   }
   result = ASPx.CloneObject(result);
   for(var ch, i = 0; ch = changes[i]; i++)
    ASPx.SetStylesCore(ch[0], "display", ch[1]);
   var dummy = document.body.offsetWidth; 
  }
  if(Browser.Firefox && Browser.MajorVersion >= 62 && window.frameElement && result.length === 0) { 
   result = ASPx.CloneObject(result);
   result.display = element.style.display;
  }
  return result;
 }
 return window.getComputedStyle(element, null);
};
ASPx.CreateStyleSheetInDocument = function(doc) {
 if(doc.createStyleSheet) {
  try {
   return doc.createStyleSheet();
  }
  catch(e) {
   var message = "The CSS link limit (31) has been exceeded. Please enable CSS merging or reduce the number of CSS files on the page. For details, see http://www.devexpress.com/Support/Center/p/K18487.aspx.";
   throw new Error(message);
  }
 }
 else {
  var styleSheet = doc.createElement("STYLE");
  ASPx.GetNodeByTagName(doc, "HEAD", 0).appendChild(styleSheet);
  return styleSheet.sheet;
 }
};
ASPx.currentStyleSheet = null;
ASPx.GetCurrentStyleSheet = function() {
 if(!ASPx.currentStyleSheet)
  ASPx.currentStyleSheet = ASPx.CreateStyleSheetInDocument(document);
 return ASPx.currentStyleSheet;
};
function getStyleSheetRules(styleSheet){
 try {
  if (styleSheet.href && styleSheet.href.indexOf("file:///") === 0)
   return null;
  return styleSheet.cssRules;
 }
 catch(e) {
  return null;
 }
}
ASPx.cachedCssRules = { };
ASPx.GetStyleSheetRules = function (className, stylesStorageDocument) {
 if(ASPx.cachedCssRules[className]) {
  if(ASPx.cachedCssRules[className] != ASPx.EmptyObject)
   return ASPx.cachedCssRules[className];
  return null;
 }
 var result = iterateStyleSheetRules(stylesStorageDocument, function(rule) {
  if(rule.selectorText == "." + className){
   ASPx.cachedCssRules[className] = rule;
   return rule;
  }
 });
 if(ASPx.IsExists(result))
  return result;
 ASPx.cachedCssRules[className] = ASPx.EmptyObject;
 return null;
};
function iterateStyleSheetRules(stylesStorageDocument, callback) {
 var doc = stylesStorageDocument || document;
 for(var i = 0; i < doc.styleSheets.length; i ++){
  var styleSheet = doc.styleSheets[i];
  var rules = getStyleSheetRules(styleSheet);
  if(rules != null){
   for(var j = 0; j < rules.length; j ++) {
    var result = callback(rules[j]);
    if(result !== undefined)
     return result;
   }
  }
 }
}
ASPx.ProcessStyleSheetRules = function(prefix, callback) {
 iterateStyleSheetRules(null, function(rule) {
  if(!!rule.selectorText && rule.selectorText.indexOf(prefix) === 0) {
   var name = rule.selectorText.substring(prefix.length);
   var result = callback(name, rule.style, rule);
   if(result !== undefined)
    return result;
  }
 });
};
ASPx.ClearCachedCssRules = function(){
 ASPx.cachedCssRules = { };
};
var styleCount = 0;
var styleNameCache = { };
ASPx.CreateImportantStyleRule = function(styleSheet, cssText, postfix, prefix) {
 styleSheet = styleSheet || ASPx.GetCurrentStyleSheet();
 var cacheKey = (postfix ? postfix + "||" : "") + cssText + (prefix ? "||" + prefix : "");
 if(styleNameCache[cacheKey])
  return styleNameCache[cacheKey];
 prefix = prefix ? prefix + " " : "";
 var className = "dxh" + styleCount + (postfix ? postfix : "");
 ASPx.AddStyleSheetRule(styleSheet, prefix + "." + className, ASPx.CreateImportantCssText(cssText));
 styleCount++;
 styleNameCache[cacheKey] = className;
 return className; 
};
ASPx.CreateImportantCssText = function(cssText) {
 var newText = "";
 var hasEncodedSemicolon = cssText.indexOf(ASPx.StyleValueEncodedSemicolon) > -1;
 var attributes = cssText.split(";");
 for(var i = 0; i < attributes.length; i++) {
  var rule = attributes[i];
  if(rule != "")
   newText += ASPx.CreateImportantCssRule(rule, hasEncodedSemicolon);
 }
 return newText;
};
ASPx.CreateImportantCssRule = function(rule, hasEncodedSemicolon) {
 var result = rule;
 if(hasEncodedSemicolon) {
  var regex = new RegExp(ASPx.StyleValueEncodedSemicolon, "g");
  result = result.replace(regex, ";");
 }
 result = result + " !important;";
 return result;
};
ASPx.AddStyleSheetRule = function(styleSheet, selector, cssText){
 if(!cssText) return;
 var index = styleSheet.cssRules.length;
 styleSheet.insertRule(selector + " { " + cssText + " }", index);
 return styleSheet.cssRules[index];
};
ASPx.GetPointerCursor = function() {
 return "pointer";
};
ASPx.SetPointerCursor = function(element) {
 if(element.style.cursor == "")
  element.style.cursor = ASPx.GetPointerCursor();
};
ASPx.SetElementFloat = function(element, value) {
 if(ASPx.IsExists(element.style.cssFloat))
  element.style.cssFloat = value;
 else if(ASPx.IsExists(element.style.styleFloat))
  element.style.styleFloat = value;
 else
  Attr.SetAttribute(element.style, "float", value);
};
ASPx.GetElementFloat = function(element) {
 var currentStyle = ASPx.GetCurrentStyle(element);
 if(ASPx.IsExists(currentStyle.cssFloat))
  return currentStyle.cssFloat;
 if(ASPx.IsExists(currentStyle.styleFloat))
  return currentStyle.styleFloat;
 return Attr.GetAttribute(currentStyle, "float");
};
function getElementDirection(element) {
 return ASPx.GetCurrentStyle(element).direction;
}
ASPx.IsElementRightToLeft = function(element) {
 return getElementDirection(element) == "rtl";
};
ASPx.AdjustVerticalMarginsInContainer = function(container) {
 var containerBorderAndPaddings = ASPx.GetTopBottomBordersAndPaddingsSummaryValue(container);
 var flowElements = [], floatElements = [], floatTextElements = [];
 var maxHeight = 0, maxFlowHeight = 0;
 for(var i = 0; i < container.childNodes.length; i++) {
  var element = container.childNodes[i];
  if(!element.offsetHeight) continue;
  ASPx.ClearVerticalMargins(element);
 }
 for(var i = 0; i < container.childNodes.length; i++) {
  var element = container.childNodes[i];
  if(!element.offsetHeight) continue;
  var float = ASPx.GetElementFloat(element);
  var isFloat = (float === "left" || float === "right");
  if(isFloat)
   floatElements.push(element);
  else {
   flowElements.push(element);
   if(element.tagName !== "IMG"){
    if(!ASPx.IsTextWrapped(element))
     element.style.verticalAlign = 'baseline'; 
    floatTextElements.push(element);
   }
   if(element.tagName === "DIV")
    Attr.ChangeStyleAttribute(element, "float", "left"); 
  }
  if(element.offsetHeight > maxHeight) 
   maxHeight = element.offsetHeight;
  if(!isFloat && element.offsetHeight > maxFlowHeight) 
   maxFlowHeight = element.offsetHeight;
 }
 for(var i = 0; i < flowElements.length; i++) 
  Attr.RestoreStyleAttribute(flowElements[i], "float");
 var containerBorderAndPaddings = ASPx.GetTopBottomBordersAndPaddingsSummaryValue(container);
 var containerHeight = container.offsetHeight - containerBorderAndPaddings;
 if(maxHeight == containerHeight) {
  var verticalAlign = ASPx.GetCurrentStyle(container).verticalAlign;
  for(var i = 0; i < floatTextElements.length; i++)
   floatTextElements[i].style.verticalAlign = '';
  containerHeight = container.offsetHeight - containerBorderAndPaddings;
  for(var i = 0; i < floatElements.length; i++)
   adjustVerticalMarginsCore(floatElements[i], containerHeight, verticalAlign, true);
  for(var i = 0; i < flowElements.length; i++) {
   if(maxFlowHeight != maxHeight)
    adjustVerticalMarginsCore(flowElements[i], containerHeight, verticalAlign);
  }
 }
};
ASPx.AdjustVerticalMargins = function(element) {
 ASPx.ClearVerticalMargins(element);
 var parentElement = element.parentNode;
 var parentHeight = parentElement.getBoundingClientRect().height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(parentElement);
 adjustVerticalMarginsCore(element, parentHeight, ASPx.GetCurrentStyle(parentElement).verticalAlign);
};
function adjustVerticalMarginsCore(element, parentHeight, verticalAlign, toBottom) {
 var marginTop;
 if(verticalAlign == "top")
  marginTop = 0;
 else if(verticalAlign == "bottom")
  marginTop = parentHeight - element.getBoundingClientRect().height;
 else
  marginTop = (parentHeight - element.getBoundingClientRect().height) / 2;
 if(marginTop !== 0){
  element.style.marginTop = marginTop + "px";
 }
}
ASPx.ClearVerticalMargins = function(element) {
 element.style.marginTop = "";
 element.style.marginBottom = "";
};
ASPx.AdjustHeightInContainer = function(container) {
 var height = container.offsetHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(container);
 for(var i = 0; i < container.childNodes.length; i++) {
  var element = container.childNodes[i];
  if(!element.offsetHeight) continue;
  ASPx.ClearHeight(element);
 }
 var elements = [];
 var childrenHeight = 0;
 for(var i = 0; i < container.childNodes.length; i++) {
  var element = container.childNodes[i];
  if(!element.offsetHeight) continue;
  childrenHeight += element.offsetHeight + ASPx.GetTopBottomMargins(element);
  elements.push(element);
 }
 if(elements.length > 0 && childrenHeight < height) {
  var correctedHeight = 0;
  for(var i = 0; i < elements.length; i++) {
   var elementHeight = 0;
   if(i < elements.length - 1){
    var elementHeight = Math.floor(height / elements.length);
    correctedHeight += elementHeight;
   }
   else{
    var elementHeight = height - correctedHeight;
    if(elementHeight < 0) elementHeight = 0;
   }
   adjustHeightCore(elements[i], elementHeight);
  }
 }
};
ASPx.AdjustHeight = function(element) {
 ASPx.ClearHeight(element);
 var parentElement = element.parentNode;
 var height = parentElement.getBoundingClientRect().height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(parentElement);
 adjustHeightCore(element, height);
};
function adjustHeightCore(element, height) {
 var height = height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element);
 if(height < 0) height = 0;
 element.style.height = height + "px";
}
ASPx.ClearHeight = function(element) {
 element.style.height = "";
};
ASPx.ShrinkWrappedTextInContainer = function(container) {
 if(!container) return;
 for(var i = 0; i < container.childNodes.length; i++){
  var child = container.childNodes[i];
  if(child.style && ASPx.IsTextWrapped(child)) {
   Attr.ChangeStyleAttribute(child, "width", "1px");
   child.shrinkedTextContainer = true;
  }
 }
};
ASPx.AdjustWrappedTextInContainer = function(container) {
 if(!container) return;
 var textContainer, leftWidth = 0, rightWidth = 0;
 for(var i = 0; i < container.childNodes.length; i++){
  var child = container.childNodes[i];
  if(child.tagName === "BR")
   return;
  if(!child.tagName)
   continue;
  if(child.tagName !== "IMG"){
   textContainer = child;
   if(ASPx.IsTextWrapped(textContainer)){
    if(!textContainer.shrinkedTextContainer)
     textContainer.style.width = "";
    textContainer.style.marginRight = "";
   }
  }
  else {
   if(ASPx.GetElementOffsetWidth(child)=== 0)
    Evt.AttachEventToElement(child, "load", function(evt) { ASPx.AdjustWrappedTextInContainer(container); });
   else {
    var width = ASPx.GetElementOffsetWidth(child) + ASPx.GetLeftRightMargins(child);
    if(textContainer)
     rightWidth += width;
    else
     leftWidth += width;
   }
  }
 }
 if(textContainer && ASPx.IsTextWrapped(textContainer)) {
  var containerWidth = ASPx.GetElementOffsetWidth(container) - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(container);
  if(textContainer.shrinkedTextContainer) {
   Attr.RestoreStyleAttribute(textContainer, "width");
   Attr.ChangeStyleAttribute(container, "width", containerWidth + "px");
  }
  if(ASPx.GetElementOffsetWidth(textContainer) + leftWidth + rightWidth >= containerWidth) {
    if(rightWidth > 0 && !textContainer.shrinkedTextContainer)
    textContainer.style.width = (containerWidth - rightWidth) + "px";
   else if(leftWidth > 0){
    if(ASPx.IsElementRightToLeft(container))
     textContainer.style.marginLeft = leftWidth + "px";
    else
     textContainer.style.marginRight = leftWidth + "px";
   }
  }
 }
};
ASPx.IsTextWrapped = function(element) {
 return element && ASPx.GetCurrentStyle(element).whiteSpace !== "nowrap";
};
ASPx.IsValidPosition = function(pos){
 return pos != ASPx.InvalidPosition && pos != -ASPx.InvalidPosition;
};
ASPx.getSpriteMainElement = function(element) {
 var cssClassMarker = "dx-acc";
 if(ASPx.ElementContainsCssClass(element, cssClassMarker))
  return element;
 if(element.parentNode && ASPx.ElementContainsCssClass(element.parentNode, cssClassMarker))
  return element.parentNode;
 return element;
};
ASPx.GetAbsoluteX = function(curEl){
 return ASPx.GetAbsolutePositionX(curEl);
};
ASPx.GetAbsoluteY = function(curEl){
 return ASPx.GetAbsolutePositionY(curEl);
};
ASPx.SetAbsoluteX = function(element, x){
 element.style.left = ASPx.PrepareClientPosForElement(x, element, true) + "px";
};
ASPx.SetAbsoluteY = function(element, y){
 element.style.top = ASPx.PrepareClientPosForElement(y, element, false) + "px";
};
ASPx.GetAbsolutePositionX = function(element){
 if(Browser.Firefox && Browser.Version >= 3)
  return getAbsolutePositionX_FF3(element);
 else if(Browser.Opera)
  return getAbsolutePositionX_Opera(element);
 else if(Browser.NetscapeFamily && (!Browser.Firefox || Browser.Version < 3))
  return getAbsolutePositionX_NS(element);
 else if(Browser.WebKitFamily || Browser.Edge)
  return getAbsolutePositionX_FF3(element);
 else
  return getAbsolutePositionX_Other(element);
};
function getAbsolutePositionX_Opera(curEl){
 var isFirstCycle = true;
 var pos = getAbsoluteScrollOffset_OperaFF(curEl, true);
 while(curEl != null) {
  pos += curEl.offsetLeft;
  if(!isFirstCycle)
   pos -= curEl.scrollLeft;
  curEl = curEl.offsetParent;
  isFirstCycle = false;
 }
 pos += document.body.scrollLeft;
 return pos;
}
function getAbsolutePositionX_FF3(element){
 if(element == null) return 0;
 var x = element.getBoundingClientRect().left + ASPx.GetDocumentScrollLeft();
 return x;
}
function getAbsolutePositionX_NS(curEl){
 var pos = getAbsoluteScrollOffset_OperaFF(curEl, true);
 var isFirstCycle = true;
 while(curEl != null) {
  pos += curEl.offsetLeft;
  if(!isFirstCycle && curEl.offsetParent != null)
   pos -= curEl.scrollLeft;
  if(!isFirstCycle && Browser.Firefox){
   var style = ASPx.GetCurrentStyle(curEl);
   if(curEl.tagName == "DIV" && style.overflow != "visible")
    pos += ASPx.PxToInt(style.borderLeftWidth);
  }
  isFirstCycle = false;
  curEl = curEl.offsetParent;
 }
 return pos;
}
function getAbsolutePositionX_Other(curEl){
 var pos = 0;
 var isFirstCycle = true;
 while(curEl != null) {
  pos += curEl.offsetLeft;
  if(!isFirstCycle && curEl.offsetParent != null)
   pos -= curEl.scrollLeft;
  isFirstCycle = false;
  curEl = curEl.offsetParent;
 }
 return pos;
}
ASPx.GetAbsolutePositionY = function(element){
 if(Browser.Firefox && Browser.Version >= 3)
  return getAbsolutePositionY_FF3(element);
 else if(Browser.Opera)
  return getAbsolutePositionY_Opera(element);
 else if(Browser.NetscapeFamily && (!Browser.Firefox || Browser.Version < 3))
  return getAbsolutePositionY_NS(element);
 else if(Browser.WebKitFamily || Browser.Edge)
  return getAbsolutePositionY_FF3(element);
 else
  return getAbsolutePositionY_Other(element);
};
function getAbsolutePositionY_Opera(curEl){
 var isFirstCycle = true;
 if(curEl && curEl.tagName == "TR" && curEl.cells.length > 0)
  curEl = curEl.cells[0];
 var pos = getAbsoluteScrollOffset_OperaFF(curEl, false);
 while(curEl != null) {
  pos += curEl.offsetTop;
  if(!isFirstCycle)
   pos -= curEl.scrollTop;
  curEl = curEl.offsetParent;
  isFirstCycle = false;
 }
 pos += document.body.scrollTop;
 return pos;
}
function getAbsolutePositionY_FF3(element){
 if(element == null) return 0;
 var y = element.getBoundingClientRect().top + ASPx.GetDocumentScrollTop();
 return y;
}
function getAbsolutePositionY_NS(curEl){
 var pos = getAbsoluteScrollOffset_OperaFF(curEl, false);
 var isFirstCycle = true;
 while(curEl != null) {
  pos += curEl.offsetTop;
  if(!isFirstCycle && curEl.offsetParent != null)
   pos -= curEl.scrollTop;
  if(!isFirstCycle && Browser.Firefox){
   var style = ASPx.GetCurrentStyle(curEl);
   if(curEl.tagName == "DIV" && style.overflow != "visible")
    pos += ASPx.PxToInt(style.borderTopWidth);
  }
  isFirstCycle = false;
  curEl = curEl.offsetParent;
 }
 return pos;
}
function getAbsoluteScrollOffset_OperaFF(curEl, isX) {
 var pos = 0;   
 var isFirstCycle = true;
 while(curEl != null) {
  if(curEl.tagName == "BODY")
   break;
  var style = ASPx.GetCurrentStyle(curEl);
  if(style.position == "absolute")
   break;
  if(!isFirstCycle && curEl.tagName == "DIV" && (style.position == "" || style.position == "static"))
   pos -= isX ? curEl.scrollLeft : curEl.scrollTop;
  curEl = curEl.parentNode;
  isFirstCycle = false;
 }
 return pos; 
}
function getAbsolutePositionY_Other(curEl){
 var pos = 0;
 var isFirstCycle = true;
 while(curEl != null) {
  pos += curEl.offsetTop;
  if(!isFirstCycle && curEl.offsetParent != null)
   pos -= curEl.scrollTop;
  isFirstCycle = false;
  curEl = curEl.offsetParent;
 }
 return pos;
}
function createElementMock(element) {
 var div = document.createElement('DIV');
 div.style.top = "0px";
 div.style.left = "0px";
 div.visibility = "hidden";
 div.style.position = ASPx.GetCurrentStyle(element).position;
 return div;
}
ASPx.PrepareClientPosElementForOtherParent = function(pos, element, otherParent, isX) {
 if(element.parentNode == otherParent)
  return ASPx.PrepareClientPosForElement(pos, element, isX);
 var elementMock = createElementMock(element);
 otherParent.appendChild(elementMock); 
 var preparedPos = ASPx.PrepareClientPosForElement(pos, elementMock, isX);
 otherParent.removeChild(elementMock);
 return preparedPos;
};
ASPx.PrepareClientPosForElement = function(pos, element, isX) {
 pos -= ASPx.GetPositionElementOffset(element, isX);
 return pos;
};
function getExperimentalPositionOffset(element, isX) {
 var div = createElementMock(element);
 if(div.style.position == "static")
  div.style.position = "absolute";
 element.parentNode.appendChild(div); 
 var realPos = isX ? ASPx.GetAbsoluteX(div) : ASPx.GetAbsoluteY(div);
 element.parentNode.removeChild(div);
 return realPos;
}
ASPx.GetPositionElementOffset = function(element, isX) {
 return getExperimentalPositionOffset(element, isX);
};
ASPx.GetSizeOfText = function(text, textCss) {
 var testContainer = document.createElement("tester");
 var defaultLineHeight = ASPx.Browser.Firefox ? "1" : "";
 testContainer.style.fontSize = textCss.fontSize;
 testContainer.style.fontFamily = textCss.fontFamily;
 testContainer.style.fontWeight = textCss.fontWeight;
 testContainer.style.letterSpacing = textCss.letterSpacing;
 testContainer.style.lineHeight = textCss.lineHeight || defaultLineHeight;
 testContainer.style.position = "absolute";
 testContainer.style.top = ASPx.InvalidPosition + "px";
 testContainer.style.left = ASPx.InvalidPosition + "px";
 testContainer.style.width = "auto";
 testContainer.style.whiteSpace = "nowrap";
 testContainer.appendChild(document.createTextNode(text));
 var testElement = document.body.appendChild(testContainer);
 var size = {
  "width": testElement.offsetWidth,
  "height": testElement.offsetHeight
 };
 document.body.removeChild(testElement);
 return size;
};
ASPx.PointToPixel = function(points, addPx) {  
 var result = 0;
 try {
  var indexOfPt = points.toLowerCase().indexOf("pt");
  if(indexOfPt > -1)
   result = parseInt(points.substr(0, indexOfPt)) * 96 / 72;
  else
   result = parseInt(points) * 96 / 72;
  if(addPx)
   result = result + "px";
 } catch(e) {}
 return result;
};
ASPx.PixelToPoint = function(pixels, addPt) { 
 var result = 0;
 try {
  var indexOfPx = pixels.toLowerCase().indexOf("px");
  if(indexOfPx > -1)
   result = parseInt(pixels.substr(0, indexOfPx)) * 72 / 96;
  else
   result = parseInt(pixels) * 72 / 96;
  if(addPt)
   result = result + "pt";
 } catch(e) {}
 return result;         
};
ASPx.PxToInt = function(px) {
 return pxToNumber(px, parseInt);
};
ASPx.PxToFloat = function(px) {
 return pxToNumber(px, parseFloat);
};
function pxToNumber(px, parseFunction) {
 var result = 0;
 if(px != null && px != "") {
  try {
   var indexOfPx = px.indexOf("px");
   if(indexOfPx > -1)
    result = parseFunction(px.substr(0, indexOfPx));
  } catch(e) { }
 }
 return result;
}
ASPx.PercentageToFloat = function(perc) {
 var result = 0;
 if(perc != null && perc != "") {
  try {
   var indexOfPerc = perc.indexOf("%");
   if(indexOfPerc > -1)
    result = parseFloat(perc.substr(0, indexOfPerc)) / 100;
  } catch(e) { }
 }
 return result;
};
ASPx.CreateGuid = function() {
 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 
   var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;
  return v.toString(16);
 });
};
ASPx.GetLeftRightBordersAndPaddingsSummaryValue = function(element, currentStyle) {
 return ASPx.GetLeftRightPaddings(element, currentStyle) + ASPx.GetHorizontalBordersWidth(element, currentStyle);
};
ASPx.GetTopBottomBordersAndPaddingsSummaryValue = function(element, currentStyle) {
 return ASPx.GetTopBottomPaddings(element, currentStyle) + ASPx.GetVerticalBordersWidth(element, currentStyle);
};
ASPx.GetVerticalBordersWidth = function(element, style) {
 if(!ASPx.IsExists(style))
  style = ASPx.GetCurrentStyle(element);
 var res = 0;
 if(style.borderTopStyle != "none")
  res += ASPx.PxToFloat(style.borderTopWidth);
 if(style.borderBottomStyle != "none")
  res += ASPx.PxToFloat(style.borderBottomWidth);
 return res;
};
ASPx.GetHorizontalBordersWidth = function(element, style) {
 if(!ASPx.IsExists(style))
  style = ASPx.GetCurrentStyle(element);
 var res = 0;
 if(style.borderLeftStyle != "none")
  res += ASPx.PxToFloat(style.borderLeftWidth);
 if(style.borderRightStyle != "none")
  res += ASPx.PxToFloat(style.borderRightWidth);
 return res;
};
ASPx.GetTopBottomPaddings = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.paddingTop) + ASPx.PxToInt(currentStyle.paddingBottom);
};
ASPx.GetTopPaddings = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.paddingTop);
};
ASPx.GetBottomPaddings = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.paddingBottom);
};
ASPx.GetLeftRightPaddings = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.paddingLeft) + ASPx.PxToInt(currentStyle.paddingRight);
};
ASPx.GetTopBottomMargins = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.marginTop) + ASPx.PxToInt(currentStyle.marginBottom);
};
ASPx.GetLeftRightMargins = function(element, style) {
 var currentStyle = style ? style : ASPx.GetCurrentStyle(element);
 return ASPx.PxToInt(currentStyle.marginLeft) + ASPx.PxToInt(currentStyle.marginRight);
};
ASPx.GetClearClientWidth = function(element) {
 return ASPx.GetElementOffsetWidth(element)- ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element);
};
ASPx.GetClearClientHeight = function(element) {
 return ASPx.GetElementOffsetHeight(element) - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element);
};
ASPx.SetOffsetWidth = function(element, widthValue, currentStyle) {
 if(!ASPx.IsExists(currentStyle))
  currentStyle = ASPx.GetCurrentStyle(element);
 var value = widthValue - ASPx.PxToInt(currentStyle.marginLeft) - ASPx.PxToInt(currentStyle.marginRight);
  value -= ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element, currentStyle);
 if(value > -1)
  element.style.width = value + "px";
};
ASPx.SetOffsetHeight = function(element, heightValue, currentStyle) {
 if(!ASPx.IsExists(currentStyle))
  currentStyle = ASPx.GetCurrentStyle(element);
 var value = heightValue - ASPx.PxToInt(currentStyle.marginTop) - ASPx.PxToInt(currentStyle.marginBottom);
  value -= ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element, currentStyle);
 if(value > -1)
  element.style.height = value + "px";
};
ASPx.FindOffsetParent = function(element) {
 var currentElement = element.parentNode;
 while(ASPx.IsExistsElement(currentElement) && currentElement.tagName != "BODY") {
  if(ASPx.GetElementOffsetWidth(currentElement) > 0 && ASPx.GetElementOffsetHeight(currentElement) > 0)
   return currentElement;
  currentElement = currentElement.parentNode;
 }
 return document.body;
};
ASPx.GetDocumentScrollTop = function(){
 if(Browser.WebKitFamily || Browser.Edge) {
  if(Browser.MacOSMobilePlatform) 
   return window.pageYOffset;
  if(Browser.WebKitFamily)
   return document.documentElement.scrollTop || document.body.scrollTop;
  return document.body.scrollTop;
 }
 else
  return document.documentElement.scrollTop;
};
ASPx.SetDocumentScrollTop = function(scrollTop) {
 if(!Browser.MacOSMobilePlatform && (Browser.Safari || (Browser.Chrome && Browser.Version < 60) || (Browser.Opera && Browser.MajorVersion >= 15) || Browser.Edge))  
  document.body.scrollTop = scrollTop;
 else
  document.documentElement.scrollTop = scrollTop;
};
ASPx.GetDocumentScrollLeft = function(){
 if(Browser.Edge)
  return document.body ? document.body.scrollLeft : document.documentElement.scrollLeft;
 if(Browser.WebKitFamily)
  return document.documentElement.scrollLeft || document.body.scrollLeft;
 return document.documentElement.scrollLeft;
};
ASPx.SetDocumentScrollLeft = function (scrollLeft) {
 if(!Browser.MacOSMobilePlatform && (Browser.Safari || (Browser.Chrome && Browser.Version < 60) || (Browser.Opera && Browser.MajorVersion >= 15) || Browser.Edge))  
  document.body.scrollLeft = scrollLeft;
 else
  document.documentElement.scrollLeft = scrollLeft;
};
ASPx.GetDocumentClientWidth = function(){
 if(document.documentElement.clientWidth == 0)
  return document.body.clientWidth;
 else
  return document.documentElement.clientWidth;
};
ASPx.GetDocumentClientHeight = function() {
 if(Browser.Firefox && window.innerHeight - document.documentElement.clientHeight > ASPx.GetVerticalScrollBarWidth()) {
  return window.innerHeight;
 } else if(Browser.Opera && Browser.Version < 9.6 || document.documentElement.clientHeight == 0) {
   return document.body.clientHeight;
 }
 return document.documentElement.clientHeight;
};
ASPx.GetDocumentWidth = function(){
 var bodyWidth = document.body.offsetWidth;
 var docWidth = document.documentElement.offsetWidth;
 var bodyScrollWidth = document.body.scrollWidth;
 var docScrollWidth = document.documentElement.scrollWidth;
 return getMaxDimensionOf(bodyWidth, docWidth, bodyScrollWidth, docScrollWidth);
};
ASPx.GetDocumentHeight = function(){
 var bodyHeight = document.body.offsetHeight;
 var docHeight = document.documentElement.offsetHeight;
 var bodyScrollHeight = document.body.scrollHeight;
 var docScrollHeight = document.documentElement.scrollHeight;
 var maxHeight = getMaxDimensionOf(bodyHeight, docHeight, bodyScrollHeight, docScrollHeight);
 if(Browser.Opera && Browser.Version >= 9.6){
  if(Browser.Version < 10)
   maxHeight = getMaxDimensionOf(bodyHeight, docHeight, bodyScrollHeight);
  var visibleHeightOfDocument = document.documentElement.clientHeight;
  if(maxHeight > visibleHeightOfDocument)
   maxHeight = getMaxDimensionOf(window.outerHeight, maxHeight);
  else
   maxHeight = document.documentElement.clientHeight;
  return maxHeight;
 }
 return maxHeight;
};
ASPx.GetDocumentMaxClientWidth = function(){
 var bodyWidth = document.body.offsetWidth;
 var docWidth = document.documentElement.offsetWidth;
 var docClientWidth = document.documentElement.clientWidth;
 return getMaxDimensionOf(bodyWidth, docWidth, docClientWidth);
};
ASPx.GetDocumentMaxClientHeight = function(){
 var bodyHeight = document.body.offsetHeight;
 var docHeight = document.documentElement.offsetHeight;
 var docClientHeight = document.documentElement.clientHeight;
 return getMaxDimensionOf(bodyHeight, docHeight, docClientHeight);
};
ASPx.verticalScrollIsNotHidden = null;
ASPx.horizontalScrollIsNotHidden = null;
ASPx.GetVerticalScrollIsNotHidden = function() {
 if(!ASPx.IsExists(ASPx.verticalScrollIsNotHidden))
  ASPx.verticalScrollIsNotHidden = ASPx.GetCurrentStyle(document.body).overflowY !== "hidden"
   && ASPx.GetCurrentStyle(document.documentElement).overflowY !== "hidden";
 return ASPx.verticalScrollIsNotHidden;
};
ASPx.GetHorizontalScrollIsNotHidden = function() {
 if(!ASPx.IsExists(ASPx.horizontalScrollIsNotHidden))
  ASPx.horizontalScrollIsNotHidden = ASPx.GetCurrentStyle(document.body).overflowX !== "hidden"
   && ASPx.GetCurrentStyle(document.documentElement).overflowX !== "hidden";
 return ASPx.horizontalScrollIsNotHidden;
};
ASPx.GetCurrentDocumentWidth = function() {
 var result = ASPx.GetDocumentClientWidth();
 if(!ASPx.Browser.Safari && ASPx.GetVerticalScrollIsNotHidden() && ASPx.GetDocumentHeight() > ASPx.GetDocumentClientHeight())
  result += ASPx.GetVerticalScrollBarWidth();
 return result;
};
ASPx.GetCurrentDocumentHeight = function() {
 var result = ASPx.GetDocumentClientHeight();
 if(!ASPx.Browser.Safari && ASPx.GetHorizontalScrollIsNotHidden() && ASPx.GetDocumentWidth() > ASPx.GetDocumentClientWidth())
  result += ASPx.GetVerticalScrollBarWidth();
 return result;
};
function getMaxDimensionOf(){
 var max = ASPx.InvalidDimension;
 for(var i = 0; i < arguments.length; i++){
  if(max < arguments[i])
   max = arguments[i];
 }
 return max;
}
ASPx.GetClientLeft = function(element) {
 return ASPx.IsExists(element.clientLeft) ? element.clientLeft : (ASPx.GetElementOffsetWidth(element)- element.clientWidth) / 2;
};
ASPx.GetClientTop = function(element) {
 return ASPx.IsExists(element.clientTop) ? element.clientTop : (ASPx.GetElementOffsetHeight(element) - element.clientHeight) / 2;
};
var requestAnimationFrameFunc = window.requestAnimationFrame || function(callback) { callback(); };
var cancelAnimationFrameFunc = window.cancelAnimationFrame || function(id) { };
ASPx.CancelAnimationFrame = function(id) { cancelAnimationFrameFunc(id); };
ASPx.RequestAnimationFrame = function (callback) { return requestAnimationFrameFunc(callback); };
ASPx.SetStyles = function(element, styles, makeImportant) {
 if(ASPx.IsExists(styles.cssText))
  element.style.cssText = styles.cssText;
 if(ASPx.IsExists(styles.className)) {
  ASPx.SetClassName(element, styles.className);
 }
 for(var property in styles) {
  if(!styles.hasOwnProperty(property))
   continue;
  var value = styles[property];
  switch (property) {
   case "cssText":
   case "className":
    break;
   case "float":
    ASPx.SetElementFloat(element, value);
    break;
   case "opacity":
    ASPx.SetElementOpacity(element, value);
    break;
   case "zIndex":
    ASPx.SetStylesCore(element, property, value, makeImportant);
    break;
   default:
    ASPx.SetStylesCore(element, property, value + (typeof (value) == "number" ? "px" : ""), makeImportant);
  }
 }
};
ASPx.SetStylesCore = function(element, property, value, makeImportant) {
 if(makeImportant) {
  var index = property.search("[A-Z]");
  if(index != -1)
   property = property.replace(property.charAt(index), "-" + property.charAt(index).toLowerCase());
  if(element.style.setProperty)
   element.style.setProperty(property, value, "important");
  else 
   element.style.cssText += ";" + property + ":" + value + "!important";
 }
 else
  element.style[property] = value;
};
ASPx.RemoveBordersAndShadows = function(el) {
 if(!el || !el.style)
  return;
 el.style.borderWidth = 0;
 if(ASPx.IsExists(el.style.boxShadow))
  el.style.boxShadow = "none";
 else if(ASPx.IsExists(el.style.MozBoxShadow))
  el.style.MozBoxShadow = "none";
 else if(ASPx.IsExists(el.style.webkitBoxShadow))
  el.style.webkitBoxShadow = "none";
};
ASPx.GetCellSpacing = function(element) {
 var val = parseInt(element.cellSpacing);
 if(!isNaN(val)) return val;
 val = parseInt(ASPx.GetCurrentStyle(element).borderSpacing);
 if(!isNaN(val)) return val;
 return 0;
};
ASPx.GetInnerScrollPositions = function(element) {
 var scrolls = [];
 getInnerScrollPositionsCore(element, scrolls);
 return scrolls;
};
function getInnerScrollPositionsCore(element, scrolls) {
 for(var child = element.firstChild; child; child = child.nextSibling) {
  var scrollTop = child.scrollTop,
   scrollLeft = child.scrollLeft;
  if(scrollTop > 0 || scrollLeft > 0)
   scrolls.push([child, scrollTop, scrollLeft]);
  getInnerScrollPositionsCore(child, scrolls);
 }
}
ASPx.RestoreInnerScrollPositions = function(scrolls) {
 for(var i = 0, scrollArr; scrollArr = scrolls[i]; i++) {
  if(scrollArr[1] > 0)
   scrollArr[0].scrollTop = scrollArr[1];
  if(scrollArr[2] > 0)
   scrollArr[0].scrollLeft = scrollArr[2];
 }
};
ASPx.GetOuterScrollPosition = function(element) {
 while(element && element.tagName !== "BODY") {
  var scrollTop = element.scrollTop,
   scrollLeft = element.scrollLeft;
  if(scrollTop > 0 || scrollLeft > 0) {
   return {
    scrollTop: scrollTop,
    scrollLeft: scrollLeft,
    element: element
   };
  }
  element = element.parentNode;
 }
 return {
  scrollTop: ASPx.GetDocumentScrollTop(),
  scrollLeft: ASPx.GetDocumentScrollLeft()
 };
};
ASPx.RestoreOuterScrollPosition = function(scrollInfo) {
 if(scrollInfo.element) {
  if(scrollInfo.scrollTop > 0)
   scrollInfo.element.scrollTop = scrollInfo.scrollTop;
  if(scrollInfo.scrollLeft > 0)
   scrollInfo.element.scrollLeft = scrollInfo.scrollLeft;
 }
 else {
  if(scrollInfo.scrollTop > 0)
   ASPx.SetDocumentScrollTop(scrollInfo.scrollTop);
  if(scrollInfo.scrollLeft > 0)
   ASPx.SetDocumentScrollLeft(scrollInfo.scrollLeft);
 }
};
ASPx.ChangeElementContainer = function(element, container, savePreviousContainer) {
 if(element.parentNode != container) {
  var parentNode = element.parentNode;
  parentNode.removeChild(element);
  container.appendChild(element);
  if(savePreviousContainer)
   element.previousContainer = parentNode;
 }
};
ASPx.RestoreElementContainer = function(element) {
 if(element.previousContainer) {
  ASPx.ChangeElementContainer(element, element.previousContainer, false);
  element.previousContainer = null;
 }
};
ASPx.MoveChildrenToElement = function(sourceElement, destinationElement){
 while(sourceElement.childNodes.length > 0)
  destinationElement.appendChild(sourceElement.childNodes[0]);
};
ASPx.GetScriptCode = function(script) {
 var useFirstChildElement = Browser.Chrome && Browser.Version < 11 || Browser.Safari && Browser.Version < 5; 
 var text = useFirstChildElement ? script.firstChild.data : script.text;
 var comment = "<!--";
 var pos = text.indexOf(comment);
 if(pos > -1)
  text = text.substr(pos + comment.length);
 return text;
};
ASPx.AppendScript = function(script) {
 var parent = document.getElementsByTagName("head")[0];
 if(!parent)
  parent = document.body;
 if(parent)
  parent.appendChild(script);
};
function getFrame(frames, name) {
 if(frames[name])
  return frames[name];
 for(var i = 0; i < frames.length; i++) {
  try {
   var frame = frames[i];
   if(frame.name == name) 
    return frame; 
   frame = getFrame(frame.frames, name);
   if(frame != null)   
    return frame; 
  } catch(e) {
  } 
 }
 return null;
}
ASPx.IsValidElement = function(element) {
 if(!element) 
  return false;
 if(!(Browser.Firefox && Browser.Version < 4)) {
  if(element.ownerDocument && element.ownerDocument.body && element.ownerDocument.body.compareDocumentPosition)
   return element.ownerDocument.body.compareDocumentPosition(element) % 2 === 0;
 }
 if(!Browser.Opera && element.offsetParent && element.parentNode.tagName)
  return true;
 while(element != null){
  if(element.tagName == "BODY")
   return true;
  element = element.parentNode;
 }
 return false;
};
ASPx.IsValidElements = function(elements) {
 if(!elements)
  return false; 
 for(var i = 0; i < elements.length; i++) {
  if(elements[i] && !ASPx.IsValidElement(elements[i]))
   return false;
 }
 return true;
};
ASPx.IsExistsElement = function(element) {
 return element && ASPx.IsValidElement(element);
};
ASPx.CreateHtmlElementFromString = function(str) {
 var dummy = ASPx.CreateHtmlElement();
 setInnerHtmlInternal(dummy, str);
 return dummy.firstChild;
};
ASPx.CreateHtmlElement = function(tagName, styles) {
 var element = document.createElement(tagName || "DIV");
 if(styles)
  ASPx.SetStyles(element, styles);
 return element;
};
ASPx.RestoreElementOriginalWidth = function(element) {
 if(!ASPx.IsExistsElement(element)) 
  return;
 element.style.width = element.dxOrigWidth = ASPx.GetElementOriginalWidth(element);
};
ASPx.GetElementOriginalWidth = function(element) {
 if(!ASPx.IsExistsElement(element)) 
  return null;
 var width;
 if(!ASPx.IsExists(element.dxOrigWidth)) {
  width = String(element.style.width).length > 0
   ? element.style.width
   : ASPx.GetElementOffsetWidth(element) + "px";
 } else {
  width = element.dxOrigWidth;
 }
 return width;
};
ASPx.DropElementOriginalWidth = function(element) {
 if(ASPx.IsExists(element.dxOrigWidth))
  element.dxOrigWidth = null;
};
ASPx.GetObjectKeys = function(obj) {
 if(!obj) return [ ];
 if(Object.keys)
  return Object.keys(obj);
 var keys = [ ];
 for(var key in obj) {
  if(obj.hasOwnProperty(key))
   keys.push(key);
 }
 return keys;
};
ASPx.ShowErrorAlert = function(message) {
 message = ASPx.Str.DecodeHtmlViaTextArea(message);
 if(ASPx.IsExists(message) && message !== "")
  alert(message);
};
ASPx.ShowKBErrorMessage = function(text, kbid) {
 ASPx.ShowErrorMessage(text + "https://www.devexpress.com/kbid=" + kbid + ".");
};
ASPx.ShowErrorMessage = function(errorMessage) {
 var console = window.console;
 if(!console || !ASPx.IsFunction(console.error))
  return;
 console.error(errorMessage);
};
ASPx.IsInteractiveControl = function(element, extremeParent) { 
 return Data.ArrayIndexOf(["A", "INPUT", "SELECT", "OPTION", "TEXTAREA", "BUTTON", "IFRAME"], element.tagName) > -1;
};
ASPx.IsUrlContainsClientScript = function(url) {
 return url.toLowerCase().indexOf("javascript:") !== -1;
};
ASPx.GetMSAjaxRequestManager = function() {
 if(window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager && Sys.WebForms.PageRequestManager.getInstance)
  return Sys.WebForms.PageRequestManager.getInstance();
 return null;
};
Function.prototype.aspxBind = function(scope) {
 var func = this;
 return function() {
  return func.apply(scope, arguments);
 };
};
var FilteringUtils = { };
FilteringUtils.EventKeyCodeChangesTheInput = function(evt) {
 if(ASPx.IsPasteShortcut(evt))
  return true;
 else if(evt.ctrlKey && !evt.altKey)
  return false;
 if(ASPx.Browser.AndroidMobilePlatform || ASPx.Browser.MacOSMobilePlatform) return true; 
 var keyCode = ASPx.Evt.GetKeyCode(evt);
 var isSystemKey = ASPx.Key.Windows <= keyCode && keyCode <= ASPx.Key.ContextMenu;
 var isFKey = ASPx.Key.F1 <= keyCode && keyCode <= 127; 
 return ASPx.Key.Delete <= keyCode && !isSystemKey && !isFKey || keyCode == ASPx.Key.Backspace || keyCode == ASPx.Key.Space;
};
FilteringUtils.FormatCallbackArg = function(prefix, arg) {
 return (ASPx.IsExists(arg) ? prefix + "|" + arg.length + ';' + arg + ';' : "");
};
ASPx.FilteringUtils = FilteringUtils;
var FormatStringHelper = { };
FormatStringHelper.PlaceHolderTemplateStruct = function(startIndex, length, index, placeHolderString){
 this.startIndex = startIndex;
 this.realStartIndex = 0;
 this.length = length;
 this.realLength = 0;
 this.index = index;
 this.placeHolderString = placeHolderString;
};
FormatStringHelper.GetPlaceHolderTemplates = function(formatString){
 formatString = this.CollapseDoubleBrackets(formatString);
 var templates = this.CreatePlaceHolderTemplates(formatString);
 return templates;
};
FormatStringHelper.CreatePlaceHolderTemplates = function(formatString){
 var templates = [];
 var templateStrings = formatString.match(/{[^}]+}/g);
 if(templateStrings != null){
  var pos = 0;
  for(var i = 0; i < templateStrings.length; i++){
   var tempString = templateStrings[i];
   var startIndex = formatString.indexOf(tempString, pos);
   var length = tempString.length;
   var indexString = tempString.slice(1).match(/^[0-9]+/);
   var index = parseInt(indexString);
   templates.push(new this.PlaceHolderTemplateStruct(startIndex, length, index, tempString));
   pos = startIndex + length;
  }
 }
 return templates;
};
FormatStringHelper.CollapseDoubleBrackets = function(formatString){
 formatString = this.CollapseOpenDoubleBrackets(formatString);
 formatString = this.CollapseCloseDoubleBrackets(formatString);
 return formatString;
};
FormatStringHelper.CollapseOpenDoubleBrackets = function(formatString){
 return formatString.replace(/{{/g, "_");
};
FormatStringHelper.CollapseCloseDoubleBrackets = function(formatString){
 while(true){
  var index = formatString.lastIndexOf("}}");
  if(index == -1) 
   break;
  else
   formatString = formatString.substr(0, index) + "_" + formatString.substr(index + 2);
 }
 return formatString;
};
ASPx.FormatStringHelper = FormatStringHelper;
var StartWithFilteringUtils = { };
StartWithFilteringUtils.HighlightSuggestedText = function(input, suggestedText, control, onChangeInput){
 if(this.NeedToLockAndoidKeyEvents(control))
  control.LockAndroidKeyEvents();
 var selInfo = ASPx.Selection.GetInfo(input);
 var currentTextLenght = ASPx.Str.GetCoincideCharCount(suggestedText, input.value, 
  function(text, filter) { 
   return text.indexOf(filter) == 0;
  });
 var suggestedTextLenght = suggestedText.length;
 var isSelected = selInfo.startPos == 0 && selInfo.endPos == currentTextLenght && 
  selInfo.endPos == suggestedTextLenght && input.value == suggestedText;
 if(!isSelected) { 
  input.value = suggestedText;
  if(onChangeInput)
   onChangeInput();
  if(this.NeedToLockAndoidKeyEvents(control)) {
   window.setTimeout(function() {
    this.SelectText(input, currentTextLenght, suggestedTextLenght);
    control.UnlockAndroidKeyEvents();
   }.aspxBind(this), control.adroidSamsungBugTimeout);
  } else
   this.SelectText(input, currentTextLenght, suggestedTextLenght);
 }
};
StartWithFilteringUtils.SelectText = function(input, startPos, stopPos) {
 if(startPos < stopPos)
  ASPx.Selection.Set(input, startPos, stopPos);
};
StartWithFilteringUtils.RollbackOneSuggestedChar = function(input){
 var currentText = input.value;
 var cutText = currentText.slice(0, -1);
 if(cutText != currentText)
  input.value = cutText;
};
StartWithFilteringUtils.NeedToLockAndoidKeyEvents = function(control) {
 return ASPx.Browser.AndroidMobilePlatform && control && control.LockAndroidKeyEvents;
};
ASPx.StartWithFilteringUtils = StartWithFilteringUtils;
var ContainsFilteringUtils = { };
ContainsFilteringUtils.ColumnSelectionStruct = function(index, startIndex, length){
 this.index = index;
 this.length = length;
 this.startIndex = startIndex;
};
ContainsFilteringUtils.IsFilterCrossPlaseHolder = function(filterStartIndex, filterEndIndex, template) {
 var left = Math.max(filterStartIndex, template.realStartIndex);
 var right = Math.min(filterEndIndex,  template.realStartIndex + template.realLength);
 return left < right;
};
ContainsFilteringUtils.GetColumnSelectionsForItem = function(itemValues, formatString, filterString) {
 if(formatString == "") 
  return this.GetSelectionForSingleColumnItem(itemValues, filterString); 
 var result = [];
 var formatedString = ASPx.Formatter.Format(formatString, itemValues);
 var filterStartIndex = ASPx.Str.PrepareStringForFilter(formatedString).indexOf(ASPx.Str.PrepareStringForFilter(filterString));
 if(filterStartIndex == -1) return result;
 var filterEndIndex = filterStartIndex + filterString.length;
 var templates = FormatStringHelper.GetPlaceHolderTemplates(formatString);
 this.SupplyTemplatesWithRealValues(itemValues, templates);
 for(var i = 0; i < templates.length ; i++) {
  if(this.IsFilterCrossPlaseHolder(filterStartIndex, filterEndIndex, templates[i])) 
   result.push(this.GetColumnSelectionsForItemValue(templates[i], filterStartIndex, filterEndIndex));
 }
 return result;
};
ContainsFilteringUtils.GetColumnSelectionsForItemValue = function(template, filterStartIndex, filterEndIndex) {
 var selectedTextStartIndex = filterStartIndex < template.realStartIndex ? 0 :
  filterStartIndex - template.realStartIndex;
 var selectedTextEndIndex = filterEndIndex >  template.realStartIndex + template.realLength ? template.realLength :
  filterEndIndex - template.realStartIndex;
 var selectedTextLength = selectedTextEndIndex - selectedTextStartIndex;
 return new this.ColumnSelectionStruct(template.index, selectedTextStartIndex, selectedTextLength);
};
ContainsFilteringUtils.GetSelectionForSingleColumnItem = function(itemValues, filterString) {
 var selectedTextStartIndex = ASPx.Str.PrepareStringForFilter(itemValues[0]).indexOf(ASPx.Str.PrepareStringForFilter(filterString));
 var selectedTextLength = filterString.length;
 return [new this.ColumnSelectionStruct(0, selectedTextStartIndex, selectedTextLength)];
};
ContainsFilteringUtils.ResetFormatStringIndex = function(formatString, index) {
 if(index != 0)
  return formatString.replace(index.toString(), "0");
 return formatString;
};
ContainsFilteringUtils.SupplyTemplatesWithRealValues = function(itemValues, templates) {
 var shift = 0;
 for(var i = 0; i < templates.length; i++) {
  var formatString = this.ResetFormatStringIndex(templates[i].placeHolderString, templates[i].index);
  var currentItemValue = itemValues[templates[i].index];
  templates[i].realLength = ASPx.Formatter.Format(formatString, currentItemValue).length;
  templates[i].realStartIndex  += templates[i].startIndex + shift; 
  shift += templates[i].realLength - templates[i].placeHolderString.length; 
 }
};
ContainsFilteringUtils.PrepareElementText = function(itemText) {
 return itemText ? itemText.replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
};
ContainsFilteringUtils.UnselectContainsTextInElement = function(element, selection, highlightTagName) {
 var currentText =  ASPx.Attr.GetAttribute (element, "DXText");
 if(ASPx.IsExists(currentText)) {
  currentText = ContainsFilteringUtils.PrepareElementText(currentText);
  ASPx.Security.setInnerHtml(element, currentText === "" ? "&nbsp;" : currentText, ASPx.Security.DataType.Trusted);
 }
};
ContainsFilteringUtils.ReselectContainsTextInElement = function(element, selection, highlightTagName) {
 var currentText = ASPx.GetInnerText(element);
 if(!highlightTagName)
  highlightTagName = "em";
 highlightTagName = highlightTagName.toLowerCase();
 if(currentText.indexOf("</" + highlightTagName + ">") != -1)
  ContainsFilteringUtils.UnselectContainsTextInElement(element, selection, highlightTagName);
 return ContainsFilteringUtils.SelectContainsTextInElement(element, selection, highlightTagName);
};
ContainsFilteringUtils.SelectContainsTextInElement = function(element, selection, highlightTagName) {
 if(selection.startIndex == -1)
  return;
 var currentText =  ASPx.Attr.GetAttribute (element, "DXText");
 if(!ASPx.IsExists(currentText)) ASPx.Attr.SetAttribute (element, "DXText", ASPx.GetInnerText(element));
 if(!highlightTagName)
  highlightTagName = "em";
 highlightTagName = highlightTagName.toLowerCase();
 var oldInnerText = ASPx.GetInnerText(element);
 var newInnerText = ContainsFilteringUtils.PrepareElementText(oldInnerText.substr(0, selection.startIndex)) + "<" + highlightTagName + ">" +
      ContainsFilteringUtils.PrepareElementText(oldInnerText.substr(selection.startIndex, selection.length)) + "</" + highlightTagName + ">" +
      ContainsFilteringUtils.PrepareElementText(oldInnerText.substr(selection.startIndex + selection.length));
 ASPx.Security.setInnerHtml(element, newInnerText, ASPx.Security.DataType.Trusted);
};
ASPx.ContainsFilteringUtils = ContainsFilteringUtils;
ASPx.MakeEqualControlsWidth = function(name1, name2){
 var control1 = ASPx.GetControlCollection().Get(name1);
 var control2 = ASPx.GetControlCollection().Get(name2);
 if(control1 && control2){
  var width = Math.max(control1.GetWidth(), control2.GetWidth());
  control1.SetWidth(width);
  control2.SetWidth(width);
 }
};
ASPx.HighContrastForeColorHighlightColorMap = {
 "#ffff00" : "#008000",
 "#00ff00" : "#0000ff",
 "#ffffff" : "#00838f",
 "#000000" : "#a347ff"
};
var BadgeManagerBase = ASPx.CreateClass(null, {
 createBadge: function(text, iconCssClass) {
  var badge = document.createElement("SPAN");
  ASPx.SetClassName(badge, this.getBadgeClassName());
  if(iconCssClass && iconCssClass.length)
   this.setBadgeIconCssClass(badge, iconCssClass);
  if(text && text.length)
   this.setBadgeText(badge, text);
  return badge;
 },
 findBadge: function(element) {
  if(!element)
   return null;
  return element.querySelector("." + this.getBadgeClassName());
 },
 setBadgeIconCssClass: function(badge, iconCssClass) {
  if(!badge || iconCssClass === undefined)
   return;
  var iconElement = this.getBadgeIconElement(badge);
  if(!iconCssClass) {
   if(iconElement)
    badge.removeChild(iconElement);
  }
  else {
   if(!iconElement) {
    iconElement = document.createElement("SPAN");
    badge.insertBefore(iconElement, badge.childNodes[0]);
   }
   ASPx.SetClassName(iconElement, iconCssClass + " " + this.getBadgeIconDefaultClassName());
  }
 },
 getBadgeIconCssClass: function(element) {
  var badge = this.findBadge(element);
  if(badge) {
   var iconElement = this.getBadgeIconElement(badge);
   var regEx = new RegExp("(?:^|\\s)" + this.getBadgeIconDefaultClassName() + "(?!\\S)");
   return iconElement ? ASPx.Str.Trim(ASPx.GetClassName(iconElement).replace(regEx, "")) : "";
  }
  return "";
 },
 setBadgeText: function(badge, text) {
  if(!badge || text === undefined)
   return;
  var textElement = this.getBadgeTextElement(badge);
  if(!text) {
   if(textElement)
    badge.removeChild(textElement);
  }
  else {
   if(!textElement) {
    textElement = document.createElement("SPAN");
    badge.appendChild(textElement);
   }
   ASPx.Security.setInnerHtml(textElement, text, ASPx.Security.DataType.Trusted);
  }
 },
 getBadgeText: function(element) {
  var badge = this.findBadge(element);
  if(badge) {
   var textElement = this.getBadgeTextElement(badge);
   return textElement ? ASPx.GetInnerText(textElement) : "";
  }
  return "";
 },
 getBadgeClassName: function() {
  return "";
 },
 getBadgeIconDefaultClassName: function() {
  return "";
 },
 getBadgeIconElement: function(badge) {
  return badge.childNodes.length ? badge.querySelector("." + this.getBadgeIconDefaultClassName()) : null;
 },
 getBadgeTextElement: function(badge) {
  return badge.childNodes.length ? badge.querySelector("span:not(." + this.getBadgeIconDefaultClassName() + ")") : null;
 }
});
ASPx.BadgeManagerBase = BadgeManagerBase;
var BadgeManager = ASPx.CreateClass(BadgeManagerBase, {
 getBadgeClassName: function() {
  return "dxBadge";
 },
 getBadgeIconDefaultClassName: function() {
  return "dxBadgeImage";
 },
 createBadgeForButton: function(button) {
  var badge = ASPx.BadgeManager.createBadge();
  var buttonImage = button.GetButtonImage();
  var textContainer = button.GetTextContainer();
  var badgeRightSibling = !!buttonImage ? buttonImage : textContainer;
  badgeRightSibling.parentNode.insertBefore(badge, badgeRightSibling);
  if(button.IsLink() && buttonImage)
   ASPx.SetStyles(badge, { verticalAlign: "middle" });
  return badge;
 },
 createBadgeForToolbar: function(toolbarItem) {
  var badge = ASPx.BadgeManager.createBadge();
  var itemImage = toolbarItem.GetImage();
  var badgeRightSibling = itemImage;
  if(!itemImage) {
   var itemContentElement = toolbarItem.menu.GetItemContentElement(toolbarItem.indexPath);
   badgeRightSibling = toolbarItem.menu.GetContentTextElement(itemContentElement);
  }
  badgeRightSibling.parentNode.insertBefore(badge, badgeRightSibling);
  return badge;
 }
});
ASPx.BadgeManager = new BadgeManager();
var AccessibilityUtils = {
 isInitialized: false,
 highContrastCssClassMarker: "dxHighContrast",
 highContrastBackgroundCssClassMarker: "dxHCB",
 highContrastDefaultBackgroundColor: "#a347ff",
 highContrastThemeActive: false,
 accessibleBackgroundCssMarker: ".dx-runtime-background",
 createAccessibleBackgrounds: function(control) {
  if(!this.highContrastThemeActive || control.accessibleBackgroundsCreated || !control.accessibilityCompliant)
   return;
  var className = this.accessibleBackgroundCssMarker;
  var styleSheetRuleNames = [];
  iterateStyleSheetRules(null, function(rule) {
   var selectorTxt = rule.selectorText;
   if(selectorTxt && selectorTxt.indexOf(className) > -1)
    styleSheetRuleNames.push(ASPx.Str.CompleteReplace(selectorTxt, className, "")); 
  });
  for(var i = 0; i < styleSheetRuleNames.length; i++) {
   var name = styleSheetRuleNames[i];
   var rule = ASPx.GetStyleSheetRules(name.substring(1));
   if(rule && rule.style && rule.style.backgroundImage)
    this.createAccessibleBackground(control.GetMainElement(), rule.style, name);
  }
  control.accessibleBackgroundsCreated = true;
 },
 createAccessibleBackground: function(container, style, selector) {
  if(!container)
   return;
  var backgroundUrl = style.backgroundImage.substring(5, style.backgroundImage.length - 2);
  var elements = container.querySelectorAll(selector);
  var accessibleBackgroundClassName = "dx-acc-bi";
  for(var i = 0; i < elements.length; i++) {
   var element = elements[i];
   if(ASPx.ElementHasCssClass(element, accessibleBackgroundClassName))
    continue;
   var image = null;
   if(element.tagName !== "IMG") {
    ASPx.AddClassNameToElement(element, accessibleBackgroundClassName);
    image = element.ownerDocument.createElement("IMG");
    ASPx.SetStyles(image, { width: "100%", height: "100%" });
    if(element.firstChild)
     element.insertBefore(image, element.firstChild);
    else
     element.appendChild(image);
   } else
    image = element;
   image.src = backgroundUrl;
  }
 },
 createHighContrastBackgroundStyle: function() {
  var style = document.createElement('style');
  ASPx.Attr.AppendStyleType(style);
  var styleContent = [
   "." + this.highContrastCssClassMarker + " ." + this.highContrastBackgroundCssClassMarker + ":after {",
   "border-image: url(" + this.getHighContrastBackgroundUrl() + ") 0 1 0 0 round;",
   "}",
  ];
  setInnerHtmlInternal(style, styleContent.join('\n'));
  document.getElementsByTagName('head')[0].appendChild(style);
 },
 getHighContrastBackgroundUrl: function() {
  var canvas = document.createElement("canvas"),
  ctx = canvas.getContext('2d');
  canvas.width = 1;
  canvas.height = 1;
  ctx.fillStyle = this.getHighContrastBackgroundColor();
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  return canvas.toDataURL();
 },
 getHighContrastBackgroundColor: function() {
  var foreColor = ASPx.GetCurrentStyle(document.body).color;
  var hexColor = ASPx.Color.ColorToHexadecimal(foreColor);
  return ASPx.HighContrastForeColorHighlightColorMap[hexColor] || this.highContrastDefaultBackgroundColor;
 },
 initialize: function() {
  if(this.isInitialized)
   return;
  this.isInitialized = true;
  this.detectHighContrastTheme();
  if(this.highContrastThemeActive)
   this.createHighContrastBackgroundStyle();
 },
 detectHighContrastTheme: function() {
  var testElement = document.createElement("DIV");
  ASPx.SetStyles(testElement, {
   backgroundColor: "rgb(255, 255, 255)",
   display: "none"
  }, true);
  var docElement = document.documentElement;
  docElement.appendChild(testElement);
  var actualBackgroundColor = ASPx.GetCurrentStyle(testElement).backgroundColor;
  docElement.removeChild(testElement);
  if(actualBackgroundColor === "rgb(0, 0, 0)") {
   this.highContrastThemeActive = true;
   ASPx.AddClassNameToElement(docElement, this.highContrastCssClassMarker);
  }
 }
};
ASPx.AccessibilityUtils = AccessibilityUtils;
ASPx.AccessibilityUtils.SendMessageToAssistiveTechnology = function(message) {
 var messageParts = ASPx.Ident.IsArray(message) ? message : [message];
 var args = new ASPxClientControlBeforePronounceEventArgs(messageParts, null);
 ASPx.AccessibilityPronouncer.EnsureInitialize();
 ASPx.AccessibilityPronouncer.Pronounce(args, ASPx.AccessibilityPronouncerType.live);
};
ASPx.AccessibilityUtils.SetFocusAccessible = function(focusableElement) {
 if(!focusableElement)
  return;
 var elementId = focusableElement.id;
 if(!elementId) {
  var namedParent = ASPx.GetParent(focusableElement, function(element) {
   return !!element.id;
  });
  if(ASPx.IsExists(namedParent))
   elementId = namedParent.id;
 }
 var focusableControl = ASPx.GetClientControlByElementID(elementId);
 if(focusableControl && focusableControl.OnAssociatedLabelClick)
  focusableControl.OnAssociatedLabelClick(focusableElement);
 else
  window.setTimeout(function() {
   ASPx.AccessibilityUtils.SetFocusAccessibleCore(focusableElement);
  }, 0);
};
ASPx.AccessibilityUtils.SetFocusAccessibleCore = function(focusableElement) {
 if(!ASPx.IsExists(focusableElement))
  return;
 var isTabIndexChanged = ASPx.ControlTabIndexManager.getInstance().isElementWithChangedIndex(focusableElement);
 if(isTabIndexChanged)
  return;
 if(!ASPx.IsValidElement(focusableElement) && focusableElement.id)
  focusableElement = ASPx.GetElementById(focusableElement.id);
 if(!ASPx.IsActionElement(focusableElement))
  focusableElement = ASPx.RestoreFocusHelper.findNeighbourFocusElement(focusableElement, document.body);
 if(ASPx.IsExistsElement(focusableElement))
  focusableElement.focus();
};
var Security = {
 setInnerHtml: function(el, html, dataType) {
  if(!html) {
   while(el.firstChild)
    ASPx.RemoveElement(el.firstChild);
  } else
   Security.setData(html, function(d) { ASPx.SetInnerHtml.call(window, el, d); }, dataType);
 },
 setText: function(control, text, dataType) { Security.setData(text, control.SetText.aspxBind(control), dataType); },
 safeEncodeHtml: function(html) { return ASPx.Str.EncodeHtml(ASPx.Str.DecodeHtml(html)); },
 setData: function(data, dataSetter, dataType) {
  if(dataType === undefined)
   throw new Error("Specify the dataType");
  if(dataType == Security.DataType.Untrusted)
   data = Security.safeEncodeHtml(data);
  dataSetter(data);
 }
};
Security.DataType = {
 Trusted: 0,
 Untrusted: 1
};
ASPx.EnableCssAnimation = true;
var AnimationTransitionBase = ASPx.CreateClass(null, {
 constructor: function(element, options) {
  if(element) {
   AnimationTransitionBase.Cancel(element);
   this.element = element;
   this.element.aspxTransition = this;
  }
  this.duration = options.duration || AnimationConstants.Durations.DEFAULT;
  this.transition = options.transition || AnimationConstants.Transitions.SINE;
  this.property = options.property;
  this.unit = options.unit || "";
  this.onComplete = options.onComplete;
  this.to = null;
  this.from = null;
 },
 Start: function(from, to) {
  if(to != undefined) {
   this.to = to;
   this.from = from;
   this.SetValue(this.from);
  }
  else
   this.to = from;
 },
 Cancel: function() {
  if(!this.element)
   return;
  try {
   delete this.element.aspxTransition;
  } catch(e) {
   this.element.aspxTransition = undefined;
  }
 },
 GetValue: function() {
  return this.getValueInternal(this.element, this.property);
 },
 SetValue: function(value) {
  this.setValueInternal(this.element, this.property, this.unit, value);
 },
 setValueInternal: function(element, property, unit, value) {
  if(property == "opacity")
   AnimationUtils.setOpacity(element, value);
  else
   element.style[property] = value + unit;
 },
 getValueInternal: function(element, property) {
  if(property == "opacity")
   return ASPx.GetElementOpacity(element);
  var value = parseFloat(element.style[property]);
  return isNaN(value) ? 0 : value;
 },
 performOnComplete: function() {
  if(this.onComplete)
   this.onComplete(this.element);
 },
 getTransition: function() {
  return this.transition;
 }
});
AnimationTransitionBase.Cancel = function(element) {
 if(element.aspxTransition)
  element.aspxTransition.Cancel();
};
var AnimationConstants = {};
AnimationConstants.Durations = {
 SHORT: 200,
 DEFAULT: 400,
 LONG: 600
};
AnimationConstants.Transitions = {
 LINER: {
  Css: "cubic-bezier(0.250, 0.250, 0.750, 0.750)",
  Js: function(progress) { return progress; }
 },
 SINE: {
  Css: "cubic-bezier(0.470, 0.000, 0.745, 0.715)",
  Js: function(progress) { return Math.sin(progress * 1.57); }
 },
 POW: {
  Css: "cubic-bezier(0.755, 0.050, 0.855, 0.060)",
  Js: function(progress) { return Math.pow(progress, 4); }
 },
 POW_EASE_OUT: {
  Css: "cubic-bezier(0.165, 0.840, 0.440, 1.000)",
  Js: function(progress) { return 1 - AnimationConstants.Transitions.POW.Js(1 - progress); }
 },
 RIPPLE: {
  Css: "cubic-bezier(0.47, 0.06, 0.23, 0.99)",
  Js: function(progress) {
   return Math.pow((progress), 3) * 0.47 + 3 * progress * Math.pow((1 - progress), 2) * 0.06 + 3 * Math.pow(progress, 2) *
    (1 - progress) * 0.23 + 0.99 * Math.pow(progress, 3);
  }
 }
};
var JsAnimationTransition = ASPx.CreateClass(AnimationTransitionBase, {
 constructor: function(element, options) {
  this.constructor.prototype.constructor.call(this, element, options);
  this.onStep = options.onStep;
  this.fps = 60;
  this.startTime = null;
 },
 Start: function(from, to) {
  if(from == to) {
   this.from = this.to = from;
   setTimeout(this.complete.aspxBind(this), 0);
  }
  else {
   AnimationTransitionBase.prototype.Start.call(this, from, to);
   if(to == undefined)
    this.from = this.GetValue();
   this.initTimer();
  }
 },
 Cancel: function() {
  AnimationTransitionBase.prototype.Cancel.call(this);
  if(this.timerId)
   clearInterval(this.timerId);
 },
 initTimer: function() {
  this.startTime = new Date();
  this.timerId = window.setInterval(function() { this.onTick(); }.aspxBind(this), 1000 / this.fps);
 },
 onTick: function() {
  var progress = (new Date() - this.startTime) / this.duration;
  if(progress >= 1)
   this.complete();
  else {
   this.update(progress);
   if(this.onStep)
    this.onStep();
  }
 },
 update: function(progress) {
  this.SetValue(this.gatCalculatedValue(this.from, this.to, progress));
 },
 complete: function() {
  this.Cancel();
  this.update(1);
  this.performOnComplete();
 },
 gatCalculatedValue: function(from, to, progress) {
  if(progress == 1)
   return to;
  return from + (to - from) * this.getTransition()(progress);
 },
 getTransition: function() {
  return this.transition.Js;
 }
});
var SimpleAnimationTransition = ASPx.CreateClass(JsAnimationTransition, {
 constructor: function(options) {
  this.constructor.prototype.constructor.call(this, null, options);
  this.transition = options.transition || AnimationConstants.Transitions.POW_EASE_OUT;
  this.onUpdate = options.onUpdate;
  this.lastValue = 0;
 },
 SetValue: function(value) {
  this.onUpdate(value - this.lastValue);
  this.lastValue = value;
 },
 GetValue: function() {
  return this.lastValue;
 },
 performOnComplete: function() {
  if(this.onComplete)
   this.onComplete();
 }
});
var MultipleJsAnimationTransition = ASPx.CreateClass(JsAnimationTransition, {
 constructor: function(element, options) {
  this.constructor.prototype.constructor.call(this, element, options);
  this.properties = {};
 },
 Start: function(properties) {
  this.initProperties(properties);
  this.initTimer();
 },
 initProperties: function(properties) {
  this.properties = properties;
  for(var propName in this.properties)
   if(properties[propName].from == undefined)
    properties[propName].from = this.getValueInternal(this.element, propName);
 },
 update: function(progress) {
  for(var propName in this.properties) {
   if(this.properties.hasOwnProperty(propName)) {
    var property = this.properties[propName];
    if(property.from != property.to)
     this.setValueInternal(this.element, propName, property.unit, this.gatCalculatedValue(property.from, property.to, progress));
   }
  }
 }
});
var CssAnimationTransition = ASPx.CreateClass(AnimationTransitionBase, {
 constructor: function(element, options) {
  this.constructor.prototype.constructor.call(this, element, options);
  this.transitionPropertyName = AnimationUtils.CurrentTransition.property;
  this.eventName = AnimationUtils.CurrentTransition.event;
  this.forceTransitionEndByTimer = true;
  this.needForceTransitionEndByTimerFlag = options.needForceTransitionEndByTimerFlag;
 },
 Start: function(from, to) {
  this.forceTransitionEndByTimer = true;
  AnimationTransitionBase.prototype.Start.call(this, from, to);
  this.startTimerId = window.setTimeout(function() {
   if(this.from == this.to)
    this.onTransitionEnd();
   else {
    var isHidden = ASPx.GetElementOffsetHeight(this.element) == 0 && ASPx.GetElementOffsetWidth(this.element) == 0; 
    if(!isHidden)
     this.prepareElementBeforeAnimation();
    this.SetValue(this.to);
    if(isHidden)
     this.onTransitionEnd();
   }
  }.aspxBind(this), 0);
 },
 Cancel: function() {
  this.forceTransitionEndByTimer = false;
  window.clearTimeout(this.startTimerId);
  AnimationTransitionBase.prototype.Cancel.call(this);
  ASPx.Evt.DetachEventFromElement(this.element, this.eventName, CssAnimationTransition.transitionEnd);
  this.setValueInternal(this.element, this.transitionPropertyName, "", "");
  this.stopAnimation();
 },
 prepareElementBeforeAnimation: function() {
  ASPx.Evt.AttachEventToElement(this.element, this.eventName, CssAnimationTransition.transitionEnd);
  var dummy = this.element.offsetHeight;
  this.element.style[this.transitionPropertyName] = this.getTransitionCssString();
  if(this.needForceTransitionEndByTimer()) {
   setTimeout(function() {
    if(this.forceTransitionEndByTimer && this.element && this.element.aspxTransition) {
     this.element.style[this.transitionPropertyName] = "";
     this.element.aspxTransition.onTransitionEnd();
    }
   }.aspxBind(this), this.duration + 100);
  }
 },
 needForceTransitionEndByTimer: function() {
  if(this.needForceTransitionEndByTimerFlag)
   return true;
  if(ASPx.Browser.Safari && ASPx.Browser.MacOSMobilePlatform && ASPx.Browser.MajorVersion >= 8) 
   return true;
  return ASPx.Browser.AndroidMobilePlatform; 
 },
 stopAnimation: function() {
  this.SetValue(ASPx.GetCurrentStyle(this.element)[this.property]);
 },
 onTransitionEnd: function() {
  this.Cancel();
  this.performOnComplete();
 },
 getTransition: function() {
  return this.transition.Css;
 },
 getTransitionCssString: function() {
  return this.getTransitionCssStringInternal(this.getCssName(this.property));
 },
 getTransitionCssStringInternal: function(cssProperty) {
  return cssProperty + " " + this.duration + "ms " + this.getTransition();
 },
 getCssName: function(property) {
  switch(property) {
   case "marginLeft":
    return "margin-left";
   case "marginTop":
    return "margin-top";
  }
  return property;
 }
});
var MultipleCssAnimationTransition = ASPx.CreateClass(CssAnimationTransition, {
 constructor: function(element, options) {
  this.constructor.prototype.constructor.call(this, element, options);
  this.properties = null;
 },
 Start: function(properties) {
  this.properties = properties;
  this.forEachProperties(function(property, propName) {
   if(property.from !== undefined)
    this.setValueInternal(this.element, propName, property.unit, property.from);
  }.aspxBind(this));
  this.prepareElementBeforeAnimation();
  window.setTimeout(function() {
   this.forEachProperties(function(property, propName) {
    this.setValueInternal(this.element, propName, property.unit, property.to);
   }.aspxBind(this));
  }.aspxBind(this), 0);
 },
 stopAnimation: function() {
  var style = ASPx.GetCurrentStyle(this.element);
  this.forEachProperties(function(property, propName) {
   this.setValueInternal(this.element, propName, "", style[propName]);
  }.aspxBind(this));
 },
 getTransitionCssString: function() {
  var str = "";
  this.forEachProperties(function(property, propName) {
   str += this.getTransitionCssStringInternal(this.getCssName(propName)) + ",";
  }.aspxBind(this));
  str = str.substring(0, str.length - 1);
  return str;
 },
 forEachProperties: function(func) {
  for(var propName in this.properties) {
   if(this.properties.hasOwnProperty(propName)) {
    var property = this.properties[propName];
    if(property.from == undefined)
     property.from = this.getValueInternal(this.element, propName);
    if(property.from != property.to)
     func(property, propName);
   }
  }
 }
});
CssAnimationTransition.transitionEnd = function(evt) {
 var element = evt.target;
 if(element && element.aspxTransition)
  element.aspxTransition.onTransitionEnd();
};
var AnimationUtils = {
 CanUseCssTransition: function() { return ASPx.EnableCssAnimation && this.CurrentTransition; },
 CanUseCssTransform: function() { return this.CanUseCssTransition() && this.CurrentTransform; },
 CurrentTransition: (function() {
  var transitions = [
   { property: "webkitTransition", event: "webkitTransitionEnd" },
   { property: "MozTransition", event: "transitionend" },
   { property: "OTransition", event: "oTransitionEnd" },
   { property: "transition", event: "transitionend" }
  ];
  var fakeElement = document.createElement("DIV");
  for(var i = 0; i < transitions.length; i++)
   if(transitions[i].property in fakeElement.style)
    return transitions[i];
 })(),
 CurrentTransform: (function() {
  var transforms = ["transform", "MozTransform", "-webkit-transform", "msTransform", "OTransform"];
  var fakeElement = document.createElement("DIV");
  for(var i = 0; i < transforms.length; i++)
   if(transforms[i] in fakeElement.style)
    return transforms[i];
 })(),
 SetTransformValue: function(element, position, isTop) {
  if(this.CanUseCssTransform())
   element.style[this.CurrentTransform] = this.GetTransformCssText(position, isTop);
  else
   element.style[!isTop ? "left" : "top"] = position + "px";
 },
 GetTransformValue: function(element, isTop) {
  if(this.CanUseCssTransform()) {
   var cssValue = element.style[this.CurrentTransform];
   return cssValue && cssValue != "none" ? Number(cssValue.replace('matrix(1, 0, 0, 1,', '').replace(')', '').split(',')[!isTop ? 0 : 1]) : 0;
  }
  else
   return !isTop ? element.offsetLeft : element.offsetTop;
 },
 GetTransformCssText: function(position, isTop) {
  if(!position)
   return "none";
  return "matrix(1, 0, 0, 1," + (!isTop ? position : 0) + ", " + (!isTop ? 0 : position) + ")";
 },
 createMultipleAnimationTransition: function (element, options) {
  return this.CanUseCssTransition() && !options.onStep ? new MultipleCssAnimationTransition(element, options) : new MultipleJsAnimationTransition(element, options);
 },
 createSimpleAnimationTransition: function(options) {
  return new SimpleAnimationTransition(options);
 },
 createJsAnimationTransition: function(element, options) {
  return new JsAnimationTransition(element, options);
 },
 createCssAnimationTransition: function(element, options) {
  return new CssAnimationTransition(element, options);
 },
 setOpacity: function(element, value) {
  ASPx.SetElementOpacity(element, value);
 }
};
var AsyncTracker = function() {
 var currentToken,
  lockedTokens,
  onDoneDelegates,
  lockedDelegates;
 function clearState() {
  currentToken = 1;
  lockedTokens = [];
  onDoneDelegates = [];
  lockedDelegates = {};
 }
 clearState();
 var log = function(msg) { };
 function setLog(delegate){
  log = delegate;
 }
 function getLockToken() {
  if(onDoneDelegates.length === 0)
   return -1;
  var token = currentToken++;
  lockedTokens.push(token);
  lockedDelegates[token] = [];
  for (var i = 0; i < onDoneDelegates.length; i++) {
   lockedDelegates[token].push(onDoneDelegates[i]);
  }
  log("module locks token " + token);
  return token;
 }
 function releaseToken(token) {
  if(token < 0) return;
  log("module releasing token " + token);
  ASPx.Data.ArrayRemove(lockedTokens, token);
  delete lockedDelegates[token];
  invokeUnlockedDelegates();
  if(lockedTokens.length === 0)
   clearState();
  log("module released token " + token);
 }
 function invokeUnlockedDelegates() {
  var onDoneDelegate;
  for (var i = onDoneDelegates.length - 1; i >= 0; i--) {
   if(onDoneDelegates[i] && !isDelegateLocked(onDoneDelegates[i])) {
    onDoneDelegate = onDoneDelegates[i];
    delete onDoneDelegates[i];
    onDoneDelegate();
   }
  }
 }
 function isDelegateLocked(delegate) {
  for (var i = lockedTokens.length - 1; i >= 0; i--) {
   var token = lockedTokens[i];
   var delegates = lockedDelegates[token];
   if(delegates) {
    for (var j = delegates.length - 1; j >= 0; j--) {
     if(delegates[j] && delegates[j] === delegate)
      return true;
    }
   }
  }
  return false;
 }
 function track(doDelegate, onDoneDelegate) {
  if(onDoneDelegate)
   onDoneDelegates.push(onDoneDelegate);
  doDelegate();
  if(onDoneDelegate)
   invokeUnlockedDelegates();
 }
 return {
  getLockToken: getLockToken,
  releaseToken: releaseToken,
  track: track,
  setLog:setLog,
 };
};
var GetEditorValuesInContainer = function(containerOrId, processInvisibleEditors, needSerialize) {
 var container = typeof(containerOrId) === "string" ? ASPx.GetElementById(containerOrId) : containerOrId;
 var result = {};
 if(!ASPx.ProcessEditorsInContainer) 
  return result;
 ASPx.ProcessEditorsInContainer(container, function(editor){
  result[editor.name] = GetCorrectedByTypeValue(ASPx.GetEditorValueByControl(editor), needSerialize);
  return true;
 }, null, null, processInvisibleEditors, false);
 return result;
};
var SetEditorValues = function(values) {
 for(var controlName in values) {
  if(values.hasOwnProperty(controlName)) {
   var trackedControl = ASPxClientControl.GetControlCollection().Get(controlName);
   if(!trackedControl)
    continue;
   var setValueMethod = trackedControl.SetTokenCollection || trackedControl.SelectValues || trackedControl.SetValue;
   if(setValueMethod === trackedControl.SelectValues)
    trackedControl.UnselectAll();
   setValueMethod.call(trackedControl, values[controlName]);
  }
 }
};
var GetCorrectedByTypeValue = function(value, needSerialize){
 if(ASPx.Ident.IsArray(value))
  for(var i = 0; i < value.length; i++)
   value[i] = GetCorrectedByTypeValue(value[i]);
 if(needSerialize && ASPx.Ident.IsDate(value))
  return ASPx.DateUtils.GetInvariantDateTimeString(value);
 return value;
};
var ListBoxTemporaryCache = ASPx.CreateClass(null, {
 constructor: function() { 
  this.cache = { };
  this.invalidateTimerID = -1;
 },
 Get: function(key, getObjectFunc, context, args) {
  if(this.invalidateTimerID < 0) {
   this.invalidateTimerID = window.setTimeout(function() {
    this.Invalidate();
   }.aspxBind(this), 0);
  }
  if(!ASPx.IsExists(this.cache[key])) {
   if(!ASPx.IsExists(args))
    args = [ ];
   this.cache[key] = getObjectFunc.apply(context, args);
  }
  return this.cache[key];
 },
 Invalidate: function() {
  this.cache = { };
  this.invalidateTimerID = ASPx.Timer.ClearTimer(this.invalidateTimerID);
 }
});
ASPx.GetEditorValueByControl = function(control, needSerialize) {
 var result;
 if(ASPx.IsMultipleValueOwner(control))
  result = control.GetSelectedValues();
 if(ASPx.IsTokenBox(control)) {
  if(needSerialize)
   result = control.GetTokenValuesCollection();
  else
   result = control.GetTokenCollection();
 }
 if(ASPx.IsDropDownEdit(control))
  result = control.GetKeyValue();
 if(ASPx.IsHtmlEditor(control))
  result = control.GetHtml();
 return result || control.GetValue();
};
ASPx.IsMultipleValueOwner = function(control) {
 return ASPx.IsListBox(control) || ASPx.IsCheckBoxList(control);
};
ASPx.IsCheckBoxList = function(control) {
 return control && typeof(ASPxClientCheckBoxList) != "undefined" && control instanceof ASPxClientCheckBoxList;
};
ASPx.IsListBox = function(control) {
 return control && typeof(ASPxClientListBox) != "undefined" && control instanceof ASPxClientListBox;
};
ASPx.IsComboBox = function(control) {
 return control && typeof(ASPxClientComboBox) != "undefined" && control instanceof ASPxClientComboBox;
};
ASPx.IsTokenBox = function(control) {
 return control && typeof(ASPxClientTokenBox) != "undefined" && control instanceof ASPxClientTokenBox;
};
ASPx.IsDropDownEdit = function(control) {
 return control && typeof (ASPxClientDropDownEdit) != "undefined" && control instanceof ASPxClientDropDownEdit;
};
ASPx.IsGridLookup = function(control) {
 return control && typeof(MVCxClientGridLookup) != "undefined" && control instanceof MVCxClientGridLookup;
};
ASPx.IsSpinEdit = function(control) {
 return control && typeof(ASPxClientSpinEdit) != "undefined" && control instanceof ASPxClientSpinEdit;
};
ASPx.IsHtmlEditor = function(control) {
 return control && typeof (ASPxClientHtmlEditor) != "undefined" && control instanceof ASPxClientHtmlEditor;
};
ASPx.DatePickerType = {
 Days: 0,
 Months: 1,
 Years: 2,
 Decades: 3
};
ASPx.FullScreenUtils = {
 subscribeChange: function(handler) {
  Evt.AttachEventToElement(document, "fullscreenchange", handler);
  Evt.AttachEventToElement(document, "msfullscreenchange", handler); 
  Evt.AttachEventToElement(document, "MSFullscreenChange", handler); 
  Evt.AttachEventToElement(document, "webkitfullscreenchange", handler);
  Evt.AttachEventToElement(document, "mozfullscreenchange", handler);
 },
 unsubscribeChange: function(handler) {
  Evt.DetachEventFromElement(document, "fullscreenchange", handler);
  Evt.DetachEventFromElement(document, "msfullscreenchange", handler);
  Evt.DetachEventFromElement(document, "MSFullscreenChange", handler);
  Evt.DetachEventFromElement(document, "webkitfullscreenchange", handler);
  Evt.DetachEventFromElement(document, "mozfullscreenchange", handler);
 },
 setFullscreen: function(on) {
  var element = window.self.document.body;
  if(on) {
   if(element.requestFullscreen) {
    element.requestFullscreen();
   } else if(element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
   } else if(element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
   } else if(element.msRequestFullscreen) {
    element.msRequestFullscreen();
   }
  } else {
   if(document.exitFullscreen) {
    document.exitFullscreen();
   } else if(document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
   } else if(document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen();
   } else if(document.msExitFullscreen) {
    document.msExitFullscreen();
   }
  }
 },
 inFullscreen: function() {
  var fullscreenElement = document.fullscreenElement || document.msFullscreenElement || document.webkitFullscreenElement;
  var isInFullscreen = fullscreenElement === document.body || document.webkitIsFullScreen;
  return !!isInFullscreen;
 }
 };
ASPx.InitializeSVGSprite = function () {
 if (ASPx.SVGSprites && ASPx.SVGSprites.length > 0) {
  var svgContainer = document.getElementById('svgContainer');
  var hasSvgContainer = !!svgContainer;
  if (!hasSvgContainer) {
   svgContainer = document.createElement('div');
   svgContainer.id = 'svgContainer';
   svgContainer.style.display = "none";
   document.body.appendChild(svgContainer);
  }
  for (var i = 0; i < ASPx.SVGSprites.length; i++) {
   svgContainer.innerHTML += ASPx.SVGSprites[i];
  }
  ASPx.SVGSprites = null;
 }
};
var GridDynamicStyleSheetHelper = ASPx.CreateClass(null, {
 constructor: function() {
  this.styleSheet = {};
  this.rules = {};
  this.updateLock = 0;
 },
 Update: function(control, styleName, rules) {
  var key = control.name + "_" + styleName;
  this.BeginUpdate(key);
  this.ChangeRules(key, rules);
  this.EndUpdate(key);
 },
 ChangeRules: function(key, rules) {
  if(key && rules)
   this.rules[key] = rules;
 },
 BeginUpdate: function(key) {
  this.updateLock++;
  this.RemoveStyleSheetElement(key);
 },
 EndUpdate: function(key) {
  this.updateLock--;
  if(this.updateLock !== 0)
   return;
  var styleArgs = [];
  var controlRules = this.rules[key];
  for(var i = 0; i < controlRules.length; i++) {
   var rule = controlRules[i];
   styleArgs.push(rule.selector + " { " + rule.cssText + " } ");
  }
  this.styleSheet[key] = this.CreateStyleSheet(key, styleArgs.join(""));
 },
 CreateStyleSheet: function(key, cssText) {
  var container = document.createElement("DIV");
  ASPx.Security.setInnerHtml(container, "<style type='text/css' id='" + key + "'>" + cssText + "</style>", ASPx.Security.DataType.Trusted);
  styleSheet = ASPx.GetNodeByTagName(container, "style", 0);
  if(styleSheet)
   ASPx.GetNodeByTagName(document, "HEAD", 0).appendChild(styleSheet);
  return styleSheet;
 },
 ClearStyleSheet: function(control, styleName) {
  var key = control.name + "_" + styleName;
  this.RemoveStyleSheetElement(key);
 },
 RemoveStyleSheetElement: function(key) {
  if(this.styleSheet[key]) {
   ASPx.RemoveElement(this.styleSheet[key]);
   delete this.styleSheet[key];
  }
 }
});
GridDynamicStyleSheetHelper.Instance = new GridDynamicStyleSheetHelper();
ASPx.GridDynamicStyleSheetHelper = GridDynamicStyleSheetHelper;
ASPxClientUtils = {};
ASPxClientUtils.agent = Browser.UserAgent;
ASPxClientUtils.opera = Browser.Opera;
ASPxClientUtils.opera9 = Browser.Opera && Browser.MajorVersion == 9;
ASPxClientUtils.safari = Browser.Safari;
ASPxClientUtils.safari3 = Browser.Safari && Browser.MajorVersion == 3;
ASPxClientUtils.safariMacOS = Browser.Safari && Browser.MacOSPlatform;
ASPxClientUtils.chrome = Browser.Chrome;
ASPxClientUtils.ie = Browser.IE;
ASPxClientUtils.ie7 = Browser.IE && Browser.MajorVersion == 7;
ASPxClientUtils.firefox = Browser.Firefox;
ASPxClientUtils.firefox3 = Browser.Firefox && Browser.MajorVersion == 3;
ASPxClientUtils.mozilla = Browser.Mozilla;
ASPxClientUtils.netscape = Browser.Netscape;
ASPxClientUtils.browserVersion = Browser.Version;
ASPxClientUtils.browserMajorVersion = Browser.MajorVersion;
ASPxClientUtils.macOSPlatform = Browser.MacOSPlatform;
ASPxClientUtils.windowsPlatform = Browser.WindowsPlatform;
ASPxClientUtils.webKitFamily = Browser.WebKitFamily;
ASPxClientUtils.netscapeFamily = Browser.NetscapeFamily;
ASPxClientUtils.touchUI = Browser.TouchUI;
ASPxClientUtils.webKitTouchUI = Browser.WebKitTouchUI;
ASPxClientUtils.msTouchUI = Browser.MSTouchUI;
ASPxClientUtils.iOSPlatform = Browser.MacOSMobilePlatform;
ASPxClientUtils.androidPlatform = Browser.AndroidMobilePlatform;
ASPxClientUtils.ArrayInsert = Data.ArrayInsert;
ASPxClientUtils.ArrayRemove = Data.ArrayRemove;
ASPxClientUtils.ArrayRemoveAt = Data.ArrayRemoveAt;
ASPxClientUtils.ArrayClear = Data.ArrayClear;
ASPxClientUtils.ArrayIndexOf = Data.ArrayIndexOf;
ASPxClientUtils.AttachEventToElement = Evt.AttachEventToElement;
ASPxClientUtils.DetachEventFromElement = Evt.DetachEventFromElement;
ASPxClientUtils.GetEventSource = Evt.GetEventSource;
ASPxClientUtils.GetEventX = Evt.GetEventX;
ASPxClientUtils.GetEventY = Evt.GetEventY;
ASPxClientUtils.GetKeyCode = Evt.GetKeyCode;
ASPxClientUtils.PreventEvent = Evt.PreventEvent;
ASPxClientUtils.PreventEventAndBubble = Evt.PreventEventAndBubble;
ASPxClientUtils.PreventDragStart = Evt.PreventDragStart;
ASPxClientUtils.ClearSelection = Selection.Clear;
ASPxClientUtils.IsExists = ASPx.IsExists;
ASPxClientUtils.IsFunction = ASPx.IsFunction;
ASPxClientUtils.GetAbsoluteX = ASPx.GetAbsoluteX;
ASPxClientUtils.GetAbsoluteY = ASPx.GetAbsoluteY;
ASPxClientUtils.SetAbsoluteX = ASPx.SetAbsoluteX;
ASPxClientUtils.SetAbsoluteY = ASPx.SetAbsoluteY;
ASPxClientUtils.GetDocumentScrollTop = ASPx.GetDocumentScrollTop;
ASPxClientUtils.GetDocumentScrollLeft = ASPx.GetDocumentScrollLeft;
ASPxClientUtils.GetDocumentClientWidth = ASPx.GetDocumentClientWidth;
ASPxClientUtils.GetDocumentClientHeight = ASPx.GetDocumentClientHeight;
ASPxClientUtils.AddClassNameToElement = ASPx.AddClassNameToElement;
ASPxClientUtils.RemoveClassNameFromElement = ASPx.RemoveClassNameFromElement;
ASPxClientUtils.ToggleClassName = ASPx.ToggleClassNameToElement;
ASPxClientUtils.GetIsParent = ASPx.GetIsParent;
ASPxClientUtils.GetParentById = ASPx.GetParentById;
ASPxClientUtils.GetParentByTagName = ASPx.GetParentByTagName;
ASPxClientUtils.GetParentByClassName = ASPx.GetParentByPartialClassName;
ASPxClientUtils.GetChildById = ASPx.GetChildById;
ASPxClientUtils.GetChildByTagName = ASPx.GetChildByTagName;
ASPxClientUtils.SetCookie = Cookie.SetCookie;
ASPxClientUtils.GetCookie = Cookie.GetCookie;
ASPxClientUtils.DeleteCookie = Cookie.DelCookie;
ASPxClientUtils.GetShortcutCode = ASPx.GetShortcutCode; 
ASPxClientUtils.GetShortcutCodeByEvent = ASPx.GetShortcutCodeByEvent;
ASPxClientUtils.StringToShortcutCode = ASPx.ParseShortcutString;
ASPxClientUtils.Trim = Str.Trim; 
ASPxClientUtils.TrimStart = Str.TrimStart;
ASPxClientUtils.TrimEnd = Str.TrimEnd;
ASPxClientUtils.GetEditorValuesInContainer = GetEditorValuesInContainer;
ASPxClientUtils.SetEditorValues = SetEditorValues;
ASPxClientUtils.SendMessageToAssistiveTechnology = ASPx.AccessibilityUtils.SendMessageToAssistiveTechnology;
window.ASPxClientUtils = ASPxClientUtils;
window.ListBoxTemporaryCache = ListBoxTemporaryCache;
ASPx.AnimationUtils = AnimationUtils;
ASPx.AnimationTransitionBase = AnimationTransitionBase;
ASPx.AnimationConstants = AnimationConstants;
ASPx.AsyncTracker = AsyncTracker;
ASPx.Security = Security;
})(ASPx, dx);

(function () {
 var ASPx = window.ASPx || {};
 ASPx.ASPxImageLoad = {};
 ASPx.ASPxImageLoad.dxDefaultLoadingImageCssClass = "dxe-loadingImage";
 ASPx.ASPxImageLoad.dxDefaultLoadingImageCssClassRegexp = new RegExp("dx\\w+-loadingImage");
 ASPx.ASPxImageLoad.OnLoad = function (image, customLoadingImage, isOldIE, customBackgroundImageUrl) {
  image.dxCustomBackgroundImageUrl = "";
  image.dxShowLoadingImage = true;
  image.dxCustomLoadingImage = customLoadingImage;
  if (customBackgroundImageUrl != "")
   image.dxCustomBackgroundImageUrl = "url('" + customBackgroundImageUrl + "')";
  ASPx.ASPxImageLoad.prepareImageBackground(image, isOldIE);
  ASPx.ASPxImageLoad.removeHandlers(image);
  image.className = image.className.replace(ASPx.ASPxImageLoad.dxDefaultLoadingImageCssClassRegexp, "");
 };
 ASPx.ASPxImageLoad.removeASPxImageBackground = function (image, isOldIE) {
  if (isOldIE) 
   image.style.removeAttribute("background-image");
  else 
   image.style.backgroundImage = "";
 };
 ASPx.ASPxImageLoad.prepareImageBackground = function (image, isOldIE) {
  ASPx.ASPxImageLoad.removeASPxImageBackground(image, isOldIE);
  if (image.dxCustomBackgroundImageUrl != "")
   image.style.backgroundImage = image.dxCustomBackgroundImageUrl;
 };
 ASPx.ASPxImageLoad.removeHandlers = function (image) {
  image.removeAttribute("onload");
  image.removeAttribute("onabort");
  image.removeAttribute("onerror");
 };
 window.ASPx = ASPx;
})();
(function module(ASPx, options) {
ASPx.modules.Classes = module;
ASPx.classesScriptParsed = false;
ASPx.documentLoaded = false; 
ASPx.CallbackType = {
 Data: "d",
 Common: "c"
};
ASPx.callbackState = {
 aborted: "aborted",
 inTurn: "inTurn",
 sent: "sent"
};
var ASPxClientEvent = ASPx.CreateClass(null, {
 constructor: function() {
  this.handlerInfoList = [];
  this.firingIndex = -1;
 },
 AddHandler: function(handler, executionContext) {
  if(typeof(executionContext) == "undefined")
   executionContext = null;
  this.RemoveHandler(handler, executionContext);
  var handlerInfo = ASPxClientEvent.CreateHandlerInfo(handler, executionContext);
  this.handlerInfoList.push(handlerInfo);
 },
 RemoveHandler: function(handler, executionContext) {
  this.removeHandlerByCondition(function(handlerInfo) {
   return handlerInfo.handler == handler && 
    (!executionContext || handlerInfo.executionContext == executionContext);
  });
 },
 removeHandlerByCondition: function(predicate) {
   for(var i = this.handlerInfoList.length - 1; i >= 0; i--) {
   var handlerInfo = this.handlerInfoList[i];
   if(predicate(handlerInfo)) {
    ASPx.Data.ArrayRemoveAt(this.handlerInfoList, i);
    if(i <= this.firingIndex)
     this.firingIndex--;
   }
  }
 },
 removeHandlerByControlName: function(controlName) {
  this.removeHandlerByCondition(function(handlerInfo) {
   return handlerInfo.executionContext &&  
    handlerInfo.executionContext.name === controlName;
  });
 },
 ClearHandlers: function() {
  this.handlerInfoList.length = 0;
 },
 FireEvent: function(obj, args) {
  for(this.firingIndex = 0; this.firingIndex < this.handlerInfoList.length; this.firingIndex++) {
   var handlerInfo = this.handlerInfoList[this.firingIndex];
   handlerInfo.handler.call(handlerInfo.executionContext, obj, args);
  }
 },
 InsertFirstHandler: function(handler, executionContext){
  if(typeof(executionContext) == "undefined")
   executionContext = null;
  var handlerInfo = ASPxClientEvent.CreateHandlerInfo(handler, executionContext);
  ASPx.Data.ArrayInsert(this.handlerInfoList, handlerInfo, 0);
 },
 IsEmpty: function() {
  return this.handlerInfoList.length == 0;
 }
});
ASPxClientEvent.CreateHandlerInfo = function(handler, executionContext) {
 return {
  handler: handler,
  executionContext: executionContext
 };
};
var ASPxClientEventArgs = ASPx.CreateClass(null, {
 constructor: function() {
 }
});
ASPxClientEventArgs.Empty = new ASPxClientEventArgs();
var ASPxClientCancelEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(){
  this.constructor.prototype.constructor.call(this);
  this.cancel = false;
 }
});
var ASPxClientProcessingModeEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(processOnServer){
  this.constructor.prototype.constructor.call(this);
  this.processOnServer = !!processOnServer;
 }
});
var ASPxClientProcessingModeCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(processOnServer){
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.cancel = false;
 }
});
var OrderedMap = ASPx.CreateClass(null, {
 constructor: function(){
  this.entries = {};
  this.firstEntry = null;
  this.lastEntry = null;
 },
 add: function(key, element) {
  var entry = this.addEntry(key, element);
  this.entries[key] = entry;
 },
 remove: function(key) {
  var entry = this.entries[key];
  if(entry === undefined)
   return;
  this.removeEntry(entry);
  delete this.entries[key];
 },
 clear: function() {
  this.markAllEntriesAsRemoved();
  this.entries = {};
  this.firstEntry = null;
  this.lastEntry = null;
 },
 get: function(key) {
  var entry = this.entries[key];
  return entry ? entry.value : undefined;
 },
 forEachEntry: function(processFunc, context) {
  context = context || this;
  for(var entry = this.firstEntry; entry; entry = entry.next) {
   if(entry.removed)
    continue;
   if(processFunc.call(context, entry.key, entry.value))
    return;
  }
 },
 addEntry: function(key, element) {
  var entry = { key: key, value: element, next: null, prev: null };
  if(!this.firstEntry)
   this.firstEntry = entry;
  else {
   entry.prev = this.lastEntry;
   this.lastEntry.next = entry;
  }
  this.lastEntry = entry;
  return entry;
 },
 removeEntry: function(entry) {
  if(this.firstEntry == entry)
   this.firstEntry = entry.next;
  if(this.lastEntry == entry)
   this.lastEntry = entry.prev;
  if(entry.prev)
   entry.prev.next = entry.next;
  if(entry.next)
   entry.next.prev = entry.prev;
  entry.removed = true;
 },
 markAllEntriesAsRemoved: function() {
  for(var entry = this.firstEntry; entry; entry = entry.next)
   entry.removed = true;
 }
});
var CollectionBase = ASPx.CreateClass(null, {
 constructor: function(){
  this.elementsMap = new OrderedMap();
  this.isASPxClientCollection = true;
 },
 Add: function(key, element) {
  this.elementsMap.add(key, element);
 },
 Remove: function(key) {
  this.elementsMap.remove(key);
 },
 Clear: function(){
  this.elementsMap.clear();
 },
 Get: function(key){
  return this.elementsMap.get(key);
 }
});
(function garbageCollector(ASPx, options) {
 ASPx.modules.garbageCollector = garbageCollector;
 var interval = options.GCCheckInterval;
 window.setInterval(collectObjects, interval);
 function canCollectObjects() {
  if (!ASPx.GetControlCollection) return false;
  var collection = ASPx.GetControlCollection();
  return collection && !collection.InCallback();
 }
 function collectObjects() {
  if (!canCollectObjects()) return;
  ASPx.GetControlCollectionCollection().RemoveDisposedControls();
  if(typeof(ASPx.GetStateController) != "undefined")
   ASPx.GetStateController().RemoveDisposedItems();
  if(ASPx.TableScrollHelperCollection)
   ASPx.TableScrollHelperCollection.RemoveDisposedObjects();
  if(ASPx.Ident.scripts.ASPxClientRatingControl)
   ASPxClientRatingControl.RemoveDisposedElementUnderCursor();
  var postHandler = ASPx.GetPostHandler();
  if(postHandler)
   postHandler.RemoveDisposedFormsFromCache();
 }
})(ASPx, options);
var ControlTree = ASPx.CreateClass(null, {
 constructor: function(controlCollection, container, controlFilter) {
  this.container = container;
  this.domMap = { };
  this.rootNode = this.createNode(null, null);
  this.createControlTree(controlCollection, container, controlFilter);
 },
 createControlTree: function(controlCollection, container, controlFilter) {
  controlCollection.ProcessControlsInContainer(container, function(control) {
   control.RegisterInControlTree(this);
  }.aspxBind(this), controlFilter);
  var fixedNodes = [];
  var fixedNodesChildren = [];
  for(var domElementID in this.domMap) {
   if(!this.domMap.hasOwnProperty(domElementID)) continue;
   var node = this.domMap[domElementID];
   var controlOwner = node.control ? node.control.controlOwner : null;
   if(controlOwner && this.domMap[controlOwner.name])
    continue;
   if(this.isFixedNode(node))
    fixedNodes.push(node);
   else {
    var parentNode = this.findParentNode(domElementID);
    parentNode = parentNode || this.rootNode;
    if(this.isFixedNode(parentNode))
     fixedNodesChildren.push(node);
    else {
     var childNode = node.mainNode || node;
     this.addChildNode(parentNode, childNode);
    }
   }
  }
  for(var i = fixedNodes.length - 1; i >= 0; i--)
   this.insertChildNode(this.rootNode, fixedNodes[i], 0);
  for(var i = fixedNodesChildren.length - 1; i >= 0; i--)
   this.insertChildNode(this.rootNode, fixedNodesChildren[i], 0);
 },
 findParentNode: function(id) {
  var element = document.getElementById(id).parentNode;
  while(element && element.tagName !== "BODY") {
   if(element.id) {
    var parentNode = this.domMap[element.id];
    if(parentNode)
     return parentNode;
   }
   element = element.parentNode;
  }
  return null;
 },
 addChildNode: function(node, childNode) {
  if(!childNode.parentNode) {
   node.children.push(childNode);
   childNode.parentNode = node;
  }
 },
 insertChildNode: function(node, childNode, index) {
  if(!childNode.parentNode) {
   ASPx.Data.ArrayInsert(node.children, childNode, index);
   childNode.parentNode = node;
  }
 },
 addRelatedNode: function(node, relatedNode) {
  this.addChildNode(node, relatedNode);
  relatedNode.mainNode = node;
 },
 isFixedNode: function(node) {
  var control = node.mainNode ? node.mainNode.control : node.control;
  return control && control.HasFixedPosition();
 },
 createNode: function(domElementID, control) {
  var node = {
   control: control,
   children: [],
   parentNode: null,
   mainNode: null
  };
  if(domElementID)
   this.domMap[domElementID] = node;
  return node;
 }
});
var ControlAdjuster = ASPx.CreateClass(null, {
 constructor: function() {
 },
 adjustControlsInHierarchy: function(controlCollection, adjustFunc, container, collapseControls, controlFilter) {
  var controlTree = new ASPx.ControlTree(controlCollection, container, controlFilter);
  this.adjustControlsInTree(controlTree.rootNode, adjustFunc, container, collapseControls);
 },
 adjustControlsInTree: function(treeNode, adjustFunc, container, collapseControls) {
  var observer = _aspxGetDomObserver();
  observer.pause(container, true);
  var documentScrollInfo;
  if(collapseControls) {
   documentScrollInfo = ASPx.GetOuterScrollPosition(document.body);
   this.collapseControls(treeNode);
  }
  var adjustNodes = [], 
   autoHeightNodes = [];
  var requireReAdjust = this.forEachControlCore(treeNode, collapseControls, adjustFunc, adjustNodes, autoHeightNodes);
  if(requireReAdjust)
   this.forEachControlsBackward(adjustNodes, collapseControls, adjustFunc);
  else {
   for(var i = 0, node; node = autoHeightNodes[i]; i++)
    node.control.AdjustAutoHeight();
  }
  if(collapseControls)
   ASPx.RestoreOuterScrollPosition(documentScrollInfo);
  observer.resume(container, true);
 },
 forEachControlCore: function(node, collapseControls, processFunc, adjustNodes, autoHeightNodes) {
  var requireReAdjust = false,
   size, newSize;
  if(node.control) {
   var checkReadjustment = collapseControls && node.control.IsControlCollapsed() && node.control.CanCauseReadjustment();
   if(checkReadjustment)
    size = node.control.GetControlPercentMarkerSize(false, true);
   if(node.control.IsControlCollapsed() && !node.control.IsExpandableByAdjustment())
    node.control.ExpandControl();
   node.control.isInsideHierarchyAdjustment = true;
   processFunc(node.control);
   node.control.isInsideHierarchyAdjustment = false;
   if(checkReadjustment) {
    newSize = node.control.GetControlPercentMarkerSize(false, true);
    requireReAdjust = size.width !== newSize.width;
   }
   if(node.control.sizingConfig.supportAutoHeight)
    autoHeightNodes.push(node);
   node.control.ResetControlPercentMarkerSize();
  }
  for(var childNode, i = 0; childNode = node.children[i]; i++)
   requireReAdjust = this.forEachControlCore(childNode, collapseControls, processFunc, adjustNodes, autoHeightNodes) || requireReAdjust;
  adjustNodes.push(node);
  return requireReAdjust;
 },
 forEachControlsBackward: function(adjustNodes, collapseControls, processFunc) {
  for(var i = 0, node; node = adjustNodes[i]; i++)
   this.forEachControlsBackwardCore(node, collapseControls, processFunc);
 },
 forEachControlsBackwardCore: function(node, collapseControls, processFunc) {
  if(node.control)
   processFunc(node.control);
  if(node.children.length > 1) {
   for(var i = 0, childNode; childNode = node.children[i]; i++) {
    if(childNode.control)
     processFunc(childNode.control);
   }
  }
 },
 collapseControls: function(node) {
  for(var childNode, i = 0; childNode = node.children[i]; i++)
   this.collapseControls(childNode);
  if(node.control && node.control.NeedCollapseControl())
   node.control.CollapseControl();
 }
});
var controlAdjuster = null;
function GetControlAdjuster() {
 if(!controlAdjuster)
  controlAdjuster = new ControlAdjuster();
 return controlAdjuster;
}
function _aspxFunctionIsInCallstack(currentCallee, targetFunction, depthLimit) {
 var candidate = currentCallee;
 var depth = 0;
 while(candidate && depth <= depthLimit) {
  candidate = candidate.caller;
  if(candidate == targetFunction)
   return true;
  depth++;
 }
 return false;
}
ASPx.attachToReady(aspxClassesWindowOnLoad);
function aspxClassesWindowOnLoad(){
 ASPx.documentLoaded = true;
 _aspxMoveLinkElements();
 _aspxSweepDuplicatedLinks();
 ResourceManager.SynchronizeResources();
 var externalScriptProcessor = GetExternalScriptProcessor();
 if(externalScriptProcessor)
  externalScriptProcessor.ShowErrorMessages();
 ASPx.AccessibilityUtils.initialize();
 ASPx.GetControlCollection().Initialize();
 _aspxInitializeScripts();
 _aspxInitializeLinks();
 _aspxInitializeFocus();
 ASPx.GetControlCollection().FinalizeInitialization();
}
Ident = { };
Ident.IsDate = function(obj) {
 return obj && obj.constructor == Date;
};
Ident.IsRegExp = function(obj) {
 return obj && obj.constructor === RegExp;
};
Ident.IsArray = function(obj) {
 return obj && obj.constructor == Array;
};
Ident.IsASPxClientCollection = function(obj) {
 return obj && obj.isASPxClientCollection;
};
Ident.IsASPxClientControl = function(obj) {
 return obj && obj instanceof ASPxClientControlBase;
};
Ident.IsASPxClientEdit = function(obj) {
 return obj && obj.isASPxClientEdit;
};
Ident.IsFocusableElementRegardlessTabIndex = function (element) {
 var tagName = element.tagName;
 return tagName == "TEXTAREA" || tagName == "INPUT" || tagName == "A" ||
  tagName == "SELECT" || tagName == "IFRAME" || tagName == "OBJECT" || tagName == "BUTTON";
};
Ident.isDialogInvisibleControl = function(control) {
 return !!ASPx.Dialog && ASPx.Dialog.isDialogInvisibleControl(control);
};
Ident.isBatchEditUnusedEditor = function(control) {
 return !!ASPx.BatchEditHelper && ASPx.BatchEditHelper.isBatchEditUnusedEditor(control);
};
Ident.scripts = {};
if(ASPx.IsFunction(window.WebForm_InitCallbackAddField)) {
 (function() {
  var original = window.WebForm_InitCallbackAddField;
  window.WebForm_InitCallbackAddField = function(name, value) {
   if(typeof(name) == "string" && name)
    original.apply(null, arguments);
  };
 })();
}
ASPx.FireDefaultButton = function(evt, buttonID) {
 if(_aspxIsDefaultButtonEvent(evt, buttonID)) {
  var defaultButton = ASPx.GetElementById(buttonID);
  if(defaultButton && defaultButton.click) {
   if(ASPx.IsFocusable(defaultButton))
    defaultButton.focus();
   ASPx.Evt.DoElementClick(defaultButton);
   ASPx.Evt.PreventEventAndBubble(evt);
   return false;
  }
 }
 return true;
};
function _aspxIsDefaultButtonEvent(evt, defaultButtonID) {
 if(evt.keyCode != ASPx.Key.Enter)
  return false;
 var srcElement = ASPx.Evt.GetEventSource(evt);
 if(!srcElement || srcElement.id === defaultButtonID)
  return true;
 var tagName = srcElement.tagName;
 var type = srcElement.type;
 return tagName != "TEXTAREA" && tagName != "BUTTON" && tagName != "A" &&
  (tagName != "INPUT" || type != "checkbox" && type != "radio" && type != "button" && type != "submit" && type != "reset");
}
var PostHandler = ASPx.CreateClass(null, {
 constructor: function() {
  this.Post = new ASPxClientEvent();
  this.PostFinalization = new ASPxClientEvent();
  this.observableForms = [];
  this.dxCallbackTriggers = {};
  this.lastSubmitElementName = null;
  this.beforeOnSubmit = function() { };
  this.ReplaceGlobalPostFunctions();
  this.HandleDxCallbackBeginning();
  this.HandleMSAjaxRequestBeginning();
 },
 Update: function() {
  this.ReplaceFormsSubmit(true);
 },
 ProcessPostRequest: function(ownerID, isCallback, isMSAjaxRequest, isDXCallback) {
  this.cancelPostProcessing = false;
  this.isMSAjaxRequest = isMSAjaxRequest;
  if(this.SkipRaiseOnPost(ownerID, isCallback, isDXCallback))
   return;
  var args = new PostHandlerOnPostEventArgs(ownerID, isCallback, isMSAjaxRequest, isDXCallback);
  this.Post.FireEvent(this, args);
  this.cancelPostProcessing = args.cancel;
  if(!args.cancel)
   this.PostFinalization.FireEvent(this, args);
 },
 SkipRaiseOnPost: function(ownerID, isCallback, isDXCallback) { 
  if(!isCallback)
   return false;
  var dxOwner = isDXCallback && ASPx.GetControlCollection().GetByName(ownerID);
  if(dxOwner) {
   this.dxCallbackTriggers[dxOwner.uniqueID] = true;
   return false;
  }
  if(this.dxCallbackTriggers[ownerID]) {
   this.dxCallbackTriggers[ownerID] = false;
   return true;
  }
  return false;
 },
 ReplaceGlobalPostFunctions: function() {
  if(ASPx.IsFunction(window.__doPostBack))
   this.ReplaceDoPostBack();
  if(ASPx.IsFunction(window.WebForm_DoCallback))
   this.ReplaceDoCallback();
  if(ASPx.IsFunction(window.WebForm_ExecuteCallback))
   this.ReplaceExecuteCallback();
  this.ReplaceFormsSubmit();
 },
 HandleDxCallbackBeginning: function() {
  ASPx.GetControlCollection().BeforeInitCallback.AddHandler(function(s, e) {
   aspxRaisePostHandlerOnPost(e.callbackOwnerID, true, false, true); 
  });
 },
 HandleMSAjaxRequestBeginning: function() {
  var pageRequestManager = ASPx.GetMSAjaxRequestManager();
  if(pageRequestManager != null && Ident.IsArray(pageRequestManager._onSubmitStatements)) {
   pageRequestManager._onSubmitStatements.unshift(function() {
    var postbackSettings = Sys.WebForms.PageRequestManager.getInstance()._postBackSettings;
    var postHandler = aspxGetPostHandler();
    aspxRaisePostHandlerOnPost(postbackSettings.asyncTarget, true, true);
    return !postHandler.cancelPostProcessing;
   });
  }
 },
 ReplaceDoPostBack: function() {
  var original = __doPostBack;
  __doPostBack = function(eventTarget, eventArgument) {
   var postHandler = aspxGetPostHandler();
   aspxRaisePostHandlerOnPost(eventTarget);
   if(postHandler.cancelPostProcessing)
    return;
   ASPxClientControl.postHandlingLocked = true;
   original(eventTarget, eventArgument);
   delete ASPxClientControl.postHandlingLocked;
  };
 },
 ReplaceDoCallback: function() {
  var original = WebForm_DoCallback;
  WebForm_DoCallback = function(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) {
   var postHandler = aspxGetPostHandler();
   aspxRaisePostHandlerOnPost(eventTarget, true);
   if(postHandler.cancelPostProcessing)
    return;
   return original(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync);
  };
 },
 ReplaceExecuteCallback: function() {
  var original = WebForm_ExecuteCallback;
  var handler = this;
  WebForm_ExecuteCallback = function(callbackObject) {
   var isDxCallback = callbackObject && callbackObject.context && ASPx.GetControlCollection().Get(callbackObject.context) !== null;
   ASPx.callbackProcessed = false;
   original(callbackObject);
   if(ASPx.Browser.Firefox && document.getElementById("__EVENTVALIDATION")) {
    var viewStateField = document.getElementById("__VIEWSTATE");
    if(viewStateField) {
     var response = callbackObject.xmlRequest.responseText;
     var separatorIndex = response.indexOf("|");
     var validationFieldLength = separatorIndex > 0 ? response.substring(0, separatorIndex) : null;
     if(ASPx.IsNumber(validationFieldLength))
      viewStateField.value = viewStateField.value; 
    }
   }
   if(isDxCallback && !ASPx.callbackProcessed) {
    var request = callbackObject.xmlRequest;
    if(handler.HasAppErrorOnCallback(request) && ASPxClientUtils.IsExists(callbackObject.eventCallback))
     callbackObject.eventCallback(handler.GetServerErrorText(), callbackObject.context);
   }
  };
 },
 HasAppErrorOnCallback: function(request) {
  if(!request) return false;
  var isServerError = request.status && request.status == 500;
  var pattern = /<html[^>]*>([\w|\W]*)<\/html>/im;
  var text = request.responseText;
  return isServerError && !!text && pattern.test(text);
 },
 GetServerErrorText: function() {
  return "Internal Server Error";
 }, 
 ReplaceFormsSubmit: function(checkObservableCollection) {
  for(var i = 0; i < document.forms.length; i++) { 
   var form = document.forms[i];
   if(checkObservableCollection && ASPx.Data.ArrayIndexOf(this.observableForms, form) >= 0)
    continue;
   if(form.submit)
    this.ReplaceFormSubmit(form);
   this.ReplaceFormOnSumbit(form);
   this.observableForms.push(form);
  }
 },
 ReplaceFormSubmit: function(form) {
  var originalSubmit = form.submit;
  form.submit = function() {
   var postHandler = aspxGetPostHandler();
   aspxRaisePostHandlerOnPost();
   if(postHandler.cancelPostProcessing)
    return false;
   var callee = arguments.callee;
   this.submit = originalSubmit;
   var submitResult = this.submit();
   this.submit = callee;
   return submitResult;
  };
  form = null;
 },
 ReplaceFormOnSumbit: function(form) {
  var originalSubmit = form.onsubmit;
  form.onsubmit = function() {
   var postHandler = aspxGetPostHandler();
   postHandler.beforeOnSubmit();
   if(postHandler.isMSAjaxRequest)
    postHandler.isMsAjaxRequest = false;
   else
    aspxRaisePostHandlerOnPost(postHandler.GetLastSubmitElementName());
   if(postHandler.cancelPostProcessing)
    return false;
   return ASPx.IsFunction(originalSubmit)
    ? originalSubmit.apply(this, arguments)
    : true;
  };
  form = null;
 },
 SetBeforeOnSubmit: function(action) {
  this.beforeOnSubmit = action;
 },
 SetLastSubmitElementName: function(elementName) {
  this.lastSubmitElementName = elementName;
 },
 GetLastSubmitElementName: function() {
  return this.lastSubmitElementName;
 },
 RemoveDisposedFormsFromCache: function(){
  for(var i = 0; this.observableForms && i < this.observableForms.length; i++){
   var form = this.observableForms[i];
   if(!ASPx.IsExistsElement(form)){
    ASPx.Data.ArrayRemove(this.observableForms, form);
    i--;
   }
  }
 }
});
function aspxRaisePostHandlerOnPost(ownerID, isCallback, isMSAjaxRequest, isDXCallback) {
 if(ASPxClientControl.postHandlingLocked) return;
 var postHandler = aspxGetPostHandler();
 if(postHandler)
  postHandler.ProcessPostRequest(ownerID, isCallback, isMSAjaxRequest, isDXCallback);
}
var aspxPostHandler;
function aspxGetPostHandler() {
 if(!aspxPostHandler)
  aspxPostHandler = new PostHandler();
 return aspxPostHandler;
}
var PostHandlerOnPostEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(ownerID, isCallback, isMSAjaxCallback, isDXCallback){
  this.constructor.prototype.constructor.call(this);
  this.ownerID = ownerID;
  this.isCallback = !!isCallback;
  this.isDXCallback = !!isDXCallback;
  this.isMSAjaxCallback = !!isMSAjaxCallback;
 }
});
var ResourceManager = {
 HandlerStr: "DXR.axd?r=",
 ResourceHashes: {},
 SynchronizeResources: function(method){
  if(!method){
   method = function(name, resource) { 
    this.UpdateInputElements(name, resource); 
   }.aspxBind(this);
  }
  var resources = this.GetResourcesData();
  for(var name in resources)
   if(resources.hasOwnProperty(name))
    method(name, resources[name]);
 },
 GetResourcesData: function(){
  return {
   DXScript: this.GetResourcesElementsString(_aspxGetIncludeScripts(), "src", "DXScript"),
   DXCss: this.GetResourcesElementsString(_aspxGetLinks(), "href", "DXCss")
  };
 },
 ParseBundleSrc: function(elements, urlAttr){
  var timeStamp = "";
  var resourceUrlArray = [];
  for(var i = 0; i < elements.length; i++) {
   var resourceUrl = ASPx.Attr.GetAttribute(elements[i], urlAttr);
   if(resourceUrl) {
    var pos = resourceUrl.indexOf(this.HandlerStr);
    if(pos > -1){
     var list = resourceUrl.substr(pos + this.HandlerStr.length);
     var ampPos = list.lastIndexOf("-");
     if(ampPos > -1) {
      timeStamp = list.substr(ampPos);
      list = list.substr(0, ampPos);
     }
     var indexes = list.split(",");
     for(var j = 0; j < indexes.length; j++) {
      resourceUrlArray.push(indexes[j]);
     }
    }
    else
     resourceUrlArray.push(resourceUrl);
   }
  }
  return {
   'resourceUrlArray': resourceUrlArray,
   'timeStamp': timeStamp
  };
 },
 GetResourceHashes: function (id) {
  if (!this.ResourceHashes[id])
   this.ResourceHashes[id] = {};
  return this.ResourceHashes[id];
 },
 GetResourcesElementsString: function (elements, urlAttr, id) {
  var hash = this.GetResourceHashes(id);
  var resourceUrlArray = this.ParseBundleSrc(elements, urlAttr).resourceUrlArray;
  for(var i = 0; i < resourceUrlArray.length; i++) {
   hash[resourceUrlArray[i]] = resourceUrlArray[i];
  }
  var array = [];
  for(var key in hash)
   if(hash.hasOwnProperty(key))
    array.push(key);
  return array.join(",");
 },
 GetNewResourcesElementString: function (element, urlAttr, id) {
  var originalUrl = ASPx.Attr.GetAttribute(element, urlAttr);
  var handlerStrIndex = originalUrl.indexOf(this.HandlerStr);
  var dxResources = handlerStrIndex > -1;
  if(!dxResources) return element[urlAttr];
  var hash = this.GetResourceHashes(id);
  var srcInfo = this.ParseBundleSrc([element], urlAttr);
  var resourceUrlArray = srcInfo.resourceUrlArray;
  var timeStamp = srcInfo.timeStamp;
  var newResourceArray = [];
  for(var i = 0; i < resourceUrlArray.length; i++) {
    if(!hash[resourceUrlArray[i]])
    newResourceArray.push(resourceUrlArray[i]);
  }
  var newResources = "";
  if(newResourceArray.length > 0) {
   var baseUrl = originalUrl.substr(0, handlerStrIndex);
   newResources = baseUrl + this.HandlerStr + newResourceArray.join(",") + timeStamp;
  }
  return newResources;
 },
 UpdateInputElements: function(typeName, list){
  for(var i = 0; i < document.forms.length; i++){
   var inputElement = document.forms[i][typeName];
   if(!inputElement)
    inputElement = this.CreateInputElement(document.forms[i], typeName);
   inputElement.value = list;
  }
 },
 CreateInputElement: function(form, typeName){
  var inputElement = ASPx.CreateHiddenField(typeName);
  form.appendChild(inputElement);
  return inputElement;
 }
};
ASPx.includeScriptPrefix = "dxis_";
ASPx.startupScriptPrefix = "dxss_";
var includeScriptsCache = {};
var createdIncludeScripts = [];
var appendedScriptsCount = 0;
var callbackOwnerNames = [];
var scriptsRestartHandlers = { };
function _aspxIsKnownIncludeScript(script) {
 return !!includeScriptsCache[script.src];
}
function _aspxCacheIncludeScript(script) {
 includeScriptsCache[script.src] = 1;
}
function _aspxProcessScriptsAndLinks(ownerName, isCallback) {
 if(!ASPx.documentLoaded) return; 
 _aspxProcessScripts(ownerName, isCallback);
 getLinkProcessor().process();
 ASPx.ClearCachedCssRules();
}
function _aspxGetStartupScripts(container) {
 return _aspxGetScriptsCore(ASPx.startupScriptPrefix, container);
}
function _aspxGetIncludeScripts() {
 return _aspxGetScriptsCore(ASPx.includeScriptPrefix);
}
function _aspxGetScriptsCore(prefix, container) {
 var result = [];
 var scripts;
 if(ASPx.IsExists(container))
  scripts = ASPx.GetNodesByTagName(container, "SCRIPT");
 else
  scripts = document.getElementsByTagName("SCRIPT");
 for(var i = 0; i < scripts.length; i++) {
  if(scripts[i].id.indexOf(prefix) == 0)
   result.push(scripts[i]);
 }
 return result;
}
function _aspxIsResourceLink(link) {
 if(typeof link !== "string")
  link = link.href;
 return link.toLowerCase().indexOf(ResourceManager.HandlerStr.toLowerCase()) >= 0;
}
function _aspxGetLinks(allLinks) {
 var result = [];
 var links = document.getElementsByTagName("LINK");
 for(var i = 0; i < links.length; i++) {
  if(allLinks || _aspxIsResourceLink(links[i]))
   result.push(links[i]);
 }
 return result;
}
function _aspxIsLinksLoaded() {
 var links = _aspxGetLinks(true);
 for(var i = 0, link; link = links[i]; i++)
  if(link.readyState && link.readyState.toLowerCase() == "loading")
    return false;
 return true;
}
function _aspxInitializeLinks() {
 var links = _aspxGetLinks(true);
 for(var i = 0; i < links.length; i++)
  links[i].loaded = true; 
}
var scriptExecutedAttrName = "data-executed";
var scriptDelayedExecutionAttrName = "data-dx-delayedeval";
ASPx.MarkInnerScriptBlocksAsDelayedExecution = function(scriptsContainer) {
 var scripts = scriptsContainer.querySelectorAll("script[id^=" + ASPx.startupScriptPrefix + "]");
 for(var i = 0; i < scripts.length; i++)
  ASPx.Attr.SetAttribute(scripts[i], scriptDelayedExecutionAttrName, true);
};
function isScriptExecuted(script) {
 return ASPx.Attr.GetAttribute(script, scriptExecutedAttrName);
}
function markScriptAsExecuted(script) {
 if(ASPx.Attr.GetAttribute(script, scriptDelayedExecutionAttrName))
  ASPx.Attr.RemoveAttribute(script, scriptDelayedExecutionAttrName);
 else
  ASPx.Attr.SetAttribute(script, scriptExecutedAttrName, true);
}
function _aspxInitializeScripts() {
 var scripts = _aspxGetIncludeScripts();
 for(var i = 0; i < scripts.length; i++)
  _aspxCacheIncludeScript(scripts[i]);   
 var startupScripts = _aspxGetStartupScripts();
 for(var i = 0; i < startupScripts.length; i++)
  markScriptAsExecuted(startupScripts[i]);
}
function _aspxSweepDuplicatedLinks() {
 var hash = { };
 var links = _aspxGetLinks();
 for(var i = 0; i < links.length; i++) {
  var href = links[i].href;
  if(!href)
   continue;
  if(hash[href]){
   if(!hash[href].loaded && links[i].loaded) {
    ASPx.RemoveElement(hash[href]);
    hash[href] = links[i];
   }
   else
    ASPx.RemoveElement(links[i]);
  }
  else
   hash[href] = links[i];
 }
}
function _aspxSweepDuplicatedScripts() {
 var hash = { };
 var scripts = _aspxGetIncludeScripts();
 for(var i = 0; i < scripts.length; i++) {
  var src = scripts[i].src;
  if(!src) continue;
  if(hash[src])
   ASPx.RemoveElement(scripts[i]);
  else
   hash[src] = scripts[i];
 }
}
function _aspxAreScriptsEqual(script1, script2) {
 return script1.src == script2.src;
}
function _aspxProcessScripts(ownerName, isCallback) {
 var scripts = _aspxGetIncludeScripts();
 var previousCreatedScript = null;
 var firstCreatedScript = null;
 for(var i = 0; i < scripts.length; i++) {
  var script = scripts[i];
  if(script.src == "") continue; 
  if(_aspxIsKnownIncludeScript(script))
   continue;
  var getOnlyNewResources = true;
  var onlyNewScripts = ResourceManager.GetNewResourcesElementString(script, "src", "DXScript", getOnlyNewResources);
  if (onlyNewScripts == "")
   continue;
  var createdScript = document.createElement("script");
  ASPx.Attr.AppendScriptType(createdScript);
  createdScript.src = onlyNewScripts;
  createdScript.id = script.id;
  if(ASPx.Data.ArrayIndexOf(createdIncludeScripts, createdScript, _aspxAreScriptsEqual) >= 0)
   continue;
  createdIncludeScripts.push(createdScript);
  ASPx.RemoveElement(script);
  if(ASPx.Browser.Edge || ASPx.Browser.WebKitFamily || (ASPx.Browser.Firefox && ASPx.Browser.Version >= 4) || ASPx.Browser.IE) {
   createdScript.onload = new Function("ASPx.OnScriptLoadCallback(this, " + isCallback + ");");
   if(firstCreatedScript == null)
    firstCreatedScript = createdScript;
   createdScript.nextCreatedScript = null;
   if(previousCreatedScript != null)
    previousCreatedScript.nextCreatedScript = createdScript;
   previousCreatedScript = createdScript;
  } else {
   createdScript.onload = new Function("ASPx.OnScriptLoadCallback(this);");
   ASPx.AppendScript(createdScript);
   _aspxCacheIncludeScript(createdScript);
  }
 }
 if(firstCreatedScript != null) {
  ASPx.AppendScript(firstCreatedScript);
  _aspxCacheIncludeScript(firstCreatedScript);
 }
 if(isCallback)
  callbackOwnerNames.push(ownerName);
 if(createdIncludeScripts.length == 0) {
  var newLinks = ASPx.GetNodesByTagName(document.body, "link");
  var needProcessLinks = isCallback && newLinks.length > 0;
  if(needProcessLinks)
   needProcessLinks = getLinkProcessor().addLinks(newLinks);
  if(!needProcessLinks)
   ASPx.FinalizeScriptProcessing(isCallback);
 }
}
ASPx.FinalizeScriptProcessing = function(isCallback) {
 createdIncludeScripts = [];
 appendedScriptsCount = 0;
 var linkProcessor = getLinkProcessor();
 if(linkProcessor.hasLinks())
  _aspxSweepDuplicatedLinks();
 linkProcessor.reset();
 _aspxSweepDuplicatedScripts();
 ResourceManager.SynchronizeResources();
 _aspxRunStartupScripts(isCallback);
};
var startupScriptsRunning = false;
function _aspxRunStartupScripts(isCallback, container) {
 startupScriptsRunning = true;
 try {
  _aspxRunStartupScriptsCore(container);
 }
 finally {
  startupScriptsRunning = false;
 }
 if(ASPx.documentLoaded) {
  ASPx.GetControlCollection().ProcessActionByPredicate(
   function(collection) { collection.InitializeElements(isCallback); },
   function(control) { return !ASPx.IsExists(container) || ASPx.GetIsParent(container, control.GetMainElement()); }
  );
  for(var key in scriptsRestartHandlers)
   if(scriptsRestartHandlers.hasOwnProperty(key))
    scriptsRestartHandlers[key]();
  if(isCallback)
   _aspxRunEndCallbackScript();
 }
}
function _aspxIsStartupScriptsRunning(isCallback) {
 return startupScriptsRunning;
}
function _aspxRunStartupScriptsCore(container) {
 var scripts = _aspxGetStartupScripts(container);
 var code;
 for(var i = 0; i < scripts.length; i++){
  var script = scripts[i];
  if(!isScriptExecuted(script)) {
   _aspxEnsureStartupScriptIsUnique(script.id); 
   code = ASPx.GetScriptCode(script);
   eval(code);
   markScriptAsExecuted(script);
  }
 }
}
function _aspxEnsureStartupScriptIsUnique(scriptId) {
 if(!scriptId)
  return;
 var scriptExecutedSelector = "script[" + scriptExecutedAttrName + "='true']#" + scriptId;
 ASPx.RemoveElement(document.querySelector(scriptExecutedSelector));
}
function _aspxRunEndCallbackScript() {
 while(callbackOwnerNames.length > 0) {
  var callbackOwnerName = callbackOwnerNames.pop();
  var callbackOwner = ASPx.GetControlCollection().Get(callbackOwnerName);
  if(callbackOwner)
   callbackOwner.DoEndCallback();
 }
}
ASPx.RunStartupScriptsCreatedOnClient = function(container) {
 _aspxRunStartupScriptsCore(container);
};
ASPx.OnScriptReadyStateChangedCallback = function(scriptElement, isCallback) {
 if(scriptElement.readyState == "loaded") {
  _aspxCacheIncludeScript(scriptElement);
  for(var i = 0; i < createdIncludeScripts.length; i++) {
   var script = createdIncludeScripts[i];
   if(_aspxIsKnownIncludeScript(script)) {
    if(!isScriptExecuted(script)) {
     markScriptAsExecuted(script);
     ASPx.AppendScript(script);
     appendedScriptsCount++;
    }
   } else
    break;
  }
  if(createdIncludeScripts.length == appendedScriptsCount)
   ASPx.FinalizeScriptProcessing(isCallback);
 }
};
ASPx.OnScriptLoadCallback = function(scriptElement, isCallback) {
 appendedScriptsCount++;
 if(scriptElement.nextCreatedScript) {
  ASPx.AppendScript(scriptElement.nextCreatedScript);
  _aspxCacheIncludeScript(scriptElement.nextCreatedScript);
 }
 if(createdIncludeScripts.length == appendedScriptsCount)
  ASPx.FinalizeScriptProcessing(isCallback);
};
function _aspxAddScriptsRestartHandler(objectName, handler) {
 scriptsRestartHandlers[objectName] = handler;
}
function _aspxMoveLinkElements() {
 var head = ASPx.GetNodesByTagName(document, "head")[0];
 var bodyLinks = ASPx.GetNodesByTagName(document.body, "link");
 if(head && bodyLinks.length > 0){
  var headLinks = ASPx.GetNodesByTagName(head, "link");
  var dxLinkAnchor = head.firstChild;
  for(var i = 0; i < headLinks.length; i++){
   if(_aspxIsResourceLink(headLinks[i]))
    dxLinkAnchor = headLinks[i].nextSibling;
  }
  while(bodyLinks.length > 0) 
   head.insertBefore(bodyLinks[0], dxLinkAnchor);
 }
}
var LinkProcessor = ASPx.CreateClass(null, {
 constructor: function() {
  this.linkInfos = [];
  this.loadingObservationTimerID = -1;
 },
 process: function() {
  if(this.hasLinks()) {
   if(this.isLinkLoadEventSupported())
    this.processViaLoadEvent();
   else
    this.processViaTimer();
  }
  else
   _aspxSweepDuplicatedLinks();
  _aspxMoveLinkElements();
 },
 addLinks: function(links) {
  var prevLinkCount = this.linkInfos.length;
  for(var i = 0; i < links.length; i++) {
   var link = links[i];
   if(link.loaded || link.rel != "stylesheet" || !_aspxIsResourceLink(link))
    continue;
   var linkInfo = {
    link: link,
    href: link.href
   };
   this.linkInfos.push(linkInfo);
  }
  return prevLinkCount != this.linkInfos.length;
 },
 hasLinks: function() {
  return this.linkInfos.length > 0;
 },
 reset: function() {
  this.linkInfos = [];
 },
 processViaLoadEvent: function() {
  for(var i = 0, linkInfo; linkInfo = this.linkInfos[i]; i++)
   linkInfo.link.onload = this.onLinkLoad.bind(this);
 },
 isLinkLoadEventSupported: function() {
  return !(ASPx.Browser.Chrome && ASPx.Browser.MajorVersion < 19 || ASPx.Browser.Firefox && ASPx.Browser.MajorVersion < 9 ||
   ASPx.Browser.Safari && ASPx.Browser.MajorVersion < 6 || ASPx.Browser.AndroidDefaultBrowser && ASPx.Browser.MajorVersion < 4.4);
 },
 processViaTimer: function() {
  if(this.loadingObservationTimerID == -1)
   this.onLinksLoadingObserve();
 },
 onLinksLoadingObserve: function() {
  if(this.getIsAllLinksLoaded()) {
   this.loadingObservationTimerID = -1;
   this.onAllLinksLoad();
  }
  else
   this.loadingObservationTimerID = window.setTimeout(this.onLinksLoadingObserve.aspxBind(this), 100);
 },
 getIsAllLinksLoaded: function() {
  var styleSheets = document.styleSheets;
  var loadedLinkHrefs = { };
  for(var i = 0; i < styleSheets.length; i++) {
   var styleSheet = styleSheets[i];
   try {
    if(styleSheet.cssRules)
     loadedLinkHrefs[styleSheet.href] = 1;
   }
   catch(ex) { }
  }
  var loadedLinksCount = 0;
  for(var i = 0, linkInfo; linkInfo = this.linkInfos[i]; i++) {
   if(loadedLinkHrefs[linkInfo.href])
    loadedLinksCount++;
  }
  return loadedLinksCount == this.linkInfos.length;
 },
 onAllLinksLoad: function() {
  this.reset();
  _aspxSweepDuplicatedLinks();
  if(createdIncludeScripts.length == 0)
   ASPx.FinalizeScriptProcessing(true);
 },
 onLinkReadyStateChanged: function(linkElement) {
  if(linkElement.readyState == "complete")
   this.onLinkLoadCore(linkElement);
 },
 onLinkLoad: function(evt) {
  var linkElement = ASPx.Evt.GetEventSource(evt);
  this.onLinkLoadCore(linkElement);
 },
 onLinkLoadCore: function(linkElement) {
  var linkInfo = this.getLinkInfo(linkElement);
  if(!linkInfo) return;
  linkInfo.loaded = true;
  var notLoadedLinks = this.linkInfos.filter(function(info) { return !info.loaded; });
  if(notLoadedLinks.length == 0)
   this.onAllLinksLoad();
 },
 getLinkInfo: function(linkElement) {
  for(var i = 0, linkInfo; linkInfo = this.linkInfos[i]; i++) {
   if(linkInfo.link == linkElement)
    return linkInfo;
  }
 }
});
var linkProcessor = null;
function getLinkProcessor() {
 if(linkProcessor == null)
  linkProcessor = new LinkProcessor();
 return linkProcessor;
}
ASPx.LinkProcessor = LinkProcessor;
var IFrameHelper = ASPx.CreateClass(null, {
 constructor: function(params) {
  this.params = params || {};
  this.params.src = this.params.src || "";
  this.CreateElements();
 },
 CreateElements: function() {
  var elements = IFrameHelper.Create(this.params);
  this.containerElement = elements.container;
  this.iframeElement = elements.iframe;
  this.AttachOnLoadHandler(this, this.iframeElement);
  this.SetLoading(true);
  if(this.params.onCreate)
   this.params.onCreate(this.containerElement, this.iframeElement);
 },
 AttachOnLoadHandler: function(instance, element) {
  ASPx.Evt.AttachEventToElement(element, "load", function() {
   instance.OnLoad(element);
  });
 },
 OnLoad: function(element) {
  this.SetLoading(false, element);
  if(!element.preventCustomOnLoad && this.params.onLoad)
   this.params.onLoad();
 },
 IsLoading: function(element) {
  element = element || this.iframeElement;
  if(element)
   return element.loading;
  return false;
 },
 SetLoading: function(value, element) {
  element = element || this.iframeElement;
  if(element)
   element.loading = value;
 },
 GetContentUrl: function() {
  return this.params.src;
 },
 SetContentUrl: function(url, preventBrowserCaching) {
  if(url) {
   this.params.src = url;
   if(preventBrowserCaching)
    url = IFrameHelper.AddRandomParamToUrl(url);
   this.SetLoading(true);
   this.iframeElement.src = url;
  }
 },
 RefreshContentUrl: function() {
  if(this.IsLoading())
   return;
  this.SetLoading(true);
  var oldContainerElement = this.containerElement;
  var oldIframeElement = this.iframeElement;
  var postfix = "_del" + Math.floor(Math.random()*100000).toString();
  if(this.params.id)
   oldIframeElement.id = this.params.id + postfix;
  if(this.params.name)
   oldIframeElement.name = this.params.name + postfix;
  ASPx.SetStyles(oldContainerElement, { height: 0 });
  this.CreateElements();
  oldIframeElement.preventCustomOnLoad = true;
  oldIframeElement.src = ASPx.BlankUrl;
  window.setTimeout(function() {
   oldContainerElement.parentNode.removeChild(oldContainerElement);
  }, 10000); 
 }
});
IFrameHelper.Create = function(params) {
 var iframeHtmlStringParts = [ "<iframe frameborder='0'" ];
 if(params) {
  if(params.id)
   iframeHtmlStringParts.push(" id='", params.id, "'");
  if(params.name)
   iframeHtmlStringParts.push(" name='", params.name, "'");
  if(params.title)
   iframeHtmlStringParts.push(" title='", params.title, "'");
  if(params.scrolling)
   iframeHtmlStringParts.push(" scrolling='", params.scrolling, "'");
  if(params.src)
   iframeHtmlStringParts.push(" src='", params.src, "'");
 }
 iframeHtmlStringParts.push("></iframe>");
 var containerElement = ASPx.CreateHtmlElementFromString("<div style='border-width: 0px; padding: 0px; margin: 0px'></div>");
 var iframeElement = ASPx.CreateHtmlElementFromString(iframeHtmlStringParts.join(""));
 containerElement.appendChild(iframeElement);
 return {
  container: containerElement,
  iframe: iframeElement
 };
};
IFrameHelper.AddRandomParamToUrl = function(url) {
 var prefix = url.indexOf("?") > -1
  ? "&"
  : "?";
 var param = prefix + Math.floor(Math.random()*100000).toString();
 var anchorIndex = url.indexOf("#");
 return anchorIndex == -1
  ? url + param
  : url.substr(0, anchorIndex) + param + url.substr(anchorIndex);
};
IFrameHelper.GetWindow = function(name) {
 var frameElement = document.getElementById(name);
 return (frameElement != null) ? frameElement.contentWindow : null;
};
IFrameHelper.GetDocument = function(name) {
 var frameElement = document.getElementById(name);
 return (frameElement != null) ? frameElement.contentDocument : null;
};
IFrameHelper.GetDocumentBody = function(name) {
 var doc = IFrameHelper.GetDocument(name);
 return (doc != null) ? doc.body : null;
};
IFrameHelper.GetDocumentHead = function (name) {
 var doc = IFrameHelper.GetDocument(name);
 return (doc != null) ? doc.head || doc.getElementsByTagName('head')[0] : null;
};
IFrameHelper.GetElement = function(name) {
 return document.getElementById(name);
};
var KbdHelper = ASPx.CreateClass(null, {
 constructor: function(control) {
  this.control = control;
  this.ready = false;
  this.clickHandler = this.HandleClick.bind(this);
  this.focusHandler = this.onElementFocus.bind(this);
  this.blurHandler = this.onBlur.bind(this);
 },
 Init: function() {
  if(!this.ready){
   KbdHelper.GlobalInit();
   var elements = this.getFocusableElements();
   for(var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.tabIndex = Math.max(element.tabIndex, 0);
    ASPx.Evt.AttachEventToElement(element, "click", this.clickHandler);
    ASPx.Evt.AttachEventToElement(element, "focus", this.focusHandler);
    ASPx.Evt.AttachEventToElement(element, "blur", this.blurHandler);
   }
   this.ready = true;
  }
 },
 Dispose: function() {
  if(this.ready) {
   var elements = this.getFocusableElements();
   for(var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.tabIndex = -1;
    ASPx.Evt.DetachEventFromElement(element, "click", this.clickHandler);
    ASPx.Evt.DetachEventFromElement(element, "focus", this.focusHandler);
    ASPx.Evt.DetachEventFromElement(element, "blur", this.blurHandler);
   }
   this.ready = false;
  }
 },
 onElementFocus: function(e) {
  if(!this.CanFocus(e))
   return true;
  KbdHelper.active = this;
 },
 getFocusableElements: function() {
  return [this.GetFocusableElement()]; 
 },
 GetFocusableElement: function() { return this.control.GetMainElement(); },
 canHandleNoFocusAction: function() { 
  var focusableElements = this.getFocusableElements();
  for(var i = 0; i < focusableElements.length; i++) {
   if(focusableElements[i] === _aspxGetFocusedElement())
    return false;
  }
  return true;
 },
 RequirePreventScrollOnFocus: function() { return false; },
 CanFocus: function(e) {
  var tag = ASPx.Evt.GetEventSource(e).tagName;
  return !(tag === "A" || tag === "TEXTAREA" || tag === "INPUT" || tag === "SELECT" || tag === "IFRAME" || tag === "OBJECT");
 },
 HandleClick: function(e) {
  if(!this.CanFocus(e))
   return;
  this.Focus();
 },
 Focus: function() {
  var preventScroll = this.RequirePreventScrollOnFocus();
  var savedDocumentScrollTop = preventScroll ? ASPx.GetDocumentScrollTop() : -1;
  try {
   this.GetFocusableElement().focus({ preventScroll: preventScroll });
  } catch(e) { }
  if(preventScroll && !this.IsNativePreventScrollOnFocusSupported() && savedDocumentScrollTop !== ASPx.GetDocumentScrollTop())
   ASPx.SetDocumentScrollTop(savedDocumentScrollTop);
 },
 IsNativePreventScrollOnFocusSupported: function() {
  if(this.isNativePreventScrollOnFocusSupported === undefined)
   this.isNativePreventScrollOnFocusSupported = this.CalcIsNativePreventScrollOnFocusSupported();
  return this.isNativePreventScrollOnFocusSupported;
 },
 CalcIsNativePreventScrollOnFocusSupported: function() {
  var result = false;
  try {
   ASPx.GetActiveElement().focus(Object.defineProperty({}, "preventScroll", { get: function() { result = true; } }));
  } catch(e) { result = false; }
  return result;
 },
 onBlur: function(){
  delete KbdHelper.active;
 },
 HandleKeyDown: function(e) { }, 
 HandleKeyPress: function(e) { }, 
 HandleKeyUp: function (e) { },
 HandleNoFocusAction: function(e) { },
 FocusByAccessKey: function () { }
});
KbdHelper.GlobalInit = function() {
 if(KbdHelper.ready)
  return;
 ASPx.Evt.AttachEventToDocument("keydown", KbdHelper.OnKeyDown);
 ASPx.Evt.AttachEventToDocument("keypress", KbdHelper.OnKeyPress);
 ASPx.Evt.AttachEventToDocument("keyup", KbdHelper.OnKeyUp);
 KbdHelper.ready = true; 
};
KbdHelper.swallowKey = false;
KbdHelper.accessKeys = { };
KbdHelper.ProcessKey = function(e, actionName) {
 if(!KbdHelper.active) 
  return;
 if (KbdHelper.active.canHandleNoFocusAction()) {
  KbdHelper.active["HandleNoFocusAction"](e, actionName);
  return;
 }
 var ctl = KbdHelper.active.control;
 if(ctl !== ASPx.GetControlCollection().Get(ctl.name)) {
  delete KbdHelper.active;
  return;
 }
 if(!KbdHelper.swallowKey) 
  KbdHelper.swallowKey = KbdHelper.active[actionName](e);
 if(KbdHelper.swallowKey)
  ASPx.Evt.PreventEvent(e);
};
KbdHelper.OnKeyDown = function(e) {
 KbdHelper.swallowKey = false;
 if(KbdHelper.TryAccessKey(KbdHelper.getKeyName(e)))
  ASPx.Evt.PreventEvent(e);
 else 
  KbdHelper.ProcessKey(e, "HandleKeyDown"); 
};
KbdHelper.OnKeyPress = function(e) { KbdHelper.ProcessKey(e, "HandleKeyPress"); };
KbdHelper.OnKeyUp = function(e) { KbdHelper.ProcessKey(e, "HandleKeyUp"); };
KbdHelper.RegisterAccessKey = function(obj) {
 var key;
 if(obj.accessKey)
  key = "CtrlShift" + obj.accessKey;
 else if(obj.keyTipModeShortcut)
  key = obj.keyTipModeShortcut;
 if(!key) return;
 KbdHelper.accessKeys[key.toLowerCase()] = obj.name;
};
KbdHelper.TryAccessKey = function(code) {
 var key = code.toLowerCase ? code.toLowerCase() : String.fromCharCode(code).toLowerCase();
 var name = KbdHelper.accessKeys[key];
 if(!name) return false;
 var obj = ASPx.GetControlCollection().Get(name);
 return KbdHelper.ClickAccessKey(obj);
};
KbdHelper.ClickAccessKey = function (control) {
 if (!control) return false;
 var el = control.GetMainElement();
 if (!el) return false;
 el.focus();
 setTimeout(function () {
  if (KbdHelper.active && KbdHelper.active.FocusByAccessKey)
   KbdHelper.active.FocusByAccessKey();
 }.aspxBind(this), ASPx.FOCUS_TIMEOUT);
 return true;
};
KbdHelper.getKeyName = function(e) {
 var name = "";
 if(e.altKey)
  name += "Alt";
 if(e.ctrlKey)
  name += "Ctrl";
 if(e.shiftKey)
  name += "Shift";
 var keyCode = e.key || e.code || String.fromCharCode(ASPx.Evt.GetKeyCode(e));
 if(keyCode.match(/key/i))
  name += keyCode.replace(/key/i, "");
 else if(keyCode.match(/digit/i))
  name += keyCode.replace(/digit/i, "");
 else if(keyCode.match(/arrow/i))
  name += keyCode.replace(/arrow/i, "");
 else if(keyCode.match(/ins/i))
  name += "Ins";
 else if(keyCode.match(/del/i))
  name += "Del";
 else if(keyCode.match(/back/i))
  name += "Back";
 else if(!keyCode.match(/alt/i) && !keyCode.match(/control/i) && !keyCode.match(/shift/i))
  name += keyCode;
 return name.replace(/^a-zA-Z0-9/, "");
};
AccessKeysHelper = ASPx.CreateClass(KbdHelper, {
 constructor: function (control) {
  this.constructor.prototype.constructor.call(this, control);
  this.accessKeysVisible = false;
  this.activeKey = null;
  this.accessKey = control.createAccessKey ? control.createAccessKey(control.accessKey) : new AccessKey(control.accessKey);
  this.accessKeys = this.accessKey.accessKeys;
  this.charIndex = 0;
  this.onFocusByAccessKey = null;
  this.onClose = null;
  this.manualStopProcessing = false;
  this.isActive = false;
  this.areAccessKeysShown = false;
 },
 Init: function (control) {
  KbdHelper.prototype.Init.call(this);
  KbdHelper.RegisterAccessKey(control);   
 },
 Add: function (accessKey) {
  this.accessKey.Add(accessKey);
 },
 HandleKeyDown: function (e) {
  var keyCode = ASPx.Evt.GetKeyCode(e);
  var stopProcessing = this.processKeyDown(keyCode);
  if (stopProcessing.value) {
   this.stopProcessing();
   if(this.onClosedOnEscape && (keyCode == ASPx.Key.Esc || stopProcessing.fireEvent))
    this.onClosedOnEscape();
  }
  return stopProcessing;
 },
 HandleNoFocusAction: function (e, actionName) {
  var keyCode = ASPx.Evt.GetKeyCode(e);
  if (this.onClosedOnEscape && keyCode == ASPx.Key.Esc && actionName == "HandleKeyDown")
   this.onClosedOnEscape();
 },
 Activate: function () {
  KbdHelper.ClickAccessKey(this.control);
  this.areAccessKeysShown = true;
 },
 Stop: function() {
  this.stopProcessing();
 },
 stopProcessing: function () {
  this.HideAccessKeys();
  if (KbdHelper.active && this.isActive) {
   this.isActive = false;
   KbdHelper.active.control.GetMainElement().blur();
   delete KbdHelper.active;
  }
 },
 onBlur: function() {
  if (this.manualStopProcessing) {
   this.manualStopProcessing = false;
   return;
  }
  this.HideAccessKeys();
  KbdHelper.prototype.onBlur.call(this);
 },
 processKeyDown: function (keyCode) {
  switch (keyCode) {
   case ASPx.Key.Left:
    this.TryMoveFocusLeft();
    return { value: false };
   case ASPx.Key.Right:
    this.TryMoveFocusRight();
    return { value: false };
   case ASPx.Key.Esc:
    if(this.control.hideAllPopups)
     this.control.hideAllPopups(true, true);
    if(this.activeKey)
     this.activeKey = this.activeKey.Return();
    this.charIndex = 0;
    if (!this.activeKey)
     return { value: true };
    break;
   case ASPx.Key.Enter:
    return { value: true };
   default:
    if (!ASPx.IsPrintableKey(keyCode))
     return { value: false };
    var char = String.fromCharCode(keyCode).toUpperCase();
    var needToContinue = { value: false };
    var keyResult;
    if(this.activeKey)
     keyResult = this.activeKey.TryAccessKey(char, this.charIndex, needToContinue);
    if (needToContinue.value) {
     this.charIndex++;
     return { value: false };
    }
    this.charIndex = 0;
    if(keyResult !== undefined)
     this.activeKey = keyResult;
    else
     return { value: true, fireEvent: true };
    if (!this.activeKey || !this.activeKey.accessKeys || this.activeKey.accessKeys.length == 0) {
     if (this.activeKey && this.activeKey.manualStopProcessing) {
      this.manualStopProcessing = true;
      break;
     }
     return { value: true, fireEvent: true };
    }
  }
  return { value: false };
 },
 TryMoveFocusLeft: function (modifier) {},
 TryMoveFocusRight: function (modifier) {},
 TryMoveFocusUp: function (modifier) {},
 TryMoveFocusDown: function (modifier) {},
 FocusByAccessKey: function() {
  if (this.onFocusByAccessKey)
   this.onFocusByAccessKey();
  this.HideAccessKeys();
  KbdHelper.prototype.FocusByAccessKey.call(this);
  this.activeKey = this.accessKey;
  this.activeKey.execute();
  this.isActive = true;
  this.areAccessKeysShown = true;
 },
 HideAccessKeys: function() {
  this.areAccessKeysShown = false;
  this.hideAccessKeys(this.accessKey);
 },
 Update: function() {
  this.throttleMethod(this.refresh, 100);
 },
 refresh: function() {
  if(this.activeKey && this.areAccessKeysShown) {
   this.activeKey.execute();
  }
 },
 throttleMethod: function(method, delay) {
  clearTimeout(method.timerId);
  method.timerId = setTimeout(function() {
   method.call(this);
  }.aspxBind(this), delay);
 },
 AreAccessKeysShown: function() {
  return this.areAccessKeysShown;
 },
 hideAccessKeys: function (accessKey) {
  for (var i = 0, ak; ak = accessKey.accessKeys[i]; i++) {
   this.hideAccessKeys(ak);
  }
  if (accessKey)
   accessKey.hide();
 },
 HandleClick: function(e) {
  KbdHelper.prototype.HandleClick.call(this, e);
  this.stopProcessing();
 }
});
AccessKey = ASPx.CreateClass(null, {
 constructor: function (popupItem, getPopupElement, keyTipElement, key, onlyClick, manualStopProcessing) {
  this.key = key ? key : keyTipElement ? ASPxClientUtils.Trim(ASPx.GetInnerText(keyTipElement)) : null;
  this.popupItem = popupItem;
  this.getPopupElement = getPopupElement;
  this.keyTipElement = keyTipElement;
  this.accessKeys = [];
  this.needShowChilds = true;
  this.parent = null;
  this.onlyClick = onlyClick;
  this.manualStopProcessing = manualStopProcessing;
 },
 Add: function (accessKey) {
  this.accessKeys.push(accessKey);
  accessKey.parent = this;
 },
 TryAccessKey: function (char, index, needToContinue) {
  if (!this.accessKeys || this.accessKeys.length == 0)
   return;
  for (var i = 0, accessKey; accessKey = this.accessKeys[i]; i++) {
   if (accessKey.key[index] == char && accessKey.isVisible()) {
    if (accessKey.key[index + 1]) {
     needToContinue.value = true;
    }
    else {
     accessKey.execute();
     return accessKey;
    }
   } else {
    accessKey.hide();
   }
  }
  for (var i = 0, accessKey; accessKey = this.accessKeys[i]; i++) {
   var key = accessKey.TryAccessKey(char, index, needToContinue);
   if (key)
    return key;
  }
  return;
 },
 isVisible: function(){
  return ASPx.GetElementVisibility(this.keyTipElement);
 },
 Return: function () {
  this.hideChildAccessKeys();
  if (this.parent) {
   this.parent.showAccessKeys(true);
  }  
  return this.parent;
 },
 execute: function () {
  this.hideAll();
  if (this.popupItem && this.popupItem.accessKeyClick && !this.onlyClick)
   this.popupItem.accessKeyClick();
  if (this.getPopupElement && this.onlyClick)
   ASPx.Evt.EmulateMouseClick(this.getPopupElement(this.popupItem));
  if (this.accessKeys)
   setTimeout(function () {
    this.showAccessKeys(true);
   }.aspxBind(this), 100);
 },
 showAccessKeys: function(directShow) {
  if (!directShow && !this.needShowChilds)
   return;
  for (var i = 0; i < this.accessKeys.length; i++) {
   var accessKey = this.accessKeys[i];
   if (accessKey) {
    var popupElement = accessKey.getPopupElement ? accessKey.getPopupElement(accessKey.popupItem) : null;
    if (popupElement && this.isElementVisible(popupElement)) {
     this.show(accessKey);
    }
    accessKey.showAccessKeys();
   }
  }
 },
 isElementVisible: function (el) { return ASPx.IsElementVisible(el, true); },
 show: function(accessKey) {
  var keyTipElement = accessKey.keyTipElement;
  var popupElement = accessKey.getPopupElement(accessKey.popupItem);
  this.showKeyTipElement(keyTipElement, this.calculateCoordinates(accessKey, keyTipElement, popupElement));
 },
 showKeyTipElement: function (keyTipElement, coordinates) {
  ASPx.SetAbsoluteY(keyTipElement, coordinates.top);
  ASPx.SetAbsoluteX(keyTipElement, coordinates.left);
  ASPx.SetElementVisibility(keyTipElement, true); 
 },
 calculateCoordinates: function (accessKey, keyTipElement, popupElement) {
  var top = ASPx.GetAbsolutePositionY(popupElement);
  var left = ASPx.GetAbsolutePositionX(popupElement);
  if (accessKey.popupItem.getAccessKeyPosition)
   switch (accessKey.popupItem.getAccessKeyPosition()) {
    case "AboveRight":
     left = left + popupElement.offsetWidth - keyTipElement.offsetWidth / 3;
     top = top - keyTipElement.offsetHeight / 2;
     break;
    case "Right":
     left = left + popupElement.offsetWidth - keyTipElement.offsetWidth / 3;
     top = top + popupElement.offsetHeight / 2 - keyTipElement.offsetHeight / 2;
     break;
    case "BelowRight":
     left = left + popupElement.offsetWidth - keyTipElement.offsetWidth / 3;
     top = top + keyTipElement.offsetHeight / 2;
     break;
    default:
     top = top + popupElement.offsetHeight;
     left = left + popupElement.offsetWidth / 2 - keyTipElement.offsetWidth / 2;
     break;
   }
  else {
   top = top + popupElement.offsetHeight;
   left = left + popupElement.offsetWidth / 2 - keyTipElement.offsetWidth / 2;
  }
  return { top: top, left: left };
 },
 hide: function() {
  if (this.keyTipElement)
   ASPx.SetElementVisibility(this.keyTipElement, false);
 },
 hideChildAccessKeys: function () {
  this.hideAccessKeys(this.accessKeys);
 },
 hideAccessKeys: function (accessKeys) {
  if (accessKeys) {
   for (var i = 0, accessKey; accessKey = accessKeys[i]; i++) {
    if (accessKey.keyTipElement)
     accessKey.hide();
    accessKey.hideChildAccessKeys();
   }
  }
 },
 hideAll: function () {
  this.getRoot(this).hideChildAccessKeys();
 },
 getRoot: function (accessKey) {
  if (!accessKey.parent)
   return accessKey;
  return this.getRoot(accessKey.parent);
 }
});
var focusedElement = null;
function aspxOnElementFocused(evt) {
 evt = ASPx.Evt.GetEvent(evt);
 if(evt && evt.target)
  focusedElement = evt.target;
}
function _aspxInitializeFocus() {
 if(!ASPx.GetActiveElement())
  ASPx.Evt.AttachEventToDocument("focus", aspxOnElementFocused);
}
function _aspxGetFocusedElement() {
 var activeElement = ASPx.GetActiveElement();
 return activeElement ? activeElement : focusedElement;
}
CheckBoxCheckState = {
 Checked : "Checked",
 Unchecked : "Unchecked",
 Indeterminate : "Indeterminate"
};
CheckBoxInputKey = { 
 Checked : "C",
 Unchecked : "U",
 Indeterminate : "I"
};
var CheckableElementStateController = ASPx.CreateClass(null, {
 constructor: function(imageProperties) {
  this.checkBoxStates = [];
  this.imageProperties = imageProperties;
  this.customImageMarkerClassName = "dxcbCI";
 },
 GetValueByInputKey: function(inputKey) {
  return this.GetFirstValueBySecondValue("Value", "StateInputKey", inputKey);
 },
 GetInputKeyByValue: function(value) {
  return this.GetFirstValueBySecondValue("StateInputKey", "Value", value);
 },
 GetImagePropertiesNumByInputKey: function(value) {
  return this.GetFirstValueBySecondValue("ImagePropertiesNumber", "StateInputKey", value);
 },
 GetNextCheckBoxValue: function(currentValue, allowGrayed) {
  var currentInputKey = this.GetInputKeyByValue(currentValue);
  var nextInputKey = '';
  switch(currentInputKey) {
   case CheckBoxInputKey.Checked:
    nextInputKey = CheckBoxInputKey.Unchecked; break;
   case CheckBoxInputKey.Unchecked:
    nextInputKey = allowGrayed ? CheckBoxInputKey.Indeterminate : CheckBoxInputKey.Checked; break;
   case CheckBoxInputKey.Indeterminate:
    nextInputKey = CheckBoxInputKey.Checked; break;
  }
  return this.GetValueByInputKey(nextInputKey);
 },
 GetCheckStateByInputKey: function(inputKey) {
  switch(inputKey) {
   case CheckBoxInputKey.Checked: 
    return CheckBoxCheckState.Checked;
   case CheckBoxInputKey.Unchecked: 
    return CheckBoxCheckState.Unchecked;
   case CheckBoxInputKey.Indeterminate: 
    return CheckBoxCheckState.Indeterminate;
  }
 },
 GetValueByCheckState: function(checkState) {
  switch(checkState) {
   case CheckBoxCheckState.Checked: 
    return this.GetValueByInputKey(CheckBoxInputKey.Checked);
   case CheckBoxCheckState.Unchecked: 
    return this.GetValueByInputKey(CheckBoxInputKey.Unchecked);
   case CheckBoxCheckState.Indeterminate: 
    return this.GetValueByInputKey(CheckBoxInputKey.Indeterminate);
  }
 },
 GetFirstValueBySecondValue: function(firstValueName, secondValueName, secondValue) {
  return this.GetValueByFunc(firstValueName, 
   function(checkBoxState) { return checkBoxState[secondValueName] === secondValue; });
 },
 GetValueByFunc: function(valueName, func) {
  for(var i = 0; i < this.checkBoxStates.length; i++) {
   if(func(this.checkBoxStates[i]))
    return this.checkBoxStates[i][valueName];
  }  
 },
 AssignElementClassName: function(element, cssClassPropertyKey, disabledCssClassPropertyKey, assignedClassName) {
  var classNames = [ ];
  for(var i = 0; i < this.imageProperties[cssClassPropertyKey].length; i++) {
   classNames.push(this.imageProperties[disabledCssClassPropertyKey][i]);
   classNames.push(this.imageProperties[cssClassPropertyKey][i]);
  }
  var elementClassName = element.className;
  for(var i = 0; i < classNames.length; i++) {
   var className = classNames[i];
   var index = elementClassName.indexOf(className);
   if(index > -1)
    elementClassName = elementClassName.replace((index == 0 ? '' : ' ') + className, "");
  }
  elementClassName += " " + assignedClassName;
  element.className = elementClassName;
 },
 UpdateInternalCheckBoxDecoration: function(mainElement, inputKey, enabled) {
  var imagePropertiesNumber = this.GetImagePropertiesNumByInputKey(inputKey);
  for(var imagePropertyKey in this.imageProperties) {
   if(this.imageProperties.hasOwnProperty(imagePropertyKey)) {
    var propertyValue = this.imageProperties[imagePropertyKey][imagePropertiesNumber];
    propertyValue = propertyValue || !isNaN(propertyValue) ? propertyValue : "";
    switch(imagePropertyKey) {
     case "0" : mainElement.title = propertyValue; break;
     case "1" : mainElement.style.width = propertyValue + (propertyValue != "" ? "px" : ""); break;
     case "2" : mainElement.style.height = propertyValue + (propertyValue != "" ? "px" : ""); break;
    }
    if(enabled) {
     switch(imagePropertyKey) {
      case "3" : this.SetImageSrc(mainElement, propertyValue); break;
      case "4" : 
       this.AssignElementClassName(mainElement, "4", "8", propertyValue);
       break;
      case "5" : this.SetBackgroundPosition(mainElement, propertyValue, true); break;
      case "6" : this.SetBackgroundPosition(mainElement, propertyValue, false); break;
     }
    } else {
     switch(imagePropertyKey) {
      case "7" : this.SetImageSrc(mainElement, propertyValue); break;
      case "8" : 
       this.AssignElementClassName(mainElement, "4", "8", propertyValue);
       break;
      case "9" : this.SetBackgroundPosition(mainElement, propertyValue, true); break;
      case "10" : this.SetBackgroundPosition(mainElement, propertyValue, false); break;
     }
    }
   }
  }
 },
 SetImageSrc: function(mainElement, src) {
  if(src === ""){
   mainElement.style.backgroundImage = "";
   mainElement.style.backgroundPosition = "";
   ASPx.RemoveClassNameFromElement(mainElement, this.customImageMarkerClassName);
  }
  else{
   mainElement.style.backgroundImage = "url('" + src + "')";
   this.SetBackgroundPosition(mainElement, 0, true);
   this.SetBackgroundPosition(mainElement, 0, false);
   ASPx.AddClassNameToElement(mainElement, this.customImageMarkerClassName);
  }
 },
 SetBackgroundPosition: function(element, value, isX) {
  if(value === "") {
   element.style.backgroundPosition = value;
   return;
  }
  if(element.style.backgroundPosition === "")
   element.style.backgroundPosition = isX ? "-" + value.toString() + "px 0px" : "0px -" + value.toString() + "px";
  else {
   var position = element.style.backgroundPosition.split(' ');
   element.style.backgroundPosition = isX ? '-' + value.toString() + "px " + position[1] :  position[0] + " -" + value.toString() + "px";
  }
 },
 AddState: function(value, stateInputKey, imagePropertiesNumber) {
  this.checkBoxStates.push({
   "Value" : value, 
   "StateInputKey" : stateInputKey, 
   "ImagePropertiesNumber" : imagePropertiesNumber
  });
 },
 GetAriaCheckedValue: function(state) {
  switch(state) {
   case ASPx.CheckBoxCheckState.Checked: return "true";
   case ASPx.CheckBoxCheckState.Unchecked: return "false";
   case ASPx.CheckBoxCheckState.Indeterminate: return "mixed";
   default: return "";
  }
 },
 GetAriaSelectedValue: function(state) {
  switch(state) {
   case ASPx.CheckBoxCheckState.Checked: return "true";
   case ASPx.CheckBoxCheckState.Unchecked: return "false";
   case ASPx.CheckBoxCheckState.Indeterminate: return "undefined";
   default: return "";
  }
 },
 SetAriaCheckedSelectedAttributes: function(mainElement, state) {
  if(mainElement.attributes["aria-checked"] !== undefined) {
   var ariaCheckedValue = this.GetAriaCheckedValue(state);
   mainElement.setAttribute("aria-checked", ariaCheckedValue);
  }
  if(mainElement.attributes["aria-selected"] !== undefined) {
   var ariaSelectedValue = this.GetAriaSelectedValue(state);
   mainElement.setAttribute("aria-selected", ariaSelectedValue);
  }
 }
});
CheckableElementStateController.Create = function(imageProperties, valueChecked, valueUnchecked, valueGrayed, allowGrayed) {
 var stateController = new CheckableElementStateController(imageProperties);
 stateController.AddState(valueChecked, CheckBoxInputKey.Checked, 0);
 stateController.AddState(valueUnchecked, CheckBoxInputKey.Unchecked, 1);
 if(typeof(valueGrayed) != "undefined")
  stateController.AddState(valueGrayed, CheckBoxInputKey.Indeterminate, allowGrayed ? 2 : 1);
 stateController.allowGrayed = allowGrayed;
 return stateController;
};
var CheckableElementHelper = ASPx.CreateClass(null, {
 InternalCheckBoxInitialize: function(internalCheckBox) {
  this.AttachToMainElement(internalCheckBox);
  this.AttachToInputElement(internalCheckBox);
 },
 AttachToMainElement: function(internalCheckBox) {
  var instance = this;
  if(internalCheckBox.mainElement) {
    var toggleEvent = internalCheckBox.displaySwitch ? ASPx.TouchUIHelper.touchMouseDownEventName : "click";
    ASPx.Evt.AttachEventToElement(internalCheckBox.mainElement, toggleEvent,
    function (evt) {
     if(ASPx.Evt.IsRightButtonPressed(evt))
      return;
     instance.InvokeClick(internalCheckBox, evt);
     if(!internalCheckBox.disableCancelBubble)
      return ASPx.Evt.PreventEventAndBubble(evt);
    }
   );
   ASPx.Evt.AttachEventToElement(internalCheckBox.mainElement, "mousedown",
    function (evt) {
     internalCheckBox.Refocus();
    }
   );
   ASPx.Evt.PreventElementDragAndSelect(internalCheckBox.mainElement, true);
  }
 },
 AttachToInputElement: function(internalCheckBox) {
  var instance = this;
  if(internalCheckBox.inputElement && internalCheckBox.mainElement) {
   var checkableElement = internalCheckBox.accessibilityCompliant ? internalCheckBox.mainElement : internalCheckBox.inputElement;
   ASPx.Evt.AttachEventToElement(checkableElement, "focus",
    function (evt) { 
     if(!internalCheckBox.enabled)
      checkableElement.blur();
     else
      internalCheckBox.OnFocus();
    }
   );
   ASPx.Evt.AttachEventToElement(checkableElement, "blur", 
    function (evt) { 
     internalCheckBox.OnLostFocus();
    }
   );
   ASPx.Evt.AttachEventToElement(checkableElement, "keyup",
    function (evt) { 
     if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Space)
      instance.InvokeClick(internalCheckBox, evt);
    }
   );
   ASPx.Evt.AttachEventToElement(checkableElement, "keydown",
    function (evt) { 
     if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Space)
      return ASPx.Evt.PreventEvent(evt);
    }
   );
  }
 },
 IsKBSInputWrapperExist: function() {
  return ASPx.Browser.Opera || ASPx.Browser.WebKitFamily;
 },
 GetICBMainElementByInput: function(icbInputElement) {
  return this.IsKBSInputWrapperExist() ? icbInputElement.parentNode.parentNode : icbInputElement.parentNode;
 },
 RequirePreventFocus: function() { return false; },
 InvokeClick: function(internalCheckBox, evt) {
  if(internalCheckBox.enabled && !internalCheckBox.GetReadOnly()) {
   var inputElementValue = internalCheckBox.inputElement.value;
   var focusableElement = internalCheckBox.accessibilityCompliant ? internalCheckBox.mainElement : internalCheckBox.inputElement; 
   if(!this.RequirePreventFocus())
    focusableElement.focus();
   internalCheckBox.inputElement.value = inputElementValue; 
   this.InvokeClickCore(internalCheckBox, evt);
   }
 },
 InvokeClickCore: function(internalCheckBox, evt) {
  internalCheckBox.OnClick(evt);
 }
});
CheckableElementHelper.Instance = new CheckableElementHelper();
var CheckBoxInternal = ASPx.CreateClass(null, {
 constructor: function(inputElement, stateController, allowGrayed, allowGrayedByClick, helper, container, storeValueInInput, key, disableCancelBubble,
  accessibilityCompliant, displaySwitch) {
  this.inputElement = inputElement;
  this.mainElement = helper.GetICBMainElementByInput(this.inputElement);
  this.name = (key ? key : this.inputElement.id) + CheckBoxInternal.GetICBMainElementPostfix();
  this.mainElement.id = this.name;
  this.stateController = stateController;
  this.container = container;
  this.allowGrayed = allowGrayed;
  this.allowGrayedByClick = allowGrayedByClick;
  this.autoSwitchEnabled = true;
  this.displaySwitch = displaySwitch;
  this.storeValueInInput = !!storeValueInInput;
  this.storedInputKey = !this.storeValueInInput ? this.inputElement.value : null;
  this.disableCancelBubble = !!disableCancelBubble;
  this.accessibilityCompliant = accessibilityCompliant;
  this.focusDecoration = null;
  this.focused = false;
  this.focusLocked = false;
  this.enabled = !this.mainElement.className.match(/dxWeb_\w+Disabled(\b|_)/);
  this.readOnly = false;
  this.preventFocus = helper.RequirePreventFocus();
  this.CheckedChanged = new ASPxClientEvent();
  this.Focus = new ASPxClientEvent();
  this.LostFocus = new ASPxClientEvent();
  helper.InternalCheckBoxInitialize(this);
 },
 GetReadOnly: function() {
  return this.readOnly;
 },
 ChangeInputElementTabIndex: function() {  
  var changeMethod = this.enabled ? ASPx.Attr.RestoreTabIndexAttribute : ASPx.Attr.SaveTabIndexAttributeAndReset;
  changeMethod(this.inputElement);
 },
 CreateFocusDecoration: function(focusedStyle) {
   this.focusDecoration = new FocusedStyleDecoration(this);
   this.focusDecoration.AddStyle('F', focusedStyle[0], focusedStyle[1]);
   this.focusDecoration.AddPostfix("");
 },
 UpdateFocusDecoration: function() {
  this.focusDecoration.Update();
 },  
 StoreInputKey: function(inputKey) {
  if(this.storeValueInInput)
   this.inputElement.value = inputKey;
  else
   this.storedInputKey = inputKey;
 },
 GetStoredInputKey: function() {
  if(this.storeValueInInput)
   return this.inputElement.value;
  else
   return this.storedInputKey;
 },
 OnClick: function(e) {
  if(this.autoSwitchEnabled) {
   var currentValue = this.GetValue();
   var value = this.stateController.GetNextCheckBoxValue(currentValue, this.allowGrayedByClick && this.allowGrayed);
   this.SetValue(value);
  }
  this.CheckedChanged.FireEvent(this, e);
 },
 OnFocus: function() {
  if(!this.IsFocusLocked()) {
   this.focused = true;
   this.UpdateFocusDecoration();
   this.Focus.FireEvent(this, null);
  } else
   this.UnlockFocus();
 },
 OnLostFocus: function() {
  if(!this.IsFocusLocked()) {
   this.focused = false;
   this.UpdateFocusDecoration();
   this.LostFocus.FireEvent(this, null);
  }
 },
 Refocus: function() {
  if(this.preventFocus) return;
  if(this.focused) {
   this.LockFocus();
   this.inputElement.blur();
   if(ASPx.Browser.MacOSMobilePlatform) {
    window.setTimeout(function() {
     ASPx.SetFocus(this.inputElement);
    }, ASPx.FOCUS_TIMEOUT);
   } else {
    ASPx.SetFocus(this.inputElement);
   }
  }
 },
 LockFocus: function() {
  this.focusLocked = true;
 },
 UnlockFocus: function() {
  this.focusLocked = false;
 },
 IsFocusLocked: function() {
  if(!!ASPx.Attr.GetAttribute(this.mainElement, ASPx.Attr.GetTabIndexAttributeName()))
   return false;
  return this.focusLocked;
 },
 SetValue: function(value, force) {
  var currentValue = this.GetValue();
  if(currentValue !== value || force) {
   var newInputKey = this.stateController.GetInputKeyByValue(value);
   if(newInputKey) {
    this.StoreInputKey(newInputKey);   
    this.stateController.UpdateInternalCheckBoxDecoration(this.mainElement, newInputKey, this.enabled);
   }
  }
  if(this.accessibilityCompliant) {
   var state = this.GetCurrentCheckState();
   this.stateController.SetAriaCheckedSelectedAttributes(this.mainElement, state);
  }
 },
 GetValue: function() {
  return this.stateController.GetValueByInputKey(this.GetCurrentInputKey());
 },
 GetCurrentCheckState: function() {
  return this.stateController.GetCheckStateByInputKey(this.GetCurrentInputKey());
 },
 GetCurrentInputKey: function() {
  return this.GetStoredInputKey();
 },
 GetChecked: function() {
  return this.GetCurrentInputKey() === CheckBoxInputKey.Checked;
 },
 SetChecked: function(checked) {
  var newValue = this.stateController.GetValueByCheckState(checked ? CheckBoxCheckState.Checked : CheckBoxCheckState.Unchecked);
  this.SetValue(newValue);
 },
 SetEnabled: function(enabled) {
  if(this.enabled != enabled) {
   this.enabled = enabled;
   this.stateController.UpdateInternalCheckBoxDecoration(this.mainElement, this.GetCurrentInputKey(), this.enabled);
   this.ChangeInputElementTabIndex();
  }
 },
 GetEnabled: function() {
  return this.enabled;
 }
});
CheckBoxInternal.GetICBMainElementPostfix = function() {
 return "_D";
};
var CheckBoxInternalCollection = ASPx.CreateClass(CollectionBase, {
 constructor: function(imageProperties, allowGrayed, storeValueInInput, helper, disableCancelBubble, accessibilityCompliant) {
  this.constructor.prototype.constructor.call(this);
  this.stateController = allowGrayed 
   ? CheckableElementStateController.Create(imageProperties, CheckBoxInputKey.Checked, CheckBoxInputKey.Unchecked, CheckBoxInputKey.Indeterminate, true)
   : CheckableElementStateController.Create(imageProperties, CheckBoxInputKey.Checked, CheckBoxInputKey.Unchecked);
  this.helper = helper || CheckableElementHelper.Instance;
  this.storeValueInInput = !!storeValueInInput;
  this.disableCancelBubble = !!disableCancelBubble;
  this.accessibilityCompliant = accessibilityCompliant;
 },
 Add: function(key, inputElement, container) {
  this.Remove(key);
  var checkBox = this.CreateInternalCheckBox(key, inputElement, container);
  CollectionBase.prototype.Add.call(this, key, checkBox);
  return checkBox;
 },
 SetImageProperties: function(imageProperties) {
  this.stateController.imageProperties = imageProperties;
 },
 CreateInternalCheckBox: function(key, inputElement, container) {
  return new CheckBoxInternal(inputElement, this.stateController, this.stateController.allowGrayed, false, this.helper, container, 
   this.storeValueInInput, key, this.disableCancelBubble, this.accessibilityCompliant);
 }
});
var FocusedStyleDecoration = ASPx.CreateClass(null, {
 constructor: function(editor) {
  this.editor = editor;
  this.postfixList = [];
  this.styles = {};
  this.innerStyles = {};
 },
 AddPostfix: function(value) {
  this.postfixList.push(value);
 },
 AddStyle: function(key, className, cssText) {
  this.styles[key] = this.CreateRule(className, cssText);
  this.innerStyles[key] = this.CreateRule("", this.FilterInnerCss(cssText));
 },
 CreateRule: function(className, cssText) {
  return ASPx.Str.Trim(className + " " + ASPx.CreateImportantStyleRule(this.GetStyleSheet(), cssText));
 },
 GetStyleSheet: function() {
  return ASPx.GetCurrentStyleSheet();
 },
 FilterInnerCss: function(css) {
  return css.replace(/(border|background-image)[^:]*:[^;]+/gi, "");
 },
 Update: function() {
  for(var i = 0; i < this.postfixList.length; i++) {
   var postfix = this.postfixList[i];
   var inner = postfix.length > 0;
   var element = this.GetElementByPostfix(postfix);
   if(element)
    this.ApplyStyles(element, inner);
  }
 },
 GetElementByPostfix: function(postfix) {
  return ASPx.GetElementById(this.editor.name + postfix);
 },
 ApplyStyles: function(element, inner) {
  this.ApplyFocusedStyle(element, inner);
 },
 ApplyFocusedStyle: function(element, inner) {
  if(this.HasDecoration("F"))
   this.ApplyDecoration("F", element, inner, this.editor.focused);
 },
 HasDecoration: function(key) {
  return !!this.styles[key];
 },
 ApplyDecoration: function(key, element, inner, active) {
  var value = inner ? this.innerStyles[key] : this.styles[key];
  this.RemoveDecoration(element, value);
  if(active)
   ASPx.AddClassNameToElement(element, value);
 },
 RemoveDecoration: function(element, value) {
  ASPx.RemoveClassNameFromElement(element, value);
 },
 ApplyDecorationCore: function() {
 },
 EnsureElementBorder: function(element) {
  var border = parseInt(element.border) || 0;
  element.border = 1;
  element.border = border;
 }
});
var EditorStyleDecoration = ASPx.CreateClass(FocusedStyleDecoration, {
 constructor: function(editor) {
  this.constructor.prototype.constructor.call(this, editor);
  this.lockUpdate = false;
 },
 LockUpdate: function() {
  this.lockUpdate = true;
 },
 UnlockUpdate: function() {
  this.lockUpdate = false;
 },
 IsUpdateLocked: function() {
  return this.lockUpdate;
 },
 Update: function () {
  if(this.IsUpdateLocked())
   return;
  ASPx.FocusedStyleDecoration.prototype.Update.call(this);
 },
 ApplyStyles: function (element, inner) {
  this.ApplyInvalidStyle(element, inner);
  ASPx.FocusedStyleDecoration.prototype.ApplyStyles.call(this, element, inner);
 },
 ApplyInvalidStyle: function (element, inner) {
  if(this.HasDecoration("I")) {
   var isValid = this.editor.GetIsValid();
   this.ApplyDecoration("I", element, inner, !isValid);
  }
 }
});
var TextEditorStyleDecoration = ASPx.CreateClass(EditorStyleDecoration, {
 constructor: function(editor) {
  this.constructor.prototype.constructor.call(this, editor);
  this.nullTextClassName = "";
 },
 ApplyStyles: function(element, inner) {
  ASPx.EditorStyleDecoration.prototype.ApplyStyles.call(this, element, inner);
  this.ApplyNullTextStyle(element, inner);
 },
 ApplyNullTextStyle: function(element, inner) {
  if(!this.HasDecoration("N"))
   return;
  var apply = !this.editor.focused && this.editor.CanApplyNullTextDecoration();
  this.EnsureSpellcheckAttribute(element, apply);
  this.ApplyDecoration("N", element, inner, apply);
 },
 EnsureSpellcheckAttribute: function(element, apply) {
  if(apply)
   ASPx.Attr.ChangeAttribute(element, "spellcheck", "false");
  else
   ASPx.Attr.RestoreAttribute(element, "spellcheck");
 },
 ApplyNullTextClassName: function(active) {
  var nullTextClassName = this.GetNullTextClassName();
  var editorMainElement = this.editor.GetMainElement();
  if(active)
   ASPx.AddClassNameToElement(editorMainElement, nullTextClassName);
  else
   ASPx.RemoveClassNameFromElement(editorMainElement, nullTextClassName);
 },
 GetNullTextClassName: function() {
  if (!this.nullTextClassName)
   this.InitializeNullTextClassName();
  return this.nullTextClassName;
 },
 InitializeNullTextClassName: function() {
  var nullTextStyle = this.styles["N"];
  if (nullTextStyle) {
   var nullTextStyleClassNames = nullTextStyle.split(" ");
   for (var i = 0; i < nullTextStyleClassNames.length; i++)
    if (nullTextStyleClassNames[i].match("dxeNullText"))
     this.nullTextClassName = nullTextStyleClassNames[i];
  }
 }
});
var touchUIHelperUsePointerEvents = (ASPx.Browser.Edge || ASPx.Browser.EdgeWebKit) && ASPx.Browser.MSTouchUI && !!window.PointerEvent;
var TouchUIHelper = {
 isGesture: false,
 isMouseEventFromScrolling: false,
 isNativeScrollingAllowed: true,
 clickSensetivity: 10,
 documentTouchHandlers: {},
 documentEventAttachingAllowed: true,
 msTouchDraggableClassName: "dxMSTouchDraggable",
 touchMouseDownEventName: ASPx.Browser.WebKitTouchUI ? "touchstart" : (touchUIHelperUsePointerEvents ? "pointerdown" : "mousedown"),
 touchMouseUpEventName: ASPx.Browser.WebKitTouchUI ? "touchend" : (touchUIHelperUsePointerEvents ? "pointerup" : "mouseup"),
 touchMouseMoveEventName: ASPx.Browser.WebKitTouchUI ? "touchmove" : (touchUIHelperUsePointerEvents ? "pointermove" : "mousemove"),
 startPreventingTouchMove: function() {
  if(touchUIHelperUsePointerEvents)
   ASPx.Evt.AttachEventToDocument("touchmove", ASPx.Evt.PreventEvent);
 },
 stopPreventingTouchMove: function() {
  if(touchUIHelperUsePointerEvents)
   ASPx.Evt.DetachEventFromDocument("touchmove", ASPx.Evt.PreventEvent);
 },
 isTouchEvent: function(evt) {
  if(!evt) return false;
  return ASPx.Browser.WebKitTouchUI && ASPx.IsExists(evt.changedTouches); 
 },
 isTouchEventName: function(eventName) {
  return ASPx.Browser.WebKitTouchUI && (eventName.indexOf("touch") > -1 || eventName.indexOf("gesture") > -1);
 },
 getEventX: function(evt) {
  var touchPoint = null;
  if(evt.changedTouches.length > 0)
   touchPoint = evt.changedTouches;
  else if(evt.targetTouches.length > 0)
   touchPoint = evt.targetTouches;
  return touchPoint ? touchPoint[0].pageX : 0;
 },
 getEventY: function(evt) { 
  var touchPoint = null;
  if(evt.changedTouches.length > 0)
   touchPoint = evt.changedTouches;
  else if(evt.targetTouches.length > 0)
   touchPoint = evt.targetTouches;
  return touchPoint ? touchPoint[0].pageY : 0;
 },
 getWebkitMajorVersion: function(){
  if(!this.webkitMajorVersion){
   var regExp = new RegExp("applewebkit/(\\d+)", "i");
   var matches = regExp.exec(ASPx.Browser.UserAgent);
   if(matches && matches.index >= 1)
    this.webkitMajorVersion = matches[1];
  }
  return this.webkitMajorVersion;
 },
 getIsLandscapeOrientation: function(){
  if(ASPx.Browser.MacOSMobilePlatform || ASPx.Browser.AndroidMobilePlatform)
   return Math.abs(window.orientation) == 90;
  return ASPx.GetDocumentClientWidth() > ASPx.GetDocumentClientHeight();
 },
 nativeScrollingSupported: function() {
  var allowedSafariVersion = ASPx.Browser.Version >= 5.1 && ASPx.Browser.Version < 8; 
  var webkitMajorVersion = this.getWebkitMajorVersion();
  var allowedWebKitVersion = webkitMajorVersion > 533 && webkitMajorVersion < 600;
  return (ASPx.Browser.MacOSMobilePlatform && (allowedSafariVersion || allowedWebKitVersion))
   || (ASPx.Browser.AndroidMobilePlatform && ASPx.Browser.PlaformMajorVersion >= 3) || (ASPx.Browser.MSTouchUI);
 },
 makeScrollableIfRequired: function(element, options) {
  if(ASPx.Browser.WebKitTouchUI && element) {
   var overflow = ASPx.GetCurrentStyle(element).overflow;
   if(element.tagName == "DIV" &&  overflow != "hidden" && overflow != "visible" ){
    return this.MakeScrollable(element);
   }
  }
 },
 preventScrollOnEvent: function(evt){
 },
 handleFastTapIfRequired: function(evt, action, preventCommonClickEvents) {
  if(ASPx.Browser.WebKitTouchUI && evt.type == 'touchstart' && action) {
   this.FastTapHelper.HandleFastTap(evt, action, preventCommonClickEvents);
   return true;
  }
  return false;
 },
 ensureDocumentSizesCorrect: function (){
  return (document.documentElement.clientWidth - document.documentElement.clientHeight) / (screen.width - screen.height) > 0;
 },
 ensureOrientationChanged: function(onOrientationChangedFunction){
  if(ASPxClientUtils.iOSPlatform || this.ensureDocumentSizesCorrect())
   onOrientationChangedFunction();
  else {
   window.setTimeout(function(){
    this.ensureOrientationChanged(onOrientationChangedFunction);
   }.aspxBind(this), 100);
  }
 },
 onEventAttachingToDocument: function(eventName, func){
  if(ASPx.Browser.MacOSMobilePlatform && this.isTouchEventName(eventName)) {
   if(!this.documentTouchHandlers[eventName])
    this.documentTouchHandlers[eventName] = [];
   this.documentTouchHandlers[eventName].push(func);
   return this.documentEventAttachingAllowed;
  }
  return true;
 },
 onEventDettachedFromDocument: function(eventName, func){
  if(ASPx.Browser.MacOSMobilePlatform && this.isTouchEventName(eventName)) {
   var handlers = this.documentTouchHandlers[eventName];
   if(handlers)
    ASPx.Data.ArrayRemove(handlers, func);
  }
 },
 processDocumentTouchEventHandlers: function(proc) {
  var touchEventNames = ["touchstart", "touchend", "touchmove", "gesturestart", "gestureend"];
  for(var i = 0; i < touchEventNames.length; i++) {
   var eventName = touchEventNames[i];
   var handlers = this.documentTouchHandlers[eventName];
   if(handlers) {
    for(var j = 0; j < handlers.length; j++) {
     proc(eventName,handlers[j]);
    }
   }
  }
 },
 removeDocumentTouchEventHandlers: function() {
  if(ASPx.Browser.MacOSMobilePlatform) {
   this.documentEventAttachingAllowed = false;
   this.processDocumentTouchEventHandlers(ASPx.Evt.DetachEventFromDocumentCore);
  }
 },
 restoreDocumentTouchEventHandlers: function () {
  if(ASPx.Browser.MacOSMobilePlatform) {
   this.documentEventAttachingAllowed = true;
   this.processDocumentTouchEventHandlers(ASPx.Evt.AttachEventToDocumentCore);
  }
 },
 IsNativeScrolling: function() {
  return TouchUIHelper.nativeScrollingSupported() && TouchUIHelper.isNativeScrollingAllowed;
 },
 pointerEnabled: !!(window.PointerEvent || window.MSPointerEvent),
 pointerDownEventName: window.PointerEvent ? "pointerdown" : "MSPointerDown",
 pointerUpEventName: window.PointerEvent ? "pointerup" : "MSPointerUp",
 pointerCancelEventName: window.PointerEvent ? "pointercancel" : "MSPointerCancel",
 pointerMoveEventName: window.PointerEvent ? "pointermove" : "MSPointerMove",
 pointerOverEventName: window.PointerEvent ? "pointerover" : "MSPointerOver",
 pointerOutEventName: window.PointerEvent ? "pointerout" : "MSPointerOut",
 pointerType: {
  Touch: "touch",
  Pen: "pen",
  Mouse: "mouse"
 },
 msGestureEnabled: !!(window.PointerEvent || window.MSPointerEvent) && typeof(MSGesture) != "undefined",
 msTouchCreateGesturesWrapper: function(element, onTap){
  if(!TouchUIHelper.msGestureEnabled) 
   return;
  var gesture = new MSGesture();
  gesture.target = element;
  ASPx.Evt.AttachEventToElement(element, TouchUIHelper.pointerDownEventName, function(evt){
   gesture.addPointer(evt.pointerId);
  });
  ASPx.Evt.AttachEventToElement(element, TouchUIHelper.pointerUpEventName, function(evt){
   gesture.stop();
  });
  if(onTap)
   ASPx.Evt.AttachEventToElement(element, "MSGestureTap", onTap);
  return gesture;
 },
 useLongTapHelper: function () {
  return ASPx.Browser.Safari && ASPx.Browser.TouchUI;
 },
 attachLongTapHandler: function(element, handler, onlyBubbling) {
  var timerID = -1;
  var timeout = 1000;
  var event = null;
  var preventClickEvent = false;
  var startX = -1;
  var startY = -1;
  var pixelLimit = 5;
  function onTouchMouseDown(evt) {
   abortWating();
   event = evt;
   startX = evt.pageX;
   startY = evt.pageY;
   preventClickEvent = false;
   timerID = window.setTimeout(onTimeout, timeout);
  }
  function onTouchMouseMove(evt) {
   if (!isUnderTouch())
    return;
   var shiftX = Math.abs(startX - evt.pageX),
    shiftY = Math.abs(startY - evt.pageY),
    maxShift = Math.max(shiftX, shiftY);
   if (maxShift > pixelLimit)
    abortWating();
  }
  function onTouchMouseUp(evt) {
   abortWating();
   if (preventClickEvent) {
    ASPx.Evt.PreventEventAndBubble(evt);
    preventClickEvent = false;
   }
  }
  function onTimeout() {
   handler(event);
   preventClickEvent = true;
   abortWatingInternal();
  }
  function isUnderTouch() {
   return timerID !== -1;
  }
  function abortWating() {
   if (isUnderTouch()) {
    window.clearTimeout(timerID);
    abortWatingInternal();
   }
  }
  function abortWatingInternal() {
   timerID = -1;
   event = null;
  }
  ASPx.Evt.AttachEventToElement(element, TouchUIHelper.touchMouseDownEventName, onTouchMouseDown, onlyBubbling);
  ASPx.Evt.AttachEventToElement(element, TouchUIHelper.touchMouseMoveEventName, onTouchMouseMove, onlyBubbling);
  ASPx.Evt.AttachEventToElement(element, TouchUIHelper.touchMouseUpEventName, onTouchMouseUp, onlyBubbling);
  element.style["-webkit-user-select"] = "none";
  return function () {
   ASPx.Evt.DetachEventFromElement(element, TouchUIHelper.touchMouseDownEventName, onTouchMouseDown);
   ASPx.Evt.DetachEventFromElement(element, TouchUIHelper.touchMouseMoveEventName, onTouchMouseMove);
   ASPx.Evt.DetachEventFromElement(element, TouchUIHelper.touchMouseUpEventName, onTouchMouseUp);
   element.style["-webkit-user-select"] = "";
  };
 }
};
var CacheHelper = {};
CacheHelper.GetCachedValueCore = function(obj, key, func, cacheObj, fillValueMethod) {
 if(!cacheObj)
  cacheObj = obj;
 if(!cacheObj.cache)
  cacheObj.cache = {};
 if(!key) 
  key = "default";
 fillValueMethod(obj, key, func, cacheObj);
 return cacheObj.cache[key];
};
CacheHelper.GetCachedValue = function(obj, key, func, cacheObj) {
 return CacheHelper.GetCachedValueCore(obj, key, func, cacheObj, 
  function(obj, key, func, cacheObj) {
   if(!ASPx.IsExists(cacheObj.cache[key]))
    cacheObj.cache[key] = func.apply(obj, []);
  });
};
CacheHelper.GetCachedElement = function(obj, key, func, cacheObj) {
 return CacheHelper.GetCachedValueCore(obj, key, func, cacheObj, 
  function(obj, key, func, cacheObj) {
   if(!ASPx.IsValidElement(cacheObj.cache[key]))
    cacheObj.cache[key] = func.apply(obj, []);
  });
};
CacheHelper.GetCachedElements = function(obj, key, func, cacheObj) {
 return CacheHelper.GetCachedValueCore(obj, key, func, cacheObj, 
  function(obj, key, func, cacheObj) {
   if(!ASPx.IsValidElements(cacheObj.cache[key])){
    var elements = func.apply(obj, []);
    if(!Ident.IsArray(elements))
     elements = [elements];
    cacheObj.cache[key] = elements;
   }
  });
};
CacheHelper.GetCachedElementById = function(obj, id, cacheObj) {
 return CacheHelper.GetCachedElement(obj, id, function() { return ASPx.GetElementById(id); }, cacheObj);
};
CacheHelper.GetCachedChildById = function(obj, parent, id, cacheObj) {
 return CacheHelper.GetCachedElement(obj, id, function() { return ASPx.GetChildById(parent, id); }, cacheObj);
};
CacheHelper.DropCachedValue = function(cacheObj, key) {
 cacheObj.cache[key] = null;
};  
CacheHelper.DropCache = function(cacheObj) {
 cacheObj.cache = null;
};  
var DomObserver = ASPx.CreateClass(null, {
 constructor: function() {
  this.items = { };
 },
 subscribe: function(elementID, callbackFunc) {
  var item = this.items[elementID];
  if(item)
   this.unsubscribe(elementID);
  item = {
   elementID: elementID,
   callbackFunc: callbackFunc,
   pauseCount: 0
  };
  this.prepareItem(item);
  this.items[elementID] = item;
 },
 prepareItem: function(item) {
 },
 unsubscribe: function(elementID) {
  this.items[elementID] = null;
 },
 getItemElement: function(item) {
  var element = this.getElementById(item.elementID);
  if(element)
   return element;
  this.unsubscribe(item.elementID);
  return null;
 },
 getElementById: function(elementID) {
  var element = document.getElementById(elementID);
  return element && ASPx.IsValidElement(element) ? element : null;
 },
 pause: function(element, includeSubtree) {
  this.changeItemsState(element, includeSubtree, true);
 },
 resume: function(element, includeSubtree) {
  this.changeItemsState(element, includeSubtree, false);
 },
 forEachItem: function(processFunc, context) {
  context = context || this;
  for(var itemName in this.items) {
   if(!this.items.hasOwnProperty(itemName))
    continue;
   var item = this.items[itemName];
   if(item) {
    var needBreak = processFunc.call(context, item);
    if(needBreak)
     return;
   }
  }
 },
 changeItemsState: function(element, includeSubtree, pause) {
  this.forEachItem(function(item) {
   if(!element)
    this.changeItemState(item, pause);
   else {
    var itemElement = this.getItemElement(item);
    if(itemElement && (element == itemElement || (includeSubtree && ASPx.GetIsParent(element, itemElement)))) {
     this.changeItemState(item, pause);
     if(!includeSubtree)
      return true;
    }
   }
  }.aspxBind(this));
 },
 changeItemState: function(item, pause) {
  if(pause)
   this.pauseItem(item);
  else
   this.resumeItem(item);
 },
 pauseItem: function(item) {
  item.paused = true;
  item.pauseCount++;
 },
 resumeItem: function(item) {
  if(item.pauseCount > 0) {
   if(item.pauseCount == 1)
    item.paused = false;
   item.pauseCount--;
  }
 }
});
DomObserver.IsMutationObserverAvailable = function() {
 return !!window.MutationObserver;
};
var TimerObserver = ASPx.CreateClass(DomObserver, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
  this.timerID = -1;
  this.observationTimeout = 300;
 },
 subscribe: function(elementID, callbackFunc) {
  DomObserver.prototype.subscribe.call(this, elementID, callbackFunc);
  if(!this.isActivated())
   this.startObserving();
 },
 isActivated: function() {
  return this.timerID !== -1;
 },
 startObserving: function() {
  if(this.isActivated())
   window.clearTimeout(this.timerID);
  this.timerID = window.setTimeout(this.onTimeout, this.observationTimeout);
 },
 onTimeout: function() {
  var observer = _aspxGetDomObserver();
  observer.doObserve();
  observer.startObserving();
 },
 doObserve: function() {
  if(!ASPx.documentLoaded) return;
  this.forEachItem(function(item) {
   if(!item.paused)
    this.doObserveForItem(item);
  }.aspxBind(this));
 },
 doObserveForItem: function(item) {
  var element = this.getItemElement(item);
  if(element)
   item.callbackFunc.call(this, element);
 }
});
var MutationObserver = ASPx.CreateClass(DomObserver, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
  this.callbackTimeout = 10;
 },
 prepareItem: function(item) {
  item.callbackTimerID = -1;
  var target = this.getElementById(item.elementID);
  if(!target)
   return;
  var observerCallbackFunc = function() {
   if(item.callbackTimerID === -1) {
    var timeoutHander = function() {
     item.callbackTimerID = -1;
     item.callbackFunc.call(this, target);
    }.aspxBind(this);
    item.callbackTimerID = window.setTimeout(timeoutHander, this.callbackTimeout);
   }
  }.aspxBind(this);
  var observer = new window.MutationObserver(observerCallbackFunc);
  var config = { attributes: true, childList: true, characterData: true, subtree: true };
  observer.observe(target, config);
  item.observer = observer;
  item.config = config;
 },
 unsubscribe: function(elementID) {
  var item = this.items[elementID];
  if(item) {
   item.observer.disconnect();
   item.observer = null;
  }
  DomObserver.prototype.unsubscribe.call(this, elementID);
 },
 pauseItem: function(item) {
  DomObserver.prototype.pauseItem.call(this, item);
  item.observer.disconnect();
 },
 resumeItem: function(item) {
  DomObserver.prototype.resumeItem.call(this, item);
  if(!item.paused) {
   var target = this.getItemElement(item);
   if(target)
    item.observer.observe(target, item.config);
  }
 }
});
var domObserver = null;
function _aspxGetDomObserver() {
 if(domObserver == null)
  domObserver = DomObserver.IsMutationObserverAvailable() ? new MutationObserver() : new TimerObserver();
 return domObserver;
}
var ControlUpdateWatcher = ASPx.CreateClass(null, {
 constructor: function() {
  this.helpers = { };
  this.clearLockerTimerID = -1;
  this.clearLockerTimerDelay = 15;
  this.postProcessing = false;
  this.init();
 },
 init: function() {
  var postHandler = aspxGetPostHandler();
  postHandler.Post.AddHandler(this.OnPost, this);
 },
 Add: function(helper) {
  this.helpers[helper.GetName()] = helper;
 },
 CanSendCallback: function(dxCallbackOwner, arg) {
  this.LockConfirmOnBeforeWindowUnload();
  var modifiedHelpers = this.FilterModifiedHelpersByDXCallbackOwner(this.GetModifiedHelpers(), dxCallbackOwner, arg);
  if(modifiedHelpers.length === 0) return true;
  var modifiedHelpersInfo = this.GetToConfirmAndToResetLists(modifiedHelpers, dxCallbackOwner.name);
  if(!modifiedHelpersInfo) return true;
  if(modifiedHelpersInfo.toConfirm.length === 0) {
   this.ResetClientChanges(modifiedHelpersInfo.toReset);
   return true;
  }
  var helper = modifiedHelpersInfo.toConfirm[0];
  if(!confirm(helper.GetConfirmUpdateText()))
   return false;
  this.ResetClientChanges(modifiedHelpersInfo.toReset);
  return true;
 },
 OnPost: function(s, e) {
  if(this.isDxCallback(e))
   return;
  this.postProcessing = true;
  this.LockConfirmOnBeforeWindowUnload();
  var modifiedHelpersInfo = this.GetModifedHelpersInfo(e);
  if(!modifiedHelpersInfo)
   return;
  if(modifiedHelpersInfo.toConfirm.length === 0) {
   this.ResetClientChanges(modifiedHelpersInfo.toReset);
   return;
  }
  var helper = modifiedHelpersInfo.toConfirm[0];
  if(!confirm(helper.GetConfirmUpdateText())) {
   e.cancel = true;
   this.finishPostProcessing();
  }
  if(!e.cancel)
   this.ResetClientChanges(modifiedHelpersInfo.toReset);
 },
 isDxCallback: function(e) {
  return e.isDXCallback || this.isInternalUploadControlCallback();
 },
 isInternalUploadControlCallback: function() {
  var isInCallback = false;
  for(var key in this.helpers) {
   if(this.helpers.hasOwnProperty(key)) {
    var helper = this.helpers[key];
    isInCallback = isInCallback || helper.isInUploadCallback();
   }
  }
  return isInCallback;
 },
 finishPostProcessing: function() {
  this.postProcessing = false;
 },
 GetModifedHelpersInfo: function(e) {
  var modifiedHelpers = this.FilterModifiedHelpers(this.GetModifiedHelpers(), e);
  if(modifiedHelpers.length === 0) return;
  return this.GetToConfirmAndToResetLists(modifiedHelpers, e && e.ownerID);
 },
 GetToConfirmAndToResetLists: function(modifiedHelpers, ownerID) {
  var resetList = [ ];
  var confirmList = [ ];
  for(var i = 0; i < modifiedHelpers.length; i++) {
   var helper = modifiedHelpers[i];
   if(!helper.GetConfirmUpdateText()) { 
    resetList.push(helper);
    continue;
   }
   if(helper.CanShowConfirm(ownerID)) { 
    resetList.push(helper);
    confirmList.push(helper);
   }
  }
  return { toConfirm: confirmList, toReset: resetList };
 },
 FilterModifiedHelpers: function(modifiedHelpers, e) {
  if(modifiedHelpers.length === 0)
   return [ ];
  if(this.RequireProcessUpdatePanelCallback(e))
   return this.FilterModifiedHelpersByUpdatePanels(modifiedHelpers);
  if(this.postProcessing)
   return this.FilterModifiedHelpersByPostback(modifiedHelpers);
  return modifiedHelpers;
 },
 FilterModifiedHelpersByDXCallbackOwner: function(modifiedHelpers, dxCallbackOwner, arg) {
  var result = [ ];
  for(var i = 0; i < modifiedHelpers.length; i++) {
   var helper = modifiedHelpers[i];
   if(helper.NeedConfirmOnCallback(dxCallbackOwner, arg))
    result.push(helper);
  }
  return result;
 },
 FilterModifiedHelpersByUpdatePanels: function(modifiedHelpers) {
  var result = [ ];
  var updatePanels = this.GetUpdatePanelsWaitedForUpdate();
  for(var i = 0; i < updatePanels.length; i++) {
   var panelID = updatePanels[i].replace(/\$/g, "_");
   var panel = ASPx.GetElementById(panelID);
   if(!panel) continue;
   for(var j = 0; j < modifiedHelpers.length; j++) {
    var helper = modifiedHelpers[j];
    if(ASPx.GetIsParent(panel, helper.GetControlMainElement()))
     result.push(helper);
   }
  }
  return result;
 },
 FilterModifiedHelpersByPostback: function(modifiedHelpers) {
  var result = [ ];
  for(var i = 0; i < modifiedHelpers.length; i++) {
   var helper = modifiedHelpers[i];
   if(helper.NeedConfirmOnPostback())
    result.push(helper);
  }
  return result;
 },
 RequireProcessUpdatePanelCallback: function(e) {
  var rManager = this.GetMSRequestManager();
  if(rManager && e && e.isMSAjaxCallback)
   return rManager._postBackSettings.async;
  return false;
 },
 GetUpdatePanelsWaitedForUpdate: function() {
  var rManager = this.GetMSRequestManager();
  if(!rManager) return [ ];
  var panelUniqueIDs = rManager._postBackSettings.panelsToUpdate || [ ];
  var panelClientIDs = [ ];
  for(var i = 0; i < panelUniqueIDs.length; i++) {
   var index = ASPx.Data.ArrayIndexOf(rManager._updatePanelIDs, panelUniqueIDs[i]);
   if(index >= 0)
    panelClientIDs.push(rManager._updatePanelClientIDs[index]);
  }
  return panelClientIDs;
 },
 GetMSRequestManager: function() {
  return ASPx.GetMSAjaxRequestManager();
 },
 GetModifiedHelpers: function() {
  var result = [ ];
  for(var key in this.helpers) { 
   if(this.helpers.hasOwnProperty(key)) {
    var helper = this.helpers[key];
    if(helper.HasChanges())
     result.push(helper);
   }
  }
  return result;
 },
 ResetClientChanges: function(modifiedHelpers) {
  for(var i = 0; i < modifiedHelpers.length; i++)
   modifiedHelpers[i].ResetClientChanges();
 },
 GetConfirmUpdateMessage: function() {
  if(this.confirmOnWindowUnloadLocked) return;
  var modifiedHelpersInfo = this.GetModifedHelpersInfo();
  if(!modifiedHelpersInfo || modifiedHelpersInfo.toConfirm.length === 0) 
   return;
  var helper = modifiedHelpersInfo.toConfirm[0];
  return helper.GetConfirmUpdateText();
 },
 LockConfirmOnBeforeWindowUnload: function() {
  this.confirmOnWindowUnloadLocked = true;
  this.clearLockerTimerID = ASPx.Timer.ClearTimer(this.clearLockerTimerID);
  this.clearLockerTimerID = window.setTimeout(function() {
   this.confirmOnWindowUnloadLocked = false;
  }.aspxBind(this), this.clearLockerTimerDelay);
 },
 OnWindowBeforeUnload: function(e) {
  var confirmMessage = this.GetConfirmUpdateMessage();
  if(confirmMessage)
   e.returnValue = confirmMessage;
  this.finishPostProcessing();
  return confirmMessage;
 },
 OnWindowUnload: function(e) {
  if(this.confirmOnWindowUnloadLocked) return;
  var modifiedHelpersInfo = this.GetModifedHelpersInfo();
  if(!modifiedHelpersInfo) return;
  this.ResetClientChanges(modifiedHelpersInfo.toReset);
 },
 OnMouseDown: function(e) {
 },
 OnFocusIn: function(e) {
 },
 PreventBeforeUnloadOnLinkClick: function(e) {
  if(ASPx.GetObjectKeys(this.helpers).length == 0)
   return;
  var link = ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(e), "A");
  if(!link || link.dxgvLinkClickHanlderAssigned)
   return;
  var url = ASPx.Attr.GetAttribute(link, "href");
  if(!url || url.indexOf("javascript:") < 0)
   return;
  ASPx.Evt.AttachEventToElement(link, "click", function(ev) { return ASPx.Evt.PreventEvent(ev); });
  link.dxgvLinkClickHanlderAssigned = true;
 }
});
ControlUpdateWatcher.Instance = null;
ControlUpdateWatcher.getInstance = function () {
 if (!ControlUpdateWatcher.Instance) {
  ControlUpdateWatcher.Instance = new ControlUpdateWatcher();
  ASPx.Evt.AttachEventToElement(window, "beforeunload", function(e) {
   return ControlUpdateWatcher.Instance.OnWindowBeforeUnload(e);
  });
  ASPx.Evt.AttachEventToElement(window, "unload", function(e) {
   ControlUpdateWatcher.Instance.OnWindowUnload(e);
  });
  ASPx.Evt.AttachEventToDocument("mousedown", function(e) {
   ControlUpdateWatcher.Instance.OnMouseDown(e);
  });
  ASPx.Evt.AttachEventToDocument("focusin", function(e) {
   ControlUpdateWatcher.Instance.OnFocusIn(e);
  });
 }
 return ControlUpdateWatcher.Instance;
};
var UpdateWatcherHelper = ASPx.CreateClass(null, {
 constructor: function(owner) {
  this.owner = owner;
  this.ownerWatcher = ControlUpdateWatcher.getInstance();
  this.ownerWatcher.Add(this);
 },
 GetName: function() {
  return this.owner.name;
 },
 GetControlMainElement: function() {
  return this.owner.GetMainElement();
 },
 GetControlParentForm: function(){
  return ASPx.GetParentByTagName(this.GetControlMainElement(), "FORM");
 },
 CanShowConfirm: function(requestOwnerID) {
  return true;
 },
 HasChanges: function() {
  return false;
 },
 GetConfirmUpdateText: function() {
  return "";
 },
 NeedConfirmOnCallback: function(dxCallbackOwner) {
  return true;
 },
 NeedConfirmOnPostback: function() {
  if(ASPx.IsUploadSubmitRequest)
   return !ASPx.IsUploadSubmitRequest(this.GetControlParentForm());
  return true;
 },
 ResetClientChanges: function() {
 },
 ConfirmOnCustomControlEvent: function() {
  var confirmMessage = this.GetConfirmUpdateText();
  if(confirmMessage)
   return confirm(confirmMessage);
  return false;
 },
 isInUploadCallback: function() {
  return false;
 }
});
var ControlTabIndexManager = ASPx.CreateClass(null, {
 constructor: function() {
  this.elementsWithChangedTabIndex = {};
 },
 getChangedElementsForControlId: function(id) {
  if(!this.elementsWithChangedTabIndex[id])
   this.elementsWithChangedTabIndex[id] = [];
  return this.elementsWithChangedTabIndex[id];
 },
 isElementWithChangedIndex: function(element) {
  for(var key in this.elementsWithChangedTabIndex)
   if(this.elementsWithChangedTabIndex.hasOwnProperty(key))
    if(this.elementsWithChangedTabIndex[key].indexOf(element) !== -1)
     return true;
  return false;
 },
 changeTabIndexAttribute: function(element, id) {
  var elements = this.getChangedElementsForControlId(id);
  ASPx.Attr.ChangeTabIndexAttribute(element);
  if(elements.indexOf(element) === -1)
   elements.push(element);
 },
 restoreTabIndexAttribute: function(element, id) {
  var elements = this.getChangedElementsForControlId(id),
   index = elements.indexOf(element);
  if(index !== -1) {
   elements.splice(index, 1);
   if(!this.isElementWithChangedIndex(element))
    ASPx.Attr.RestoreTabIndexAttribute(element);
  }
 }
});
ControlTabIndexManager.Instance = null;
ControlTabIndexManager.getInstance = function() {
 if(!ControlTabIndexManager.Instance)
  ControlTabIndexManager.Instance = new ControlTabIndexManager();
 return ControlTabIndexManager.Instance;
};
var ControlCallbackHandlersQueue = ASPx.CreateClass(null, {
 constructor: function (owner) {
  this.owner = owner;
  this.handlerInfos = [];
 },
 addCallbackHandler: function(handlerInfo) {
  this.handlerInfos.push(handlerInfo);
 },
 executeCallbacksHandlers: function() {
  for(var i = 0, handlerInfo; handlerInfo = this.handlerInfos[i]; i++)
   handlerInfo.handler.call(this.owner, handlerInfo.result);
  this.handlerInfos = [];
 }
});
var ControlCallbackQueueHelper = ASPx.CreateClass(null, {
 constructor: function (owner) {
  this.owner = owner;
  this.pendingCallbacks = [];
  this.receivedCallbacks = [];
  this.attachEvents();
 },
 showLoadingElements: function () {
  this.owner.ShowLoadingDiv();
  if (this.owner.IsCallbackAnimationEnabled())
   this.owner.StartBeginCallbackAnimation();
  else
   this.owner.ShowLoadingElementsInternal();
 },
 attachEvents: function () {
  this.owner.EndCallback.AddHandler(this.onEndCallback.aspxBind(this));
  this.owner.CallbackError.AddHandler(this.onCallbackError.aspxBind(this));
 },
 detachEvents: function () {
  this.owner.EndCallback.RemoveHandler(this.onEndCallback);
  this.owner.CallbackError.RemoveHandler(this.onCallbackError);
 },
 onCallbackError: function (owner, result) {
  this.sendErrorToChildControl(result);
 },
 ignoreDuplicates: function () {
  return true;
 },
 hasDuplicate: function (arg) {
  for (var i in this.pendingCallbacks) {
   if (this.pendingCallbacks[i].arg == arg && this.pendingCallbacks[i].state != ASPx.callbackState.aborted)
    return true;
  }
  return false;
 },
 getToken: function (halperContext, callbackInfo) {
  return {
   cancel: function () {
    if (callbackInfo.state == ASPx.callbackState.sent) {
     callbackInfo.state = ASPx.callbackState.aborted;
     halperContext.sendNext();
    }
    if (callbackInfo.state == ASPx.callbackState.inTurn)
     ASPx.Data.ArrayRemove(halperContext.pendingCallbacks, callbackInfo);
   },
   callbackId: -1
  };
 },
 sendCallback: function (arg, handlerContext, handler, commandName, onBeforeSend) {
  if (this.ignoreDuplicates() && this.hasDuplicate(arg))
   return false;
  var handlerContext = handlerContext || this.owner;
  var callbackInfo = {
   arg: arg,
   handlerContext: handlerContext,
   handler: handler || handlerContext.OnCallback,
   state: ASPx.callbackState.inTurn,
   callbackId: -1,
   onBeforeSend: onBeforeSend
  };
  this.pendingCallbacks.push(callbackInfo);
  if (!this.hasActiveCallback()) {
   this.createCallbackByCallbackInfo(callbackInfo, commandName);
  }
  return this.getToken(this, callbackInfo);
 },
 hasActiveCallback: function () {
  return this.getCallbacksInfoByState(ASPx.callbackState.sent).length > 0;
 },
 sendNext: function () {
  var nextCallbackInfo = this.getCallbacksInfoByState(ASPx.callbackState.inTurn)[0];
  if (nextCallbackInfo) {
   this.createCallbackByCallbackInfo(nextCallbackInfo);
   return nextCallbackInfo.callbackId;
  }
 },
 createCallbackByCallbackInfo: function(callbackInfo, commandName) {
  if(callbackInfo.onBeforeSend)
   callbackInfo.onBeforeSend();
  callbackInfo.callbackId = this.owner.CreateCallback(callbackInfo.arg, commandName);
  callbackInfo.state = ASPx.callbackState.sent;
 },
 onEndCallback: function () {
  if (!this.owner.isErrorOnCallback && this.hasPendingCallbacks()) {
   var curCallbackId;
   var curCallbackInfo;
   var handlerContext;
   for (var i in this.receivedCallbacks) {
    if(this.receivedCallbacks.hasOwnProperty(i)) {
     curCallbackId = this.receivedCallbacks[i];
     curCallbackInfo = this.getCallbackInfoById(curCallbackId);
     if (curCallbackInfo.state != ASPx.callbackState.aborted) {
      handlerContext = curCallbackInfo.handlerContext;
      if (handlerContext.OnEndCallback)
       handlerContext.OnEndCallback();
      this.sendNext();
     }
     ASPx.Data.ArrayRemove(this.pendingCallbacks, curCallbackInfo);
    }
   }
   ASPx.Data.ArrayClear(this.receivedCallbacks);
  }
 },
 hasPendingCallbacks: function () {
  return this.pendingCallbacks && this.pendingCallbacks.length && this.pendingCallbacks.length > 0;
 },
 processCallback: function (result, callbackId) {
  this.receivedCallbacks.push(callbackId);
  if (this.hasPendingCallbacks()) {
   var callbackInfo = this.getCallbackInfoById(callbackId);
   if (callbackInfo.state != ASPx.callbackState.aborted)
    callbackInfo.handler.call(callbackInfo.handlerContext, result);
  }
 },
 getCallbackInfoById: function (id) {
  for (var i in this.pendingCallbacks) {
   if (this.pendingCallbacks[i].callbackId == id)
    return this.pendingCallbacks[i];
  }
 },
 getCallbacksInfoByState: function (state) {
  var result = [];
  for (var i in this.pendingCallbacks) {
   if (this.pendingCallbacks[i].state == state)
    result.push(this.pendingCallbacks[i]);
  }
  return result;
 },
 sendErrorToChildControl: function (callbackObj) {
  if (!this.hasPendingCallbacks())
   return;
  var callbackInfo = this.getCallbackInfoById(callbackObj.callbackId || 0);
  if (!callbackInfo)
   return;
  var hasChildControlHandler = (callbackInfo.handlerContext != this.owner) && callbackInfo.handlerContext.OnCallbackError;
  if (hasChildControlHandler)
   callbackInfo.handlerContext.OnCallbackError.call(callbackInfo.handlerContext, callbackObj.message, callbackObj.data);
 }
});
var AccessibilityHelperBase = ASPx.CreateClass(null, {
 constructor: function(control) {
  this.control = control;
  this.timerID = -1;
  this.pronounceMessageTimeout = 500;
  this.activeItem = this.getItems()[0];
  this.pronounceIsStarted = false;
 },
 PronounceMessage: function(text, activeItemArgs, inactiveItemArgs, mainElementArgs, ownerMainElement) {   
  this.timerID = ASPx.Timer.ClearTimer(this.timerID);
  this.pronounceIsStarted = true;
  this.timerID = window.setTimeout(function() {
   this.PronounceMessageCore(text, activeItemArgs, inactiveItemArgs, mainElementArgs, ownerMainElement);
  }.aspxBind(this), this.getPronounceTimeout());
 },
 PronounceMessageCore: function(text, activeItemArgs, inactiveItemArgs, mainElementArgs, ownerMainElement) {
  if(!this.getItems())
   return;
  this.toogleItem();
  var mainElement = this.getMainElement();
  var activeItem = this.getItem(true);
  var inactiveItem = this.getItem();
  if(ASPx.Attr.GetAttribute(mainElement, "role") != "application")
   mainElementArgs = this.addArguments(mainElementArgs, { "aria-activedescendant" : activeItem.id });
  var messageAttrObj = {};
  var activeItemRole = ASPx.Attr.GetAttribute(activeItem, "role");
  var attrName = activeItemRole == "combobox" ? "aria-label" : "innerHtml";
  messageAttrObj[attrName] = ASPx.Str.EncodeHtml(text);
  activeItemArgs = this.addArguments(activeItemArgs, messageAttrObj);
  messageAttrObj[attrName] = "";
  inactiveItemArgs = this.addArguments(inactiveItemArgs, messageAttrObj);
  var errorTextElement = null;
  if(this.control.GetErrorCell()) {
   errorTextElement = this.getAriaExplanatoryTextManager().GetErrorTextElement();
   activeItemArgs = this.addArguments(activeItemArgs,   {"aria-invalid"  : !this.control.isValid ? "true" : "" });
   mainElementArgs = this.addArguments(mainElementArgs, { "aria-invalid" : "" });
   inactiveItemArgs = this.addArguments(inactiveItemArgs,  { "aria-invalid" : "" });
  }
  this.changeActivityAttributes(activeItem, activeItemArgs);
  if(errorTextElement) {
   this.getAriaExplanatoryTextManager().SetOrRemoveText([activeItem], errorTextElement, !this.control.isValid, false, true);
   this.getAriaExplanatoryTextManager().SetOrRemoveText([mainElement, inactiveItem], errorTextElement, false, false, false);
  }
  this.changeActivityAttributes(mainElement, mainElementArgs);
  if(!!ownerMainElement && ASPx.Attr.GetAttribute(ownerMainElement, "role") != "application")
   this.changeActivityAttributes(ownerMainElement, { "aria-activedescendant": activeItem.id });
  this.changeActivityAttributes(inactiveItem, inactiveItemArgs);
  this.pronounceIsStarted = false;
 },
 GetActiveElement: function(inputIsMainElement) {
  if(this.pronounceIsStarted) return null;
  var mainElement = inputIsMainElement ? this.control.GetInputElement() : this.getMainElement();
  var activeElementId = ASPx.Attr.GetAttribute(mainElement, 'aria-activedescendant');
  return activeElementId ? ASPx.GetElementById(activeElementId) : mainElement;
 },
 getMainElement: function() {
  if(!ASPx.IsExistsElement(this.mainElement))
   this.mainElement = this.control.GetAccessibilityAssistantElement();
  return this.mainElement;
 },
 getItems: function() {
  if(!ASPx.IsExistsElement(this.items))
   this.items = ASPx.GetChildElementNodes(this.getMainElement());
  return this.items;
 },
 getItem: function(isActive) {
  if(isActive)
   return this.activeItem;
  var items = this.getItems();
  return items[0] === this.activeItem ? items[1] : items[0];
 },
 getAriaExplanatoryTextManager: function() { return this.control.ariaExplanatoryTextManager; },
 getPronounceTimeout: function() { return this.pronounceMessageTimeout; },
 toogleItem: function() {
  this.activeItem = this.getItem();
 },
 addArguments: function(targetArgs, newArgs) {
  if(!targetArgs) targetArgs = { };
  for(var key in newArgs) {
   if(newArgs.hasOwnProperty(key) && !targetArgs.hasOwnProperty(key))
    targetArgs[key] = newArgs[key];
  }
  return targetArgs;
 },
 changeActivityAttributes: function(element, args) {
  if(!element)
   return;
  for(var key in args) {
   if(args.hasOwnProperty(key)) {
    var value = args[key];
    if(key == "innerHtml")
     ASPx.SetInnerHtml(element, value);
    else {
     var action = value !== "" ? ASPx.Attr.SetAttribute : ASPx.Attr.RemoveAttribute;
     action(element, key, value);
    }
   }
  }
 }
});
var AccessibilityPronouncer = ASPx.CreateClass(null, {
 constructor: function() {
  this.pronouncerId = "dxPronouncer";
  this.initialized = false;
  this.focusableMessageElement = null;
  this.messageElement = null;
  this.pronouncers = {
   live: new AccessibilityLivePronouncer(this),
   descendant: new AccessibilityDescendantPronouncer(this)
  };
 },
 Pronounce: function(args, type) {
  this.pronouncers[type].Pronounce(args);
 },
 EnsureInitialize: function() {
  if(!this.initialized)
   this.initialize();
 },
 RemoveState: function() {
  for(var pronouncer in this.pronouncers)
   if(this.pronouncers.hasOwnProperty(pronouncer))
    pronouncer.RemoveState();
 },
 RestoreControlState: function(type, mainElement) {
  this.pronouncers[type].RestoreControlState(mainElement);
 },
 RestoreElementsState: function(type, elements) {
  this.pronouncers[type].RestoreElementsState(elements);
 },
 RestoreElementState: function(type, element) {
  this.pronouncers[type].RestoreElementState(element);
 },
 initialize: function() {
  this.createFocusableMessageElement();
  this.createMessageElement();
  this.prepareFocusableMessageElement();
  this.setAttributesForKeyboardNavigation();
  this.initialized = true;
 },
 createFocusableMessageElement: function() {
  var focusableMessageElement = document.createElement("DIV");
  document.body.appendChild(focusableMessageElement);
  this.focusableMessageElement = focusableMessageElement;   
 },
 prepareFocusableMessageElement: function() {
  this.focusableMessageElement.className = "dxAIFME";
 },
 setAttributesForKeyboardNavigation: function() {
  ASPx.Attr.Aria.SetApplicationRole(this.focusableMessageElement);
  ASPx.Attr.Aria.SetSilence(this.focusableMessageElement);
 },
 createMessageElement: function() {
  var messageElement = document.createElement("DIV");
  messageElement.id = this.pronouncerId;
  ASPx.Attr.SetAttribute(messageElement, "role", "note");
  this.focusableMessageElement.appendChild(messageElement);
  this.messageElement = messageElement;
 },
 getMessage: function(messagePartsArg) {
  var messageParts = messagePartsArg.filter(function(x) { return ASPx.IsExists(x); });
  return messageParts.join(", ");
 }
});
var AccessibilityPronouncerBase = ASPx.CreateClass(null, {
 constructor: function() {
  this.state = { };
 },
 Pronounce: function(args) {
  var messageElement = this.getMessageElement();
  ASPx.Attr.Aria.SetOrRemoveLabel(messageElement);
  ASPx.SetInnerHtml(messageElement, "");
  this.PronounceCore(args);
 },
 PronounceCore: function(args) { },
 SaveElementState: function(element) { 
  if(this.state[element.id])
   return;
  this.state[element.id] = {
   element: element,
   descendant: ASPx.Attr.GetAttribute(element, ASPx.Attr.Aria.descendant)
  };
 },
 RemoveState: function() {
  this.state = { };
 },
 RestoreControlState: function(mainElement) { 
  for(var elementInfo in this.state) {
   if(this.state.hasOwnProperty(elementInfo)) {
    var element = this.state[elementInfo].element;
    if(!mainElement || ASPx.GetIsParent(mainElement, element))
     this.RestoreElementState(element);
   }
  }
 },
 RestoreElementsState: function(elements) { 
  for(var i = 0; i < elements.length; i++)
   this.RestoreElementState(elements[i]);
 },
 RestoreElementState: function(element) {
  var elementState = this.state[element.id];
  if(!elementState)
   return;
  ASPx.Attr.Aria.SetOrRemoveDescendant(element, elementState.descendant);
  delete this.state[element.id];
 },
 getMessage: function(args) {
  return ASPx.AccessibilityPronouncer.getMessage(args.messageParts);
 },
 getMessageElement: function() {
  return ASPx.AccessibilityPronouncer.messageElement;
 },
 getFocusableMessageElement: function() {
   return ASPx.AccessibilityPronouncer.focusableMessageElement;
 }
});
var AccessibilityLivePronouncer = ASPx.CreateClass(AccessibilityPronouncerBase, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
 },
 PronounceCore: function(args) {
  var message = this.getMessage(args);
  var messageElement = this.getMessageElement();
  ASPx.Attr.SetAttribute(this.getFocusableMessageElement(), "aria-live", "assertive");
  ASPx.Attr.Aria.SetAtomic(this.getFocusableMessageElement(), "true");
  ASPx.SetInnerHtml(messageElement, ASPx.Str.EncodeHtml(message));
 }
});
var AccessibilityDescendantPronouncer = ASPx.CreateClass(AccessibilityPronouncerBase, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
 },
 PronounceCore: function(args) {
  var message = this.getMessage(args);
  var activeElement = ASPx.GetActiveElement();
  var messageElement = this.getMessageElement();
  this.SaveElementState(activeElement);
  ASPx.Attr.RemoveAttribute(this.getFocusableMessageElement(), "aria-live");
  ASPx.Attr.RemoveAttribute(this.getFocusableMessageElement(), "aria-atomic");
  ASPx.Attr.Aria.SetOrRemoveLabel(messageElement, message);
  ASPx.Attr.Aria.SetOrRemoveDescendant(activeElement, messageElement.id);
 }
});
ASPx.AccessibilityPronouncerType = {
 live: "live",
 descendant: "descendant"
};
ASPx.AccessibilityPronouncer = new AccessibilityPronouncer();
var RestoreFocusHelper = ASPx.CreateClass(null, {
 constructor: function() {
  this.excludedIDs = [ "DXCBtn" ]; 
  this.pronouncerType = ASPx.AccessibilityPronouncerType.live;
  this.callbackQueue = [];
  this.Initialize();
 },
 Initialize: function() {
  var that = this;
  ASPx.attachToLoad(function() {
   ASPxClientControl.GetControlCollection().BeginCallback.AddHandler(that.OnBeginCallback, that);
   ASPxClientControl.GetControlCollection().EndCallback.AddHandler(that.OnEndCallback, that);
  });
 },
 OnBeginCallback: function(s, e) {
  var control = e.control;
  if(!control.allowRestoreFocusOnCallbacks())
   return;
  control.accessibilityFocusTreeLine = this.getFocusTreeLine(control);
  var controlHasCallbackTreeLine = this.callbackQueueContainsTreeLine(control);
  this.pushTreeLineInfoIntoCallbackQueue(control);
  if(control.accessibilityFocusTreeLine && !controlHasCallbackTreeLine)
   control.SendMessageToAssistiveTechnology(this.getDefaultCallbackMessage());
 },
 OnEndCallback: function(s, e) {
  var control = e.control;
  if(!control.allowRestoreFocusOnCallbacks())
   return;
  var treeLineInfo = this.shiftTreeLineInfoFromCallbackQueue(control);
  if(treeLineInfo.queueLength == 0) {
   if(!control.accessibilityFocusTreeLine && treeLineInfo.treeLine)
    control.accessibilityFocusTreeLine = treeLineInfo.treeLine;
   var focusElement = this.findFocusElement(control);
   var focusIsManagerByPopupwindow = this.isFocusManagedByActivePopupWindow(focusElement);
   var focusIsManagedByControl = control.shouldPreventFocusRestoringOnCallback && control.shouldPreventFocusRestoringOnCallback();
   if(!focusIsManagerByPopupwindow && !focusIsManagedByControl)
    ASPx.AccessibilityUtils.SetFocusAccessible(focusElement);
   delete control.accessibilityFocusTreeLine;
  }
 },
 pushTreeLineInfoIntoCallbackQueue: function(control) {
  var controlTreeLine = control.accessibilityFocusTreeLine ? control.accessibilityFocusTreeLine.slice(0) : null;
  if(!this.callbackQueue[control.name])
   this.callbackQueue[control.name] = [];
  this.callbackQueue[control.name].push(controlTreeLine);
 },
 shiftTreeLineInfoFromCallbackQueue: function(control) {
  var treeLineInfo = { queueLength: 0, treeLine: null };
  var treeLines = this.callbackQueue[control.name];
  if(treeLines && treeLines.length > 0) {
   treeLineInfo.treeLine = treeLines.shift();
   var linesCount = treeLines.length;
   treeLineInfo.queueLength = linesCount;
   if(linesCount > 0 && !treeLines[0] && treeLineInfo.treeLine)
    treeLines[0] = treeLineInfo.treeLine.slice(0);
  }
  return treeLineInfo;
 },
 callbackQueueContainsTreeLine: function(control) {
  var treeLines = this.callbackQueue[control.name];
  if(!treeLines || treeLines.length == 0) 
   return false;
  if(treeLines[treeLines.length - 1])
   return true;
  return false;
 },
 getDefaultCallbackMessage: function() {
  return ASPx.AccessibilitySR.DefaultCallbackMessage;
 },
 isFocusManagedByActivePopupWindow: function(focusElement) {
  var popupControl = this.getActivePopupControl();
  if(!popupControl || popupControl.accessibleFocusElement)
   return false;
  this.initializePopupAccessibleFocusElement(popupControl, focusElement);
  return popupControl.setFocusOnCallback;
 },
 getActivePopupControl: function() {
  var activePopupWindow = ASPx.GetPopupControlCollection && ASPx.GetPopupControlCollection().GetCurrentActiveWindowElement();
  if(!activePopupWindow)
   return null;
  var popupInfo = ASPx.GetPopupControlCollection().GetPopupWindowFromID(activePopupWindow.id);
  return popupInfo.popupControl;
 },
 initializePopupAccessibleFocusElement: function(popupControl, focusElement) {
  if(popupControl.setFocusOnCallback)
   popupControl.accessibleFocusElement = focusElement;
  else {
   var parentControl = popupControl.GetParentControl();
   if(parentControl && parentControl.GetMainElement())
    popupControl.accessibleFocusElement = ASPx.FindFirstChildActionElement(parentControl.GetMainElement());
  }
 },
 getFocusTreeLine: function(control) {
  var element = ASPx.GetActiveElement();
  if(!ASPx.IsExistsElement(element))
   return null;
  var mainElement = control.GetMainElement();
  if(!ASPx.GetIsParent(mainElement, element)) {
   var treeInfo = this.findFocusedControlElement(mainElement, element);
   element = treeInfo.focusElement;
   mainElement = treeInfo.rootElement;
  }
  return this.getTreeLineCore(mainElement, element);
 },
 getTreeLineCore: function(mainElement, element) {
  if(!element) return null;
  treeLine = [ ];
  while(element) {
   treeLine.push({ 
    id: element.id,
    tagName: element.tagName,
    index: ASPx.Data.ArrayIndexOf(element.parentNode.childNodes, element)
   });
   if(element === mainElement || element === document.body)
    break;
   element = element.parentNode;
  }
  return treeLine;
 },
 findFocusedControlElement: function(mainElement, activeElement) {
  var element = null;
  var parentElement = mainElement;
  var focusedEditor = ASPx.IsExists(ASPx.GetFocusedEditor) ? ASPx.GetFocusedEditor() : null;
  if(focusedEditor && ASPx.GetIsParent(mainElement, focusedEditor.GetMainElement()))
   element = focusedEditor.GetFocusableInputElement();
  else {
   if(mainElement && activeElement) {
    var mainControl = ASPx.GetClientControlByElementID(mainElement.id);
    var parentControls = ASPx.GetParentClientControls(activeElement.id);
    for(var i = parentControls.length - 1; i > -1; i--) {   
     if(mainControl.name == parentControls[i].name) {
      element = activeElement;
      var rootIndex = i > 0 ? i - 1 : i;
      parentElement = parentControls[rootIndex].GetMainElement();
      if(!parentElement && parentControls[rootIndex].GetCurrentWindowElement)
       parentElement = parentControls[rootIndex].GetCurrentWindowElement();
      break;
     }
    }
   }
  }
  return { focusElement: element, rootElement: parentElement }; 
 },
 findFocusElement: function(control) {
  if(!control.accessibilityFocusTreeLine)
   return;
  var treeLine = control.accessibilityFocusTreeLine.slice(0);
  var focusElementParent = this.findFocusElementParentById(treeLine);
  if(!focusElementParent) 
   return;
  return this.findFocusElementFromDOMTree(treeLine, focusElementParent);
 },
 findFocusElementParentById: function(treeLine) {
  for(var i = 0; i < treeLine.length; i++) {
   var id = treeLine[i].id;
   if(!this.isValidId(id))
    continue;
   var element = document.getElementById(id);
   if(element) {
    treeLine.splice(i, treeLine.length - i);
    treeLine.reverse();
    return element;
   }
  }
  return null;
 },
 findFocusElementFromDOMTree: function(treeLine, focusElementParent) {
  var element = focusElementParent;
  for(var i = 0; i < treeLine.length; i++) {
   var info = treeLine[i];
   if(info.index >= element.childNodes.length) {
    element = element.childNodes.length > 0 ? element.childNodes[element.childNodes.length - 1] : null;
    return this.findNeighbourFocusElement(element, focusElementParent);
   }
   var child = element.childNodes[info.index];
   if(child.tagName !== info.tagName)
    return this.findNeighbourFocusElement(child, focusElementParent);
   element = child;
  }
  return element;
 },
 findNeighbourFocusElement: function(element, focusElementParent) {
  ASPx.ActionElementsCache.BeginUsage();
  var result = this.findNeighbourFocusElementCore(element, focusElementParent);
  ASPx.ActionElementsCache.EndUsage();
  return result;
 },
 findNeighbourFocusElementCore: function(element, focusElementParent) {
  if(!element || !element.parentNode) return null;
  var neighbours = element.parentNode.childNodes;
  var indices = this.calcLeftRightIndices(ASPx.Data.ArrayIndexOf(neighbours, element), neighbours.length);
  for(var i = 0; i < indices.length; i++) {
   var index = indices[i];
   var actionElement = ASPx.FindFirstChildActionElement(neighbours[index]);
   if(actionElement)
    return actionElement;
  }
  if(element === focusElementParent)
   return null;
  return this.findNeighbourFocusElement(element.parentNode, focusElementParent);
 },
 calcLeftRightIndices: function(startIndex, count) {
  var indices = [ ];
  var incSides = [ 0, 0 ];
  var index = startIndex;
  for(var i = 0; i < count; i++) {
   indices.push(index);
   var even = i % 2 === 0;
   var nextIndex = this.calcNextIndex(startIndex, count, incSides, even);
   if(nextIndex < 0)
    nextIndex = this.calcNextIndex(startIndex, count, incSides, !even);
   index = nextIndex;
  }
  return indices;
 },
 calcNextIndex: function(startIndex, count, incSides, even) {
  var sideIndex = even ? 0 : 1;
  var inc = incSides[sideIndex];
  inc += even ? -1 : 1;
  var nextIndex = startIndex + inc;
  if(nextIndex >= 0 && nextIndex < count) {
   incSides[sideIndex] = inc;
   return nextIndex;
  }
  return -1;
 },
 isValidId: function(id) {
  return id && !this.isExcludedId(id);
 },
 isExcludedId: function(id) {
  var result = false;
  for(var i = 0; i < this.excludedIDs.length; i++) {
   if(id.indexOf(this.excludedIDs[i]) > -1) {
    result = true;
    break;
   }
  }
  return result;
 }
});
var EventStorage = ASPx.CreateClass(null, {
 constructor: function() {
  this.bag = { };
 },
 Save: function(e, data, overwrite) {
  var key = this.getEventKey(e);
  if(this.bag.hasOwnProperty(key) && !overwrite)
   return;
  this.bag[key] = data;
  window.setTimeout(function() { delete this.bag[key]; }.aspxBind(this), 100);
 },
 Load: function(e) {
  var key = this.getEventKey(e);
  return this.bag[key];
 },
 getEventKey: function(e) {
  if(ASPx.IsExists(e.timeStamp))
   return e.timeStamp.toString();
  var eventSource = ASPx.Evt.GetEventSource(e);
  var type = e.type.toString();
  return eventSource ? type + "_" + eventSource.uniqueID.toString() : type;
 }
});
ASPx.RestoreFocusHelper = new RestoreFocusHelper();
EventStorage.Instance = null;
EventStorage.getInstance = function() {
 if(!EventStorage.Instance)
  EventStorage.Instance = new EventStorage();
 return EventStorage.Instance;
};
var GetGlobalObject = function(objectName) {
 var fields = objectName.split('.');
 var obj = window[fields[0]];
 for(var i = 1; obj && i < fields.length; i++) {
  obj = obj[fields[i]];
 }
 return obj;
};
var GetExternalScriptProcessor = function() {
 return ASPx.ExternalScriptProcessor ? ASPx.ExternalScriptProcessor.getInstance() : null;
};
var SAVED_WIDTH_ATTR = "data-dx-ripple-saved-width";
var RIPPLE_FIXED_ROW_ATTR = "data-dx-ripple-locked";
var READ_ONLY_COMBOBOX_MARKER_CSS_CLASS = "dxICBReadonlyMarker";
var ThemesWithRipple = ['Material'];
var RippleHelper = {
 rippleTargetClassName: "dxRippleTarget",
 rippleTargetExternalClassName: "dxRippleTargetExternal",
 rippleContainerClassName: "dxRippleContainer",
 rippleClassName: "dxRipple",
 touchRadius: -1,
 isMobileExternalRipple: null,
 zoom: 1,
 Init: function() {
  if(this.getIsRippleFunctionalityEnabled()) {
   setTimeout(function() {
    this.calcTouchRadius();
   }.aspxBind(this), 0);
  }
 },
 calcTouchRadius: function() {
  var testBlock = document.createElement("DIV");
  ASPx.SetStyles(testBlock, {
   height: "1in",
   width: "1in",
   left: "-100%",
   top: "-100%",
   position: "absolute"
  });
  document.body.appendChild(testBlock);
  this.touchRadius = (1.8 / 2.54) * Math.max(testBlock.offsetWidth, testBlock.offsetHeight);
  document.body.removeChild(testBlock);
 },
 isRippleFunctionalityEnabled: null,
 checkRippleFunctionality: function() {
  if(ASPx.Browser.Safari && ASPx.Browser.Version <= 5.1)
   return false;
  for(var i = 0; i < ThemesWithRipple.length; i++) {
   var firstRippleThemeElement = document.querySelector("[class*='_" + ThemesWithRipple[i] + "']");
   if(firstRippleThemeElement)
    return true;
  }  
  return false;
 },
 ReInit: function() {
  this.isRippleFunctionalityEnabled = null;
  this.Init();
 },
 onDocumentMouseDown: function(evt) {
  if(RippleHelper.getIsRippleFunctionalityEnabled())
   RippleHelper.processMouseDown(evt);
 },
 getIsRippleFunctionalityEnabled: function() {
  if(!ASPx.IsExists(this.isRippleFunctionalityEnabled))
   this.isRippleFunctionalityEnabled = this.checkRippleFunctionality();
  return this.isRippleFunctionalityEnabled;
 },
   createTargetInfo: function(target) {
  return { 
   x: ASPx.GetAbsoluteX(target),
   y: ASPx.GetAbsoluteY(target),
   width: target.offsetWidth,
   height: target.offsetHeight,
   classNames: ASPx.GetClassNameList(target),
   getTarget: function() { return target; },
   getRect: function() { return {x: this.x, y: this.y, width: this.width, height: this.height }; }
  };
 },
 createEventInfo: function(evt) {
  return { x: this.getEventX(evt), y: this.getEventY(evt) };
 },
 processMouseDown: function(evt) {
  var evtSource = ASPx.Evt.GetEventSource(evt);
  var rippleTarget = this.getRippleTargetElement(evtSource);
  if(this.needToProcessRipple(rippleTarget, evtSource))
   this.processRipple(this.createTargetInfo(rippleTarget), this.createEventInfo(evt));
 },
 getRippleTargetElement: function(evtSource) {
  if(this.hasRippleMarker(evtSource))
   return evtSource;
  if(evtSource.tagName && evtSource.tagName.toLowerCase() == "input" && ASPx.ElementContainsCssClass(evtSource, "dxTI")) {
   var elements = ASPx.GetChildElementNodesByPredicate(evtSource.parentNode.parentNode, function(element) {
    return this.hasRippleMarker(element);
   }.aspxBind(this));
   return elements && elements[0];
  }
  return ASPx.GetParent(evtSource, function(element) {
   return this.hasRippleMarker(element);
  }.aspxBind(this));
 },
 hasRippleMarker: function(element) {
  if(!ASPx.IsExistsElement(element))
   return false;
  var computedStyles = window.getComputedStyle(element, ":before");
  if(ASPx.IsExists(computedStyles)) {
   var content = computedStyles.getPropertyValue("content");
   if(content.indexOf(this.rippleTargetExternalClassName) > -1) {
    ASPx.AddClassNameToElement(element, this.rippleTargetExternalClassName);
    return true;
   }
   return content.indexOf(this.rippleTargetClassName) > -1;
  }
  return false;
 },
 needToProcessRipple: function(rippleTarget, evtSource) {
  if(!rippleTarget || !ASPx.AnimationUtils)
   return false;
  var isClearButton = ASPx.ElementContainsCssClass(rippleTarget, "dxeButton") && rippleTarget.id && rippleTarget.id.indexOf("B-100") !== -1;
  var isEmptyCalendarDay = ASPx.ElementContainsCssClass(rippleTarget, "dxeCalendarDay") && ASPx.Str.Trim(rippleTarget.textContent) == "";
  var isReadonly = ASPx.ElementContainsCssClass(rippleTarget, READ_ONLY_COMBOBOX_MARKER_CSS_CLASS);
  var tempFixDisable = ASPx.ElementContainsCssClass(rippleTarget, "dxSwitcher") && ASPx.Browser.MacOSMobilePlatform;
  var rippleIsForbidden = isReadonly || isClearButton || isEmptyCalendarDay || ASPx.GetParentByPartialClassName(rippleTarget, "Disabled") ||
   ASPx.ElementContainsCssClass(rippleTarget, "dxgvBatchEditCell") || ASPx.ElementContainsCssClass(rippleTarget, "dxcvEditForm") ||
   ASPx.GetParentByPartialClassName(evtSource, "dxcvFocusedCell") || tempFixDisable;
  return !rippleIsForbidden;
 },
 hasBothOverflow: function(style) {
  return style.overflow == "scroll" || style.overflow == "auto" || style.overflow == "hidden";
 },
 hasOverflowX: function(style) {
  return style.overflowX == "scroll" || style.overflowX == "auto" || style.overflowX == "hidden";
 },
 hasOverflowY: function(style) {
  return style.overflowY == "scroll" || style.overflowY == "auto" || style.overflowY == "hidden";
 },
 getExternalRippleContainerSize: function(targetRect) {
  if(ASPx.Browser.MobileUI) {
   var origTouchRadius = this.getOriginTouchRadius();
   if(origTouchRadius < targetRect.width || origTouchRadius < targetRect.height)
    origTouchRadius = Math.max(targetRect.width, targetRect.height);
   return {x: targetRect.x + (targetRect.width - origTouchRadius) / 2, y: targetRect.y + (targetRect.height - origTouchRadius) / 2, width: origTouchRadius, height: origTouchRadius };
  }
  var result = { x: 0, y: 0, width: 0, height: 0 };
  var diff = targetRect.width - targetRect.height;
  if(diff > 0) {
   result.x = targetRect.x;
   result.y = targetRect.y - diff / 2;
   result.width = targetRect.width;
   result.height = targetRect.width;
  } else {
   result.x = targetRect.x + diff / 2;
   result.y = targetRect.y;
   result.width = targetRect.height;
   result.height = targetRect.height;
  }
  return result;
 },
 getInternalContainerSize: function(targetInfo) {
  var parentWithOverflow = RippleHelper.getParentWithOverflow(targetInfo.getTarget());
  if(!ASPx.IsExists(parentWithOverflow))
   return targetInfo;
  var parentWithOverflowStyle = ASPx.GetCurrentStyle(parentWithOverflow);
  var bothOverflow = this.hasBothOverflow(parentWithOverflowStyle);
  var overflowX = this.hasOverflowX(parentWithOverflowStyle);
  var overflowY = this.hasOverflowY(parentWithOverflowStyle);
  var parentRect = {
   x: ASPx.GetAbsoluteX(parentWithOverflow),
   y: ASPx.GetAbsoluteY(parentWithOverflow),
   width: parentWithOverflow.offsetWidth,
   height: parentWithOverflow.offsetHeight
  };
  return this.getInternalContainerSizeCore(targetInfo, parentRect, bothOverflow, overflowX, overflowY);
 },
 getInternalContainerSizeCore: function(targetRect, parentRect, bothOverflow, overflowX, overflowY) {
  var result = {};
  ASPx.Data.MergeHashTables(result, targetRect);
  if(bothOverflow || overflowX) {
   result.x = targetRect.x < parentRect.x ? parentRect.x : targetRect.x;
   if(targetRect.x + targetRect.width > parentRect.x + parentRect.width)
    result.width = parentRect.x + parentRect.width - targetRect.x;
   if(parentRect.x > targetRect.x)
    result.width -= (parentRect.x - targetRect.x);
  }
  if(bothOverflow || overflowY) {
   result.y = targetRect.y < parentRect.y ? parentRect.y : targetRect.y;
   if(targetRect.y + targetRect.height > parentRect.y + parentRect.height)
    result.height = parentRect.y + parentRect.height - targetRect.y;
   if(parentRect.y > targetRect.y)
    result.height -= (parentRect.y - targetRect.y);
  }
  return result;
 },
 calculateRippleContainerSize: function(targetInfo, isExternalRipple) {
  return isExternalRipple ? this.getExternalRippleContainerSize(targetInfo) : this.getInternalContainerSize(targetInfo);
 },
 getParentWithOverflow: function(rippleTarget) {
  var result = ASPx.GetParent(rippleTarget, function(element) {
   var elementStyle = ASPx.GetCurrentStyle(element);
   return this.hasBothOverflow(elementStyle) || this.hasOverflowX(elementStyle) || this.hasOverflowY(elementStyle);
  }.aspxBind(this));
  return result;
 },
 getDuration: function(targetInfo) {
  return this.IsExternalRipple(targetInfo) || ASPx.Browser.MobileUI ? 650 : 450;
 },
 createRippleTransition: function(container, rippleElement, radius, targetInfo) {
  var rippleSize = 2 * radius;
  var transitionProperties = {
   width: { from: 0, to: rippleSize, transition: ASPx.AnimationConstants.Transitions.RIPPLE, propName: "width", unit: "px" },
   height: { from: 0, to: rippleSize, transition: ASPx.AnimationConstants.Transitions.RIPPLE, propName: "height", unit: "px" },
   marginLeft: { from: 0, to: -rippleSize / 2, transition: ASPx.AnimationConstants.Transitions.RIPPLE, propName: "marginLeft", unit: "px" },
   marginTop: { from: 0, to: -rippleSize / 2, transition: ASPx.AnimationConstants.Transitions.RIPPLE, propName: "marginTop", unit: "px" },
   opacity: { from: 1, to: 0.05, transition: ASPx.AnimationConstants.Transitions.RIPPLE, propName: "opacity", unit: "%" }
  };
  var rippleTransition = ASPx.AnimationUtils.createMultipleAnimationTransition(rippleElement, {
   transition: ASPx.AnimationConstants.Transitions.RIPPLE,
   duration: this.getDuration(targetInfo),
   needForceTransitionEndByTimerFlag: true, 
   onComplete: function() {
    this.RemoveRippleContainer(container.parentElement);
   }.bind(this)
  });
  rippleTransition.Start(transitionProperties);
 },
 needForceTransitionEndByTimer: function() { return true; }, 
 calculateRadius: function(isExternalRipple, posX, posY, containerRect) {
  var radius = -1;
  if(isExternalRipple) {
   if(ASPx.Browser.MobileUI)
    radius = this.getOriginTouchRadius() / 2;
   else
    radius = Math.max(containerRect.height, containerRect.width);
  } else {
   var width1 = posX - containerRect.x;
   var width2 = containerRect.width - width1;
   var height1 = posY - containerRect.y;
   var height2 = containerRect.height - height1;
   var rippleWidth = Math.max(width1, width2);
   var rippleHeight = Math.max(height1, height2);
   radius = Math.sqrt(Math.pow(rippleHeight, 2) + Math.pow(rippleWidth, 2));
  }
  return radius;
 },
 createRippleElement: function(container, rippleCenter) {
  var rippleElement = document.createElement("DIV");
  rippleElement.className = this.rippleClassName;
  container.appendChild(rippleElement);
  ASPxClientUtils.SetAbsoluteX(rippleElement, rippleCenter.x);
  ASPxClientUtils.SetAbsoluteY(rippleElement, rippleCenter.y);
  return rippleElement;
 },
 processRipple: function(targetInfo, eventInfo) {
  this.initRippleProcess();
  var isExternalRipple = this.IsExternalRipple(targetInfo);
  var rippleCenter = this.getRippleCenter(targetInfo.getRect(), eventInfo, isExternalRipple);
  var container = this.createRippleContainer(targetInfo, isExternalRipple);
  var rippleElement = this.createRippleElement(container, rippleCenter);
  var radius = this.calculateRadius(isExternalRipple, rippleCenter.x, rippleCenter.y, this.getElementRect(container));
  this.createRippleTransition(container, rippleElement, radius, targetInfo);
 },
 initRippleProcess: function() {
  this.isMobileExternalRipple = null;
  this.zoom = screen.width / window.innerWidth;
 },
 getRippleCenter: function(targetInfo, eventInfo, isExternalRipple) {
  var posX = 0;
  var posY = 0;
  if(isExternalRipple) {
   posX = targetInfo.x + targetInfo.width / 2;
   posY = targetInfo.y + targetInfo.height / 2;
  } else {
   posX = eventInfo.x;
   posY = eventInfo.y;
  }
  return {x: posX, y: posY};
 },
 createRippleContainer: function(targetInfo, isExternalRipple) {
  var containerParent = targetInfo.getTarget();
  if(!containerParent)
   return;
  var containerTagName = containerParent.tagName == "TR" ? "TD" : "DIV";
  var container = document.createElement(containerTagName);
  container.className = this.rippleContainerClassName;
  if(containerParent.parentNode && containerParent.tagName == "IMG")
   containerParent = containerParent.parentNode;
  if(this.isARowInFixedLayoutTable(containerParent))
   this.lockFixedLayoutTableSizes(containerParent);
  containerParent.appendChild(container);
  if(isExternalRipple)
   container.style.borderRadius = "50%";
  var containerRect = this.calculateRippleContainerSize(targetInfo, isExternalRipple);
  this.assignContainerSettings(container, containerRect);
  return container;
 },
 isARowInFixedLayoutTable: function(containerParent) {
  if(containerParent.tagName !== "TR")
   return false;
  var parentTable = this.getParentTable(containerParent);
  return parentTable && ASPx.GetCurrentStyle(parentTable)["table-layout"] === "fixed";
 },
 processFirstRowOfFixedTable: function(containerRow, rowAction, cellAction) {
  var firstRow = this.getFirstRow(containerRow);
  rowAction(firstRow);
  var cells = ASPx.Data.CollectionToArray(firstRow.cells);
  cells.forEach(cellAction);
 },
 getParentTable: function(element) {
  var parentTable = element;
  while(parentTable && parentTable.tagName !== "TABLE")
   parentTable = parentTable.parentElement;
  return parentTable;
 },
 lockFixedLayoutTableSizes: function(containerRow) {
  var firstRow = this.getFirstRow(containerRow);
  if(this.incLockCount(firstRow) === 1) {
   var cells = ASPx.Data.CollectionToArray(firstRow.cells);
   var widths = cells.map(function(cell) { return cell.style.width; });
   var computedWidths = cells.map(function(cell) {
    return window.getComputedStyle(cell).width;
   });
   var fixWidth = function(cell, i) {
    if(ASPx.Attr.IsExistsAttribute(cell, SAVED_WIDTH_ATTR))
     return;
    if(widths[i])
     ASPx.Attr.SetAttribute(cell, SAVED_WIDTH_ATTR, widths[i]);
    cell.style.width = computedWidths[i];
   };
   cells.forEach(fixWidth);
  }
 }, 
 unlockFixedLayoutTableSizes: function(containerRow) {
  var firstRow = this.getFirstRow(containerRow);   
  if(this.decLockCount(firstRow) === 0) {
   var cells = ASPx.Data.CollectionToArray(firstRow.cells);
   var restoreState = function(cell) {
    if(ASPx.Attr.IsExistsAttribute(cell, SAVED_WIDTH_ATTR)) {
     cell.style.width = ASPx.Attr.GetAttribute(cell, SAVED_WIDTH_ATTR);
     ASPx.Attr.RemoveAttribute(cell, SAVED_WIDTH_ATTR);
    } else {
     cell.style.width = null;
    }
   };
   cells.forEach(restoreState);
  }
 },
 getFirstRow: function(containerRow) { return ASPx.GetChildByTagName(containerRow.parentElement, "TR", 0); },
 incLockCount: function(elem) { return this.changeLockCount(elem, 1); },
 decLockCount: function(elem) { return this.changeLockCount(elem, -1); },
 changeLockCount: function(elem, diff) {
  var lockCounter = this.getLockCount(elem);
  lockCounter += diff;
  lockCounter = Math.max(0, lockCounter);
  if(lockCounter === 0)
   ASPx.Attr.RemoveAttribute(elem, RIPPLE_FIXED_ROW_ATTR);
  else
   ASPx.Attr.SetAttribute(elem, RIPPLE_FIXED_ROW_ATTR, lockCounter);
  return lockCounter;
 },
 getLockCount: function(lockElement) {
  var attrValue = ASPx.Attr.GetAttribute(lockElement, RIPPLE_FIXED_ROW_ATTR);
  return parseInt(attrValue) || 0;
 },
 assignContainerSettings: function(container, containerRect) {
  var properties = {
   height: containerRect.height,
   width: containerRect.width,
   left: ASPx.PrepareClientPosForElement(containerRect.x, container, true),
   top: ASPx.PrepareClientPosForElement(containerRect.y, container, false)
  };
  if(ASPx.Browser.MobileUI)
   ASPx.Data.MergeHashTables(properties, {marginTop: 0, marginLeft: 0 });
  ASPx.SetStyles(container, properties, ASPx.Browser.MobileUI);
 },
 IsExternalRipple: function(targetInfo) {
  var hasExternalRippleClassName = ASPx.ElementContainsCssClass(targetInfo.getTarget(), this.rippleTargetExternalClassName);
  if(!ASPx.Browser.MobileUI)
   return hasExternalRippleClassName;
  return hasExternalRippleClassName || this.IsMobileExternalRipple(targetInfo);
 },
 IsMobileExternalRipple: function(targetInfo) {
  if(this.isMobileExternalRipple == null) {
   var originTouchRadius = this.getOriginTouchRadius();
   this.isMobileExternalRipple = ASPx.Browser.MobileUI && targetInfo.width < originTouchRadius && targetInfo.height < originTouchRadius;
  }
  return this.isMobileExternalRipple;
 },
 RemoveRippleContainer: function(element) {
  if(!element)
   return;
  var childs = ASPx.GetChildNodesByClassName(element, this.rippleContainerClassName);
  var rippleContainer = childs.length > 0 ? childs[0] : null;
  if(rippleContainer != null) {
   var containerParent = rippleContainer.parentNode;
   containerParent.removeChild(rippleContainer);
   if(this.isARowInFixedLayoutTable(containerParent))
    this.unlockFixedLayoutTableSizes(containerParent);
  }
 },
 getEventX: function(evt) {
  return ASPxClientUtils.GetEventX(evt);
 },
 getEventY: function(evt) {
  return ASPxClientUtils.GetEventY(evt);
 },
 getOriginTouchRadius: function() {
  return this.touchRadius / this.zoom;
 },
 getElementRect: function(element) {
  return { x: ASPx.GetAbsoluteX(element), y: ASPx.GetAbsoluteY(element), width: element.offsetWidth, height: element.offsetHeight };
 }
};
var AccessibilitySR = {
 AddStringResources: function(stringResourcesObj) {
  if(stringResourcesObj) {
   for(var key in stringResourcesObj)
    if(stringResourcesObj.hasOwnProperty(key))
     this[key] = stringResourcesObj[key];
  }
 }
};
ASPx.OrderedMap = OrderedMap;
ASPx.CollectionBase = CollectionBase;
ASPx.FunctionIsInCallstack = _aspxFunctionIsInCallstack;
ASPx.RaisePostHandlerOnPost = aspxRaisePostHandlerOnPost;
ASPx.GetPostHandler = aspxGetPostHandler;
ASPx.ProcessScriptsAndLinks = _aspxProcessScriptsAndLinks;
ASPx.InitializeLinks = _aspxInitializeLinks;
ASPx.InitializeScripts = _aspxInitializeScripts;
ASPx.RunStartupScripts = _aspxRunStartupScripts;
ASPx.IsStartupScriptsRunning = _aspxIsStartupScriptsRunning;
ASPx.AddScriptsRestartHandler = _aspxAddScriptsRestartHandler;
ASPx.GetFocusedElement = _aspxGetFocusedElement;
ASPx.GetDomObserver = _aspxGetDomObserver;
ASPx.CacheHelper = CacheHelper;
ASPx.ControlTree = ControlTree;
ASPx.ControlAdjuster = ControlAdjuster;
ASPx.GetControlAdjuster = GetControlAdjuster;
ASPx.ControlCallbackHandlersQueue = ControlCallbackHandlersQueue;
ASPx.ResourceManager = ResourceManager;
ASPx.UpdateWatcherHelper = UpdateWatcherHelper;
ASPx.EventStorage = EventStorage;
ASPx.GetGlobalObject = GetGlobalObject;
ASPx.GetExternalScriptProcessor = GetExternalScriptProcessor;
ASPx.CheckBoxCheckState = CheckBoxCheckState;
ASPx.CheckBoxInputKey = CheckBoxInputKey;
ASPx.CheckableElementStateController = CheckableElementStateController;
ASPx.CheckableElementHelper = CheckableElementHelper;
ASPx.CheckBoxInternal = CheckBoxInternal;
ASPx.CheckBoxInternalCollection = CheckBoxInternalCollection;
ASPx.ControlCallbackQueueHelper = ControlCallbackQueueHelper;
ASPx.FocusedStyleDecoration = FocusedStyleDecoration;
ASPx.EditorStyleDecoration = EditorStyleDecoration;
ASPx.TextEditorStyleDecoration = TextEditorStyleDecoration;
ASPx.AccessibilitySR = AccessibilitySR;
ASPx.KbdHelper = KbdHelper;
ASPx.AccessKeysHelper = AccessKeysHelper;
ASPx.AccessKey = AccessKey;
ASPx.IFrameHelper = IFrameHelper;
ASPx.Ident = Ident;
ASPx.TouchUIHelper = TouchUIHelper;
ASPx.ControlUpdateWatcher = ControlUpdateWatcher;
ASPx.ControlTabIndexManager = ControlTabIndexManager;
ASPx.AccessibilityHelperBase = AccessibilityHelperBase;
ASPx.RippleHelper = RippleHelper;
ASPx.ThemesWithRipple = ThemesWithRipple;
window.ASPxClientEvent = ASPxClientEvent;
window.ASPxClientEventArgs = ASPxClientEventArgs;
window.ASPxClientCancelEventArgs = ASPxClientCancelEventArgs;
window.ASPxClientProcessingModeEventArgs = ASPxClientProcessingModeEventArgs;
window.ASPxClientProcessingModeCancelEventArgs = ASPxClientProcessingModeCancelEventArgs;
ASPx.Evt.AttachEventToDocument(TouchUIHelper.touchMouseDownEventName, RippleHelper.onDocumentMouseDown);
ASPx.classesScriptParsed = true;
})(ASPx, { GCCheckInterval: 5000 });

(function () {
 IntersectionObserversManager = ASPx.CreateClass(null, {
  constructor: function() {
   this.rootElementToObserverMap = this.createMap();
   this.elementToHandlerMap = this.createMap();
   this.clearInvalidElementsInterval = null;
   this.clearInvalidElementsPeriod = 5000;
  },
  AddTargetElement: function(element, rootElement, visibilityChangedHandler) {
   this.addTargetElementCore(element, rootElement, visibilityChangedHandler);
  },
  SubscribeElemensVisibilityChangeInBrowserWindow: function (element, visibilityChangedHandler) {
   this.addTargetElementCore(element, null, visibilityChangedHandler);
  },
  createMap: function() {
   return new Map();
  },
  getObserver: function() {
   return IntersectionObserver;
  },
  initializeObserver: function(rootElement) {
   if(!this.rootElementToObserverMap.get(rootElement)) {
    var options = {
     root: rootElement,
     rootMargin: '-1px',
     threshold: 0.0 
    };
    var observerClass = this.getObserver();
    var observer = new observerClass(this.visibilityChanged.bind(this), options);
    this.rootElementToObserverMap.set(rootElement, observer);
   }
  },
  addTargetElementCore: function(element, rootElement, visibilityChangedHandler) {
   this.initializeObserver(rootElement);
   if(!this.isAlreadyObserved(element)) {
    var observer = this.rootElementToObserverMap.get(rootElement);
    if(observer) {
     observer.observe(element);
     this.setObservedMarker(element);
     this.setElementVisibilityChangedHandler(element, visibilityChangedHandler, observer);
     if(this.clearInvalidElementsInterval === null) {
      this.clearInvalidElementsInterval = setInterval(this.removeDeletedElements.bind(this), this.clearInvalidElementsPeriod);
     }
    }
   }
  },
  visibilityChanged: function(entries, observer) {
   entries.forEach(function (entry) {
    if(ASPx.IsExistsElement(entry.target)){
     var element = this.elementToHandlerMap.get(observer);
     if(element) {
      var handler = element.get(entry.target);
      if(handler)
       handler(entry.isIntersecting);
     }
    }
   }.bind(this));
  },
  removeDeletedElements: function() {
   this.elementToHandlerMap.forEach(function(elements, observer) {
    elements.forEach(function(handler, element) {
     if(!ASPx.IsExistsElement(element)) {
      elements.delete(element);
     }
    }.bind(this));
    if(elements.size === 0) {
     this.elementToHandlerMap.delete(observer);
    }
   }.bind(this));
   if(this.elementToHandlerMap.size === 0) {
    clearInterval(this.clearInvalidElementsInterval);
    this.clearInvalidElementsInterval = null;
   }
  },
  setElementVisibilityChangedHandler: function(element, visibilityChangedHandler, observer) {
   if(!this.elementToHandlerMap.get(observer))
    this.elementToHandlerMap.set(observer, this.createMap());
   var el = this.elementToHandlerMap.get(observer);
   if(el)
    el.set(element, visibilityChangedHandler);
  },
  isAlreadyObserved: function(element) {
   return !!element.dxObserved;
  },
  setObservedMarker: function(element) {
   element.dxObserved = true;
  },
  reset: function() {
   this.rootElementToObserverMap.forEach(function(observer, rootElement) {
    observer.disconnect();
   }.bind(this));
   this.rootElementToObserverMap = this.createMap();
   this.elementToHandlerMap = this.createMap();
   this.clearInvalidElementsInterval = null;
   this.clearInvalidElementsPeriod = 5000;
  }
 });
 IntersectionObserversManagerForOldBrowsers = ASPx.CreateClass(null, {
  SubscribeElemensVisibilityChangeInBrowserWindow: function() { }
 });
 ASPx.IntersectionObserversManager = ASPx.IntersectionObserversManager || ((typeof(IntersectionObserver) !== "undefined") ? new IntersectionObserversManager() : new IntersectionObserversManagerForOldBrowsers());
}
)(ASPx);

(function() {
var CheckingScriptObjectCommand = ASPx.CreateClass(null, {
 constructor: function(scriptName, markerObjectName) {
  this.scriptName = scriptName;
  this.markerObjectName = markerObjectName;
  this.isExisted = false;
 },
 Run: function() {
  var markerObj = this.GetMarkerObject();
  this.isExisted = !!markerObj;
  if(this.isExisted)
   markerObj.DXPatched = true;
 },
 GetErrorMessage: function() {
  return this.GetErrorMessageCore(true);
 },
 GetErrorMessageCore: function(isScriptRequired){
  var markerObj = this.GetMarkerObject();
  if(this.isExisted && markerObj && markerObj.DXPatched || !isScriptRequired && !markerObj)
   return null;
  if(isScriptRequired && !this.GetMarkerObject()){
   if(this.isExisted)
    return this.scriptName + " script was attached but has been overridden.";
   else
    return this.scriptName + " script was not attached.";
  }
  if(!this.isExisted)
   return this.scriptName + " script was attached after DevExpress scripts.";
  return this.scriptName + " script was attached multiple times and mixed up with DevExpress scripts.";
 },
 GetMarkerObject: function() {
  return ASPx.GetGlobalObject(this.markerObjectName);
 }
});
var PatchScriptCommand = ASPx.CreateClass(CheckingScriptObjectCommand, {
 constructor: function(scriptName, markerObjectName, patchMethod, required) {
  this.constructor.prototype.constructor.call(this, scriptName, markerObjectName);
  this.required = required;
  this.patchMethod = patchMethod;
 },
 Run: function() {
  CheckingScriptObjectCommand.prototype.Run.call(this);
  if(this.isExisted)
   this.patchMethod();
 },
 GetErrorMessage: function() {  
  return this.GetErrorMessageCore(this.required);
 }
});
var ExternalScriptProcessor = ASPx.CreateClass(null, {
 constructor: function() {
  this.commands = {};
 },
 Process: function(scriptName, markerObjectName, patchMethod, required) {
  var newCommand = this.CreateCommand(scriptName, markerObjectName, patchMethod, !!required);
  var oldCommand = this.commands[markerObjectName];
  if(oldCommand) {
   if(!oldCommand.patchMethod && !newCommand.patchMethod)
    newCommand = null;
   else if(newCommand.patchMethod && (!oldCommand.patchMethod || oldCommand.required))
    newCommand.required = true;
   else if(oldCommand.patchMethod && !newCommand.patchMethod) {
    oldCommand.required = true;
    newCommand = null;
   }
  }
  if(newCommand) {
   this.commands[markerObjectName] = newCommand;
   newCommand.Run();
  }
 },
 CreateCommand: function(scriptName, markerObjectName, patchMethod, required) {
  if(patchMethod)
   return new PatchScriptCommand(scriptName, markerObjectName, patchMethod, required);
  return new CheckingScriptObjectCommand(scriptName, markerObjectName);
 },
 ShowErrorMessages: function() {
  var messages = this.GetErrorMessages();
  var console = window.console;
  if(!messages.length || !console || !ASPx.IsFunction(console.error))
   return;
  for(var i = 0; i < messages.length; i++) {
   console.error(messages[i]);
  }
  ASPx.ShowKBErrorMessage("Please check the correctness of script registration on the page. For details, see ", "T272309");
 },
 GetErrorMessages: function() {
  var messages = [];
  for (var key in this.commands) {
   if (this.commands.hasOwnProperty(key)) {
    var message = this.commands[key].GetErrorMessage();
    if (message)
     messages.push(message);
   }
  }
  return messages;
 }
});
ExternalScriptProcessor.Instance = null;
ExternalScriptProcessor.getInstance = function() {
 if(!ExternalScriptProcessor.Instance)
  ExternalScriptProcessor.Instance = new ExternalScriptProcessor();
 return ExternalScriptProcessor.Instance;
};
ASPx.ExternalScriptProcessor = ExternalScriptProcessor;
})();
(function module(ASPx) {
ASPx.modules.Controls = module;
var ASPxClientBeginCallbackEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(command){
  this.constructor.prototype.constructor.call(this);
  this.command = command;
 }
});
var ASPxClientGlobalBeginCallbackEventArgs = ASPx.CreateClass(ASPxClientBeginCallbackEventArgs, {
 constructor: function(control, command){
  this.constructor.prototype.constructor.call(this, command);
  this.control = control;
 }
});
var ASPxClientEndCallbackEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(command){
  this.constructor.prototype.constructor.call(this);
  this.command = command;
 }
});
var ASPxClientGlobalEndCallbackEventArgs = ASPx.CreateClass(ASPxClientEndCallbackEventArgs, {
 constructor: function(control){
  this.constructor.prototype.constructor.call(this);
  this.control = control;
 }
});
var ASPxClientCustomDataCallbackEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(result) {
  this.constructor.prototype.constructor.call(this);
  this.result = result;
 }
});
var ASPxClientCallbackErrorEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (message, callbackId) {
  this.constructor.prototype.constructor.call(this);
  this.message = message;
  this.handled = false;
  this.callbackId = callbackId;
 }
});
var ASPxClientGlobalCallbackErrorEventArgs = ASPx.CreateClass(ASPxClientCallbackErrorEventArgs, {
 constructor: function (control, message, callbackId) {
  this.constructor.prototype.constructor.call(this, message, callbackId);
  this.control = control;
 }
});
var ASPxClientValidationCompletedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (container, validationGroup, invisibleControlsValidated, isValid, firstInvalidControl, firstVisibleInvalidControl) {
  this.constructor.prototype.constructor.call(this);
  this.container = container;
  this.validationGroup = validationGroup;
  this.invisibleControlsValidated = invisibleControlsValidated;
  this.isValid = isValid;
  this.firstInvalidControl = firstInvalidControl;
  this.firstVisibleInvalidControl = firstVisibleInvalidControl;
 }
});
var ASPxClientControlsInitializedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(isCallback) {
  this.isCallback = isCallback;
 }
});
var ASPxClientControlBeforePronounceEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(messageParts, control){
  this.constructor.prototype.constructor.call(this);
  this.messageParts = messageParts;
  this.control = control;
 }
});
var ASPxClientControlUnloadEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(control){
  this.constructor.prototype.constructor.call(this);
  this.control = control;
 }
});
var ASPxClientEndFocusEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(item) {
  this.constructor.prototype.constructor.call(this);
  this.item = item;
 }
});
var ASPxClientItemFocusedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(item) {
  this.constructor.prototype.constructor.call(this);
  this.item = item;
 }
});
var BeforeInitCallbackEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(callbackOwnerID){
  this.constructor.prototype.constructor.call(this);
  this.callbackOwnerID = callbackOwnerID;
 }
});
var ASPxClientBrowserWindowResizedInternalEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(eventInfo) {
  this.constructor.prototype.constructor.call(this);
  this.htmlEvent = eventInfo.htmlEvent;
  this.windowClientWidth = eventInfo.wndWidth;
  this.windowClientHeigth = eventInfo.wndHeight;
  this.previousWindowClientWidth = eventInfo.prevWndWidth;
  this.previousWindowClientHeight = eventInfo.prevWndHeight;
  this.virtualKeyboardShownOnAndroid = eventInfo.virtualKeyboardShownOnAndroid;
 }
});
ASPx.createControl = function(type, name, windowName, properties, events, setupMethod, data){
 var globalName = windowName && windowName.length > 0 ? windowName : name;
 var dxo = new type(name);
 var haveWrapper = ASPx.Platform === "NETCORE" && dxo.createWrapper && !DevExpress.AspNetCore.Internal.BackwardCompatibility.useLegacyClientAPI;
 if(haveWrapper) {
  window[globalName] = dxo.createWrapper();
  dxo.aspNetCoreWrapperInstance = window[globalName];
 }
 else
  dxo.InitGlobalVariable(globalName);
 if(properties)
  dxo.SetProperties(properties);
 if(events)
  dxo.SetEvents(events);
 if(setupMethod)
  setupMethod.call(dxo);
 if(data)
  dxo.SetData(data);
 dxo.AfterCreate();
};
var ASPxClientControlBase = ASPx.CreateClass(null, {
 constructor: function(name){
  this.name = name;
  this.uniqueID = name;   
  this.globalName = name;
  this.stateObject = null;
  this.needEncodeState = true;
  this.encodeHtml = true;
  this.enabled = true;
  this.clientEnabled = true;
  this.savedClientEnabled = true;
  this.clientVisible = true;
  this.accessibilityCompliant = false;
  this.parseJSPropertiesOnCallbackError = false;
  this.autoPostBack = false;
  this.allowMultipleCallbacks = true;
  this.callBack = null;
  this.enableCallbackAnimation = false;
  this.enableSlideCallbackAnimation = false;
  this.slideAnimationDirection = null;
  this.beginCallbackAnimationProcessing = false;
  this.endCallbackAnimationProcessing = false;
  this.savedCallbackResult = null;
  this.savedCallbacks = null;
  this.isCallbackAnimationPrevented = false;
  this.lpDelay = 300;
  this.lpTimer = -1;
  this.requestCount = 0;
  this.enableSwipeGestures = false;
  this.disableSwipeGestures = false;
  this.supportGestures = false;
  this.repeatedGestureValue = 0;
  this.repeatedGestureCount = 0;
  this.isInitialized = false;
  this.initialFocused = false;
  this.leadingAfterInitCall = ASPxClientControl.LeadingAfterInitCallConsts.None; 
  this.serverEvents = [];
  this.loadingPanelElement = null;
  this.loadingDivElement = null;  
  this.hasPhantomLoadingElements = false;
  this.mainElement = null;
  this.touchUIMouseScroller = null;
  this.hiddenFields = {};
  this.scPrefix = "dx";
  this.callbackHandlersQueue = new ASPx.ControlCallbackHandlersQueue(this);
  this.callbackCommand = {};
  this.currentCallbackID = -1;
  this.InitializeIntersectionObserversManager();
  this.Init = new ASPxClientEvent();
  this.BeginCallback = new ASPxClientEvent();
  this.EndCallback = new ASPxClientEvent();
  this.EndCallbackAnimationStart = new ASPxClientEvent();
  this.CallbackError = new ASPxClientEvent();
  this.CustomDataCallback = new ASPxClientEvent();
  this.BeforePronounce = new ASPxClientEvent();
  this.Unload = new ASPxClientEvent();
  this.Disposed = new ASPxClientEvent(); 
  aspxGetControlCollection().Add(this);
 },
 Initialize: function() {
  if(this.callBack != null)
   this.InitializeCallBackData();
  if (this.useCallbackQueue())
   this.callbackQueueHelper = new ASPx.ControlCallbackQueueHelper(this);
  ASPx.AccessibilityUtils.createAccessibleBackgrounds(this);
  if(this.accessibilityCompliant)
   ASPx.AccessibilityPronouncer.EnsureInitialize();
 },
 FinalizeInitialization: function() { },
 InlineInitialize: function() {
  this.savedClientEnabled = this.clientEnabled;
 },
 InitializeGestures: function() {
  if(this.isSwipeGesturesEnabled() && this.supportGestures) {
   ASPx.GesturesHelper.AddSwipeGestureHandler(this.name, 
    function() { return this.GetCallbackAnimationElement(); }.aspxBind(this), 
    function(evt) { return this.CanHandleGestureCore(evt); }.aspxBind(this), 
    function(value) { return this.AllowStartGesture(value); }.aspxBind(this),
    function(value) { return this.StartGesture(); }.aspxBind(this),
    function(value) { return this.AllowExecuteGesture(value); }.aspxBind(this),
    function(value) { this.ExecuteGesture(value); }.aspxBind(this),
    function(value) { this.CancelGesture(value); }.aspxBind(this),
    this.GetDefaultanimationEngineType(),
    this.rtl
   );
   if(ASPx.Browser.MSTouchUI)
    this.touchUIMouseScroller = ASPx.MouseScroller.Create(
     function() { return this.GetCallbackAnimationElement(); }.aspxBind(this),
     function() { return null; },
     function() { return this.GetCallbackAnimationElement(); }.aspxBind(this),
     function(element) { return this.NeedPreventTouchUIMouseScrolling(element); }.aspxBind(this),
     true
    );
  }
 },
 isSwipeGesturesEnabled: function() {
  return !this.disableSwipeGestures && (this.enableSwipeGestures || ASPx.Browser.TouchUI);
 },
 isSlideCallbackAnimationEnabled: function() {
  return this.enableSlideCallbackAnimation || this.isSwipeGesturesEnabled(); 
 },
 InitGlobalVariable: function(varName){
  if(!window) return;
  this.globalName = varName;
  window[varName] = this;
 },
 SetElementDisplay: function(element, value, checkCurrentStyle, makeInline) {
  ASPx.SetElementDisplay(element, value, checkCurrentStyle, makeInline);
 },
 SetProperties: function(properties, obj){
  if(!obj) obj = this;
  var isAspNetCoreWrapperInstanceExist = !!obj.aspNetCoreWrapperInstance;
  for(var name in properties){
   if(!properties.hasOwnProperty(name)) continue;
   obj[name] = properties[name];
   if(isAspNetCoreWrapperInstanceExist && name.indexOf("cp") === 0)
    obj.aspNetCoreWrapperInstance[name] = properties[name]; 
  }
 },
 SetEvents: function(events, obj){
  if(!obj) obj = this;
  for(var name in events){
   if(events.hasOwnProperty(name) && obj[name] && obj[name].AddHandler)
    obj[name].AddHandler(events[name]);
  }
 },
 SetData: function(data){
 },
 useCallbackQueue: function(){
  return false;
 },
 NeedPreventTouchUIMouseScrolling: function(element) {
  return false;
 },
 InitializeFocus: function() {
  if(this.initialFocused && this.IsVisible()) {
   if(ASPxClientUtils.iOSPlatform || ASPxClientUtils.androidPlatform)
    setTimeout(function() { this.Focus(); }.bind(this), ASPx.FOCUS_TIMEOUT);
   else
    this.Focus();
  }
 },
 AfterCreate: function() {
  this.AddDefaultStateControllerItems();
  this.InlineInitialize();
  this.InitializeGestures();
 },
 AfterInitialize: function() {
  this.initializeAriaDescriptor();
  this.InitializeFocus();
  this.isInitialized = true;
  this.RaiseInit();
  if(this.savedCallbacks) {
   for(var i = 0; i < this.savedCallbacks.length; i++) 
    this.CreateCallbackInternal(this.savedCallbacks[i].arg, this.savedCallbacks[i].command, 
     false, this.savedCallbacks[i].callbackInfo);
   this.savedCallbacks = null;
  }
 },
 InitializeCallBackData: function() {
 },
 AtlasPreInitialize: function() {
 },
 AtlasInitialize: function() {
 },
 IsDOMDisposed: function() { 
  return !ASPx.IsExistsElement(this.GetMainElement());
 },
 initializeAriaDescriptor: function() {
  if(this.ariaDescription) {
   var descriptionObject = ASPx.Json.Eval(this.ariaDescription);
   if(descriptionObject) {
    this.ariaDescriptor = new AriaDescriptor(this, descriptionObject);
    this.applyAccessibilityAttributes(this.ariaDescriptor); 
   }
  }
 },
 applyAccessibilityAttributes: function() { },
 setAriaDescription: function(selector, argsList) {
  if(this.ariaDescriptor)
   this.ariaDescriptor.setDescription(selector, argsList || [[]]);
 },
 allowRestoreFocusOnCallbacks: function(){
  return this.accessibilityCompliant;
 },
 HtmlEncode: function(text) {
  return this.encodeHtml ? ASPx.Str.EncodeHtml(text) : text;
 },
 IsServerEventAssigned: function(eventName){
  return ASPx.Data.ArrayIndexOf(this.serverEvents, eventName) >= 0;
 },
 OnPost: function(args){
  this.SerializeStateHiddenField();
 },
 SerializeStateHiddenField: function() {
  this.UpdateStateObject();
  if(this.stateObject != null)
   this.UpdateStateHiddenField();
 },
 OnPostFinalization: function(args){
 },
 UpdateStateObject: function(){
 },
 UpdateStateObjectWithObject: function(obj){
  if(!obj) return;
  if(!this.stateObject)
   this.stateObject = { };
  for(var key in obj)
   if(obj.hasOwnProperty(key))
    this.stateObject[key] = obj[key];
 },
 UpdateStateHiddenField: function() {
  var stateHiddenField = this.GetStateHiddenField();
  if(stateHiddenField) {
   var stateObjectStr = ASPx.Json.ToJson(this.stateObject, !this.needEncodeState);
   stateHiddenField.value = this.needEncodeState ? ASPx.Str.EncodeHtml(stateObjectStr) : stateObjectStr;
  }
 },
 GetStateHiddenField: function() {
  return this.GetHiddenField(this.GetStateHiddenFieldName(), this.GetStateHiddenFieldID(), 
   this.GetStateHiddenFieldParent(), this.GetStateHiddenFieldOrigin());
 },
 GetStateHiddenFieldName: function() {
  return this.uniqueID;
 },
 GetStateHiddenFieldID: function() {
  return this.name + "_State";
 },
 GetStateHiddenFieldOrigin: function() {
  return this.GetMainElement();
 },
 GetStateHiddenFieldParent: function() {
  var element = this.GetStateHiddenFieldOrigin();
  return element ? element.parentNode : null;
 },
 GetHiddenField: function(name, id, parent, beforeElement) {
  var hiddenField = this.hiddenFields[id];
  if(!hiddenField || !ASPx.IsValidElement(hiddenField)) {
   if(parent) {
    var existingHiddenField = ASPx.GetElementById(this.GetStateHiddenFieldID());
    this.hiddenFields[id] = hiddenField = existingHiddenField || ASPx.CreateHiddenField(name, id);
    if(existingHiddenField)
     return existingHiddenField;
    if(beforeElement)
     parent.insertBefore(hiddenField, beforeElement);
    else
     parent.appendChild(hiddenField);
   }
  }
  return hiddenField;
 },
 GetChildElement: function(idPostfix){
  var mainElement = this.GetMainElement();
  if(idPostfix.charAt && idPostfix.charAt(0) !== "_")
   idPostfix = "_" + idPostfix;
  return mainElement ? ASPx.CacheHelper.GetCachedChildById(this, mainElement, this.name + idPostfix) : null;
 },
 getChildControl: function(idPostfix) {
  var result = null;
  var childControlId = this.getChildControlUniqueID(idPostfix);
  ASPx.GetControlCollection().ProcessControlsInContainer(this.GetMainElement(), function(control) {
   if(control.uniqueID == childControlId)
    result = control;
  });
  return result;  
 },
 getChildControlUniqueID: function(idPostfix) {
  idPostfix = idPostfix.split("_").join("$");
  if(idPostfix.charAt && idPostfix.charAt(0) !== "$")
   idPostfix = "$" + idPostfix;
  return this.uniqueID + idPostfix;  
 },
 getInnerControl: function(idPostfix) {
  var name = this.name + idPostfix;
  var result = window[name];
  return result && Ident.IsASPxClientControl(result)
   ? result
   : null;
 },
 GetParentForm: function(){
  return ASPx.GetParentByTagName(this.GetMainElement(), "FORM");
 },
 GetMainElement: function(){
  if(!ASPx.IsExistsElement(this.mainElement))
   this.mainElement = ASPx.GetElementById(this.GetMainElementId());
  return this.mainElement;
 },
 GetMainElementId: function() {
  return this.name;
 },
 IsLoadingContainerVisible: function(){
  return this.IsVisible();
 },
 GetLoadingPanelElement: function(){
  return ASPx.GetElementById(this.name + "_LP");
 },
 GetClonedLoadingPanel: function(){
  return document.getElementById(this.GetLoadingPanelElement().id + "V"); 
 },
 CloneLoadingPanel: function(element, parent) {
  var clone = element.cloneNode(true);
  clone.id = element.id + "V";
  parent.appendChild(clone);
  return clone;
 },
 CreateLoadingPanelWithoutBordersInsideContainer: function(container) {
  var loadingPanel = this.CreateLoadingPanelInsideContainer(container, false, true, true);
  var contentStyle = ASPx.GetCurrentStyle(container);
  if(!loadingPanel || !contentStyle)
   return;
  var elements = [ ];
  var table = (loadingPanel.tagName == "TABLE") ? loadingPanel : ASPx.GetNodeByTagName(loadingPanel, "TABLE", 0);
  if(table != null)
   elements.push(table);
  else
   elements.push(loadingPanel);
  var cells = ASPx.GetNodesByTagName(loadingPanel, "TD");
  if(!cells) cells = [ ];
  for(var i = 0; i < cells.length; i++)
   elements.push(cells[i]);
  for(var i = 0; i < elements.length; i++) {
   var el = elements[i];
   el.style.backgroundColor = contentStyle.backgroundColor;
   ASPx.RemoveBordersAndShadows(el);
  }
 },
 CreateLoadingPanelInsideContainer: function(parentElement, hideContent, collapseHeight, collapseWidth) {
  if(this.ShouldHideExistingLoadingElements())
   this.HideLoadingPanel();
  if(parentElement == null)
   return null;
  if(!this.IsLoadingContainerVisible()) {
   this.hasPhantomLoadingElements = true;
   return null;
  }
  var element = this.GetLoadingPanelElement();
  if(element != null){
   var width = collapseWidth ? 0 : ASPx.GetClearClientWidth(parentElement);
   var height = collapseHeight ? 0 : ASPx.GetClearClientHeight(parentElement);
   if(hideContent){
    for(var i = parentElement.childNodes.length - 1; i > -1; i--){
     if(parentElement.childNodes[i].style)
      parentElement.childNodes[i].style.display = "none";
     else if(parentElement.childNodes[i].nodeType == 3) 
      parentElement.removeChild(parentElement.childNodes[i]);
    }
   }
   else
    parentElement.innerHTML = "";
   var table = document.createElement("TABLE");
   parentElement.appendChild(table);
   table.border = 0;
   table.cellPadding = 0;
   table.cellSpacing = 0;
   ASPx.SetStyles(table, {
    width: (width > 0) ? width : "100%",
    height: (height > 0) ? height : "100%"
   });
   var tbody = document.createElement("TBODY");
   table.appendChild(tbody);
   var tr = document.createElement("TR");
   tbody.appendChild(tr);
   var td = document.createElement("TD");
   tr.appendChild(td);
   td.align = "center";
   td.vAlign = "middle";
   element = this.CloneLoadingPanel(element, td);
   ASPx.SetElementDisplay(element, true);
   this.loadingPanelElement = element;
   return element;
  } else
   parentElement.innerHTML = "&nbsp;";
  return null;
 },
 CreateLoadingPanelWithAbsolutePosition: function(parentElement, offsetElement) {
  if(this.ShouldHideExistingLoadingElements())
   this.HideLoadingPanel();
  if(parentElement == null)
   return null;
  if(!this.IsLoadingContainerVisible()) {
   this.hasPhantomLoadingElements = true;
   return null;
  }
  if(!offsetElement)
   offsetElement = parentElement;
  var element = this.GetLoadingPanelElement();
  if(element != null) {
   element = this.CloneLoadingPanel(element, parentElement);
   ASPx.SetStyles(element, {
    position: "absolute"
   });
   ASPx.SetElementDisplay(element, true);
   ASPx.Evt.AttachEventToElement(element, ASPx.Evt.GetMouseWheelEventName(), ASPx.Evt.PreventEvent);
   this.SetLoadingPanelLocation(offsetElement, element);
   this.loadingPanelElement = element;
   return element;
  }
  return null;
 },
 CreateLoadingPanelInline: function(parentElement, centerInParent){
  if(this.ShouldHideExistingLoadingElements())
   this.HideLoadingPanel();
  if(parentElement == null)
   return null;
  if(!this.IsLoadingContainerVisible()) {
   this.hasPhantomLoadingElements = true;
   return null;
  }
  var element = this.GetLoadingPanelElement();
  if(element != null) {
   element = this.CloneLoadingPanel(element, parentElement);
   if(centerInParent){
    ASPx.SetElementDisplay(element, true);
    parentElement.style.textAlign = "center";
   }
   else
    ASPx.SetElementDisplay(element, true);
   this.loadingPanelElement = element;
   return element;
  }
  return null;
 },
 ShowLoadingPanel: function() {
 },
 ShowLoadingElements: function() {
  if(this.InCallback() || this.lpTimer > -1) return;
  this.ShowLoadingDiv();
  if(this.IsCallbackAnimationEnabled())
   this.StartBeginCallbackAnimation();
  else
   this.ShowLoadingElementsInternal();
 },
 ShowLoadingElementsInternal: function() {
  if(this.lpDelay > 0 && !this.IsCallbackAnimationEnabled()) 
   this.lpTimer = window.setTimeout(function() { 
    this.ShowLoadingPanelOnTimer(); 
   }.aspxBind(this), this.lpDelay);
  else {
   this.RestoreLoadingDivOpacity();
   this.ShowLoadingPanel();
  }
 },
 GetLoadingPanelOffsetElement: function (baseElement) {
  if(this.IsCallbackAnimationEnabled()) {
   var element = this.GetLoadingPanelCallbackAnimationOffsetElement();
   if(element) {
    var container = typeof(ASPx.AnimationHelper) != "undefined" ? ASPx.AnimationHelper.findSlideAnimationContainer(element) : null;
    if(container)
     return container.parentNode.parentNode;
    else
     return element;
   }
  }
  return baseElement;
 },
 GetLoadingPanelCallbackAnimationOffsetElement: function () {
  return this.GetCallbackAnimationElement();
 },
 IsCallbackAnimationEnabled: function () {
  return (this.enableCallbackAnimation || this.isSlideCallbackAnimationEnabled()) && !this.isCallbackAnimationPrevented;
 },
 GetDefaultanimationEngineType: function() {
  return ASPx.AnimationEngineType.DEFAULT;
 },
 StartBeginCallbackAnimation: function () {
  this.beginCallbackAnimationProcessing = true;
  this.isCallbackFinished = false;
  var element = this.GetCallbackAnimationElement();
  if (element && this.isSlideCallbackAnimationEnabled() && this.slideAnimationDirection)
   ASPx.AnimationHelper.slideOut(element, this.slideAnimationDirection, this.FinishBeginCallbackAnimation.aspxBind(this), this.GetDefaultanimationEngineType(), this.rtl);
  else if(element && this.enableCallbackAnimation) 
   ASPx.AnimationHelper.fadeOut(element, this.FinishBeginCallbackAnimation.aspxBind(this), null, ASPx.AnimationEngineType.JS);
  else
   this.FinishBeginCallbackAnimation();
 },
 CancelBeginCallbackAnimation: function() {
  if(this.beginCallbackAnimationProcessing) {
   this.beginCallbackAnimationProcessing = false;
   var element = this.GetCallbackAnimationElement();
   ASPx.AnimationHelper.cancelAnimation(element);
  }
 },
 FinishBeginCallbackAnimation: function () {
  this.beginCallbackAnimationProcessing = false;
  if(!this.isCallbackFinished)
   this.ShowLoadingElementsInternal();
  else {
   this.DoCallback(this.savedCallbackResult);
   this.savedCallbackResult = null;
  }
 },
 CheckBeginCallbackAnimationInProgress: function(callbackResult) {
  if(this.beginCallbackAnimationProcessing) {
   this.savedCallbackResult = callbackResult;
   this.isCallbackFinished = true;
   return true;
  }
  return false;
 },
 StartEndCallbackAnimation: function () {
  this.HideLoadingPanel();
  this.SetInitialLoadingDivOpacity();
  this.RaiseEndCallbackAnimationStart();
  this.endCallbackAnimationProcessing = true;
  var element = this.GetCallbackAnimationElement();
  if(element && this.isSlideCallbackAnimationEnabled() && this.slideAnimationDirection) 
   ASPx.AnimationHelper.slideIn(element, this.slideAnimationDirection, this.FinishEndCallbackAnimation.aspxBind(this), this.GetDefaultanimationEngineType(), this.rtl);
  else if(element && this.enableCallbackAnimation) 
   ASPx.AnimationHelper.fadeIn(element, this.FinishEndCallbackAnimation.aspxBind(this), null, ASPx.AnimationEngineType.JS);
  else
   this.FinishEndCallbackAnimation();
  this.slideAnimationDirection = null;
 },
 FinishEndCallbackAnimation: function () {
  this.DoEndCallback();
  this.endCallbackAnimationProcessing = false;
  this.CheckRepeatGesture();
 },
 CheckEndCallbackAnimationNeeded: function() {
  if(!this.endCallbackAnimationProcessing && this.requestCount == 1) {
   this.StartEndCallbackAnimation();
   return true;
  }
  return false;
 },
 PreventCallbackAnimation: function() {
  this.isCallbackAnimationPrevented = true;
 },
 GetCallbackAnimationElement: function() {
  return null;
 },
 AssignSlideAnimationDirectionByPagerArgument: function(arg, currentPageIndex) {
  this.slideAnimationDirection = null;
  if(this.isSlideCallbackAnimationEnabled() && typeof(ASPx.AnimationHelper) != "undefined") {
   if(arg == PagerCommands.Next || arg == PagerCommands.Last)
    this.slideAnimationDirection = ASPx.AnimationHelper.SLIDE_LEFT_DIRECTION;
   else if(arg == PagerCommands.First || arg == PagerCommands.Prev)
    this.slideAnimationDirection = ASPx.AnimationHelper.SLIDE_RIGHT_DIRECTION;
   else if(!isNaN(currentPageIndex) && arg.indexOf(PagerCommands.PageNumber) == 0) {
    var newPageIndex = parseInt(arg.substring(2));
    if (!isNaN(newPageIndex)) {
     var leftDir = this.rtl ? ASPx.AnimationHelper.SLIDE_LEFT_DIRECTION : ASPx.AnimationHelper.SLIDE_RIGHT_DIRECTION;
     var rightDir = this.rtl ? ASPx.AnimationHelper.SLIDE_RIGHT_DIRECTION : ASPx.AnimationHelper.SLIDE_LEFT_DIRECTION;
     this.slideAnimationDirection = newPageIndex < currentPageIndex ? leftDir : rightDir;
    }
   }
  }
 },
 TryShowPhantomLoadingElements: function () {
  if(this.hasPhantomLoadingElements && this.InCallback()) {
   this.hasPhantomLoadingElements = false;
   this.ShowLoadingDivAndPanel();
  }
 },
 ShowLoadingDivAndPanel: function () {
  this.ShowLoadingDiv();
  this.RestoreLoadingDivOpacity();
  this.ShowLoadingPanel();
 },
 HideLoadingElements: function() {
  this.CancelBeginCallbackAnimation();
  this.HideLoadingPanel();
  this.HideLoadingDiv();
 },
 ShowLoadingPanelOnTimer: function() {
  this.ClearLoadingPanelTimer();
  if(!this.IsDOMDisposed()) {
   this.RestoreLoadingDivOpacity();
   this.ShowLoadingPanel();
  }
 },
 ClearLoadingPanelTimer: function() {
  this.lpTimer = ASPx.Timer.ClearTimer(this.lpTimer);  
 },
 HideLoadingPanel: function() {
  this.ClearLoadingPanelTimer();
  this.hasPhantomLoadingElements = false;
  if(ASPx.IsExistsElement(this.loadingPanelElement)) {
   ASPx.RemoveElement(this.loadingPanelElement);
   this.loadingPanelElement = null;
  }
 },
 SetLoadingPanelLocation: function(offsetElement, loadingPanel, x, y, offsetX, offsetY) {
  if(!ASPx.IsExists(x) || !ASPx.IsExists(y)){
   var x1 = ASPx.GetAbsoluteX(offsetElement);
   var y1 = ASPx.GetAbsoluteY(offsetElement);
   var x2 = x1;
   var y2 = y1;
   if(offsetElement == document.body) {
    x1 = 0;
    y1 = 0;
    x2 = ASPx.GetDocumentMaxClientWidth();
    y2 = ASPx.GetDocumentMaxClientHeight();
   }
   else{
    x2 += offsetElement.offsetWidth;
    y2 += offsetElement.offsetHeight;
   }
   if(x1 < ASPx.GetDocumentScrollLeft())
    x1 = ASPx.GetDocumentScrollLeft();
   if(y1 < ASPx.GetDocumentScrollTop())
    y1 = ASPx.GetDocumentScrollTop();
   if(x2 > ASPx.GetDocumentScrollLeft() + ASPx.GetDocumentClientWidth())
    x2 = ASPx.GetDocumentScrollLeft() + ASPx.GetDocumentClientWidth();
   if(y2 > ASPx.GetDocumentScrollTop() + ASPx.GetDocumentClientHeight())
    y2 = ASPx.GetDocumentScrollTop() + ASPx.GetDocumentClientHeight();
   x = x1 + ((x2 - x1 - loadingPanel.offsetWidth) / 2);
   y = y1 + ((y2 - y1 - loadingPanel.offsetHeight) / 2);
  }
  if(ASPx.IsExists(offsetX) && ASPx.IsExists(offsetY)){
   x += offsetX;
   y += offsetY;
  }
  x = ASPx.PrepareClientPosForElement(x, loadingPanel, true);
  y = ASPx.PrepareClientPosForElement(y, loadingPanel, false);
  ASPx.SetStyles(loadingPanel, { left: x, top: y });
 },
 GetLoadingDiv: function(){
  return ASPx.GetElementById(this.name + "_LD");
 },
 CreateLoadingDiv: function(parentElement, offsetElement){
  if(this.ShouldHideExistingLoadingElements())
   this.HideLoadingDiv();
  if(parentElement == null) 
   return null;
  if(!this.IsLoadingContainerVisible()) {
   this.hasPhantomLoadingElements = true;
   return null;
  }
  if(!offsetElement)
   offsetElement = parentElement;
  var div = this.GetLoadingDiv();
  if(div != null){
   div = div.cloneNode(true);
   parentElement.appendChild(div);
   ASPx.SetElementDisplay(div, true);
   ASPx.Evt.AttachEventToElement(div, ASPx.TouchUIHelper.touchMouseDownEventName, ASPx.Evt.PreventEvent);
   ASPx.Evt.AttachEventToElement(div, ASPx.TouchUIHelper.touchMouseMoveEventName, ASPx.Evt.PreventEvent);
   ASPx.Evt.AttachEventToElement(div, ASPx.TouchUIHelper.touchMouseUpEventName, ASPx.Evt.PreventEvent);
   ASPx.Evt.AttachEventToElement(div, ASPx.Evt.GetMouseWheelEventName(), ASPx.Evt.PreventEvent);
   this.SetLoadingDivBounds(offsetElement, div);
   this.loadingDivElement = div;
   this.SetInitialLoadingDivOpacity();
   return div;
  }
  return null;
 },
 SetInitialLoadingDivOpacity: function() {
  if(!this.loadingDivElement) return;
  ASPx.Attr.SaveStyleAttribute(this.loadingDivElement, "opacity");
  ASPx.Attr.SaveStyleAttribute(this.loadingDivElement, "filter");
  ASPx.SetElementOpacity(this.loadingDivElement, 0.01);
 },
 RestoreLoadingDivOpacity: function() {
  if(!this.loadingDivElement) return;
  ASPx.Attr.RestoreStyleAttribute(this.loadingDivElement, "opacity");
  ASPx.Attr.RestoreStyleAttribute(this.loadingDivElement, "filter");
 },
 SetLoadingDivBounds: function(offsetElement, loadingDiv) {
  var absX = (offsetElement == document.body) ? 0 : ASPx.GetAbsoluteX(offsetElement);
  var absY = (offsetElement == document.body) ? 0 : ASPx.GetAbsoluteY(offsetElement);
  ASPx.SetStyles(loadingDiv, {
   left: ASPx.PrepareClientPosForElement(absX, loadingDiv, true),
   top: ASPx.PrepareClientPosForElement(absY, loadingDiv, false)
  });
  var width = (offsetElement == document.body) ? ASPx.GetDocumentWidth() : offsetElement.offsetWidth;
  var height = (offsetElement == document.body) ? ASPx.GetDocumentHeight() : offsetElement.offsetHeight;
  if(height < 0) 
   height = 0;
  ASPx.SetStyles(loadingDiv, { width: width, height: height });
  var correctedWidth = 2 * width - loadingDiv.offsetWidth;
  if(correctedWidth <= 0) correctedWidth = width;
  var correctedHeight = 2 * height - loadingDiv.offsetHeight;
  if(correctedHeight <= 0) correctedHeight = height;
  ASPx.SetStyles(loadingDiv, { width: correctedWidth, height: correctedHeight });
 },
 ShowLoadingDiv: function() {
 },
 HideLoadingDiv: function() {
  this.hasPhantomLoadingElements = false;
  if(ASPx.IsExistsElement(this.loadingDivElement)){
   ASPx.RemoveElement(this.loadingDivElement);
   this.loadingDivElement = null;
  }
 },
 CanHandleGesture: function(evt) {
  return false;
 },
 CanHandleGestureCore: function(evt) {
  var source = ASPx.Evt.GetEventSource(evt);
  if(ASPx.GetIsParent(this.loadingPanelElement, source) || ASPx.GetIsParent(this.loadingDivElement, source))
   return true; 
  var callbackAnimationElement = this.GetCallbackAnimationElement();
  if(!callbackAnimationElement)
   return false;
  var animationContainer = ASPx.AnimationHelper.getSlideAnimationContainer(callbackAnimationElement, false, false);
  if(animationContainer && ASPx.GetIsParent(animationContainer, source) && !ASPx.GetIsParent(animationContainer.childNodes[0], source))
   return true; 
  return this.CanHandleGesture(evt); 
 },
 AllowStartGesture: function() {
  return !this.beginCallbackAnimationProcessing && !this.endCallbackAnimationProcessing;
 },
 StartGesture: function() {
 },
 AllowExecuteGesture: function(value) {
  return false;
 },
 ExecuteGesture: function(value) {
 },
 CancelGesture: function(value) {
  if(this.repeatedGestureCount === 0) {
   this.repeatedGestureValue = value;
   this.repeatedGestureCount = 1;
  }
  else {
   if(this.repeatedGestureValue * value > 0)
    this.repeatedGestureCount++;
   else
    this.repeatedGestureCount--;
   if(this.repeatedGestureCount === 0)
    this.repeatedGestureCount = 0;
  }
 },
 CheckRepeatGesture: function() {
  if(this.repeatedGestureCount !== 0) {
   if(this.AllowExecuteGesture(this.repeatedGestureValue))
    this.ExecuteGesture(this.repeatedGestureValue, this.repeatedGestureCount);
   this.repeatedGestureValue = 0;
   this.repeatedGestureCount = 0;
  }
 },
 AllowExecutePagerGesture: function (pageIndex, pageCount, value) {
  if(pageIndex < 0) return false;
  if(pageCount <= 1) return false;
  if(value > 0 && pageIndex === 0) return false;
  if(value < 0 && pageIndex === pageCount - 1) return false;
  return true;
 },
 ExecutePagerGesture: function(pageIndex, pageCount, value, count, method) {
  if(!count) count = 1;
  var pageIndex = pageIndex + (value < 0 ? count : -count);
  if(pageIndex < 0) pageIndex = 0;
  if(pageIndex > pageCount - 1) pageIndex = pageCount - 1;
  method(PagerCommands.PageNumber + pageIndex);
 },
 RaiseInit: function(){
  if(!this.Init.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.Init.FireEvent(this, args);
  }
 },
 RaiseBeginCallbackInternal: function(command){
  if(!this.BeginCallback.IsEmpty()){
   var args = new ASPxClientBeginCallbackEventArgs(command);
   this.BeginCallback.FireEvent(this, args);
  }
 },
 RaiseEndCallbackInternal: function(command) {
  if(!this.EndCallback.IsEmpty()){
   var args = new ASPxClientEndCallbackEventArgs(command);
   this.EndCallback.FireEvent(this, args);
  }
 },
 RaiseCallbackErrorInternal: function(message, callbackId) {
  if(!this.CallbackError.IsEmpty()) {
   var args = new ASPxClientCallbackErrorEventArgs(message, callbackId);
   this.CallbackError.FireEvent(this, args);
   if(args.handled)
    return { isHandled: true, errorMessage: args.message };
  }
 },
 RaiseBeginCallback: function(command){
  this.RaiseBeginCallbackInternal(command);    
  aspxGetControlCollection().RaiseBeginCallback(this, command);
 },
 RaiseEndCallback: function(command){
  this.RaiseEndCallbackInternal(command);
  aspxGetControlCollection().RaiseEndCallback(this, command);
 },
 RaiseCallbackError: function (message, callbackId) {
  var result = this.RaiseCallbackErrorInternal(message, callbackId);
  if(!result) 
   result = aspxGetControlCollection().RaiseCallbackError(this, message, callbackId);
  return result;
 },
 RaiseEndCallbackAnimationStart: function(){
  if(!this.EndCallbackAnimationStart.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.EndCallbackAnimationStart.FireEvent(this, args);
  }
 },
 RaiseBeforePronounce: function(message) {
  var args = new ASPxClientControlBeforePronounceEventArgs(message, this);
  if(!this.BeforePronounce.IsEmpty())
   this.BeforePronounce.FireEvent(this, args);
  return args;
 },
 RaiseUnload: function() {
  var args = new ASPxClientControlUnloadEventArgs(this);
  if(!this.Unload.IsEmpty())
   this.Unload.FireEvent(this, args);
 },
 RaiseDisposed: function() {
  this.Disposed.FireEvent(this, new ASPxClientEventArgs(this));
 },
 SendMessageToAssistiveTechnology: function(message) {
  if(!this.accessibilityCompliant)
   return;
  this.PronounceMessageInternal(message, ASPx.AccessibilityPronouncerType.live);
 },
 PronounceMessageInternal: function(messageArg, type) {
  var message = messageArg;
  if(!ASPx.Ident.IsArray(messageArg))
   message = [messageArg];
  var args = this.RaiseBeforePronounce(message);
  ASPx.AccessibilityPronouncer.Pronounce(args, type);
 },
 IsVisible: function() {
  var element = this.GetMainElement();
  return ASPx.IsElementVisible(element);
 },
 IsDisplayedElement: function(element) {
  while(element && element.tagName != "BODY") {
   if(!ASPx.GetElementDisplay(element)) 
    return false;
   element = element.parentNode;
  }
  return true;
 },
 IsDisplayed: function() {
  return this.IsDisplayedElement(this.GetMainElement());
 },
 IsHiddenElement: function(element) {
  return element && element.offsetWidth == 0 && element.offsetHeight == 0;
 },
 IsHidden: function() {
  return this.IsHiddenElement(this.GetMainElement());
 },
 IsDisposed: function() {
  return this.disposed;
 },
 GetParentControl: function() {
  var mainElement = this.getActualMainElement();
  var popupPostfix = ASPx.PCWIdSuffix + "-1";
  var result = null;
  ASPx.GetParent(mainElement, function(element) {
   if(element === mainElement || !element.id)
    return false;
   var controlName = element.id.replace(popupPostfix, "");
   result = ASPx.GetControlCollection().Get(controlName);
   return !!result;
  });
  return result;
 },
 getActualMainElement: function() { return this.GetMainElement(); },
 findParentByType: function (type) {
  var ctrl = this;
  while (ctrl) {
   var parent = ctrl.GetParentControl();
   if (parent && parent instanceof type)
    return parent;
   ctrl = parent;
  }
  return null;
 },
 Focus: function() {
 },
 GetClientVisible: function(){
  return this.GetVisible();
 },
 SetClientVisible: function(visible){
  this.SetVisible(visible);
 },
 GetVisible: function(){
  return this.clientVisible;
 },
 SetVisible: function(visible){
  if(this.clientVisible != visible){
   this.clientVisible = visible;
   ASPx.SetElementDisplay(this.GetMainElement(), visible);
   if(visible) {
    this.AdjustControl();
    var mainElement = this.GetMainElement();
    if(mainElement)
     aspxGetControlCollection().AdjustControls(mainElement);
   }
  }
 },
 GetEnabled: function() {
  return this.clientEnabled;
 },
 SetEnabled: function(enabled) {
  this.clientEnabled = enabled;
  if(ASPxClientControl.setEnabledLocked)
   return;
  else
   ASPxClientControl.setEnabledLocked = true;
  this.savedClientEnabled = enabled;
  aspxGetControlCollection().ProcessControlsInContainer(this.GetMainElement(), function(control) {
   if(ASPx.IsFunction(control.SetEnabled))
    control.SetEnabled(enabled && control.savedClientEnabled);
  });
  delete ASPxClientControl.setEnabledLocked;
 },
 InCallback: function() {
  return this.requestCount > 0;
 },
 DoBeginCallback: function(command) {
  this.RaiseBeginCallback(command || "");
  aspxGetControlCollection().Before_WebForm_InitCallback(this.name);
  if(typeof(WebForm_InitCallback) != "undefined" && WebForm_InitCallback) {
   __theFormPostData = "";
   __theFormPostCollection = [ ];
   this.ClearPostBackEventInput("__EVENTTARGET");
   this.ClearPostBackEventInput("__EVENTARGUMENT");
   WebForm_InitCallback();
   this.savedFormPostData = __theFormPostData;
   this.savedFormPostCollection = __theFormPostCollection;
  }
 },
 ClearPostBackEventInput: function(id){
  var element = ASPx.GetElementById(id);
  if(element != null) element.value = "";
 },
 PerformDataCallback: function(arg, handler) {
  this.CreateCustomDataCallback(arg, "", handler);
 },
 sendCallbackViaQueue: function (prefix, arg, showLoadingPanel, context, handler, onBeforeSend) {
  if (!this.useCallbackQueue())
   return false;
  var context = context || this;
  var token = this.callbackQueueHelper.sendCallback(ASPx.FormatCallbackArg(prefix, arg), context, handler || context.OnCallback, prefix, onBeforeSend);
  if (showLoadingPanel)
   this.callbackQueueHelper.showLoadingElements();
  return token;
 },
 CreateCallback: function (arg, command, handler) {
  var callbackInfo = this.CreateCallbackInfo(ASPx.CallbackType.Common, handler || null);
  var callbackID = this.CreateCallbackByInfo(arg, command, callbackInfo);
  return callbackID;
 },
 CreateCustomDataCallback: function(arg, command, handler) {
  var callbackInfo = this.CreateCallbackInfo(ASPx.CallbackType.Data, handler);
  this.CreateCallbackByInfo(arg, command, callbackInfo);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  if(!this.CanCreateCallback()) return;
  var callbackID;
  if(typeof(WebForm_DoCallback) != "undefined" && WebForm_DoCallback && ASPx.documentLoaded || ASPx.Platform === "NETCORE")
   callbackID = this.CreateCallbackInternal(arg, command, true, callbackInfo);
  else {
   if(!this.savedCallbacks)
    this.savedCallbacks = [];
   var callbackInfo = { arg: arg, command: command, callbackInfo: callbackInfo };
   if(this.allowMultipleCallbacks)
    this.savedCallbacks.push(callbackInfo);
   else
    this.savedCallbacks[0] = callbackInfo;
  }
  return callbackID;
 },
 CreateCallbackInternal: function(arg, command, viaTimer, callbackInfo) {
  var watcher = ASPx.ControlUpdateWatcher.getInstance();
  if(watcher && !watcher.CanSendCallback(this, arg)) {
   this.CancelCallbackInternal();
   return;
  }
  this.requestCount++;
  this.DoBeginCallback(command);
  if(typeof(arg) == "undefined")
   arg = "";
  if(typeof(command) == "undefined")
   command = "";
  var callbackID = this.SaveCallbackInfo(callbackInfo, command),
   customArgs = this.GetCustomCallbackArgs();
  if(viaTimer)
   window.setTimeout(function() { this.CreateCallbackCoreWithCustomArgs(arg, command, callbackID, customArgs); }.aspxBind(this), 0);
  else
   this.CreateCallbackCoreWithCustomArgs(arg, command, callbackID, customArgs);
  return callbackID;
 },
 CreateCallbackCoreWithCustomArgs: function(arg, command, callbackID, customArgs) {
  this.CreateCallbackCore(arg, command, callbackID);
 },
 GetCustomCallbackArgs: function() {
  return {};
 },
 CancelCallbackInternal: function() {
  this.CancelCallbackCore();
  this.HideLoadingElements();
 },
 CancelCallbackCore: function() {
 },
 CreateCallbackCore: function(arg, command, callbackID) {
  var callBackMethod = this.GetCallbackMethod(command);
  __theFormPostData = this.savedFormPostData;
  __theFormPostCollection = this.savedFormPostCollection;
  callBackMethod.call(this, this.GetSerializedCallbackInfoByID(callbackID) + arg);
 },
 GetCallbackMethod: function(command){
  return this.callBack;
 },
 CanCreateCallback: function() {
  return !this.InCallback() || (this.allowMultipleCallbacks && !this.beginCallbackAnimationProcessing && !this.endCallbackAnimationProcessing);
 },
 DoLoadCallbackScripts: function() {
  ASPx.ProcessScriptsAndLinks(this.name, true);
 },
 DoEndCallback: function() {
  if(this.IsCallbackAnimationEnabled() && this.CheckEndCallbackAnimationNeeded()) 
   return;
  this.requestCount--;
  if (this.requestCount < 1) 
   this.callbackHandlersQueue.executeCallbacksHandlers();
  if(this.HideLoadingPanelOnCallback() && this.requestCount < 1) 
   this.HideLoadingElements();
  if(this.isSwipeGesturesEnabled() && this.supportGestures) {
   ASPx.GesturesHelper.UpdateSwipeAnimationContainer(this.name);
   if(this.touchUIMouseScroller)
    this.touchUIMouseScroller.update();
  }
  this.isCallbackAnimationPrevented = false;
  this.OnCallbackFinalized();
  this.AssignEllipsisTooltips();
  var command = this.GetCallbackCommand();
  this.RaiseEndCallback(command);
  this.InitializeIntersectionObserversManager();
  this.currentCallbackID = -1;
 },
 DoFinalizeCallback: function() {
 },
 OnCallbackFinalized: function() {
 },
 AssignEllipsisTooltips: function() { },
 GetCallbackCommand: function() {
  var result = "";
  if(this.currentCallbackID != -1) {
   var command = this.callbackCommand[this.currentCallbackID];
   if(command)
    result = command;
  }
  return result;
 },
 HideLoadingPanelOnCallback: function() {
  return true;
 },
 ShouldHideExistingLoadingElements: function() {
  return true;
 },
 EvalCallbackResult: function(resultString) {
  return eval(resultString);
 },
 ParseJSProperties: function(resultObj) {
  if(resultObj.cp) {
   for(var name in resultObj.cp)
    if(resultObj.cp.hasOwnProperty(name)) {
     this[name] = resultObj.cp[name];
     if(this.aspNetCoreWrapperInstance)
      this.aspNetCoreWrapperInstance[name] = resultObj.cp[name]; 
    }
  }
 },
 DoCallback: function(result) {
  if(this.IsCallbackAnimationEnabled() && this.CheckBeginCallbackAnimationInProgress(result))
   return;
  result = ASPx.Str.Trim(result);
  if(result.indexOf(ASPx.CallbackResultPrefix) != 0) 
   this.ProcessCallbackGeneralError(result, false);
  else {
   var resultObj = null;
   try {
    resultObj = this.EvalCallbackResult(result);
   } 
   catch(e) {
   }
   if(resultObj) {
    this.currentCallbackID = resultObj.id;
    ASPx.CacheHelper.DropCache(this);
    if(resultObj.redirect) {
     this.ParseJSProperties(resultObj); 
     ASPx.Url.Redirect(resultObj.redirect);
    }
    else if(ASPx.IsExists(resultObj.generalError)) {
     this.ProcessCallbackGeneralError(resultObj.generalError, true);
    }
    else {
     var errorObj = resultObj.error;
     if(errorObj) { 
      if(this.parseJSPropertiesOnCallbackError)
       this.ParseJSProperties(resultObj);
      this.ProcessCallbackError(errorObj,resultObj.id);
     } else {
      this.ParseJSProperties(resultObj);
      var callbackInfo = this.DequeueCallbackInfo(resultObj.id);
      if(callbackInfo && callbackInfo.type == ASPx.CallbackType.Data)
       this.ProcessCustomDataCallback(resultObj.result, callbackInfo);
      else {
       if (this.useCallbackQueue() && this.callbackQueueHelper.getCallbackInfoById(resultObj.id))
        this.callbackQueueHelper.processCallback(resultObj.result, resultObj.id);
       else {
        this.ProcessCallback(resultObj.result, resultObj.id);
        if(callbackInfo && callbackInfo.handler) {
         var handlerInfo = { handler: callbackInfo.handler, result: resultObj.result.data };
         this.callbackHandlersQueue.addCallbackHandler(handlerInfo);
        }
       }
      }
     }
    }
   }
  }
  this.DoLoadCallbackScripts();
 },
 DoCallbackError: function(result) {
  this.HideLoadingElements();
  this.ProcessCallbackGeneralError(result, false); 
 },
 DoControlClick: function(evt) {
  this.OnControlClick(ASPx.Evt.GetEventSource(evt), evt);
 },
 ProcessCallback: function (result, callbackId) {
  this.OnCallback(result, callbackId);
 },
 ProcessCustomDataCallback: function(result, callbackInfo) {
  if(callbackInfo.handler != null)
   callbackInfo.handler(this, result);
  this.RaiseCustomDataCallback(result);
 },
 RaiseCustomDataCallback: function(result) {
  if(!this.CustomDataCallback.IsEmpty()) {
   var arg = new ASPxClientCustomDataCallbackEventArgs(result);
   this.CustomDataCallback.FireEvent(this, arg);
  }
 },
 OnCallback: function(result) {
 },
 CreateCallbackInfo: function(type, handler) {
  return { type: type, handler: handler };
 },
 GetSerializedCallbackInfoByID: function(callbackID) {
  return this.GetCallbackInfoByID(callbackID).type + callbackID + ASPx.CallbackSeparator;
 },
 SaveCallbackInfo: function(info, command) {
  var callbacks = this.GetActiveCallbacksInfo();
  var index = callbacks.indexOf(null);
  if(index === -1)
   index = callbacks.length;
  callbacks[index] = info;
  this.callbackCommand[index] = command;
  return index;
 },
 GetActiveCallbacksInfo: function() {
  var persistentProperties = this.GetPersistentProperties();
  if(!persistentProperties.activeCallbacks)
   persistentProperties.activeCallbacks = [ ];
  return persistentProperties.activeCallbacks;
 },
 GetPersistentProperties: function() {
  var storage = _aspxGetPersistentControlPropertiesStorage();
  var persistentProperties = storage[this.name];
  if(!persistentProperties) {
   persistentProperties = { };
   storage[this.name] = persistentProperties;
  }
  return persistentProperties;
 },
 GetCallbackInfoByID: function(callbackID) {
  return this.GetActiveCallbacksInfo()[callbackID];
 },
 DequeueCallbackInfo: function(index) {
  var activeCallbacksInfo = this.GetActiveCallbacksInfo();
  if(index < 0 || index >= activeCallbacksInfo.length)
   return null;
  var result = activeCallbacksInfo[index];
  activeCallbacksInfo[index] = null;
  return result;
 },
 ProcessCallbackError: function (errorObj, callbackId) {
  var data = ASPx.IsExists(errorObj.data) ? errorObj.data : null;
  var result = this.RaiseCallbackError(errorObj.message, callbackId);
  if(result.isHandled)
   this.OnCallbackErrorAfterUserHandle(result.errorMessage, data); 
  else
   this.OnCallbackError(result.errorMessage, data); 
 },
 OnCallbackError: function(errorMessage, data) {
  if(errorMessage)
   ASPx.ShowErrorAlert(errorMessage);
 },
 OnCallbackErrorAfterUserHandle: function(errorMessage, data) {
 },
 ProcessCallbackGeneralError: function(errorMessage, serverExceptionOnLastCallback) {
  this.serverExceptionOnLastCallback = serverExceptionOnLastCallback;
  var result = this.RaiseCallbackError(errorMessage);
  if(result.isHandled)
   this.OnCallbackGeneralErrorAfterUserHandle(result.errorMessage);
  else
   this.OnCallbackGeneralError(result.errorMessage);
 },
 OnCallbackGeneralError: function(errorMessage) {
  this.OnCallbackError(errorMessage, null);
 },
 OnCallbackGeneralErrorAfterUserHandle: function (errorMessage) {
 },
 SendPostBack: function(params, preventConvertToUpdatePanelCallback) {
  if(preventConvertToUpdatePanelCallback)
   this.sendMSAjaxCompatPostBack(params);
  else
   this.sendPostBackInternal(params);
 },
 sendPostBackInternal: function(params) {
  if(typeof(__doPostBack) != "undefined")
   __doPostBack(this.uniqueID, params);
  else{
   var form = this.GetParentForm();
   if(form) form.submit();
  }
 },
 sendMSAjaxCompatPostBack: function(params) {
  var rm = ASPx.GetMSAjaxRequestManager();
  var triggers = rm ? rm._postBackControlClientIDs : null;
  var needRegister = triggers && ASPx.Ident.IsArray(triggers) && ASPx.Data.ArrayIndexOf(triggers, this.name) == -1;
  if(needRegister)
   triggers.unshift(this.name);
  this.sendPostBackInternal(params);
  if(needRegister)
   triggers.shift();
 },
 IsValidInstance: function () {
  return aspxGetControlCollection().GetByName(this.name) === this;
 },
 OnDispose: function() { 
  this.RaiseDisposed();
  var varName = this.globalName;
  if(varName && varName !== "" && window && window[varName] && window[varName] == this){
   try{
    delete window[varName];
   }
   catch(e){  }
  }
  if(this.callbackQueueHelper)
   this.callbackQueueHelper.detachEvents();
  if (!this.IsDisposed())
   this.disposed = true;
 },
 OnGlobalControlsInitialized: function(args) { 
 },
 OnGlobalBrowserWindowResized: function(args) { 
 },
 OnGlobalBeginCallback: function(args) { 
 },
 OnGlobalEndCallback: function(args) { 
 },
 OnGlobalCallbackError: function(args) { 
 },
 OnGlobalValidationCompleted: function(args) { 
 },
 AddDefaultStateControllerItems: function() {
  var states = this.scStates;
  if(!states) return;
  var postfix = this.scPostfix ? ("_" + this.scPostfix) : "";
  var mainElementId = this.GetMainElementId();
  if(states & 2)
   this.AddDefaultReadOnlyStateControllerItem(this.scPrefix + "ReadOnly" + postfix, mainElementId);
  if(states & 4)
   this.AddDefaultDisabledStateControllerItem(this.scPrefix + "Disabled" + postfix, mainElementId);
 },
 AddDefaultReadOnlyStateControllerItem: function(cssClass, mainElementId) { throw "Not implemented"; },
 AddDefaultDisabledStateControllerItem: function(cssClass, mainElementId) { throw "Not implemented"; },
 DOMContentLoaded: function() { },
 IsStateControllerEnabled: function() { return false; },
 InitializeDOM: function() {
  var mainElement = this.GetMainElement();
  if(mainElement)
   ASPx.SetElementInitializedFlag(mainElement);
 },
 IsDOMInitialized: function() {
  var mainElement = this.GetMainElement();
  return mainElement && ASPx.GetElementInitializedFlag(mainElement);
 },
 AdjustControl: function(nestedCall) { },
 OnBrowserWindowResizeInternal: function(e) { },
 RegisterInControlTree: function(tree) { },
 InitializeIntersectionObserversManager: function () {
  var elementToObserve = this.getElementToObserveVisibilityChange();
  if(elementToObserve) {
   ASPx.IntersectionObserversManager.SubscribeElemensVisibilityChangeInBrowserWindow(elementToObserve, this.processVisibilityChanged.bind(this));
  }
 },
 getElementToObserveVisibilityChange: function () { },
 processVisibilityChanged: function (visible) { }
});
ASPxClientControlBase.Cast = function(obj) {
 if(typeof obj == "string")
  return window[obj];
 return obj;
};
var persistentControlPropertiesStorage = null;
function _aspxGetPersistentControlPropertiesStorage() {
 if(persistentControlPropertiesStorage == null)
  persistentControlPropertiesStorage = { };
 return persistentControlPropertiesStorage;
}
var ELLIPSIS_MARKER_CLASS = "dx-ellipsis";
var ELLIPSIS_TOOLTIP_MARKER_ATTR = "dxEllipsisTitle";
var ASPxClientControl = ASPx.CreateClass(ASPxClientControlBase, {
 constructor: function(name){
  this.constructor.prototype.constructor.call(this, name);
  this.rtl = false;
  this.enableEllipsis = false;
  this.isNative = false;
  this.isControlCollapsed = false;
  this.isInsideHierarchyAdjustment = false;
  this.controlOwner = null;
  this.adjustedSizes = { };
  this.dialogContentHashTable = { };
  this.renderIFrameForPopupElements = false;
  this.widthValueSetInPercentage = false;
  this.heightValueSetInPercentage = false;
  this.verticalAlignedElements = { };
  this.wrappedTextContainers = { };
  this.scrollPositionState = { };
  this.sizingConfig = {
   allowSetWidth: true,
   allowSetHeight: true,
   correction : false,
   adjustControl : false,
   supportPercentHeight: false,
   supportAutoHeight: false
  };
  this.percentSizeConfig = {
   width: -1,
   height: -1,
   markerWidth: -1,
   markerHeight: -1
  };  
 },
 querySelector: function(selector) { return this.querySelectorAll(selector)[0] || null; },
 querySelectorAll: function(selector) {
  return ASPx.CacheHelper.GetCachedElement(this, "querySelectorAll_" + selector,
   function() { return Array.prototype.slice.call(this.GetMainElement().querySelectorAll(selector)); });
 },
 createAccessKey: function (popupItem, getPopupElement, keyTipElement, key, onlyClick, manualStopProcessing) {
  return new ASPx.AccessKey(popupItem, getPopupElement, keyTipElement, key, onlyClick, manualStopProcessing);
 },
 InlineInitialize: function() {
  this.InitializeDOM();
  ASPxClientControlBase.prototype.InlineInitialize.call(this);
 },
 AfterCreate: function() { 
  ASPxClientControlBase.prototype.AfterCreate.call(this);
  if(!this.CanInitializeAdjustmentOnDOMContentLoaded() || ASPx.IsStartupScriptsRunning())
   this.InitializeAdjustment();
 },
 DOMContentLoaded: function() {
  if(this.CanInitializeAdjustmentOnDOMContentLoaded()) 
   this.InitializeAdjustment();
 },
 CanInitializeAdjustmentOnDOMContentLoaded: function() {
  return true;
 },
 InitializeAdjustment: function() {
  this.UpdateAdjustmentFlags();
  this.AdjustControl();
 },
 AfterInitialize: function() {
  this.AdjustControl();
  ASPxClientControlBase.prototype.AfterInitialize.call(this);
 },
 IsStateControllerEnabled: function(){
  return typeof(ASPx.GetStateController) != "undefined" && ASPx.GetStateController();
 },
 GetWidth: function() {
  return this.GetMainElement().offsetWidth;
 },
 GetHeight: function() {
  return this.GetMainElement().offsetHeight;
 },
 SetWidth: function(width) {
  if(this.sizingConfig.allowSetWidth)
   this.SetSizeCore("width", width, "GetWidth", false);
 },
 SetHeight: function(height) {
  if(this.sizingConfig.allowSetHeight)
   this.SetSizeCore("height", height, "GetHeight", false);
 },
 SetSizeCore: function(sizePropertyName, size, getFunctionName, corrected) {
  if(size < 0 || !this.GetMainElement())
   return;
  this.GetMainElement().style[sizePropertyName] = size + "px";
  this.UpdateAdjustmentFlags(sizePropertyName);
  if(this.sizingConfig.adjustControl)
   this.AdjustControl(true);
  if(this.sizingConfig.correction && !corrected) {
   var realSize = this[getFunctionName]();
   if(realSize != size) {
    var correctedSize = size - (realSize - size);
    this.SetSizeCore(sizePropertyName, correctedSize, getFunctionName, true);
   }
  }
 },
 AdjustControl: function(nestedCall) {
  if(this.IsAdjustmentRequired() && (!ASPxClientControl.adjustControlLocked || nestedCall)) {
   ASPxClientControl.adjustControlLocked = true;
   try {
    if(!this.IsAdjustmentAllowed())
     return;
    this.AdjustControlCore();
    this.UpdateAdjustedSizes();
   } 
   finally {
    delete ASPxClientControl.adjustControlLocked;
   }
  }
  this.AssignEllipsisTooltips();
  this.TryShowPhantomLoadingElements();
 },
 ResetControlAdjustment: function () {
  this.adjustedSizes = { };
 },
 UpdateAdjustmentFlags: function(sizeProperty) {
  var mainElement = this.GetMainElement();
  if(mainElement) {
   var mainElementStyle = ASPx.GetCurrentStyle(mainElement);
   this.UpdatePercentSizeConfig([mainElementStyle.width, mainElement.style.width], [mainElementStyle.height, mainElement.style.height], sizeProperty);
  }
 },
 UpdatePercentSizeConfig: function(widths, heights, modifyStyleProperty) {
  switch(modifyStyleProperty) {
   case "width":
    this.UpdatePercentWidthConfig(widths);
    break;
   case "height":
    this.UpdatePercentHeightConfig(heights);
    break;
   default:
    this.UpdatePercentWidthConfig(widths);
    this.UpdatePercentHeightConfig(heights);
    break;
  }
  this.ResetControlPercentMarkerSize();
 },
 UpdatePercentWidthConfig: function(widths) {
  this.widthValueSetInPercentage = false;
  for(var i = 0; i < widths.length; i++) {
   if(this.IsPercentageWidth(widths[i])) {
    this.percentSizeConfig.width = widths[i];
    this.widthValueSetInPercentage = true;
    break;
   }
  }
 },
 IsPercentageWidth: function(width) { return ASPx.IsPercentageSize(width); },
 UpdatePercentHeightConfig: function(heights) {
  this.heightValueSetInPercentage = false;
    for(var i = 0; i < heights.length; i++) {
   if(ASPx.IsPercentageSize(heights[i])) {
    this.percentSizeConfig.height = heights[i];
    this.heightValueSetInPercentage = true;
    break;
   }
  }
 },
 GetAdjustedSizes: function() {
  var mainElement = this.GetMainElement();
  if(mainElement) 
   return { width: mainElement.offsetWidth, height: mainElement.offsetHeight };
  return { width: 0, height: 0 };
 },
 IsAdjusted: function() {
  return (this.adjustedSizes.width && this.adjustedSizes.width > 0) && (this.adjustedSizes.height && this.adjustedSizes.height > 0);
 },
 IsAdjustmentRequired: function() {
  if(!this.IsAdjusted())
   return true;
  if(this.widthValueSetInPercentage)
   return true;
  if(this.heightValueSetInPercentage)
   return true;
  var sizes = this.GetAdjustedSizes();
  for(var name in sizes){
   if(this.adjustedSizes[name] !== sizes[name])
    return true;
  }
  return false;
 },
 IsAdjustmentAllowed: function() {
  var mainElement = this.GetMainElement();
  return mainElement && this.IsDisplayed() && !this.IsHidden() && this.IsDOMInitialized();
 },
 UpdateAdjustedSizes: function() {
  var sizes = this.GetAdjustedSizes();
  for(var name in sizes)
   if(sizes.hasOwnProperty(name))
    this.adjustedSizes[name] = sizes[name];
 },
 AdjustControlCore: function() {
 },
 AdjustAutoHeight: function() {
 },
 IsControlCollapsed: function() {
  return this.isControlCollapsed;
 },
 NeedCollapseControl: function() {
  return this.NeedCollapseControlCore() && this.IsAdjustmentRequired() && this.IsAdjustmentAllowed();
 },
 NeedCollapseControlCore: function() {
  return false;
 },
 CollapseEditor: function() {
 },
 CollapseControl: function() {
  this.SaveScrollPositions();
  var mainElement = this.GetMainElement(),
   marker = this.GetControlPercentSizeMarker();
  marker.style.height = this.heightValueSetInPercentage && this.sizingConfig.supportPercentHeight
   ? this.percentSizeConfig.height 
   : (mainElement.offsetHeight + "px");
  mainElement.style.display = "none";
  this.isControlCollapsed = true;
 },
 ExpandControl: function() {
  var mainElement = this.GetMainElement();
  mainElement.style.display = "";
  this.GetControlPercentSizeMarker().style.height = "0px";
  this.isControlCollapsed = false;
  this.RestoreScrollPositions();
 },
 CanCauseReadjustment: function() {
  return this.NeedCollapseControlCore();
 },
 IsExpandableByAdjustment: function() {
  return false;
 },
 HasFixedPosition: function() {
  return false;
 },
 SaveScrollPositions: function() {
  var mainElement = this.GetMainElement();
  this.scrollPositionState.outer = ASPx.GetOuterScrollPosition(mainElement.parentNode);
  this.scrollPositionState.inner = ASPx.GetInnerScrollPositions(mainElement);
 },
 RestoreScrollPositions: function() {
  ASPx.RestoreOuterScrollPosition(this.scrollPositionState.outer);
  ASPx.RestoreInnerScrollPositions(this.scrollPositionState.inner);
 },
 GetControlPercentSizeMarker: function() {
  if(this.percentSizeMarker === undefined) {
   this.percentSizeMarker = ASPx.CreateHtmlElementFromString("<div style='height:0px;font-size:0px;line-height:0;width:100%;'></div>");
   ASPx.InsertElementAfter(this.percentSizeMarker, this.GetMainElement());
  }
  return this.percentSizeMarker;
 },
 KeepControlPercentSizeMarker: function(needCollapse, needCalculateHeight) {
  var marker = this.GetControlPercentSizeMarker(),
   markerHeight;
  if(needCollapse)
   this.CollapseControl();
  if(this.widthValueSetInPercentage && marker.style.width !== this.percentSizeConfig.width)
   marker.style.width = this.percentSizeConfig.width;
  if(needCalculateHeight) {
   if(this.IsControlCollapsed())
    markerHeight = marker.style.height;
   marker.style.height = this.percentSizeConfig.height;
  }
  this.percentSizeConfig.markerWidth = marker.offsetWidth;
  if(needCalculateHeight) {
   this.percentSizeConfig.markerHeight = marker.offsetHeight;
   if(this.IsControlCollapsed())
    marker.style.height = markerHeight;
   else
    marker.style.height = "0px";
  }
  if(needCollapse)
   this.ExpandControl();
 },
 ResetControlPercentMarkerSize: function() {
  this.percentSizeConfig.markerWidth = -1;
  this.percentSizeConfig.markerHeight = -1;
 },
 GetControlPercentMarkerSize: function(hideControl, force) {
  var needCalculateHeight = this.heightValueSetInPercentage && this.sizingConfig.supportPercentHeight;
  if(force || this.percentSizeConfig.markerWidth < 1 || (needCalculateHeight && this.percentSizeConfig.markerHeight < 1))
   this.KeepControlPercentSizeMarker(hideControl && !this.IsControlCollapsed(), needCalculateHeight);
  return {
   width: this.percentSizeConfig.markerWidth,
   height: this.percentSizeConfig.markerHeight
  };
 },
 AssignEllipsisTooltips: function() {
  if(this.RequireAssignTooltips())
   this.AssignEllipsisTooltipsCore();
 },
 AssignEllipsisTooltipsCore: function(rootElement, reassingExistingTooltips) {
  var requirePaddingManipulation = ASPx.Browser.Edge || ASPx.Browser.Firefox;
  rootElement = rootElement || this.GetMainElement();
  var nodes = this.GetEllipsisNodes(rootElement);
  var nodeInfos = [];
  var nodesCount = nodes.length;
  for(var i = 0; i < nodesCount; i++) {
   var node = nodes[i];
   var info = { node: node };
   if(requirePaddingManipulation) {
    var style = ASPx.GetCurrentStyle(node);
    info.paddingLeft = node.style.paddingLeft;
    info.totalPadding = ASPx.GetLeftRightPaddings(node, style);
   }
   nodeInfos.push(info);
  }
  if(requirePaddingManipulation) {
   for(var i = 0; i < nodesCount; i++) {
    var info = nodeInfos[i];
    ASPx.SetStyles(info.node, { paddingLeft: info.totalPadding }, true);
   }
  }
  for(var i = 0; i < nodesCount; i++) {
   var info = nodeInfos[i];
   var node = info.node;
   info.isTextShortened = node.scrollWidth > node.clientWidth;
   info.hasTitle = ASPx.Attr.GetAttribute(node, "title") !== null;
   if(!info.hasTitle || reassingExistingTooltips)
    info.title = ASPx.GetEllipsisTooltipText(node);
  }
  for(var i = 0; i < nodesCount; i++) {
   var info = nodeInfos[i];
   var node = info.node;
   if(info.isTextShortened && info.title) {
    ASPx.Attr.SetAttribute(node, "title", info.title);
    ASPx.Attr.SetAttribute(node, ELLIPSIS_TOOLTIP_MARKER_ATTR, true);
   }
   if(!info.isTextShortened && info.hasTitle)
    ASPx.Attr.RemoveAttribute(node, "title");
  }
  if(requirePaddingManipulation) {
   for(var i = 0; i < nodesCount; i++) {
    var info = nodeInfos[i];
    var node = info.node;
    node.style.paddingLeft = info.paddingLeft;
   }
  }
 },
 GetEllipsisNodes: function(element) {
  var ellipsibleNodes = ASPx.Data.CollectionToArray(ASPx.GetNodesByClassName(element, ELLIPSIS_MARKER_CLASS));
  if(ASPx.ElementHasCssClass(element, ELLIPSIS_MARKER_CLASS))
   ellipsibleNodes.push(element);
  return ellipsibleNodes.filter(function(node) {
   return !ASPx.Attr.IsExistsAttribute(node, "title") || ASPx.Attr.IsExistsAttribute(node, ELLIPSIS_TOOLTIP_MARKER_ATTR);
  });
 },
 RequireAssignTooltips: function() {
  return this.enableEllipsis && !ASPx.Browser.MobileUI;
 },
 RemoveEllipsisFromNode: function(node) {
  ASPx.RemoveClassNameFromElement(node, ELLIPSIS_MARKER_CLASS);
  this.RemoveEllipsisTooltip(node);
 },
 RemoveEllipsisTooltip: function(node) {
  if(ASPx.Attr.IsExistsAttribute(node, ELLIPSIS_TOOLTIP_MARKER_ATTR)) {
   ASPx.Attr.RemoveAttribute(node, "title");
   ASPx.Attr.RemoveAttribute(node, ELLIPSIS_TOOLTIP_MARKER_ATTR);
  }
 },
 OnBrowserWindowResize: function(e) {
 },
 OnBrowserWindowResizeInternal: function(e){
  if(this.BrowserWindowResizeSubscriber()) 
   this.OnBrowserWindowResize(e);
 },
 BrowserWindowResizeSubscriber: function() {
  return this.widthValueSetInPercentage || !this.IsAdjusted();
 },
 ShrinkWrappedText: function(getElements, key, reCorrect) {
  if(!ASPx.Browser.Safari) return;
  var elements = ASPx.CacheHelper.GetCachedElements(this, key, getElements, this.wrappedTextContainers);
  for(var i = 0; i < elements.length; i++)
   this.ShrinkWrappedTextInContainer(elements[i], reCorrect);
 },
 ShrinkWrappedTextInContainer: function(container, reCorrect) {
  if(!ASPx.Browser.Safari || !container || (container.dxWrappedTextShrinked && !reCorrect) || container.offsetWidth === 0) return;
  ASPx.ShrinkWrappedTextInContainer(container);
  container.dxWrappedTextShrinked = true;
 },
 CorrectWrappedText: function(getElements, key, reCorrect) {
  var elements = ASPx.CacheHelper.GetCachedElements(this, key, getElements, this.wrappedTextContainers);
  for(var i = 0; i < elements.length; i++)
   this.CorrectWrappedTextInContainer(elements[i], reCorrect);
 },
 CorrectWrappedTextInContainer: function(container, reCorrect) {
  if(!container || (container.dxWrappedTextCorrected && !reCorrect) || container.offsetWidth === 0) return;
  ASPx.AdjustWrappedTextInContainer(container);
  container.dxWrappedTextCorrected = true;
 },
 CorrectVerticalAlignment: function(alignMethod, getElements, key, reAlign) {
  var elements = ASPx.CacheHelper.GetCachedElements(this, key, getElements, this.verticalAlignedElements);
  for(var i = 0; i < elements.length; i++)
   this.CorrectElementVerticalAlignment(alignMethod, elements[i], reAlign);
 },
 CorrectElementVerticalAlignment: function(alignMethod, element, reAlign) {
  if(!element || (element.dxVerticalAligned && !reAlign) || element.offsetHeight === 0) return;
  alignMethod(element);
  element.dxVerticalAligned = true;
 },
 ClearVerticalAlignedElementsCache: function() {
  ASPx.CacheHelper.DropCache(this.verticalAlignedElements);
 },
 ClearWrappedTextContainersCache: function() {
  ASPx.CacheHelper.DropCache(this.wrappedTextContainers);
 },
 AdjustPagerControls: function() {
  if(typeof(ASPx.GetPagersCollection) != "undefined")
   ASPx.GetPagersCollection().AdjustControls(this.GetMainElement());
 },
 RegisterInControlTree: function(tree) {
  var mainElement = this.GetMainElement();
  if(mainElement && mainElement.id)
   tree.createNode(mainElement.id, this);
 },
 GetItemElementName: function(element) {
  var name = "";
  if(element.id)
   name = element.id.substring(this.name.length + 1);
  return name;
 },
 GetLinkElement: function(element) {
  if(element == null) return null;
  return (element.tagName == "A") ? element : ASPx.GetNodeByTagName(element, "A", 0);
 },
 GetInternalHyperlinkElement: function(parentElement, index) {
  var element = ASPx.GetNodeByTagName(parentElement, "A", index);
  if(element == null) 
   element = ASPx.GetNodeByTagName(parentElement, "SPAN", index);
  return element;
 },
 OnControlClick: function(clickedElement, htmlEvent) {
 }
});
ASPxClientControl.Cast = function(obj) {
 if(typeof obj == "string")
  return window[obj];
 return obj;
};
ASPxClientControl.AdjustControls = function(container, collapseControls){
 aspxGetControlCollection().AdjustControls(container, collapseControls);
};
ASPxClientControl.GetControlCollection = function(){
 return aspxGetControlCollection();
};
ASPxClientControl.LeadingAfterInitCallConsts = {
 None: 0,
 Direct: 1,
 Reverse: 2
};
var ASPxClientComponent = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
 },
 IsDOMDisposed: function() { 
  return false;
 }
});
var ASPxClientControlCollection = ASPx.CreateClass(ASPx.CollectionBase, {
 constructor: function(){
  this.constructor.prototype.constructor.call(this);
  this.prevWndWidth = "";
  this.prevWndHeight = "";
  this.requestCountInternal = 0; 
  this.BeforeInitCallback = new ASPxClientEvent();
  this.ControlsInitialized = new ASPxClientEvent();
  this.BrowserWindowResized = new ASPxClientEvent();
  this.BrowserWindowResizedInternal = new ASPxClientEvent();
  this.BeginCallback = new ASPxClientEvent();
  this.EndCallback = new ASPxClientEvent();
  this.CallbackError = new ASPxClientEvent();
  this.ValidationCompleted = new ASPxClientEvent();
  aspxGetControlCollectionCollection().Add(this);
 },
 Add: function(element) {
  var existsElement = this.Get(element.name);
  if(existsElement && existsElement !== element) 
   this.Remove(existsElement);
  ASPx.CollectionBase.prototype.Add.call(this, element.name, element);
 },
 Remove: function(element) {
  if(element && element instanceof ASPxClientControl && !element.IsDisposed())
   element.OnDispose();
  ASPx.CollectionBase.prototype.Remove.call(this, element.name);
 },
 GetGlobal: function(name) {
  var result = window[name];
  return result && Ident.IsASPxClientControl(result)
   ? result
   : null;
 },
 GetByName: function(name){
  return this.Get(name) || this.GetGlobal(name);
 },
 GetCollectionType: function(){
  return ASPxClientControlCollection.BaseCollectionType;
 },
 GetControlsByPredicate: function(predicate) {
  var result = [];
  this.ForEachControl(function(control) {
   if(!predicate || predicate(control))
    result.push(control);
  });
  return result;
 },
 GetControlsByType: function(type) {
  return this.GetControlsByPredicate(function(control) { 
   return type && (control instanceof type);
  });
 },
 ForEachControl: function(action, context) {
  context = context || this;
  this.elementsMap.forEachEntry(function(name, control) {
   if(Ident.IsASPxClientControl(control) && (!this.filterPredicate || this.filterPredicate(control)))
    return action.call(context, control);
  }, context);
 },
 ProcessActionByPredicate: function(action, predicate) {
  try {
   this.filterPredicate = predicate;
   action(this);
  }
  finally {
   this.filterPredicate = null;
  }
 },
 adjustControlsInternal: function(container, context, collapseControls, adjustFunc) {
  context = context || this;
  var func = function(control) {
   adjustFunc.call(context, control);
  };
  ASPx.GetControlAdjuster().adjustControlsInHierarchy(this, func, container, collapseControls);
 },
 AdjustControls: function(container, collapseControls) {
  container = container || null;
  window.setTimeout(function() {
   this.AdjustControlsCore(container, collapseControls);
  }.aspxBind(this), 0);
 },
 AdjustControlsCore: function(container, collapseControls) {
  var adjustFunction = function(control) { control.AdjustControl(); };
  this.adjustControlsInternal(container, this, collapseControls, adjustFunction);
 },
 CollapseControls: function(container) {
  this.ProcessControlsInContainer(container, function(control) {
   if(control.isASPxClientEdit)
    control.CollapseEditor();
   else if(!!window.ASPxClientRibbon && control instanceof ASPxClientRibbon)
    control.CollapseControl();
  });
 },
 AtlasInitialize: function(isCallback) {
  this.ForEachControl(function(control) {
   control.AtlasPreInitialize();
  });
  ASPx.ProcessScriptsAndLinks("", isCallback);
  this.ForEachControl(function(control) {
   control.AtlasInitialize();
  });
 },
 DOMContentLoaded: function() {
  this.ForEachControl(function(control){
    control.DOMContentLoaded();
  });
 },
 OnDocumentUnload: function() {
  this.ForEachControl(function(control) {
   control.RaiseUnload();
  });
 },
 Initialize: function() {
  ASPx.GetPostHandler().Post.AddHandler(
   function(s, e) { this.OnPost(e); }.aspxBind(this)
  );
  ASPx.GetPostHandler().PostFinalization.AddHandler(
   function(s, e) { this.OnPostFinalization(e); }.aspxBind(this)
  );
  this.InitializeElements(false );
  if(typeof(Sys) != "undefined" && typeof(Sys.Application) != "undefined") {
   var checkIsInitialized = function() {
    if(Sys.Application.get_isInitialized())
     Sys.Application.add_load(aspxCAInit);
    else
     setTimeout(checkIsInitialized, 0);
   };
   checkIsInitialized();
  }
  this.InitWindowSizeCache();
 },
 FinalizeInitialization: function() {
  this.ForEachControl(function(control) {
   control.FinalizeInitialization();
  });
 },
 InitializeElements: function(isCallback) {
  this.ForEachControl(function(control){
   if(!control.isInitialized)
    control.Initialize();
  });
  this.AfterInitializeElementsLeadingCall();
  this.AfterInitializeElements();
  this.RaiseControlsInitialized(isCallback);
 },
 AfterInitializeElementsLeadingCall: function() {
  var controls = {};
  controls[ASPxClientControl.LeadingAfterInitCallConsts.Direct] = [];
  controls[ASPxClientControl.LeadingAfterInitCallConsts.Reverse] = [];
  this.ForEachControl(function(control) {
   if(control.leadingAfterInitCall != ASPxClientControl.LeadingAfterInitCallConsts.None && !control.isInitialized)
    controls[control.leadingAfterInitCall].push(control);
  });
  var directInitControls = controls[ASPxClientControl.LeadingAfterInitCallConsts.Direct],
   reverseInitControls = controls[ASPxClientControl.LeadingAfterInitCallConsts.Reverse];
  for(var i = 0, control; control = directInitControls[i]; i++)
   control.AfterInitialize();
  for(var i = reverseInitControls.length - 1, control; control = reverseInitControls[i]; i--)
   control.AfterInitialize();
 },
 AfterInitializeElements: function() {
  this.ForEachControl(function(control) {
   if(control.leadingAfterInitCall == ASPxClientControl.LeadingAfterInitCallConsts.None && !control.isInitialized)
    control.AfterInitialize();
  });
  ASPx.RippleHelper.Init();
 },
 DoFinalizeCallback: function() {
  this.ForEachControl(function(control){
   control.DoFinalizeCallback();
  });
 },
 ProcessControlsInContainer: function(container, processFunc, filterFunc) {
  this.ForEachControl(function(control){
   if((!filterFunc || filterFunc(control)) && (!container || this.IsControlInContainer(container, control)))
    processFunc(control);
  });
 },
 IsControlInContainer: function(container, control) {
  if(control.GetMainElement) {
   var mainElement = control.GetMainElement();
   if(mainElement && (mainElement != container)) {
    if(ASPx.GetIsParent(container, mainElement))
     return true;
   }
  }
  return false;
 },
 RaiseControlsInitialized: function(isCallback) {
  if(typeof(isCallback) == "undefined")
   isCallback = true;
  var args = new ASPxClientControlsInitializedEventArgs(isCallback);
  if(!this.ControlsInitialized.IsEmpty())  
   this.ControlsInitialized.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalControlsInitialized(args);
  });
 },
 RaiseBrowserWindowResized: function() {
  var args = new ASPxClientEventArgs();
  if(!this.BrowserWindowResized.IsEmpty())
   this.BrowserWindowResized.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalBrowserWindowResized(args);
  });
 },
 RaiseBrowserWindowResizedInternal: function(eventInfo) {
  var args = new ASPxClientBrowserWindowResizedInternalEventArgs(eventInfo);
  if(!this.BrowserWindowResizedInternal.IsEmpty())
   this.BrowserWindowResizedInternal.FireEvent(this, args);
 },
 RaiseBeginCallback: function (control, command) {
  var args = new ASPxClientGlobalBeginCallbackEventArgs(control, command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalBeginCallback(args);
  });
  this.IncrementRequestCount();
 },
 RaiseEndCallback: function (control) {
  var args = new ASPxClientGlobalEndCallbackEventArgs(control);
  if (!this.EndCallback.IsEmpty()) 
   this.EndCallback.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalEndCallback(args);
  });
  this.DecrementRequestCount();
 },
 InCallback: function() {
  return this.requestCountInternal > 0;
 },
 RaiseCallbackError: function (control, message, callbackId) {
  var args = new ASPxClientGlobalCallbackErrorEventArgs(control, message, callbackId);
  if (!this.CallbackError.IsEmpty()) 
   this.CallbackError.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalCallbackError(args);
  });
  if(args.handled)
   return { isHandled: true, errorMessage: args.message };  
  return { isHandled: false, errorMessage: message };
 },
 RaiseValidationCompleted: function (container, validationGroup, invisibleControlsValidated, isValid, firstInvalidControl, firstVisibleInvalidControl) {
  var args = new ASPxClientValidationCompletedEventArgs(container, validationGroup, invisibleControlsValidated, isValid, firstInvalidControl, firstVisibleInvalidControl);
  if (!this.ValidationCompleted.IsEmpty()) 
   this.ValidationCompleted.FireEvent(this, args);
  this.ForEachControl(function(control){
   control.OnGlobalValidationCompleted(args);
  });
  return args.isValid;
 },
 Before_WebForm_InitCallback: function(callbackOwnerID){
  var args = new BeforeInitCallbackEventArgs(callbackOwnerID);
  this.BeforeInitCallback.FireEvent(this, args);
 },
 InitWindowSizeCache: function(){
  this.prevWndWidth = ASPx.GetDocumentClientWidth();
  this.prevWndHeight = ASPx.GetDocumentClientHeight();
 },
 OnBrowserWindowResize: function(evt){
  this.OnBrowserWindowResizeCore(evt);
 },
 OnBrowserWindowResizeCore: function(htmlEvent){
  var args = this.CreateOnBrowserWindowResizeEventArgs(htmlEvent);
  if(this.CalculateIsBrowserWindowSizeChanged()) {
   this.RaiseBrowserWindowResizedInternal(args);
   this.adjustControlsInternal(null, this, true, function(control) {
    if(control.IsDOMInitialized())
     control.OnBrowserWindowResizeInternal(args);
   });
   this.RaiseBrowserWindowResized();
  }
 },
 CreateOnBrowserWindowResizeEventArgs: function(htmlEvent) {
  return {
   htmlEvent: htmlEvent,
   wndWidth: ASPx.GetDocumentClientWidth(),
   wndHeight: ASPx.GetDocumentClientHeight(),
   prevWndWidth: this.prevWndWidth,
   prevWndHeight: this.prevWndHeight,
   virtualKeyboardShownOnAndroid: this.IsVirtualKeyboardShownOnAndroid()
  };
 },
 IsVirtualKeyboardShownOnAndroid: function() {
  if(!ASPx.Browser.AndroidMobilePlatform)
   return false;
  var documentClientWidth = ASPx.GetDocumentClientWidth();
  var documentClientHeight = ASPx.GetDocumentClientHeight();
  var isDocumentClientHeightChangedOnly = documentClientWidth === this.prevWndWidth && documentClientHeight !== this.prevWndHeight;
  return isDocumentClientHeightChangedOnly && this.IsElementSupportKeyboardInput(document.activeElement);
 },
 IsElementSupportKeyboardInput: function(element) {
  if(!element || !element.tagName)
   return false;
  var supportedKeyboardInputTagNames = ["INPUT", "TEXTAREA"];
  return supportedKeyboardInputTagNames.indexOf(element.tagName) !== -1;
 },
 CalculateIsBrowserWindowSizeChanged: function(){
  var wndWidth = ASPx.GetDocumentClientWidth();
  var wndHeight = ASPx.GetDocumentClientHeight();
  var isBrowserWindowSizeChanged = (this.prevWndWidth != wndWidth) || (this.prevWndHeight != wndHeight);
  if(isBrowserWindowSizeChanged){
   this.prevWndWidth = wndWidth;
   this.prevWndHeight = wndHeight;
   return true;
  }
  return false;
 },
 OnPost: function(args){
  this.ForEachControl(function(control) {
   control.OnPost(args);
  }, null);
 },
 OnPostFinalization: function(args){
  this.ForEachControl(function(control) {
   control.OnPostFinalization(args);
  }, null);
 },
 IncrementRequestCount: function() {
  this.requestCountInternal++;
 },
 DecrementRequestCount: function() {
  this.requestCountInternal--;
 },
 ResetRequestCount: function() {
  this.requestCountInternal = 0;
 }
});
ASPxClientControlCollection.BaseCollectionType = "Control";
var controlCollection = null;
function aspxGetControlCollection(){
 if(controlCollection == null) {
  controlCollection = new ASPxClientControlCollection();
  if(ASPx.loadControlCollectionPreloadHandlers)
   ASPx.loadControlCollectionPreloadHandlers(controlCollection);
 }
 return controlCollection;
}
var ControlCollectionCollection = ASPx.CreateClass(ASPx.CollectionBase, {
 constructor: function(){
  this.constructor.prototype.constructor.call(this);
 },
 Add: function(element) {
  var key = element.GetCollectionType();
  if(!key) throw "The collection type isn't specified.";
  if(this.Get(key)) throw "The collection with type='" + key + "' already exists.";
  ASPx.CollectionBase.prototype.Add.call(this, key, element);
 },
 RemoveDisposedControls: function(){
  var baseCollection = this.Get(ASPxClientControlCollection.BaseCollectionType);
  var disposedControls = [];
  baseCollection.elementsMap.forEachEntry(function(name, control) {
   if(!ASPx.Ident.IsASPxClientControl(control)) return;
   if(control.IsDOMDisposed())
    disposedControls.push(control);
  });
  this.RemoveControls(disposedControls);
 },
 RemoveControls: function(controls){
  for(var i = 0; i < controls.length; i++) {
   this.elementsMap.forEachEntry(function(key, collection) {
    if(ASPx.Ident.IsASPxClientCollection(collection))
     collection.Remove(controls[i]);
   });
  }
 }
});
var controlCollectionCollection = null;
function aspxGetControlCollectionCollection(){
 if(controlCollectionCollection == null)
  controlCollectionCollection = new ControlCollectionCollection();
 return controlCollectionCollection;
}
var AriaDescriptionAttributes = {
 Role: "0",
 AriaLabel: "1",
 TabIndex: "2",
 AriaOwns: "3",
 AriaDescribedBy: "4",
 AriaDisabled: "5",
 AriaHasPopup: "6",
 AriaLevel: "7"
};
var AriaDescriptor = ASPx.CreateClass(null, {
 constructor: function(ownerControl, description) {
  this.ownerControl = ownerControl;
  this.rootElement = ownerControl.GetMainElement();
  this.description = description;
 },
 setDescription: function(name, argList) {
  var description = this.findChildDescription(name);
  if(description) {
   var elements = name ? this.rootElement.querySelectorAll(this.getDescriptionSelector(description)) : [this.rootElement];
   for(var i = 0; i < elements.length; i++)
    this.applyDescriptionToElement(elements[i], description, argList[i] || argList[0]);
  }
 },
 getDescriptionName: function(description) {
  return description.n;
 },
 getDescriptionSelector: function(description) {
  return description.s;
 },
 findChildDescription: function(name) {
  if(name === this.getDescriptionName(this.description))
   return this.description;
  var childCollection = this.description.c || [];
  for(var i = 0; i < childCollection.length; i++) {
   var childDescription = childCollection[i];
   if(this.getDescriptionName(childDescription) === name)
    return childDescription;
  }
  return null;
 },
 applyDescriptionToElement: function(element, description, args) {
  if(!description || !element)
   return;
  this.trySetAriaOwnsAttribute(element, description);
  this.trySetAriaDescribedByAttribute(element, description);
  this.trySetAttribute(element, description, AriaDescriptionAttributes.Role, "role");
  this.trySetAttribute(element, description, AriaDescriptionAttributes.TabIndex, "tabindex");
  this.trySetAttribute(element, description, AriaDescriptionAttributes.AriaLevel, "aria-level");
  this.executeOnDescription(description, AriaDescriptionAttributes.AriaLabel, function(value) {
   ASPx.Attr.SetAttribute(element, "aria-label", ASPx.Str.ApplyReplacement(value, args));
  });
  this.executeOnDescription(description, AriaDescriptionAttributes.AriaDisabled, function(value) {
   ASPx.Attr.SetAttribute(element, "aria-disabled", !!value); 
  });
  this.executeOnDescription(description, AriaDescriptionAttributes.AriaHasPopup, function(value) {
   ASPx.Attr.SetAttribute(element, "aria-haspopup", !!value);
  });
 },
 trySetAriaDescribedByAttribute: function(element, description) {
  this.executeOnDescription(description, AriaDescriptionAttributes.AriaDescribedBy, function(selectorInfo) {
   var descriptor = this.getNodesBySelector(element, selectorInfo.descriptorSelector)[0];
   var target = this.getNodesBySelector(element, selectorInfo.targetSelector)[0];
   if(!target || !descriptor)
    return;
   ASPx.Attr.SetAttribute(target, "aria-describedby", this.getNodeId(descriptor));
  });
 },
 trySetAriaOwnsAttribute: function(element, description) {
  this.executeOnDescription(description, AriaDescriptionAttributes.AriaOwns, function(selector) {
   var ownedNodes = this.getNodesBySelector(element, selector);
   var ariaOwnsAttributeValue = "";
   for(var i = 0; i < ownedNodes.length; i++)
    ariaOwnsAttributeValue += (this.getNodeId(ownedNodes[i]) + (i != ownedNodes.length - 1 ? " " : ""));
   ASPx.Attr.SetAttribute(element, "aria-owns", ariaOwnsAttributeValue);
  });
 },
 trySetAttribute: function(element, description, ariaAttribute, attributeName) {
  this.executeOnDescription(description, ariaAttribute, function(value) { 
   ASPx.Attr.SetAttribute(element, attributeName, description[ariaAttribute]); 
  });
 },
 executeOnDescription: function(description, ariaDescAttr, callback) {
  var descInfo = description[ariaDescAttr];
  if(ASPx.IsExists(descInfo))
   callback.aspxBind(this)(descInfo);
 },
 getNodesBySelector: function(element, selector) {
  var id = element.id || "";
  var childNodes = element.querySelectorAll("#" + this.getNodeId(element) + " > " + selector);
  ASPx.Attr.SetOrRemoveAttribute(element, "id", id);
  return childNodes;
 },
 getNodeId: function(node) {
  if(!node.id)
   node.id = this.createRandomId();
  return node.id; 
 },
 createRandomId: function() {
  return "r" + ASPx.CreateGuid();
 }
});
PagerCommands = {
 Next : "PBN",
 Prev : "PBP",
 Last : "PBL",
 First : "PBF",
 PageNumber : "PN",
 PageSize : "PSP"
};
ASPx.callbackProcessed = false;
ASPx.Callback = function(result, context){ 
 var collection = aspxGetControlCollection();
 collection.DoFinalizeCallback();
 var control = collection.Get(context);
 if(control != null)
  control.DoCallback(result);
 ASPx.RippleHelper.ReInit();
 ASPx.callbackProcessed = true;
};
ASPx.CallbackError = function(result, context){
 var control = aspxGetControlCollection().Get(context);
 if(control != null)
  control.DoCallbackError(result, false);
 ASPx.callbackProcessed = true;
};
ASPx.CClick = function(name, evt) {
 var control = aspxGetControlCollection().Get(name);
 if(control != null) control.DoControlClick(evt);
};
function aspxCAInit() {
 var isAppInit = typeof(Sys$_Application$initialize) != "undefined" &&
  ASPx.FunctionIsInCallstack(arguments.callee, Sys$_Application$initialize, 10 );
 aspxGetControlCollection().AtlasInitialize(!isAppInit);
}
ASPx.Evt.AttachEventToElement(window, "resize", aspxGlobalWindowResize);
function aspxGlobalWindowResize(evt){
 aspxGetControlCollection().OnBrowserWindowResize(evt); 
}
ASPx.Evt.AttachEventToElement(window, "unload", aspxClassesUnload);
function aspxClassesUnload(evt) {
 aspxGetControlCollection().OnDocumentUnload();
}
ASPx.attachToLoad(aspxClassesDOMContentLoaded);
function aspxClassesDOMContentLoaded(evt){
 aspxGetControlCollection().DOMContentLoaded();
}
ASPx.GetControlCollection = aspxGetControlCollection;
ASPx.GetControlCollectionCollection = aspxGetControlCollectionCollection;
ASPx.GetPersistentControlPropertiesStorage = _aspxGetPersistentControlPropertiesStorage;
ASPx.PagerCommands = PagerCommands;
ASPx.ELLIPSIS_MARKER_CLASS = ELLIPSIS_MARKER_CLASS;
window.ASPxClientBeginCallbackEventArgs = ASPxClientBeginCallbackEventArgs;
window.ASPxClientGlobalBeginCallbackEventArgs = ASPxClientGlobalBeginCallbackEventArgs;
window.ASPxClientEndCallbackEventArgs = ASPxClientEndCallbackEventArgs;
window.ASPxClientGlobalEndCallbackEventArgs = ASPxClientGlobalEndCallbackEventArgs;
window.ASPxClientCallbackErrorEventArgs = ASPxClientCallbackErrorEventArgs;
window.ASPxClientGlobalCallbackErrorEventArgs = ASPxClientGlobalCallbackErrorEventArgs;
window.ASPxClientCustomDataCallbackEventArgs = ASPxClientCustomDataCallbackEventArgs;
window.ASPxClientValidationCompletedEventArgs = ASPxClientValidationCompletedEventArgs;
window.ASPxClientControlsInitializedEventArgs = ASPxClientControlsInitializedEventArgs;
window.ASPxClientControlBeforePronounceEventArgs = ASPxClientControlBeforePronounceEventArgs;
window.ASPxClientControlUnloadEventArgs = ASPxClientControlUnloadEventArgs;
window.ASPxClientEndFocusEventArgs = ASPxClientEndFocusEventArgs;
window.ASPxClientItemFocusedEventArgs = ASPxClientItemFocusedEventArgs;
window.ASPxClientControlCollection = ASPxClientControlCollection;
window.ASPxClientControlBase = ASPxClientControlBase;
window.ASPxClientControl = ASPxClientControl;
window.ASPxClientComponent = ASPxClientComponent;
})(ASPx);

(function () {
 var PositionAnimationTransition = ASPx.CreateClass(ASPx.AnimationTransitionBase, {
  constructor: function (element, options) {
   this.constructor.prototype.constructor.call(this, element, options);
   this.direction = options.direction;
   this.animationTransition = this.createAnimationTransition();
   AnimationHelper.appendWKAnimationClassNameIfRequired(this.element);
  },
  Start: function (to) {
   var from = this.GetValue();
   if(ASPx.AnimationUtils.CanUseCssTransform()) {
    from = this.convertPosToCssTransformPos(from);
    to = this.convertPosToCssTransformPos(to);
   }
   this.animationTransition.Start(from, to);
  },
  SetValue: function (value) {
   ASPx.AnimationUtils.SetTransformValue(this.element, value, this.direction == AnimationHelper.SLIDE_VERTICAL_DIRECTION);
  },
  GetValue: function () {
   return ASPx.AnimationUtils.GetTransformValue(this.element, this.direction == AnimationHelper.SLIDE_VERTICAL_DIRECTION);
  },
  createAnimationTransition: function () {
   var transition = ASPx.AnimationUtils.CanUseCssTransform() ? this.createTransformAnimationTransition() : this.createPositionAnimationTransition();
   transition.transition = ASPx.AnimationConstants.Transitions.POW_EASE_OUT;
   return transition;
  },
  createTransformAnimationTransition: function () {
   return ASPx.AnimationUtils.createCssAnimationTransition(this.element, {
    property: ASPx.AnimationUtils.CanUseCssTransform(),
    duration: this.duration,
    onComplete: this.onComplete
   });
  },
  createPositionAnimationTransition: function () {
   return AnimationHelper.createAnimationTransition(this.element, {
    property: this.direction == AnimationHelper.SLIDE_VERTICAL_DIRECTION ? "top" : "left",
    unit: "px",
    duration: this.duration,
    onComplete: this.onComplete
   });
  },
  convertPosToCssTransformPos: function (position) {
   return ASPx.AnimationUtils.GetTransformCssText(position, this.direction == AnimationHelper.SLIDE_VERTICAL_DIRECTION);
  }
 });
 var AnimationHelper = {
  SLIDE_HORIZONTAL_DIRECTION: 0,
  SLIDE_VERTICAL_DIRECTION: 1,
  SLIDE_TOP_DIRECTION: 0,
  SLIDE_RIGHT_DIRECTION: 1,
  SLIDE_BOTTOM_DIRECTION: 2,
  SLIDE_LEFT_DIRECTION: 3,
  SLIDE_CONTAINER_CLASS: "dxAC",
  MAXIMUM_DEPTH: 3,
  createAnimationTransition: function (element, options) {
   if(options.onStep)
    options.animationEngineType = AnimationEngineType.JS;
   switch(options.animationEngineType) {
    case AnimationEngineType.JS:
     return ASPx.AnimationUtils.createJsAnimationTransition(element, options);
    case AnimationEngineType.CSS:
     return ASPx.AnimationUtils.createCssAnimationTransition(element, options);
    default:
     return ASPx.AnimationUtils.CanUseCssTransition() ? ASPx.AnimationUtils.createCssAnimationTransition(element, options) :
      ASPx.AnimationUtils.createJsAnimationTransition(element, options);
   }
  },
  createMultipleAnimationTransition: function (element, options) {
   return ASPx.AnimationUtils.createMultipleAnimationTransition(element, options);
  },
  createSimpleAnimationTransition: function (options) {
   return ASPx.AnimationUtils.createSimpleAnimationTransition(options);
  },
  cancelAnimation: function (element) {
   ASPx.AnimationTransitionBase.Cancel(element);
  },
  fadeIn: function(element, onComplete, duration, animationEngineType) {
   AnimationHelper.fadeTo(element, {
    from: 0, to: 1,
    onComplete: onComplete,
    animationEngineType: animationEngineType || AnimationEngineType.DEFAULT,
    duration: duration || ASPx.AnimationConstants.Durations.DEFAULT
   });
  },
  fadeOut: function(element, onComplete, duration, animationEngineType) {
   AnimationHelper.fadeTo(element, {
    from: ASPx.GetElementOpacity(element), to: 0,
    onComplete: onComplete,
    animationEngineType: animationEngineType || AnimationEngineType.DEFAULT,
    duration: duration || ASPx.AnimationConstants.Durations.DEFAULT
   });
  },
  fadeTo: function (element, options) {
   options.property = "opacity";
   if(!options.duration)
    options.duration = ASPx.AnimationConstants.Durations.SHORT;
   var transition = AnimationHelper.createAnimationTransition(element, options);
   if(!ASPx.IsExists(options.from))
    options.from = transition.GetValue();
   transition.Start(options.from, options.to);
  },
  slideIn: function (element, direction, onComplete, animationEngineType, rtl) {
   AnimationHelper.setOpacity(element, 1);
   var animationContainer = AnimationHelper.getSlideAnimationContainer(element, true, true);
   var pos = AnimationHelper.getSlideInStartPos(animationContainer, direction, rtl);
   var transition = AnimationHelper.createSlideTransition(animationContainer, direction,
    function (el) {
     AnimationHelper.resetSlideAnimationContainerSize(animationContainer);
     if(onComplete)
      onComplete(el);
    }, animationEngineType, rtl);
   transition.Start(pos, 0);
  },
  slideOut: function (element, direction, onComplete, animationEngineType, rtl) {
   var animationContainer = AnimationHelper.getSlideAnimationContainer(element, true, true);
   var pos = AnimationHelper.getSlideOutFinishPos(animationContainer, direction, rtl);
   var transition = AnimationHelper.createSlideTransition(animationContainer, direction,
    function (el) {
     AnimationHelper.setOpacity(el.firstChild, 0);
     if(onComplete)
      onComplete(el);
    }, animationEngineType, rtl);
   transition.Start(pos);
  },
  slideTo: function (element, options) {
   if(!ASPx.IsExists(options.direction))
    options.direction = AnimationHelper.SLIDE_HORIZONTAL_DIRECTION;
   var transition = new PositionAnimationTransition(element, options);
   transition.Start(options.to);
  },
  setOpacity: function (element, value) {
   ASPx.AnimationUtils.setOpacity(element, value);
  },
  appendWKAnimationClassNameIfRequired: function (element) {
   if(ASPx.AnimationUtils.CanUseCssTransform() && ASPx.Browser.WebKitFamily && !ASPx.ElementHasCssClass(element, "dx-wbv"))
    element.className += " dx-wbv";
  },
  findSlideAnimationContainer: function (element) {
   var container = element;
   for(var i = 0; i < AnimationHelper.MAXIMUM_DEPTH; i++) {
    if(container.tagName == "BODY")
     return null;
    if(ASPx.ElementHasCssClass(container, AnimationHelper.SLIDE_CONTAINER_CLASS))
     return container;
    container = container.parentNode;
   }
   return null;
  },
  createSlideAnimationContainer: function (element) {
   var rootContainer = document.createElement("DIV");
   ASPx.SetStyles(rootContainer, {
    className: AnimationHelper.SLIDE_CONTAINER_CLASS,
    overflow: "hidden"
   });
   var elementContainer = document.createElement("DIV");
   rootContainer.appendChild(elementContainer);
   var parentNode = element.parentNode;
   parentNode.insertBefore(rootContainer, element);
   elementContainer.appendChild(element);
   return rootContainer;
  },
  getSlideAnimationContainer: function (element, create, fixSize) {
   if(!element) return;
   var width = element.offsetWidth;
   var height = element.offsetHeight;
   var container;
   if(element.className == AnimationHelper.SLIDE_CONTAINER_CLASS)
    container = element;
   if(!container)
    container = AnimationHelper.findSlideAnimationContainer(element);
   if(!container && create)
    container = AnimationHelper.createSlideAnimationContainer(element);
   if(container && fixSize) {
    ASPx.SetStyles(container, {
     width: width, height: height
    });
    ASPx.SetStyles(container.firstChild, {
     width: width, height: height
    });
   }
   return container;
  },
  resetSlideAnimationContainerSize: function (container) {
   ASPx.SetStyles(container, {
    width: "", height: ""
   });
   ASPx.SetStyles(container.firstChild, {
    width: "", height: ""
   });
  },
  getModifyProperty: function (direction, rtl) {
   if(direction == AnimationHelper.SLIDE_TOP_DIRECTION || direction == AnimationHelper.SLIDE_BOTTOM_DIRECTION)
    return "marginTop";
   return rtl ? "margin-right" : "margin-left";
  },
  createSlideTransition: function (animationContainer, direction, complete, animationEngineType, rtl) {
   if(rtl == undefined)
    rtl = false;
   return AnimationHelper.createAnimationTransition(animationContainer.firstChild, {
    unit: "px",
    property: AnimationHelper.getModifyProperty(direction, rtl),
    onComplete: complete,
    animationEngineType: animationEngineType
   });
  },
  getSlideInStartPos: function (animationContainer, direction, rtl) {
   var dir = rtl ? -1 : 1;
   switch (direction) {
    case AnimationHelper.SLIDE_TOP_DIRECTION:
     return animationContainer.offsetHeight;
    case AnimationHelper.SLIDE_LEFT_DIRECTION:
     return animationContainer.offsetWidth * dir;
    case AnimationHelper.SLIDE_RIGHT_DIRECTION:
     return -animationContainer.offsetWidth * dir;
    case AnimationHelper.SLIDE_BOTTOM_DIRECTION:
     return -animationContainer.offsetHeight;
   }
  },
  getSlideOutFinishPos: function (animationContainer, direction, rtl) {
   var dir = rtl ? -1 : 1;
   switch (direction) {
    case AnimationHelper.SLIDE_TOP_DIRECTION:
     return -animationContainer.offsetHeight;
    case AnimationHelper.SLIDE_LEFT_DIRECTION:
     return -animationContainer.offsetWidth * dir;
    case AnimationHelper.SLIDE_RIGHT_DIRECTION:
     return animationContainer.offsetWidth * dir;
    case AnimationHelper.SLIDE_BOTTOM_DIRECTION:
     return animationContainer.offsetHeight;
   }
  }
 };
 var GestureHandler = ASPx.CreateClass(null, {
  constructor: function (getAnimationElement, canHandle, allowStart) {
   this.getAnimationElement = getAnimationElement;
   this.canHandle = canHandle;
   this.allowStart = allowStart;
   this.startMousePosX = 0;
   this.startMousePosY = 0;
   this.startTime = null;
   this.isEventsPrevented = false;
   this.savedElements = [];
  },
  OnSelectStart: function(evt) {
   ASPx.Evt.PreventEvent(evt); 
  },
  OnDragStart: function(evt) {
   ASPx.Evt.PreventEvent(evt);  
  },
  OnMouseDown: function (evt) {
   this.startMousePosX = ASPx.Evt.GetEventX(evt);
   this.startMousePosY = ASPx.Evt.GetEventY(evt);
   this.startTime = new Date();
  },
  OnMouseMove: function(evt) {
   if(!ASPx.Browser.MobileUI)
    ASPx.Selection.Clear();
   if(Math.abs(this.GetCurrentDistanceX(evt)) < GestureHandler.SLIDER_MIN_START_DISTANCE && Math.abs(this.GetCurrentDistanceY(evt)) < GestureHandler.SLIDER_MIN_START_DISTANCE)
    GesturesHelper.isExecutedGesture = false;
  },
  OnMouseUp: function (evt) {
  },
  CanHandleEvent: function (evt) {
   return !this.canHandle || this.canHandle(evt);
  },
  IsStartAllowed: function(value) {
   return !this.allowStart || this.allowStart(value);
  },
  RollbackGesture: function () {
  },
  GetRubberPosition: function (position) {
   return position / GestureHandler.FACTOR_RUBBER;
  },
  GetCurrentDistanceX: function (evt) {
   return ASPx.Evt.GetEventX(evt) - this.startMousePosX;
  },
  GetCurrentDistanceY: function (evt) {
   return ASPx.Evt.GetEventY(evt) - this.startMousePosY;
  },
  GetDistanceLimit: function () {
   return (new Date() - this.startTime) < GestureHandler.MAX_TIME_SPAN ? GestureHandler.MIN_DISTANCE_LIMIT : GestureHandler.MAX_DISTANCE_LIMIT;
  },
  GetContainerElement: function () {
  },
  AttachPreventEvents: function (evt) {
   if(!this.isEventsPrevented) {
    var element = ASPx.Evt.GetEventSource(evt);
    var container = this.GetContainerElement();
    while(element && element != container) {
     ASPx.Evt.AttachEventToElement(element, "mouseup", ASPx.Evt.PreventEvent);
     ASPx.Evt.AttachEventToElement(element, "click", ASPx.Evt.PreventEvent);
     this.savedElements.push(element);
     element = element.parentNode;
    }
    this.isEventsPrevented = true;
   }
  },
  DetachPreventEvents: function () {
   if(this.isEventsPrevented) {
    window.setTimeout(function () {
     while(this.savedElements.length > 0) {
      var element = this.savedElements.pop();
      ASPx.Evt.DetachEventFromElement(element, "mouseup", ASPx.Evt.PreventEvent);
      ASPx.Evt.DetachEventFromElement(element, "click", ASPx.Evt.PreventEvent);
     }
    }.aspxBind(this), 0);
    this.isEventsPrevented = false;
   }
  }
 });
 GestureHandler.MAX_DISTANCE_LIMIT = 70;
 GestureHandler.MIN_DISTANCE_LIMIT = 10;
 GestureHandler.MIN_START_DISTANCE = 0;
 GestureHandler.SLIDER_MIN_START_DISTANCE = 5;
 GestureHandler.MAX_TIME_SPAN = 300;
 GestureHandler.FACTOR_RUBBER = 4;
 GestureHandler.RETURN_ANIMATION_DURATION = 150;
 var SwipeSlideGestureHandler = ASPx.CreateClass(GestureHandler, {
  constructor: function (getAnimationElement, direction, canHandle, backward, forward, rollback, move) {
   this.constructor.prototype.constructor.call(this, getAnimationElement, canHandle);
   this.slideElement = this.getAnimationElement();
   this.container = this.slideElement.parentNode;
   this.direction = direction;
   this.backward = backward;
   this.forward = forward;
   this.rollback = rollback;
   this.slideElementSize = 0;
   this.containerElementSize = 0;
   this.startSliderElementPosition = 0;
   this.centeredSlideElementPosition = 0;
  },
  OnMouseDown: function (evt) {
   GestureHandler.prototype.OnMouseDown.call(this, evt);
   this.slideElementSize = this.GetElementSize();
   this.startSliderElementPosition = this.GetElementPosition();
   this.containerElementSize = this.GetContainerElementSize();
   if(this.slideElementSize <= this.containerElementSize)
    this.centeredSlideElementPosition = (this.containerElementSize - this.slideElementSize) / 2;
  },
  OnMouseMove: function (evt) {
   GestureHandler.prototype.OnMouseMove.call(this, evt);
   if(!ASPx.Browser.TouchUI && !ASPx.GetIsParent(this.container, ASPx.Evt.GetEventSource(evt))) {
    GesturesHelper.OnDocumentMouseUp(evt);
    return;
   }
   var distance = this.GetCurrentDistance(evt);
   if(Math.abs(distance) < GestureHandler.SLIDER_MIN_START_DISTANCE || ASPx.TouchUIHelper.isGesture)
    return;
   this.SetElementPosition(this.GetCalculatedPosition(distance));
   this.AttachPreventEvents(evt);
   ASPx.Evt.PreventEvent(evt);
  },
  GetCalculatedPosition: function (distance) {
   ASPx.AnimationTransitionBase.Cancel(this.slideElement);
   var position = this.startSliderElementPosition + distance,
    maxPosition = -(this.slideElementSize - this.containerElementSize),
    minPosition = 0;
   if(this.centeredSlideElementPosition > 0)
    position = this.GetRubberPosition(distance) + this.centeredSlideElementPosition;
   else if(position > minPosition)
    position = this.GetRubberPosition(distance);
   else if(position < maxPosition)
    position = this.GetRubberPosition(distance) + maxPosition;
   return position;
  },
  OnMouseUp: function (evt) {
   this.DetachPreventEvents();
   if(this.GetCurrentDistance(evt) != 0)
    this.OnMouseUpCore(evt);
  },
  OnMouseUpCore: function (evt) {
   var distance = this.GetCurrentDistance(evt);
   if(this.centeredSlideElementPosition > 0 || this.CheckSlidePanelIsOutOfBounds())
    this.PerformRollback();
   else
    this.PerformAction(distance);
  },
  PerformAction: function (distance) {
   if(Math.abs(distance) < this.GetDistanceLimit())
    this.PerformRollback();
   else if(distance < 0)
    this.PerformForward();
   else
    this.PerformBackward();
  },
  PerformBackward: function () {
   this.backward();
  },
  PerformForward: function () {
   this.forward();
  },
  PerformRollback: function () {
   this.rollback();
  },
  CheckSlidePanelIsOutOfBounds: function () {
   var minOffset = -(this.slideElementSize - this.containerElementSize), maxOffset = 0;
   var slideElementPos = this.GetElementPosition();
   if(slideElementPos > maxOffset || slideElementPos < minOffset)
    return true;
   return false;
  },
  GetContainerElement: function () {
   return this.container;
  },
  GetElementSize: function () {
   return this.IsHorizontalDirection() ? this.slideElement.offsetWidth : this.slideElement.offsetHeight;
  },
  GetContainerElementSize: function () {
   return this.IsHorizontalDirection() ? ASPx.GetClearClientWidth(this.container) : ASPx.GetClearClientHeight(this.container);
  },
  GetCurrentDistance: function (evt) {
   return this.IsHorizontalDirection() ? this.GetCurrentDistanceX(evt) : this.GetCurrentDistanceY(evt);
  },
  GetElementPosition: function () {
   return ASPx.AnimationUtils.GetTransformValue(this.slideElement, !this.IsHorizontalDirection());
  },
  SetElementPosition: function (position) {
   ASPx.AnimationUtils.SetTransformValue(this.slideElement, position, !this.IsHorizontalDirection());
  },
  IsHorizontalDirection: function () {
   return this.direction == AnimationHelper.SLIDE_HORIZONTAL_DIRECTION;
  }
 });
 var SwipeSimpleSlideGestureHandler = ASPx.CreateClass(SwipeSlideGestureHandler, {
  constructor: function (getAnimationElement, direction, canHandle, backward, forward, rollback, updatePosition) {
   this.constructor.prototype.constructor.call(this, getAnimationElement, direction, canHandle, backward, forward, rollback);
   this.container = this.slideElement;
   this.updatePosition = updatePosition;
   this.prevDistance = 0;
  },
  OnMouseDown: function (evt) {
   GestureHandler.prototype.OnMouseDown.call(this, evt);
   this.prevDistance = 0;
  },
  OnMouseUpCore: function (evt) {
   this.PerformAction(this.GetCurrentDistance(evt));
  },
  PerformAction: function (distance) {
   if(Math.abs(distance) < this.GetDistanceLimit())
    this.PerformRollback();
   else if(distance < 0)
    this.PerformForward();
   else
    this.PerformBackward();
  },
  GetCalculatedPosition: function (distance) {
   var position = distance - this.prevDistance;
   this.prevDistance = distance;
   return position;
  },
  SetElementPosition: function (position) {
   this.updatePosition(position);
  }
 });
 var SwipeGestureHandler = ASPx.CreateClass(GestureHandler, {
  constructor: function (getAnimationElement, canHandle, allowStart, start, allowComplete, complete, cancel, animationEngineType, rtl) {
   this.constructor.prototype.constructor.call(this, getAnimationElement, canHandle, allowStart);
   this.start = start;
   this.allowComplete = allowComplete;
   this.complete = complete;
   this.cancel = cancel;
   this.animationTween = null;
   this.currentDistanceX = 0;
   this.currentDistanceY = 0;
   this.tryStartGesture = false;
   this.tryStartScrolling = false;
   this.animationEngineType = animationEngineType;
   this.rtl = rtl;
   this.UpdateAnimationContainer();
  },
  UpdateAnimationContainer: function () {
   this.animationContainer = AnimationHelper.getSlideAnimationContainer(this.getAnimationElement(), true, false);
  },
  CanHandleEvent: function (evt) {
   if(GestureHandler.prototype.CanHandleEvent.call(this, evt))
    return true;
   return this.animationTween && this.animationContainer && ASPx.GetIsParent(this.animationContainer, ASPx.Evt.GetEventSource(evt));
  },
  OnMouseDown: function (evt) {
   GestureHandler.prototype.OnMouseDown.call(this, evt);
   if(this.animationTween)
    this.animationTween.Cancel();
   this.currentDistanceX = 0;
   this.currentDistanceY = 0;
   this.tryStartGesture = false;
   this.tryStartScrolling = false;
  },
  OnMouseMove: function (evt) {
   GestureHandler.prototype.OnMouseMove.call(this, evt);
   var isZoomGestureConflict = evt.touches && evt.touches.length > 1;
   if (isZoomGestureConflict)
    return false;
   this.currentDistanceX = this.GetCurrentDistanceX(evt);
   this.currentDistanceY = this.GetCurrentDistanceY(evt);
   if(this.rtl)
    this.currentDistanceX = -this.currentDistanceX;
   if(!this.animationTween && !this.tryStartScrolling && (Math.abs(this.currentDistanceX) >
    GestureHandler.MIN_START_DISTANCE || Math.abs(this.currentDistanceY) > GestureHandler.MIN_START_DISTANCE)) {
    if(Math.abs(this.currentDistanceY) < Math.abs(this.currentDistanceX)) {
     this.tryStartGesture = true;
     if(this.IsStartAllowed(this.currentDistanceX)) {
      this.animationContainer = AnimationHelper.getSlideAnimationContainer(this.getAnimationElement(), true, true);
      this.animationTween = AnimationHelper.createSlideTransition(this.animationContainer, AnimationHelper.SLIDE_LEFT_DIRECTION,
       function () {
        AnimationHelper.resetSlideAnimationContainerSize(this.animationContainer);
        this.animationContainer = null;
        this.animationTween = null;
       }.aspxBind(this), this.animationEngineType, this.rtl);
      this.PerformStart(this.currentDistanceX);
      this.AttachPreventEvents(evt);
     }
    }
    else
     this.tryStartScrolling = true;
   }
   if(this.animationTween) {
    if(this.allowComplete && !this.allowComplete(this.currentDistanceX))
     this.currentDistanceX = this.GetRubberPosition(this.currentDistanceX);
    this.animationTween.SetValue(this.currentDistanceX);
   }
   if(!this.tryStartScrolling && !ASPx.TouchUIHelper.isGesture && evt.touches && evt.touches.length < 2)
    ASPx.Evt.PreventEvent(evt);
  },
  OnMouseUp: function (evt) {
   if(!this.animationTween) {
    if(this.tryStartGesture)
     this.PerformCancel(this.currentDistanceX);
   }
   else {
    if(Math.abs(this.currentDistanceX) < this.GetDistanceLimit())
     this.RollbackGesture();
    else {
     if(this.IsCompleteAllowed(this.currentDistanceX)) {
      this.PerformComplete(this.currentDistanceX);
      this.animationContainer = null;
      this.animationTween = null;
     }
     else
      this.RollbackGesture();
    }
   }
   this.DetachPreventEvents();
   this.tryStartGesture = false;
   this.tryStartScrolling = false;
  },
  PerformStart: function (value) {
   if(this.start)
    this.start(value);
  },
  IsCompleteAllowed: function (value) {
   return !this.allowComplete || this.allowComplete(value);
  },
  PerformComplete: function (value) {
   if(this.complete)
    this.complete(value);
  },
  PerformCancel: function (value) {
   if(this.cancel)
    this.cancel(value);
  },
  RollbackGesture: function () {
   this.animationTween.Start(this.currentDistanceX, 0);
  },
  ResetGestureElementPosition: function () {
   if (this.currentDistanceX === 0) return;
   var container = AnimationHelper.getSlideAnimationContainer(this.getAnimationElement());
   var onComplete = function () { AnimationHelper.resetSlideAnimationContainerSize(container); };
   var animation = AnimationHelper.createSlideTransition(container, AnimationHelper.SLIDE_LEFT_DIRECTION, onComplete, this.animationEngineType, this.rtl);
   animation.Start(this.currentDistanceX, 0);
  },
  GetContainerElement: function () {
   return this.animationContainer;
  }
 });
 var GesturesHelper = {
  handlers: {},
  activeHandler: null,
  isAttachedEvents: false,
  isExecutedGesture: false,
  AddSwipeGestureHandler: function (id, getAnimationElement, canHandle, allowStart, start, allowComplete, complete, cancel, animationEngineType, rtl) {
   this.handlers[id] = new SwipeGestureHandler(getAnimationElement, canHandle, allowStart, start, allowComplete, complete, cancel, animationEngineType, rtl);
  },
  UpdateSwipeAnimationContainer: function (id) {
   if(this.handlers[id])
    this.handlers[id].UpdateAnimationContainer();
  },
  AddSwipeSlideGestureHandler: function (id, getAnimationElement, direction, canHandle, backward, forward, rollback, updatePosition) {
   if(updatePosition)
    this.handlers[id] = new SwipeSimpleSlideGestureHandler(getAnimationElement, direction, canHandle, backward, forward, rollback, updatePosition);
   else
    this.handlers[id] = new SwipeSlideGestureHandler(getAnimationElement, direction, canHandle, backward, forward, rollback);
  },
  getParentDXEditorWithSwipeGestures: function(element) {
     return ASPx.GetParent(element, function(parent) {
      var parentObj = ASPx.GetControlCollection().Get(parent.id);
      return parentObj && parentObj.supportGestures && parentObj.isSwipeGesturesEnabled();
   });
  },
  canHandleMouseDown: function(evt) {
   if(!ASPx.Evt.IsLeftButtonPressed(evt))
    return false;
   var element = ASPx.Evt.GetEventSource(evt);
   var dxFocusedEditor = ASPx.Ident.scripts.ASPxClientEdit && ASPx.GetFocusedEditor();
   if(dxFocusedEditor && dxFocusedEditor.IsEditorElement(element)) {
    var elementParentDXEditorWithSwipeGestures = GesturesHelper.getParentDXEditorWithSwipeGestures(element);
    if(!elementParentDXEditorWithSwipeGestures || !dxFocusedEditor.IsEditorElement(elementParentDXEditorWithSwipeGestures))
     return false;
   }
   var isTextEditor = element.tagName == "TEXTAREA" || element.tagName == "INPUT" && ASPx.Attr.GetAttribute(element, "type") == "text";
   if(isTextEditor && document.activeElement == element)
    return false;
   return true;  
  },
  OnDocumentDragStart: function(evt) {
   if(GesturesHelper.activeHandler)
    GesturesHelper.activeHandler.OnDragStart(evt);
  },
  OnDocumentSelectStart: function(evt) {
   if(GesturesHelper.activeHandler)
    GesturesHelper.activeHandler.OnSelectStart(evt);
  },
  OnDocumentMouseDown: function (evt) {
   if(!GesturesHelper.canHandleMouseDown(evt))
    return;
   GesturesHelper.activeHandler = GesturesHelper.FindHandler(evt);
   if(GesturesHelper.activeHandler)
    GesturesHelper.activeHandler.OnMouseDown(evt);
  },
  OnDocumentMouseMove: function (evt) {
   if(GesturesHelper.activeHandler) {
    GesturesHelper.isExecutedGesture = true;
    GesturesHelper.activeHandler.OnMouseMove(evt);
   }
  },
  OnDocumentMouseUp: function (evt) {
   if(GesturesHelper.activeHandler) {
    GesturesHelper.activeHandler.OnMouseUp(evt);
    GesturesHelper.activeHandler = null;
    window.setTimeout(function () { GesturesHelper.isExecutedGesture = false; }, 0);
   }
  },
  AttachEvents: function () {
   if(!GesturesHelper.isAttachedEvents) {
    GesturesHelper.Attach(ASPx.Evt.AttachEventToElement);
    GesturesHelper.isAttachedEvents = true;
   }
  },
  DetachEvents: function () {
   if(GesturesHelper.isAttachedEvents) {
    GesturesHelper.Attach(ASPx.Evt.DetachEventFromElement);
    GesturesHelper.isAttachedEvents = false;
   }
  },
  Attach: function (changeEventsMethod) {
   var doc = window.document;
   changeEventsMethod(doc, ASPx.TouchUIHelper.touchMouseDownEventName, GesturesHelper.OnDocumentMouseDown);
   changeEventsMethod(doc, ASPx.TouchUIHelper.touchMouseMoveEventName, GesturesHelper.OnDocumentMouseMove);
   changeEventsMethod(doc, ASPx.TouchUIHelper.touchMouseUpEventName, GesturesHelper.OnDocumentMouseUp);
   if(!ASPx.Browser.MobileUI) {
    changeEventsMethod(doc, "selectstart", GesturesHelper.OnDocumentSelectStart);
    changeEventsMethod(doc, "dragstart", GesturesHelper.OnDocumentDragStart);
   }
  },
  FindHandler: function (evt) {
   var handlers = [];
   for(var id in GesturesHelper.handlers) {
    if(GesturesHelper.handlers.hasOwnProperty(id)) {
     var handler = GesturesHelper.handlers[id];
     if(handler.CanHandleEvent && handler.CanHandleEvent(evt))
      handlers.push(handler);
    }
   }
   if(!handlers.length)
    return null;
   handlers.sort(function (a, b) {
    return ASPx.GetIsParent(a.getAnimationElement(), b.getAnimationElement()) ? 1 : -1;
   });
   return handlers[0];
  },
  IsExecutedGesture: function () {
   return GesturesHelper.isExecutedGesture;
  }
 };
 GesturesHelper.AttachEvents();
 var AnimationEngineType = {
  "DEFAULT": 0,
  "CSS": 1,
  "JS": 2
 };
 ASPx.AnimationEngineType = AnimationEngineType;
 ASPx.AnimationHelper = AnimationHelper;
 ASPx.GesturesHelper = GesturesHelper;
})();

(function() {
 var InitializeMobileScripts = function() {
  var customScrollableElementsCollection = [];
  var SCROLLBAR_CLASSNAMES = {
   VERTICAL: "dxTouchVScrollHandle",
   HORIZONTAL: "dxTouchHScrollHandle",
   SHOWN_VERTICAL: "dxTouchScrollHandleVisible",
   SHOWN_HORIZONTAL: "dxTouchScrollHandleVisible",
   CUSTOMIZED_NATIVE: "dxTouchNativeScrollHandle"
  };
  ASPx.Evt.AttachEventToDocument("gesturestart", function() {
   ASPx.TouchUIHelper.isGesture = true;
  });
  ASPx.Evt.AttachEventToDocument("gestureend", function() {
   ASPx.TouchUIHelper.isGesture = false;
  });
  ASPx.TouchUIHelper.MakeScrollable = function(element, options) {
   return new ASPx.TouchUIHelper.ScrollExtender(element, options);
  };
  ASPx.TouchUIHelper.ScrollExtender = function(element, options) {
   this.parseOptions(options ? options : {});
   this.create(element);
  };
  ASPx.TouchUIHelper.preventScrollOnEvent = function(evt) {
   evt.ASPxTouchUIScrollOff = true;
  };
  var isCustomScroll = function(elem) { return ASPx.Data.ArrayContains(customScrollableElementsCollection, elem); };
  var isNativeScroll = function(elem) {
   var style = window.getComputedStyle(elem);
   return ["overflow", "overflow-x", "overflow-y"].some(function(prop) {
    return ASPx.Data.ArrayContains(["scroll", "auto"], style[prop]);
   });
  };
  var requirePreventCustomScroll = function(elem, scrollElement) {
   if(!scrollElement)
    return;
   while(elem && elem !== scrollElement && elem.tagName !== 'BODY') {
    if(isNativeScroll(elem) || isCustomScroll(elem))
     return true;
    elem = elem.parentNode;
   }
   return false;
  };
  ASPx.TouchUIHelper.RequirePreventCustomScroll = requirePreventCustomScroll;
  ASPx.TouchUIHelper.InitNativeScrolling = function(element, options) {
   if(options.showHorizontalScrollbar || options.showVerticalScrollbar) {
    element.style["overflow"] = "scroll";
    element.style["overflow-x"] = options.showHorizontalScrollbar ? "scroll" : "hidden";
    element.style["overflow-y"] = options.showVerticalScrollbar ? "scroll" : "hidden";
    element.style["-webkit-overflow-scrolling"] = "touch";
    if(options.customizeNativeScrolling)
     ASPx.AddClassNameToElement(element, SCROLLBAR_CLASSNAMES.CUSTOMIZED_NATIVE);
   }
  };
  ASPx.TouchUIHelper.ScrollExtender.prototype = {
   ChangeElement: function(element) {
    this.Destroy();
    this.create(element);
   },
   Destroy: function() {
    this.destroyScrollHandlers();
    this.detachEventHandlers();
    ASPx.Data.ArrayRemove(customScrollableElementsCollection, this.element);
   },
   PreventAndStopScroll: function() {
    this.updateScrollHandles();
    this.stopScroll();
    this.ReleaseScrolling();
   },
   LockScrollUpdate: function() {
    this.scrollUpdateLocked = true;
   },
   UnlockScrollUpdate: function() {
    this.scrollUpdateLocked = false;
   },
   acceptElement: function(element) {
    if(typeof (element) == "string")
     element = document.getElementById(element);
    this.element = element;
    this.touchEventHandlersElement = this.options.touchEventHandlersElement ? this.options.touchEventHandlersElement : this.element;
    if(ASPx.Browser.AndroidMobilePlatform) {
     element.dxScrollable = true;
     element.style["overflow-x"] = "hidden";
     element.style["overflow-y"] = "hidden";
    }
    return element;
   },
   create: function(element) {
    this.acceptElement(element);
    if(this.options.nativeScrolling) {
     ASPx.TouchUIHelper.InitNativeScrolling(this.element, this.options);
    } else {
     customScrollableElementsCollection.push(this.element);
     this.createScrollHandlers();
     this.createEventHandlers();
     this.updateInitData();
     this.updateScrollHandles();
     this.attachEventHandlers();
    }
   },
   parseOptions: function(options) {
    this.options = {};
    this.options.showHorizontalScrollbar = options.showHorizontalScrollbar !== false;
    this.options.showVerticalScrollbar = options.showVerticalScrollbar !== false;
    this.options.acceleration = options.acceleration || 0.8;
    this.options.timeStep = options.timeStep || 50;
    this.options.minScrollbarSize = options.minScrollbarSize || 20;
    this.options.vScrollClassName = options.vScrollClassName || SCROLLBAR_CLASSNAMES.VERTICAL;
    this.options.hScrollClassName = options.hScrollClassName || SCROLLBAR_CLASSNAMES.HORIZONTAL;
    this.options.vScrollClassNameShown = [
     this.options.vScrollClassName,
     options.vScrollClassNameShown || SCROLLBAR_CLASSNAMES.SHOWN_VERTICAL
    ].join(" ");
    this.options.hScrollClassNameShown = [
     this.options.hScrollClassName,
     options.hScrollClassNameShown || SCROLLBAR_CLASSNAMES.SHOWN_HORIZONTAL
    ].join(" ");
    this.options.forceCustomScroll = options.forceCustomScroll === true;
    this.options.forceOnDesktop = options.forceOnDesktop === true;
    this.options.allowMouseWheelOnCtrl = options.allowMouseWheelOnCtrl !== false;
    var nativeScrollPossible = !options.acceleration && !options.timeStep && !options.minScrollbarSize && !options.vScrollClassName && !options.hScrollClassName && !options.forceCustomScroll;
    if(nativeScrollPossible && ASPx.TouchUIHelper.IsNativeScrolling())
     this.options.nativeScrolling = true;
    if(ASPx.Browser.AndroidMobilePlatform && ASPx.Browser.WebKitFamily)
     this.options.customizeNativeScrolling = true;
    this.options.touchEventHandlersElement = options.touchEventHandlersElement;
    this.options.scrollPageIfCannotScrollDiv = options.scrollPageIfCannotScrollDiv === true;
    this.options.enableMultiTouchScrolling = options.enableMultiTouchScrolling !== false;
   },
   createEventHandlers: function() {
    var instance = this;
    this.onTouchStart = function(e) {
     if(!instance.options.enableMultiTouchScrolling && ASPx.TouchUIHelper.IsMultiTouchEvent(e)) return;
     if(!ASPx.TouchUIHelper.isGesture) {
      if(!ASPx.TouchUIHelper.ScrollExtender.activeScrolling) {
       if(requirePreventCustomScroll(ASPx.Evt.GetEventSource(e), instance.touchEventHandlersElement)) {
        e.stopPropagation();
        return;
       }
       ASPx.TouchUIHelper.ScrollExtender.activeScrolling = instance;
       instance.startScroll(e);
      }
     }
    };
    this.onTouchMove = function(e) {
     if(!instance.options.enableMultiTouchScrolling && ASPx.TouchUIHelper.IsMultiTouchEvent(e)) return;
     if(e.cancelable && !ASPx.TouchUIHelper.isGesture && instance.ScrollingActive(e)) {
      var scrolled = instance.scroll(e);
      var alwaysPreventDefault = !instance.options.scrollPageIfCannotScrollDiv;
      if((instance.scrollBarsShown && alwaysPreventDefault) || (!alwaysPreventDefault && scrolled))
       ASPx.Evt.PreventEvent(e);
     }
    };
    this.onTouchEnd = function(e) {
     if(!instance.options.enableMultiTouchScrolling && ASPx.TouchUIHelper.IsMultiTouchEvent(e)) return;
     if(!ASPx.TouchUIHelper.isGesture) {
      instance.scrollLeft = instance.element.scrollLeft;
      instance.scrollTop = instance.element.scrollTop;
      instance.stopScroll();
      if(ASPx.TouchUIHelper.ScrollExtender.activeScrolling && ASPx.TouchUIHelper.ScrollExtender.activeScrolling.initTouchX == instance.initTouchX && ASPx.TouchUIHelper.ScrollExtender.activeScrolling.initTouchY == instance.initTouchY)
       instance.MouseEventEmulationProtectHelper.onTouchEnd(instance.initTouchX, instance.initTouchY, e);
      instance.ReleaseScrolling();
     }
    };
    this.onScroll = function(e) {
     if(ASPx.TouchUIHelper.isGesture && instance.ScrollingActive(e)) {
      instance.showScrollBars();
      instance.updateScrollHandles();
     }
    };
    this.onClick = function() {
     instance.MouseEventEmulationProtectHelper.onClick();
    };
    this.onHandleMouseDown = function(e, isVertical) {
     if(!ASPx.TouchUIHelper.ScrollExtender.activeHandlerDragging) {
      ASPx.TouchUIHelper.ScrollExtender.activeHandlerDragging = instance;
      instance.startHandleDrag(e, isVertical);
     }
    };
    this.onMouseMove = function(e) {
     if(instance.HandlerDraggingActive(e))
      instance.dragHandle(e);
    };
    this.onMouseUp = function(e) {
     if(instance.HandlerDraggingActive(e)) {
      instance.scrollLeft = instance.element.scrollLeft;
      instance.scrollTop = instance.element.scrollTop;
      instance.stopHandleDrag();
      instance.ReleaseHandlerDragging();
     }
    };
    this.onMouseOver = function() {
     if(!instance.scrollUpdateLocked) {
      instance.updateInitData();
      instance.showScrollBars();
      instance.updateScrollHandles();
     }
    };
    this.onMouseOut = function(e) {
     if(!instance.HandlerDraggingActive(e))
      instance.hideScrollBars();
    };
    this.onMouseWheel = function(e) {
     if(e.ctrlKey && !instance.options.allowMouseWheelOnCtrl) return;
     instance.showScrollBars();
     instance.updateScrollHandles();
     instance.offset(e.deltaX, e.deltaY);
     instance.updateScrollHandles();
     ASPx.Evt.PreventEventAndBubble(e);
    };
   },
   createScrollHandlers: function() {
    if(this.options.showHorizontalScrollbar) {
     this.hScrollHandleElement = document.createElement("DIV");
     this.hScrollHandleElement.className = this.options.hScrollClassName;
     this.element.appendChild(this.hScrollHandleElement);
     this.hEndMargin = this.options.showVerticalScrollbar ? ASPx.PxToInt(ASPx.GetCurrentStyle(this.hScrollHandleElement).marginRight) : 0;
    }
    if(this.options.showVerticalScrollbar) {
     this.vScrollHandleElement = document.createElement("DIV");
     this.vScrollHandleElement.className = this.options.vScrollClassName;
     this.element.appendChild(this.vScrollHandleElement);
     this.vEndMargin = this.options.showHorizontalScrollbar ? ASPx.PxToInt(ASPx.GetCurrentStyle(this.vScrollHandleElement).marginBottom) : 0;
    }
   },
   destroyScrollHandlers: function() {
    if(this.hScrollHandleElement && this.hScrollHandleElement.parentNode)
     this.hScrollHandleElement.parentNode.removeChild(this.hScrollHandleElement);
    if(this.vScrollHandleElement && this.vScrollHandleElement.parentNode)
     this.vScrollHandleElement.parentNode.removeChild(this.vScrollHandleElement);
    this.hScrollHandleElement = null;
    this.vScrollHandleElement = null;
   },
   attachEventHandlers: function() {
    if(ASPx.Browser.WebKitTouchUI) {
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "touchstart", this.onTouchStart, true);
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "touchend", this.onTouchEnd, true);
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "touchmove", this.onTouchMove, true);
    } else if(this.options.forceOnDesktop) {
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "mouseover", this.onMouseOver);
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "mouseout", this.onMouseOut);
     ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "wheel", this.onMouseWheel);
     if(this.vScrollHandleElement)
      ASPx.Evt.AttachEventToElement(this.vScrollHandleElement, "mousedown", function(e) { this.onHandleMouseDown(e, true); }.bind(this));
     if(this.hScrollHandleElement)
      ASPx.Evt.AttachEventToElement(this.hScrollHandleElement, "mousedown", function(e) { this.onHandleMouseDown(e, false); }.bind(this));
     ASPx.Evt.AttachEventToDocument("mousemove", this.onMouseMove);
     ASPx.Evt.AttachEventToDocument("mouseup", this.onMouseUp);
    }
    ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "scroll", this.onScroll, true);
    ASPx.Evt.AttachEventToElement(this.touchEventHandlersElement, "click", this.onClick, true);
   },
   detachEventHandlers: function() {
    if(ASPx.Browser.WebKitTouchUI) {
     ASPx.Evt.DetachEventFromElement(this.touchEventHandlersElement, "touchstart", this.onTouchStart, true);
     ASPx.Evt.DetachEventFromElement(this.touchEventHandlersElement, "touchend", this.onTouchEnd, true);
     ASPx.Evt.DetachEventFromElement(this.touchEventHandlersElement, "touchmove", this.onTouchMove, true);
    }
    ASPx.Evt.DetachEventFromElement(this.touchEventHandlersElement, "scroll", this.onScroll, true);
    ASPx.Evt.DetachEventFromElement(this.touchEventHandlersElement, "click", this.onClick, true);
   },
   updateInitData: function() {
    window.clearTimeout(this.inertialStopTimerId);
    this.initScrollLeft = this.element.scrollLeft;
    this.initScrollTop = this.element.scrollTop;
    this.scrollLeft = this.initScrollLeft;
    this.scrollTop = this.initScrollTop;
    this.initElementX = ASPx.GetAbsoluteX(this.element);
    this.initElementY = ASPx.GetAbsoluteY(this.element);
    this.scrollTime = new Date();
    this.vx = 0;
    this.vy = 0;
    this.vxs = [];
    this.vys = [];
   },
   ScrollingActive: function(e) {
    return (!e || !e.ASPxTouchUIScrollOff) && ASPx.TouchUIHelper.ScrollExtender.activeScrolling == this;
   },
   ReleaseScrolling: function() {
    if(this.ScrollingActive())
     ASPx.TouchUIHelper.ScrollExtender.activeScrolling = null;
   },
   HandlerDraggingActive: function(e) {
    return (!e || !e.ASPxTouchUIScrollOff) && ASPx.TouchUIHelper.ScrollExtender.activeHandlerDragging == this;
   },
   ReleaseHandlerDragging: function() {
    if(this.HandlerDraggingActive())
     ASPx.TouchUIHelper.ScrollExtender.activeHandlerDragging = null;
   },
   startHandleDrag: function(e, isVertical) {
    this.startScroll(e, { x: ASPx.Evt.GetEventX(e), y: ASPx.Evt.GetEventY(e) });
    this.isVerticalHandle = isVertical;
   },
   dragHandle: function(e) {
    var x = ASPx.Evt.GetEventX(e),
     y = ASPx.Evt.GetEventY(e),
     opts = this.options,
     el = this.element,
     vert = this.isVerticalHandle;
    var deltaY = y - this.initTouchY,
     deltaX = x - this.initTouchX;
    var applyScrollX = opts.showHorizontalScrollbar;
    var applyScrollY = opts.showVerticalScrollbar;
    if(applyScrollY && vert && this.vScrollHandleElement) {
     var vScrollHandler = this.calcScrollHandles(el.scrollHeight, el.clientHeight,
      opts.minScrollbarSize, 1, this.vEndMargin);
     var newY = this.initScrollTop + deltaY / vScrollHandler.pos;
     this.scrollTop = newY;
     el.scrollTop = newY;
    }
    if(applyScrollX && !vert && this.hScrollHandleElement) {
     var hScrollHandler = this.calcScrollHandles(el.scrollWidth, el.clientWidth,
      opts.minScrollbarSize, 1, this.hEndMargin);
     var newX = this.initScrollLeft + deltaX / hScrollHandler.pos;
     this.scrollLeft = newX;
     el.scrollLeft = newX;
    }
    this.updateScrollHandles();
   },
   stopHandleDrag: function() {
    this.isVerticalHandle = null;
   },
   startScroll: function(e, point) {
    this.initTouchX = point ? point.x : ASPx.TouchUIHelper.getEventX(e);
    this.initTouchY = point ? point.y : ASPx.TouchUIHelper.getEventY(e);
    this.lastTouchX = this.initTouchX;
    this.lastTouchY = this.initTouchY;
    this.updateInitData();
    this.updateScrollHandles();
    this.showScrollBars();
   },
   scroll: function(e) {
    var el = this.element;
    var opts = this.options;
    var currentTouchX = ASPx.TouchUIHelper.getEventX(e);
    var currentTouchY = ASPx.TouchUIHelper.getEventY(e);
    var newX = this.initScrollLeft + (this.initTouchX - currentTouchX);
    var newY = this.initScrollTop + (this.initTouchY - currentTouchY);
    var dt = (new Date() - this.scrollTime);
    if(dt < 1) dt = 1;
    var dx = this.lastTouchX - currentTouchX;
    var dy = this.lastTouchY - currentTouchY;
    this.lastTouchX = currentTouchX;
    this.lastTouchY = currentTouchY;
    this.vx = dx / dt;
    this.vy = dy / dt;
    this.vxs.push(this.vx);
    this.vys.push(this.vy);
    var applyScrollX = opts.showHorizontalScrollbar;
    var applyScrollY = opts.showVerticalScrollbar;
    var stuck = false;
    if(opts.scrollPageIfCannotScrollDiv) {
     var sensitivity = 5;
     var dxSignificant = Math.abs(dx) > sensitivity;
     var dySignificant = Math.abs(dy) > sensitivity;
     var xStuck = !applyScrollX;
     var yStuck = !applyScrollY;
     xStuck = xStuck || (this.scrollLeft == 0 && dx < 0);
     xStuck = xStuck || (this.scrollLeft == el.scrollWidth - el.clientWidth && dx > 0);
     xStuck = xStuck && dxSignificant && Math.abs(dx) > Math.abs(dy);
     yStuck = yStuck || (this.scrollTop == 0 && dy < 0);
     yStuck = yStuck || (this.scrollTop == el.scrollHeight - el.clientHeight && dy > 0);
     yStuck = yStuck && dySignificant && Math.abs(dy) > Math.abs(dx);
     stuck = xStuck || yStuck;
     applyScrollX = !stuck;
     applyScrollY = !stuck;
    }
    if(applyScrollX) {
     this.scrollLeft = newX;
     el.scrollLeft = newX;
    }
    if(applyScrollY) {
     this.scrollTop = newY;
     el.scrollTop = newY;
    }
    if(stuck) {
     this.scrollLeft = el.scrollLeft;
     this.scrollTop = el.scrollTop;
    }
    this.updateScrollHandles();
    this.scrollTime = new Date();
    var scrolled = applyScrollX || applyScrollY;
    return scrolled;
   },
   stopScroll: function() {
    var instance = this;
    var element = this.element;
    var acceleration = this.options.acceleration;
    var timeStep = this.options.timeStep;
    if(this.vxs && this.vxs.length === 0) return;
    if(this.vxs) {
     var countToSmooth = 3;
     var lenToSlice = Math.max(this.vxs.length - countToSmooth, 0);
     this.vxs = this.vxs.slice(lenToSlice);
     this.vys = this.vys.slice(lenToSlice);
     this.vx = Math.min.apply(null, this.vxs);
     if(this.vx < 0)
      this.vx = Math.max.apply(null, this.vxs);
     this.vy = Math.min.apply(null, this.vys);
     if(this.vy < 0)
      this.vy = Math.max.apply(null, this.vys);
     delete this.vxs;
     delete this.vys;
    }
    this.inertialStopTimerId = window.setTimeout(function() {
     instance.vx *= acceleration;
     instance.vy *= acceleration;
     if(Math.abs(instance.vx) < 0.1)
      instance.vx = 0;
     if(Math.abs(instance.vy) < 0.1)
      instance.vy = 0;
     if(instance.vx == 0 && instance.vy == 0) {
      instance.hideScrollBars();
      return;
     }
     var dx = Math.ceil(instance.vx * timeStep);
     var dy = Math.ceil(instance.vy * timeStep);
     if(instance.options.showHorizontalScrollbar) {
      instance.scrollLeft += dx;
      element.scrollLeft = instance.scrollLeft;
     }
     if(instance.options.showVerticalScrollbar) {
      instance.scrollTop += dy;
      element.scrollTop = instance.scrollTop;
     }
     if(element.scrollLeft + element.clientWidth >= element.scrollWidth || element.scrollLeft <= 0)
      instance.vx = 0;
     if(element.scrollTop + element.clientHeight >= element.scrollHeight || element.scrollTop <= 0)
      instance.vy = 0;
     instance.updateScrollHandles();
     instance.stopScroll();
    }, timeStep);
   },
   offset: function(deltaX, deltaY) {
    var el = this.element;
    var opts = this.options;
    var applyScrollX = opts.showHorizontalScrollbar;
    var applyScrollY = opts.showVerticalScrollbar;
    if(applyScrollX) {
     el.scrollLeft += deltaX;
     this.scrollLeft = el.scrollLeft;
    }
    if(applyScrollY) {
     el.scrollTop += deltaY;
     this.scrollTop = el.scrollTop;
    }
    this.updateScrollHandles();
   },
   updateScrollHandles: function() {
    if(this.hScrollHandleElement) {
     var scrollHandler = this.calcScrollHandles(this.element.scrollWidth, this.element.clientWidth,
      this.options.minScrollbarSize, this.element.scrollLeft, this.hEndMargin);
     this.hScrollHandleElement.style.width = scrollHandler.size + "px";
     ASPx.SetAbsoluteX(this.hScrollHandleElement, this.initElementX + scrollHandler.pos);
     ASPx.SetAbsoluteY(this.hScrollHandleElement, this.initElementY + this.element.clientHeight -
      this.hScrollHandleElement.offsetHeight);
    }
    if(this.vScrollHandleElement) {
     var scrollHandler = this.calcScrollHandles(this.element.scrollHeight, this.element.clientHeight,
      this.options.minScrollbarSize, this.element.scrollTop, this.vEndMargin);
     this.vScrollHandleElement.style.height = scrollHandler.size + "px";
     ASPx.SetAbsoluteX(this.vScrollHandleElement, this.initElementX + this.element.clientWidth - this.vScrollHandleElement.offsetWidth);
     ASPx.SetAbsoluteY(this.vScrollHandleElement, this.initElementY + scrollHandler.pos);
    }
   },
   calcScrollHandles: function(scrollSize, clientSize, scrollBarMinSize, scrollPos, endMargin) {
    var scrollBarMaxSize = clientSize - endMargin;
    var scrollBarSize = clientSize * clientSize / scrollSize;
    scrollBarSize = Math.min(scrollBarMaxSize, Math.max(scrollBarMinSize, scrollBarSize));
    var k = (scrollSize == clientSize) ? 0 :
     (clientSize - scrollBarSize - endMargin) / (scrollSize - clientSize);
    return { size: scrollBarSize, pos: scrollPos * k };
   },
   showScrollBars: function() {
    var needVScrollHandle = this.element.scrollHeight > this.element.clientHeight;
    var needHScrollHandle = this.element.scrollWidth > this.element.clientWidth;
    if(this.vScrollHandleElement && needVScrollHandle)
     this.vScrollHandleElement.className = this.options.vScrollClassNameShown;
    if(this.hScrollHandleElement && needHScrollHandle)
     this.hScrollHandleElement.className = this.options.hScrollClassNameShown;
    this.scrollBarsShown = needVScrollHandle || needHScrollHandle;
   },
   hideScrollBars: function() {
    if(this.vScrollHandleElement)
     this.vScrollHandleElement.className = this.options.vScrollClassName;
    if(this.hScrollHandleElement)
     this.hScrollHandleElement.className = this.options.hScrollClassName;
    this.scrollBarsShown = false;
   },
   MouseEventEmulationProtectHelper: {
    onTouchEnd: function(initTouchX, initTouchY, e) {
     var difX = initTouchX - ASPx.TouchUIHelper.getEventX(e);
     var difY = initTouchY - ASPx.TouchUIHelper.getEventY(e);
     if(Math.abs(difX) > ASPx.TouchUIHelper.clickSensetivity || Math.abs(difY) > ASPx.TouchUIHelper.clickSensetivity) {
      ASPx.TouchUIHelper.isMouseEventFromScrolling = true;
      window.setTimeout(function() { ASPx.TouchUIHelper.isMouseEventFromScrolling = false; }, 100);
     }
    },
    onClick: function() {
     if(ASPx.TouchUIHelper.isMouseEventFromScrolling) {
      window.setTimeout(function() { ASPx.TouchUIHelper.isMouseEventFromScrolling = false; }, 0);
     }
    }
   }
  };
  ASPx.TouchUIHelper.FastTapHelper = (function() {
   var actions = [];
   var DISTANCE_LIMIT = 10;
   var startX;
   var startY;
   var preventCommonClickEvents = false;
   var invokeActions = function(actions) {
    for(var i = 0; i < actions.length; i++)
     actions[i]();
   };
   var onTouchStart = function(e) {
    if(preventCommonClickEvents)
     e.stopPropagation();
    if(actions.length > 1)
     return;
    startX = e.touches[0].clientX;
    startY = e.touches[0].clientY;
    if(ASPx.Browser.AndroidDefaultBrowser)
     ASPx.Evt.AttachEventToElement(e.currentTarget, "click", onClick, true);
    else
     ASPx.Evt.AttachEventToElement(e.currentTarget, "touchend", onTouchEnd, true);
   };
   if(ASPx.Browser.AndroidDefaultBrowser) {
    var onClick = function(e) {
     invokeActions(actions);
     actions = [];
     ASPx.Evt.DetachEventFromElement(e.currentTarget, "click", onClick, true);
    };
   } else {
    var onTouchEnd = function(e) {
     if(preventCommonClickEvents)
      ASPx.Evt.PreventEventAndBubble(e);
     var stopX = e.changedTouches[0].clientX;
     var stopY = e.changedTouches[0].clientY;
     var distanceX = Math.abs(startX - stopX);
     var distanceY = Math.abs(startY - stopY);
     var allowClick = distanceX < DISTANCE_LIMIT && distanceY < DISTANCE_LIMIT;
     if(allowClick) {
      var actionsToInvoke = actions;
      setTimeout(function() { invokeActions(actionsToInvoke); }, 0);
     }
     actions = [];
     ASPx.Evt.DetachEventFromElement(e.currentTarget, "touchend", onTouchEnd, true);
    };
   }
   return {
    HandleFastTap: function(e, tapAction, preventClickEvents) {
     if(e.touches.length > 1)
      return;
     preventCommonClickEvents = preventClickEvents;
     actions.push(tapAction);
     onTouchStart(e);
    }
   };
  })();
  ASPx.TouchUIHelper.doubleTapEventName = "dxDoubleTap";
  ASPx.TouchUIHelper.allowDoubleTapProcessing = function(e) {
   var DOUBLE_TAP_DELAY = 600;
   var DISTANCE_LIMIT = 10;
   var currentTapTime = e.timeStamp;
   var currentX = e.changedTouches[0].clientX;
   var currentY = e.changedTouches[0].clientY;
   var lastTapTime = this["lastTap"] || currentTapTime;
   var lastX = this["lastX"] || currentX;
   var lastY = this["lastY"] || currentY;
   this["lastTap"] = currentTapTime;
   this["lastX"] = currentX;
   this["lastY"] = currentY;
   var delay = currentTapTime - lastTapTime;
   return delay && delay <= DOUBLE_TAP_DELAY && e.touches.length === 1 &&
    Math.abs(currentX - lastX) <= DISTANCE_LIMIT &&
    Math.abs(currentY - lastY) <= DISTANCE_LIMIT;
  };
  ASPx.TouchUIHelper.AttachDoubleTapEventToElement = function(element, action) {
   var onTouchEnd = function(e) {
    ASPx.Evt.DetachEventFromElement(e.currentTarget, "touchend", onTouchEnd, true);
    e[ASPx.TouchUIHelper.doubleTapEventName] = true;
    var startActionAfterFastTap = function() {
     window.setTimeout(function() { action(e); }, 0);
    };
    startActionAfterFastTap();
   };
   var onTouchStart = function(e) {
    if(ASPx.TouchUIHelper.allowDoubleTapProcessing(e)) {
     var preventZoom = function() { ASPx.Evt.PreventEvent(e); };
     preventZoom();
     ASPx.Evt.AttachEventToElement(e.currentTarget, "touchend", onTouchEnd, true);
    }
   };
   ASPx.Evt.AttachEventToElement(element, "touchstart", onTouchStart, true);
  };
  ASPx.TouchUIHelper.HasCustomizedNativeScrollBarClass = function(element) {
   return element && ASPx.ElementHasCssClass(element, SCROLLBAR_CLASSNAMES.CUSTOMIZED_NATIVE);
  };
  ASPx.TouchUIHelper.IsMultiTouchEvent = function(e) {
   return e.touches && e.touches.length > 1;
  };
  window.ASPxClientTouchUI = {};
  window.ASPxClientTouchUI.MakeScrollable = ASPx.TouchUIHelper.MakeScrollable;
  window.ASPxClientTouchUI.ScrollExtender = ASPx.TouchUIHelper.ScrollExtender;
 };
 ASPx.InitializeMobileScripts = InitializeMobileScripts;
 var isMacOSOrIPadSafari = ASPx.Browser.MacOSPlatform && !ASPx.Browser.MacOSMobilePlatform && ASPx.Browser.Safari && ASPx.Browser.MajorVersion >= 13; 
 if(!isMacOSOrIPadSafari) 
  InitializeMobileScripts();
})(ASPx || (ASPx = {}));

(function() {
var RelatedControlManager = {
 storage: { },
 GetRelatedCollection: function(masterName) {
  if(!this.storage[masterName])
   this.storage[masterName] = [ ];
  return this.storage[masterName];
 },
 RegisterRelatedControl: function(masterName, name) {
  this.GetRelatedCollection(masterName)[name] = name;
 },
 RegisterRelatedControls: function(masterName, names) {
  var relatedCollection = this.GetRelatedCollection(masterName);
  var name;
  for(var i = 0; i < names.length; i++) {
   name = names[i];
   relatedCollection[name] = name;
  }
 },
 GetLinkedControls: function(masterControl) {
  var result = [masterControl];
  var collection = this.GetRelatedCollection(masterControl.name); 
  for(var name in collection) {
   if(collection.hasOwnProperty(name)) {
    var control = ASPx.GetControlCollection().Get(name);
    if(control)
     result.push(control);
   }
  }
  return result;
 },
 coverCache: { },
 panelCache: { },
 timers: { },
 Shade: function(masterControl) {  
  this.ShadeCore(masterControl, true);
  this.timers[masterControl.name] = window.setTimeout(function() { ASPx.RelatedControlManager.ShadeTransition(masterControl.name); }, 750);
 },
 ShadeCore: function(masterControl, isTransparent) {
  if(!isTransparent) {
   this.panelCache[masterControl.name] = masterControl.ShowLoadingPanel();
  } 
  var controls = this.GetLinkedControls(masterControl);
  for(var i = 0; i < controls.length; i++) {
   var control = controls[i];
   var cover = control.CreateLoadingDiv(document.body, control.GetMainElement());
   if(ASPx.IsExistsElement(cover)) {
    if(isTransparent) {
     cover.className = "";
     cover.style.background = "white";         
     cover.style.opacity = "0.01";
    }
    this.coverCache[control.name] = cover;
   }
  }  
 },
 ShadeTransition: function(masterName) {
  var obj = ASPx.GetControlCollection().Get(masterName);
  if(obj) {
   this.Unshade(obj);
   this.ShadeCore(obj, false);
  }
 },
 Unshade: function(masterControl) {
  var masterName = masterControl.name;
  ASPx.Timer.ClearTimer(this.timers[masterName]);
  delete this.timers[masterName];
  var panel = this.panelCache[masterName];
  if(ASPx.IsExistsElement(panel))
   ASPx.RemoveElement(panel);
  delete this.panelCache[masterName];
  var controls = this.GetLinkedControls(masterControl);
  for(var i = 0; i < controls.length; i++) {
   var control = controls[i];
   var cover = this.coverCache[control.name];
   if(ASPx.IsExistsElement(cover))
    ASPx.RemoveElement(cover);    
   delete this.coverCache[control.name];
  }
 },
 CreateInfo: function() {
  return { 
   clientObjectName:   "",
   elementId:    "",
   innerHtml:    "",
   parameters:   ""
  }; 
 },
 ProcessInfo: function(info) {
  var control = ASPx.GetControlCollection().Get(info.clientObjectName);  
  if(!control || !ASPx.IsFunction(control.ProcessCallbackResult))
   this.ProcessCallbackResultDefault(info.elementId, info.innerHtml, info.parameters);
  else
   control.ProcessCallbackResult(info.elementId, info.innerHtml, info.parameters);
 },
 ProcessCallbackResultDefault: function(elementId, innerHtml, parameters) {
  var element = ASPx.GetElementById(elementId);
  if(ASPx.IsExistsElement(element))
   element.innerHTML = innerHtml;  
 },
 ParseResult: function(result) {
  if(!result)
   return;
  result.forEach(function(controlResult) {
   var info = this.CreateInfo();
   info.clientObjectName = controlResult[0];
   info.elementId = controlResult[1];
   info.innerHtml = controlResult[2];
   info.parameters = controlResult[3];
   this.ProcessInfo(info);
  }, this);
 }
};
ASPx.RelatedControlManager = RelatedControlManager;
})();

(function () {
 var ASPxClientHint = ASPx.CreateClass(ASPxClientControl, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
  },
  GetMainElement: function () {
   return null;
  }
 });
 ASPxClientHint.Update = function () {
  ASPxClientHint.Instances.each(function (instance) { instance.update(); });
 };
 ASPxClientHint.UpdatePosition = function (element) {
  if (element) {
   var wnd = ASPxClientHint.createdWindows.find(element);
   if (wnd)
    wnd.UpdatePosition();
  } else
   ASPxClientHint.createdWindows.each(function (wnd) { wnd.UpdatePosition(); });
 };
 ASPx.attachToReady(function () {
  window.setTimeout(function () {
   ASPxClientHint.Update();
  }, 0);
 });
 ASPxClientHint.TriggerHelper = (function () {
  var triggers = {
   none: {
    subscribeActivation: function () { },
    unsubscribeActivation: function () { },
    subscribeDeactivation: function () { },
   },
   hover: {
    activationEvent: "mouseover", 
    deactivationEvent: "mouseleave", 
    subscribeActivation: function (targetSelector, handler) {
     return ASPxClientHint.events.subscribe(targetSelector, this.activationEvent, handler);
    },
    unsubscribeActivation: function (targetElements, handler) {
     ASPxClientHint.events.unsubscribe(targetElements, this.activationEvent, handler);
    },
    subscribeDeactivation: function (targetElement, hintElement, handler) {
     var onMouseoutDeactivating = function (evt) {
      var relatedTargetElement = ASPx.Evt.GetEventRelatedTarget(evt, false);
      var mouseOutsToTarget = ASPxClientUtils.GetIsParent(targetElement, relatedTargetElement);
      var mouseOutsToHint = ASPxClientUtils.GetIsParent(hintElement, relatedTargetElement);
      if (!mouseOutsToTarget && !mouseOutsToHint) {
       ASPx.Evt.DetachEventFromElement(targetElement, this.deactivationEvent, onMouseoutDeactivating);
       handler();
      }
     }.aspxBind(this);
     ASPx.Evt.AttachEventToElement(targetElement, this.deactivationEvent, onMouseoutDeactivating);
     ASPx.Evt.AttachEventToElement(hintElement, this.deactivationEvent, onMouseoutDeactivating);
    },
   },
   click: {
    subscribeActivation: function (targetSelector, handler) {
     return ASPxClientHint.events.subscribe(targetSelector, "click", handler);
    },
    unsubscribeActivation: function (targetElements, handler) {
     ASPxClientHint.events.unsubscribe(targetElements, "click", handler);
    },
    subscribeDeactivation: function (targetElement, hintElement, handler) {
     var closeAction = "click";
     var reactivationAction = "click";
     var onHintClickReactivating = function () {
      ASPx.Evt.DetachEventFromElement(hintElement, reactivationAction, onHintClickReactivating);
      handler("reactivation");
     };
     var onDeactivating = function (evt) {
      var eventSourceElement = ASPx.Evt.GetEventSource(evt);
      var clickTarget = ASPxClientUtils.GetIsParent(targetElement, eventSourceElement);
      var clickHint = ASPxClientUtils.GetIsParent(hintElement, eventSourceElement);
      if (!clickTarget && !clickHint) {
       ASPx.Evt.DetachEventFromDocument(closeAction, onDeactivating);
       handler("deactivation");
       ASPx.Evt.AttachEventToElement(hintElement, reactivationAction, onHintClickReactivating);
      }
     };
     ASPx.Evt.AttachEventToDocument(closeAction, onDeactivating);
    },
   },
   focus: {
    subscribeActivation: function (targetSelector, handler) {
     return ASPxClientHint.events.subscribe(targetSelector, "focus", handler);
    },
    unsubscribeActivation: function (targetElement, handler) {
     ASPxClientHint.events.unsubscribe(targetElement, "focus", handler);
    },
    subscribeDeactivation: function (targetElement, hintElement, handler) {
     var closeAction = "blur";
     var onMouseoutDeactivating = function (evt) {
      var relatedTargetElement = ASPx.Evt.GetEventRelatedTarget(evt, false);
      var focusToTarget = ASPxClientUtils.GetIsParent(targetElement, relatedTargetElement);
      var focusToHint = ASPxClientUtils.GetIsParent(hintElement, relatedTargetElement);
      if (!focusToTarget && !focusToHint) {
       ASPx.Evt.DetachEventFromElement(targetElement, closeAction, onMouseoutDeactivating);
       handler();
      }
     };
     ASPx.Evt.AttachEventToElement(targetElement, closeAction, onMouseoutDeactivating);
    },
   },
  };
  var validTriggers = [];
  for (var trigger in triggers) {
   if (triggers.hasOwnProperty(trigger)) {
    validTriggers.push(trigger);
   }
  }
  var defaultTriggerAction = "hover focus";
  function validate(triggerString) {
   var trigger = triggerString.split(" ");
   for (var i = 0; i < trigger.length; i++) {
    if (trigger[i] && ASPx.Data.ArrayIndexOf(validTriggers, trigger[i]) == -1)
     ASPx.ShowErrorMessage("Property 'triggerAction' has an inappropriate value '" + trigger[i] + "'");
   }
  }
  function fixTriggerString(triggerString) {
   if(ASPxClientUtils.webKitTouchUI) {
    if(triggerString === "hover" || triggerString === "focus")
     return "click";
    var triggerStrings = triggerString.split(" ");
    for (var i = triggerStrings.length - 1; i >= 0 ; i--) {
     if(triggerStrings[i] === "hover" || triggerStrings[i] === "focus")
      triggerStrings.splice(i, 1);
    }
    if(triggerStrings.length === 0)
     return "click";
    return triggerStrings.join(" ");
   }
   return triggerString;
  }
  function subscribeActivation(triggerString, targetSelector, handler) {
   triggerString = fixTriggerString(triggerString);
   var targetElements;
   var trigger = triggerString.split(" ");
   for (var i = 0; i < trigger.length; i++)
    targetElements = triggers[trigger[i]].subscribeActivation(targetSelector, handler);
   return targetElements;
  }
  function unsubscribActivatione(triggerString, targetElements, handler) {
   triggerString = fixTriggerString(triggerString);
   var trigger = triggerString.split(" ");
   for (var i = 0; i < trigger.length; i++)
    triggers[trigger[i]].unsubscribeActivation(targetElements, handler);
  }
  function subscribeDeactivation(triggerString, targetElement, hintElement, handler) {
   triggerString = fixTriggerString(triggerString);
   var trigger = triggerString.split(" ");
   for (var i = 0; i < trigger.length; i++)
    triggers[trigger[i]].subscribeDeactivation(targetElement, hintElement, handler);
  }
  return {
   defaultTriggerAction: defaultTriggerAction,
   validate: validate,
   subscribeActivation: subscribeActivation,
   unsubscribActivatione: unsubscribActivatione,
   subscribeDeactivation: subscribeDeactivation,
  };
 })();
 ASPxClientHint.Instances = (function () {
  var all = {};
  function composeKey(targetSelector, triggerAction) {
   return targetSelector + "|" + triggerAction;
  }
  function add(targetSelector, triggerAction, instance, onExists) {
   var key = composeKey(targetSelector, triggerAction);
   var oldInstance = all[key];
   if (oldInstance) onExists(oldInstance);
   all[key] = instance;
  }
  function each(delegate) {
   for (var item in all) {
    if (all.hasOwnProperty(item)) {
     var stop = delegate(all[item]);
     if (stop) break;
    }
   }
  }
  return {
   add: add,
   each: each
  };
 })();
 ASPxClientHint.createdWindows = (function () {
  var all = [];
  function add(wnd) {
   var index = ASPxClientUtils.ArrayIndexOf(all, wnd);
   if (index == -1)
    all.push(wnd);
  }
  function remove(wnd) {
   ASPxClientUtils.ArrayRemove(all, wnd);
  }
  function each(delegate) {
   var fihished = false;
   for (var i = all.length - 1; i >= 0; i--) {
    fihished = delegate(all[i]);
    if (fihished)
     break;
   }
  }
  function findFirst(comparer) {
   var foundWnd = null;
   each(function (wnd) {
    if (comparer(wnd)) {
     foundWnd = wnd;
     return true;
    }
   }.aspxBind(this));
   return foundWnd;
  }
  function findByHintElement(hintElement) {
   return ASPxClientHint.createdWindows.findFirst(function (wnd) { return wnd.hintElement == hintElement; });
  }
  function findByTargetElement(targetElement) {
   return ASPxClientHint.createdWindows.findFirst(function (wnd) { return wnd.targetElement == targetElement; });
  }
  function find(element) {
   var wnd = findByHintElement(element);
   if (!wnd)
    wnd = findByTargetElement(element);
   return wnd;
  }
  return {
   add: add,
   remove: remove,
   each: each,
   find: find,
   findFirst: findFirst,
   findByTargetElement: findByTargetElement,
   findByHintElement: findByHintElement,
  };
 })();
 ASPxClientHint.errorMessages = {
  selectorArgumentRequired: "ASPxHint: The first Register's method argument (selector) is required"
 };
 ASPxClientHint.showErrorMessage = function (errorMessage) {
  ASPx.ShowErrorMessage(errorMessage);
  throw new Error(errorMessage);
 };
 ASPxClientHint.Register = function (targetSelector, options) {
  var oldInstanceDetachDelegate = function (oldInstance) { oldInstance.detach(); };
  var instance = new ASPxClientHint.Instance(targetSelector, options);
  if(targetSelector) {
   ASPxClientHint.Instances.add(
    targetSelector,
    instance.options.triggerAction,
    instance,
    oldInstanceDetachDelegate
   );
  }
  return instance;
 };
 ASPxClientHint.Show = function () {
  var hasNoTargetSelector = arguments.length == 1;
  var hasTargetSelectorAndOptions = arguments.length == 2;
  var targetSelector, options, targetElement;
  if (hasNoTargetSelector) {
   targetSelector = "body";
   options = arguments[0];
   targetElement = document.body;
  } else if (hasTargetSelectorAndOptions) {
   if (typeof arguments[0] === "string") {
    targetSelector = arguments[0];
    targetElement = document.querySelectorAll(targetSelector)[0];
   } else {
    targetSelector = "";
    targetElement = arguments[0];
   }
   options = arguments[1];
  } else
   return;
  if (typeof options === "string") options = { content: options };
  options = ASPxClientHint.OptionsParser.patchOptionsForShow(hasNoTargetSelector, options);
  var instance = new ASPxClientHint.Instance(targetSelector, options);
  instance.Show(targetElement);
  return instance;
 };
 ASPxClientHint.Hide = function (target, immediately) {
  if (typeof target === "string") {
   var targetSelector = target;
   var targetElements = document.querySelectorAll(targetSelector);
   for (var i = 0, length = targetElements.length; i < length; i++) {
    ASPxClientHint.hideByTargetElement(targetElements[i], immediately);
   }
  } else {
   var targetElements = target;
   var wasHidden = ASPxClientHint.hideByTargetElement(targetElements, immediately);
   if (!wasHidden) {
    var hintElement = targetElements;
    ASPxClientHint.HideByHintElement(hintElement, immediately);
   }
  }
 };
 ASPxClientHint.hideByTargetElement = function (targetElement, immediately) {
  var wasHidden = false;
  ASPxClientHint.createdWindows.each(function (wnd) {
   if (wnd.targetElement === targetElement) {
    ASPxClientHint.HideByWnd(wnd, immediately);
    wasHidden = true;
   }
  });
  return wasHidden;
 };
 ASPxClientHint.hideByTargetsContainerElement = function(containerElement, immediately) {
  var wasHidden = false;
  ASPxClientHint.createdWindows.each(function(wnd) {
   if(containerElement.contains(wnd.targetElement)) {
    ASPxClientHint.HideByWnd(wnd, immediately);
    wasHidden = true;
   }
  });
  return wasHidden;
 };
 ASPxClientHint.HideByHintElement = function (hintElement, immediately) {
  ASPxClientHint.createdWindows.each(function (wnd) {
   if (wnd.hintElement === hintElement) {
    ASPxClientHint.HideByWnd(wnd, immediately);
    return true;
   }
  });
 };
 ASPxClientHint.HideAll = function (immediately) {
  ASPxClientHint.createdWindows.each(function (wnd) { ASPxClientHint.HideByWnd(wnd, immediately); });
 };
 ASPxClientHint.HideByWnd = function (wnd, immediately) {
  if (wnd) {
   if (immediately)
    wnd.hideCore();
   else
    wnd.hide(true);
  }
 };
 ASPxClientHint.Instance = function (targetSelector, options) {
  var legalTargetSelector = typeof targetSelector === "string";
  if (!legalTargetSelector) {
   ASPxClientHint.showErrorMessage(ASPxClientHint.errorMessages.selectorArgumentRequired);
   return null;
  }
  this.targetSelector = targetSelector;
  this.options = ASPxClientHint.OptionsParser.parse(options);
  if(this.options.hideNativeTooltipForNestedTitleAttributes) {
   var children = document.querySelectorAll(targetSelector + " [title]");
   for (var key in children) {
    if (children.hasOwnProperty(key)) {
      ASPxClientHint.AttributeHelper.getRelocateTitleAttribute(children[key]);
    }
   }
  }
  var notEmptyTargetSelector = legalTargetSelector && targetSelector !== "";
  if(notEmptyTargetSelector)
   this.attach();
 };
 ASPxClientHint.Instance.prototype = {
  Show: function (targetElement) {
   var viaAPI = true;
   if (typeof targetElement === "string")
    targetElement = document.querySelector(targetElement);
   if(!targetElement && this.targetSelector)
    targetElement = document.querySelector(this.targetSelector);
   if(!targetElement)
    targetElement = document.body;
   return this.showAtElement(targetElement, viaAPI);
  },
  showAtElement: function (targetElement, viaAPI) {
   var wnd = this.startShowing(targetElement, viaAPI);
   if (wnd)
    this.completeShowing(wnd);
   return wnd;
  },
  attach: function () {
   this.onActivatingHandler = this.onActivatingHandler || function (evt) { this.activating(evt); }.aspxBind(this);
   this.targetElements = ASPxClientHint.TriggerHelper.subscribeActivation(this.options.triggerAction, this.targetSelector, this.onActivatingHandler);
  },
  detach: function () {
   ASPxClientHint.TriggerHelper.unsubscribActivatione(this.options.triggerAction, this.targetElements, this.onActivatingHandler);
  },
  update: function () {
   this.detach();
   this.attach();
  },
  getTargetElementFromEvent: function (evt) {
   if (!ASPx.IsExists(evt)) return null;
   return evt.currentTarget ?
    evt.currentTarget :
    evt.srcElement ?
     evt.srcElement :
     evt.target;
  },
  activating: function (evt) {
   var targetElement = this.getTargetElementFromEvent(evt);
   this.activatingAtElement(targetElement, evt);
  },
  activatingAtElement: function (targetElement, evt) {
   var wnd = ASPxClientHint.createdWindows.findByTargetElement(targetElement);
   var wndAlreadyCreated = wnd && wnd.getStatus() >= ASPxClientHintWindow.Statuses.created;
   if (wndAlreadyCreated){
    var T568873 = ASPx.Browser.Edge && evt.buttons === 1;
    if(!T568873)
     this.reactivation(wnd);
   }
   if (!wndAlreadyCreated)
    wnd = this.startShowing(targetElement);
   if (this.options.appearAfter > 0) {
    window.setTimeout(function () {
     this.completeActivation(wnd);
    }.aspxBind(this), this.options.appearAfter);
   } else
    this.completeActivation(wnd);
   return wnd;
  },
  completeActivation: function (wnd) {
   if (wnd && wnd.getStatus() === ASPxClientHintWindow.Statuses.created)
    this.completeShowing(wnd);
  },
  reactivation: function (wnd) {
   if (wnd && wnd.disappearAfterTimerIsActive()) {
    wnd.stopDisappearTimer();
    this.subscribeDeactivation(wnd); 
   }
  },
  startShowing: function (targetElement, viaAPI) {
   var contentHtmlContainer = this.getContentHtml(targetElement);
   if (!contentHtmlContainer.valid)
    return;
   var contentHtml = contentHtmlContainer.content;
   var titleHtml = this.getTitleHtml(targetElement);
   var hasNoContent = !contentHtml && !titleHtml && !this.options.onShowing;
   if (hasNoContent && !viaAPI)
    return;
   var wnd = new ASPxClientHintWindow(targetElement, this.options);
   wnd.getCreateRender(
    contentHtml,
    titleHtml
   );
   this.subscribeDeactivation(wnd);
   wnd.setStatus(ASPxClientHintWindow.Statuses.created);
   return wnd;
  },
  completeShowing: function (wnd) {
   var statusBeforeEvent =  wnd.getStatus();
   var customContent = this.raiseOnShowing(wnd, wnd.targetElement, wnd.hintElement, wnd.getContentElement(), wnd.getTitleElement());
   this.processCustomContent(customContent, wnd);
   var statusAfterEvent =  wnd.getStatus();
   if(statusAfterEvent < statusBeforeEvent) return;
   wnd.show();
   wnd.setStatus(ASPxClientHintWindow.Statuses.activated);
   var completeShown = function () {
    wnd.setStatus(ASPxClientHintWindow.Statuses.shown);
    if (this.options.autoDisappearAfter > 0)
     setTimeout(function () { wnd.hide(); }, this.options.autoDisappearAfter);
   }.aspxBind(this);
   if (ASPxClientHint.OptionsParser.getShowAnimationEnabled(this.options)) {
    var duration = ASPxClientHint.OptionsParser.getShowAnimationDuration(this.options);
    ASPx.AnimationHelper.fadeIn(
     wnd.hintElement,
     completeShown,
     duration);
   } else
    completeShown();
  },
  raiseOnShowing: function (wnd, targetElement, hintElement, contentElement, titleElement) {
   var customContent;
   var cancel = false;
   if (this.options.onShowing) {
    var args = new ASPxClientHintShowingEventArgs(targetElement, hintElement, contentElement, titleElement, false);
    customContent = this.options.onShowing(wnd, args);
    cancel = args.cancel;
   }
   if(cancel)
    ASPxClientHint.Hide(targetElement);
   return customContent;
  },
  processCustomContent: function (customContent, wnd) {
   wnd.beforeHtmlSet();
   if (typeof customContent === "string") {
    wnd.setContent(customContent);
   } else if (typeof customContent === "object") {
    if (typeof customContent.title === "string")
     wnd.setTitle(customContent.title);
    if (typeof customContent.content === "string")
     wnd.setContent(customContent.content);
   }
   wnd.afterHtmlSet();
  },
  subscribeDeactivation: function (wnd) {
   ASPxClientHint.TriggerHelper.subscribeDeactivation(
    this.options.triggerAction,
    wnd.targetElement,
    wnd.hintElement,
    function (message) {
     if (message === "reactivation")
      this.reactivation(wnd);
     else 
      wnd.deactivating();
    }.aspxBind(this)
   );
  },
  getContentHtml: function (targetElement) {
   var contentContainer = {
    content: "",
    valid: true
   };
   if (this.options.content) {
    contentContainer.content = this.options.content;
    contentContainer.valid = true;
   } else if (this.options.contentAttribute) {
    contentContainer.content = ASPxClientHint.AttributeHelper.getAttributeValue(targetElement, this.options.contentAttribute);
    contentContainer.valid = contentContainer.content !== null;
   } else {
    var titleValue = ASPxClientHint.AttributeHelper.getAttributeValue(targetElement, "title");
    if (titleValue !== null) {
     contentContainer.content = titleValue;
     contentContainer.valid = true;
    }
   }
   return contentContainer;
  },
  getTitleHtml: function (targetElement) {
   if (this.options.title)
    return this.options.title;
   if (this.options.titleAttribute)
    return targetElement.getAttribute(this.options.titleAttribute);
   return "";
  },
 };
 var ASPxClientHintWindow = function (targetElement, options) {
  this.targetElement = targetElement;
  this.options = options;
  this.hintElement = null;
 };
 ASPxClientHintWindow.prototype = {
  hintElement: null,
  UpdatePosition: function () {
   var targetElementWasDeleted = this.targetElement && !ASPx.IsExistsElement(this.targetElement);
   if(targetElementWasDeleted)
    this.hide(true);
   else
    ASPxClientHint.RenderHelper.updatePosition(this.targetElement, this.hintElement, this.options);
  },
  getCreateRender: function (contentHtml, titleHtml) {
   this.hintElement = ASPxClientHint.RenderHelper.create(this.targetElement, contentHtml, titleHtml, this.options);
  },
  getContentElement: function () {
   return ASPxClientHint.RenderHelper.getContentElement(this.hintElement, this.options.classNames);
  },
  getTitleElement: function () {
   return ASPxClientHint.RenderHelper.getTitleElement(this.hintElement, this.options.classNames);
  },
  setContent: function (contentHTML) {
   var contentElement = this.getContentElement();
   if(!contentElement) return;
   contentElement.innerHTML = contentHTML;
   this.setHTMLChanged();
  },
  setTitle: function (titleHTML) {
   var titleElement = this.getTitleElement();
   if(!titleElement) return;
   titleElement.innerHTML = titleHTML;
   this.setHTMLChanged();
  },
  setHtml: function (html) {
   if(!this.hintElement) return;
   this.hintElement.innerHTML = html;
   this.setHTMLChanged();
  },
  SetContent: function (html, options) {
   this.setContent(html);
   this.onHtmlSetted(options);
  },
  SetTitle: function (html, options) {
   this.setTitle(html);
   this.onHtmlSetted(options);
  },
  SetHTML: function (html, options) {
   this.setHtml(html);
   this.onHtmlSetted(options);
  },
  setHTMLChanged: function() {
   this.htmlChanged = true;
  },
  beforeHtmlSet: function() {
   this.htmlChanged = false;
  },
  afterHtmlSet: function() {
   if(this.htmlChanged === true) {
    this.onHtmlSetted();
    this.htmlChanged = false;
   }
  },
  onHtmlSetted: function(options) {
   if(!this.hintElement) return;
   if(this.options.autoProcessScriptsAndLinks || ( options && options.autoProcessScriptsAndLinks))
    ASPx.ProcessScriptsAndLinks(); 
   if(this.options.autoUpdatePosition || ( options && options.autoUpdatePosition)) {
    this.UpdatePosition();
   }
  },
  SetContentLoading:function() {
   var contentElement = this.getContentElement();
   this.createLoadingPanel(contentElement);
  },
  SetTitleLoading:function() {
   var titleElement = this.getTitleElement();
   this.createLoadingPanel(titleElement);
  },
  createLoadingPanel: function(parent) {
   parent.innerHTML = "";
   ASPxClientHint.RenderHelper.createLoadingPanel(parent, this.options);
  },
  show: function () {
   ASPxClientHint.RenderHelper.show(this.targetElement, this.hintElement, this.options);
  },
  hideCore: function () {
   var cancel = false;
   var onShowingHasBeenCalled = this.getStatus() >= ASPxClientHintWindow.Statuses.activated;
   if (this.options.onHiding && onShowingHasBeenCalled) {
    var args = new ASPxClientHintHidingEventArgs(this.targetElement, this.hintElement, this.getContentElement(), this.getTitleElement(), cancel);
    this.options.onHiding(this, args);
    cancel = args.cancel;
   }
   if (!cancel)
    this.dismiss();
  },
  hide: function (viaAPI) {
   var notVisibleYet = this.getStatus() <= ASPxClientHintWindow.Statuses.created;
   if(notVisibleYet)
    this.hideCore();
   this.deactivating(viaAPI);
  },
  deactivating: function (viaAPI) {
   if (!this || this.getStatus() < ASPxClientHintWindow.Statuses.created) return;
   if (!viaAPI && this.options.disappearAfter > 0) {
    this.setDisappearTimer(function () {
     this.completeDeactivating();
    }.aspxBind(this), this.options.disappearAfter);
   } else
    this.completeDeactivating();
  },
  completeDeactivating: function () {
   if (ASPxClientHint.OptionsParser.getHideAnimationEnabled(this.options)) {
    var duration = ASPxClientHint.OptionsParser.getHideAnimationDuration(this.options);
    if (this.hintElement) { 
     ASPx.AnimationHelper.fadeOut(this.hintElement, function () {
      this.hideCore();
     }.aspxBind(this), duration);
    }
   } else
    this.hideCore();
  },
  dismiss: function () {
   this.setStatus(ASPxClientHintWindow.Statuses.destroyed);
   if (this.hintElement !== null) {
    this.hintElement.parentNode.removeChild(this.hintElement);
    this.hintElement = null;
   }
  },
  status: 0,
  setStatus: function (status) {
   if (status === ASPxClientHintWindow.Statuses.created)
    ASPxClientHint.createdWindows.add(this);
   if (status === ASPxClientHintWindow.Statuses.destroyed)
    ASPxClientHint.createdWindows.remove(this);
   this.status = status;
  },
  getStatus: function () {
   return this.status;
  },
  disappearAfterTimerId: -1,
  disappearAfterTimerIsActive: function() {
   return this.disappearAfterTimerId >= 0;
  },
  setDisappearTimer: function (handler, disappearAfter) {
   this.disappearAfterTimerId = window.setTimeout(handler, disappearAfter);
  },
  stopDisappearTimer: function () {
   window.clearTimeout(this.disappearAfterTimerId);
   this.disappearAfterTimerId = -1;
  }
 };
 ASPxClientHintWindow.Statuses = {
  destroyed: -1,
  created: 1,
  activated: 2,
  shown: 3,
 };
 ASPxClientHint.RenderHelper = (function () {
  var CSS_PREFIX = "dxh-";
  function findBestParentToNest(targetElement, options) {
   if (typeof options.container === "string")
    return document.querySelectorAll(options.container)[0];
   else if (typeof options.container === "object")
    return options.container;
   return findBestParentToNestCore(targetElement, options);
  }
  function findBestParentToNestCore(element, options) {
   var renderToBody = !options.renderToTargetParent;
   if (renderToBody)
    return getFormOrBody();
   if (element.tagName == "TR" || element.tagName == "TD" || element.tagName == "TBODY")
    return element.offsetParent.parentNode;
   if (element.tagName == "BODY")
    return getFormOrBody();
   return element.parentNode;
  }
  function getFormOrBody() {
   var form = document.querySelectorAll("FORM")[0];
   return form && ASPx.IsElementVisible(form) ? form : document.body;
  }
  function getPositionClassName(position) {
   return CSS_PREFIX + position.toLowerCase();
  }
  function ensureCalloutPosition(mainElement, prevPosition, currentPosition) {
   var prevClassName = getPositionClassName(prevPosition);
   var currentClassName = getPositionClassName(currentPosition);
   ASPx.RemoveClassNameFromElement(mainElement, prevClassName);
   ASPx.AddClassNameToElement(mainElement, currentClassName);
  }
  function isPositionHorizontal(position) { 
   return position == "left" || position == "right";
  }
  function ensureCalloutShift(mainElement, options, shift) {
   var calloutElement = ASPxClientHint.RenderHelper.getCalloutElement(mainElement, options.classNames);
   if (!calloutElement) return;
   var isX = !isPositionHorizontal(options.position);
   var hintSize = isX ? mainElement.offsetWidth : mainElement.offsetHeight;
   var shiftSize = isX ? shift.x : shift.y;
   var calloutPos = hintSize / 2 - shiftSize;
   calloutPos = LimitCalloutPos(calloutPos, hintSize);
   var propName = isX ? "left" : "top";
   calloutElement.style[propName] = calloutPos;
  }
  function LimitCalloutPos(calloutPos, hintSize) {
   var padding = 15;
   var limits = { min: padding, max: hintSize - padding };
   var outsideMin = calloutPos < limits.min;
   var outsideMax = calloutPos > limits.max;
   if (outsideMax) calloutPos = limits.max;
   if (outsideMin) calloutPos = limits.min;
   calloutPos += "px";
   if (outsideMin && outsideMax) calloutPos = "50%";
   return calloutPos;
  }
  function getMainElementClasses(options) {
   var theme = options.theme || window['_aspxHintTheme'];
   if(theme == 'Default')
    theme = '';
   return getMainElementClassName(options.classNames.mainElementClassName, theme) + " " + options.classNames.sysClassName + " " + options.className + " " + getPositionClassName(options.position);
  }
  function getMainElementClassName(className, postfix) {
   if(className !== ASPxClientHint.OptionsParser.dxHintClassNames.mainElementClassName)
    return className;
   else
    return postfix ? className + "_" + postfix : className;
  }
  function createLoadingPanel(parent, options) {
   var loadingElement = document.createElement("DIV");
   loadingElement.className = "dxh-loading"; 
   parent.appendChild(loadingElement);
   return loadingElement;
  }
  function create(targetElement, content, title, options) {
   var parent = findBestParentToNest(targetElement, options);
   var mainElement = document.createElement("DIV");
   mainElement.className = getMainElementClasses(options);
   parent.appendChild(mainElement);
   var calloutElement;
   if (options.showCallout) {
    calloutElement = document.createElement("DIV");
    calloutElement.className = options.classNames.calloutElementClassName;
    mainElement.appendChild(calloutElement);
   }
   if (title || options.showTitle === true) {
    var titleElement = document.createElement("DIV");
    titleElement.className = options.classNames.titleElementClassName;
    titleElement.innerHTML = title;
    mainElement.appendChild(titleElement);
   }
   var contentElement = document.createElement("DIV");
   contentElement.className = options.classNames.contentElementClassName;
   contentElement.innerHTML = content;
   mainElement.appendChild(contentElement);
   setSize(mainElement, options);
   return mainElement;
  }
  function getContentElement(mainElement, classNames) {
   return mainElement ? mainElement.getElementsByClassName(classNames.contentElementClassName)[0] : null;
  }
  function getTitleElement(mainElement, classNames) {
   return mainElement ? mainElement.getElementsByClassName(classNames.titleElementClassName)[0] : null;
  }
  function getCalloutElement(mainElement, classNames) {
   return mainElement ? mainElement.getElementsByClassName(classNames.calloutElementClassName)[0] : null;
  }
  function show(targetElement, hintElement, options) {
   hintElement.style.visibility = "hidden";
   hintElement.style.display = "block";
   togglePositionInCaseOfUndefinedHintSizes(targetElement, hintElement);
   updatePosition(targetElement, hintElement, options);
   hintElement.style.visibility = "";
  }
  function togglePositionInCaseOfUndefinedHintSizes(targetElement, hintElement) {
   var x = ASPx.GetAbsoluteX(targetElement);
   var y = ASPx.GetAbsoluteY(targetElement);
   ASPx.SetAbsoluteX(hintElement, x);
   ASPx.SetAbsoluteY(hintElement, y);
  }
  function updatePosition(targetElement, mainElement, options) {
   var maxSteps = 10;
   var hintChangesSizeDueMoving = false;
   do {
    var mainElementSize = { w: mainElement.offsetWidth, h: mainElement.offsetHeight };
    updatePositionStep(targetElement, mainElement, options);
    hintChangesSizeDueMoving = mainElementSize.w != mainElement.offsetWidth || mainElementSize.h != mainElement.offsetHeight;
    maxSteps --;
   } while (hintChangesSizeDueMoving && maxSteps > 0 );
  }
  function updatePositionStep(targetElement, mainElement, options) {
   var changes = ASPxClientHint.PositionHelper.set(targetElement, mainElement, options);
   ensureCalloutPosition(mainElement, options.position, changes.flipPosition);
   ensureCalloutShift(mainElement, options, changes.shift);
  }
  function setSize(mainElement, options) {
   mainElement.style.width = options.width;
   mainElement.style.height = options.height;
  }
  return {
   create: create,
   getContentElement: getContentElement,
   getTitleElement: getTitleElement,
   getCalloutElement: getCalloutElement,
   show: show,
   updatePosition: updatePosition,
   createLoadingPanel:createLoadingPanel,
  };
 })();
 var ASPxClientHintShowingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function (targetElement, hintElement, contentElement, titleElement, cancel) {
   this.constructor.prototype.constructor.call(this);
   this.targetElement = targetElement;
   this.hintElement = hintElement;
   this.contentElement = contentElement;
   this.titleElement = titleElement;
   this.cancel = cancel;
  }
 });
 var ASPxClientHintHidingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function (targetElement, hintElement, contentElement, titleElement, cancel) {
   this.constructor.prototype.constructor.call(this);
   this.targetElement = targetElement;
   this.hintElement = hintElement;
   this.contentElement = contentElement;
   this.titleElement = titleElement;
   this.cancel = cancel;
  }
 });
 ASPxClientHint.OptionsParser = (function () {
  var dxHintClassNames = {
   mainElementClassName: "dxhControl",
   sysClassName: "dxhSys",
   contentElementClassName: "dxh-content",
   calloutElementClassName: "dxh-callout",
   titleElementClassName: "dxh-title",
  };
  var defaults = {
   triggerAction: ASPxClientHint.TriggerHelper.defaultTriggerAction,
   appearAfter: 100,
   disappearAfter: 100,
   autoDisappearAfter: 0,
   showCallout: true,
   position: "top", 
   className: "",
   classNames: dxHintClassNames,
   allowFlip: true,
   allowShift: true,
   animation: {
    show: {},
    hide: {}
   },
   offset: 4,
   autoProcessScriptsAndLinks: false,
   autoUpdatePosition: false,
   hideNativeTooltipForNestedTitleAttributes: false,
  };
  var defaultsByAPI = {
   triggerAction: "none",
  };
  var defaultsByAPIWithNoSelector = {
   showCallout: false
  };
  function ensureDefaults(options) {
   return ensureDefaultsCore(options, defaults);
  }
  function patchOptionsForShow(hasSelector, options) {
   options = cloneOptionsObject(options);
   if(options)
    delete options.triggerAction;
   options = ensureDefaultsCore(options, defaultsByAPI);
   if (hasSelector)
    options = ensureDefaultsCore(options, defaultsByAPIWithNoSelector);
   return options;
  }
  function ensureDefaultsCore(options, defaultOptions) {
   for (var defaultProperty in defaultOptions) {
    if (defaultOptions.hasOwnProperty(defaultProperty)) {
     if (typeof options[defaultProperty] === "undefined")
      options[defaultProperty] = defaultOptions[defaultProperty];
    }
   }
   return options;
  }
  function validate(options) {
   ASPxClientHint.TriggerHelper.validate(options.triggerAction);
   options.position = options.position.toLowerCase();
  }
  function parseUsersArgument(options) {
   if (typeof options === "undefined")
    options = { contentAttribute: "title" };
   else if (typeof options === "string")
    options = { contentAttribute: options };
   else if (typeof options === "function")
    options = { onShowing: options };
   return options;
  }
  function cloneOptionsObject(options) {
   if (!options) return options;
   if (typeof options === "function") return options;
   if (typeof options === "string") return options;
   var clone = {};
   for (var key in options) {
    if (Object.prototype.hasOwnProperty.call(options, key)) {
     clone[key] = options[key];
    }
   }
   return clone;
  }
  function parse(options) {
   var optionsClone = cloneOptionsObject(options);
   optionsClone = parseUsersArgument(optionsClone);
   optionsClone = ensureDefaults(optionsClone);
   validate(optionsClone);
   return optionsClone;
  }
  var defultShowDuration = 200;
  var defultHideDuration = 100;
  function getShowAnimationEnabled(options) {
   return getShowAnimationEnabledCore(options) && getShowAnimationDuration(options) > 0;
  }
  function getShowAnimationEnabledCore(options) {
   if (options.animation === true) return true;
   if (options.animation === false) return false;
   if (options.animation) return !!options.animation.show;
  }
  function getHideAnimationEnabled(options) {
   return getHideAnimationEnabledCore(options) && getHideAnimationDuration(options) > 0;
  }
  function getHideAnimationEnabledCore(options) {
   if (options.animation === true) return true;
   if (options.animation === false) return false;
   if (options.animation && options.animation.hide === true) return true;
   if (options.animation) return !!options.animation.hide;
  }
  function getShowAnimationDuration(options) {
   if (!getShowAnimationEnabledCore(options)) return 0;
   return options.animation && options.animation.show && options.animation.show.duration >= 0 ?
    options.animation.show.duration :
    defultShowDuration;
  }
  function getHideAnimationDuration(options) {
   if (!getHideAnimationEnabledCore(options)) return 0;
   return options.animation && options.animation.hide && options.animation.hide.duration >= 0 ?
    options.animation.hide.duration :
    defultHideDuration;
  }
  return {
   dxHintClassNames:dxHintClassNames,
   parse: parse,
   patchOptionsForShow: patchOptionsForShow,
   getShowAnimationEnabled: getShowAnimationEnabled,
   getHideAnimationEnabled: getHideAnimationEnabled,
   getShowAnimationDuration: getShowAnimationDuration,
   getHideAnimationDuration: getHideAnimationDuration,
   defaults: defaults,
   ensureDefaults: ensureDefaults
  };
 })();
 ASPxClientHint.events = (function () {
  function subscribe(targetSelector, eventName, handler) {
   var targetElements = document.querySelectorAll(targetSelector);
   for (var i = 0; i < targetElements.length; i++) {
    ASPx.Evt.AttachEventToElement(targetElements[i], eventName, handler);
   }
   return targetElements;
  }
  function unsubscribe(targetElements, eventName, handler) {
   for (var i = 0; i < targetElements.length; i++) {
    ASPx.Evt.DetachEventFromElement(targetElements[i], eventName, handler);
   }
  }
  return {
   subscribe: subscribe,
   unsubscribe: unsubscribe,
  };
 })();
 function PositionCalcContext(targetElement, hintElement, options) {
  this.targetElement = targetElement;
  this.hintElement = hintElement;
  this.options = options;
  this.position = options.position;
  this.calloutSize = { width: 0, height: 0 };
  var calloutElement = ASPxClientHint.RenderHelper.getCalloutElement(hintElement, options.classNames);
  if (calloutElement) {
   this.calloutSize.width = calloutElement.offsetWidth;
   this.calloutSize.height = calloutElement.offsetHeight;
  }
  this.horizontal = new SizeContent(targetElement, hintElement, options, this.calloutSize, true);
  this.vertical = new SizeContent(targetElement, hintElement, options, this.calloutSize, false);
  function SizeContent(targetElement, hintElement, options, calloutSize, isX) {
   this.location = 0;
   this.screen = { min: 0, max: 0 };
   this.screen.min = isX ? ASPx.GetDocumentScrollLeft() : ASPx.GetDocumentScrollTop();
   var viewPortWidth = ASPx.Browser.WebKitTouchUI ? window.innerWidth : ASPx.GetDocumentClientWidth();
   this.screen.max = this.screen.min + (isX ? viewPortWidth : ASPx.GetDocumentClientHeight());
   this.target = { min: 0, max: 0 };
   this.target.min = isX ? ASPx.GetAbsoluteX(targetElement) : ASPx.GetAbsoluteY(targetElement);
   if(targetElement instanceof SVGElement) {
    var bBox = targetElement.getBBox();
    this.target.max = this.target.min + (isX ? bBox.width : bBox.height);
   }
   else
    this.target.max = this.target.min + (isX ? targetElement.offsetWidth : targetElement.offsetHeight);
   this.hintSize = isX ? hintElement.offsetWidth : hintElement.offsetHeight;
  }
 }
 var PositionHelper = (function () {
  function calcPosition(targetElement, hintElement, options) {
   var context = new PositionCalcContext(targetElement, hintElement, options);
   var positionOrientation = getPositionOrienation(context.position);
   if (options.allowFlip) {
    if (positionOrientation.horizontal)
     context.position = ASPxClientHint.FlipPositionToClientScreenHelper.flipPositionIfRequired(context.horizontal, context.position);
    else if (positionOrientation.vertical)
     context.position = ASPxClientHint.FlipPositionToClientScreenHelper.flipPositionIfRequired(context.vertical, context.position);
   }
   var offsets = getNotShiftedOffset(context);
   var minTargetMargin = 0;
   var shift = {
    x: 0,
    y: 0
   };
   if (options.allowShift) {
    shift.x = ASPxClientHint.ShiftPositionToClientScreenHelper.getShift(context.horizontal, positionOrientation, offsets.x, minTargetMargin, true);
    shift.y = ASPxClientHint.ShiftPositionToClientScreenHelper.getShift(context.vertical, positionOrientation, offsets.y, minTargetMargin, false);
   }
   return {
    location: {
     x: offsets.x + shift.x,
     y: offsets.y + shift.y
    },
    shift: shift,
    flipPosition: context.position
   };
  }
  function getPositionOrienation(position) {
   var vertical = position == "bottom" || position == "top";
   var horizontal = position == "right" || position == "left";
   return {
    vertical: vertical,
    horizontal: horizontal
   };
  }
  function getNotShiftedOffset(context) {
   var targetSize = {
    width: context.horizontal.target.max - context.horizontal.target.min,
    height: context.vertical.target.max - context.vertical.target.min,
   };
   var hintSize = {
    width: context.horizontal.hintSize,
    height: context.vertical.hintSize,
   };
   return getNotShiftedOffsetCore(context.position, targetSize, hintSize, context.calloutSize);
  }
  function getNotShiftedOffsetCore(position, targetSize, hintSize, calloutSize) {
   var offset = { x: 0, y: 0 };
   if (position == "top")
    offset.y -= hintSize.height + calloutSize.height;
   else if (position == "bottom")
    offset.y += targetSize.height + calloutSize.height;
   else if (position == "left")
    offset.x -= hintSize.width + calloutSize.width;
   else if (position == "right")
    offset.x += targetSize.width + calloutSize.width;
   if (position == "top" || position == "bottom")
    offset.x += targetSize.width / 2 - hintSize.width / 2;
   if (position == "left" || position == "right")
    offset.y += targetSize.height / 2 - hintSize.height / 2;
   return offset;
  }
  function set(targetElement, windowElement, options) {
   var pos = calcPosition(targetElement, windowElement, options);
   var customOffsets = { x: 0, y: 0 };
   var positionOrientation = getPositionOrienation(pos.flipPosition);
   if (positionOrientation.horizontal)
    customOffsets.x = options.offset * pos.location.x / Math.abs(pos.location.x); 
   if (positionOrientation.vertical)
    customOffsets.y = options.offset * pos.location.y / Math.abs(pos.location.y);
   var x = typeof options["x"] !== "undefined" ? options.x : ASPx.GetAbsoluteX(targetElement) + pos.location.x + customOffsets.x;
   var y = typeof options["y"] !== "undefined" ? options.y : ASPx.GetAbsoluteY(targetElement) + pos.location.y + customOffsets.y;
   ASPx.SetAbsoluteX(windowElement, x);
   ASPx.SetAbsoluteY(windowElement, y);
   return {
    flipPosition: pos.flipPosition,
    shift: {
     x: pos.shift.x,
     y: pos.shift.y
    }
   };
  }
  return {
   set: set,
   getNotShiftedOffsetCore: getNotShiftedOffsetCore, 
  };
 })();
 var FlipPositionToClientScreenHelper = {
  flipPositionIfRequired: function (context, position) {
   return this.ensureFlipCore(context.screen, context.target, context.hintSize, position);
  },
  getFlipPosition: function (position) {
   if (position == "bottom")
    return "top";
   if (position == "top")
    return "bottom";
   if (position == "right")
    return "left";
   if (position == "left")
    return "right";
   return position;
  },
  ensureFlipCore: function (screen, target, hintSize, position) {
   var positionMax = position == "bottom" || position == "right";
   var positionMin = position == "top" || position == "left";
   var spaceToMin = (target.min - hintSize) - screen.min;
   if (target.min - hintSize > screen.max) spaceToMin = -1;
   var spaceToMax = screen.max - (target.max + hintSize);
   if (target.max + hintSize < screen.min) spaceToMax = -1;
   var enoughSpaceMin = spaceToMin >= 0;
   var enoughSpaceMax = spaceToMax >= 0;
   if (!enoughSpaceMin && !enoughSpaceMax)
    return position;
   var enoughSpaceToShowHintMinWithoutFlip = positionMin && enoughSpaceMin;
   if (enoughSpaceToShowHintMinWithoutFlip) {
    return position;
   }
   var enoughSpaceToShowHintMaxWithoutFlip = positionMax && enoughSpaceMax;
   if (enoughSpaceToShowHintMaxWithoutFlip) {
    return position;
   }
   var flipMinToMax = positionMin && !enoughSpaceMin && spaceToMin < spaceToMax;
   var flipMaxToMin = positionMax && !enoughSpaceMax && spaceToMax < spaceToMin;
   if (flipMinToMax) {
    return this.getFlipPosition(position);
   }
   if (flipMaxToMin) {
    return this.getFlipPosition(position);
   }
   return position;
  }
 };
 var ShiftPositionToClientScreenHelper = {
  getShift: function (context, positionOrientation, hintOffset, minTargetMargin, isX) {
   var hintShift = 0;
   var canShift = !(positionOrientation.horizontal && isX) &&
    !(positionOrientation.vertical && !isX);
   if (canShift)
    hintShift = this.getShiftCore(context.screen, context.target, context.hintSize, hintOffset, minTargetMargin);
   return hintShift;
  },
  getShiftCore: function (screen, target, hintSize, hintOffset, minTargetMargin) {
   var notShiftedPos = 0;
   var targetIsOutsideMin = target.max < screen.min + minTargetMargin;
   var targetIsOutsideMax = target.min > screen.max - minTargetMargin;
   if (targetIsOutsideMin || targetIsOutsideMax)
    return notShiftedPos;
   var hint = { min: target.min + hintOffset, max: target.min + hintOffset + hintSize };
   var targetPartiallyOutsideLeft = hint.min < screen.min && hint.max > screen.min;
   var targetPartiallyOutsideRight = hint.max > screen.max && hint.min < screen.max;
   if (targetPartiallyOutsideLeft && !targetPartiallyOutsideRight) {
    var newPos = screen.min;
    var shift = newPos - hint.min;
    return shift;
   }
   if (targetPartiallyOutsideRight && !targetPartiallyOutsideLeft) {
    var newPos = screen.max - hintSize;
    var shift = newPos - hint.min;
    return shift;
   }
   return notShiftedPos;
  }
 };
 var attributeHelper = {
  attributeNameToBackupTitle: "data-dxhint-title",
  getAttributeValue: function (targetElement, attributeName) {
   var value = targetElement.getAttribute(attributeName);
   if (attributeName === "title") {
    if (value)
     return this.getRelocateTitleAttribute(targetElement);
    else if (value === "")
     return targetElement.getAttribute(this.attributeNameToBackupTitle);
   }
   if (!value && attributeName === this.attributeNameToBackupTitle) {
    return this.getRelocateTitleAttribute(targetElement);
   }
   return value;
  },
  getRelocateTitleAttribute: function (targetElement) {
   var titleValue = targetElement.getAttribute("title");
   if (titleValue) {
    targetElement.setAttribute(this.attributeNameToBackupTitle, titleValue);
    targetElement.setAttribute("title", "");
   }
   return titleValue;
  }
 };
 ASPxClientHint.FlipPositionToClientScreenHelper = FlipPositionToClientScreenHelper;
 ASPxClientHint.ShiftPositionToClientScreenHelper = ShiftPositionToClientScreenHelper;
 ASPxClientHint.PositionHelper = PositionHelper;
 ASPxClientHint.AttributeHelper = attributeHelper;
 window.ASPxClientHint = ASPxClientHint;
})();

(function() {
 ASPxClientPanelBase = ASPx.CreateClass(ASPxClientControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.touchUIScroller = null;
  },
  Initialize: function(){
   ASPxClientControl.prototype.Initialize.call(this);
   this.touchUIScroller = ASPx.TouchUIHelper.makeScrollableIfRequired(this.GetMainElement());
  },
  getContentElement: function() {
   if(this.getAnimationContentContainerElement())
    return this.getAnimationContentContainerElement();
   if(this.getScrollContentContainerElement())
    return this.getScrollContentContainerElement();
   if(!ASPx.IsExistsElement(this.contentElement)){
    var element = this.GetMainElement();
    this.contentElement = element && element.tagName == "TABLE" ? element.rows[0].cells[0] : element;
   }
   return this.contentElement;
  },
  getAnimationContentContainerElement: function() {
   return null;
  },
  getScrollContentContainerElement: function() {
   return null;
  },
  GetContentHTML: function(){
   return this.GetContentHtml();
  },
  SetContentHTML: function(html){
   this.SetContentHtml(html);
  },
  GetContentHtml: function(){
   return this.getContentElement().innerHTML;
  },
  SetContentHtml: function(html){
   ASPx.SetInnerHtml(this.getContentElement(), html);
   if(this.touchUIScroller)
    this.touchUIScroller.ChangeElement(this.getContentElement());
  }
 });
 ASPxClientPanelBase.Cast = ASPxClientControl.Cast;
 var FixedPanels = {};
 var FixedPositionProperties;
 var InitFixedPositionProperties = function(){
  FixedPositionProperties = {};
  FixedPositionProperties["Top"] = { 
   documentPadding: "padding-top", documentMargin: "margin-top", documentMargin2: "margin-bottom", 
   contentEdge: "top", oppositeContentEdge: "bottom", size: "offsetHeight", animationSize: "height", oppositePanel: "Bottom" 
  };
  FixedPositionProperties["Bottom"] = { 
   documentPadding: "padding-bottom", documentMargin: "margin-top", documentMargin2: "margin-bottom", 
   contentEdge: "bottom", oppositeContentEdge: "top", size: "offsetHeight", animationSize: "height", oppositePanel: "Top"
  };
  FixedPositionProperties["Left"] = { 
   documentPadding: "padding-left", documentMargin: "margin-left", documentMargin2: "margin-right", 
   contentEdge: "left", oppositeContentEdge: "right", size: "offsetWidth", animationSize: "width", oppositePanel: "Right"
  };
  FixedPositionProperties["Right"] = { 
   documentPadding: "padding-right", documentMargin: "margin-left", documentMargin2: "margin-right", 
   contentEdge: "right", oppositeContentEdge: "left", size: "offsetWidth", animationSize: "width", oppositePanel: "Left"
  };
 };
 var ExpandDirectionProperties;
 var InitExpandDirectionProperties = function(){
  ExpandDirectionProperties = {};
  ExpandDirectionProperties["PopupToLeft"] = { 
   hAlign: ASPx.PopupUtils.OutsideLeftAlignIndicator, vAlign: ASPx.PopupUtils.TopSidesAlignIndicator, 
   size: "offsetWidth", animationSize: "width" 
  };
  ExpandDirectionProperties["PopupToRight"] = { 
   hAlign: ASPx.PopupUtils.OutsideRightAlignIndicator, vAlign: ASPx.PopupUtils.TopSidesAlignIndicator, 
   size: "offsetWidth", animationSize: "width" 
  };
  ExpandDirectionProperties["PopupToTop"] = { 
   hAlign: ASPx.PopupUtils.LeftSidesAlignIndicator, vAlign: ASPx.PopupUtils.AboveAlignIndicator, 
   size: "offsetHeight", animationSize: "height" 
  };
  ExpandDirectionProperties["PopupToBottom"] = { 
   hAlign: ASPx.PopupUtils.LeftSidesAlignIndicator, vAlign: ASPx.PopupUtils.BelowAlignIndicator, 
   size: "offsetHeight", animationSize: "height" 
  };
 };
 var CollapsiblePanelsAutoGenGroupCount = 0;
 var CollapsiblePanelsGroups = {};
 var ExpandedPanels = {};
 var DocumentProperties = {};
 var EXPANDED_SELECTOR = "dxpnl-expanded";
 var COLLAPSIBLE_SELECTOR = "dxpnl-collapsible";
 var CENTER_BTN_POSITION_SELECTOR = "dxpnl-cp";
 var FAR_BTN_POSITION_SELECTOR = "dxpnl-fp";
 var EXPAND_BAR_ID = "_EB";
 var MODAL_ELEMENT_ID = "_M";
 var EXPAND_BUTTON_ID = "_EBB";
 var COLLAPSED_STATE_CLASS_NAME = "dxpnl-collapsedState";
 var HIDDEN_STATE_CLASS_NAME = "dxpnl-hiddenState";
 var EXPAND_BAR_TEMPLATE_CLASS_NAME = "dxpnl-bar-tmpl";
 ASPxClientPanel = ASPx.CreateClass(ASPxClientPanelBase, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.animationType = "none";
   this.fixedPosition = this.getFixedPosition();
   this.expandEffect = "Slide";
   this.expandOnPageLoad = false;
   this.groupName = "";
   this.fixedPositionOverlap = false;
   this.fixedPositionProperties = null;
   this.expandDirectionProperties = null;
   this.documentMarginsChanged = false;
   this.slideAnimationPosProperty = null;
   this.slideAnimationExpandBarSize = null;
   this.collapseWindowWidth = 0;
   this.collapseWindowHeight = 0;
   this.hideWindowWidth = 0;
   this.hideWindowHeight = 0;
   this.modalElement = null;
   this.modalElementOpacity = 0.7;
   this.modalShowAnimationDuration = ASPx.AnimationConstants.Durations.SHORT;
   this.modalHideAnimationDuration = ASPx.AnimationConstants.Durations.SHORT - 50;
   this.contentElement = null;
   this.expandBarElement = null;
   this.expandButtonElement = null;
   this.animationContentContainerElement = null;
   this.scrollContentContainerElement = null;
   this.Collapsed = new ASPxClientEvent();
   this.Expanded = new ASPxClientEvent();
  },
  InlineInitialize: function(){
   ASPxClientPanelBase.prototype.InlineInitialize.call(this);
   if(this.fixedPosition) {
    if(!FixedPositionProperties)
     InitFixedPositionProperties();
    this.fixedPositionProperties = FixedPositionProperties[this.fixedPosition];
   }
   if(this.expandEffect.indexOf("Popup") > -1){
    if(!ExpandDirectionProperties)
     InitExpandDirectionProperties();
    this.expandDirectionProperties = ExpandDirectionProperties[this.expandEffect];
   }
   if(this.isPositionFixed()){
    this.prepareModalElement();
    FixedPanels[this.fixedPosition] = this;
    var scrollContainer = this.getScrollContentContainerElement();
    if(scrollContainer && 
     (scrollContainer.style.overflow !== "" && scrollContainer.style.overflow !== "visible" ||
     scrollContainer.style.overflowX !== "" && scrollContainer.style.overflowX !== "visible" ||
     scrollContainer.style.overflowY !== "" && scrollContainer.style.overflowY !== "visible")){
     ASPx.Evt.AttachEventToElement(scrollContainer, "scroll",
      function (evt) {
       if(ASPx.Evt.GetEventSource(evt) != scrollContainer)
        return;
       if(typeof(ASPx.GetDropDownCollection) != "undefined")
        ASPx.GetDropDownCollection().ProcessControlsInContainer(scrollContainer, function(control) {
         control.HideDropDown();
        });
       if(typeof(ASPx.GetMenuCollection) != "undefined")
        ASPx.GetMenuCollection().HideAll();
      }.aspxBind(this));
    }
   }
   if(this.hideWindowWidth > 0 || this.hideWindowHeight > 0) {
    this.createVisibilityCss();
    this.checkExpandBarContent();
   }
   if(this.collapseWindowWidth > 0 || this.collapseWindowHeight > 0) {
    this.createCollapsibilityCss();
    this.checkExpandBarContent();
   }
   if(this.groupName == ""){
    this.groupName = "DXAutoGenExpandGroup" + CollapsiblePanelsAutoGenGroupCount;
    CollapsiblePanelsAutoGenGroupCount++;
   }
   if(!CollapsiblePanelsGroups[this.groupName])
    CollapsiblePanelsGroups[this.groupName] = [];
   CollapsiblePanelsGroups[this.groupName].push(this);
   var btnElement = this.getExpandButtonElement();
   if(btnElement){
    ASPx.Evt.AttachEventToElement(btnElement, ASPx.TouchUIHelper.touchMouseUpEventName,
     function (evt) {
      if(ASPx.Evt.IsLeftButtonPressed(evt))
       this.Toggle();
     }.aspxBind(this));
   }
   this.updateFixedPanelContext();
   if(!this.clientEnabled)
    this.SetEnabled(this.clientEnabled);
  },
  prepareModalElement: function() {
   if(!this.isModal()) return;
   var modalElement = this.getModalElement();
   this.modalElementOpacity = ASPx.GetCurrentStyle(modalElement).opacity;
   ASPx.Evt.AttachEventToElement(modalElement, ASPx.TouchUIHelper.touchMouseUpEventName,
    function(evt) {
     if(ASPx.Evt.IsLeftButtonPressed(evt))
      this.Collapse();
    }.aspxBind(this));
   modalElement.style.zIndex = ASPx.GetCurrentStyle(this.GetMainElement()).zIndex - 2;
  },
  AfterInitialize: function(){
   ASPxClientPanelBase.prototype.AfterInitialize.call(this);
   var barElement = this.getExpandBarElement();
   if(barElement && this.isExpandBarChangeVisibilityOnExpanding())
    ASPx.AddClassNameToElement(barElement, "h");
   if(this.expandOnPageLoad)
    this.Expand(true);
  },
  OnDispose: function () {
   if(FixedPanels[this.fixedPosition] === this)
    delete FixedPanels[this.fixedPosition];
   if(ASPx.Ident.IsArray(CollapsiblePanelsGroups[this.groupName])){
    ASPx.Data.ArrayRemove(CollapsiblePanelsGroups[this.groupName], this);
    if(CollapsiblePanelsGroups[this.groupName].length === 0)
     delete CollapsiblePanelsGroups[this.groupName];
   }
   if(ExpandedPanels[this.groupName] === this)
    delete ExpandedPanels[this.groupName];
   ASPxClientPanelBase.prototype.OnDispose.call(this);
  },
  AdjustControlCore: function() {
   this.updateExpandButtonPosition();
   this.updateFixedPanelContext();
  },
  GetAdjustedSizes: function() {
   var sizes = ASPxClientControl.prototype.GetAdjustedSizes.call(this);
   var expandBar = this.getExpandBarElement();
   if(expandBar) {
    sizes["expandBarWidth"] = expandBar.offsetWidth;
    sizes["expandBarHeight"] = expandBar.offsetHeight;
   }
   return sizes;
  },
  IsDisplayed: function() {
   if(ASPxClientPanelBase.prototype.IsDisplayed.call(this))
    return true;
   return this.IsDisplayedElement(this.getExpandBarElement());
  },
  IsHidden: function() {
   if(!ASPxClientPanelBase.prototype.IsHidden.call(this))
    return false;
   return this.IsHiddenElement(this.getExpandBarElement());
  },
  OnBrowserWindowResize: function(e) {
   this.onBrowserWindowResizeCore();
   window.setTimeout(function() {
    this.onBrowserWindowResizeCore();
   }.aspxBind(this), 0);
  },
  BrowserWindowResizeSubscriber: function() {
   return this.isPositionFixed() || this.getExpandBarElement();
  },
  HasFixedPosition: function() {
   return this.isPositionFixed();
  },
  RegisterInControlTree: function(tree) {
   var mainNode = tree.createNode(null, this);
   this.registerElementInTree(this.GetMainElement(), tree, mainNode);
   this.registerElementInTree(this.getExpandBarElement(), tree, mainNode);
  },
  getSizeCore: function(element, sizeProperty){
   return element[sizeProperty];
  },
  getFixedSize: function(sizeProperty){
   return this.getSizeCore(this.getFixedElement(), sizeProperty);
  },
  getExpandedSize: function(sizeProperty){
   if(this.getExpandBarElement() && this.isElementDisplayed(this.getExpandBarElement()))
    return this.getSizeCore(this.GetMainElement(), sizeProperty);
   return 0;
  },
  GetWidth: function() {
   if(!this.getExpandBarElement()) 
    return ASPxClientControl.prototype.GetWidth.call(this);
   var width = 0;
   if(this.isElementDisplayed(this.getExpandBarElement()))
    width += this.getExpandBarElement().offsetWidth;
   if(this.isElementDisplayed(this.GetMainElement()) && (!this.IsExpandedInternal() || !this.isPopupExpanding()))
    width += this.GetMainElement().offsetWidth;
   return width;
  },
  GetHeight: function() {
   if(!this.getExpandBarElement()) 
    return ASPxClientControl.prototype.GetHeight.call(this);
   var height = 0;
   if(this.isElementDisplayed(this.getExpandBarElement()))
    height += this.getExpandBarElement().offsetHeight;
   if(this.isElementDisplayed(this.GetMainElement()) && (!this.IsExpandedInternal() || !this.isPopupExpanding()))
    height += this.GetMainElement().offsetHeight;
   return height;
  },
  SetVisible: function (value) {
   if(this.clientVisible != value) {
    ASPxClientPanelBase.prototype.SetVisible.call(this, value);
    var expandBarElement = this.getExpandBarElement();
    if(expandBarElement) ASPx.SetElementDisplay(expandBarElement, value);
    this.updateFixedPanelContext();
   }
  },
  onBrowserWindowResizeCore: function() {
   this.updateExpandButtonPosition();
   this.updateFixedPanelContext();
   this.checkCollapseContent();
   this.checkExpandBarContent();
  },
  registerElementInTree: function(element, tree, mainNode) {
   if(element && element.id) {
    var node = tree.createNode(element.id, null);
    tree.addRelatedNode(node, mainNode);
   }
  },
  updateFixedPanelContext: function(){
   if(!this.isPositionFixed()) return;
   this.updateDocumentPaddings();
   this.updateMainElementFixedPosition();
   this.updateFixedPanelsPosition();
  },
  updateExpandButtonPosition: function(){
   var expandButton = this.getExpandButtonElement();
   if(!expandButton) return;
   var expandBar = this.getExpandBarElement();
   if(!expandBar) return;
   var isCenterPosition = expandButton.className.indexOf(CENTER_BTN_POSITION_SELECTOR) > -1;
   var isFarPosition = expandButton.className.indexOf(FAR_BTN_POSITION_SELECTOR) > -1;
   if(isCenterPosition && expandButton.offsetWidth > 0){
    expandButton.style.width = expandButton.offsetWidth + "px";
    ASPx.SetElementFloat(expandButton, "none");
   }
   var correctButtonPosition = false;
   if(this.fixedPosition == "Top" || this.fixedPosition == "Bottom")
    correctButtonPosition = true;
   else if(this.fixedPosition == "Left" || this.fixedPosition == "Right")
    correctButtonPosition = (isCenterPosition || isFarPosition) && !expandBar.querySelector("." + EXPAND_BAR_TEMPLATE_CLASS_NAME);
   else if(this.hasVerticalOrientation())
    correctButtonPosition = isCenterPosition;
   else
    correctButtonPosition = true;
   if(correctButtonPosition) 
    this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.getExpandButtonElement, "Btn", true);
  },
  updateDocumentPaddings: function(){
   if(!this.fixedPositionProperties) return;
   var size = this.getFixedSize(this.fixedPositionProperties.size);
   var expandedSize = 0;
   if(this.expandEffect == "Slide"){
    expandedSize = this.getExpandedSize(this.fixedPositionProperties.size);
    if(this.fixedPosition == "Right" || this.fixedPosition == "Bottom")
     expandedSize = -expandedSize;
   }
   if(!this.fixedPanelCoversViewPort(this.fixedPositionProperties.contentEdge, size))
    this.changeStyleSideAttribute(document.documentElement, "padding", this.fixedPositionProperties.documentPadding, size + "px");
   var documentMarginValue = this.getDocumentPropertyValue(this.fixedPositionProperties.documentMargin);
   var documentMargin2Value = this.getDocumentPropertyValue(this.fixedPositionProperties.documentMargin2);
   if(expandedSize != 0){
    ASPx.Attr.ChangeStyleAttribute(document.documentElement, this.fixedPositionProperties.documentMargin, (documentMarginValue + expandedSize) + "px");
    ASPx.Attr.ChangeStyleAttribute(document.documentElement, this.fixedPositionProperties.documentMargin2, (documentMargin2Value - expandedSize) + "px");
    this.documentMarginsChanged = true;
   }
   else if(this.documentMarginsChanged){
    ASPx.Attr.RestoreStyleAttribute(document.documentElement, this.fixedPositionProperties.documentMargin);
    ASPx.Attr.RestoreStyleAttribute(document.documentElement, this.fixedPositionProperties.documentMargin2);
    this.documentMarginsChanged = false;
   }
  },
  fixedPanelCoversViewPort: function(contentEdge, size) {
   return ((contentEdge === "top" || contentEdge === "bottom") && size >= window.innerHeight) ||
    ((contentEdge === "left" || contentEdge === "right") && size >= window.innerWidth);
  },
  changeStyleSideAttribute: function(element, baseAttr, attr, value){
   ASPx.Attr.ChangeStyleAttribute(element, attr, value);
  },
  updateMainElementFixedPosition: function(){
   if(!this.fixedPositionProperties) return;
   var barElement = this.getExpandBarElement();
   if(barElement){
    var size = this.getSizeCore(barElement, this.fixedPositionProperties.size);
    ASPx.Attr.ChangeStyleAttribute(this.GetMainElement(), this.fixedPositionProperties.contentEdge, size + "px");
   }
  },
  updateFixedPanelsPosition: function() {
   this.updateFixedPanelsEdges(this.updateFixedPanelEdge);
   this.updateFixedPanelsEdges(this.updateFixedPanelOppositeEdge);
  },
  updateFixedPanelsEdges: function(method) {
   if(FixedPanels["Top"]){
    if(FixedPanels["Left"] && !FixedPanels["Top"].fixedPositionOverlap && FixedPanels["Left"].fixedPositionOverlap)
     method.call(FixedPanels["Left"], FixedPanels["Top"], FixedPanels["Right"]);
    if(FixedPanels["Right"] && !FixedPanels["Top"].fixedPositionOverlap && FixedPanels["Right"].fixedPositionOverlap)
     method.call(FixedPanels["Right"], FixedPanels["Top"], FixedPanels["Left"]);
   }
   if(FixedPanels["Bottom"]){
    if(FixedPanels["Left"] && !FixedPanels["Bottom"].fixedPositionOverlap && FixedPanels["Left"].fixedPositionOverlap)
     method.call(FixedPanels["Left"], FixedPanels["Bottom"], FixedPanels["Right"]);
    if(FixedPanels["Right"] && !FixedPanels["Bottom"].fixedPositionOverlap && FixedPanels["Right"].fixedPositionOverlap)
     method.call(FixedPanels["Right"], FixedPanels["Bottom"], FixedPanels["Left"]);
   }
   if(FixedPanels["Left"]){
    if(FixedPanels["Top"] && (!FixedPanels["Left"].fixedPositionOverlap || FixedPanels["Top"].fixedPositionOverlap))
     method.call(FixedPanels["Top"], FixedPanels["Left"], FixedPanels["Bottom"]);
    if(FixedPanels["Bottom"] && (!FixedPanels["Left"].fixedPositionOverlap || FixedPanels["Bottom"].fixedPositionOverlap))
     method.call(FixedPanels["Bottom"], FixedPanels["Left"], FixedPanels["Top"]);
   }
   if(FixedPanels["Right"]){
    if(FixedPanels["Top"] && (!FixedPanels["Right"].fixedPositionOverlap || FixedPanels["Top"].fixedPositionOverlap))
     method.call(FixedPanels["Top"], FixedPanels["Right"], FixedPanels["Bottom"]);
    if(FixedPanels["Bottom"] && (!FixedPanels["Right"].fixedPositionOverlap || FixedPanels["Bottom"].fixedPositionOverlap))
     method.call(FixedPanels["Bottom"], FixedPanels["Right"], FixedPanels["Top"]);
   }
  },
  updateFixedPanelEdge: function(panel){
   var size = this.getFixedSize(this.fixedPositionProperties.size);
   if(this.expandEffect == "Slide")
    size += this.getExpandedSize(this.fixedPositionProperties.size);
   this.updateFixedPanelEdgeCore(panel, this.fixedPositionProperties.contentEdge, size);
  },
  updateFixedPanelOppositeEdge: function(panel, opppositePanel){
   if(!this.IsExpandedInternal() && opppositePanel) return;
   if(this.expandEffect == "Slide") {
    var size = this.getExpandedSize(this.fixedPositionProperties.size);
    this.updateFixedPanelEdgeCore(panel, this.fixedPositionProperties.oppositeContentEdge, -size);
   }
  },
  updateFixedPanelEdgeCore: function(panel, edge, size){
   var mainElement = panel.GetMainElement();
   mainElement.style[edge] = size + "px";
   var expandBarElement = panel.getExpandBarElement();
   if(expandBarElement)
    expandBarElement.style[edge] = size + "px";
  },
  isPositionFixed: function(){
   return !!this.fixedPositionProperties;
  },
  getFixedPosition: function(){
   var cssClass = this.GetMainElement().className;
   if(cssClass.indexOf("dxpnl-edge t") > -1)
    return "Top";
   if(cssClass.indexOf("dxpnl-edge b") > -1)
    return "Bottom";
   if(cssClass.indexOf("dxpnl-edge l") > -1)
    return "Left";
   if(cssClass.indexOf("dxpnl-edge r") > -1)
    return "Right";
   return null;
  },
  isPopupExpanding: function(){
   return !!this.expandDirectionProperties;
  },
  isExpandBarChangeVisibilityOnExpanding: function(){
   return !this.isPopupExpanding() && !this.isPositionFixed() && CollapsiblePanelsGroups[this.groupName].length > 1;
  },
  createVisibilityCss: function() {
   var rules = [];
   rules.push({ selector: "#" + this.name, cssText: "display: none!important;" });
   rules.push({ selector: "#" + this.getExpandBarId(), cssText: "display: none!important;" });
   this.insertAdaptivityRules(rules, this.hideWindowWidth, this.hideWindowHeight, HIDDEN_STATE_CLASS_NAME);
  },
  createCollapsibilityCss: function() {
   var rules = [];
   rules.push({ selector: "#" + this.name, cssText: "display: none;" });
   rules.push({ selector: "#" + this.getExpandBarId() + ".dxpnl-bar", cssText: (this.isPositionFixed() ? "display: block;" : "display: table;") });
   rules.push({ selector: "#" + this.name + "." + EXPANDED_SELECTOR, cssText: "display: block!important;" });
   this.insertAdaptivityRules(rules, this.collapseWindowWidth, this.collapseWindowHeight, COLLAPSED_STATE_CLASS_NAME);
  },
  insertAdaptivityRules: function(rules, maxWindowWidth, maxWindowHeight, adaptivityClassName) {
   var styleSheet = ASPx.GetCurrentStyleSheet();
   if(!styleSheet) return;
   var mediaRule = "@media all and (max-width: " + maxWindowWidth + "px), (max-height: " + maxWindowHeight + "px) { ";
   for(var i = 0; i < rules.length; i++)
    mediaRule += rules[i].selector + "{" + rules[i].cssText + "}";
   mediaRule += "}";
   if(styleSheet.insertRule)
    styleSheet.insertRule(mediaRule, styleSheet.cssRules.length);
  },
  ensureAdaptivityClassNames: function() {
   this.ensureAdaptivityClassName(HIDDEN_STATE_CLASS_NAME, this.hideWindowWidth, this.hideWindowHeight);
   this.ensureAdaptivityClassName(COLLAPSED_STATE_CLASS_NAME, this.collapseWindowWidth, this.collapseWindowHeight);
  },
  ensureAdaptivityClassName: function(adaptivityClassName, maxWindowWidth, maxWindowHeight) {
   var currentDocumentWidth = ASPx.GetCurrentDocumentWidth();
   var currentDocumentHeight = ASPx.GetCurrentDocumentHeight();
   if(currentDocumentWidth <= maxWindowWidth || currentDocumentHeight <= maxWindowHeight)
    this.addAdaptivityClassName(adaptivityClassName);
   else
    this.removeAdaptivityClassName(adaptivityClassName);
  },
  addAdaptivityClassName: function(className) {
   ASPx.AddClassNameToElement(this.GetMainElement(), className);
   if(ASPx.IsExists(this.getExpandBarElement()))
    ASPx.AddClassNameToElement(this.getExpandBarElement(), className);
  },
  removeAdaptivityClassName: function(className) {
   ASPx.RemoveClassNameFromElement(this.GetMainElement(), className);
   if(ASPx.IsExists(this.getExpandBarElement()))
    ASPx.RemoveClassNameFromElement(this.getExpandBarElement(), className);
  },
  Toggle: function() {
   if(this.IsExpandedInternal()) 
    this.Collapse();
   else 
    this.Expand();
  },
  IsExpandable: function() {
   if(this.GetMainElement().className.indexOf(" " + COLLAPSIBLE_SELECTOR) > -1)
    return true;
   if(this.collapseWindowWidth > 0 || this.collapseWindowHeight > 0){
    var expandBarElement = this.getExpandBarElement();
    return expandBarElement && ASPx.GetCurrentStyle(expandBarElement).display !== "none";
   }
   return false;
  },
  IsExpanded: function() {
   if(this.IsExpandable())
    return this.IsExpandedInternal();
   return true;
  },
  IsExpandedInternal: function() {
   return this.GetMainElement().className.indexOf(" " + EXPANDED_SELECTOR) > -1;
  },
  Expand: function(preventAnimation) {
   if(ExpandedPanels[this.groupName] != this) {
    if(ExpandedPanels[this.groupName])
     ExpandedPanels[this.groupName].Collapse(preventAnimation);
    this.collapseOppositePanel(preventAnimation);
    this.collapseUnfixedPopupPanels();
    ExpandedPanels[this.groupName] = this;
    ASPx.GetStateController().SelectElementBySrcElement(this.GetMainElement());
    ASPx.GetStateController().SelectElementBySrcElement(this.getExpandButtonElement());
    if(this.isModal()) {
     var modalElement = this.getModalElement();
     ASPx.AnimationHelper.fadeTo(modalElement, { from: 0, to: this.modalElementOpacity, duration: this.modalShowAnimationDuration });
    }
    ASPx.GetControlCollection().AdjustControls(this.GetMainElement());
    if(this.isPopupExpanding() && !this.isPositionFixed())
     this.updateMainElementPosition(true);
    if(this.isExpandBarChangeVisibilityOnExpanding())
     this.slideAnimationExpandBarSize = this.getSlideAnimationSize(this.getExpandBarElement(), true);
    ASPx.GetStateController().SelectElementBySrcElement(this.getExpandBarElement());
    if(!preventAnimation && this.animationType == "slide")
     this.startSlideAnimation(this.GetMainElement(), false);
    else if(!preventAnimation && this.animationType == "fade")
     this.startFadeAnimation(this.GetMainElement(), false);
    else
     this.expandCore();
   }
  },
  Collapse: function(preventAnimation) {
   if(ExpandedPanels[this.groupName] == this) {
    ExpandedPanels[this.groupName] = null;
    this.collapseUnfixedPopupPanels();
    if(this.isExpandBarChangeVisibilityOnExpanding()){
     ASPx.GetStateController().DeselectElementBySrcElement(this.getExpandBarElement());
     this.slideAnimationExpandBarSize = this.getSlideAnimationSize(this.getExpandBarElement(), true);
     ASPx.GetStateController().SelectElementBySrcElement(this.getExpandBarElement());
    }
    if(this.isModal()) {
     var modalElement = this.getModalElement(),
      fromOpacity = ASPx.GetCurrentStyle(modalElement).opacity;
     ASPx.AnimationHelper.fadeTo(modalElement, { from: fromOpacity, to: 0, duration: this.modalHideAnimationDuration });
    }
    if(!preventAnimation && this.animationType == "slide")
     this.startSlideAnimation(this.GetMainElement(), true);
    else if(!preventAnimation && this.animationType == "fade")
     this.startFadeAnimation(this.GetMainElement(), true);
    else
     this.collapseCore();
   }
  },
  isModal: function() {
   return !!this.getModalElement();
  },
  expandCore: function() {
   if(this.isPositionFixed()) {
    this.updateFixedPanelContext();
   }
   this.raiseExpanded();
  },
  collapseCore: function() {
   ASPx.GetStateController().DeselectElementBySrcElement(this.GetMainElement());
   ASPx.GetStateController().DeselectElementBySrcElement(this.getExpandButtonElement());
   if(this.isPopupExpanding() && !this.isPositionFixed())
    this.updateMainElementPosition(false);
   ASPx.GetStateController().DeselectElementBySrcElement(this.getExpandBarElement());
   if(this.isPositionFixed()) {
    this.updateFixedPanelContext();
   }
   this.slideAnimationPosProperty = null;
   this.raiseCollapsed();
  },
  collapseOppositePanel: function(preventAnimation) {
   if(!this.fixedPositionProperties) return;
   if(FixedPanels[this.fixedPositionProperties.oppositePanel])
    FixedPanels[this.fixedPositionProperties.oppositePanel].Collapse(preventAnimation);
  },
  collapseUnfixedPopupPanels: function() {
   if(!this.isPositionFixed() || this.isPopupExpanding()) return;
   for(var groupName in ExpandedPanels){
    if(ExpandedPanels[groupName] && !ExpandedPanels[groupName].fixedPosition && ExpandedPanels[groupName].isPopupExpanding())
     ExpandedPanels[groupName].Collapse(true);
   }
  },
  saveOpacity: function(element) {
   ASPx.Attr.SaveStyleAttribute(element, "opacity");
  },
  restoreOpacity: function(element) {
   ASPx.Attr.RestoreStyleAttribute(element, "opacity");
  },
  startFadeAnimation: function (element, isCollapsing) {
   this.saveOpacity(element);
   var onComplete =  function() { this.finishFadeAnimation(element, isCollapsing); }.aspxBind(this);
   if(isCollapsing)
    ASPx.AnimationHelper.fadeOut(element, onComplete, ASPx.AnimationConstants.Durations.SHORT);
   else
    ASPx.AnimationHelper.fadeIn(element, onComplete, ASPx.AnimationConstants.Durations.SHORT);
  },
  finishFadeAnimation: function (element, isCollapsing) {
   this.restoreOpacity(element);
   if(isCollapsing)
    this.collapseCore(); 
   else
    this.expandCore(); 
  },
  startSlideAnimation: function(element, isCollapsing) {
   var sizeProperty = this.getSlideAnimationSizeProperty();
   ASPx.Attr.ChangeStyleAttribute(element, "overflow", "auto");
   var offsetWidth = element.offsetWidth;
   var offsetHeight = element.offsetHeight;
   ASPx.Attr.RestoreStyleAttribute(element, "overflow");
   ASPx.Attr.SaveStyleAttribute(element, sizeProperty);
   if(element.style.overflow !== "")
    ASPx.Attr.ChangeStyleAttribute(element, "overflow", "hidden");
   else {
    ASPx.Attr.ChangeStyleAttribute(element, "overflow-x", "hidden");
    ASPx.Attr.ChangeStyleAttribute(element, "overflow-y", "hidden");
   }
   var contentContainer = this.getAnimationContentContainerElement();
   if(contentContainer) {
    if(contentContainer.style.overflow !== "")
     ASPx.Attr.ChangeStyleAttribute(contentContainer, "overflow", "hidden");
    else{
     ASPx.Attr.ChangeStyleAttribute(contentContainer, "overflow-x", "hidden");
     ASPx.Attr.ChangeStyleAttribute(contentContainer, "overflow-y", "hidden");
    }
    ASPx.Attr.ChangeStyleAttribute(contentContainer, "width", offsetWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element) + "px");
    ASPx.Attr.ChangeStyleAttribute(contentContainer, "height", offsetHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element) + "px");
   }
   var transitionProperties = {
    duration: ASPx.AnimationConstants.Durations.SHORT, 
    onComplete: function() { this.finishSlideAnimation(element, isCollapsing); }.aspxBind(this)
   };
   if(this.isPositionFixed())
    transitionProperties.onStep = function() { this.performSlideAnimationStep(); }.aspxBind(this);
   var transition = ASPx.AnimationHelper.createMultipleAnimationTransition(element, transitionProperties);
   var size = this.getSlideAnimationSize(element, !this.isPositionFixed());
   var startSize = isCollapsing ? size : 0;
   var endSize = isCollapsing ? 0 : size;
   if(this.isExpandBarChangeVisibilityOnExpanding() && this.slideAnimationExpandBarSize){
    if(startSize == 0)
     startSize = this.slideAnimationExpandBarSize;
    if(endSize == 0)
     endSize = this.slideAnimationExpandBarSize;
   }
   var properties = {};
   properties[sizeProperty] = { from: startSize, to: endSize, unit: "px" };
   if(!isCollapsing) 
    ASPx.Attr.ChangeStyleAttribute(element, sizeProperty, startSize + "px");
   if(this.slideAnimationPosProperty){
    var position = parseInt(element.style[this.slideAnimationPosProperty]);
    var startPosition = isCollapsing ? position : position + size;
    var endPosition = isCollapsing ? position + size : position;
    properties[this.slideAnimationPosProperty] = { from: startPosition, to: endPosition, unit: "px" };
    if(!isCollapsing) 
     ASPx.Attr.ChangeStyleAttribute(element, this.slideAnimationPosProperty, startPosition + "px");
   }
   transition.Start(properties);
  },
  finishSlideAnimation: function(element, isCollapsing) {
   var sizeProperty = this.getSlideAnimationSizeProperty();
   ASPx.Attr.RestoreStyleAttribute(element, sizeProperty);
   ASPx.Attr.RestoreStyleAttribute(element, "overflow");
   ASPx.Attr.RestoreStyleAttribute(element, "overflow-x");
   ASPx.Attr.RestoreStyleAttribute(element, "overflow-y");
   var contentContainer = this.getAnimationContentContainerElement();
   if(contentContainer) {
    ASPx.Attr.RestoreStyleAttribute(contentContainer, "overflow");
    ASPx.Attr.RestoreStyleAttribute(contentContainer, "overflow-x");
    ASPx.Attr.RestoreStyleAttribute(contentContainer, "overflow-y");
    ASPx.Attr.RestoreStyleAttribute(contentContainer, "width");
    ASPx.Attr.RestoreStyleAttribute(contentContainer, "height");
   }
   if(isCollapsing)
    this.collapseCore(); 
   else
    this.expandCore(); 
  },
  performSlideAnimationStep: function() {
   this.updateFixedPanelContext();
  },
  getSlideAnimationSizeProperty: function() {
   if(this.fixedPositionProperties)
    return this.fixedPositionProperties.animationSize;
   else if(this.expandDirectionProperties)
    return this.expandDirectionProperties.animationSize;
   else 
    return this.hasVerticalOrientation() ? "width" : "height";
  },
  getSlideAnimationSize: function(element, fullSize) {
   var sizeProperty;
   if(this.fixedPositionProperties)
    sizeProperty = this.fixedPositionProperties.size;
   else if(this.expandDirectionProperties)
    sizeProperty = this.expandDirectionProperties.size;
   else
    sizeProperty = this.hasVerticalOrientation() ? "offsetWidth" : "offsetHeight";
   var size = this.getSizeCore(element, sizeProperty);
   if(fullSize) {
    if(sizeProperty == "offsetWidth")
     size -= ASPx.GetHorizontalBordersWidth(element);
    else
     size -= ASPx.GetVerticalBordersWidth(element);
   }
   else {
    if(sizeProperty == "offsetWidth")
     size -= ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element);
    else
     size -= ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element);
   }
   return size;
  },
  getSlideAnimationPosProperty: function(x, y) {
   if(this.expandEffect == "PopupToTop")
    return !y.isInverted ? "top" : null;
   if(this.expandEffect == "PopupToBottom")
    return y.isInverted ? "top" : null;
   if(this.expandEffect == "PopupToLeft")
    return !x.isInverted ? "left" : null;
   if(this.expandEffect == "PopupToRight")
    return y.isInverted ? "left" : null;
   return null;
  }, 
  hasVerticalOrientation: function() {
   var float = ASPx.GetElementFloat(this.GetMainElement());
   return (float === "left" || float === "right");
  },
  updateMainElementPosition: function(expanded) {
   if(!this.expandDirectionProperties) return;
   if(expanded)
    this.updateMainElementExpandedPosition(this.GetMainElement());
   else
    this.updateMainElementCollapsedPosition(this.GetMainElement());
  },
  updateMainElementExpandedPosition: function(element) {
   if(element.style.width === "100%")
    ASPx.Attr.ChangeStyleAttribute(element, "width", (element.parentNode.offsetWidth - ASPx.GetLeftRightMargins(element)) + "px");
   if(element.style.height === "100%")
    ASPx.Attr.ChangeStyleAttribute(element, "height", (element.parentNode.offsetHeight - ASPx.GetTopBottomMargins(element)) + "px");
   ASPx.Attr.ChangeStyleAttribute(element, "position", "absolute");
   var barElement = this.getExpandBarElement();
   var x = ASPx.PopupUtils.GetPopupAbsoluteX(element,
    barElement, this.expandDirectionProperties.hAlign, 0, 0, 0, false, false);
   var y = ASPx.PopupUtils.GetPopupAbsoluteY(element,
    barElement, this.expandDirectionProperties.vAlign, 0, 0, 0, true, false);
   ASPx.SetAbsoluteX(element, x.position);
   ASPx.SetAbsoluteY(element, y.position);
   this.slideAnimationPosProperty = this.getSlideAnimationPosProperty(x, y);
  },
  updateMainElementCollapsedPosition: function(element) {
   ASPx.Attr.RestoreStyleAttribute(element, "position");
   ASPx.Attr.RestoreStyleAttribute(element, "left");
   ASPx.Attr.RestoreStyleAttribute(element, "top");
   ASPx.Attr.RestoreStyleAttribute(element, "width");
   ASPx.Attr.RestoreStyleAttribute(element, "height");
  },
  checkCollapseContent: function(){
   if(!this.getExpandBarElement()) return;
   if(this.IsExpandedInternal()){
    if(CollapsiblePanelsGroups[this.groupName].length === 1 && !this.isElementDisplayed(this.getExpandBarElement()) && this.isElementDisplayed(this.GetMainElement()))
     this.Collapse(true);
    if(!this.isPositionFixed() && this.isPopupExpanding())
     this.Collapse(true);
   }
  },
  checkExpandBarContent: function() {
   var expandBar = this.getExpandBarElement();
   if(expandBar) {
    var expandBarTmpl = expandBar.querySelector("." + EXPAND_BAR_TEMPLATE_CLASS_NAME);
    if(expandBarTmpl) {
     var expandBarVisible = window.getComputedStyle(expandBar).display !== "none";
     if(this.expandBarVisible !== expandBarVisible && expandBarVisible) {
      var btn = this.getExpandButtonElement();
      if(this.fixedPosition == "Top" || this.fixedPosition == "Bottom") {
       var btnWidth = 0;
       if(btn) {
        var style = window.getComputedStyle(btn);
        btnWidth += btn.getBoundingClientRect().width + parseInt(style.marginLeft) + parseInt(style.marginRight);
       }
       expandBarTmpl.style.width = "calc(100% - " + Math.ceil(btnWidth) + "px)";
      }
      else if(this.fixedPosition == "Left" || this.fixedPosition == "Right") {
       var btnHeight = 0;
       if(btn) {
        var style = window.getComputedStyle(btn);
        btnHeight += btn.getBoundingClientRect().height + parseInt(style.marginTop) + parseInt(style.marginBottom);
       }
       expandBarTmpl.style.height = "calc(100% - " + Math.ceil(btnHeight) + "px)";
      }
      ASPx.GetControlCollection().AdjustControls(expandBar);
     }
     this.expandBarVisible = expandBarVisible;
    }
   }
  },
  raiseCollapsed: function() {
   if(!this.Collapsed.IsEmpty()) {
    var args = new ASPxClientEventArgs();
    this.Collapsed.FireEvent(this, args);
   }
  },
  raiseExpanded: function() {
   if(!this.Expanded.IsEmpty()) {
    var args = new ASPxClientEventArgs();
    this.Expanded.FireEvent(this, args);
   }
  },
  getAnimationContentContainerElement: function() {
   if(!ASPx.IsExistsElement(this.animationContentContainerElement)) 
    this.animationContentContainerElement = ASPx.GetChildByClassName(this.GetMainElement(), "dxpnl-acc");
   return this.animationContentContainerElement;
  },
  getScrollContentContainerElement: function() {
   if (!ASPx.IsExistsElement(this.scrollContentContainerElement)) {
    var mainElement = this.GetMainElement();
    this.scrollContentContainerElement = ASPx.GetNodesByPartialClassName(this.GetMainElement(), "dxpnl-scc")[0];
    if (mainElement.tagName == "DIV" && this.scrollContentContainerElement && this.scrollContentContainerElement.parentNode != mainElement)
     this.scrollContentContainerElement = null;
   }
   return this.scrollContentContainerElement;
  },
  getExpandBarElement: function() {
   if(!ASPx.IsExistsElement(this.expandBarElement))
    this.expandBarElement = ASPx.GetElementById(this.getExpandBarId());
   return this.expandBarElement;
  },
  getExpandBarId: function() {
   return this.name + EXPAND_BAR_ID;
  },
  getModalElement: function() {
   if(!ASPx.IsExistsElement(this.modalElement))
    this.modalElement = ASPx.GetElementById(this.getModalELementId());
   return this.modalElement;
  },
  getModalELementId: function() {
   return this.name + MODAL_ELEMENT_ID;
  },
  getExpandButtonElement: function() {
   if(!ASPx.IsExistsElement(this.expandButtonElement))
    this.expandButtonElement = ASPx.GetElementById(this.name + EXPAND_BUTTON_ID);
   return this.expandButtonElement;
  },
  getFixedElement: function(){
   if(this.getExpandBarElement() && this.isElementDisplayed(this.getExpandBarElement()))
    return this.getExpandBarElement();
   else
    return this.GetMainElement();
  },
  getDocumentPropertyValue: function(attr){
   if(DocumentProperties[attr] === undefined){
    var currentStyle = ASPx.GetCurrentStyle(document.documentElement);
    var attrValue = parseInt(ASPx.Attr.GetAttribute(currentStyle, attr));
    DocumentProperties[attr] = !isNaN(attrValue) ? attrValue : 0;
   }
   return DocumentProperties[attr];
  },
  isElementDisplayed: function(element){
   return ASPx.GetCurrentStyle(element).display != "none";
  }
 });
 ASPxClientPanel.Cast = ASPxClientControl.Cast;
 window.ASPxClientPanelBase = ASPxClientPanelBase;
 window.ASPxClientPanel = ASPxClientPanel;
})();

(function () {
var PopupUtils = {
 NotSetAlignIndicator: "NotSet",
 InnerAlignIndicator: "Sides",
 OutsideLeftAlignIndicator: "OutsideLeft",
 LeftSidesAlignIndicator: "LeftSides",
 RightSidesAlignIndicator: "RightSides",
 OutsideRightAlignIndicator: "OutsideRight",
 CenterAlignIndicator: "Center",
 AboveAlignIndicator: "Above",
 TopSidesAlignIndicator: "TopSides",
 MiddleAlignIndicator: "Middle",
 BottomSidesAlignIndicator: "BottomSides",
 BelowAlignIndicator: "Below",
 WindowCenterAlignIndicator: "WindowCenter",
 LeftAlignIndicator: "Left",
 RightAlignIndicator: "Right",
 TopAlignIndicator: "Top",
 BottomAlignIndicator: "Bottom",
 WindowLeftAlignIndicator: "WindowLeft",
 WindowRightAlignIndicator: "WindowRight",
 WindowTopAlignIndicator: "WindowTop",
 WindowBottomAlignIndicator: "WindowBottom",
 IsAlignNotSet: function (align) {
  return align == PopupUtils.NotSetAlignIndicator;
 },
 IsInnerAlign: function (align) {
  return align.indexOf(PopupUtils.InnerAlignIndicator) != -1;
 },
 IsRightSidesAlign: function(align) {
  return align == PopupUtils.RightSidesAlignIndicator;
 },
 IsOutsideRightAlign: function(align) {
  return align == PopupUtils.OutsideRightAlignIndicator;
 },
 IsCenterAlign: function(align) {
  return align == PopupUtils.CenterAlignIndicator;
 },
 FindPopupElementById: function (id) {
  if(id == "")
   return null; 
  var popupElement = ASPx.GetElementById(id);
  if(!ASPx.IsExistsElement(popupElement)) {
   var idParts = id.split("_");
   var uniqueId = idParts.join("$");
   popupElement = ASPx.GetElementById(uniqueId);
  }
  return popupElement;
 },
 FindEventSourceParentByTestFunc: function (evt, testFunc) {
  return ASPx.GetParent(ASPx.Evt.GetEventSource(evt), testFunc);
 },
 PreventContextMenu: function (evt) {
  ASPx.Evt.PreventEventAndBubble(evt);
  if(ASPx.Browser.WebKitFamily)
   evt.returnValue = false;
 },
 GetDocumentClientWidthForPopup: function() {
  return ASPx.Browser.WebKitTouchUI ? document.body.offsetWidth : ASPx.GetDocumentClientWidth();
 },
 GetDocumentClientHeightForPopup: function() {
  return ASPx.Browser.WebKitTouchUI ? document.body.offsetHeight : ASPx.GetDocumentClientHeight();
 },
 AdjustPositionToClientScreen: function (element, pos, rtl, isX) {
  var min = isX ? ASPx.GetDocumentScrollLeft() : ASPx.GetDocumentScrollTop(),
   max = min + (isX ? ASPx.GetDocumentClientWidth() : ASPx.GetDocumentClientHeight());
  max -= (isX ? element.offsetWidth : element.offsetHeight);
  if(rtl && isX) {
   if(pos < min) pos = min;
   if(pos > max) pos = max;
  } else {
   if(pos > max) pos = max;
   if(pos < min) pos = min;
  }
  return pos;
 },
 GetPopupAbsoluteX: function(element, popupElement, hAlign, hOffset, x, left, rtl, isPopupFullCorrectionOn, showPopupInsideScreenBounds) {
  return PopupUtils.getPopupAbsolutePos(element, popupElement, hAlign, hOffset, x, left, rtl, isPopupFullCorrectionOn, false, false, true, showPopupInsideScreenBounds);
 },
 GetPopupAbsoluteY: function(element, popupElement, vAlign, vOffset, y, top, isPopupFullCorrectionOn, ignoreAlignWithoutScrollReserve, ignorePopupElementBorders, showPopupInsideScreenBounds) {
  return PopupUtils.getPopupAbsolutePos(element, popupElement, vAlign, vOffset, y, top, false, isPopupFullCorrectionOn, ignoreAlignWithoutScrollReserve, ignorePopupElementBorders, false, showPopupInsideScreenBounds);
 },
 getPopupAbsolutePos: function(element, popupElement, align, offset, startPos, startPosInit, rtl, isPopupFullCorrectionOn, ignoreAlignWithoutScrollReserve, ignorePopupElementBorders, isHorizontal, showPopupInsideScreenBounds) {
  var calculator = getPositionCalculator();
  calculator.applyParams(element, popupElement, align, offset, startPos, startPosInit, rtl, isPopupFullCorrectionOn, ignoreAlignWithoutScrollReserve, ignorePopupElementBorders, isHorizontal, showPopupInsideScreenBounds);
  var position = calculator.getPopupAbsolutePos();
  calculator.disposeState();
  return position;
 },
 InitAnimationProperties: function(element, onAnimStopCallString) {
  element.popuping = true;
  element.onAnimStopCallString = onAnimStopCallString;
 },
 InitAnimationDiv: function (element, x, y, onAnimStopCallString, skipSizeInit) {
  PopupUtils.InitAnimationProperties(element, onAnimStopCallString);
  PopupUtils.InitAnimationDivCore(element);
  if(!skipSizeInit) {
   ASPx.SetStyles(element, { width: "", height: "" });
   ASPx.SetStyles(element, { width: element.offsetWidth, height: element.offsetHeight });
  }
  ASPx.SetStyles(element, { left: x, top: y });
 },
 InitAnimationDivCore: function (element) {
  ASPx.SetStyles(element, {
   overflow: "hidden",
   position: "absolute"
  });
 },
 StartSlideAnimation: function (animationDivElement, element, iframeElement, duration, preventChangingWidth, preventChangingHeight) {
  if(iframeElement) {
   var endLeft = ASPx.PxToInt(iframeElement.style.left);
   var endTop = ASPx.PxToInt(iframeElement.style.top);
   var startLeft = ASPx.PxToInt(element.style.left) < 0 ? endLeft : animationDivElement.offsetLeft + animationDivElement.offsetWidth;
   var startTop = ASPx.PxToInt(element.style.top) < 0 ? endTop : animationDivElement.offsetTop + animationDivElement.offsetHeight;
   var properties = {
    left: { from: startLeft, to: endLeft, unit: "px" },
    top: { from: startTop, to: endTop, unit: "px" }
   };
   if(!preventChangingWidth)
    properties.width = { to: element.offsetWidth, unit: "px" };
   if(!preventChangingHeight)
    properties.height = { to: element.offsetHeight, unit: "px" };
   ASPx.AnimationHelper.createMultipleAnimationTransition(iframeElement, {
    duration: duration
   }).Start(properties);
  }
  ASPx.AnimationHelper.createMultipleAnimationTransition(element, {
   duration: duration,
   onComplete: function () { PopupUtils.AnimationFinished(animationDivElement, element); }
  }).Start({
   left: { to: 0, unit: "px" },
   top: { to: 0, unit: "px" }
  });
 },
 AnimationFinished: function (animationDivElement, element) {
  if(PopupUtils.StopAnimation(animationDivElement, element) && ASPx.IsExists(animationDivElement.onAnimStopCallString) &&
   animationDivElement.onAnimStopCallString !== "") {
   window.setTimeout(animationDivElement.onAnimStopCallString, 0);
  }
 },
 StopAnimation: function (animationDivElement, element) {
  if(animationDivElement.popuping) {
   ASPx.AnimationHelper.cancelAnimation(element);
   animationDivElement.popuping = false;
   animationDivElement.style.overflow = "visible";
   return true;
  }
  return false;
 },
 GetAnimationHorizontalDirection: function (popupPosition, horizontalAlign, verticalAlign, rtl) {
  if(PopupUtils.IsInnerAlign(horizontalAlign)
   && !PopupUtils.IsInnerAlign(verticalAlign)
   && !PopupUtils.IsAlignNotSet(verticalAlign))
   return 0;
  var toTheLeft = (horizontalAlign == PopupUtils.OutsideLeftAlignIndicator || horizontalAlign == PopupUtils.RightSidesAlignIndicator || (horizontalAlign == PopupUtils.NotSetAlignIndicator && rtl)) ^ popupPosition.isInverted;
  return toTheLeft ? 1 : -1;
 },
 GetAnimationVerticalDirection: function (popupPosition, horizontalAlign, verticalAlign) {
  if(PopupUtils.IsInnerAlign(verticalAlign)
   && !PopupUtils.IsInnerAlign(horizontalAlign)
   && !PopupUtils.IsAlignNotSet(horizontalAlign))
   return 0;
  var toTheTop = (verticalAlign == PopupUtils.AboveAlignIndicator || verticalAlign == PopupUtils.BottomSidesAlignIndicator) ^ popupPosition.isInverted;
  return toTheTop ? 1 : -1;
 },
 IsVerticalScrollExists: function () {
  var scrollIsNotHidden = ASPx.GetCurrentStyle(document.body).overflowY !== "hidden" && ASPx.GetCurrentStyle(document.documentElement).overflowY !== "hidden";
  return (scrollIsNotHidden && ASPx.GetDocumentHeight() > ASPx.GetDocumentClientHeight());
 },
 CoordinatesInDocumentRect: function (x, y) {
  var docScrollLeft = ASPx.GetDocumentScrollLeft();
  var docScrollTop = ASPx.GetDocumentScrollTop();
  return (x > docScrollLeft && y > docScrollTop &&
   x < ASPx.GetDocumentClientWidth() + docScrollLeft &&
   y < ASPx.GetDocumentClientHeight() + docScrollTop);
 },
 GetElementZIndexArray: function (element) {
  var currentElement = element;
  var zIndexesArray = [0];
  while(currentElement && currentElement.tagName != "BODY") {
   if(currentElement.style) {
    if(typeof (currentElement.style.zIndex) != "undefined" && currentElement.style.zIndex != "")
     zIndexesArray.unshift(currentElement.style.zIndex);
   }
   currentElement = currentElement.parentNode;
  }
  return zIndexesArray;
 },
 IsHigher: function (higherZIndexArrat, zIndexArray) {
  if(zIndexArray == null) return true;
  var count = (higherZIndexArrat.length >= zIndexArray.length) ? higherZIndexArrat.length : zIndexArray.length;
  for(var i = 0; i < count; i++)
   if(typeof (higherZIndexArrat[i]) != "undefined" && typeof (zIndexArray[i]) != "undefined") {
    var higherZIndexArrayCurrentElement = parseInt(higherZIndexArrat[i].toString());
    var zIndexArrayCurrentElement = parseInt(zIndexArray[i].toString());
    if(higherZIndexArrayCurrentElement != zIndexArrayCurrentElement)
     return higherZIndexArrayCurrentElement > zIndexArrayCurrentElement;
   } else return typeof (zIndexArray[i]) == "undefined";
  return true;
 },
 TestIsPopupElement: function (element) {
  return !!element.DXPopupElementControl;
 },
 adjustViewportScrollWrapper: function(wrapper, wrapperScroll, windowElement) {
  var document = wrapper.ownerDocument;
  var window = document.defaultView || document.parentWindow;
  var isWindowElementDisplayed = ASPx.IsElementDisplayed(windowElement);
  if(!isWindowElementDisplayed) {
   wrapper.style.cssText = "";
   wrapperScroll.style.cssText = "";
   return; 
  }
  var windowRect = windowElement.getBoundingClientRect();
  var yAxis = this.calculateViewPortScrollDataByAxis(wrapper.style.top, windowRect.top, windowElement.offsetHeight, window.innerHeight, wrapper.scrollTop);
  var xAxis = this.calculateViewPortScrollDataByAxis(wrapper.style.left, windowRect.left, windowElement.offsetWidth, window.innerWidth, wrapper.scrollLeft);
  this.prepareViewPortScrollData(xAxis, yAxis);
  ASPx.SetStyles(windowElement, {
   top: yAxis.windowOffset,
   left: xAxis.windowOffset
  });
  ASPx.SetStyles(wrapper, {
   width: xAxis.wrapperSize,
   height: yAxis.wrapperSize,
   position: "absolute",
   overflow: ASPx.Browser.MobileUI ? "scroll" : "auto",
   zIndex: windowElement.style.zIndex
  });
  ASPx.SetAbsoluteX(wrapper, ASPx.GetDocumentScrollLeft());
  ASPx.SetAbsoluteY(wrapper, ASPx.GetDocumentScrollTop());
  ASPx.SetStyles(wrapperScroll, {
   width: xAxis.wrapperScrollSize,
   height: yAxis.wrapperScrollSize,
   position: "absolute",
   overflow: "hidden"
  });
  wrapper.scrollLeft = xAxis.scrollSize;
  wrapper.scrollTop = yAxis.scrollSize;
 },
 calculateViewPortScrollDataByAxis: function(wrapperOffsetStyle, windowOffset, windowSize, viewPortSize, scrollSize) {
  var isWindowOffsetNegative = windowOffset < 0;
  windowOffset = isWindowOffsetNegative ? 0 : windowOffset;
  var wrapperScrollSize = Math.max(viewPortSize + Math.abs(Math.min(0, windowOffset)), windowSize + Math.abs(windowOffset));
  return { 
   windowOffset: isWindowOffsetNegative ? 0 : windowOffset,
   wrapperSize: viewPortSize,
   wrapperScrollSize: wrapperScrollSize,
   scrollSize: isWindowOffsetNegative ? scrollSize + Math.abs(windowOffset) : 0,
   hasScroll: wrapperScrollSize > viewPortSize
  };
 },
 prepareViewPortScrollData: function(xAxis, yAxis) {
  var scrollBarSize = ASPx.GetVerticalScrollBarWidth();
  if(yAxis.hasScroll && !xAxis.hasScroll) {
   xAxis.wrapperScrollSize = Math.min(xAxis.wrapperSize - scrollBarSize, xAxis.wrapperScrollSize);
  } else if(xAxis.hasScroll && !yAxis.hasScroll) {
   yAxis.wrapperScrollSize = Math.min(yAxis.wrapperSize - scrollBarSize, yAxis.wrapperScrollSize);
  } else if(yAxis.hasScroll && xAxis.hasScroll) {
   yAxis.wrapperScrollSize -= scrollBarSize;
   xAxis.wrapperScrollSize -= scrollBarSize;
  }
 }
};
PopupUtils.OverControl = {
 GetPopupElementByEvt: function (evt) {
  return PopupUtils.FindEventSourceParentByTestFunc(evt, PopupUtils.TestIsPopupElement);
 },
 OnMouseEvent: function (evt, mouseOver) {
  var popupElement = PopupUtils.OverControl.GetPopupElementByEvt(evt);
  if(mouseOver)
   popupElement.DXPopupElementControl.OnPopupElementMouseOver(evt, popupElement);
  else
   popupElement.DXPopupElementControl.OnPopupElementMouseOut(evt, popupElement);
 },
 OnMouseOut: function (evt) {
  PopupUtils.OverControl.OnMouseEvent(evt, false);
 },
 OnMouseOver: function (evt) {
  PopupUtils.OverControl.OnMouseEvent(evt, true);
 }
};
PopupUtils.BodyScrollHelper = (function () {
 var windowScrollLock = {},
  windowScroll = {},
  hideScrollbarsClassName = "dxpc-hideScrollbars";
 function lockWindowScroll(windowId) {
  windowScrollLock[windowId] = true;
 }
 function unlockWindowScroll(windowId) {
  delete windowScrollLock[windowId];
 }
 function isLocked(windowId) {
  return !!windowScrollLock[windowId];
 }
 function isAnyWindowScrollLocked() {
  for(var key in windowScrollLock) 
   if (windowScrollLock.hasOwnProperty(key) && windowScrollLock[key] === true)
    return true;
  return false;
 }
 function replaceVerticalScrollByPadding() {
  var currentBodyStyle = ASPx.GetCurrentStyle(document.body),
   paddingWidth = ASPx.GetVerticalScrollBarWidth() + ASPx.PxToInt(currentBodyStyle.paddingRight);
  ASPx.Attr.ChangeStyleAttribute(document.body, "padding-right", paddingWidth + "px");
 }
 function changeOverflow() {
  ASPx.Attr.ChangeStyleAttribute(document.documentElement, "overflow", "hidden");
  if(ASPx.GetCurrentStyle(document.body).overflowY === "scroll")
   ASPx.Attr.ChangeStyleAttribute(document.body, "overflow", "hidden");
  resetOverflowCache();
 }
 function restoreOverflow() {
  ASPx.Attr.RestoreStyleAttribute(document.documentElement, "overflow");
  ASPx.Attr.RestoreStyleAttribute(document.body, "overflow");
  resetOverflowCache();
 }
 function resetOverflowCache() {
  ASPx.verticalScrollIsNotHidden = null;
  ASPx.horizontalScrollIsNotHidden = null;
 }
 function saveScrollPosition(windowId) {
  windowScroll[windowId] = {
   x: window.pageXOffset,
   y: window.pageYOffset
  };
 }
 function restoreScrollPosition(windowId) {
  var currentWindowScroll = windowScroll[windowId];
  if(!!currentWindowScroll)
   window.scrollTo(currentWindowScroll.x, currentWindowScroll.y);
 }
 function restoreBodyScroll(windowId) {
  unlockWindowScroll(windowId);
  if(isAnyWindowScrollLocked())
   return;
  if(ASPx.Browser.WebKitTouchUI) {
   ASPx.Attr.RestoreStyleAttribute(document.body, "position");
   ASPx.Attr.RestoreStyleAttribute(document.body, "height");
   ASPx.Attr.RestoreStyleAttribute(document.body, "margin");
   ASPx.RemoveClassNameFromElement(document.documentElement, hideScrollbarsClassName);
   ASPx.Attr.RestoreStyleAttribute(document.body, "overflow");
   restoreScrollPosition(windowId);
  } else {
   restoreOverflow();
   restoreScrollPosition(windowId);
  }
  if(ASPx.Browser.Chrome)
   var dummy = document.documentElement.scrollTop; 
  ASPx.Attr.RestoreStyleAttribute(document.body, "padding-right");
  ASPx.Attr.RestoreStyleAttribute(document.body, "height");
  ASPx.Attr.RestoreStyleAttribute(document.body, "width");
 }
 return {
  RestoreIfLocked: function(windowId) {
   if(isLocked(windowId))
    restoreBodyScroll(windowId);
  },
  HideBodyScroll: function(windowId) {
   if(isAnyWindowScrollLocked()) { 
    lockWindowScroll(windowId);
    return;
   }
   lockWindowScroll(windowId);
   if(PopupUtils.IsVerticalScrollExists())
    replaceVerticalScrollByPadding();
   if(ASPx.Browser.WebKitTouchUI) {
    saveScrollPosition(windowId);
    ASPx.Attr.ChangeStyleAttribute(document.body, "overflow", "hidden");
    ASPx.Attr.ChangeStyleAttribute(document.body, "position", "relative");
    ASPx.Attr.ChangeStyleAttribute(document.body, "height", "100%");
    ASPx.Attr.ChangeStyleAttribute(document.body, "margin", "0");
    ASPx.AddClassNameToElement(document.documentElement, hideScrollbarsClassName);
   } else {
    saveScrollPosition(windowId);
    changeOverflow();
    var documentHeight = ASPx.GetDocumentHeight();
    var documentWidth = ASPx.GetDocumentWidth();
    if(window.pageYOffset > 0 && ASPx.PxToInt(window.getComputedStyle(document.body, null)) != documentHeight)
     ASPx.Attr.ChangeStyleAttribute(document.body, "height", documentHeight + "px");
    if(window.pageXOffset > 0 && ASPx.PxToInt(window.getComputedStyle(document.body, null)) != documentWidth)
     ASPx.Attr.ChangeStyleAttribute(document.body, "width", documentWidth + "px");
   }
  },
  RestoreBodyScroll: restoreBodyScroll
 };
})();
var PositionAlignConsts = {
 NOT_SET: 0,
 OUTSIDE_START: 1,
 NEAR_BOUND_START: 2,
 INNER_START: 3,
 CENTER: 4,
 INNER_END: 5,
 NEAR_BOUND_END: 6,
 OUTSIDE_END: 7,
 WINDOW_CENTER: 8,
 WINDOW_START: 9,
 WINDOW_END: 10
};
var AlignIndicatorTable = {};
var PositionCalculator = ASPx.CreateClass(null, {
 constructor: function() {
  this.element = null;
  this.popupElement = null;
  this.align = 0;
  this.offset = 0;
  this.startPos = 0;
  this.startPosInit = 0;
  this.rtl = false;
  this.isPopupFullCorrectionOn = false;
  this.isHorizontal = true;
  this.size = 0;
  this.bodySize = 0;
  this.actualBodySize = 0;
  this.elementStartPos = 0;
  this.scrollStartPos = 0;
  this.isInverted = false;
  this.popupElementSize = 0;
  this.boundStartPos = 0;
  this.boundEndPos = 0;
  this.innerBoundStartPos = 0;
  this.innerBoundEndPos = 0;
  this.isMoreFreeSpaceLeft = false;
  this.nearBoundOverlapRate = 0.25;
  this.functionsTable = {};
  this.initializeFunctionsTable();
 },
 applyParams: function(element, popupElement, align, offset, startPos, startPosInit, rtl, isPopupFullCorrectionOn, ignoreAlignWithoutScrollReserve, ignorePopupElementBorders, isHorizontal, showPopupInsideScreenBounds) {
  this.isHorizontal = isHorizontal;
  this.element = element;
  this.popupElement = popupElement;
  this.align = this.getAlignValueFromIndicator(align);
  this.offset = offset;
  this.startPos = startPos;
  this.startPosInit = startPosInit;
  this.rtl = rtl;
  this.isPopupFullCorrectionOn = isPopupFullCorrectionOn;
  this.ignoreAlignWithoutScrollReserve = ignoreAlignWithoutScrollReserve;
  this.ignorePopupElementBorders = ignorePopupElementBorders;
  this.showPopupInsideScreenBounds = showPopupInsideScreenBounds;
  this.calculateParams();
 },
 disposeState: function() {
  this.element = null;
  this.popupElement = null;
 },
 getPopupAbsolutePos: function() {
  if(this.isWindowAlign()) {
   var showAtPos = this.startPos != ASPx.InvalidPosition && !this.popupElement;
   if(showAtPos)
    this.align = PositionAlignConsts.NOT_SET;
   else
    return this.getWindowAlignPos();
  }
  if(this.popupElement)
   this.calculatePopupElement();
  else
   this.align = PositionAlignConsts.NOT_SET;
  return this.getPopupAbsolutePosCore();
 },
 initializeFunctionsTable: function() {
  var table = this.functionsTable;
  table[PositionAlignConsts.NOT_SET] = this.calculateNotSet;
  table[PositionAlignConsts.OUTSIDE_START] = this.calculateOutsideStart;
  table[PositionAlignConsts.INNER_START] = this.calculateInnerStart;
  table[PositionAlignConsts.CENTER] = this.calculateCenter;
  table[PositionAlignConsts.INNER_END] = this.calculateInnerEnd;
  table[PositionAlignConsts.OUTSIDE_END] = this.calculateOutsideEnd;
  table[PositionAlignConsts.NEAR_BOUND_START] = this.calculateNearBoundStart;
  table[PositionAlignConsts.NEAR_BOUND_END] = this.calculateNearBoundEnd;
  table[PositionAlignConsts.WINDOW_CENTER] = this.calculateWindowCenter;
  table[PositionAlignConsts.WINDOW_START] = this.calculateWindowStart;
  table[PositionAlignConsts.WINDOW_END] = this.calculateWindowEnd;
 },
 calculateParams: function() {
  this.size = this.getElementSize();
  if(this.isHorizontal) {
   this.bodySize = ASPx.GetDocumentClientWidth();
   this.elementStartPos = ASPx.GetAbsoluteX(this.popupElement) + this.getBorderCorrection();
   this.scrollStartPos = ASPx.GetDocumentScrollLeft();
  }
  else {
   this.bodySize = ASPx.GetDocumentClientHeight();
   this.elementStartPos = ASPx.GetAbsoluteY(this.popupElement) + this.getBorderCorrection();
   this.scrollStartPos = ASPx.GetDocumentScrollTop();
  }
 },
 getBorderCorrection: function() {
  if(!this.ignorePopupElementBorders)
   return 0;
  var style = getComputedStyle(this.popupElement);
  return ASPx.PxToInt(this.isHorizontal ? style.borderLeftWidth : style.borderTopWidth);
 },
 isWindowAlign: function() {
  return this.align == PositionAlignConsts.WINDOW_CENTER || this.align == PositionAlignConsts.WINDOW_START ||
   this.align == PositionAlignConsts.WINDOW_END;
 },
 getWindowAlignPos: function() {
  this.actualBodySize = ASPx.Browser.WebKitTouchUI ? this.getWindowInnerSize() : this.bodySize;
  return this.getPopupAbsolutePosCore();
 },
 getPopupAbsolutePosCore: function() {
  var calculationFunc = this.functionsTable[this.align];
  calculationFunc.call(this);
  return new ASPx.PopupPosition(this.startPos, this.isInverted);
 },
 calculateWindowCenter: function() {
  this.startPos = Math.max(Math.ceil(this.actualBodySize / 2 - this.size / 2), 0) + this.scrollStartPos + this.offset;
 },
 calculateWindowStart: function() {
  this.startPos = this.scrollStartPos + this.offset;
 },
 calculateWindowEnd: function() {
  this.startPos = this.scrollStartPos + this.actualBodySize - this.size + this.offset;
 },
 calculatePopupElement: function() {
  this.popupElementSize = this.getPopupElementSize();
  this.boundStartPos = this.elementStartPos - this.size;
  this.boundEndPos = this.elementStartPos + this.popupElementSize;
  this.innerBoundStartPos = this.elementStartPos;
  this.innerBoundEndPos = this.elementStartPos + this.popupElementSize - this.size;
  var hasLeftScrollReserve = this.boundStartPos >= 0;
  this.isMoreFreeSpaceLeft = (this.bodySize - (this.boundEndPos + this.size) < this.boundStartPos - 2 * this.scrollStartPos) && (!this.ignoreAlignWithoutScrollReserve || hasLeftScrollReserve);
 },
 calculateOutsideStart: function() {
  this.isInverted = this.isPopupFullCorrectionOn && (!(this.boundStartPos - this.scrollStartPos > 0 || this.isMoreFreeSpaceLeft));
  if(this.isInverted)
   this.startPos = this.boundEndPos - this.offset;
  else
   this.startPos = this.boundStartPos + this.offset;
 },
 calculateInnerStart: function() {
  this.startPos = this.innerBoundStartPos + this.offset;
  if(this.isPopupFullCorrectionOn)
   this.startPos = PopupUtils.AdjustPositionToClientScreen(this.element, this.startPos, this.rtl, this.isHorizontal);
 },
 calculateCenter: function() {
  this.startPos = this.elementStartPos + Math.round((this.popupElementSize - this.size) / 2) + this.offset;
  if(this.showPopupInsideScreenBounds) {
   if(this.startPos < 0)
    this.startPos = 0;
   if(this.startPos + this.size > this.bodySize)
    this.startPos = this.bodySize - this.size;
  }
 },
 calculateInnerEnd: function() {
  this.startPos = this.innerBoundEndPos + this.offset;
  if(this.isPopupFullCorrectionOn)
   this.startPos = PopupUtils.AdjustPositionToClientScreen(this.element, this.startPos, this.rtl, this.isHorizontal);
 },
 calculateOutsideEnd: function() {
  this.isInverted = this.isPopupFullCorrectionOn && (!(this.boundEndPos + this.size < this.bodySize + this.scrollStartPos || !this.isMoreFreeSpaceLeft));
  if(this.isInverted)
   this.startPos = this.boundStartPos - this.offset;
  else
   this.startPos = this.boundEndPos + this.offset;
 },
 calculateNotSet: function() {
  if(this.rtl)
   this.calculateNotSetRightToLeft();
  else
   this.calculateNotSetLeftToRight();
 },
 calculateNotSetLeftToRight: function() {
  if(!ASPx.IsValidPosition(this.startPos)) {
   if(this.popupElement)
    this.startPos = this.elementStartPos;
   else if(this.offset)
    this.startPos = 0;
   else
    this.startPos = this.startPosInit;
  }
  this.isInverted = this.isPopupFullCorrectionOn && (this.startPos - this.scrollStartPos + this.size > this.bodySize && this.startPos - this.scrollStartPos > this.bodySize / 2);
  if(this.isInverted)
   this.startPos = this.startPos - this.size - this.offset;
  else
   this.startPos = this.startPos + this.offset;
 },
 calculateNotSetRightToLeft: function() {
  if(!ASPx.IsValidPosition(this.startPos)) {
   if(this.popupElement)
    this.startPos = this.innerBoundEndPos;
   else if(this.offset)
    this.startPos = 0;
   else
    this.startPos = this.startPosInit;
  }
  else
   this.startPos -= this.size;
  this.isInverted = this.isPopupFullCorrectionOn && (this.startPos < this.scrollStartPos && this.startPos - this.scrollStartPos < this.bodySize / 2);
  if(this.isInverted)
   this.startPos = this.startPos + this.size + this.offset;
  else
   this.startPos = this.startPos - this.offset;
 },
 calculateNearBoundStart: function() {
  this.startPos = this.boundStartPos + this.offset + this.size * this.nearBoundOverlapRate;
  if(this.isPopupFullCorrectionOn)
   this.startPos = PopupUtils.AdjustPositionToClientScreen(this.element, this.startPos, this.rtl, this.isHorizontal);
 },
 calculateNearBoundEnd: function() {
  this.startPos = this.boundEndPos + this.offset - this.size * this.nearBoundOverlapRate;
  if(this.isPopupFullCorrectionOn)
   this.startPos = PopupUtils.AdjustPositionToClientScreen(this.element, this.startPos, this.rtl, this.isHorizontal);
 },
 getAlignValueFromIndicator: function(alignIndicator) {
  var alignValue = AlignIndicatorTable[alignIndicator];
  if(alignValue === undefined)
   throw "Incorrect align indicator.";
  return alignValue;
 },
 getElementSize: function() {
  return this.getCustomElementSize(this.element, false);
 },
 getPopupElementSize: function() {
  return this.getCustomElementSize(this.popupElement, this.ignorePopupElementBorders);
 },
 getCustomElementSize: function(customElement, ignoreBorders) {
  if(ignoreBorders) {
   return this.isHorizontal ? ASPx.GetClearClientWidth(customElement) : ASPx.GetClearClientHeight(customElement);
  }
  return this.isHorizontal ? ASPx.GetElementOffsetWidth(customElement) : ASPx.GetElementOffsetHeight(customElement);
 },
 getWindowInnerSize: function() {
  return this.isHorizontal ? window.innerWidth : window.innerHeight;
 }
});
var positionCalculator = null;
function getPositionCalculator() {
 if(positionCalculator == null)
  positionCalculator = new PositionCalculator();
 return positionCalculator;
}
function initializeAlignIndicatorTable() {
 AlignIndicatorTable[PopupUtils.NotSetAlignIndicator] = PositionAlignConsts.NOT_SET;
 AlignIndicatorTable[PopupUtils.OutsideLeftAlignIndicator] = PositionAlignConsts.OUTSIDE_START;
 AlignIndicatorTable[PopupUtils.AboveAlignIndicator] = PositionAlignConsts.OUTSIDE_START;
 AlignIndicatorTable[PopupUtils.LeftAlignIndicator] = PositionAlignConsts.NEAR_BOUND_START;
 AlignIndicatorTable[PopupUtils.TopAlignIndicator] = PositionAlignConsts.NEAR_BOUND_START;
 AlignIndicatorTable[PopupUtils.LeftSidesAlignIndicator] = PositionAlignConsts.INNER_START;
 AlignIndicatorTable[PopupUtils.TopSidesAlignIndicator] = PositionAlignConsts.INNER_START;
 AlignIndicatorTable[PopupUtils.CenterAlignIndicator] = PositionAlignConsts.CENTER;
 AlignIndicatorTable[PopupUtils.MiddleAlignIndicator] = PositionAlignConsts.CENTER;
 AlignIndicatorTable[PopupUtils.RightSidesAlignIndicator] = PositionAlignConsts.INNER_END;
 AlignIndicatorTable[PopupUtils.BottomSidesAlignIndicator] = PositionAlignConsts.INNER_END;
 AlignIndicatorTable[PopupUtils.RightAlignIndicator] = PositionAlignConsts.NEAR_BOUND_END;
 AlignIndicatorTable[PopupUtils.BottomAlignIndicator] = PositionAlignConsts.NEAR_BOUND_END;
 AlignIndicatorTable[PopupUtils.OutsideRightAlignIndicator] = PositionAlignConsts.OUTSIDE_END;
 AlignIndicatorTable[PopupUtils.BelowAlignIndicator] = PositionAlignConsts.OUTSIDE_END;
 AlignIndicatorTable[PopupUtils.WindowCenterAlignIndicator] = PositionAlignConsts.WINDOW_CENTER;
 AlignIndicatorTable[PopupUtils.WindowLeftAlignIndicator] = PositionAlignConsts.WINDOW_START;
 AlignIndicatorTable[PopupUtils.WindowTopAlignIndicator] = PositionAlignConsts.WINDOW_START;
 AlignIndicatorTable[PopupUtils.WindowRightAlignIndicator] = PositionAlignConsts.WINDOW_END;
 AlignIndicatorTable[PopupUtils.WindowBottomAlignIndicator] = PositionAlignConsts.WINDOW_END;
}
initializeAlignIndicatorTable();
ASPx.PopupPosition = function(position, isInverted) {
 this.position = position;
 this.isInverted = isInverted;
};
ASPx.PopupSize = function(width, height) {
 this.width = width;
 this.height = height;
};
ASPx.PopupUtils = PopupUtils;
ASPx.PositionCalculator = PositionCalculator;
})();

(function () {
ASPxClientCallbackPanel = ASPx.CreateClass(ASPxClientPanel, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.hideContentOnCallback = true;
  this.isLoadingPanelTextEmpty = false;
 },
 OnCallback: function (result) {
  ASPx.SetInnerHtml(this.getContentElement(), result);
  if(this.touchUIScroller)
   this.touchUIScroller.ChangeElement(this.getContentElement());
 },
 ShowLoadingPanel: function () {
  var element = this.getContentElement();
  var mainElement = (element.tagName == "TD") ? this.GetMainElement() : element;
  if(!this.hideContentOnCallback)
   this.CreateLoadingPanelWithAbsolutePosition(this.GetMainElement().parentNode, mainElement);
  else
   this.CreateLoadingPanelInsideContainer(element, true, true, false);
 },
 ShowLoadingDiv: function () {
  this.CreateLoadingDiv(this.GetMainElement().parentNode, this.getContentElement());
 },
 GetCallbackAnimationElement: function() {
  return this.getContentElement();
 },
 PerformCallback: function (parameter, onSuccess) {
  this.CreateCallback(parameter, null, null, onSuccess);
 },
 CreateCallback: function (arg, command, callbackInfo, handler) {
  this.ShowLoadingElements();
  ASPxClientControl.prototype.CreateCallback.call(this, arg, command, handler);
 },
 GetLoadingPanelTextLabelID: function () {
  return this.name + "_TL";
 },
 GetLoadingPanelTextLabel: function () {
  return ASPx.GetElementById(this.GetLoadingPanelTextLabelID());
 },
 GetClonedLoadingPanelTextLabel: function() {
  var clonedLoadingPanel = this.GetClonedLoadingPanel();
  return clonedLoadingPanel ? clonedLoadingPanel.querySelector("#" + this.GetLoadingPanelTextLabelID()) : null;
 },
 GetLoadingPanelText: function () {
  var textLabel = this.GetLoadingPanelTextLabel();
  if(textLabel && !this.isLoadingPanelTextEmpty)
   return textLabel.innerHTML;
  return "";
 },
 SetLoadingPanelText: function(text) {
  this.isLoadingPanelTextEmpty = text == null || text == "";
  var loadingPanelTextHtml = this.isLoadingPanelTextEmpty ? "&nbsp;" : text; 
  var textLabel = this.GetLoadingPanelTextLabel();
  if(textLabel)
   textLabel.innerHTML = loadingPanelTextHtml;
  textLabel = this.GetClonedLoadingPanelTextLabel();
  if(textLabel)
   textLabel.innerHTML = loadingPanelTextHtml;
 },
 SetContentHtml: function (html, useAnimation) {
  ASPxClientPanel.prototype.SetContentHtml.call(this, html);
  if(useAnimation && typeof(ASPx.AnimationHelper) != "undefined")
   ASPx.AnimationHelper.fadeIn(this.getContentElement());
 }
});
ASPxClientCallbackPanel.Cast = ASPxClientControl.Cast;
window.ASPxClientCallbackPanel = ASPxClientCallbackPanel;
})();
var MVCx = {};
(function(jQuery) {
var RunStartupScriptBlockID = "dxrssb";
var $ = jQuery;
MVCx.CallbackHtmlContentPrefix = "/*DXHTML*/";
MVCx.CallbackHtmlContentPlaceholder = "<%html%>";
MVCx.EditorsValuesKey = "DXMVCEditorsValues";
MVCx.ScriptNames = {
 MicrosoftMvcAjax: 'Microsoft Mvc Ajax',
 JQuery: 'jQuery',
 JQueryValidation: 'jQuery Validation',
 JQueryUnobtrusiveValidation: 'jQuery Unobtrusive Validation'
};
MVCx.PerformControlCallback = function(name, url, arg, params, customParams) {
 if(ASPx.GetPostHandler().cancelPostProcessing)
  return;
 var data = {};
 data.DXCallbackName = name;
 data["__DXCallbackArgument"] = arg;
 ASPx.Data.MergeHashTables(data, params);
 ASPx.Data.MergeHashTables(data, customParams);
 $.ajax({
  type: 'POST',
  url: url,
  dataType: 'html',
  data: data,
  error: function(response) {
   var ctrl = ASPx.GetControlCollection().Get(data.DXCallbackName);
   if (ctrl != null) {
    var text = "";
    var handler = ASPx.GetPostHandler();    
    if(handler && handler.HasAppErrorOnCallback(response))
     text = handler.GetServerErrorText();
    else if(typeof(response.responseText) == "string" && response.responseText != "")
     text = response.responseText;     
    else if(typeof(response) == "string" && response != "")
     text = response;
    if(text)
     ctrl.DoCallbackError(text);
   }
  },
  success: function(response) {
   var ctrl = ASPx.GetControlCollection().Get(data.DXCallbackName);
   if (ctrl != null) ctrl.DoCallback(response);
  }
 });
};
MVCx.ThrowExceptionOnCallback = function() {
 ASPx.ShowKBErrorMessage("Invalid server response. It is required that a Partial View contains only the extension definition code, without any additional markup. To learn more, see ", "KA20010");
};
MVCx.IsCustomCallback = function(command) {
 return command && command.toUpperCase() == "CUSTOMCALLBACK";
};
MVCx.IsCustomDataCallback = function(command) {
 var commandInUpperCase = command.toUpperCase();
 return commandInUpperCase == "CUSTOMDATACALLBACK" || commandInUpperCase == "CUSTOMVALUES";
};
MVCx.GetCustomActionCallBackMethod = function(control) {
 return control.customActionCallBack || control.callBack;
};
MVCx.AddCallbackParam = function(params, input) {
 if(!params || !input || input.name == "undefined") return;
 if(params.hasOwnProperty(input.name))
  return;
 switch(input.type) {
  case "checkbox":
   params[input.name] = input.checked;
   break;
  case "radio":
   if(input.checked)
    params[input.name] = input.value;
   break;
  case "select-multiple":
   var values = $(input).val() || [];
   params[input.name] = values.join ? values.join(',') : values;
   break;
  default:
   params[input.name] = input.value;
 }
};
MVCx.AddCallbackParamsInContainer = function(params, container, addEditorValuePredicate) {
 if(!params || !container) return;
 var requireCollectEditorValues = true;
 var dxEditorValues = { };
 var $form = $(container).closest("form");
 if($form.length > 0){
  dxEditorValues = GetCachedVisibleEditorValues($form[0].DXEditorValues, addEditorValuePredicate);
  requireCollectEditorValues = false;
 }
 $(container).find("input,textarea,select").each(function() {
  if(addEditorValuePredicate && !addEditorValuePredicate(this, null))
   return;
  MVCx.AddCallbackParam(params, this);
  if(requireCollectEditorValues){
   var dxEditor = ASPx.GetControlCollection().Get(this.name);
   if(IsPossiblePassEditorValue(dxEditor))
    dxEditorValues[this.name] = MVCx.GetEditorValueByControl(dxEditor);
  }
 });
 params[MVCx.EditorsValuesKey] = ASPx.Json.ToJson(dxEditorValues);
};
MVCx.AddDXEditorValuesInContainer = function(params, container, addEditorValuePredicate) {
 if(!params || !container || !ASPx.ProcessEditorsInContainer)
  return;
 var editorValues = {};
 ASPx.ProcessEditorsInContainer(container, function(control) {
  if(!addEditorValuePredicate || addEditorValuePredicate(null, control))
   editorValues[control.name] = MVCx.GetEditorValueByControl(control);
  return true;
 }, null, null, true, false);
 params[MVCx.EditorsValuesKey] = ASPx.Json.ToJson(editorValues);
};
function GetCachedVisibleEditorValues(editorValues, addEditorValuePredicate) {
 var result = { };
 for(var key in editorValues) {
  if(!editorValues.hasOwnProperty(key)) continue;
  var editor = ASPx.GetControlCollection().GetByName(key);
  if(editor && ASPx.IsValidElement(editor.GetMainElement()) && (!addEditorValuePredicate || addEditorValuePredicate(null, editor)))
   result[key] = editorValues[key];
 }
 return result;
}
function IsPossiblePassEditorValue(dxEditor){
 if(!dxEditor || !dxEditor.GetEnabled || !dxEditor.GetEnabled())
  return false;
 if(dxEditor.InCallback() || !dxEditor.GetValueString)
  return false;
 if(ASPx.IsGridLookup(dxEditor))
  return !dxEditor.GetGridView().InCallback();
 return true;
}
MVCx.EditorValuesSynchronizer = {
 RefreshFormsCache: function(){
  ASPx.GetControlCollection().ForEachControl(function(control){ this.UpdateFormValue(control); }.aspxBind(this));
  this.CacheAllFormValues();
 },
 UpdateFormValue: function(control, isPushValueToCache){
  if(!control || !control.GetMainElement) return;
  var mainElement = control.GetMainElement();
  var form = ASPx.GetParentByTagName(mainElement, "FORM");
  if(!form || !MVCx.IsExistingClientEdit(control) || !mainElement || !ASPx.IsValidElement(mainElement)){
   this.RemoveFormCacheValue(form);
   return;
  }
  if(control.GetEnabled())
   this.SetFormCacheValue(form, control.name, MVCx.GetEditorValueByControl(control));
  else
   this.RemoveFormCacheValue(form, control.name);
  if(isPushValueToCache)
   this.CacheFormValues(form);
 },
 CacheAllFormValues: function(){
  for(var i = 0; i < document.forms.length; i++){
   this.CacheFormValues(document.forms[i]);
  }
 },
 CacheFormValues: function(form){
  if(!form || !form.DXEditorValues || !form.dxRequireCache)
   return;
  if(!ASPx.IsValidElement(form.DXEditorValuesField)){
   form.DXEditorValuesField = ASPx.CreateHiddenField(MVCx.EditorsValuesKey, "");
   form.appendChild(form.DXEditorValuesField);
  }
  if(form.DXEditorValuesField)
   form.DXEditorValuesField.value = ASPx.Json.ToJson(form.DXEditorValues);
 },
 SetFormCacheValue: function(form, controlName, value){
  if(!form.DXEditorValues)
   form.DXEditorValues = {};
  if(form.DXEditorValues[controlName] !== value){
   form.DXEditorValues[controlName] = value;
   form.dxRequireCache = true;
  }
 },
 RemoveFormCacheValue: function(form, controlName){
  if(!form || !form.DXEditorValues) return;
  if(form.DXEditorValues[controlName] !== undefined){
   delete form.DXEditorValues[controlName];
   form.dxRequireCache = true;
  }
 }
};
MVCx.IsExistingClientEdit = function(control) {
 if(!ASPx.Ident.IsASPxClientEdit(control))
  return false;
 var getValueInputMethod = MVCx.GetValueInputMethod(control);
 return getValueInputMethod ? ASPx.IsExistsElement(getValueInputMethod.call(control)) : true;
};
MVCx.GetValueInputElement = function(control) {
 var method = MVCx.GetValueInputMethod(control);
 return method ? method.call(control) : null;
};
MVCx.GetValueInputMethod = function(control) {
 return control.FindStateInputElement || control.GetStateInput || control.GetInputElement;
};
MVCx.GetEditorValueByControl = function(control) { 
 return ASPx.GetEditorValueByControl(control, true);
};
MVCx.EditorValueChanged = function(s, e) {
 MVCx.EditorValuesSynchronizer.UpdateFormValue(s, true);
 if(s.context) s.context.validate("blur");
};
MVCx.GetEditorByElements = function(elements) {
 for(var i = 0; i < elements.length; i++) {
  var control = MVCx.GetEditorByElement(elements[i]);
  if(control)
   return control;
 }
 return null;
};
MVCx.GetEditorByElement = function(element) {
 var control = MVCx.GetControlByElement(element);
 return control && ASPx.Ident.IsASPxClientEdit(control) ? control : null;
};
MVCx.GetControlByElement = function(element) {
 var valueInputPostfixes = ["", "_I", "_S", "_VI", "_STATE", "_KBS", "_DXValueKeyInput", ASPx.TempHiddenInputSuffix];
 for(var j = 0; j < valueInputPostfixes.length; j++) {
  var regexp = new RegExp("(\S*)" + valueInputPostfixes[j] + "$");
  var controlName = regexp.test(element.id) ? element.id.replace(regexp, function(a, b) { return b; }) : "";
  var control = ASPx.GetControlCollection().Get(controlName);
  if(control)
   return control;
 }
 return null;
};
MVCx.PerformExportCallback = function(form, name, url, arg, params, endCallbackHandler) {
 var sourceFormAction = ASPx.Attr.GetAttribute(form, "action"),
  sourceFormMethod = ASPx.Attr.GetAttribute(form, "method"),
  data = { DXExportCallback: name, __DXCallbackArgument: arg };
 ASPx.Data.MergeHashTables(data, params);
 var preparedData = PrepareExportCallbackData(data),
  exportArgsElement = CreateExportCallbackArgsElement(preparedData);
 ASPx.Attr.SetAttribute(form, "action", url);
 ASPx.Attr.SetAttribute(form, "method", "post");
 form.appendChild(exportArgsElement);
 form.submit();
 window.setTimeout(function() {
  ASPx.Attr.SetAttribute(form, "action", sourceFormAction);
  ASPx.Attr.SetAttribute(form, "method", sourceFormMethod);
  form.removeChild(exportArgsElement);
  endCallbackHandler();
 }, 0);
};
function PrepareExportCallbackData(data) {
 var result = [],
  add = function(name, val) {
   var value = ASPx.IsFunction(val) ? val() : (val == null ? "" : val);
   result.push({ name: name, value: value });
  };
 for(var key in data) {
  if(data.hasOwnProperty(key))
   BuildExportCallbackParams(key, data[key], add);
 }
 return result;
}
function BuildExportCallbackParams(prefix, obj, add) {
 if(ASPx.Ident.IsArray(obj))
  ASPx.Data.ForEach(obj, function(value, i) {
   BuildExportCallbackParams(prefix + "[" + (typeof (value) === "object" ? i : "") + "]", value, add);
  });
 else if(typeof(obj) === "object" && obj !== null) {
  for(var key in obj) {
   if(obj.hasOwnProperty(key))
    BuildExportCallbackParams(prefix + "[" + key + "]", obj[key], add);
  }
 } else
  add(prefix, obj);
}
function CreateExportCallbackArgsElement(args) {
 var argsDiv = ASPx.CreateHtmlElement("div", { className: "mvcExportCallbackArguments", display: "none" });
 ASPx.Data.ForEach(args, function(arg) {
  CreateAndAppendExportCallbackArgHiddenField(argsDiv, arg.name, arg.value);
 });
 return argsDiv;
}
function CreateAndAppendExportCallbackArgHiddenField(parent, argName, argValue) {
 var hiddenField = ASPx.CreateHiddenField(argName, argName);
 hiddenField.value = argValue;
 parent.appendChild(hiddenField);
}
MVCx.JQueryValidation = {
 IsEnabled: function(control) {
  return !!($.validator && control.GetParentForm());
 },
 Validate:function(control){
  var valueInput = MVCx.GetValueInputElement(control);
  return $(valueInput).valid();
 },
 SetUVAttributes: function(editor, rules){
  if(!editor || !rules) return;
  $input = $(MVCx.GetValueInputElement(editor));
  $.each(rules, function(ruleName, ruleValue){
   if(ruleName === 'data-val-remote-dxfieldsmap')
    editor.uvRemoteAdditionalFields = ASPx.GetObjectKeys(ruleValue);
   var attrValue = ruleName === 'data-val-remote-dxfieldsmap' ? JSON.stringify(ruleValue) : ruleValue; 
   $input.attr(ruleName, attrValue);
  });
 },
 PrepareUVRules: function(control, prepareMethod){
  var form = control.GetParentForm();
  if(form.dxUVExecuted)
   return;
  if(prepareMethod)
   prepareMethod();
  var $form = $(form);
  if($form.off)
   $form.off(".validate");
  $form.removeData("validator");
  $.validator.unobtrusive.parse(form);
  form.dxUVExecuted = true;
 },
 ResetUVRules: function(control){
  var form = control.GetParentForm();
  if(form && typeof(form.dxUVExecuted) !== "undefined")
   delete form.dxUVExecuted;
 },
 HasPendingRequests: function(control){
  var validator = this.GetValidator(control);
  return validator && validator.pendingRequest;
 },
 SetOnStopRequestHandler: function(control, handler){
  var validator = this.GetValidator(control);
  if(validator)
   validator.dxOnStopRequestHandler = handler;
 },
 GetValidator: function(control){
  var form = control.GetParentForm();
  return form ? $(form).data('validator') : null;
 },
 EnsureStopRequestHandling: function(validator){
  if(!validator || validator.pendingRequest || !validator.dxOnStopRequestHandler) return;
  validator.dxOnStopRequestHandler();
  delete validator.dxOnStopRequestHandler;
 },
 GetValidationErrorMessage: function(editor) { 
   var validator = this.GetValidator(editor); 
   return validator && validator.errorMap && validator.errorMap[editor.uniqueID]; 
  }
};
function PatchScript(scriptName, markerObjectName, patchMethod, required) {
 var externalScriptProcessor = ASPx.GetExternalScriptProcessor();
 if(externalScriptProcessor)
  externalScriptProcessor.Process(scriptName, markerObjectName, patchMethod, required);
 else if (ASPx.GetGlobalObject(markerObjectName))
  patchMethod();
}
PatchScript(MVCx.ScriptNames.MicrosoftMvcAjax, 'Sys.Mvc', function() {
 MVCx.RequiredValidator = function MVCx_RequiredValidator() {
  MVCx.RequiredValidator.initializeBase(this);
 };
 MVCx.RequiredValidator.prototype = {
  editor: null,
  getEditor: function(context){
   if(!this.editor)
    this.editor = MVCx.GetEditorByElements(context.fieldContext.elements);
   return this.editor;
  },
  validate: function(value, context){
   var editor = this.getEditor(context);
   if(editor)
    return value != null && String(value).length > 0;
   return MVCx.RequiredValidator.callBaseMethod(this, 'validate', [value, context]);
  }
 };
 MVCx.RequiredValidator.registerClass('MVCx.RequiredValidator', Sys.Mvc.RequiredValidator);
 MVCx.RequiredValidator.create = function (rule) {
  return Function.createDelegate(new MVCx.RequiredValidator(), new MVCx.RequiredValidator().validate);
 };
 Sys.Mvc.ValidatorRegistry.validators["required"] = MVCx.RequiredValidator.create;
 MVCx.FieldContext = function MVCx_FieldContext(formContext){
  MVCx.FieldContext.initializeBase(this);
 };
 MVCx.FieldContext.prototype = {
  editor: null,
  getEditor: function(){
   if(!this.editor)
    this.editor = MVCx.GetEditorByElements(this.elements);
   return this.editor;
  },
  getDisabled: function() {
   var editor = this.getEditor();
   return this.elements[0].disabled || editor && !editor.GetEnabled();
  },
  enableDynamicValidation: function(){
   MVCx.FieldContext.callBaseMethod(this, 'enableDynamicValidation');
   var editor = this.getEditor(this.elements);
   if(editor) editor.context = this;
  },
  _getStringValue: function(){
   var editor = this.getEditor();
   if(editor)
    return editor.GetValueString();
   return MVCx.FieldContext.callBaseMethod(this, '_getStringValue');
  },
  $12: function(){
   var editor = this.getEditor();
   if(editor)
    return editor.GetValueString();
   return MVCx.FieldContext.callBaseMethod(this, '$12');
  },
  validate: function(eventName) {
   var errors = MVCx.FieldContext.callBaseMethod(this, 'validate', [eventName]);
   var editor = this.getEditor();
   if(editor){
    var errorMessage = errors.length == 0 ? null : errors[0];
    MVCx.SetEditorValidationParameters(editor, errorMessage);
   }
   return errors;
  }
 };
 MVCx.FieldContext.registerClass('MVCx.FieldContext', Sys.Mvc.FieldContext);
 if(Sys.Mvc.FormContext){
  if(Sys.Mvc.FormContext._parseJsonOptions)
   eval("Sys.Mvc.FormContext._parseJsonOptions = " + Sys.Mvc.FormContext._parseJsonOptions.toString().replace("Sys.Mvc.FieldContext", "MVCx.FieldContext"));
  else if(Sys.Mvc.FormContext.$12)
   eval("Sys.Mvc.FormContext.$12 = " + Sys.Mvc.FormContext.$12.toString().replace("Sys.Mvc.FieldContext", "MVCx.FieldContext"));
  if(Sys.Mvc.FormContext.prototype.validate)
   eval("Sys.Mvc.FormContext.prototype.validate = " + Sys.Mvc.FormContext.prototype.validate.toString().replace("elements[0].disabled", "getDisabled()"));
 }
 if(typeof(ASPx.ClearProcessingProc) != "undefined"){
  MVCx.ClearProcessingProc = ASPx.ClearProcessingProc;
  ASPx.ClearProcessingProc = function(edit) {
   MVCx.ClearProcessingProc(edit);
   if(edit.context) edit.context.clearErrors();
  };
 }
 if(typeof(Sys.Mvc.MvcHelpers) != "undefined"){
  var _asyncRequestInternal = Sys.Mvc.MvcHelpers._asyncRequest || Sys.Mvc.MvcHelpers.$2;
  Sys.Mvc.MvcHelpers._asyncRequest = Sys.Mvc.MvcHelpers.$2 = function(url, verb, body, triggerElement, ajaxOptions){
   ASPx.ResourceManager.SynchronizeResources(
    function(name, resource) { 
     if(body && body.length > 0 && !body.endsWith('&'))
      body += '&';
     body += (name + "=" + resource);
    }
   );
   var customMethodOnSuccess = ajaxOptions.onSuccess;
   ajaxOptions.onSuccess = function(ajaxContext){
    if(customMethodOnSuccess)
     customMethodOnSuccess(ajaxContext);
    ASPx.ProcessScriptsAndLinks('', true);
   };
   _asyncRequestInternal(url, verb, body, triggerElement, ajaxOptions);
  };
 }
});
PatchScript(MVCx.ScriptNames.JQueryValidation, 'jQuery.validator', function(){
  MVCx.getValueOfEditor = function(element){
   var control = MVCx.GetEditorByElement(element);
   return control ? control.GetValueString() : element.value.replace(/\r/g, "");
  };
  var elementsInternal = $.validator.prototype.elements;
  $.validator.prototype.elements = function(){
   var $elements = elementsInternal.call(this);
   var $dxElements = $();
   ASPxClientControl.GetControlCollection().ProcessControlsInContainer(this.currentForm, function(control){
    if(!MVCx.IsExistingClientEdit(control))
     return;
    var input = MVCx.GetValueInputElement(control);
    if(input && $.inArray(input, $elements) == -1)
     $dxElements = $dxElements.add(input);
   });
   $elements = $.merge($elements, $dxElements);
   if($dxElements.length){
    var allFormInputElements = Array.prototype.slice.call(this.currentForm.getElementsByTagName("INPUT"));
    $elements.sort(function(a, b) {
     return allFormInputElements.indexOf(a) - allFormInputElements.indexOf(b);
    });
   }
   return $elements;
  };
  var validationTargetForBase = $.validator.prototype.validationTargetFor;
  $.validator.prototype.validationTargetFor = function(element) {
   if(MVCx.GetEditorByElement(element)) {
    if(!ASPx.Attr.GetAttribute(element, "name")) {
     var savedNameAttrValue = ASPx.Attr.GetAttribute(element, "data-name");
     if(savedNameAttrValue)
      return element.parentNode.querySelector("[name='" + savedNameAttrValue + "']") || element;
    }
    return element;
   }
   return validationTargetForBase.call(this, element);
  };
  var checkInternal = $.validator.prototype.check;
  $.validator.prototype.check = function(element){
   var control = MVCx.GetEditorByElement(element);
   if(control && (!control.GetEnabled() || !MVCx.validateInvisibleEditors && !control.IsVisible()))
    return;
   var isValid = checkInternal.call(this, element, $);
   if(control) {
    element = $.validator.prototype.validationTargetFor(element);
    MVCx.SetEditorValidationParameters(control, this.errorMap[element.name]);
   }
   return isValid;
  };
  var elementValueBase = $.validator.prototype.elementValue;
  $.validator.prototype.elementValue = elementValueBase && function(element){
   var dxControl = MVCx.GetEditorByElement(element);
   return dxControl ? GetStringValue(dxControl): elementValueBase.call(this, element);
  };
  var GetStringValue = function(dxControl){
   var value = dxControl.GetValueString();
   return value == null ? '' : value;
  };
  var showLabelInternal = $.validator.prototype.showLabel;
  $.validator.prototype.showLabel = function(element, message){
   var control = MVCx.GetEditorByElement(element);
   if(control)
    MVCx.SetEditorValidationParameters(control, message);
   if(control && !$.validator.unobtrusive)
    element = control.GetMainElement();
   if(!control || !control.GetErrorCell() && !control.dxgvColumnIndex)
    showLabelInternal.call(this, element, message);
  };
  var optionalInternal = $.validator.prototype.optional;
  $.validator.prototype.optional = function(element){
   var dxControl = MVCx.GetEditorByElement(element);
   if(!this.elementValue && dxControl)
    return !$.validator.methods.required.call(this, dxControl.GetValueString(), element) && "dependency-mismatch";
   return optionalInternal.call(this, element);
  };
  var requiredInternal = $.validator.methods.required;
  $.validator.methods.required = function(value, element, param) {
   var editor = MVCx.GetEditorByElement(element);
   var isCheckBox = editor && typeof (ASPxClientCheckBox) != "undefined" && editor instanceof ASPxClientCheckBox;
   if(isCheckBox && editor.checkedIsValidOnly)
    return editor.GetChecked();
   var editorValue = MVCx.getValueOfEditor(element);
   return requiredInternal.call(this, editorValue === null ? "" : editorValue, element);
  };
  if (!$.validator.prototype.elementValue){
   var rangeInternal = $.validator.methods.range;
   $.validator.methods.range = function(value, element, param){
    return rangeInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var minlengthInternal = $.validator.methods.minlength;
   $.validator.methods.minlength = function(value, element, param){
    return minlengthInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var maxlengthInternal = $.validator.methods.maxlength;
   $.validator.methods.maxlength = function(value, element, param){
    return maxlengthInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var rangelengthInternal = $.validator.methods.rangelength;
   $.validator.methods.rangelength = function(value, element, param){
    return rangelengthInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var minInternal = $.validator.methods.min;
   $.validator.methods.min = function(value, element, param){
    return minInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var maxInternal = $.validator.methods.max;
   $.validator.methods.max = function(value, element, param){
    return maxInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
   var emailInternal = $.validator.methods.email;
   $.validator.methods.email = function(value, element){
    return emailInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var urlInternal = $.validator.methods.url;
   $.validator.methods.url = function(value, element){
    return urlInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var dateISOInternal = $.validator.methods.dateISO;
   $.validator.methods.dateISO = function(value, element){
    return dateISOInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var numberInternal = $.validator.methods.number;
   $.validator.methods.number = function(value, element){
    return numberInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var digitsInternal = $.validator.methods.digits;
   $.validator.methods.digits = function(value, element){
    return digitsInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var creditcardInternal = $.validator.methods.creditcard;
   $.validator.methods.creditcard = function(value, element){
    return creditcardInternal.call(this, MVCx.getValueOfEditor(element), element);
   };
   var acceptInternal = $.validator.methods.accept;
   $.validator.methods.accept = function(value, element, param){
    return acceptInternal.call(this, MVCx.getValueOfEditor(element), element, param);
   };
  }
  var dateInternal = $.validator.methods.date;
  $.validator.methods.date = function(value, element){
   var editor = MVCx.GetEditorByElement(element);
   if(editor)
    value = editor.GetValue();
   return dateInternal.call(this, value, element);
  };
  var equalToInternal = $.validator.methods.equalTo;
  $.validator.methods.equalTo = function(value, element, param){
   var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
    $(element).valid();
   });
   var dxEditor;
   if(target.length > 0)
    dxEditor = MVCx.GetEditorByElement(target[0]);
   return dxEditor ? value == GetStringValue(dxEditor) : equalToInternal.call(this, value, element, param);
  };
  var remoteInternal = $.validator.methods.remote;
  $.validator.methods.remote = function(value, element, param){
   if(param && param.data){
    $.each(param.data, function(fieldName){
     var editorName = param.dxfieldsmap && param.dxfieldsmap[fieldName] || fieldName;
     var dxeditor = ASPx.GetControlCollection().Get(editorName);
     if(dxeditor) {
      dxeditor.EnsureValueStringIsActual();
      param.data[fieldName] = dxeditor.GetValueString();
     } 
    });
   }
   return remoteInternal.call(this, value, element, param);
  };
  var stopRequestInternal = $.validator.prototype.stopRequest;
  $.validator.prototype.stopRequest = function(element, valid) {
   stopRequestInternal.call(this, element, valid);
   MVCx.JQueryValidation.EnsureStopRequestHandling(this);
  };
  var focusInvalidInternal = $.validator.prototype.focusInvalid;
  $.validator.prototype.focusInvalid = function() {
   if(!this.settings.focusInvalid)
    return;
   var firstInvalidElement = this.errorList.length && this.errorList[0].element;
   var control = firstInvalidElement && MVCx.GetEditorByElement(firstInvalidElement);
   if(control)
    control.SetFocus();
   else
    focusInvalidInternal.call(this);
  };
  $.validator.addMethod("dxmask", function (value, element, params) {
   var control = MVCx.GetEditorByElement(element);
   if(control && control.maskInfo)
    return control.maskInfo.IsValid();
   return true;
  });
  $.validator.addMethod("dxdaterange", function (value, element, params) {
   var control = MVCx.GetEditorByElement(element);
   if(!control || !control.GetStartDateEdit)
    return;
   if(control.MinOrMaxRangeExist && !control.MinOrMaxRangeExist())
    return true;
   var pattern = new ASPx.DateRangeValidationPattern(control);
   return pattern && pattern.EvaluateIsValid();
  });
});
PatchScript(MVCx.ScriptNames.JQueryUnobtrusiveValidation, 'jQuery.validator.unobtrusive', function(){
  $.validator.unobtrusive.adapters.add("dxmask", [], function (options) {
   options.rules["dxmask"] = { };
   options.messages["dxmask"] = options.message;
  });
  $.validator.unobtrusive.adapters.add("dxdaterange", [], function (options) {
   options.rules["dxdaterange"] = { };
   options.messages["dxdaterange"] = options.message;
  });
  $.each($.validator.unobtrusive.adapters, function (i, adapter) {
   if (adapter.name != "remote") return;
   adapter.params.push("dxfieldsmap");
   adapter.adaptCore = adapter.adapt;
   adapter.adapt = function (options) {
    this.adaptCore(options);
    if (options.params.dxfieldsmap)
     $.extend(options.rules["remote"], { dxfieldsmap: ASPx.Json.Eval(options.params.dxfieldsmap) });
   };
  });
  $.validator.unobtrusive.prototype = {
   parseElement: $.validator.unobtrusive.parseElement
  };
  $.validator.unobtrusive.parseElement = function (element, skipAttach) {
   $.validator.unobtrusive.prototype.parseElement.call(this, element, skipAttach);
   var editor = MVCx.GetEditorByElement(element);
   if (editor && ASPx.IsExists(editor.validationPatterns) && !editor.isRequiredCheckBox)
    editor.validationPatterns = [ ];
  };
});
PatchScript(MVCx.ScriptNames.JQuery, 'jQuery', function(){
 if($.expr && $.expr[":"] && $.expr[":"].tabbable) {
    var tabbableCore = $.expr[":"].tabbable;
    $.expr[":"].tabbable = function(element) {
   return tabbableCore.call(this, element) || isInternalTabbableInput(element);
  };
    var isInternalTabbableInput = function(element) {
     if(!element || element.tagName != 'INPUT') return false;
     var tabIndex = ASPx.Attr.GetAttribute(element, ASPx.Attr.GetTabIndexAttributeName());
     return (!tabIndex || tabIndex >= 0) && IsVisibleControlInput(element);
    };
    var IsVisibleControlInput = function(element) {
     var control = MVCx.GetControlByElement(element);
     return control && control.IsVisible();
    };
 }
 $.prototype.ajax = $.ajax;
 $.ajax = function(url, settings){
  if(typeof url === "object"){
   settings = url;
   url = undefined;
  }
  if(typeof url === "string" && !ASPx.IsExists(settings)){
   settings = { url: url };
   url = undefined;
  }
  if(isPassDXHeaders(settings)){
   var baseBeforeSendMethod = settings.beforeSend || jQuery.ajaxSettings.beforeSend;
   settings.beforeSend = function(jqXHR, options){
    var result;
    if(baseBeforeSendMethod)
     result = baseBeforeSendMethod.call(this, jqXHR, options);
    ASPx.ResourceManager.SynchronizeResources(
     function(name, resource) { 
      jqXHR.setRequestHeader(name, resource); 
     }
    );
    return result;
   };
  }
  if(Array.isArray(settings.complete))
   settings.complete.push(onAjaxRequestComplete);
  else {
   var baseCompleteMethod = settings.complete;
   settings.complete = function(jqXHR, status) {
    onAjaxRequestComplete.call(this);
    var result;
    if(baseCompleteMethod)
     result = baseCompleteMethod.call(this, jqXHR, status);
    return result;
   };
  }
  var params = [ ];
  if(url)
   params.push(url);
  params.push(settings);
  return $.prototype.ajax.apply(this, params);
 };
 if(compareJQueryVersion("1.12") < 0){
  $.prototype.clean = $.clean;
  $.clean = function(elems, context, fragment, scripts){
   var result = $.prototype.clean.call(this, elems, context, fragment, scripts);
   for(var i=0; scripts && i < scripts.length; i++){
    var script = scripts[i];
    if(isDXScriptElement(script)){
     fragment.appendChild(script);
     scripts.splice(i--, 1);
    }
   }
   return result;
  };
  var mapBase = $.map;
  $.map = function (elems, callback, arg){
   function calbackInternal(element, index, arg){
    if(isDXScriptElement(element))
     return;
    return callback(element, index, arg);
   }
   return mapBase.call(this, elems, calbackInternal, arg);
  };
  $.fn.prototype = {
   domManip: $.fn.domManip
  };
  $.fn.domManip = function (args, table, callback) {
   var result = $.fn.prototype.domManip.apply(this, arguments);
   if(MVCx.isDXScriptInitializedOnLoad && haveElementsDXScript(args)) {
    ASPx.ProcessScriptsAndLinks('', true);
    ASPx.RunStartupScripts(true);
   }
   return result;
  };
 }
 if(compareJQueryVersion("1.12") >= 0){
  var mapBase = $.map;
  $.map = function (elems, callback, arg){
   var reenableScripts = [ ];
   function calbackInternal(element, index, arg){
    var disabledDXScript = isDXScriptElement(element) && (element.type.indexOf("true") == 0 || element.type.indexOf("false") == 0);
    var ret = callback(element, index, arg);
    if (disabledDXScript && element.type.indexOf("true") !== 0 && element.type.indexOf("false") !== 0)
     reenableScripts.push(element);
    return ret;
   }
   var ret = mapBase.call(this, elems, calbackInternal, arg);
   var lastIndex = -1;
   for(var i = 0; i < reenableScripts.length; i++){
    lastIndex = elems.indexOf(reenableScripts[i]);
    elems[lastIndex] = document.createElement("script");
   }
   if(lastIndex > -1){
    ASPxClientUtils.ArrayRemoveAt(elems, lastIndex);
    elems.push(createRunStartupScriptBlock());
    window.setTimeout(function(){ disposeRunStartupScriptBlock(); }, 0);
   }
   return ret;
  };
 }
 function compareJQueryVersion(version){
  if(!$.fn.jquery)
   return 1;
  var jQVersionParts = $.fn.jquery.split('.');
  var versionParts = version.split('.');
  var count = Math.max(jQVersionParts.length, versionParts.length);
  for(var i = 0; i < count; i++){
   var jQPart = i < jQVersionParts.length ? parseInt(jQVersionParts[i]) : 0;
   var vPart = i < versionParts.length ? parseInt(versionParts[i]) : 0;
   var cmp = (jQPart > vPart) - (jQPart < vPart);
   if(cmp != 0)
    return cmp;
  }
  return 0;
 }
 function isDXScriptElement(element){
  return element && element.id && element.id.indexOf && element.id.indexOf(ASPx.startupScriptPrefix) == 0;
 }
 function haveElementsDXScript(elements){
  if(!elements || !elements.length)
   return false;
  var isDXScriptFound = false;
  var dxScriptSelector = "script[id^=" + ASPx.startupScriptPrefix + "]";
  var isHtmlExpression = /<|&#?\w+;/;
  for(var i = 0; i < elements.length && !isDXScriptFound; i++){
   var element = elements[i];
   if ($.type(element) != "object" && !isHtmlExpression.test(element)) continue;
   var $element = element instanceof $ ? element : $("<div>" + element + "</div>");
   $element.each(function() {
    var $this = $(this);
    if($this.is(dxScriptSelector) || $this.find(dxScriptSelector).length) {
     isDXScriptFound = true;
     return false;
    }
   });
  }
  return isDXScriptFound;
 }
 function createRunStartupScriptBlock(){
  var script = document.getElementById(RunStartupScriptBlockID);
  if(script)
   return script;
  var script = document.createElement("script");
  script.id = RunStartupScriptBlockID;
  script.type = "dx/script";
  script.text = "MVCx.isDXScriptInitializedOnLoad && ASPx.ProcessScriptsAndLinks('', true) && ASPx.RunStartupScripts(true);";
  document.body.appendChild(script);
  script.type = "text/javascript";
  return script;
 }
 function disposeRunStartupScriptBlock(){
  var script = ASPx.GetElementById(RunStartupScriptBlockID);
  ASPx.RemoveElement(script);
 }
 function isPassDXHeaders(ajaxOptions){
  if(!ajaxOptions)
   return true;
  if(ajaxOptions.hasOwnProperty("passDXHeaders"))
   return ajaxOptions.passDXHeaders;
  var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
  if(ajaxOptions.accepts && ajaxOptions.accepts.json && ajaxOptions.accepts.json.indexOf(JSON_VERBOSE_MIME_TYPE) > -1)
   return false;
  if(ajaxOptions.headers && ajaxOptions.headers.hasOwnProperty("accepts") && ajaxOptions.headers.accepts.indexOf(JSON_VERBOSE_MIME_TYPE) > -1)
   return false;
  return true;
 }
 function onAjaxRequestComplete() {
  var self = this;
  $("[data-ajax=true]")
   .filter(function() { return (this.action || this.href) === self.url; })
   .each(function() {
    var insertionMode = ($(this).attr("data-ajax-mode") || "").toUpperCase();
    if(insertionMode && insertionMode != "REPLACE" && MVCx.isDXScriptInitializedOnLoad)
     ASPx.RunStartupScripts(true);
   });
 } 
}, true);
MVCx.isDXScriptInitializedOnLoad = false;
MVCx.validateInvisibleEditors = false;
MVCx.EditorSetValue = function(){
 if(this.oldSetValue)
  this.oldSetValue.apply(this, arguments);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.SetEditorValidationParameters = function(control, errorText){
 var isValid = !errorText;
 if(control.GetIsValid() == isValid && (isValid || control.GetErrorText() == errorText))
  return;
 if(!isValid)
  control.SetErrorText(errorText, true);
 if(ASPx.Ident.scripts.ASPxClientValidationSummary)
  ASPx.GetClientValidationSummaryCollection().AllowNewErrorsAccepting();
 control.SetIsValid(isValid);
 control.ariaExplanatoryTextManager.UpdateValidationState(ASPx.ValidationType.MassValidation);
 if(ASPx.Ident.scripts.ASPxClientValidationSummary)
  ASPx.GetClientValidationSummaryCollection().ForbidNewErrorsAccepting();
};
MVCx.MultipleEditorSelectValues = function(values){
 if(this.oldSelectValues)
  this.oldSelectValues(values);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.MultipleEditorSelectAll = function(){
 if(this.oldSelectAll)
  this.oldSelectAll();
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.MultipleEditorUnselectAll = function(){
 if(this.oldUnselectAll)
  this.oldUnselectAll();
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.ListBoxSetSelectedIndex = function(index){
 if(this.oldSetSelectedIndex)
  this.oldSetSelectedIndex(index);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.ListBoxSetIndicesSelectionState = function(indices, selected){
 if(this.oldSetIndicesSelectionState){
  this.oldSetIndicesSelectionState(indices, selected);
 }
 MVCx.EditorValueChanged(this.listBoxControl, new ASPxClientEventArgs());
};
MVCx.ComboBoxSelectIndex = function(index, initialize){
 if(this.oldSelectIndex)
  this.oldSelectIndex(index, initialize);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
 var listBox = this.GetListBoxControl();
 if(listBox)
  MVCx.EditorValueChanged(listBox, new ASPxClientEventArgs());
};
MVCx.TokenBoxAddToken = function(text) {
 if(this.oldAddToken)
  this.oldAddToken(text);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.TokenBoxRemoveToken = function(text) {
 if(this.oldRemoveToken)
  this.oldRemoveToken(text);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.TokenBoxClearTokenCollection = function() {
 if(this.oldClearTokenCollection)
  this.oldClearTokenCollection();
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
MVCx.TokenBoxSetTokenCollection = function(collection) {
 if(this.oldSetTokenCollection)
  this.oldSetTokenCollection(collection);
 MVCx.EditorValueChanged(this, new ASPxClientEventArgs());
};
function aspxMVCControlsInitialized(s, e){
 ASPx.GetControlCollection().ForEachControl(function(control){
  if(!MVCx.IsExistingClientEdit(control) || control.AreSyncHandlersAdded || !control.ValueChanged)
   return;
  if(ASPx.IsTokenBox(control))
   InitializeTokenBoxHandlers(control);
  else
   control.ValueChanged.InsertFirstHandler(MVCx.EditorValueChanged);
  control.EnabledChanged.InsertFirstHandler(MVCx.EditorValueChanged);
  control.LostFocus.InsertFirstHandler(function(){ MVCx.EditorValuesSynchronizer.RefreshFormsCache(); });
  if (ASPx.IsMultipleValueOwner(control))
   control.SelectedIndexChanged.InsertFirstHandler(MVCx.EditorValueChanged);
  if(!control.oldSetValue){
   control.oldSetValue = control.SetValue;
   control.SetValue = MVCx.EditorSetValue;
  }
  if(ASPx.IsMultipleValueOwner(control) && !control.oldSelectValues){
   control.oldSelectValues = control.SelectValues;
   control.SelectValues = MVCx.MultipleEditorSelectValues;
  }
  if(ASPx.IsMultipleValueOwner(control) && !control.oldSelectAll){
   control.oldSelectAll = control.SelectAll;
   control.SelectAll = MVCx.MultipleEditorSelectAll;
  }
  if(ASPx.IsMultipleValueOwner(control) && !control.oldUnselectAll){
   control.oldUnselectAll = control.UnselectAll;
   control.UnselectAll = MVCx.MultipleEditorUnselectAll;
  }
  if(ASPx.IsListBox(control)){
   if(!control.oldSetSelectedIndex){
    control.oldSetSelectedIndex = control.SetSelectedIndex;
    control.SetSelectedIndex = MVCx.ListBoxSetSelectedIndex;
   }
   var itemSelectionHelper = control.GetItemSelectionHelper();
   if(itemSelectionHelper && !itemSelectionHelper.oldSetIndicesSelectionState){
    itemSelectionHelper.oldSetIndicesSelectionState = itemSelectionHelper.SetIndicesSelectionState;
    itemSelectionHelper.SetIndicesSelectionState = MVCx.ListBoxSetIndicesSelectionState;
   }
  }
  if(ASPx.IsComboBox(control) && !control.oldSelectIndex){
   control.oldSelectIndex = control.SelectIndex;
   control.SelectIndex = MVCx.ComboBoxSelectIndex;
  }
  if($.validator && (ASPx.IsGridLookup(control) || ASPx.IsSpinEdit(control) || HasControlDxMaskAttribute(control))){ 
   control.ValueChanged.AddHandler(function(s, e){
    if(MVCx.JQueryValidation.IsEnabled(s))
     MVCx.JQueryValidation.Validate(s);
   });
  }
  control.AreSyncHandlersAdded = true;
 });
 ASPx.GetPostHandler().SetBeforeOnSubmit(function() {
  if(!ASPx.GetFocusedEditor)
   return;
  var focusedEditor = ASPx.GetFocusedEditor();
  if(focusedEditor)
   MVCx.EditorValuesSynchronizer.UpdateFormValue(focusedEditor, true);
 });
 ASPx.GetPostHandler().Update();
 MVCx.EditorValuesSynchronizer.RefreshFormsCache();
}
function InitializeTokenBoxHandlers(tokenBox) {
 tokenBox.TokensChanged.InsertFirstHandler(MVCx.EditorValueChanged);
 if(!tokenBox.oldAddToken){
  tokenBox.oldAddToken = tokenBox.AddToken;
  tokenBox.AddToken = MVCx.TokenBoxAddToken;
 }
 if(!tokenBox.oldRemoveToken){
  tokenBox.oldRemoveToken = tokenBox.RemoveToken;
  tokenBox.RemoveToken = MVCx.TokenBoxRemoveToken;
 }
 if(!tokenBox.oldClearTokenCollection){
  tokenBox.oldClearTokenCollection = tokenBox.ClearTokenCollection;
  tokenBox.ClearTokenCollection = MVCx.TokenBoxClearTokenCollection;
 }
 if(!tokenBox.oldSetTokenCollection){
  tokenBox.oldSetTokenCollection = tokenBox.SetTokenCollection;
  tokenBox.SetTokenCollection = MVCx.TokenBoxSetTokenCollection;
 }
}
function HasControlDxMaskAttribute(control){
 var inputElement = MVCx.GetValueInputElement(control);
 return inputElement && inputElement.getAttribute("data-val-dxmask");
}
ASPx.GetControlCollection().ControlsInitialized.AddHandler(aspxMVCControlsInitialized);
ASPx.attachToReady(function (evt) { 
 MVCx.isDXScriptInitializedOnLoad = true;
});
var MVCxClientUtils = {};
MVCxClientUtils.FinalizeCallback = function(){
 ASPx.ProcessScriptsAndLinks('', true);
};
MVCxClientUtils.GetSerializedEditorValuesInContainer = function(containerOrId, processInvisibleEditors) {
 return ASPxClientUtils.GetEditorValuesInContainer(containerOrId, processInvisibleEditors, true);
};
MVCxClientUtils.PerformValidationInContainerById = function(containerId, validateInvisibleEditors) {
 var container = document.getElementById(containerId);
 return MVCxClientUtils.PerformValidationInContainer(container, validateInvisibleEditors);
};
MVCxClientUtils.PerformValidationInContainer = function(container, validateInvisibleEditors) {
 if(!$.validator)
  throw new Error("The jQuery validation requires loading the jquery.validate script to a page");
 var oldValidateInvisibleEditors = MVCx.validateInvisibleEditors;
 try {
  MVCx.validateInvisibleEditors = !!validateInvisibleEditors;
  var isValid = true;
  if(container) {
   var form = ASPx.GetParentByTagName(container, "FORM");
   isValid = PerformValidationInContainerCore(container, form);
  } else {
   isValid = PerformValidationInAllForms();
  }
  return isValid;
 } finally {
  MVCx.validateInvisibleEditors = oldValidateInvisibleEditors;
 }
};
function PerformValidationInContainerCore(container, form) {
 if(!form)
  throw new Error("The jQuery validation requires wrapping the validating element into a form");
 var inputs = $(form).validate().elements().filter(
  function() { return ASPx.GetIsParent(container, this); }
 );
 var result = true;
 for(var i = 0; i < inputs.length; i++) {
  var isValidInput = $(form).validate().element(inputs[i]);
  result = result && isValidInput;
 }  
 return result;
}
function PerformValidationInAllForms() {
 var forms = document.forms;
 if(forms.length === 0)
  throw new Error("The jQuery validation requires at least one form element on a page");
 var result = true;
 for(var i = 0; i < forms.length; i++) {
  var isValidForm = $(forms[i]).validate().form();
  result = result && isValidForm;
 }
 return result;
}
var MVCxClientBeginCallbackEventArgs = ASPx.CreateClass(ASPxClientBeginCallbackEventArgs, {
 constructor: function(command){
  this.constructor.prototype.constructor.call(this, command);
  this.customArgs = {};
 }
});
var MVCxClientGlobalBeginCallbackEventArgs = ASPx.CreateClass(ASPxClientGlobalBeginCallbackEventArgs, {
 constructor: function(control, command){
  this.constructor.prototype.constructor.call(this, control, command);
  this.customArgs = {};
 }
});
var MVCxClientGlobalEvents = {
 ControlsInitialized: new ASPxClientEvent(),
 BeginCallback: new ASPxClientEvent(),
 EndCallback: new ASPxClientEvent(),
 CallbackError: new ASPxClientEvent(),
 OnControlsInitialized: function(sender, args) {
  if(!this.ControlsInitialized.IsEmpty())
   this.ControlsInitialized.FireEvent(this, args);
 },
 OnBeginCallback: function(sender, args) {
  if(this.BeginCallback.IsEmpty())
   return;
  args = new MVCxClientGlobalBeginCallbackEventArgs(args.control, args.command);
  if(args.control && args.control.callbackCustomArgs)
   ASPx.Data.MergeHashTables(args.customArgs, args.control.callbackCustomArgs);
  this.BeginCallback.FireEvent(this, args);
  if(args.control && args.control.callbackCustomArgs)
   ASPx.Data.MergeHashTables(args.control.callbackCustomArgs, args.customArgs);
 },
 OnEndCallback: function(sender, args) {
  if(!this.EndCallback.IsEmpty())
   this.EndCallback.FireEvent(this, args);
 },
 OnCallbackError: function(sender, args) {
  if(!this.CallbackError.IsEmpty())
   this.CallbackError.FireEvent(this, args);
 }
};
MVCxClientGlobalEvents.AddControlsInitializedEventHandler = function(handler) {
 this.ControlsInitialized.AddHandler(handler);
};
MVCxClientGlobalEvents.AddBeginCallbackEventHandler = function(handler) {
 this.BeginCallback.AddHandler(handler);
};
MVCxClientGlobalEvents.AddEndCallbackEventHandler = function(handler) {
 this.EndCallback.AddHandler(handler);
};
MVCxClientGlobalEvents.AddCallbackErrorHandler = function(handler) {
 this.CallbackError.AddHandler(handler);
};
var collection = ASPx.GetControlCollection();
if(collection){
 var AddHandlerToCollection = function(eventName) {
  collection[eventName].AddHandler(MVCxClientGlobalEvents["On" + eventName].aspxBind(MVCxClientGlobalEvents));
 };
 AddHandlerToCollection("ControlsInitialized");
 AddHandlerToCollection("BeginCallback");
 AddHandlerToCollection("EndCallback");
 AddHandlerToCollection("CallbackError");
}
window.MVCxClientUtils = MVCxClientUtils;
window.MVCxClientGlobalEvents = MVCxClientGlobalEvents;
window.MVCxClientBeginCallbackEventArgs = MVCxClientBeginCallbackEventArgs;
})(window.jQuery);

(function() {
var MVCxClientCallbackPanel = ASPx.CreateClass(ASPxClientCallbackPanel, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 PerformCallback: function(data, onSuccess) {
  this.callbackCustomArgs = {};
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientCallbackPanel.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.callbackCustomArgs, this.GetCallbackParams()); }; 
  ASPxClientCallbackPanel.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(arg) {
  var params = {};
  var editorValues = $(this.GetParentForm()).find("[name=" + MVCx.EditorsValuesKey + "]").val();
  if(editorValues)
   params[MVCx.EditorsValuesKey] = editorValues;
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 CreateCallbackCoreWithCustomArgs: function(arg, command, callbackID, customArgs) {
  this.callbackCustomArgs = customArgs;
  this.CreateCallbackCore(arg, command, callbackID);
 },
 GetCustomCallbackArgs: function() {
  return this.callbackCustomArgs;
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientCallbackPanel.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientCallbackPanel.prototype.EvalCallbackResult.call(this, resultString);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientCallbackPanel.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientCallbackPanel.Cast = ASPxClientControl.Cast;
window.MVCxClientCallbackPanel = MVCxClientCallbackPanel;
})();

(function() {
var BreakpointsLayoutCssHelper = ASPx.CreateClass(null, {
 BreakpointsLayoutMarkerClass: "dxbplc",
 RuleFormat: "#{0} .dxbplc{width:{1}%;}",
 MediaRuleFormat: "@media all and (max-width:{0}px){{1}}",
 constructor: function() {
  this.styleSheetElement = null;
 },
 GetBreakpointsLayoutSettings: function(defaultItemsCount, breakpointsInfo) {
  var breakpoints = [];
  for(var i = 0; i < breakpointsInfo.length; i++) {
   var breakpointInfo = breakpointsInfo[i];
   breakpoints.push({
    maxWidth: breakpointInfo[0],
    itemsCount: breakpointInfo[1]
   });
  }
  return { defaultItemsCount: defaultItemsCount, breakpoints: breakpoints };
 },
 Update: function() {
  this.RemoveStyleSheetElement();
  var cssText = "";
  ASPx.GetControlCollection().ForEachControl(function(control) {
   if(this.IsBreakpointsLayoutSupport(control) && control.IsBreakpointsLayoutMode())
    cssText += this.CreateCssRules(control.name, control.GetBreakpointsLayoutSettings());
  }.aspxBind(this));
  if(cssText.length > 0)
   this.CreateStyleSheetElement(cssText);
 },
 IsBreakpointsLayoutSupport: function(control) {
  return control.IsBreakpointsLayoutMode && typeof(control.IsBreakpointsLayoutMode) == "function"
   && control.GetBreakpointsLayoutSettings && typeof(control.GetBreakpointsLayoutSettings) == "function";
 },
 CreateStyleSheetElement: function(cssText) {
  var styleElementHtml = "<style>" + cssText + "</style>";
  this.styleSheetElement = ASPx.CreateHtmlElementFromString(styleElementHtml);
  ASPx.GetNodeByTagName(document, "HEAD", 0).appendChild(this.styleSheetElement);
 },
 RemoveStyleSheetElement: function() {
  if(!this.styleSheetElement)
   return;
  ASPx.RemoveElement(this.styleSheetElement);
  this.styleSheetElement = null;
 },
 CreateCssRules: function(id, breakpointsLayoutSettings) {
  var cssTexts = breakpointsLayoutSettings.breakpoints.map(function(breakpoint) {
   return ASPx.Str.ApplyReplacement(this.MediaRuleFormat, [["{0}", breakpoint.maxWidth], ["{1}", this.GetCssRule(id, breakpoint.itemsCount)]]);
  }.bind(this));
  ASPx.Data.ArrayInsert(cssTexts, this.GetCssRule(id, breakpointsLayoutSettings.defaultItemsCount), 0);
  return cssTexts.join('');
 },
 GetCssRule: function(id, itemsCount) {
  var percentWidth = Math.round(Math.pow(10, 10) / itemsCount) / Math.pow(10, 8);
  return ASPx.Str.ApplyReplacement(this.RuleFormat, [["{0}", id], ["{1}", percentWidth]]);
 }
});
BreakpointsLayoutCssHelper.Instance = new BreakpointsLayoutCssHelper();
ASPx.BreakpointsLayoutCssHelper = BreakpointsLayoutCssHelper.Instance;
})();
(function () {
var PagerIDSuffix = {
 PageSizeBox: "PSB",
 PageSizeButton: "DDB",
 PageSizePopup: "PSP",
 PageSizePopupMenuContainer: "DXMCC"
};
var ASPxClientPager = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.hasOwnerControl = false;
  this.originalWidth = null;
  this.containerOffsetWidth = 0;
  this.droppedDown = false;
  this.pageSizeItems = [];
  this.pageSizeSelectedItem = null;
  this.enableAdaptivity = false;
  this.pageSizeChanged = new ASPxClientEvent();
  this.requireInlineLayout = false;
  this.rightAlignContainer = null;
 },
 InlineInitialize: function () {
  this.originalWidth = this.GetMainElement().style.width;
  ASPxClientControl.prototype.InlineInitialize.call(this);
 },
 Initialize: function() {
  ASPxClientControl.prototype.Initialize.call(this);
  aspxGetPagersCollection().Add(this);
  if(this.requireInlineLayout) {
   var mainElement = this.GetMainElement();
   mainElement.style.display = "inline-block";
   mainElement.style.float = "none";
  }
  this.InitAccessibilityListboxRole();
 },
 BrowserWindowResizeSubscriber: function () {
  return ASPxClientControl.prototype.BrowserWindowResizeSubscriber.call(this) || this.hasOwnerControl;
 },
 OnBrowserWindowResize: function (e) {
  this.AdjustControl();
 },
 GetAdjustedSizes: function () {
  if(this.hasOwnerControl) {
   var mainElement = this.GetMainElement();
   if(mainElement)
    return { width: mainElement.parentNode.offsetWidth, height: mainElement.parentNode.offsetHeight };
  }
  return ASPxClientControl.prototype.GetAdjustedSizes.call(this);
 },
 AdjustControlCore: function() {
  this.CorrectVerticalAlignment(ASPx.ClearHeight, this.GetPageSizeButtonElement, "PSB");
  this.CorrectVerticalAlignment(ASPx.ClearVerticalMargins, this.GetPageSizeButtonImage, "PSBImg");
  this.CorrectVerticalAlignment(ASPx.ClearHeight, this.GetButtonElements, "Btns");
  this.CorrectVerticalAlignment(ASPx.ClearVerticalMargins, this.GetButtonImages, "BtnImgs");
  this.CorrectVerticalAlignment(ASPx.ClearVerticalMargins, this.GetSeparatorElements, "Seps");
  this.containerOffsetWidth = this.GetContainerWidth();
  var savedDroppedDown = false;
  if(this.droppedDown && this.GetPageSizePopupMenu()) {
   this.HidePageSizeDropDown();
   savedDroppedDown = true;
  }
  if(ASPx.IsPercentageSize(this.originalWidth))
   this.AdjustControlItems();
  else if(this.hasOwnerControl)
   this.AdjustControlMinWidth();
  if(savedDroppedDown)
   this.ShowPageSizeDropDown();
  this.CorrectVerticalAlignment(ASPx.AdjustHeight, this.GetPageSizeButtonElement, "PSB");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetPageSizeButtonImage, "PSBImg");
  this.CorrectVerticalAlignment(ASPx.AdjustHeight, this.GetButtonElements, "Btns");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetButtonImages, "BtnImgs");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetSeparatorElements, "Seps");
 },
 AdjustControlMinWidth: function() {
  var mainElement = this.GetMainElement();
  if(!mainElement) return;  
  if(this.enableAdaptivity) {
   var selectors = this.GetAdaptiveElementSelectors();
   this.SetElementsDisplay(mainElement, selectors.numeric, true);
   this.SetElementsDisplay(mainElement, selectors.ellipsis, true);
   this.SetElementsDisplay(mainElement, selectors.summary, true);
   var hideSummaryAtFirst = this.GetButtonElements().length === 0;
   if(hideSummaryAtFirst && this.GetAdaptiveWidth(mainElement) < this.GetMinWidth(mainElement))
    this.SetElementsDisplay(mainElement, selectors.summary, false);
   if(this.GetAdaptiveWidth(mainElement) < this.GetMinWidth(mainElement)){
    this.SetElementsDisplay(mainElement, selectors.numeric, false);
    this.SetElementsDisplay(mainElement, selectors.ellipsis, false);
   }
   if(!hideSummaryAtFirst && this.GetAdaptiveWidth(mainElement) < this.GetMinWidth(mainElement))
    this.SetElementsDisplay(mainElement, selectors.summary, false);
  }
  else {
   var minWidth = this.GetMinWidth(mainElement);
   mainElement.style.minWidth = minWidth + "px";
  }
 },
 GetAdaptiveElementSelectors: function(){
  return { summary: "dxp-summary", ellipsis: "dxp-ellip", numeric: "dxp-num" };
 },
 GetAdaptiveWidth: function(element){
  if(ASPx.IsPercentageSize(this.originalWidth)) 
   return element.offsetWidth;
  else if(this.hasOwnerControl)
   return element.parentNode.offsetWidth;
  else
   return 10000;
 },
 GetMinWidth: function(element){
  return Math.ceil(this.GetItemsWidth(element)) + ASPx.GetLeftRightPaddings(element);
 },
 SetElementsDisplay: function(element, cssClass, value) {
  var elements = ASPx.GetNodesByPartialClassName(element, cssClass);
  for(var i = 0; i < elements.length; i++) 
   ASPx.SetElementDisplay(elements[i], value);
 },
 AdjustControlItems: function () {
  var mainElement = this.GetMainElement();
  mainElement.style.width = this.originalWidth;
  var spacers = [];
  for(var i = 0; i < mainElement.childNodes.length; i++) {
   var itemElement = mainElement.childNodes[i];
   if(!itemElement.tagName) continue;
   if(itemElement.className === "dxp-spacer") {
    spacers.push(itemElement);
    itemElement.style.width = "0px";
   }
  }
  this.AdjustControlMinWidth();
  if(spacers.length > 0) {
   var clientWidth = mainElement.clientWidth - ASPx.GetLeftRightPaddings(mainElement);
   var spacerWidth = Math.floor((clientWidth - this.GetItemsWidth(mainElement)) / spacers.length);
   var makeItemsFloatRight = false;
   var rightItems = [];
   for(var i = 0; i < mainElement.childNodes.length; i++) {
    var itemElement = mainElement.childNodes[i];
    if(!itemElement.tagName) continue;
    if(itemElement.className === "dxp-spacer") {
     if(itemElement == spacers[spacers.length - 1])
      makeItemsFloatRight = true;
     else
      itemElement.style.width = spacerWidth + "px";
    }
    else if(makeItemsFloatRight) {
     if(!this.IsAdjusted())
      rightItems.push(itemElement);
    }
   }
   this.AdjustRightFloatItems(rightItems, ASPx.GetLeftRightPaddings(mainElement));
   this.AdjustControlMinWidth();
  }
 },
 AdjustRightFloatItems: function (items, rightMargin) {
  if(items.length === 0)
   return;
  var container = this.GetRightAlignContainer();
  for(var i = 0; i < items.length; i++) {
   if(items[i] !== container)
    container.appendChild(items[i]);
  }
 },
 GetRightAlignContainer: function() {
  if(!ASPx.IsExistsElement(this.rightAlignContainer)) {
   this.rightAlignContainer = ASPx.CreateHtmlElementFromString("<div class='dxp-right' style='border-width: 0px; padding: 0px; margin: 0px'></div>");
   this.GetMainElement().appendChild(this.rightAlignContainer);
  }
  return this.rightAlignContainer;
 },
 GetItemsWidth: function (mainElement) {
  var width = 0;
  for(var i = 0; i < mainElement.childNodes.length; i++)
   width += this.GetItemWidth(mainElement.childNodes[i]);
  return width;
 },
 GetItemWidth: function (item) {
  if(!item || !item.tagName || !ASPx.GetElementDisplay(item))
   return 0;
  var style = ASPx.GetCurrentStyle(item);
  var margins = 0;
  if(!this.ShouldIgnoreItemHorizontalMargin(item, true))
   margins += ASPx.PxToInt(style.marginLeft);
  if(!this.ShouldIgnoreItemHorizontalMargin(item, false))
   margins += ASPx.PxToInt(style.marginRight);
  return item.getBoundingClientRect().width + margins;
 },
 ShouldIgnoreItemHorizontalMargin: function(item, isLeft) {
  return false;
 },
 GetContainerWidth: function () {
  var mainElement = this.GetMainElement();
  if(mainElement && mainElement.parentNode)
   return mainElement.parentNode.offsetWidth;
  return 0;
 },
 GetPageSizeBoxID: function () {
  return this.name + "_" + PagerIDSuffix.PageSizeBox;
 },
 GetPageSizeButtonID: function () {
  return this.name + "_" + PagerIDSuffix.PageSizeButton;
 },
 GetPageSizePopupMenuID: function () {
  return this.name + "_" + PagerIDSuffix.PageSizePopup;
 },
 GetPageSizePopupMenuContainerID: function () {
  return this.name + "_" + PagerIDSuffix.PageSizePopupMenuContainer;
 },
 GetPageSizeBoxElement: function () {
  return ASPx.GetElementById(this.GetPageSizeBoxID());
 },
 GetPageSizeButtonElement: function () {
  return ASPx.GetElementById(this.GetPageSizeButtonID());
 },
 GetPageSizeButtonImage: function () {
  return ASPx.GetNodeByTagName(this.GetPageSizeButtonElement(), "IMG", 0);
 },
 GetPageSizeInputElement: function () {
  return ASPx.GetNodeByTagName(this.GetPageSizeBoxElement(), "INPUT", 0);
 },
 GetPageSizePopupMenu: function () {
  return ASPx.GetControlCollection().Get(this.GetPageSizePopupMenuID());
 },
 GetButtonElements: function () {
  return ASPx.GetNodesByClassName(this.GetMainElement(), "dxp-button");
 },
 GetButtonImages: function () {
  var images = [];
  var buttons = this.GetButtonElements();
  for(var i = 0; i < buttons.length; i++) {
   var img = ASPx.GetNodeByTagName(buttons[i], "IMG", 0);
   if(img) images.push(img);
  }
  return images;
 },
 GetSeparatorElements: function () {
  return ASPx.GetNodesByClassName(this.GetMainElement(), "dxp-sep");
 },
 TogglePageSizeDropDown: function () {
  if(!this.droppedDown)
   this.ShowPageSizeDropDown();
  else
   this.HidePageSizeDropDown();
 },
 ShowPageSizeDropDown: function () {
  this.GetPageSizePopupMenu().Show();
  this.droppedDown = true;
  this.SetAccessibilityPopupMenuExpanded(true);
 },
 HidePageSizeDropDown: function () {
  this.GetPageSizePopupMenu().Hide();
  this.droppedDown = false;
  this.SetAccessibilityPopupMenuExpanded(false);
 },
 ChangePageSizeInput: function (isNext) {
  var input = this.GetPageSizeInputElement();
  var oldIndex = this.GetPageSizeIndexByText(input.value);
  var index = oldIndex;
  var count = this.pageSizeItems.length;
  if(isNext)
   index = (oldIndex < count - 1) ? (oldIndex + 1) : 0;
  else
   index = (oldIndex > 0) ? (oldIndex - 1) : (count - 1);
  input.value = this.pageSizeItems[index].text;
  this.SetAccessibilitySelectedItem(index, oldIndex);
 },
 ChangePageSizeValue: function (value) {
  this.GetPageSizeInputElement().value = this.GetPageSizeTextByValue(value);
 },
 IsPageSizeValueChanged: function () {
  var newValue = this.GetPageSizeValueByText(this.GetPageSizeInputElement().value);
  return newValue != this.pageSizeSelectedItem.value;
 },
 InitAccessibilityListboxRole: function() {
  var popupMenu = this.GetPageSizePopupMenu();
  if(!this.accessibilityCompliant || !popupMenu)
   return;
  var listElement = popupMenu.GetMenuMainElement(popupMenu.GetMainElement()).firstElementChild; 
  listElement.id = this.GetPageSizePopupMenuContainerID();
  ASPx.Attr.SetAttribute(listElement, "role", "listbox");
  ASPx.Attr.SetAttribute(this.GetPageSizeInputElement(), "aria-owns", listElement.id);
  for(var i = 0; i < popupMenu.GetItemCount(); i++) {
   var menuItemElement = popupMenu.GetItemElement(i);
   ASPx.Attr.SetAttribute(menuItemElement, "role", "option");
   ASPx.Attr.SetAttribute(menuItemElement, "aria-selected", false);
  }
 },
 SetAccessibilityPopupMenuExpanded: function(expanded) {
  if(!this.accessibilityCompliant)
   return;
  var inputElement = this.GetPageSizeInputElement();
  if(expanded){
   ASPx.Attr.SetAttribute(inputElement, "aria-expanded", true);
   setTimeout(function() {
    var index = this.GetPageSizeIndexByText(inputElement.value);
    this.SetAccessibilitySelectedItem(index);
   }.aspxBind(this), ASPx.AccessibilityPronounceTimeout);
  } else {
   ASPx.Attr.SetAttribute(inputElement, "aria-expanded", false);
   ASPx.Attr.RemoveAttribute(inputElement, "aria-activedescendant");
  }
 },
 SetAccessibilitySelectedItem: function(curIndex, oldIndex) {
  if(!this.accessibilityCompliant)
   return;
  var popupMenu = this.GetPageSizePopupMenu();
  if(ASPx.IsExists(oldIndex)) {
   var itemElement = popupMenu.GetItemElement(oldIndex);
   if(itemElement)
    ASPx.Attr.SetAttribute(itemElement, "aria-selected", false);
  }
  var selItemElement = popupMenu.GetItemElement(curIndex);
  if(selItemElement) {
   ASPx.Attr.SetAttribute(selItemElement, "aria-selected", true);
   if(this.droppedDown)
    ASPx.Attr.SetAttribute(this.GetPageSizeInputElement(), "aria-activedescendant", selItemElement.id);
  }
 },
 OnDocumentOnClick: function (evt) {
  var srcElement = ASPx.Evt.GetEventSource(evt);
  if(srcElement != this.GetPageSizeBoxElement() && ASPx.GetParentById(srcElement, this.GetPageSizeBoxID()) == null) {
   this.droppedDown = false;
  }
 },
 OnPageSizeClick: function (evt) {
  var self = this;
  window.setTimeout(function () {
   self.TogglePageSizeDropDown();
  }, 0);
  ASPx.SetFocus(this.GetPageSizeInputElement());
 },
 OnPageSizePopupItemClick: function (value) {
  this.ChangePageSizeValue(value);
  if(this.IsPageSizeValueChanged())
   this.OnPageSizeValueChangedWrapped(true);
 },
 OnPageSizeBlur: function (evt) {
  if(this.IsPageSizeValueChanged())
   this.OnPageSizeValueChangedWrapped(false);
 },
 OnPageSizeValueChangedWrapped: function(keepFocus) {
  if(this.accessibilityCompliant) {
   setTimeout(function() {
    if(keepFocus)
     this.GetPageSizeInputElement().focus();
    this.OnPageSizeValueChanged();
    this.SetAccessibilityPopupMenuExpanded(false);
   }.aspxBind(this), 0);
  } else
   this.OnPageSizeValueChanged();
 },
 OnPageSizeKeyDown: function (evt) {
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  if(keyCode == ASPx.Key.Down || keyCode == ASPx.Key.Up) {
   if(evt.altKey)
    this.TogglePageSizeDropDown();
   else
    this.ChangePageSizeInput(keyCode == ASPx.Key.Down);
   if(this.droppedDown) {
    var popupMenu = this.GetPageSizePopupMenu();
    var value = this.GetPageSizeValueByText(this.GetPageSizeInputElement().value);
    var item = popupMenu.GetItemByName(value);
    popupMenu.SetSelectedItem(item);
   }
   ASPx.Evt.PreventEvent(evt);
  }
  else if(keyCode == ASPx.Key.Enter) {
   if(this.IsPageSizeValueChanged())
    this.OnPageSizeValueChanged();
   else
    this.HidePageSizeDropDown();
   return ASPx.Evt.PreventEventAndBubble(evt);
  }
  else if(keyCode == ASPx.Key.Tab) {
   this.HidePageSizeDropDown();
  }
  else if(keyCode == ASPx.Key.Esc) {
   this.HidePageSizeDropDown();
   this.GetPageSizeInputElement().value = this.pageSizeSelectedItem.text;
  }
  return true;
 },
 UpdatePageSizeSelectedItem: function() {
  this.pageSizeSelectedItem.text = this.GetPageSizeInputElement().value;
  this.pageSizeSelectedItem.value = this.GetPageSizeValueByText(this.pageSizeSelectedItem.text);
 },
 OnPageSizeValueChanged: function () {
  this.UpdatePageSizeSelectedItem();
  if(!this.pageSizeChanged.IsEmpty()) {
   var popupMenu = this.GetPageSizePopupMenu();
   var menuItem = popupMenu.GetItemByName(this.pageSizeSelectedItem.value);
   var menuItemElement = popupMenu.GetItemElement(menuItem.index);
   var command = PagerIDSuffix.PageSizePopup + this.pageSizeSelectedItem.value;
   var args = new ASPxClientPagerPageSizeChangedEventArgs(menuItemElement, command);
   this.pageSizeChanged.FireEvent(this, args);
  }
 },
 GetPageSizeIndexByText: function (text) {
  var count = this.pageSizeItems.length;
  for(var i = 0; i < count; i++) {
   if(text == this.pageSizeItems[i].text)
    return i;
  }
  return -1;
 },
 GetPageSizeTextByValue: function (value) {
  var count = this.pageSizeItems.length;
  for(var i = 0; i < count; i++) {
   if(value == this.pageSizeItems[i].value)
    return this.pageSizeItems[i].text;
  }
  return value.toString();
 },
 GetPageSizeValueByText: function (text) {
  var count = this.pageSizeItems.length;
  for(var i = 0; i < count; i++) {
   if(text == this.pageSizeItems[i].text)
    return this.pageSizeItems[i].value;
  }
  return this.pageSizeSelectedItem.value;
 }
});
var ASPxClientPagerPageSizeChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (element, value) {
  this.constructor.prototype.constructor.call(this);
  this.element = element;
  this.value = value;
 }
});
var pagersCollection = null;
function aspxGetPagersCollection() {
 if(pagersCollection == null)
  pagersCollection = new ASPxClientPagersCollection();
 return pagersCollection;
}
var ASPxClientPagersCollection = ASPx.CreateClass(ASPxClientControlCollection, {
 constructor: function () {
  this.constructor.prototype.constructor.call(this);
 },
 GetCollectionType: function(){
  return "Pager";
 },
 OnDocumentOnClick: function (evt) {
  this.ForEachControl(function (control) {
   control.OnDocumentOnClick(evt);
  });
 }
});
ASPx.Evt.AttachEventToDocument("click", aspxPagerDocumentOnClick);
function aspxPagerDocumentOnClick(evt) {
 return aspxGetPagersCollection().OnDocumentOnClick(evt);
}
function _aspxPGNavCore(element) {
 if(element != null) {
  if(element.tagName != "A") {
   var linkElement = ASPx.GetNodeByTagName(element, "A", 0);
   if(linkElement != null)
    ASPx.Url.NavigateByLink(linkElement);
  }
 }
}
ASPx.PGNav = function(evt) {
 var element = ASPx.Evt.GetEventSource(evt);
 _aspxPGNavCore(element);
 if(!ASPx.Browser.NetscapeFamily)
  evt.cancelBubble = true;
};
ASPx.POnPageSizeChanged = function(s, e) {
 s.SendPostBack(e.value);
};
ASPx.POnSeoPageSizeChanged = function(s, e) {
 _aspxPGNavCore(e.element);
};
ASPx.POnPageSizeBlur = function(name, evt) {
 var pager = ASPx.GetControlCollection().Get(name);
 if(pager != null)
  pager.OnPageSizeBlur(evt);
 return true;
};
ASPx.POnPageSizeKeyDown = function(name, evt) {
 var pager = ASPx.GetControlCollection().Get(name);
 if(pager != null)
  return pager.OnPageSizeKeyDown(evt);
 return true;
};
ASPx.POnPageSizeClick = function(name, evt) {
 var pager = ASPx.GetControlCollection().Get(name);
 if(pager != null)
  pager.OnPageSizeClick(evt);
};
ASPx.POnPageSizePopupItemClick = function(name, item) {
 var pager = ASPx.GetControlCollection().Get(name);
 if(pager != null) {
  pager.OnPageSizePopupItemClick(item.name);
 }
};
window.ASPxClientPager = ASPxClientPager;
window.ASPxClientPagerPageSizeChangedEventArgs = ASPxClientPagerPageSizeChangedEventArgs;
ASPx.PagerIDSuffix = PagerIDSuffix;
ASPx.GetPagersCollection = aspxGetPagersCollection;
})();

(function () {
var ASPxClientDataView = ASPx.CreateClass(ASPxClientControl, {
 EndlessPagingMode: {
  Disabled: 0,
  OnClick: 1,
  OnScroll: 2
 },
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackPrefixes = { Custom: "c", PagerClick: "p" };
  this.supportGestures = true;
  this.endlessPagingHelper = null;
  ASPxClientDataViewCollection.add(this);
 },
 Initialize: function () {
  ASPxClientControl.prototype.Initialize.call(this);
  var helper = this.GetEndlessPagingHelper();
  if(helper) helper.Initialize();
 },
 InlineInitialize: function () {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  this.ChangeEndlessPagingContainerVisibility();
  if(this.IsBreakpointsLayoutMode())
   ASPx.BreakpointsLayoutCssHelper.Update();
 },
 AdjustControlCore: function () {
  this.UpdateItemsScroller();
  this.AdjustPagerControls();
 },
 GetContentCell: function () {
  return this.GetChildElement("CCell");
 },
 GetItemsCell: function () {
  return this.GetChildElement("ICell");
 },
 GetItemsScroller: function () {
  return this.GetChildElement("IScroller");
 },
 GetEndlessPagingContainer: function () {
  return this.GetChildElement("EPContainer");
 },
 IsTableLayoutMode: function () {
  return this.stateObject.layout === 0;
 },
 IsBreakpointsLayoutMode: function() {
  return this.stateObject.layout === 2;
 },
 GetBreakpointsLayoutSettings: function() {
  var stateObj = this.stateObject;
  return ASPx.BreakpointsLayoutCssHelper.GetBreakpointsLayoutSettings(stateObj.bpipr, stateObj.bpi);
 },
 DoPagerClick: function (value) {
  this.AssignSlideAnimationDirectionByPagerArgument(value, this.GetPageIndex());
  var endlessPagingHelper = this.GetEndlessPagingHelper();
  if(endlessPagingHelper)
   endlessPagingHelper.OnDoPagerClick(value);
  var preparedArgs = this.PrepareCallbackArgs(this.GetPageIndex() + ASPx.CallbackSeparator + this.GetPageSize() + ASPx.CallbackSeparator + value, false);
  this.CreateCallback(preparedArgs, "PAGERCLICK");
 },
 CanHandleGesture: function (evt) {
  var source = ASPx.Evt.GetEventSource(evt);
  return ASPx.GetIsParent(this.GetItemsCell(), source);
 },
 AllowStartGesture: function () {
  return ASPxClientControl.prototype.AllowStartGesture.call(this) &&
   (this.AllowExecutePagerGesture(this.GetPageIndex(), this.GetPageCount(), 1) || this.AllowExecutePagerGesture(this.GetPageIndex(), this.GetPageCount(), -1));
 },
 AllowExecuteGesture: function (value) {
  return this.AllowExecutePagerGesture(this.GetPageIndex(), this.GetPageCount(), value);
 },
 ExecuteGesture: function (value, count) {
  this.ExecutePagerGesture(this.GetPageIndex(), this.GetPageCount(), value, count, function (arg) { this.DoPagerClick(arg); }.aspxBind(this));
 },
 AssignSlideAnimationDirectionByPagerArgument: function (arg, currentPageIndex) {
  if(this.UseEndlessPaging()) return;
  ASPxClientControl.prototype.AssignSlideAnimationDirectionByPagerArgument.call(this, arg, currentPageIndex);
 },
 CustomCallback: function (args, handler) {
  var preparedArgs = this.PrepareCallbackArgs(args, true);
  if(!this.callBack) {
   if(this.isInitialized)
    this.SendPostBack(preparedArgs);
   return;
  }
  this.CreateCallback(preparedArgs, "CUSTOMCALLBACK", null, handler);
 },
 OnCallback: function (result) {
  var areStatesEqual = this.GetPageIndex() == result.stateObject.pageIndex && this.GetPageSize() == result.stateObject.pageSize;
  this.UpdateStateObjectWithObject(result.stateObject);
  var isEndlessPagingCallback = ASPx.IsExists(result.epHtml);
  if(this.UseEndlessPaging() && isEndlessPagingCallback) {
   var helper = this.GetEndlessPagingHelper();
   if(helper && !areStatesEqual)
    helper.OnCallback(result.html, result.epHtml);
  } else {
   var element = this.GetContentCell();
   if(element != null)
    ASPx.SetInnerHtml(element, result.html);
  }
 },
 DoEndCallback: function () {
  ASPxClientControl.prototype.DoEndCallback.call(this);
  var helper = this.GetEndlessPagingHelper();
  if(helper) helper.DoEndCallback();
  this.ChangeEndlessPagingContainerVisibility();
  this.UpdateItemsScroller();
 },
 CreateCallback: function (arg, command, callbackInfo, handler) {
  this.ShowLoadingElements();
  ASPxClientControl.prototype.CreateCallback.call(this, arg, command, handler);
 },
 PrepareCallbackArgs: function (args, isCustomCallback) {
  return (isCustomCallback ? this.callbackPrefixes.Custom : this.callbackPrefixes.PagerClick) + args;
 },
 ShowLoadingPanel: function () {
  var endlessPagingHelper = this.GetEndlessPagingHelper();
  var endlessContainer = this.GetEndlessPagingContainer();
  if(!endlessPagingHelper || !endlessPagingHelper.NeedShowLoadingPanelAtBottom() || !endlessContainer) {
   this.CreateLoadingPanelWithAbsolutePosition(this.GetContentCell(), this.GetLoadingPanelOffsetElement(this.GetContentCell()));
   return;
  }
  var nodes = endlessContainer.childNodes;
  for(var i = 0; i < nodes.length; i++)
   ASPx.RemoveElement(nodes[i]);
  this.CreateLoadingPanelWithoutBordersInsideContainer(endlessContainer);
 },
 ShowLoadingDiv: function () {
  this.CreateLoadingDiv(this.GetContentCell());
 },
 GetCallbackAnimationElement: function () {
  var itemsCell = this.GetItemsCell();
  if(itemsCell)
   return itemsCell.firstChild;
  return null;
 },
 GetEndlessPagingMode: function () {
  if(ASPx.IsExists(this.stateObject) && ASPx.IsExists(this.stateObject.endlessPagingMode))
   return this.stateObject.endlessPagingMode;
  return this.EndlessPagingMode.Disabled;
 },
 UseEndlessPaging: function () {
  return !!this.GetEndlessPagingMode();
 },
 GetEndlessPagingHelper: function () {
  if(!this.UseEndlessPaging())
   return;
  if(!this.endlessPagingHelper)
   this.endlessPagingHelper = new ASPxClientDataViewEndlessPagingHelper(this);
  return this.endlessPagingHelper;
 },
 ChangeEndlessPagingContainerVisibility: function() {
  var epContainer = this.GetEndlessPagingContainer();
  if(epContainer && epContainer.parentNode) {
   var isEPContainerVisible = !!epContainer.innerHTML && !(new RegExp(/^\s+$/).test(epContainer.innerHTML));
   ASPx.SetElementDisplay(epContainer.parentNode, isEPContainerVisible);
  }
 },
 OnBrowserWindowResize: function(e){
  ASPxClientControl.prototype.OnBrowserWindowResize.call(this, e);
  this.UpdateItemsScroller();
 },
 UpdateItemsScroller: function(){
  var scroller = this.GetItemsScroller();
  if(scroller){
   var scrollerParent = scroller.parentNode;
   scroller.style.height = "0px";
   scroller.style.height = (scrollerParent.offsetHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(scrollerParent)) + "px";
  }
 },
 SetHeight: function(height) {
  ASPxClientControl.prototype.SetHeight.call(this, height);
  this.UpdateItemsScroller();
 },
 GotoPage: function (pageIndex) {
  this.DoPagerClick(ASPx.PagerCommands.PageNumber + pageIndex);
 },
 GetPageIndex: function () {
  return this.stateObject.pageIndex;
 },
 GetPageSize: function () {
  return this.stateObject.pageSize;
 },
 SetPageSize: function (pageSize) {
  this.DoPagerClick(ASPx.PagerCommands.PageSize + pageSize);
 },
 GetPageCount: function () {
  return this.stateObject.pageCount;
 },
 NextPage: function () {
  this.DoPagerClick(ASPx.PagerCommands.Next);
 },
 PrevPage: function () {
  this.DoPagerClick(ASPx.PagerCommands.Prev);
 },
 FirstPage: function () {
  this.DoPagerClick(ASPx.PagerCommands.First);
 },
 LastPage: function (focusBottomRow) {
  this.DoPagerClick(ASPx.PagerCommands.Last);
 },
 PerformCallback: function (parameter, onSuccess) {
  this.CustomCallback(parameter, onSuccess);
 }
});
ASPxClientDataView.Cast = ASPxClientControl.Cast;
var ASPxClientDataViewEndlessPagingHelper = ASPx.CreateClass(null, {
 constructor: function (dataView) {
  this.dataView = dataView;
  this.needShowLoadingPanelAtBottom = false;
  this.pagingInProcess = false;
  this.containerVisible = true;
 },
 LoadNextPageIfRequired: function () {
  if(this.containerVisible)
   this.dataView.NextPage();
 },
 NeedShowLoadingPanelAtBottom: function () {
  return this.needShowLoadingPanelAtBottom;
 },
 GetEndlessPagingContainer: function() {
  return this.dataView.GetEndlessPagingContainer();
 },
 GetEndlessPagingMode: function () {
  return this.dataView.GetEndlessPagingMode();
 },
 IsTableLayout: function() {
  return this.dataView.IsTableLayoutMode();
 },
 InitializeContainerVisibility: function() {
  if(!this.GetEndlessPagingContainer())
   this.containerVisible = false;
 },
 SubscribeContainerVisibility: function() {
  var epContainer = this.GetEndlessPagingContainer();
  if(epContainer)
   ASPx.IntersectionObserversManager.SubscribeElemensVisibilityChangeInBrowserWindow(epContainer, this.OnContainerVisibilityChanged.bind(this));
 },
 OnContainerVisibilityChanged: function(visible) {
  this.containerVisible = visible;
  if(visible)
   this.LoadNextPageIfRequired();
 },
 Initialize: function () {
  this.InitializeContainerVisibility();
  if(this.GetEndlessPagingMode() === this.dataView.EndlessPagingMode.OnScroll)
   this.SubscribeContainerVisibility();
 },
 OnDoPagerClick: function (command) {
  this.needShowLoadingPanelAtBottom = command == ASPx.PagerCommands.Next;
  this.pagingInProcess = true;
 },
 OnCallback: function (html, epHtml) {
  this.dataView.HideLoadingElements();
  this.ClearEPContainer();
  this.needShowLoadingPanelAtBottom = false;
  var container = this.GetEndlessPagingContainer();
  if(container)
   ASPx.SetInnerHtml(container, epHtml);
  var itemsContainer = this.GetUpdatableItemsContainer();
  if(itemsContainer) {
   if(this.IsTableLayout())
    this.InsertRows(itemsContainer, html);
   else
    itemsContainer.insertAdjacentHTML("beforeEnd", html);
  }
  this.dataView.ChangeEndlessPagingContainerVisibility();
  this.pagingInProcess = false;
 },
 DoEndCallback: function() {
  if(this.GetEndlessPagingMode() === this.dataView.EndlessPagingMode.OnScroll) {
   this.SubscribeContainerVisibility();
   setTimeout(this.LoadNextPageIfRequired.aspxBind(this), 500);
  }
 },
 ClearEPContainer: function () {
  var epContainer = this.GetEndlessPagingContainer();
  if(!epContainer)
   return;
  var nodes = epContainer.childNodes;
  for(var i = 0; i < nodes.length; i++)
   ASPx.RemoveElement(nodes[i]);
 },
 InsertRows: function (table, rowsHtml) {
  var row = document.createElement("TR");
  var cell = document.createElement("TD");
  cell.innerHTML = "<table><tbody>" + rowsHtml + "</tbody></table>";
  var tbody = table.tBodies[0];
  tbody.appendChild(row);
  row.appendChild(cell);
  var newTable = ASPx.GetNodeByTagName(cell, "TABLE", 0);
  while(newTable.rows.length > 0)
   tbody.appendChild(newTable.rows[0]);
  ASPx.RemoveElement(row);
 },
 GetUpdatableItemsContainer: function () {
  var itemsCell = this.dataView.GetItemsCell();
  if(!itemsCell)
   return null;
  var contentTable = ASPx.GetNodesByTagName(itemsCell, "TABLE")[0];
  if(this.IsTableLayout())
   return contentTable;
  return contentTable.rows[0].cells[0];
 }
});
ASPxClientDataViewCollection = {
 instances: { },
 add: function(dataView){
  ASPxClientDataViewCollection.instances[dataView.name] = dataView;
 },
 remove: function(name){
  delete ASPxClientDataViewCollection.instances[name];
 },
 get: function(name){
  return ASPxClientDataViewCollection.instances[name];
 },
 onScroll: function(evt){
  for(var name in ASPxClientDataViewCollection.instances) {
   if(ASPxClientDataViewCollection.instances.hasOwnProperty(name)) {
    var dataView = ASPxClientDataViewCollection.get(name);
    if(!dataView || !ASPx.IsExists(dataView.GetMainElement()))
     ASPxClientDataViewCollection.remove(name);
   }
  }
 }
};
ASPx.Evt.AttachEventToElement(window, 'scroll', function(evt){ ASPxClientDataViewCollection.onScroll(evt); });
ASPx.DVPagerClick = function(name, value) {
 var dv = ASPx.GetControlCollection().Get(name);
 if(dv != null)
  dv.DoPagerClick(value);
};
ASPx.DVEPClick = function(name) {
 var dataView = ASPx.GetControlCollection().Get(name);
 if(dataView)
  dataView.NextPage();
};
window.ASPxClientDataView = ASPxClientDataView;
})();
(function() {
var MVCxClientDataView = ASPx.CreateClass(ASPxClientDataView, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.customActionUrl = "";
  this.callbackCustomArgs = {};
  this.customActionCallBack = null;
 },
 PerformCallback: function(data, onSuccess){
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientDataView.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ 
    MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs); 
   }; 
  if (this.customActionUrl != "")
   this.customActionCallBack = function(arg){ 
    MVCx.PerformControlCallback(this.name, this.customActionUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs); 
   };
  ASPxClientDataView.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function (arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(arg) {
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 EvalCallbackResult: function (resultString) {
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2) {
   var resultObj = ASPxClientDataView.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientDataView.prototype.EvalCallbackResult.call(this, resultString);
 },
 CreateCallbackCore: function(arg, command, callbackID){
  if(this.callbackCustomArgs != {})
   window.setTimeout(function(){ this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientDataView.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 GetCallbackMethod: function(command){
  return MVCx.IsCustomCallback(command) ? MVCx.GetCustomActionCallBackMethod(this) : this.callBack;
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientDataView.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientDataView.Cast = ASPxClientControl.Cast;
window.MVCxClientDataView = MVCxClientDataView;
})();

(function () {
ASPx.StateItemsExist = false;
ASPx.FocusedItemKind = "FocusedStateItem";
ASPx.HoverItemKind = "HoverStateItem";
ASPx.PressedItemKind = "PressedStateItem";
ASPx.SelectedItemKind = "SelectedStateItem";
ASPx.DisabledItemKind = "DisabledStateItem";
ASPx.ReadOnlyItemKind = "ReadOnlyStateItem";
ASPx.CachedStatePrefix = "cached";
ASPxStateItem = ASPx.CreateClass(null, {
 constructor: function(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, kind, disableApplyingStyleToLink){
  this.name = name;
  this.classNames = classNames;
  this.customClassNames = [];
  this.resultClassNames = [];
  this.cssTexts = cssTexts;
  this.postfixes = postfixes;
  this.imageObjs = imageObjs;
  this.imagePostfixes = imagePostfixes;
  this.kind = kind;
  this.classNamePostfix = kind.substr(0, 1).toLowerCase();
  this.enabled = true;
  this.needRefreshBetweenElements = false;
  this.elements = null;
  this.images = null;
  this.links = [];
  this.colorChanged = [];
  this.textDecorationChanged = [];
  this.disableApplyingStyleToLink = !!disableApplyingStyleToLink; 
 },
 GetCssText: function(index){
  if(ASPx.IsExists(this.cssTexts[index]))
   return this.cssTexts[index];
  return this.cssTexts[0];
 },
 CreateStyleRule: function(index){
  if(this.GetCssText(index) == "") return "";
  var styleSheet = ASPx.GetCurrentStyleSheet();
  if(styleSheet)
   return ASPx.CreateImportantStyleRule(styleSheet, this.GetCssText(index), this.classNamePostfix);  
  return ""; 
 },
 GetClassName: function(index){
  if(ASPx.IsExists(this.classNames[index]))
   return this.classNames[index];
  return this.classNames[0];
 },
 GetResultClassName: function(index){
  if(!ASPx.IsExists(this.resultClassNames[index])) {
   if(!ASPx.IsExists(this.customClassNames[index]))
    this.customClassNames[index] = this.CreateStyleRule(index);
   if(this.GetClassName(index) != "" && this.customClassNames[index] != "")
    this.resultClassNames[index] = this.GetClassName(index) + " " + this.customClassNames[index];
   else if(this.GetClassName(index) != "")
    this.resultClassNames[index] = this.GetClassName(index);
   else if(this.customClassNames[index] != "")
    this.resultClassNames[index] = this.customClassNames[index];
   else
    this.resultClassNames[index] = "";
  }
  return this.resultClassNames[index];
 },
 GetElements: function(element){
  if(!this.elements || !ASPx.IsValidElements(this.elements)){
   if(this.postfixes && this.postfixes.length > 0){
    this.elements = [ ];
    var parentNode = element.parentNode;
    if(parentNode){
     for(var i = 0; i < this.postfixes.length; i++){
      var id = this.name + this.postfixes[i];
      this.elements[i] = ASPx.GetChildById(parentNode, id);
      if(!this.elements[i])
       this.elements[i] = ASPx.GetElementById(id);
     }
    }
   }
   else
    this.elements = [element];
  }
  return this.elements;
 },
 GetImages: function(element){
  if(!this.images || !ASPx.IsValidElements(this.images)){
   this.images = [ ];
   if(this.imagePostfixes && this.imagePostfixes.length > 0){
    var elements = this.GetElements(element);
    for(var i = 0; i < this.imagePostfixes.length; i++){
     var id = this.name + this.imagePostfixes[i];
     for(var j = 0; j < elements.length; j++){
      if(!elements[j]) continue;
      if(elements[j].id == id)
       this.images[i] = elements[j];
      else
       this.images[i] = ASPx.GetChildById(elements[j], id);
      if(this.images[i])
       break;
     }
    }
   }
  }
  return this.images;
 },
 Apply: function(element){
  if(!this.enabled) return;
  try{
   this.ApplyStyle(element);
   if(this.imageObjs && this.imageObjs.length > 0)
    this.ApplyImage(element);
  }
  catch(e){
  }
 },
 ApplyStyle: function(element){
  var elements = this.GetElements(element);
  for(var i = 0; i < elements.length; i++){
   if(!elements[i]) continue;
   var elementColor, elementTextDecoration;
   if(this.colorChanged[i] === undefined) {
    elementColor = window.getComputedStyle(elements[i]).color;
   }
   if(this.textDecorationChanged[i] === undefined) {
    elementTextDecoration = window.getComputedStyle(elements[i]).textDecoration;
   }
   if(this.GetResultClassName(i) != "") {
    var className = elements[i].className.replace(this.GetResultClassName(i), "");
    elements[i].className = ASPx.Str.Trim(className) + " " + this.GetResultClassName(i);
   }
   if(this.colorChanged[i] === undefined) {
    this.colorChanged[i] = window.getComputedStyle(elements[i]).color !== elementColor;
   }
   if(this.textDecorationChanged[i] === undefined) {
    this.textDecorationChanged[i] = window.getComputedStyle(elements[i]).textDecoration !== elementTextDecoration;
   }
   if(!ASPx.Browser.Opera || ASPx.Browser.Version >= 9)
    this.ApplyStyleToLinks(elements, i);
  }
 },
 ApplyStyleToLinks: function(elements, index){
  if(this.disableApplyingStyleToLink)
   return;
  if(!ASPx.IsValidElements(this.links[index]))
   this.links[index] = ASPx.GetNodesByTagName(elements[index], "A");
  for(var i = 0; i < this.links[index].length; i++)
   this.ApplyStyleToLinkElement(this.links[index][i], index);
 },
 ApplyStyleToLinkElement: function(link, index) {
  if(this.colorChanged[index])
   ASPx.Attr.ChangeAttributeExtended(link.style, "color", link, "saved" + this.kind + "Color", "inherit");
  if(this.textDecorationChanged[index])
   ASPx.Attr.ChangeAttributeExtended(link.style, "text-decoration", link, "saved" + this.kind + "TextDecoration", "inherit");
 },
 ApplyImage: function(element){
  var images = this.GetImages(element);
  for(var i = 0; i < images.length; i++){
   if(!images[i] || !this.imageObjs[i]) continue;
   var useSpriteImage = typeof(this.imageObjs[i]) != "string";
   var newUrl = "", newCssClass = "", newBackground = "";
   if(useSpriteImage){
    newUrl = ASPx.EmptyImageUrl;           
    if(this.imageObjs[i].spriteCssClass) 
     newCssClass = this.imageObjs[i].spriteCssClass;
    if(this.imageObjs[i].spriteBackground)
     newBackground = this.imageObjs[i].spriteBackground;
   }
   else{
    newUrl = this.imageObjs[i];
    if(ASPx.Attr.IsExistsAttribute(images[i].style, "background"))   
     newBackground = " ";
   }
   if(newUrl != "")
    ASPx.Attr.ChangeAttributeExtended(images[i], "src", images[i], "saved" + this.kind + "Src", newUrl);
   if(newCssClass != "")
    this.ApplyImageClassName(images[i], newCssClass);
   if(newBackground != ""){
    if(ASPx.Browser.WebKitFamily) {
     var savedBackground = ASPx.Attr.GetAttribute(images[i].style, "background");
     if(!useSpriteImage)
      savedBackground += " " + images[i].style["backgroundPosition"];
     ASPx.Attr.SetAttribute(images[i], "saved" + this.kind + "Background", savedBackground);
     ASPx.Attr.SetAttribute(images[i].style, "background", newBackground);
    }
    else
     ASPx.Attr.ChangeAttributeExtended(images[i].style, "background", images[i], "saved" + this.kind + "Background", newBackground);
   }     
  }
 },
 ApplyImageClassName: function(element, newClassName){
  if(ASPx.Attr.GetAttribute(element, "saved" + this.kind + "ClassName"))
   this.CancelImageClassName(element);
  var className = element.className;
  ASPx.Attr.SetAttribute(element, "saved" + this.kind + "ClassName", className);
  element.className = className + " " + newClassName;
 },
 Cancel: function(element){
  if(!this.enabled) return;
  try{  
   if(this.imageObjs && this.imageObjs.length > 0)
    this.CancelImage(element);
   this.CancelStyle(element);
  }
  catch(e){
  }
 },
 CancelStyle: function(element){
  var elements = this.GetElements(element);
  for(var i = 0; i < elements.length; i++){
   if(!elements[i]) continue;
   if(this.GetResultClassName(i) != "") {
    var className = ASPx.Str.Trim(elements[i].className.replace(this.GetResultClassName(i), ""));
    elements[i].className = className;
   }
   if(!ASPx.Browser.Opera || ASPx.Browser.Version >= 9)
    this.CancelStyleFromLinks(elements, i);
  }
 },
 CancelStyleFromLinks: function(elements, index){
  if(this.disableApplyingStyleToLink)
   return;
  if(!ASPx.IsValidElements(this.links[index]))
   this.links[index] = ASPx.GetNodesByTagName(elements[index], "A");
  for(var i = 0; i < this.links[index].length; i++)
   this.CancelStyleFromLinkElement(this.links[index][i], index);
 },
 CancelStyleFromLinkElement: function(link, index){
  ASPx.Attr.RestoreAttributeExtended(link.style, "color", link, "saved" + this.kind + "Color");
  ASPx.Attr.RestoreAttributeExtended(link.style, "text-decoration", link, "saved" + this.kind + "TextDecoration");
 },
 CancelImage: function(element){
  var images = this.GetImages(element);
  for(var i = 0; i < images.length; i++){
   if(!images[i] || !this.imageObjs[i]) continue;
   ASPx.Attr.RestoreAttributeExtended(images[i], "src", images[i], "saved" + this.kind + "Src");
   this.CancelImageClassName(images[i]);
   ASPx.Attr.RestoreAttributeExtended(images[i].style, "background", images[i], "saved" + this.kind + "Background");
  }
 },
 CancelImageClassName: function(element){
  var savedClassName = ASPx.Attr.GetAttribute(element, "saved" + this.kind + "ClassName");
  if(ASPx.IsExists(savedClassName)) {
   element.className = savedClassName;
   ASPx.Attr.RemoveAttribute(element, "saved" + this.kind + "ClassName");
  }
 },
 Clone: function(){
  return new ASPxStateItem(this.name, this.classNames, this.cssTexts, this.postfixes, 
   this.imageObjs, this.imagePostfixes, this.kind, this.disableApplyingStyleToLink);
 },
 IsChildElement: function(element){
  if(element != null){
   var elements = this.GetElements(element);
   for(var i = 0; i < elements.length; i++){
    if(!elements[i]) continue;
    if(ASPx.GetIsParent(elements[i], element)) 
     return true;
   }
  }
  return false;
 },
 ForceRedrawAppearance: function(element) {
  if(!aspxGetStateController().IsForceRedrawAppearanceLocked()) {
   var value = element.style.opacity;
   element.style.opacity = "0.7777";
   var dummy = element.offsetWidth;
   element.style.opacity = value;
  }
 }
});
ASPxClientStateEventArgs = ASPx.CreateClass(null, {
 constructor: function(item, element){
  this.item = item;
  this.element = element;
  this.toElement = null;
  this.fromElement = null;
  this.htmlEvent = null;
 }
});
ASPxStateController = ASPx.CreateClass(null, {
 constructor: function(){
  this.focusedItems = { };
  this.hoverItems = { };
  this.pressedItems = { };
  this.selectedItems = { };
  this.disabledItems = {};
  this.readOnlyItems = {};
  this.disabledScheme = {};
  this.currentFocusedElement = null;
  this.currentFocusedItemName = null;
  this.currentHoverElement = null;
  this.currentHoverItemName = null;
  this.currentPressedElement = null;
  this.currentPressedItemName = null;
  this.savedCurrentPressedElement = null;
  this.savedCurrentMouseMoveSrcElement = null;
  this.forceRedrawAppearanceLockCount = 0;
  this.stateItemType = ASPxStateItem;
  this.AfterSetFocusedState = new ASPxClientEvent();
  this.AfterClearFocusedState = new ASPxClientEvent();
  this.AfterSetHoverState = new ASPxClientEvent();
  this.AfterClearHoverState = new ASPxClientEvent();
  this.AfterSetPressedState = new ASPxClientEvent();
  this.AfterClearPressedState = new ASPxClientEvent();
  this.AfterDisabled = new ASPxClientEvent();
  this.AfterEnabled = new ASPxClientEvent();
  this.BeforeSetFocusedState = new ASPxClientEvent();
  this.BeforeClearFocusedState = new ASPxClientEvent();
  this.BeforeSetHoverState = new ASPxClientEvent();
  this.BeforeClearHoverState = new ASPxClientEvent();
  this.BeforeSetPressedState = new ASPxClientEvent();
  this.BeforeClearPressedState = new ASPxClientEvent();
  this.BeforeDisabled = new ASPxClientEvent();
  this.BeforeEnabled = new ASPxClientEvent();
  this.FocusedItemKeyDown = new ASPxClientEvent();
 }, 
 AddHoverItem: function(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink){
  this.AddItem(this.hoverItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, ASPx.HoverItemKind, disableApplyingStyleToLink);
  this.AddItem(this.focusedItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, ASPx.FocusedItemKind, disableApplyingStyleToLink);
 },
 AddPressedItem: function(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink){
  this.AddItem(this.pressedItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, ASPx.PressedItemKind, disableApplyingStyleToLink);
 },
 AddSelectedItem: function(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink){
  this.AddItem(this.selectedItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, ASPx.SelectedItemKind, disableApplyingStyleToLink);
 },
 AddDisabledItem: function (name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink, rootId) {
  this.AddItem(this.disabledItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes,
   ASPx.DisabledItemKind, disableApplyingStyleToLink, this.addIdToDisabledItemScheme, rootId);
 },
 AddReadOnlyItem: function(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink) {
  this.AddItem(this.readOnlyItems, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, ASPx.ReadOnlyItemKind, disableApplyingStyleToLink);
 },
 addIdToDisabledItemScheme: function(rootId, childId) {
  if (!rootId)
   return;
  if (!this.disabledScheme[rootId])
   this.disabledScheme[rootId] = [rootId];
  if (childId && (rootId != childId) && ASPx.Data.ArrayIndexOf(this.disabledScheme[rootId], childId) == -1)
   this.disabledScheme[rootId].push(childId);
 },
 removeIdFromDisabledItemScheme: function(rootId, childId) {
  if (!rootId || !this.disabledScheme[rootId])
   return;
  ASPx.Data.ArrayRemove(this.disabledScheme[rootId], childId);
  if (this.disabledScheme[rootId].length == 0)
   delete this.disabledScheme[rootId];
 },
 AddItem: function (items, name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, kind, disableApplyingStyleToLink, onAdd, rootId) {
  var type = this.getStateItemType();
  var stateItem = new type(name, classNames, cssTexts, postfixes, imageObjs, imagePostfixes, kind, disableApplyingStyleToLink);
  if (postfixes && postfixes.length > 0) {
   for (var i = 0; i < postfixes.length; i++) {
    items[name + postfixes[i]] = stateItem;
    if (onAdd)
     onAdd.call(this, rootId, name + postfixes[i]);
   }
  }
  else {
   if (onAdd)
    onAdd.call(this, rootId, name);
   items[name] = stateItem;
  }
  ASPx.StateItemsExist = true;
 },
 getStateItemType: function () { return this.stateItemType; },
 withCustomStateItemType: function (newType, callback) {
  this.stateItemType = newType;
  callback(this);
  this.stateItemType = ASPxStateItem;
 },
 RemoveHoverItem: function(name, postfixes){
  this.RemoveItem(this.hoverItems, name, postfixes);
  this.RemoveItem(this.focusedItems, name, postfixes);
 },
 RemovePressedItem: function(name, postfixes){
  this.RemoveItem(this.pressedItems, name, postfixes);
 },
 RemoveSelectedItem: function(name, postfixes){
  this.RemoveItem(this.selectedItems, name, postfixes);
 },
 RemoveDisabledItem: function (name, postfixes, rootId) {
  this.RemoveItem(this.disabledItems, name, postfixes, this.removeIdFromDisabledItemScheme, rootId);
 },
 RemoveReadOnlyItem: function(name, postfixes) {
  this.RemoveItem(this.readOnlyItems, name, postfixes);
 },
 RemoveItem: function (items, name, postfixes, onRemove, rootId) {
  if (postfixes && postfixes.length > 0) {
   for (var i = 0; i < postfixes.length; i++) {
    delete items[name + postfixes[i]];
    if (onRemove)
     onRemove.call(this, rootId, name + postfixes[i]);
   }
  }
  else {
   delete items[name];
   if (onRemove)
    onRemove.call(this, rootId, name);
  }
 },
 RemoveDisposedItems: function(){
  this.RemoveDisposedItemsByType(this.hoverItems);
  this.RemoveDisposedItemsByType(this.pressedItems);
  this.RemoveDisposedItemsByType(this.focusedItems);
  this.RemoveDisposedItemsByType(this.selectedItems);
  this.RemoveDisposedItemsByType(this.disabledItems);
  this.RemoveDisposedItemsByType(this.disabledScheme);
  this.RemoveDisposedItemsByType(this.readOnlyItems);
 },
 RemoveDisposedItemsByType: function(items){
  for(var key in items) {
   if(items.hasOwnProperty(key)) {
    var item = items[key];
    var element = document.getElementById(key);
    if(!element || !ASPx.IsValidElement(element))
     delete items[key];
    try {
     if(item && item.elements) {
      for(var i = 0; i < item.elements.length; i++) {
       if(!ASPx.IsValidElements(item.links[i]))
        item.links[i] = null;
      }
     }
    }
    catch(e) {
    }
   }
  }
 },
 GetFocusedElement: function(srcElement){
  return this.GetItemElement(srcElement, this.focusedItems, ASPx.FocusedItemKind);
 },
 GetHoverElement: function(srcElement){
  return this.GetItemElement(srcElement, this.hoverItems, ASPx.HoverItemKind);
 },
 GetPressedElement: function(srcElement){
  return this.GetItemElement(srcElement, this.pressedItems, ASPx.PressedItemKind);
 },
 GetSelectedElement: function(srcElement){
  return this.GetItemElement(srcElement, this.selectedItems, ASPx.SelectedItemKind);
 },
 GetDisabledElement: function(srcElement){
  return this.GetItemElement(srcElement, this.disabledItems, ASPx.DisabledItemKind);
 },
 GetReadOnlyElement: function(srcElement) {
  return this.GetItemElement(srcElement, this.readOnlyItems, ASPx.ReadOnlyItemKind);
 },
 GetItemElement: function(srcElement, items, kind){
  if(srcElement && srcElement[ASPx.CachedStatePrefix + kind]){
   var cachedElement = srcElement[ASPx.CachedStatePrefix + kind];
   if(cachedElement != ASPx.EmptyObject)
    return cachedElement;
   return null;
  }
  var element = srcElement;
  while(element != null) {
   var item = items[element.id];
   if(item){
    this.CacheItemElement(srcElement, kind, element);
    element[kind] = item;
    return element;
   }
   element = element.parentNode;
  }
  this.CacheItemElement(srcElement, kind, ASPx.EmptyObject);
  return null;
 },
 CacheItemElement: function(srcElement, kind, value){
  if(srcElement && !srcElement[ASPx.CachedStatePrefix + kind])
   srcElement[ASPx.CachedStatePrefix + kind] = value;
 },
 DoSetFocusedState: function(element, fromElement){
  var item = element[ASPx.FocusedItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   args.fromElement = fromElement;
   this.BeforeSetFocusedState.FireEvent(this, args);
   item.Apply(element);
   this.AfterSetFocusedState.FireEvent(this, args);
  }
 },
 DoClearFocusedState: function(element, toElement){
  var item = element[ASPx.FocusedItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   args.toElement = toElement;
   this.BeforeClearFocusedState.FireEvent(this, args);
   item.Cancel(element);
   this.AfterClearFocusedState.FireEvent(this, args);
  }
 },
 DoSetHoverState: function(element, fromElement){
  var item = element[ASPx.HoverItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   args.fromElement = fromElement;
   this.BeforeSetHoverState.FireEvent(this, args);
   item.Apply(element);
   this.AfterSetHoverState.FireEvent(this, args);
  }
 },
 DoClearHoverState: function(element, toElement){
  var item = element[ASPx.HoverItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   args.toElement = toElement;
   this.BeforeClearHoverState.FireEvent(this, args);
   item.Cancel(element);
   this.AfterClearHoverState.FireEvent(this, args);
  }
 },
 DoSetPressedState: function(element){
  var item = element[ASPx.PressedItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   this.BeforeSetPressedState.FireEvent(this, args);
   item.Apply(element);
   this.AfterSetPressedState.FireEvent(this, args);
  }
 },
 DoClearPressedState: function(element){
  var item = element[ASPx.PressedItemKind];
  if(item){
   var args = new ASPxClientStateEventArgs(item, element);
   this.BeforeClearPressedState.FireEvent(this, args);
   item.Cancel(element);
   this.AfterClearPressedState.FireEvent(this, args);
  }
 },
 SetCurrentFocusedElement: function(element){
  if(this.currentFocusedElement && !ASPx.IsValidElement(this.currentFocusedElement)){
   this.currentFocusedElement = null;
   this.currentFocusedItemName = "";
  }
  if(this.currentFocusedElement != element){
   var oldCurrentFocusedElement = this.currentFocusedElement;
   var item = (element != null) ? element[ASPx.FocusedItemKind] : null;
   var itemName = (item != null) ? item.name : "";
   if(this.currentFocusedItemName != itemName){
    if(this.currentHoverItemName != "")
     this.SetCurrentHoverElement(null);
    if(this.currentFocusedElement != null)
     this.DoClearFocusedState(this.currentFocusedElement, element);
    this.currentFocusedElement = element;
    item = (element != null) ? element[ASPx.FocusedItemKind] : null;
    this.currentFocusedItemName = (item != null) ? item.name : "";
    if(this.currentFocusedElement != null)
     this.DoSetFocusedState(this.currentFocusedElement, oldCurrentFocusedElement);
   }
  }
 },
 GetCurrentHoverElement: function() {
  return this.currentHoverElement;
 },
 SetCurrentHoverElement: function(element){
  if(this.currentHoverElement && !ASPx.IsValidElement(this.currentHoverElement)){
   this.currentHoverElement = null;
   this.currentHoverItemName = "";
  }
  var item = (element != null) ? element[ASPx.HoverItemKind] : null;
  if(item && !item.enabled) { 
   element = this.GetItemElement(element.parentNode, this.hoverItems, ASPx.HoverItemKind);
   item = (element != null) ? element[ASPx.HoverItemKind] : null;
  }
  if(this.currentHoverElement != element){
   var oldCurrentHoverElement = this.currentHoverElement,
    itemName = (item != null) ? item.name : "";
   if(this.currentHoverItemName != itemName || (item != null && item.needRefreshBetweenElements)){
    if(this.currentHoverElement != null)
     this.DoClearHoverState(this.currentHoverElement, element);
    item = (element != null) ? element[ASPx.HoverItemKind] : null;
    if(item == null || item.enabled){
     this.currentHoverElement = element;
     this.currentHoverItemName = (item != null) ? item.name : "";
     if(this.currentHoverElement != null)
      this.DoSetHoverState(this.currentHoverElement, oldCurrentHoverElement);
    }
   }
  }
 },
 SetCurrentPressedElement: function(element){
  if(this.currentPressedElement && !ASPx.IsValidElement(this.currentPressedElement)){
   this.currentPressedElement = null;
   this.currentPressedItemName = "";
  }
  if(this.currentPressedElement != element){
   if(this.currentPressedElement != null)
    this.DoClearPressedState(this.currentPressedElement);
   var item = (element != null) ? element[ASPx.PressedItemKind] : null;
   if(item == null || item.enabled){
    this.currentPressedElement = element;
    this.currentPressedItemName = (item != null) ? item.name : "";
    if(this.currentPressedElement != null)
     this.DoSetPressedState(this.currentPressedElement);
   }
  }
 },
 SetCurrentFocusedElementBySrcElement: function(srcElement){
  var element = this.GetFocusedElement(srcElement);
  this.SetCurrentFocusedElement(element);
 },
 SetCurrentHoverElementBySrcElement: function(srcElement){
  var element = this.GetHoverElement(srcElement);
  this.SetCurrentHoverElement(element);
 },
 SetCurrentPressedElementBySrcElement: function(srcElement){
  var element = this.GetPressedElement(srcElement);
  this.SetCurrentPressedElement(element);
 },
 SetPressedElement: function (element) {
  this.SetCurrentHoverElement(null);
  this.SetCurrentPressedElementBySrcElement(element);
  this.savedCurrentPressedElement = this.currentPressedElement;
 },
 SelectElement: function (element) {
  var item = element[ASPx.SelectedItemKind];
  if(item)
   item.Apply(element);
 }, 
 SelectElementBySrcElement: function(srcElement){
  var element = this.GetSelectedElement(srcElement);
  if(element != null) this.SelectElement(element);
 }, 
 DeselectElement: function(element){
  var item = element[ASPx.SelectedItemKind];
  if(item)
   item.Cancel(element);
 }, 
 DeselectElementBySrcElement: function(srcElement){
  var element = this.GetSelectedElement(srcElement);
  if(element != null) this.DeselectElement(element);
 },
 SetElementEnabled: function(element, enable){
  if(enable)
   this.EnableElement(element);
  else
   this.DisableElement(element);
 },
 SetElementReadOnly: function(element, readOnly) {
  var element = this.GetReadOnlyElement(element);
  if (element != null) {
   var item = element[ASPx.ReadOnlyItemKind];
   if(item) {
    if(readOnly) {
     if(item.name == this.currentPressedItemName)
      this.SetCurrentPressedElement(null);
     if(item.name == this.currentHoverItemName)
      this.SetCurrentHoverElement(null);
    }
    if(readOnly)
     item.Apply(element);
    else
     item.Cancel(element);
   }
  }
 },
 SetElementWithChildNodesEnabled: function (parentName, enabled) {
  var procFunct = (enabled ? this.EnableElement : this.DisableElement);
  var childItems = this.disabledScheme[parentName];
  if (childItems && childItems.length > 0)
   for (var i = 0; i < childItems.length; i++) {
    procFunct.call(this, document.getElementById(childItems[i]));
   }
 },
 DisableElement: function (element) {
  var element = this.GetDisabledElement(element);
  if(element != null) {
   var item = element[ASPx.DisabledItemKind];
   if(item){
    var args = new ASPxClientStateEventArgs(item, element);
    this.BeforeDisabled.FireEvent(this, args);
    if(item.name == this.currentPressedItemName)
     this.SetCurrentPressedElement(null);
    if(item.name == this.currentHoverItemName)
     this.SetCurrentHoverElement(null);
    item.Apply(element);
    this.SetMouseStateItemsEnabled(item.name, item.postfixes, false);
    this.AfterDisabled.FireEvent(this, args);
   }
  }
 }, 
 EnableElement: function(element){
  var element = this.GetDisabledElement(element);
  if(element != null) {
   var item = element[ASPx.DisabledItemKind];
   if(item){
    var args = new ASPxClientStateEventArgs(item, element);
    this.BeforeEnabled.FireEvent(this, args);
    item.Cancel(element);
    this.SetMouseStateItemsEnabled(item.name, item.postfixes, true);
    this.AfterEnabled.FireEvent(this, args);
   }
  }
 }, 
 SetMouseStateItemsEnabled: function(name, postfixes, enabled){   
  if(postfixes && postfixes.length > 0){
   for(var i = 0; i < postfixes.length; i ++){
    this.SetItemsEnabled(this.hoverItems, name + postfixes[i], enabled);
    this.SetItemsEnabled(this.pressedItems, name + postfixes[i], enabled);
    this.SetItemsEnabled(this.focusedItems, name + postfixes[i], enabled);
   }
  }
  else{
   this.SetItemsEnabled(this.hoverItems, name, enabled);
   this.SetItemsEnabled(this.pressedItems, name, enabled);
   this.SetItemsEnabled(this.focusedItems, name, enabled);
  }  
 },
 SetItemsEnabled: function(items, name, enabled){   
  if(items[name])
   items[name].enabled = enabled;
 },
 OnFocusMove: function(evt){
  var element = ASPx.Evt.GetEventSource(evt);
  aspxGetStateController().SetCurrentFocusedElementBySrcElement(element);
 },
 OnMouseMove: function(evt, checkElementChanged){
  var srcElement = ASPx.Evt.GetEventSource(evt);
  if(checkElementChanged && srcElement == this.savedCurrentMouseMoveSrcElement) return;
  this.savedCurrentMouseMoveSrcElement = srcElement;
  if(this.savedCurrentPressedElement == null)
   this.SetCurrentHoverElementBySrcElement(srcElement);
  else{
   var element = this.GetPressedElement(srcElement);
   if(element != this.currentPressedElement){
    if(element == this.savedCurrentPressedElement)
     this.SetCurrentPressedElement(this.savedCurrentPressedElement);
    else
     this.SetCurrentPressedElement(null);
   }
  }
 },
 OnMouseDown: function(evt){
  if(!ASPx.Evt.IsLeftButtonPressed(evt)) return;
  var srcElement = ASPx.Evt.GetEventSource(evt);
  this.OnMouseDownOnElement(srcElement);
 },
 OnMouseDownOnElement: function (element) {
  if(this.GetPressedElement(element) == null) return;
  this.SetPressedElement(element);
 },
 OnMouseUp: function(evt){
  var srcElement = ASPx.Evt.GetEventSource(evt);
  this.OnMouseUpOnElement(srcElement);
 },
 OnMouseUpOnElement: function(element){
  if(this.savedCurrentPressedElement == null) return;
  this.ClearSavedCurrentPressedElement();
  this.SetCurrentHoverElementBySrcElement(element);
 },
 OnMouseOver: function(evt){
  var element = ASPx.Evt.GetEventSource(evt);
  if(element && element.tagName == "IFRAME")
   this.OnMouseMove(evt, true);
 },
 OnKeyDown: function(evt){
  var element = this.GetFocusedElement(ASPx.Evt.GetEventSource(evt));
  if(element != null && element == this.currentFocusedElement) {
   var item = element[ASPx.FocusedItemKind];
   if(item){
    var args = new ASPxClientStateEventArgs(item, element);
    args.htmlEvent = evt;
    this.FocusedItemKeyDown.FireEvent(this, args);
   }
  }
 },
 OnKeyUpOnElement: function(evt) {
  if(this.savedCurrentPressedElement != null && ASPx.Evt.IsActionKeyPressed(evt))
   this.ClearSavedCurrentPressedElement();
 },
 OnSelectStart: function(evt){
  if(this.savedCurrentPressedElement) {
   ASPx.Selection.Clear();
   return false;
  }
 },
 ClearSavedCurrentPressedElement: function() {
  this.savedCurrentPressedElement = null;
  this.SetCurrentPressedElement(null);
 },
 ClearCache: function(srcElement, kind) {
  if(srcElement[ASPx.CachedStatePrefix + kind])
   srcElement[ASPx.CachedStatePrefix + kind] = null;
 },
 ClearElementCache: function(srcElement) {
  this.ClearCache(srcElement, ASPx.FocusedItemKind);
  this.ClearCache(srcElement, ASPx.HoverItemKind);
  this.ClearCache(srcElement, ASPx.PressedItemKind);
  this.ClearCache(srcElement, ASPx.SelectedItemKind);
  this.ClearCache(srcElement, ASPx.DisabledItemKind);
 },
 ClearElementCacheInContainer: function(container) {
  var elements = ASPx.GetNodes(container);
  elements.push(container);
  ASPx.Data.ForEach(elements, this.ClearElementCache.bind(this));
 },
 LockForceRedrawAppearance: function() {
  this.forceRedrawAppearanceLockCount++;
 },
 UnlockForceRedrawAppearance: function() {
  this.forceRedrawAppearanceLockCount--;
 },
 IsForceRedrawAppearanceLocked: function() {
  return this.forceRedrawAppearanceLockCount > 0;
 },
 GetHoverItem: function(srcElement) {
  var element = this.GetHoverElement(srcElement);
  return (element != null) ? element[ASPx.HoverItemKind] : null;
 }
});
var stateController = null;
function aspxGetStateController(){
 if(stateController == null)
  stateController = new ASPxStateController();
 return stateController;
}
function aspxAddStateItems(method, namePrefix, classes, disableApplyingStyleToLink){
 for(var i = 0; i < classes.length; i ++){
  for(var j = 0; j < classes[i][2].length; j ++) {
   var name = namePrefix;
   if(classes[i][2][j])
    name += "_" + classes[i][2][j];
   var postfixes = classes[i][3] || null;
   var imageObjs = (classes[i][4] && classes[i][4][j]) || null;
   var imagePostfixes = classes[i][5] || null;
   method.call(aspxGetStateController(), name, classes[i][0], classes[i][1], postfixes, imageObjs, imagePostfixes, disableApplyingStyleToLink, namePrefix);
  }
 }
}
ASPx.AddHoverItems = function(namePrefix, classes, disableApplyingStyleToLink){
 aspxAddStateItems(aspxGetStateController().AddHoverItem, namePrefix, classes, disableApplyingStyleToLink);
};
ASPx.AddPressedItems = function(namePrefix, classes, disableApplyingStyleToLink){
 aspxAddStateItems(aspxGetStateController().AddPressedItem, namePrefix, classes, disableApplyingStyleToLink);
};
ASPx.AddSelectedItems = function(namePrefix, classes, disableApplyingStyleToLink){
 aspxAddStateItems(aspxGetStateController().AddSelectedItem, namePrefix, classes, disableApplyingStyleToLink);
};
ASPx.AddDisabledItems = function(namePrefix, classes, disableApplyingStyleToLink){
 aspxAddStateItems(aspxGetStateController().AddDisabledItem, namePrefix, classes, disableApplyingStyleToLink);
};
ASPx.AddReadOnlyItems = function(namePrefix, classes, disableApplyingStyleToLink) {
 aspxAddStateItems(aspxGetStateController().AddReadOnlyItem, namePrefix, classes, disableApplyingStyleToLink);
};
function aspxRemoveStateItems(method, namePrefix, classes){
 for(var i = 0; i < classes.length; i ++){
  for(var j = 0; j < classes[i][0].length; j ++) {
   var name = namePrefix;
   if(classes[i][0][j])
    name += "_" + classes[i][0][j];
   method.call(aspxGetStateController(), name, classes[i][1], namePrefix);
  }
 }
}
ASPx.RemoveHoverItems = function(namePrefix, classes){
 aspxRemoveStateItems(aspxGetStateController().RemoveHoverItem, namePrefix, classes);
};
ASPx.RemovePressedItems = function(namePrefix, classes){
 aspxRemoveStateItems(aspxGetStateController().RemovePressedItem, namePrefix, classes);
};
ASPx.RemoveSelectedItems = function(namePrefix, classes){
 aspxRemoveStateItems(aspxGetStateController().RemoveSelectedItem, namePrefix, classes);
};
ASPx.RemoveDisabledItems = function(namePrefix, classes){
 aspxRemoveStateItems(aspxGetStateController().RemoveDisabledItem, namePrefix, classes);
};
ASPx.RemoveReadOnlyItems = function(namePrefix, classes) {
 aspxRemoveStateItems(aspxGetStateController().RemoveReadOnlyItem, namePrefix, classes);
};
ASPx.AddAfterClearFocusedState = function(handler){
 aspxGetStateController().AfterClearFocusedState.AddHandler(handler);
};
ASPx.AddAfterSetFocusedState = function(handler){
 aspxGetStateController().AfterSetFocusedState.AddHandler(handler);
};
ASPx.AddAfterClearHoverState = function(handler){
 aspxGetStateController().AfterClearHoverState.AddHandler(handler);
};
ASPx.AddAfterSetHoverState = function(handler){
 aspxGetStateController().AfterSetHoverState.AddHandler(handler);
};
ASPx.AddAfterClearPressedState = function(handler){
 aspxGetStateController().AfterClearPressedState.AddHandler(handler);
};
ASPx.AddAfterSetPressedState = function(handler){
 aspxGetStateController().AfterSetPressedState.AddHandler(handler);
};
ASPx.AddAfterDisabled = function(handler){
 aspxGetStateController().AfterDisabled.AddHandler(handler);
};
ASPx.AddAfterEnabled = function(handler){
 aspxGetStateController().AfterEnabled.AddHandler(handler);
};
ASPx.AddBeforeClearFocusedState = function(handler){
 aspxGetStateController().BeforeClearFocusedState.AddHandler(handler);
};
ASPx.AddBeforeSetFocusedState = function(handler){
 aspxGetStateController().BeforeSetFocusedState.AddHandler(handler);
};
ASPx.AddBeforeClearHoverState = function(handler){
 aspxGetStateController().BeforeClearHoverState.AddHandler(handler);
};
ASPx.AddBeforeSetHoverState = function(handler){
 aspxGetStateController().BeforeSetHoverState.AddHandler(handler);
};
ASPx.AddBeforeClearPressedState = function(handler){
 aspxGetStateController().BeforeClearPressedState.AddHandler(handler);
};
ASPx.AddBeforeSetPressedState = function(handler){
 aspxGetStateController().BeforeSetPressedState.AddHandler(handler);
};
ASPx.AddBeforeDisabled = function(handler){
 aspxGetStateController().BeforeDisabled.AddHandler(handler);
};
ASPx.AddBeforeEnabled = function(handler){
 aspxGetStateController().BeforeEnabled.AddHandler(handler);
};
ASPx.AddFocusedItemKeyDown = function(handler){
 aspxGetStateController().FocusedItemKeyDown.AddHandler(handler);
};
ASPx.SetHoverState = function(element){
 aspxGetStateController().SetCurrentHoverElementBySrcElement(element);
};
ASPx.ClearHoverState = function(evt){
 aspxGetStateController().SetCurrentHoverElementBySrcElement(null);
};
ASPx.UpdateHoverState = function(evt){
 aspxGetStateController().OnMouseMove(evt, false);
};
ASPx.SetFocusedState = function(element){
 aspxGetStateController().SetCurrentFocusedElementBySrcElement(element);
};
ASPx.ClearFocusedState = function(evt){
 aspxGetStateController().SetCurrentFocusedElementBySrcElement(null);
};
ASPx.UpdateFocusedState = function(evt){
 aspxGetStateController().OnFocusMove(evt);
};
ASPx.AccessibilityMarkerClass = "dxalink";
ASPx.AssignAccessibilityEventsToChildrenLinks = function(container, clearFocusedStateOnMouseOut){
 var links = ASPx.GetNodesByPartialClassName(container, ASPx.AccessibilityMarkerClass);
 for(var i = 0; i < links.length; i++)
  ASPx.AssignAccessibilityEventsToLink(links[i], clearFocusedStateOnMouseOut);
};
ASPx.AssignAccessibilityEventsToLink = function(link, clearFocusedStateOnMouseOut) {
 if(!ASPx.ElementContainsCssClass(link, ASPx.AccessibilityMarkerClass))
  return;
 ASPx.AssignAccessibilityEventsToLinkCore(link, clearFocusedStateOnMouseOut);
};
ASPx.AssignAccessibilityEventsToLinkCore = function (link, clearFocusedStateOnMouseOut) {
 ASPx.Evt.AttachEventToElement(link, "focus", function (e) { ASPx.UpdateFocusedState(e); });
 var clearFocusedStateHandler = function (e) { ASPx.ClearFocusedState(e); };
 ASPx.Evt.AttachEventToElement(link, "blur", clearFocusedStateHandler);
 if(clearFocusedStateOnMouseOut)
  ASPx.Evt.AttachEventToElement(link, "mouseout", clearFocusedStateHandler);
};
ASPx.Evt.AttachEventToDocument("mousemove", function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  aspxGetStateController().OnMouseMove(evt, true);
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  aspxGetStateController().OnMouseDown(evt);
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  aspxGetStateController().OnMouseUp(evt);
});
ASPx.Evt.AttachEventToDocument("mouseover", function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  aspxGetStateController().OnMouseOver(evt);
});
ASPx.Evt.AttachEventToDocument("keydown", function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  aspxGetStateController().OnKeyDown(evt);
});
ASPx.Evt.AttachEventToDocument("selectstart", function(evt) {
 if(ASPx.classesScriptParsed && ASPx.StateItemsExist)
  return aspxGetStateController().OnSelectStart(evt);
});
ASPx.GetStateController = aspxGetStateController;
ASPx.StateItem = ASPxStateItem;
})();

(function() {
var DockPanelBag = ASPx.CreateClass(null, {
 constructor: function () {
  this.panels = {};
 },
 RegisterPanel: function (panel) {
  this.panels[panel.panelUID] = panel;
 },
 GetPanelByUID: function (panelUID) {
  return this.panels[panelUID];
 },
 ForEachPanel: function (action) {
  for(var key in this.panels) {
   if(!this.panels.hasOwnProperty(key))
    continue;
   var panel = this.panels[key];
   if(panel.GetMainElement())
    action(this.panels[key]);
  }
 },
 GetPanelList: function () {
  var panelList = [];
  this.ForEachPanel(function (panel) {
   panelList.push(panel);
  });
  return panelList;
 }
});
DockPanelBag.instance = null;
DockPanelBag.Get = function () {
 if(!DockPanelBag.instance)
  DockPanelBag.instance = new DockPanelBag();
 return DockPanelBag.instance;
};
var ASPxClientDockManager = ASPx.CreateClass(ASPxClientComponent, {
 BeforeDockServerEventName: "BeforeDock",
 AfterDockServerEventName: "AfterDock",
 BeforeFloatServerEventName: "BeforeFloat",
 AfterFloatServerEventName: "AfterFloat",
 RaiseBeforeDockEventCommand: "EBD",
 RaiseAfterDockEventCommand: "EAD",
 RaiseBeforeFloatEventCommand: "EBF",
 RaiseAfterFloatEventCommand: "EAF",
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  if(!ASPxClientDockManager.instance)
   ASPxClientDockManager.instance = this;
  this.inPostback = false;
  this.cookieName = '';
  this.clientLayoutState = {};
  this.BeforeDock = new ASPxClientEvent();
  this.AfterDock = new ASPxClientEvent();
  this.BeforeFloat = new ASPxClientEvent();
  this.AfterFloat = new ASPxClientEvent();
  this.StartPanelDragging = new ASPxClientEvent();
  this.EndPanelDragging = new ASPxClientEvent();
  this.PanelClosing = new ASPxClientEvent();
  this.PanelCloseUp = new ASPxClientEvent();
  this.PanelPopUp = new ASPxClientEvent();
  this.PanelShown = new ASPxClientEvent();
  this.PanelResize = new ASPxClientEvent();
 },
 PerformCallback: function (parameter, onSuccess) {
  if(!ASPx.IsExists(parameter)) parameter = "";
  this.CreateCallback(parameter, null, onSuccess);
 },
 SendPostBack: function (params) {
  if(!this.inPostback) {
   this.inPostback = true;
   ASPxClientControl.prototype.SendPostBack.call(this, params);
  }
 },
 UpdatePanelLayoutState: function(panel) {
  this.clientLayoutState[panel.panelUID] = panel.GetLayoutStateObject();
 },
 UpdatePanelsLayoutState: function () {
  var instance = this;
  var panelBag = DockPanelBag.Get();
  panelBag.ForEachPanel(function(panel) {
   instance.UpdatePanelLayoutState(panel);
  });
  if(this.cookieName && this.cookieName !== '') {
   ASPx.Cookie.DelCookie(this.cookieName);
   ASPx.Cookie.SetCookie(this.cookieName, ASPx.Json.ToJson(this.clientLayoutState));
  }
 },
 GetBeforeDockPostbackArgs: function (panel, zone) {
  return [
   this.RaiseBeforeDockEventCommand,
   panel.panelUID,
   zone.zoneUID,
   zone.GetPanelAfterPlaceholderVisibleIndex() + 1
  ];
 },
 GetAfterDockPostbackArgs: function (panel, zone) {
  return [
   this.RaiseAfterDockEventCommand,
   panel.panelUID,
   zone.zoneUID
  ];
 },
 GetBeforeFloatPostbackArgs: function (panel, zone) {
  return [
   this.RaiseBeforeFloatEventCommand,
   panel.panelUID,
   zone.zoneUID
  ];
 },
 GetAfterFloatPostbackArgs: function (panel, zone) {
  return [
   this.RaiseAfterFloatEventCommand,
   panel.panelUID,
   zone.zoneUID
  ];
 },
 RaiseBeforeDock: function (panel, zone) {
  var processOnServer = this.IsServerEventAssigned(this.BeforeDockServerEventName);
  var args = new ASPxClientDockManagerProcessingModeCancelEventArgs(processOnServer, panel, zone);
  if(!this.BeforeDock.IsEmpty())
   this.BeforeDock.FireEvent(this, args);
  if(!args.cancel && args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetBeforeDockPostbackArgs(panel, zone);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  return !args.cancel;
 },
 RaiseAfterDock: function (panel, zone) {
  var processOnServer = this.IsServerEventAssigned(this.AfterDockServerEventName);
  var args = new ASPxClientDockManagerProcessingModeEventArgs(processOnServer, panel, zone);
  if(!this.AfterDock.IsEmpty())
   this.AfterDock.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetAfterDockPostbackArgs(panel, zone);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
 },
 RaiseBeforeFloat: function (panel, zone) {
  var processOnServer = this.IsServerEventAssigned(this.BeforeFloatServerEventName);
  var args = new ASPxClientDockManagerProcessingModeCancelEventArgs(processOnServer, panel, zone);
  if(!this.BeforeFloat.IsEmpty())
   this.BeforeFloat.FireEvent(this, args);
  if(!args.cancel && args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetBeforeFloatPostbackArgs(panel, zone);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  return !args.cancel;
 },
 RaiseAfterFloat: function (panel, zone) {
  var processOnServer = this.IsServerEventAssigned(this.AfterFloatServerEventName);
  var args = new ASPxClientDockManagerProcessingModeEventArgs(processOnServer, panel, zone);
  if(!this.AfterFloat.IsEmpty())
   this.AfterFloat.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetAfterFloatPostbackArgs(panel, zone);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
 },
 RaiseStartPanelDragging: function (panel) {
  if(!this.StartPanelDragging.IsEmpty())
   this.StartPanelDragging.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 RaiseEndPanelDragging: function (panel) {
  if(!this.EndPanelDragging.IsEmpty())
   this.EndPanelDragging.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 RaisePanelClosing: function (panel) {
  if(this.PanelClosing.IsEmpty())
   return false;
  var args = new ASPxClientDockManagerCancelEventArgs(panel);
  this.PanelClosing.FireEvent(this, args);
  return args.cancel;
 },
 RaisePanelCloseUp: function (panel) {
  if(!this.PanelCloseUp.IsEmpty())
   this.PanelCloseUp.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 RaisePanelPopUp: function (panel) {
  if(!this.PanelPopUp.IsEmpty())
   this.PanelPopUp.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 RaisePanelShown: function (panel) {
  if(!this.PanelShown.IsEmpty())
   this.PanelShown.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 RaisePanelResize: function (panel) {
  if(!this.PanelResize.IsEmpty())
   this.PanelResize.FireEvent(this, new ASPxClientDockManagerEventArgs(panel));
 },
 GetZoneByUID: function (zoneUID) {
  var zoneBag = ASPx.DockZoneBag.Get();
  return zoneBag.GetZoneByUID(zoneUID);
 },
 GetPanelByUID: function (panelUID) {
  var panelBag = DockPanelBag.Get();
  return panelBag.GetPanelByUID(panelUID);
 },
 GetPanels: function (filterPredicate) {
  var panelBag = DockPanelBag.Get();
  return ASPx.RetrieveByPredicate(panelBag.GetPanelList(), filterPredicate);
 },
 GetZones: function (filterPredicate) {
  var zoneBag = ASPx.DockZoneBag.Get();
  return ASPx.RetrieveByPredicate(zoneBag.GetZoneList(), filterPredicate);
 }
});
ASPx.Ident.scripts.ASPxClientDockManager = true;
ASPxClientDockManager.instance = null;
ASPxClientDockManager.Get = function () {
 return ASPxClientDockManager.instance;
};
ASPxClientDockManager.Cast = ASPxClientControl.Cast;
var ASPxClientDockManagerProcessingModeCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
 constructor: function (processOnServer, panel, zone) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.panel = panel;
  this.zone = zone;
 }
});
var ASPxClientDockManagerProcessingModeEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function (processOnServer, panel, zone) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.panel = panel;
  this.zone = zone;
 }
});
var ASPxClientDockManagerEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (panel) {
  this.constructor.prototype.constructor.call(this);
  this.panel = panel;
 }
});
var ASPxClientDockManagerCancelEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function (panel) {
  this.constructor.prototype.constructor.call(this);
  this.panel = panel;
 }
});
ASPx.DockPanelBag = DockPanelBag;
window.ASPxClientDockManager = ASPxClientDockManager;
window.ASPxClientDockManagerProcessingModeCancelEventArgs = ASPxClientDockManagerProcessingModeCancelEventArgs;
window.ASPxClientDockManagerProcessingModeEventArgs = ASPxClientDockManagerProcessingModeEventArgs;
window.ASPxClientDockManagerEventArgs = ASPxClientDockManagerEventArgs;
window.ASPxClientDockManagerCancelEventArgs = ASPxClientDockManagerCancelEventArgs;
})();
(function() {
var MVCxClientDockManager = ASPx.CreateClass(ASPxClientDockManager, {
 constructor: function(name) {
  var dockManagerInstance = ASPxClientDockManager.Get();
  if(dockManagerInstance && dockManagerInstance.name == name)
   ASPxClientDockManager.instance = this;
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
  this.constructor.prototype.constructor.call(this, name);
 },
 PerformCallback: function(data, onSuccess) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientDockManager.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function() {
  if(this.callbackUrl != "")
   this.callBack = function(arg) { MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), this.callbackCustomArgs); };
  ASPxClientDockManager.prototype.InlineInitialize.call(this);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 CreateCallbackCore: function(arg, command, callbackID) {
  if(this.callbackCustomArgs != {})
   window.setTimeout(function() { this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientDockManager.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 GetCallbackParams: function() {
  this.UpdatePanelsLayoutState();
  var params = {};
  params["ClientLayoutState"] = ASPx.Json.ToJson(this.clientLayoutState);
  return params;
 },
 UpdatePanelLayoutState: function(panel) {
  if(panel.LayoutCanBeObtained())
   ASPxClientDockManager.prototype.UpdatePanelLayoutState.call(this, panel);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientDockManager.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientDockManager.Cast = ASPxClientControl.Cast;
window.MVCxClientDockManager = MVCxClientDockManager;
})();

(function() {
ASPx.PCWIdSuffix = "_PW";
var popupControlZIndex = 11998;
var defaultZIndexFromServer = "10000";
var ModalAlign = {
 WindowLeft: "WindowLeft",
 WindowCenter: "WindowCenter",
 WindowRight: "WindowRight",
 WindowTop: "WindowTop",
 WindowBottom: "WindowBottom"
};
function PCResizeCursorInfo(horizontalDirection, verticalDirection, horizontalOffset, verticalOffset) {
 this.horizontalDirection = horizontalDirection;
 this.verticalDirection = verticalDirection;
 this.horizontalOffset = horizontalOffset;
 this.verticalOffset = verticalOffset;
 this.course = verticalDirection + horizontalDirection;
}
var PopupControlCssClasses = {};
PopupControlCssClasses.Prefix = "dxpc-";
PopupControlCssClasses.SizeGripLiteCssClassName = PopupControlCssClasses.Prefix + "sizeGrip";
PopupControlCssClasses.LinkCssClassName = PopupControlCssClasses.Prefix + "link";
PopupControlCssClasses.ShadowLiteCssClassName = PopupControlCssClasses.Prefix + "shadow";
PopupControlCssClasses.MainDivLiteCssClass = PopupControlCssClasses.Prefix + "mainDiv";
PopupControlCssClasses.ContentWrapperCssClassName = PopupControlCssClasses.Prefix + "contentWrapper";
PopupControlCssClasses.ContentCssClassName = PopupControlCssClasses.Prefix + "content";
PopupControlCssClasses.HeaderContentCssClassName = PopupControlCssClasses.Prefix + "headerContent";
PopupControlCssClasses.FooterContentCssClassName = PopupControlCssClasses.Prefix + "footerContent";
PopupControlCssClasses.WindowWrapperCssClassName = PopupControlCssClasses.Prefix + "win-wrapper";
PopupControlCssClasses.WindowWrapperScrollCssClassName = PopupControlCssClasses.WindowWrapperCssClassName + "-scroll";
PopupControlCssClasses.HeaderCssClassName = "dxpc-header";
var LoadContentViaCallback = {
 Default: "Default",
 OnFirstShow: "OnFirstShow",
 OnPageLoad: "OnPageLoad"
};
var constants = {
 DEFAULT_WINDOW_WIDTH: 200,
 DEFAULT_WINDOW_HEIGHT: 0
};
var ASPxClientPopupControlBase = ASPx.CreateClass(ASPxClientControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.leadingAfterInitCall = ASPxClientControl.LeadingAfterInitCallConsts.Direct; 
  this.adjustInnerControlsSizeOnShow = true;
  this.shadowVisible = true;
  this.cookieName = "";
  this.popupAnimationType = "none";
  this.closeAnimationType = "none";
  this.closeAction = "OuterMouseClick";
  this.isPopupFullCorrectionOn = true;
  this.forceAdjustPositionToClientScreen = false;
  this.usedInDropDown = false; 
  this.popupHorizontalOffset = 0;
  this.popupVerticalOffset = 0;
  this.popupHorizontalAlign = ASPx.PopupUtils.NotSetAlignIndicator;
  this.popupVerticalAlign = ASPx.PopupUtils.NotSetAlignIndicator;
  this.contentLoadingMode = LoadContentViaCallback.Default;
  this.slideAnimationDuration = 80;
  this.fadeAnimationDuration = 400;
  this.enableAnimation = true;
  this.showOnPageLoad = false;
  this.isDragged = false;
  this.closeOnEscape = false;
  this.savedCallbackWindowIndex = null;
  this.animationLockCount = 0;
  this.windowRequestCount = [];
  this.lpTimers = [];
  this.callbackAnimationProcessings = [];
  this.isCallbackFinishedStates = [];
  this.savedCallbackResults = [];
  this.loadingPanels = [];
  this.loadingDivs = [];
  this.left = 0;
  this.top = 0;
  this.height = constants.DEFAULT_WINDOW_HEIGHT;
  this.width = constants.DEFAULT_WINDOW_WIDTH;
  this.minHeight = null;
  this.minWidth = null;
  this.maxHeight = null;
  this.maxWidth = null;
  this.isResized = false;
  this.cachedSize = null;
  this.enableContentScrolling = false;
  this.contentOverflowX = "None";
  this.contentOverflowY = "None";
  this.contentUrl = "";
  this.contentUrlIFrameTitle = "";
  this.iframeLoading = false;
  this.iframeAdjustingPostponed = false;
  this.isPopupPositionCorrectionOn = true;
  this.resizeSessionCache = {};
  this.ResizeBorderSize = ASPx.Browser.TouchUI ? 10 : 6;
  this.ResizeCornerBorderSize = 20;
  this.isLiveResizingMode = true;
  this.allowResize = false;
  this.allowDragging = false;
  this.allowDraggingInAdaptiveMode = false;
  this.isWindowDragging = false;
  this.prohibitClearSelectionOnMouseDown = false;
  this.windowElements = {};
  this.windowContentElements = {};
  this.zIndex = -1;
  this.appearAfter = 300;
  this.disappearAfter = 500;
  this.popupAction = "LeftMouseClick";
  this.autoUpdatePosition = false;
  this.defaultIsPopuped = false;
  this.defaultLastUsedPopupElementInfo = {};
  this.defaultWindowPopupElementList = [];
  this.defaultWindowPopupElementIDList = [];
  this.firstFocusableElement = null;
  this.lastFocusableElement = null;
  this.focusLastElementHandler = function(e) { this.loopFocusHandler(e, false); }.aspxBind(this);
  this.focusFirstElementHandler = function(e) { this.loopFocusHandler(e, true); }.aspxBind(this);
  this.setFocusOnCallback = true;
  this.accessibleFocusElement = null;
  this.preventAccessibilityFocus = false;
  this.CloseButtonClick = new ASPxClientEvent();
  this.CloseUp = new ASPxClientEvent();
  this.Closing = new ASPxClientEvent();
  this.PopUp = new ASPxClientEvent();
  this.Shown = new ASPxClientEvent();
  this.Resize = new ASPxClientEvent();
  this.Dragged = new ASPxClientEvent(); 
  this.BeforeDrag = new ASPxClientEvent(); 
  this.BeforeResizing = new ASPxClientEvent();
  this.AfterResizing = new ASPxClientEvent();
  aspxGetPopupControlCollection().Add(this);
 },
 WindowElementIDAssignmentMap: [
  { cssClass: PopupControlCssClasses.HeaderCssClassName, prefix: "_PWH" },
  { cssClass: "dxpc-headerText", prefix: "_PWH", postfix: "T" },
  { cssClass: "dxpc-headerImg", prefix: "_PWH", postfix: "I" },
  { cssClass: "dxpc-closeBtn", prefix: "_HCB" },
  { cssClass: "dxpc-pinBtn", prefix: "_HPB" },
  { cssClass: "dxpc-refreshBtn", prefix: "_HRB" },
  { cssClass: "dxpc-collapseBtn", prefix: "_HMNB" },
  { cssClass: "dxpc-maximizeBtn", prefix: "_HMXB" },
  { cssClass: "dxpc-content", prefix: "_PWC" },
  { cssClass: "dxpc-iFrame", prefix: "_CIF" },
  { cssClass: "dxpc-footer", prefix: "_PWF" },
  { cssClass: "dxpc-footerText", prefix: "_PWF", postfix: "T" },
  { cssClass: "dxpc-footerImg", prefix: "_PWF", postfix: "I" }
 ],
 Initialize: function() {
  this.InitializeBeforeAnyShow();
  ASPxClientControl.prototype.Initialize.call(this);
  if(this.accessibilityCompliant)
   this.InitializeAccessibleNavigation();
 },
 InitializeWindow: function(index) {
  ASPx.PopupUtils.BodyScrollHelper.RestoreIfLocked(this.GetWindowElementId(index));
  this.RemoveWindowAllPopupElements(index);
  this.PopulatePopupElements(index);
  var element = this.GetWindowElement(index);
  if(element != null) {
   this.AssignWindowElementsID(index, element);
   this.AssignWindowElementsEvents(index, element);
   element.DXPopupWindowElement = true;
   this.AttachOnDragStartEventToWindowImages(index);
   this.EnsureWindowContentUrl(index);
   element.isHiding = false;
   element.isPopupPositionCorrectionOn = this.isPopupPositionCorrectionOn || !this.GetShowOnPageLoad(index);
   if(this.GetShowOnPageLoad(index) && this.GetZIndex(index) > 0) {
    this.FirstShowWindow(index, false);
    this.SetWindowElementZIndex(element, this.GetZIndex(index));
    element.isPopupPositionCorrectionOn = true;
   }
   this.InitializeWindowEscKeyHandler(element, index);
   if(this.GetCanScrollViewPort(index))
    ensureViewPortSizeInterval();
   var headerImageElement = this.GetWindowHeaderImageCell(index);
   if(headerImageElement != null) {
    var headerImageHandler = function() {
     this.CorrectHeaderContentElementHeight(index);
    }.aspxBind(this);
    headerImageElement.addEventListener("load", headerImageHandler);
    headerImageElement.addEventListener("error", headerImageHandler);
   }
   var footerImageElement = this.GetWindowFooterImageCell(index);
   if(footerImageElement != null) {
    var footerImageHandler = function() {
     this.CorrectWindowSizeGripPositionLite(index);
     this.CorrectFooterTextElementWidth(index);
    }.aspxBind(this);
    footerImageElement.addEventListener("load", footerImageHandler);
    footerImageElement.addEventListener("error", footerImageHandler);
   }
  }
 },
 InitializeBeforeAnyShow: function() {
  this.InitializeEnableContentScrolling();
 },
 InitializeEnableContentScrolling: function() {
  this.enableContentScrolling = this.contentOverflowX != "None" || this.contentOverflowY != "None";
 },
 InitializeWindowEscKeyHandler: function(element, index) {
  if(!this.GetEnableCloseByEsc(index)) return;
  this.AddKeyDownHandler("ESC", this.OnEscKeyDown.aspxBind(this));
 },
 AfterInitialize: function() {
  if(this.HasDefaultWindow())
   this.AfterInitializeWindow(-1);
  for(var i = 0; i < this.GetWindowCount(); i++)
   this.AfterInitializeWindow(i);
  ASPxClientControl.prototype.AfterInitialize.call(this);
 },
 AfterInitializeWindow: function(index) {
  if(this.GetShowOnPageLoad(index) && this.GetZIndex(index) < 0) {
   this.FirstShowWindow(index, true);
   var element = this.GetWindowElement(index);
   if(element != null)
    element.isPopupPositionCorrectionOn = true;
  }
  this.EnsureContent(index, true);
 },
 AssignWindowElementsID: function(index, windowElement) {
  for(var i = 0; i < this.WindowElementIDAssignmentMap.length; i++) {
   var elementClass = this.WindowElementIDAssignmentMap[i].cssClass;
   var elements = ASPx.GetNodesByClassName(windowElement, elementClass);
   for(var j = 0; j < elements.length; j++) {
    var element = elements[j];
    if(this.GetFirstParentWindow(element) === windowElement)
     this.AssignElementID(element, index, this.WindowElementIDAssignmentMap[i].prefix, this.WindowElementIDAssignmentMap[i].postfix);
   }
  }
 },
 AssignElementID: function(element, index, prefix, postfix) {
  element.id = this.name + prefix + index + (postfix ? postfix : "");
 },
 AssignWindowElementsEvents: function(index, element) {
  var header = this.GetWindowHeaderElement(index);
  if(header && this.allowDragging && !this.isWindowDragging)
   ASPx.Evt.AttachEventToElement(header, ASPx.TouchUIHelper.touchMouseDownEventName, this.GetWindowHeaderElementMouseDownEventHandler(index), true);
  this.AssignHeaderButtonsEvents(index);
  var mdEventName = ASPx.TouchUIHelper.touchMouseDownEventName;
  ASPx.Evt.AttachEventToElement(element, mdEventName, this.GetWindowElementMouseDownEventHandler(index));
  if(this.IsResizeAllowed(index)) {
   var mmEventName = ASPx.TouchUIHelper.touchMouseMoveEventName;
   ASPx.Evt.AttachEventToElement(element, mmEventName, this.GetWindowElementMouseMoveEventHandler(index));
  }
  var sizeGrip = this.GetWindowSizeGripElement(index);
  if(sizeGrip) {
   var instance = this;
   ASPx.Evt.AttachEventToElement(sizeGrip, mdEventName, function(evt) {
    ASPx.PWGripMDown(evt, instance.name, index);
    ASPx.Evt.PreventEvent(evt);
   });
  }
 },
 AssignHeaderButtonsEvents: function(index) {
  this.AttachClickToHeaderButton(index, this.GetWindowCloseButton(index), "ASPx.PWCBClick");
  this.AttachClickToHeaderButton(index, this.GetWindowRefreshButton(index), "ASPx.PWRBClick");
 },
 AttachClickToHeaderButton: function(index, headerButton, eventFuncName) {
  var instance = this;
  if(headerButton) {
   ASPx.Evt.AttachEventToElement(headerButton, "click", function(evt) {
    eval(eventFuncName)(evt, instance.name, index);
   });
  }
 },
 AttachOnDragStartEventToWindowImages: function(index) {
  this.AttachChildImagesPreventDragStartEvent(this.GetWindowHeaderElement(index));
  this.AttachChildImagesPreventDragStartEvent(this.GetWindowFooterElement(index));
 },
 AttachChildImagesPreventDragStartEvent: function(parentElem) {
  var images = parentElem == null ? null : ASPx.GetNodesByTagName(parentElem, "img");
  if(images != null) {
   for(var i = 0; i < images.length; i++)
    ASPx.Evt.AttachEventToElement(images[i], "dragstart", ASPx.Evt.PreventEventAndBubble);
  }
 },
 GetPropertyValue: function(index, propName) {
  return this[propName];
 },
 SetPropertyValue: function(index, propName, value) {
  this[propName] = value;
 },
 GetStretchVerticallyByIndex: function(index) {
  return this.GetPropertyValue(index, "stretchVertically");
 },
 GetModalMaxWidth: function(index) {
  return this.GetPropertyValue(index, "modalMaxWidth");
 },
 SetAdaptiveMaxWidthByIndex: function(index, value) {
  value = this.ConvertDimensionValueToString(value);
  this.SetPropertyValue(index, "modalMaxWidth", value);
  this.GetWindowElement(index).style["maxWidth"] = value;
  if(value.indexOf("px") > 0)
   this.EnsureMaxWidthClassName(index, ASPx.PxToInt(value));
 },
 EnsureMaxWidthClassName: function(index, maxWidth) {
  var defaultPaddingsWidth = 20;
  ASPx.ToggleClassNameToElement(this.GetModalWrapperElement(index), "dxmodalMaxWidth", maxWidth < ASPx.MaxMobileWindowWidth - defaultPaddingsWidth);
 },
 GetModalMinWidth: function(index) {
  return this.GetPropertyValue(index, "modalMinWidth");
 },
 SetAdaptiveMinWidthByIndex: function(index, value) {
  value = this.ConvertDimensionValueToString(value);
  this.SetPropertyValue(index, "modalMinWidth", value);
  this.GetWindowElement(index).style["minWidth"] = value;
 },
 GetModalMinHeight: function(index) {
  return this.GetPropertyValue(index, "modalMinHeight");
 },
 SetContentElementsAdaptiveDisplayStyle: function(index) {
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  ASPx.ToggleClassNameToElement(contentWrapper, "dxmodalTableSys", !this.GetWindowContentIFrameElement(index) && !this.HasAnyScrollBars(index));
 },
 SetContentWrapperAdaptiveHeight: function(index, adaptiveHeight) {  
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  contentWrapper.style.height = adaptiveHeight;  
 },
 SetAdaptiveMinHeightByIndex: function(index, value) {  
  this.StretchVerticallyByIndex(index, false);
  this.SetPropertyValue(index, "modalMinHeight", value);
  this.SetAdaptiveHeightDimension(index, "minHeight", value);
 },
 GetModalMaxHeight: function(index) {
  return this.GetPropertyValue(index, "modalMaxHeight");
 },
 SetAdaptiveMaxHeightByIndex: function(index, value) {
  this.SetPropertyValue(index, "modalMaxHeight", value);
  this.SetAdaptiveHeightDimension(index, "maxHeight", value);
 },
 GetFixedHeader: function(index) {
  return this.GetPropertyValue(index, "fixedHeader");
 },
 GetFixedFooter: function(index) {
  return this.GetPropertyValue(index, "fixedFooter");
 },
 GetWindowWidthInternal: function(index) {
  return this.GetPropertyValue(index, "width");
 },
 GetWindowHeightInternal: function(index) {
  return this.GetPropertyValue(index, "height");
 },
 SetWindowHeight: function(index, height) {
  this.SetPropertyValue(index, "height", height);
 },
 SetWindowWidth: function(index, width) {
  this.SetPropertyValue(index, "width", width);
 },
 GetWindowMinWidth: function(index) {
  return this.GetPropertyValue(index, "minWidth");
 },
 GetWindowMaxWidth: function(index) {
  return this.GetPropertyValue(index, "maxWidth");
 },
 GetWindowMinHeight: function(index) {
  return this.GetPropertyValue(index, "minHeight");
 },
 GetWindowMaxHeight: function(index) {
  return this.GetPropertyValue(index, "maxHeight");
 },
 SetWindowMaxHeight: function(index, maxHeight) {
  this.SetPropertyValue(index, "maxHeight", maxHeight);
 },
 SetWindowCachedSize: function(index, width, height) {
  this.SetPropertyValue(index, "cachedSize", new ASPx.PopupSize(width, height));
 },
 GetWindowCachedSize: function(index) {
  return this.GetPropertyValue(index, "cachedSize");
 },
 ResetWindowCachedSize: function(index) {
  this.SetPropertyValue(index, "cachedSize", null);
 },
 GetPosition: function(index, isLeft) {
  return this.GetPropertyValue(index, isLeft ? "left" : "top");
 },
 GetWindowTop: function(index) {
  return this.GetPropertyValue(index, "top");
 },
 SetWindowTop: function(index, top) {
  this.SetPropertyValue(index, "top", top);
 },
 GetWindowLeft: function(index) {
  return this.GetPropertyValue(index, "left");
 },
 SetWindowLeft: function(index, left) {
  this.SetPropertyValue(index, "left", left);
 },
 GetEnableCloseByEsc: function(index) {
  return this.GetPropertyValue(index, "closeOnEscape");
 },
 GetIsDragged: function(index) {
  return this.GetPropertyValue(index, "isDragged");
 },
 GetWindowContentIFrameUrl: function(index) {
  return this.GetPropertyValue(index, "contentUrl");
 },
 GetWindowContentIFrameTitle: function(index) {
  return this.GetPropertyValue(index, "contentUrlIFrameTitle");
 },
 GetWindowCloseAction: function(index) {
  return this.GetPropertyValue(index, "closeAction");
 },
 GetShowOnPageLoad: function(index) {
  return this.GetPropertyValue(index, "showOnPageLoad");
 },
 GetZIndex: function(index) {
  return this.GetPropertyValue(index, "zIndex");
 },
 GetIframeLoading: function(index) {
  return this.GetPropertyValue(index, "iframeLoading");
 },
 SetIframeLoading: function(index, value) {
  this.SetPropertyValue(index, "iframeLoading", value);
 },
 SetIsDragged: function(index, value) {
  this.SetPropertyValue(index, "isDragged", value);
 },
 GetIsResized: function(index) {
  return this.GetPropertyValue(index, "isResized");
 },
 SetIsResized: function(index, value) {
  this.SetPropertyValue(index, "isResized", value);
 },
 SetIframeAdjustingPostponed: function(index, value) {
  this.SetPropertyValue(index, "iframeAdjustingPostponed", value);
 },
 GetIframeAdjustingPostponed: function(index) {
  return this.GetPropertyValue(index, "iframeAdjustingPostponed");
 },
 GetWindowPopupAction: function(index) {
  return this.GetPropertyValue(index, "popupAction");
 },
 GetWindowElementMouseMoveEventHandler: function(index) {
  var instance = this;
  return function(evt) { ASPx.PWMMove(evt, instance.name, index); };
 },
 GetWindowElementMouseDownEventHandler: function(index) {
  var instance = this;
  return function(evt) {
   if(instance.AllowMouseDown(evt, index))
    ASPx.PWMDown(evt, instance.name, index, instance.isWindowDragging);
  };
 },
 GetWindowHeaderElementMouseDownEventHandler: function(index) {
  var instance = this;
  return function(evt) {
   if(instance.AllowMouseDown(evt, index))
    ASPx.PWDGMDown(evt, instance.name, index);
  };
 },
 AllowMouseDown: function(evt, index) {
  return !this.PreventHeaderButtonMouseDownBubbling(evt, this.GetWindowCloseButton(index)) &&
   !this.PreventHeaderButtonMouseDownBubbling(evt, this.GetWindowRefreshButton(index));
 },
 PreventHeaderButtonMouseDownBubbling: function(evt, hdrButton) {
  if(hdrButton) {
   var source = ASPx.Evt.GetEventSource(evt);
   if(ASPx.GetIsParent(hdrButton, source)) {
    ASPx.PWHMDown(evt);
    return true;
   }
  }
  return false;
 },
 PrepareToAdjustContentOnShow: function(index) {
  if(this.adjustInnerControlsSizeOnShow) {
   var windowContent = this.GetContentContainer(index),
    collection = ASPx.GetControlCollection();
   collection.CollapseControls(windowContent);
  }
 },
 AdjustContentOnShow: function(index) {
  if(this.adjustInnerControlsSizeOnShow) {
   var windowElement = this.GetWindowElement(index);
   ASPx.GetControlCollection().AdjustControls(windowElement, false);
  }
 },
 AdjustSize: function() {
  if(this.enableContentScrolling)
   return;
  this.SetSize(0, 0);
 },
 GetFirstParentWindow: function(el) {
  while(el && el.tagName != "BODY") {
   if(el.nodeType == 1 && el.className.indexOf("dxpclW") > -1 && !isNaN(this.GetWindowIndex(el)))
    return el;
   el = el.parentNode;
  }
 },
 getParentPopupControl: function(index) {
  var parentPopupWindowElement = this.GetFirstParentWindow(this.GetWindowElement(index).parentNode);
  if(parentPopupWindowElement)
   return aspxGetPopupControlCollection().GetPopupWindowFromID(parentPopupWindowElement.id);
 },
 registerAndActivateWindow: function(windowElement, index, allowChangeZIndex) {
  aspxGetPopupControlCollection().RegisterVisibleWindow(windowElement, this, index);
  if(allowChangeZIndex)
   aspxGetPopupControlCollection().ActivateWindowElement(windowElement, undefined, this.GetPopupType(), this.GetDefaultZIndexFromServer(), this.GetPopupControlZIndex());
 },
 HasCloseAnimation: function() {
  return this.closeAnimationType !== ASPxClientPopupControlBase.AnimationType.None;
 },
 HasOpenAnimation: function() {
  return this.popupAnimationType !== ASPxClientPopupControlBase.AnimationType.None;
 },
 AddKeyDownHandler: function(shortcutString, handler) {
  if(typeof(this.keyDownHandlers) === "undefined")
   this.keyDownHandlers = [];
  this.keyDownHandlers[ASPx.ParseShortcutString(shortcutString)] = handler;
 },
 InternalIsWindowDisplayed: function(index) {
  var element = this.GetWindowElement(index);
  return (element != null) ? ASPx.GetElementDisplay(element) : false;
 },
 InternalIsWindowVisible: function(index) {
  var element = this.GetWindowElement(index);
  if(!element)
   return false;
  if(this.HasCloseAnimation() && !element.closeAnimationCompleted)
   return false;
  return ASPx.GetElementVisibility(element, true) && ASPx.GetElementDisplay(element);
 },
 IsWindowVisible: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.InternalIsWindowVisible(index);
 },
 IsVisible: function() {
  return this.InternalIsWindowVisible(-1);
 },
 UpdateWindowsStateCookie: function() {
  if(this.cookieName == "") return;
  ASPx.Cookie.DelCookie(this.cookieName);
  ASPx.Cookie.SetCookie(this.cookieName, this.GetWindowsState());
 },
 SetWindowElementZIndex: function(element, zIndex) {
  element.style.zIndex = zIndex;
  var iFrame = element.overflowElement;
  if(iFrame)
   iFrame.style.zIndex = zIndex - 1;
  var modalElement = element.modalElement;
  if(modalElement)
   modalElement.style.zIndex = zIndex - 1;
  this.UpdateWindowsStateCookie();
 },
 SetWindowContentHtmlCore: function(index, html, useAnimation) {
  var element = this.GetContentContainer(index);
  if(element != null) {
   ASPx.SetInnerHtml(element, html);
   this.AfterSetWindowContentHtml(index, element, useAnimation);
  }
 },
 SetContentHtml: function(html, useAnimation) {
  this.SetWindowContentHtml(null, html, useAnimation);
  if(html && this.accessibilityCompliant)
   ASPx.GetControlCollection().ControlsInitialized.AddHandler(this.OnControlsInitialized, this);
 },
 SetWindowContentHtml: function(window, html, useAnimation) {
  var index = (window != null) ? window.index : -1;
  this.SetWindowContentHtmlCore(index, html, useAnimation);
 },
 GetContentHtml: function() {
  return this.GetWindowContentHtml(null);
 },
 AfterSetWindowContentHtml: function(index, contentContainer, useAnimation) {
  if(useAnimation && typeof (ASPx.AnimationHelper) != "undefined")
   ASPx.AnimationHelper.fadeIn(contentContainer, function() { this.ResizeWindowIFrame(index); }.aspxBind(this));
  else
   this.ResizeWindowIFrame(index);
 },
 ResizeWindowIFrame: function(index) {
  if(!this.renderIFrameForPopupElements || !this.InternalIsWindowVisible(index)) return;
  var iFrame = this.GetWindowIFrame(index);
  if(iFrame) {
   var cell = this.GetWindowMainCell(this.GetWindowElement(index));
   ASPx.SetStyles(iFrame, { width: cell.offsetWidth, height: cell.offsetHeight });
  }
 },
 DoHideWindow: function(index, dontRaiseClosing, closeReason) {
  if(!this.InternalIsWindowVisible(index)) return;
  var cancel = !dontRaiseClosing && this.RaiseClosing(index, closeReason);
  if(!cancel) {
   if(this.HasCloseAnimation() && this.IsAnimationAllowed())
    this.DoHideWindowCoreWithAnimation(index, closeReason);
   else {
    this.DoHideWindowCore(index, closeReason);
    this.RaiseCloseUp(index, closeReason);
   }
  }
  return cancel;
 },
 HasAnyScrollBars: function(index) {
  var contentElement = this.GetWindowContentElement(index);
  var hasBothScrollBars = contentElement.style.overflow == "scroll" || contentElement.style.overflow == "auto";
  return hasBothScrollBars || contentElement.style.overflowX == "scroll" ||
   contentElement.style.overflowY == "scroll" || contentElement.style.overflowX == "auto" ||
   contentElement.style.overflowY == "auto";
 },
 DoHideWindowModalElement: function(element, closeReason) {
  var modalElement = element.modalElement;
  if(modalElement && ASPx.GetElementVisibility(modalElement, true)) {
   var closeModalElement = function () {
    ASPx.SetStyles(modalElement, { width: 1, height: 1, zIndex: defaultZIndexFromServer - 1 });
    ASPx.SetElementVisibility(modalElement, false);
    ASPx.SetElementDisplay(modalElement, false);
   };
   aspxGetPopupControlCollection().UnregisterVisibleModalElement(modalElement);
   if(this.GetHideBodyScrollWhenModal(this.GetWindowIndex(element))) {
    if(ASPx.Browser.WebKitFamily)
     aspxGetPopupControlCollection().LockScrollEvent();
    if(!ASPx.Browser.WebKitTouchUI)
     ASPx.PopupUtils.BodyScrollHelper.RestoreBodyScroll(element.id);
    if(ASPx.Browser.WebKitFamily)
     aspxGetPopupControlCollection().UnlockScrollEvent();
   }
   if(closeReason == ASPxClientPopupControlCloseReason.OuterMouseClick) {     
    ASPx.SetStyles(modalElement, { opacity: 0 });
    if(!modalElement.mouseHandler) {
     modalElement.mouseHandler = function() {
      ASPx.SetStyles(modalElement, { opacity: "" });
      closeModalElement();
      ASPx.Evt.DetachEventFromElement(modalElement, "mouseup", modalElement.mouseHandler);
      ASPx.Evt.DetachEventFromElement(modalElement, "mouseout", modalElement.mouseHandler);
     };
    }
    ASPx.Evt.AttachEventToElement(modalElement, "mouseup", modalElement.mouseHandler);
    ASPx.Evt.AttachEventToElement(modalElement, "mouseout", modalElement.mouseHandler);
   } else
    closeModalElement();
  }
 },
 IncreaseWindowRequestCount: function (index) {
  if(!this.windowRequestCount[index])
   this.windowRequestCount[index] = 1;
  else
   this.windowRequestCount[index]++;
 },
 DecreaseWindowRequestCount: function(index) {
  this.windowRequestCount[index]--;
 },
 IsLoadingContainerVisible: function() {
  return true;
 },
 ShouldHideExistingLoadingElements: function() {
  return false;
 },
 GetModalElementEndAnimationOpacity: function(index) {
  if(typeof (this.modalElementOpacity) == "undefined")
   this.modalElementOpacity = [];
  if(typeof (this.modalElementOpacity[index]) == "undefined")
   this.modalElementOpacity[index] = ASPx.GetElementOpacity(this.GetWindowModalElement(index));
  return this.modalElementOpacity[index];
 },
 SetModalElementVisibilityWithAnimation: function(modalElement, index) {
  if(this.AllowModalElementAnimation(index)) {
   var endOpacity = this.GetModalElementEndAnimationOpacity(index);
   ASPx.AnimationHelper.setOpacity(modalElement, 0);
   ASPx.SetElementVisibility(modalElement, true);
   ASPx.AnimationHelper.fadeTo(modalElement, { to: endOpacity });
  } else
   ASPx.SetElementVisibility(modalElement, true);
 },
 AllowModalElementAnimation: function(index) {
  return this.popupAnimationType === ASPxClientPopupControlBase.AnimationType.Fade;
 },
 SetVisibleWithAnimation: function(element, isMoving, index, horizontalPopupPosition, verticalPopupPosition) {
  var isAnimationNeed = this.IsAnimationAllowed() && !isMoving;
  if(isAnimationNeed && this.popupAnimationType !== "none") {
   switch(this.popupAnimationType) {
    case ASPxClientPopupControlBase.AnimationType.Slide:
     this.StartSlideAnimation(element, index, horizontalPopupPosition, verticalPopupPosition);
     break;
    case ASPxClientPopupControlBase.AnimationType.Fade:
     this.StartFadeAnimation(element, index);
     break;
    case ASPxClientPopupControlBase.AnimationType.Auto:
     this.StartAutoAnimation(element, index, horizontalPopupPosition, verticalPopupPosition);
     break;
   }
  }
  else
   ASPx.SetElementVisibility(element, true);
 },
 StartAutoAnimation: function(element, index, horizontalPopupPosition, verticalPopupPosition) {
  ASPx.SetElementVisibility(element, true);
 },
 StartFadeAnimation: function(element, index) {
  ASPx.AnimationHelper.setOpacity(element, 0);
  ASPx.SetElementVisibility(element, true);
  var callback = function() {
   this.OnAnimationStop(index);
  }.aspxBind(this);
  ASPx.AnimationHelper.fadeIn(element, callback, this.fadeAnimationDuration);
 },
 StartSlideAnimation: function (animationDivElement, index, horizontalPopupPosition, verticalPopupPosition) {
  var element = this.GetWindowMainCell(animationDivElement);
  var clientX = horizontalPopupPosition.position;
  var clientY = verticalPopupPosition.position;
  var args = "(\"" + this.name + "\", " + index + ")";
  var onAnimStopCallString = "ASPx.PCAStop" + args;
  this.InitDivPosForShowSlideAnimation(index, animationDivElement, clientX, clientY, onAnimStopCallString);
  var horizontalDirection = this.GetAnimationHorizontalDirection(index, horizontalPopupPosition);
  var verticalDirection = this.GetAnimationVerticalDirection(index, verticalPopupPosition);
  var offsetCoefficient = this.GetSlideOffsetCoefficient(index);
  var xPos = horizontalDirection * animationDivElement.offsetWidth * offsetCoefficient;
  var yPos = verticalDirection * animationDivElement.offsetHeight * offsetCoefficient;
  neddToForceAnimation = xPos === 0 && yPos === 0;
  if(neddToForceAnimation) 
   yPos = 1;
  ASPx.SetStyles(element, { left: xPos, top: yPos });
  ASPx.SetElementVisibility(animationDivElement, true);
  this.DoShowWindowIFrame(index, clientX, clientY, 0, 0);
  ASPx.PopupUtils.StartSlideAnimation(animationDivElement, element, this.GetWindowIFrame(index), this.GetSlideAnimationDuration(index));
 },
 GetSlideAnimationDuration: function(index) {
  return this.slideAnimationDuration;
 },
 GetSlideOffsetCoefficient: function(index) {
  return 1;
 },
 InitDivPosForShowSlideAnimation: function(index, animationDivElement, clientX, clientY, onAnimStopCallString) {
  ASPx.PopupUtils.InitAnimationDiv(animationDivElement, clientX, clientY, onAnimStopCallString, true);
 },
 InitDivPosForHideSlideAnimation: function(animationDivElement) {
 },
 StopShowAnimation: function(index) {
  if(this.HasOpenAnimation()) {
   var windowElement = this.GetWindowElement(index);
   if(this.popupAnimationType === 'slide')
    ASPx.PopupUtils.StopAnimation(windowElement, this.GetWindowMainCell(windowElement));
   else
    ASPx.AnimationHelper.cancelAnimation(windowElement);
  }
 },
 StopCloseAnimation: function(index) {
  var element = this.GetWindowElement(index);
  if(this.HasCloseAnimation() && !element.closeAnimationCompleted) {
   ASPx.AnimationHelper.cancelAnimation(element);
   this.DoHideWindowCore(index);
  }
 },
 IsFadeCloseAnimation: function(index) {
  return this.closeAnimationType === ASPxClientPopupControlBase.AnimationType.Fade;
 },
 PrepareElementAfterCloseAnimation: function(index, element) {
  element.closeAnimationCompleted = true;
  if(this.IsFadeCloseAnimation(index))
   ASPx.SetStyles(element, { opacity: 1 });
  else
   ASPx.SetStyles(this.GetWindowMainCell(element), {
    left: 0,
    top: 0
   });
 },
 DoHideWindowCoreWithAnimation: function(index, closeReason) {
  this.StopShowAnimation(index);
  var element = this.GetWindowElement(index);
  element.closeAnimationCompleted = false;
  if(this.AllowModalElementAnimation(index) && this.CanManipulateWithModalElement(index))
   ASPx.AnimationHelper.fadeOut(element.modalElement, null, this.fadeAnimationDuration);
  switch(this.closeAnimationType) {
   case ASPxClientPopupControlBase.AnimationType.Slide:
    this.DoHideWindowWithSlideAnimation(index, closeReason);
    break;
   case ASPxClientPopupControlBase.AnimationType.Fade:
    this.DoHideWindowWithFadeAnimation(index, element, closeReason);
    break;
   case ASPxClientPopupControlBase.AnimationType.Auto:
    this.DoHideWindowWithAutoAnimation(index, element, closeReason);
    break;
  }
 },
 DoHideWindowWithAutoAnimation: function(index, element, closeReason) {
 },
 DoHideWindowWithFadeAnimation: function(index, element, closeReason) {
  ASPx.AnimationHelper.fadeOut(element, function() {
   this.DoHideWindowCore(index);
   this.RaiseCloseUp(index, closeReason);
  }.aspxBind(this), this.fadeAnimationDuration);
 },
 DoHideWindowWithSlideAnimation: function(index, closeReason) {
  var element = this.GetWindowElement(index);
  var horizontalPopupPosition = this.GetSlideAnimationPosition(element, true);
  var verticalPopupPosition = this.GetSlideAnimationPosition(element, false);
  var horizontalDirection = this.GetAnimationHorizontalDirection(index, horizontalPopupPosition);
  var verticalDirection = this.GetAnimationVerticalDirection(index, verticalPopupPosition);
  this.InitDivPosForHideSlideAnimation(element);
  var offsetCoefficient = this.GetSlideOffsetCoefficient(index);
  ASPx.AnimationHelper.createMultipleAnimationTransition(this.GetWindowMainCell(element), {
   duration: this.GetSlideAnimationDuration(index),
   onComplete: function(element) {
    this.DoHideWindowCore(index);
    this.RaiseCloseUp(index, closeReason);
   }.aspxBind(this)
  }).Start({
   left: { to: horizontalDirection * element.offsetWidth * offsetCoefficient, unit: "px" },
   top: { to: verticalDirection * element.offsetHeight * offsetCoefficient, unit: "px" }
  });
 },
 GetSlideAnimationPosition: function(element, isX) {
  return this.GetClientPopupPos(element, null, ASPx.InvalidPosition, isX, true);
 },
 GetAnimationHorizontalDirection: function(index, horizontalPopupPosition) {
  return ASPx.PopupUtils.GetAnimationHorizontalDirection(horizontalPopupPosition, this.popupHorizontalAlign, this.popupVerticalAlign, this.rtl);
 },
 GetAnimationVerticalDirection: function(index, verticalPopupPosition) {
  return ASPx.PopupUtils.GetAnimationVerticalDirection(verticalPopupPosition, this.popupHorizontalAlign, this.popupVerticalAlign);
 },
 OnAnimationStop: function(index) {
  this.OnWindowShown(index);
 },
 PerformCallback: function(parameter, onSuccess) {
  this.PerformWindowCallback(null, parameter, onSuccess);
 },
 PerformWindowCallback: function(window, parameter, onSuccess) {
  parameter = ASPx.IsExists(parameter) ? parameter.toString() : "";
  var index = (window != null) ? window.index : -1;
  if(!this.InWindowCallback(index)) {
   var windowCallbackArguments = index + ";" + parameter;
   this.CreateWindowCallback(index, windowCallbackArguments, onSuccess);
  }
 },
 InWindowCallback: function(windowIndex) {
  return this.windowRequestCount[windowIndex] > 0;
 },
 CreateWindowCallback: function(windowIndex, argument, handler) {
  this.IncreaseWindowRequestCount(windowIndex);
  var element = this.GetWindowElement(windowIndex);
  if(this.contentLoadingMode != LoadContentViaCallback.OnPageLoad || !element.loading || this.GetShowOnPageLoad(windowIndex))
   this.ShowWindowLoadingElements(windowIndex);
  this.CreateCallback(argument, null, handler);
 },
 OnCallback: function(result) {
  this.OnCallbackInternal(result.html, result.index, false);
 },
 OnCallbackError: function(result, data) {
  this.OnCallbackInternal(result, ASPx.IsExists(data) ? data : -1, true);
 },
 OnCallbackErrorAfterUserHandle: function(result, data) {
  this.DecreaseWindowRequestCount(data);
 },
 OnCallbackGeneralError: function(errorMessage) {
  this.OnCallbackInternal(errorMessage, -1, true);
 },
 OnCallbackGeneralErrorAfterUserHandle: function(errorMessage) {
  this.DecreaseWindowRequestCount(-1);
 },
 OnCallbackInternal: function(html, windowIndex, isError) {
  var element = this.GetWindowElement(windowIndex);
  element.loaded = !isError;
  element.loading = false;
  this.DecreaseWindowRequestCount(windowIndex);
  this.HideWindowLoadingPanel(windowIndex);
  this.SetWindowContentHtmlCore(windowIndex, html);
  this.UpdatePositionAfterCallback(windowIndex);
  this.savedCallbackWindowIndex = windowIndex;
  this.UpdateWindowsStateCookie();
  if(this.accessibilityCompliant)
   this.InitializeAccessibleNavigationCore();
 },
 RaiseCallbackError: function(message) {
  var result = ASPxClientControl.prototype.RaiseCallbackError.call(this, message);
  if(result.isHandled)
   this.HideAllLoadingPanels();
  return result;
 },
 StartWindowBeginCallbackAnimation: function(windowIndex) {
  this.callbackAnimationProcessings[windowIndex] = true;
  this.isCallbackFinishedStates[windowIndex] = false;
  ASPx.AnimationHelper.fadeOut(this.GetWindowContentElement(windowIndex), function() { this.FinishWindowBeginCallbackAnimation(windowIndex); }.aspxBind(this));
 },
 FinishWindowBeginCallbackAnimation: function(windowIndex) {
  this.callbackAnimationProcessings[windowIndex] = false;
  if(!this.isCallbackFinishedStates[windowIndex])
   this.ShowWindowLoadingElementsInternal(windowIndex);
  else
   this.DoCallback(this.savedCallbackResults[windowIndex]);
 },
 CheckBeginCallbackAnimationInProgress: function(callbackResult) {
  var result;
  try {
   result = this.EvalCallbackResult(callbackResult).result;
  } catch(e) {
   return false;
  }
  var windowIndex = result.index;
  if(this.enableCallbackAnimation && this.callbackAnimationProcessings[windowIndex]) {
   this.savedCallbackResults[windowIndex] = callbackResult;
   this.isCallbackFinishedStates[windowIndex] = true;
   return true;
  }
  return false;
 },
 StartWindowEndCallbackAnimation: function(windowIndex) {
  this.callbackAnimationProcessings[windowIndex] = true;
  ASPx.AnimationHelper.fadeIn(this.GetWindowContentElement(windowIndex), function() { this.FinishWindowEndCallbackAnimation(windowIndex); }.aspxBind(this));
 },
 FinishWindowEndCallbackAnimation: function(windowIndex) {
  this.DoEndCallback();
  this.callbackAnimationProcessings[windowIndex] = false;
 },
 CheckEndCallbackAnimationNeeded: function() {
  var windowIndex = this.savedCallbackWindowIndex;
  this.savedCallbackWindowIndex = null;
  if(windowIndex !== null && !this.callbackAnimationProcessings[windowIndex]) {
   this.StartWindowEndCallbackAnimation(windowIndex);
   return true;
  }
  return false;
 },
 EnsureContent: function(windowIndex, isInit) {
  var element = this.GetWindowElement(windowIndex);
  if(element && !element.loaded && !element.loading) {
   var shouldLoad = this.contentLoadingMode == LoadContentViaCallback.OnPageLoad || this.contentLoadingMode == LoadContentViaCallback.OnFirstShow && !isInit;
   if(shouldLoad) {
    element.loading = true;
    this.CreateWindowCallback(windowIndex, windowIndex);
   } else if(this.contentLoadingMode == LoadContentViaCallback.Default)
    element.loaded = true;
  }
 },
 HideAllLoadingPanels: function() {
  if(this.HasDefaultWindow())
   this.HideWindowLoadingPanel(-1);
  for(var i = 0; i < this.GetWindowCount() ; i++)
   this.HideWindowLoadingPanel(i);
 },
 HideWindowLoadingPanel: function(windowIndex) {
  this.ClearWindowLoadingPanelTimer(windowIndex);
  if(this.loadingDivs[windowIndex]) {
   ASPx.RemoveElement(this.loadingDivs[windowIndex]);
   this.loadingDivs[windowIndex] = null;
  }
  if(this.loadingPanels[windowIndex]) {
   ASPx.RemoveElement(this.loadingPanels[windowIndex]);
   this.loadingPanels[windowIndex] = null;
  }
 },
 ShowWindowLoadingElements: function(windowIndex) {
  if(this.lpTimers[windowIndex] && this.lpTimers[windowIndex] > -1) return;
  if(this.enableCallbackAnimation)
   this.StartWindowBeginCallbackAnimation(windowIndex);
  else
   this.ShowWindowLoadingElementsInternal(windowIndex);
 },
 ShowWindowLoadingPanelOnTimer: function(windowIndex) {
  this.ClearWindowLoadingPanelTimer(windowIndex);
  this.ShowWindowLoadingPanel(windowIndex);
 },
 ClearWindowLoadingPanelTimer: function(windowIndex) {
  this.lpTimers[windowIndex] = ASPx.Timer.ClearTimer(this.lpTimers[windowIndex]);
 },
 ShowWindowLoadingElementsInternal: function(windowIndex) {
  if(this.lpDelay > 1 && !this.enableCallbackAnimation) {
   var _this = this;
   this.lpTimers[windowIndex] = window.setTimeout(function() { _this.ShowWindowLoadingPanelOnTimer(windowIndex); }, this.lpDelay);
  }
  else
   this.ShowWindowLoadingPanel(windowIndex);
 },
 ShowWindowLoadingPanel: function(windowIndex) {
  if(!this.IsExistLoadingPanel())
   return;
  if(!this.loadingPanels[windowIndex] && this.InternalIsWindowVisible(windowIndex)) {
   var parentElement = this.GetWindowElement(windowIndex).parentNode;
   var offsetElement = this.GetLoadingPanelOffsetElement(windowIndex);
   this.loadingDivs[windowIndex] = this.CreateLoadingDiv(parentElement, offsetElement, windowIndex);
   this.loadingPanels[windowIndex] = this.CreateLoadingPanelWithAbsolutePosition(parentElement, offsetElement, windowIndex);
  }
 },
 GetLoadingPanelOffsetElement: function(windowIndex) {
  return this.GetWindowContentWrapperElement(windowIndex);
 },
 IsExistLoadingPanel: function() {
  return !!this.GetLoadingDiv();
 },
 LockAnimation: function() {
  this.animationLockCount++;
 },
 UnlockAnimation: function() {
  this.animationLockCount--;
 },
 IsAnimationLocked: function() {
  return this.animationLockCount > 0;
 },
 IsAnimationAllowed: function() {
  return this.enableAnimation && !this.IsAnimationLocked();
 },
 SetWindowSizeByIndexCore: function(index, width, height, isWindowCollapsed) {
  this.SetClientWindowSizeLite(index, width, height, isWindowCollapsed);
  var iFrame = this.GetWindowIFrame(index);
  if(iFrame && !isWindowCollapsed) {
   var winElememnt = this.GetWindowElement(index);
   var realWidth = winElememnt.offsetWidth;
   var realHeight = winElememnt.offsetHeight;
   ASPx.SetStyles(iFrame, { width: realWidth, height: realHeight });
  }
  this.UpdateWindowsStateCookie();
 },
 SetWindowSizeByIndex: function(index, width, height) {
  var minWidth = this.GetWindowMinWidth(index);
  var minHeight = this.GetWindowMinHeight(index);
  var maxWidth = this.GetWindowMaxWidth(index);
  var maxHeight = this.GetWindowMaxHeight(index);
  if(minWidth)
   width = Math.max(width, minWidth);
  if(minHeight)
   height = Math.max(height, minHeight);
  if(maxWidth)
   width = Math.min(width, maxWidth);
  if(maxHeight)
   height = Math.min(height, maxHeight);
  var isWindowMaximized = this.GetIsMaximized(index);
  var isWindowCollapsed = this.GetIsCollapsed(index);
  var isWindowMaximizedAndCollapsed = (isWindowMaximized && isWindowCollapsed);
  if(this.SizeCanBeSet(index, isWindowMaximizedAndCollapsed)) {
   if(!this.CollapseExecuting() && !this.MaximizationExecuting() && !this.ResizingForMaxWindowLocked()) {
    this.SetWindowCachedSize(index, width, height);
    this.SetIsResized(index, true);
   }
   if(isWindowCollapsed && !this.MaximizationExecuting() && !this.ResizingForMaxWindowLocked()) {
    this.SetWindowCachedSize(index, width, height);
    this.UpdateRestoredWindowSize(index, width, height);
    height = 0;
   }
   if(isWindowMaximized && !this.CollapseExecuting() && !this.ResizingForMaxWindowLocked()) {
    this.SetWindowCachedSize(index, width, height);
    this.UpdateRestoredWindowSize(index, width, height);
   } else {
    this.SetWindowSizeByIndexCore(index, width, height, isWindowCollapsed);
   }
  } else
   this.SetWindowCachedSize(index, width, height);
 },
 SizeCanBeSet: function(index, isWindowMaximizedAndCollapsed) {
  return this.InternalIsWindowDisplayed(index) && this.IsWindowElementsIDAssigned(index) && (!isWindowMaximizedAndCollapsed || this.ResizingForMaxWindowLocked());
 },
 RestoreWindowSizeFromCache: function(index) {
  var cachedSize = this.GetWindowCachedSize(index);
  if(cachedSize != null) {
   if(cachedSize.width !== this.GetClientWindowWidth(index, true, true) ||
      cachedSize.height !== this.GetClientWindowHeight(index, true, true))
    this.SetWindowSizeByIndex(index, cachedSize.width, cachedSize.height);
   this.ResetWindowCachedSize(index);
  }
 },
 CollapseExecuting: function() {
  return false;
 },
 MaximizationExecuting: function() {
  return false;
 },
 ResizingForMaxWindowLocked: function() {
  return false;
 },
 IsResizeAllowed: function(index) {
  return this.allowResize;
 },
 GetWindowDimensionByIndex: function(index, isWidth, forceFromCache) {
  var cachedSize = this.GetWindowCachedSize(index);
  var dimensionValue = null;
  if(forceFromCache == undefined && !this.GetWindowElement(index))
   forceFromCache = true;
  if(cachedSize && forceFromCache)
   dimensionValue = isWidth ? cachedSize.width : cachedSize.height;
  if(dimensionValue)
   return dimensionValue;
  else {
   var element = this.GetWindowElement(index);
   var sizeFromDOM = 0;
   if(this.GetIsCollapsed(index)) {
    var headerCell = this.GetWindowHeaderElement(index);
    sizeFromDOM = isWidth ? headerCell.offsetWidth : headerCell.offsetHeight;
   }
   else {
    var mainCell = this.GetWindowMainCell(element);
    sizeFromDOM = isWidth ? mainCell.offsetWidth : mainCell.offsetHeight;
   }
   if(sizeFromDOM === 0 && cachedSize)
    sizeFromDOM = isWidth ? cachedSize.width : cachedSize.height;
   return sizeFromDOM;
  }
 },
 SetWindowSize: function(window, width, height) {
  var index = (window != null) ? window.index : -1;
  this.SetWindowSizeByIndex(index, width, height);
 },
 SetSize: function(width, height) {
  this.SetWindowSize(null, width, height);
 },
 SetWidth: function(width) {
  var height = this.GetHeight();
  this.SetSize(width, height);
 },
 SetHeight: function(height) {
  var width = this.GetWidth();
  this.SetSize(width, height);
 },
 GetHeight: function() {
  return this.GetWindowDimensionByIndex(-1, false, false);
 },
 GetWidth: function() {
  return this.GetWindowDimensionByIndex(-1, true, false);
 },
 CanBeClosedByClickOnElement: function(index, srcElement, posX, id) {
  return srcElement === null || ASPx.GetParentById(srcElement, id) === null;
 },
 OnMouseDown: function(evt, index, isDraggingAllowed, pointOnScrollBar) {
  if(ASPx.Evt.IsLeftButtonPressed(evt)) {
   if((this.IsResizeAllowed(index) || isDraggingAllowed) && !this.prohibitClearSelectionOnMouseDown) 
    ASPx.Selection.Clear();
   var isResizing = this.ProcessResizeOnMouseDown(evt, index);
   var clickedOnScroll = pointOnScrollBar && this.GetEnableContentScrolling(index);
   if(isDraggingAllowed && !isResizing && !clickedOnScroll && !this.GetIsPinned(index) && !this.GetIsMaximized(index) && !ASPx.Ident.IsFocusableElementRegardlessTabIndex(evt.target))
    this.OnDragStart(evt, index);
  }
 },
 OnMouseMove: function(evt, index) {
  if(this.allowResize && !this.GetIsCollapsed(index) && !this.GetIsMaximized(index))
   this.CreateResizeCursorInfo(evt, index);
 },
 CreateResizeCursorInfo: function(evt, index) {
  var element = this.GetWindowElement(index);
  var mainCell = this.GetWindowMainCell(element);
  var clientWindow = this.GetWindowClientTable(index);
  var headerElement = this.GetWindowHeaderElement(index);
  var left = ASPx.GetAbsoluteX(mainCell);
  var top = ASPx.GetAbsoluteY(mainCell);
  var x = ASPx.Evt.GetEventX(evt);
  var y = ASPx.Evt.GetEventY(evt);
  var mainCellWidth = mainCell.offsetWidth;
  var mainCellHeight = mainCell.offsetHeight;
  var leftOffset = Math.abs(x - left);
  var rightOffset = Math.abs(x - left - mainCellWidth);
  var topOffset = Math.abs(y - top);
  var bottomOffset = Math.abs(y - top - mainCellHeight);
  var cursorInfo = this.CreateResizeBorderCursorInfo(index, leftOffset, rightOffset, topOffset, bottomOffset);
  var grip = this.GetWindowSizeGripElement(index);
  if(grip) {
   var gripCursorInfo = this.CreateGripCursorInfo(index, mainCell, grip, leftOffset, rightOffset, bottomOffset);
   if(gripCursorInfo)
    cursorInfo = gripCursorInfo;
  }
  this.UpdateResizeCursor(index, clientWindow, cursorInfo.verticalDirection, cursorInfo.horizontalDirection);
  this.UpdateResizeCursor(index, mainCell, cursorInfo.verticalDirection, cursorInfo.horizontalDirection);
  if(headerElement)
   this.UpdateResizeCursor(index, headerElement, cursorInfo.verticalDirection, cursorInfo.horizontalDirection);
  return cursorInfo;
 },
 UpdateResizeCursor: function(index, element, verticalDirection, horizontalDirection) {
  var cursor = verticalDirection + horizontalDirection;
  if(cursor == "")
   this.HideTemporaryCursor(element);
  else {
   cursor += "-resize";
   this.ShowTemporaryCursor(element, cursor);
  }
 },
 CreateGripCursorInfo: function(index, mainCell, grip, leftOffset, rightOffset, bottomOffset) {
  var gripWidth = this.rtl
   ? ASPx.GetAbsoluteX(grip) - ASPx.GetAbsoluteX(mainCell) + grip.offsetWidth
   : mainCell.offsetWidth - (ASPx.GetAbsoluteX(grip) - ASPx.GetAbsoluteX(mainCell));
  var gripHeight = mainCell.offsetHeight - (ASPx.GetAbsoluteY(grip) - ASPx.GetAbsoluteY(mainCell));
  if(gripHeight > bottomOffset) {
   if(this.rtl && gripWidth > leftOffset)
    return new PCResizeCursorInfo("w", "s", leftOffset, bottomOffset);
   if(gripWidth > rightOffset)
    return new PCResizeCursorInfo("e", "s", rightOffset, bottomOffset);
  }
  return null;
 },
 CreateResizeBorderCursorInfo: function(index, leftOffset, rightOffset, topOffset, bottomOffset) {
  var ResizeBorderSize = this.ResizeBorderSize;
  var verticalDirection = this.GetResizeVerticalCourse(ResizeBorderSize, topOffset, bottomOffset);
  ResizeBorderSize = verticalDirection != "" ? this.ResizeCornerBorderSize : this.ResizeBorderSize;
  var horizontalDirection = this.GetResizeHorizontalCourse(ResizeBorderSize, leftOffset, rightOffset);
  if(verticalDirection == "" && horizontalDirection != "")
   verticalDirection = this.GetResizeVerticalCourse(this.ResizeCornerBorderSize, topOffset, bottomOffset);
  var horizontalOffset = leftOffset < rightOffset ? leftOffset : rightOffset;
  var verticalOffset = topOffset < bottomOffset ? topOffset : bottomOffset;
  return new PCResizeCursorInfo(horizontalDirection, verticalDirection, horizontalOffset, verticalOffset);
 },
 GetResizeVerticalCourse: function(ResizeBorderSize, topOffset, bottomOffset) {
  if(ResizeBorderSize > topOffset) return "n";
  if(ResizeBorderSize > bottomOffset) return "s";
  return "";
 },
 GetResizeHorizontalCourse: function(ResizeBorderSize, leftOffset, rightOffset) {
  if(ResizeBorderSize > leftOffset) return "w";
  if(ResizeBorderSize > rightOffset) return "e";
  return "";
 },
 ProcessResizeOnMouseDown: function(evt, index) {
  var isResizing = false;
  if(this.IsResizeAllowed(index) && !this.GetIsCollapsed(index) && !this.GetIsMaximized(index)) {
   var eventSourceControl = ASPx.Evt.GetEventSource(evt);
   var eventFromPopupContainer = ASPx.ElementHasCssClass(eventSourceControl, PopupControlCssClasses.ContentCssClassName) ||
    !ASPx.GetParentByClassName(eventSourceControl, PopupControlCssClasses.ContentCssClassName) ||
    this.eventFromOwnPopupContent(eventSourceControl);
   if(eventFromPopupContainer && getComputedStyle(evt.target).cursor !== "pointer")
    isResizing = this.OnResizeStart(evt, index);
  }
  if(isResizing && ASPx.Browser.WebKitTouchUI)
   aspxGetPopupControlCollection().OverStop();
  return isResizing;
 },
 eventFromOwnPopupContent: function(element) {
  while(element != null) {
   if(element.tagName == "BODY")
    return false;
   if(element.style.position == "absolute") {
    var windowIndex = this.GetWindowIndex(element);
    var isPopupWindow = !isNaN(windowIndex);
    if(isPopupWindow) {
     if(this.GetWindowElementId(windowIndex) == element.id)
      return true;
     return false;
    } else {
     var elementIsOtherPopup = element.style.zIndex >= this.GetPopupControlZIndex(); 
     if(elementIsOtherPopup)
      return false;
    }
   }
   element = element.parentNode;
  }
  return false;
 },
 OnResizeStart: function(evt, index) {
  if(!aspxGetPopupControlCollection().IsResizeInint()) {
   var cursor = this.CreateResizeCursorInfo(evt, index);
   if(cursor.course != "") {
    aspxGetPopupControlCollection().setIframesMouseMoveEnabled(false);
    this.EnsureWindowCoverDiv(index);
    this.SetIsResized(index, true);
    var resizePanel = this.CreateResizePanel(index);
    this.UpdateResizeCursor(index, resizePanel, cursor.verticalDirection, cursor.horizontalDirection);
    aspxGetPopupControlCollection().InitResizeObject(this, index, cursor, resizePanel);
    this.OnResize(evt, index, cursor, resizePanel);
   }
   ASPx.TouchUIHelper.startPreventingTouchMove();
  }
  return aspxGetPopupControlCollection().IsResizeInint();
 },
 OnResizeStop: function(evt, index, cursor, resizePanel) {
  if(this.IsResizeAllowed(index)) {
   ASPx.TouchUIHelper.stopPreventingTouchMove();
   aspxGetPopupControlCollection().setIframesMouseMoveEnabled(true);
   this.RemoveWindowCoverDiv();
   var windowElement;
   if(!this.isLiveResizingMode) {
    windowElement = this.GetWindowElement(index);
    ASPx.GetControlCollection().CollapseControls(windowElement);
    this.OnResizeWindow(index, cursor, resizePanel);
   }
   this.CreateResizeCursorInfo(evt, index);
   this.UpdateWindowsStateCookie();
   this.RaiseResize(index);
   if(!this.isLiveResizingMode)
    ASPx.GetControlCollection().AdjustControls(windowElement, true);
  }
  this.ResetResizeSessionCache();
 },
 OnResizeWindow: function(index, cursor, resizePanel) {
  var windowElement = this.GetWindowElement(index);
  var resizePanelDimensions = this.GetResizePanelDimensions();
  var left = resizePanelDimensions.left;
  var top = resizePanelDimensions.top;
  this.SetClientWindowSizeLite(index, resizePanelDimensions.offsetWidth, resizePanelDimensions.offsetHeight);
  if(this.fixedBottom)
   top = this.fixedBottom - windowElement.offsetHeight;
  if(this.fixedRight)
   left = this.fixedRight - windowElement.offsetWidth;
  this.fixedBottom = null;
  this.fixedRight = null;
  if(cursor.verticalDirection === "n")
   this.ChangePosOnResizeWindow(top, windowElement, false);
  if(cursor.horizontalDirection === "w")
   this.ChangePosOnResizeWindow(left, windowElement, true);
  if(this.InternalIsWindowVisible(index)) 
   this.DoShowWindowIFrame(index, left, top, ASPx.InvalidDimension, ASPx.InvalidDimension);
 },
 ChangePosOnResizeWindow: function(pos, windowElement, isX) {
  windowElement.style[isX ? "left" : "top"] = pos + "px";
 },
 SetClientWindowSizeLite: function(index, width, height, isWindowCollapsed) {
  this.RaiseBeforeResizing(index);
  this.SetClientWindowSizeCoreLite(index, width, height, isWindowCollapsed);
  if(!this.IsRaiseAfterResizingLocked())
   this.RaiseAfterResizing(index);
 },
 SetClientWindowSizeCoreLite: function(index, width, height, isWindowCollapsed) {
  var contentUrl = this.GetWindowContentIFrameUrl(index);
  var needToHideContent = !contentUrl;
  var element = this.GetWindowElement(index);
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  var contentElement = this.GetWindowContentElement(index);
  var contentIframeElement = this.GetWindowContentIFrameElement(index);
  var iframeHeightCorrectionOnFirstShow = height > 0;
  if(contentIframeElement && (this.GetWindowIsShown(index) || iframeHeightCorrectionOnFirstShow))
   contentIframeElement.style.height = "0px";
  contentWrapper.style.height = "";
  contentWrapper.style.width = "";
  contentElement.style.height = "";
  contentElement.style.width = "";
  var hasAnyScrollBars = this.HasAnyScrollBars(index);
  var expectedHeight = (!ASPx.IsExists(height) && hasAnyScrollBars) ? this.GetExpectedHeight(index) : null;
  if(needToHideContent)
   contentElement.style.display = "none";
  var elementsDisplayValue = this.GetWindowElementDisplayValue(hasAnyScrollBars, height);
  element.style.display = elementsDisplayValue;
  if(!this.GetIsCollapsed(index))
   contentWrapper.style.display = elementsDisplayValue;
  if(ASPx.IsExists(width)) {
   var actualWidth = width - this.GetElementBordersAndPaddings(index, element, true);
   if(actualWidth <= 0)
    actualWidth = ASPx.Browser.WebKitFamily ? 1 : 0; 
   element.style.width = actualWidth + "px";
  }
  var actualHeight;
  if(ASPx.IsExists(height)) {
   actualHeight = height - this.GetElementBordersAndPaddings(index, element, false);
   if(actualHeight < 0)
    actualHeight = 0;
   element.style.height = actualHeight + "px";
  } else {
   if(ASPx.IsExists(expectedHeight)) {
    actualHeight = expectedHeight;
    element.style.height = actualHeight + "px";
   }
  }
  this.CorrectWindowSizeGripPositionLite(index);
  this.CorrectWindowHeaderText(index);
  this.SetContentWrapperHeightLite(index, actualHeight, element, contentWrapper);
  var correctContentElementSize = hasAnyScrollBars || contentElement.style.overflow == "hidden" || contentElement.style.overflowX == "hidden" || contentElement.style.overflowY == "hidden";
  if((correctContentElementSize || contentUrl) && (height || expectedHeight)) {
   if(contentElement !== contentWrapper) {
    var contentHeight = ASPx.GetClearClientHeight(contentWrapper);
    if(contentHeight < 0)
     contentHeight = 0;
    contentElement.style.height = contentHeight + "px";
   }
  }
  if(correctContentElementSize && width && contentElement !== contentWrapper)
   contentElement.style.width = ASPx.GetClearClientWidth(contentWrapper) + "px";
  contentElement.style.display = this.getContentElementDisplay(correctContentElementSize, contentUrl);
  if(contentIframeElement)
   contentIframeElement.style.height = "100%";
  this.SetWindowWidth(index, width);
  this.SetWindowHeight(index, height);
  if(isWindowCollapsed)
   this.ResetWindowHeight(index);
 },
 GetExpectedHeight: function(index) {
  var height = this.GetWindowHeightInternal(index) || 0;
  height = Math.max(height, this.GetWindowMinHeight(index));
  if(this.HasAnyScrollBars(index)) {
   var windowHeight = this.GetWindowContentElement(index).offsetHeight + this.GetWindowHeightWithoutContent(index);
   height = Math.max(height, windowHeight);
  }
  var maxHeight = this.GetWindowMaxHeight(index);
  if(maxHeight)
   height = Math.min(height, maxHeight);
  return height;
 },
 IsRaiseAfterResizingLocked: function() {
  return false;
 },
 CreateResizePanel: function(index) {
  var element = this.GetWindowElement(index);
  var resizePanel = document.createElement("DIV");
  element.parentNode.appendChild(resizePanel);
  resizePanel.style.overflow = "hidden";
  resizePanel.style.position = "absolute";
  resizePanel.style.zIndex = this.GetPopupControlZIndex() + aspxGetPopupControlCollection().visiblePopupWindowIds.length * 2 + 2;
  if(!this.isLiveResizingMode)
   resizePanel.style.border = "black 1px dotted";
  return resizePanel;
 },
 OnResize: function(evt, index, cursor, resizePanel) {
  this.OnResizePanelLite(evt, index, cursor, resizePanel);
  if(this.isLiveResizingMode)
   this.OnResizeWindow(index, cursor, resizePanel);
  ASPx.Selection.Clear();
  if(ASPx.Browser.WebKitTouchUI)
   ASPx.Evt.PreventEvent(evt);
  if(this.GetIsPinned(index))
   this.HoldPosition(index, true, resizePanel);
 },
 OnResizePanelLite: function(evt, index, cursor, resizePanel) {
  var x = ASPx.Evt.GetEventX(evt);
  var y = ASPx.Evt.GetEventY(evt);
  var element = this.GetWindowElement(index);
  var elementTop = ASPx.GetAbsoluteY(element);
  var elementLeft = ASPx.GetAbsoluteX(element);
  var newLeft = ASPx.PxToInt(element.style.left);
  var newTop = ASPx.PxToInt(element.style.top);
  var newWidth = element.offsetWidth;
  var newHeight = element.offsetHeight;
  if(cursor.verticalDirection == "n") {
   if(!this.fixedBottom)
    this.fixedBottom = newTop + newHeight;
   newHeight += elementTop - y + cursor.verticalOffset;
   newTop = ASPx.PrepareClientPosForElement(y - cursor.verticalOffset, element, false);
  }
  if(cursor.verticalDirection == "s") {
   newHeight = y - elementTop + cursor.verticalOffset;
   this.fixedBottom = null;
  }
  if(cursor.horizontalDirection == "w") {
   if(!this.fixedRight)
    this.fixedRight = newLeft + newWidth;
   newWidth += elementLeft - x + cursor.horizontalOffset;
   newLeft = ASPx.PrepareClientPosForElement(x - cursor.horizontalOffset, element, true);
  }
  if(cursor.horizontalDirection == "e") {
   newWidth = x - elementLeft + cursor.horizontalOffset;
   this.fixedRight = null;
  }
  if(newWidth > 0 && newHeight > 0) {
   var minWidth = this.GetWindowMinWidth(index);
   var maxWidth = this.GetWindowMaxWidth(index);
   if(minWidth && newWidth < minWidth)
    newWidth = minWidth;
   if(maxWidth && newWidth > maxWidth)
    newWidth = maxWidth;
   var minHeight = this.GetWindowMinHeight(index);
   var maxHeight = this.GetWindowMaxHeight(index);
   if(minHeight && newHeight < minHeight)
    newHeight = minHeight;
   if(maxHeight && newHeight > maxHeight)
    newHeight = maxHeight;
   this.SetResizePanelDimensions(newLeft, newTop, newWidth, newHeight);
   var widthWithoutBorders = newWidth - this.getLeftRightBordersAndPaddingsSummaryValue(resizePanel);
   var heightWithoutBorders = newHeight - this.getTopBottomBordersAndPaddingsSummaryValue(resizePanel);
   ASPx.SetStyles(resizePanel, {
    left: newLeft, top: newTop,
    width: widthWithoutBorders, height: heightWithoutBorders
   });
   this.SetWindowLeft(index, elementLeft);
   this.SetWindowTop(index, elementTop);
  }
 },
 SetResizePanelDimensions: function(left, top, offsetWidth, offsetHeight) {
  var cache = this.GetResizeSessionCache();
  cache.resizePanelDimensions = {
   left: left,
   top: top,
   offsetWidth: offsetWidth,
   offsetHeight: offsetHeight
  };
 },
 GetResizePanelDimensions: function() {
  var cache = this.GetResizeSessionCache();
  return cache.resizePanelDimensions;
 },
 ResetResizeSessionCache: function() {
  this.resizeSessionCache = {};
 },
 GetResizeSessionCache: function() {
  return aspxGetPopupControlCollection().IsResizeInint() ? this.resizeSessionCache : {};
 },
 EnsureWindowCoverDiv: function(index) {
  this.windowCoverDiv = this.CreateCoverDiv(index);
  var windowElement = this.GetWindowElement(index);
  windowElement.parentNode.appendChild(this.windowCoverDiv);
 },
 CreateCoverDiv: function(index) {
  var coverDiv = document.createElement("DIV");
  ASPx.SetStyles(coverDiv, {
   position: "fixed",
   left: 0,
   top: 0,
   width: "100%",
   height: "100%"
  });
  return coverDiv;
 },
 RemoveWindowCoverDiv: function() {
  if(!!this.windowCoverDiv) {
   this.windowCoverDiv.parentNode.removeChild(this.windowCoverDiv);
   this.windowCoverDiv = null;
  }
 },
 OnDrag: function(index, x, y, xClientCorrection, yClientCorrection) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   ASPx.SetStyles(element, { left: x, top: y });
   xClientCorrection = typeof (xClientCorrection) != "undefined" ? xClientCorrection : 0;
   yClientCorrection = typeof (yClientCorrection) != "undefined" ? yClientCorrection : 0;
   this.SetWindowLeft(index, x + xClientCorrection);
   this.SetWindowTop(index, y + yClientCorrection);
   var iFrame = element.overflowElement;
   if(iFrame)
    ASPx.SetStyles(iFrame, { left: x, top: y });
   if(ASPx.Browser.Opera)
    ASPx.Selection.Clear();
  }
 },
 OnDragStop: function(index) {
  this.HideDragCursor(index);
  this.UpdateWindowsStateCookie();
  if(this.GetWindowContentIFrameElement(index))
   this.SetIframeVisibleForDragging(index, true);
  ASPx.TouchUIHelper.stopPreventingTouchMove();
  this.RaiseDragged(index);
 },
 OnDragStart: function(evt, index) {
  this.RaiseBeforeDrag(index);
  this.SetIsDragged(index, true);
  this.ShowDragCursor(index);
  ASPx.TouchUIHelper.startPreventingTouchMove();
  if(this.GetWindowContentIFrameElement(index))
   this.SetIframeVisibleForDragging(index, false);
  this.InitDragInfo(index, evt);
 },
 HideIframeElementBeforeDragging: function() {
 },
 InitDragInfo: function(index, evt) {
  var element = this.GetWindowElement(index);
  var gragXOffset = ASPx.GetAbsoluteX(element) - ASPx.Evt.GetEventX(evt);
  var gragYOffset = ASPx.GetAbsoluteY(element) - ASPx.Evt.GetEventY(evt);
  var xClientCorrection = this.GetDragCorrection(index, element, true);
  var yClientCorrection = this.GetDragCorrection(index, element, false);
  gragXOffset -= xClientCorrection;
  gragYOffset -= yClientCorrection;
  aspxGetPopupControlCollection().InitDragObject(this, index, gragXOffset, gragYOffset, xClientCorrection, yClientCorrection);
 },
 GetDragCorrection: function(index, element, isX) {
  return ASPx.GetPositionElementOffset(element, isX);
 },
 ShowDragCursor: function(index) {
  var dragElement = this.GetDragElement(index);
  if(dragElement)
   this.ShowTemporaryCursor(dragElement, "move");
 },
 ShowTemporaryCursor: function(element, cursor) {
  ASPx.Attr.ChangeStyleAttribute(element, "cursor", cursor);
 },
 HideDragCursor: function(index) {
  var dragElement = this.GetDragElement(index);
  if(dragElement != null)
   this.HideTemporaryCursor(dragElement);
 },
 GetDragElement: function(index) {
  var headerElement = this.GetWindowHeaderElement(index);
  var element = this.GetWindowElement(index);
  if(element != null)
   return (headerElement != null ? headerElement : this.GetWindowMainCell(element));
  return null;
 },
 HideTemporaryCursor: function(element) {
  ASPx.Attr.RestoreStyleAttribute(element, "cursor");
 },
 OnDocumentKeyDown: function(evt, popupWindow) {
  var handler = this.keyDownHandlers && this.keyDownHandlers[ASPx.GetShortcutCode(evt.keyCode, evt.ctrlKey, evt.shiftKey, evt.altKey)];
  if(handler)
   handler(this.GetWindowIndex(popupWindow));
 },
 OnEscKeyDown: function(index) {
  if(this.GetEnableCloseByEsc(index))
   this.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.Escape);
 },
 OnRefreshButtonClick: function(index) {
  var contentIFrame = this.GetWindowContentIFrameElement(index);
  if(contentIFrame)
   this.RefreshWindowContentUrl(this.GetWindow(index));
  else
   this.PerformWindowCallback(this.GetWindow(index));
 },
 OnCloseButtonClick: function(index) {
  this.RaiseCloseButtonClick(index);
  if(this.GetWindowCloseAction(index) != "None")
   this.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.CloseButton);
 },
 Show: function(popupElementIndex) {
  this.ShowWindowByIndex(-1, popupElementIndex);
 },
 Hide: function() {
  this.HideWindow(null);
 },
 HideWindow: function(window) {
  var index = (window != null) ? window.index : -1;
  this.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.API);
 },
 RaiseEventByIndex: function(index, event, argsName) {
  if(!event.IsEmpty()) {
   var window = index < 0 ? null : this.GetWindow(index),
    args = new argsName(window);
   event.FireEvent(this, args);
  }
 },
 RaiseCloseButtonClick: function(index) {
  this.RaiseEventByIndex(index, this.CloseButtonClick, ASPxClientPopupWindowEventArgs);
 },
 RaiseShown: function(index) {
  this.RaiseEventByIndex(index, this.Shown, ASPxClientPopupWindowEventArgs);
 },
 RaisePopUp: function(index) {
  this.RaiseEventByIndex(index, this.PopUp, ASPxClientPopupWindowEventArgs);
 },
 RaiseBeforeResizing: function(index) {
  this.RaiseEventByIndex(index, this.BeforeResizing, ASPxClientPopupWindowEventArgs);
 },
 RaiseAfterResizing: function(index) {
  this.RaiseEventByIndex(index, this.AfterResizing, ASPxClientPopupWindowEventArgs);
 },
 RaiseDragged: function(index) {
  this.RaiseEventByIndex(index, this.Dragged, ASPxClientPopupWindowEventArgs);
 },
 RaiseBeforeDrag: function(index) {
  this.RaiseEventByIndex(index, this.BeforeDrag, ASPxClientPopupWindowEventArgs);
 },
 RaiseClosing: function(index, closeReason) {
  var window = index < 0 ? null : this.GetWindow(index);
  var cancel = false;
  if(!this.Closing.IsEmpty()) {
   var args = new ASPxClientPopupWindowCancelEventArgs(window, closeReason);
   this.Closing.FireEvent(this, args);
   cancel = args.cancel;
  }
  return cancel;
 },
 RaiseCloseUp: function(index, closeReason) {
  var window = index < 0 ? null : this.GetWindow(index);
  if(!this.CloseUp.IsEmpty()) {
   var args = new ASPxClientPopupWindowCloseUpEventArgs(window, closeReason);
   this.CloseUp.FireEvent(this, args);
  }
 },
 RaiseResize: function(index, resizeState) {
  var window = index < 0 ? null : this.GetWindow(index);
  if(!this.Resize.IsEmpty()) {
   if(!resizeState)
    resizeState = ASPxClientPopupControlResizeState.Resized;
   var args = new ASPxClientPopupWindowResizeEventArgs(window, resizeState);
   this.Resize.FireEvent(this, args);
  }
 },
 RaisePopupOnShow: function(isMoving, index) {
  if(!isMoving) {
   this.RaisePopUp(index);
   if(!this.IsAnimationAllowed() || !this.HasOpenAnimation())
    this.OnWindowShown(index);
  }
 },
 OnActivate: function(index, evt) {
  var element = this.GetWindowElement(index);
  if(element != null)
   aspxGetPopupControlCollection().ActivateWindowElement(element, evt, this.GetPopupType(), this.GetDefaultZIndexFromServer(), this.GetPopupControlZIndex());
 },
 OnPWHBClickCore: function(evt, index, method) {
  this.OnActivate(index, evt);
  if(ASPx.TouchUIHelper.handleFastTapIfRequired(evt,
   function() { this[method](index); }.aspxBind(this), true)) {
   return;
  }
  if(ASPx.Browser.Opera)
   ASPx.Evt.EmulateDocumentOnMouseDown(evt);
  this[method](index);
 },
 OnScroll: function(evt, index) {
  if(this.HasIframeOnIos(index))
   this.ResetWebkitScrolling(this.getTouchScrollerElement(index), 0);
  if(!this.GetIsPinned(index) || (this.lockScroll > 0)) return;
  this.AdjustPinPositionWhileScroll(index);
 },
 ResetWebkitScrolling: function(scrollElement, timeout) {
  if(scrollElement.scrollTop === 0) {
   var styleName = "-webkit-overflow-scrolling";
   scrollElement.style[styleName] = "auto";
   window.setTimeout(function() {
    scrollElement.style[styleName] = "touch";
   }.aspxBind(this), timeout);
  }
 },
 HaveSpecialDivForAnimation: function() {
  return this.enableAnimation;
 },
 HasIframeOnIos: function(index) {
  return ASPx.Browser.MacOSMobilePlatform && !!this.GetWindowContentIFrameElement(index);
 },
 WindowIsModal: function(index) {
  return this.GetPropertyValue(index, "modal");
 },
 GetIsPopuped: function(index) {
  if(0 <= index && index < this.GetWindowCountCore())
   return this.windowsIsPopupedList[index];
  return this.defaultIsPopuped;
 },
 SetIsPopuped: function(index, isPopuped) {
  if(0 <= index && index < this.GetWindowCountCore())
   this.windowsIsPopupedList[index] = isPopuped;
  this.defaultIsPopuped = isPopuped;
 },
 GetIsMaximized: function(index) {
  return false;
 },
 GetIsMaximizedInit: function(index) {
  return false;
 },
 GetCurrentLeft: function(index) {
  return this.GetPosition(index, true);
 },
 GetCurrentTop: function(index) {
  return this.GetPosition(index, false);
 },
 GetIsPinned: function(index) {
  return false;
 },
 GetIsCollapsed: function(index) {
  return false;
 }, 
 needToHidePinnedOutFromViewPort: function(index) {
  return false;
 },
 GetHideBodyScrollWhenModal: function(index) {
  return false;
 },
 GetCanScrollViewPort: function(index) {
  return false;
 },
 GetEnableContentScrolling: function(index) {
  return false;
 },
 AutoUpdateElementsPosition: function() {
 },
 GetWindowChild: function(index, idPostfix) {
  var elem = this.GetWindowElement(index);
  if(elem)
   return ASPx.GetChildById(elem, this.name + idPostfix);
  return null;
 },
 GetWindowIndex: function(element) {
  var id = element.id;
  var pos = id.lastIndexOf(ASPx.PCWIdSuffix);
  return parseInt(id.substr(pos + ASPx.PCWIdSuffix.length));
 },
 GetWindow: function(index) {
  return (0 <= index && index < this.windows.length) ? this.windows[index] : null;
 },
 DoShowWindowIFrame: function(index, x, y, width, height) {
  if(!this.renderIFrameForPopupElements) return;
  var element = this.GetWindowElement(index);
  var iFrame = this.GetWindowIFrame(index);
  if(element && iFrame) {
   var cell = this.GetWindowMainCell(element);
   if(width < 0)
    width = cell.offsetWidth;
   if(height < 0)
    height = cell.offsetHeight;
   ASPx.SetStyles(iFrame, { width: width, height: height });
   if(this.IsValidPosition(x) && this.IsValidPosition(y))
    ASPx.SetStyles(iFrame, { left: x, top: y });
   if(ASPx.Browser.Firefox)
    this.ClearWindowIframeBodyInnerHtml(iFrame);
   ASPx.SetElementDisplay(iFrame, true);
  }
 },
 IsValidPosition: function(pos) {
  return pos !== ASPx.InvalidPosition;
 },
 DoHideWindowIFrame: function(element) {
  if(!this.renderIFrameForPopupElements) return;
  var iFrame = element.overflowElement;
  if(iFrame)
   ASPx.SetElementDisplay(iFrame, false);
 },
 GetIframeBody: function(iFrame) {
  var document = iFrame.contentDocument || iFrame.contentWindow.document;
  if(document)
   return document.getElementsByTagName('body')[0];
 },
 ClearWindowIframeBodyInnerHtml: function(iFrame) {
  var iFrameBody = this.GetIframeBody(iFrame);
  if(iFrameBody)
   iFrameBody.innerHTML = "";
 },
 FindWindowIFrame: function(index) {
  return ASPx.GetElementById(this.name + "_DXPWIF" + index);
 },
 GetWindowIFrame: function(index) {
  var element = this.GetWindowElement(index);
  var iFrame = element.overflowElement;
  if(!iFrame) {
   iFrame = this.FindWindowIFrame(index);
   element.overflowElement = iFrame;
  }
  return iFrame;
 },
 CreateFakeDivForIframe: function(iframe) {
  var fakeDiv = document.createElement("div");
  ASPx.SetStyles(fakeDiv, { width: iframe.offsetWidth, height: iframe.offsetHeight });
  return fakeDiv;
 },
 CreateIframeCoverDiv: function(iframe, index) {
  if(!this.iframeCoverDiv)
   this.iframeCoverDiv = [];
  if(!this.iframeCoverDiv[index])
   this.iframeCoverDiv[index] = this.CreateFakeDivForIframe(iframe);
  this.iframeCoverDiv[index].style.position = "absolute";
  iframe.parentElement.appendChild(this.iframeCoverDiv[index]);
  ASPx.SetAbsoluteX(this.iframeCoverDiv[index], ASPx.GetAbsoluteX(iframe));
  ASPx.SetAbsoluteY(this.iframeCoverDiv[index], ASPx.GetAbsoluteY(iframe));
 },
 RemoveIframeCoverDiv: function(iframe, index) {
  iframe.parentElement.removeChild(this.iframeCoverDiv[index]);
  this.iframeCoverDiv[index] = null;
 },
 GetWindowBorderOwnerElement: function(windowElement) {
  if(ASPx.ElementHasCssClass(windowElement, PopupControlCssClasses.MainDivLiteCssClass))
   return windowElement;
  else
   return ASPx.GetNodeByClassName(windowElement, PopupControlCssClasses.MainDivLiteCssClass);
 },
 GetWindowContentIFrameElement: function(index) {
  return this.GetWindowChild(index, "_CIF" + index);
 },
 GetWindowContentElement: function(index) {
  return this.GetWindowChild(index, "_PWC" + index);
 },
 GetWindowContentIFrameElementId: function(index) {
  return this.name + "_CIF" + index;
 },
 GetContentContainer: function(index) {
  return this.GetWindowContentElement(index);
 },
 getTouchScrollerElement: function(index) {
  return this.GetContentContainer(index);
 },
 GetWindowHeaderElement: function(index) {
  return this.GetWindowChild(index, "_PWH" + index);
 },
 GetWindowFooterElement: function(index) {
  return this.GetWindowChild(index, "_PWF" + index);
 },
 GetWindowSizeGripElement: function(index) {
  var footer = this.GetWindowFooterElement(index);
  if(!footer)
   return null;
  var descendants = ASPx.GetNodesByClassName(footer, PopupControlCssClasses.SizeGripLiteCssClassName);
  return descendants.length > 0 ? descendants[0] : null;
 },
 GetWindowContentWrapperElement: function(index) {
  if(!ASPx.IsExistsElement(this.windowContentElements[index])) {
   var windowElem = this.GetWindowElement(index);
   var contentWrapperParent = this.GetWindowMainCell(windowElem);
   this.windowContentElements[index] = ASPx.GetChildByClassName(contentWrapperParent, PopupControlCssClasses.ContentWrapperCssClassName);
  }
  return this.windowContentElements[index];
 },
 GetWindowMainCell: function(element) {
  return this.HaveSpecialDivForAnimation() ? ASPx.GetNodeByTagName(element, "DIV", 0) : element;
 },
 GetWindowModalElement: function(index) {
  var element = this.GetWindowElement(index);
  if(!element) return;
  var modalElement = element.modalElement;
  if(!modalElement) {
   modalElement = this.FindWindowModalElement(index);
   element.modalElement = modalElement;
   if(modalElement) {
    modalElement.DXModalPopupControl = this;
    modalElement.DXModalPopupWindowIndex = index;
   }
  }
  return modalElement;
 },
 CanManipulateWithModalElement: function(index) {
  return this.WindowIsModal(index);
 },
 GetCurrentZIndex: function(index) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   if(element.style.zIndex != "" && element.style.zIndex != this.GetDefaultZIndexFromServer())
    return element.style.zIndex;
   return this.GetZIndex(index);
  }
 },
 GetWindowsState: function() {
  var state = "";
  if(this.HasDefaultWindow()) {
   state += this.GetWindowState(-1);
  }
  return state;
 },
 GetWindowState: function(index) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   var visibleFlag = (!this.InternalIsWindowVisible(index) || element.isHiding) ? "0" : "1";
   var isDraggedFlag = this.GetIsDragged(index) ? "1" : "0";
   var zIndex = this.GetCurrentZIndex(index);
   var isResized = this.GetIsResized(index);
   var isResizedFlag = isResized ? "1" : "0";
   var width = null, height=null;
   if(isResized) {
    width = this.GetWindowWidthInternal(index);
    height = this.GetIsCollapsed(index) ? this.GetWindowDimensionByIndex(index, false, true) : this.GetWindowHeightInternal(index);
   } else {
    width = ASPx.InvalidDimension;
    height = ASPx.InvalidDimension;
   }
   var contentWasLoaded = element.loaded ? "1" : "0";
   var left, top;
   var isMaximized = this.GetIsMaximized(index);
   if(isMaximized && !this.MaximizationExecuting()) {
    var restoredWindowData = this.GetRestoredWindowData(index);
    left = restoredWindowData.left;
    top = restoredWindowData.top;
   } else {
    left = this.GetCurrentLeft(index);
    top = this.GetCurrentTop(index);
   }
   var isPinned = this.GetIsPinned(index);
   if(isPinned) {
    left -= ASPx.GetDocumentScrollLeft();
    top -= ASPx.GetDocumentScrollTop();
   }
   left = Math.ceil(left);
   top = Math.ceil(top);
   var pinFlag = isPinned ? "1" : "0";
   var minFlag = this.GetIsCollapsed(index) ? "1" : "0";
   var maxFlag = isMaximized || this.GetIsMaximizedInit(index) ? "1" : "0";
   return [visibleFlag, isDraggedFlag, zIndex, left, top, isResizedFlag, width, height, contentWasLoaded, pinFlag, minFlag, maxFlag].join(":");
  }
  return "";
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ windowsState: this.GetWindowsState() });
 },
 GetStateHiddenFieldOrigin: function() {
  return this.GetWindowElement(this.GetWindowCountCore() - 1);
 },
 GetPopupType: function() {
  return "aspxpopup";
 },
 GetDefaultZIndexFromServer: function() {
  return defaultZIndexFromServer;
 },
 GetPopupControlZIndex: function() {
  return popupControlZIndex;
 },
 FindWindowModalElement: function(index) {
  return ASPx.GetElementById(this.name + "_DXPWMB" + index);
 },
 GetWindowCloseButton: function(index) {
  return ASPx.GetElementById(this.name + "_HCB" + index);
 },
 GetWindowRefreshButton: function(index) {
  return ASPx.GetElementById(this.name + "_HRB" + index);
 },
 FirstShowWindow: function(index, allowChangeZIndex) {
  var popupHorizontalOffsetBackup = -1;
  var popupVerticalOffsetBackup = -1;
  var isFreeWindow = this.GetIsDragged(index);
  var x = ASPx.InvalidPosition;
  var y = ASPx.InvalidPosition;
  if(isFreeWindow) {
   x = this.GetWindowLeft(index);
   y = this.GetWindowTop(index);
   popupHorizontalOffsetBackup = this.popupHorizontalOffset;
   popupVerticalOffsetBackup = this.popupVerticalOffset;
   this.popupHorizontalOffset = 0;
   this.popupVerticalOffset = 0;
  }
  this.LockAnimation();
  this.DoShowWindowCore(index, x, y, isFreeWindow ? -1 : 0, false, allowChangeZIndex);
  this.UnlockAnimation();
  if(isFreeWindow) {
   this.popupHorizontalOffset = popupHorizontalOffsetBackup;
   this.popupVerticalOffset = popupVerticalOffsetBackup;
  }
  this.CorrectElementVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetWindowHeaderElement(index));
  this.CorrectFooterTextElementWidth(index);
 },
 HasDefaultWindow: function() {
  return true;
 },
 GetWindowCount: function() {
  return 0;
 },
 GetWindowContentHtml: function(window) {
  var index = (window != null) ? window.index : -1;
  var element = this.GetContentContainer(index);
  return (element != null) ? element.innerHTML : "";
 },
 GetWindowElementId: function(index) {
  return this.name + ASPx.PCWIdSuffix + index;
 },
 GetWindowElement: function(index) {
  if(!ASPx.IsExistsElement(this.windowElements[index]))
   this.windowElements[index] = ASPx.GetElementById(this.GetWindowElementId(index));
  return this.windowElements[index];
 },
 GetWindowClientTable: function(index) {
  return this.GetWindowElement(index);
 },
 GetCurrentWindowElement: function() {
  return this.GetWindowElement(-1);
 },
 getActualMainElement: function() { return this.GetCurrentWindowElement(); },
 ShowWindowContentUrl: function(index) {
  var contentIFrame = this.GetWindowContentIFrameElement(index);
  this.LoadWindowContentUrl(index);
  if(contentIFrame && contentIFrame.DXReloadAfterShowRequired) {
   this.RefreshWindowContentUrl(this.GetWindow(index));
   contentIFrame.DXReloadAfterShowRequired = false;
  }
 },
 RefreshWindowContentUrl: function(window) {
  this.RefreshWindowContentUrlCommon(window);
 },
 RefreshContentUrl: function() {
  this.RefreshWindowContentUrl(null);
 },
 RefreshWindowContentUrlCommon: function(window) {
  this.SetWindowContentUrl(window, this.GetWindowContentUrl(window));
 },
 GetContentUrl: function() {
  return this.GetWindowContentUrl(null);
 },
 GetWindowContentUrl: function(window) {
  var index = (window != null) ? window.index : -1;
  if(!this.IsWindowVisible(window))
   return this.GetWindowContentIFrameUrl(index);
  var element = this.GetWindowContentIFrameElement(index);
  return (element != null) ? element.src : "";
 },
 GetContentIFrame: function(window) {
  return this.GetWindowContentIFrame(null);
 },
 GetWindowContentIFrame: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetWindowContentIFrameElement(index);
 },
 GetContentIFrameWindow: function() {
  var iframeElement = this.GetContentIFrame();
  return iframeElement.contentWindow;
 },
 SetContentUrl: function(url) {
  this.SetWindowContentUrl(null, url);
 },
 SetWindowContentUrl: function(window, url) {
  var index = (window != null) ? window.index : -1;
  this.SetWindowContentUrlInternal(index, url);
 },
 LoadWindowContentUrl: function(index) {
  var url = this.GetWindowContentIFrameUrl(index);
  this.LoadWindowContentFromUrl(index, url);
 },
 LoadWindowContentFromUrl: function(index, url) {
  var element = this.GetWindowContentIFrameElement(index);
  if(element && element.src != url && element.DXSrcRaw != url) {
   this.SetSrcToIframeElement(index, element, url);
   this.SetWindowContentIFrameUrl(index, element.src); 
  }
 },
 SetWindowContentIFrameUrl: function(index, url) {
  this.SetPropertyValue(index, "contentUrl", url);
 },
 SetWindowContentUrlInternal: function(index, url) {
  var element = this.GetWindowContentIFrameElement(index);
  var windowVisible = this.InternalIsWindowVisible(index);
  if(windowVisible && element != null)
   this.SetIframeVisibleForDragging(index, true);
  this.SetWindowContentIFrameUrl(index, url);
  var src = windowVisible ? url : ASPx.Browser.WebKitFamily && ASPx.Browser.Version >= 75 ? "about:blank" : ASPx.SSLSecureBlankUrl;
  if(element == null) {
   this.CreateWindowContentIFrameElement(index, src);
   this.RefreshDimensionsAfterCreateIframe(index);
  }
  else
   this.SetSrcToIframeElement(index, element, src);
  this.ReinitScrollForIframe(index);
 },
 ReinitScrollForIframe: function(index) {
  if(this.HasIframeOnIos(index)) {
   var scrollElement = this.getTouchScrollerElement(index);
   if(scrollElement) {
    var options = this.GetWindowTouchScrollOptions(index);
    ASPx.TouchUIHelper.InitNativeScrolling(scrollElement, options);
    if(!!this.touchUIScrollers[index]) {
     this.touchUIScrollers[index].Destroy();
     this.touchUIScrollers[index] = null;
    }
   }
  }
 },
 EnsureWindowContentUrl: function(index) {
  var contentUrl = this.GetWindowContentIFrameUrl(index);
  if(contentUrl != "")
   this.SetWindowContentUrlInternal(index, contentUrl);
 },
 CreateWindowContentIFrameElement: function(index, src) {
  var content = this.GetContentContainer(index);
  var iframeParent = content;
  content.innerHTML = "";
  content.style.display = "block";
  var iframe = this.CreateContentIFrameElement(index, src);
  this.RequireIFrameHeightAdjusting(index, iframe);
  iframeParent.appendChild(iframe);
  this.InitIFrame(index);
  return iframe;
 },
 InitIFrame: function(index) {
  var contentIFrameElement = this.GetWindowContentIFrameElement(index);
  if(contentIFrameElement) {
   contentIFrameElement.popupControlName = this.name;
   contentIFrameElement.pcWndIndex = index;
   ASPx.Evt.AttachEventToElement(contentIFrameElement, "load", ASPx.PCIframeLoad);
  }
 },
 OnIFrameLoad: function(index) {
  this.SetIframeLoading(index, false);
 },
 RequireIFrameHeightAdjusting: function(index, iframe) {
  if(this.InternalIsWindowVisible(index))
   this.AdjustIFrameHeight(index, iframe);
  else
   this.PostponeIframeAdjusting(index);
 },
 PostponeIframeAdjusting: function(index) {
  this.SetIframeAdjustingPostponed(index, true);
 },
 EnsureIFrameHeightAdjusted: function(index) {
  if(this.GetIframeAdjustingPostponed(index)) {
   var iframe = this.GetWindowContentIFrameElement(index);
   this.AdjustIFrameHeight(index, iframe);
  }
 },
 AdjustIFrameHeight: function(index, iframe) {
 },
 CreateContentIFrameElement: function(index, src) {
  var iframe = document.createElement("IFRAME");
  iframe.id = this.GetWindowContentIFrameElementId(index);
  iframe.scrolling = "auto";
  iframe.frameBorder = 0;
  iframe.style.width = "100%";
  iframe.style.height = "100%";
  iframe.style.overflow = "auto";
  if(ASPx.Browser.Chrome) iframe.style.webkitBackfaceVisibility = "hidden";
  if(ASPx.Browser.Edge)
   iframe.style["-ms-user-select"] = "text";
  var titleText = this.GetWindowContentIFrameTitle(index);
  if(!!titleText)
   iframe.title = titleText;
  this.SetSrcToIframeElement(index, iframe, src);
  return iframe;
 },
 SetSrcToIframeElement: function(index, iframeElement, src) {
  this.SetIframeLoading(index, true);
  iframeElement.src = src;
  if(ASPx.Browser.Chrome && src.indexOf("#"))
   this.PreventScrollingAfterIframeLoaded(iframeElement);
  iframeElement.DXSrcRaw = src;
 },
 PreventScrollingAfterIframeLoaded: function(iframeElement) {
  var docScrollTop = ASPx.GetDocumentScrollTop();
  var onIframeLoadedHandler = function() {
   window.setTimeout(function() {
    ASPx.SetDocumentScrollTop(docScrollTop);
    ASPx.Evt.DetachEventFromElement(iframeElement, "load", onIframeLoadedHandler);
   }, 0);
  };
  ASPx.Evt.AttachEventToElement(iframeElement, "load", onIframeLoadedHandler);
 },
 GetWindowHeaderTextCell: function(index) {
  return this.GetWindowChild(index, "_PWH" + index + "T");
 },
 GetWindowHeaderTextElement: function(index) {
  var element = this.GetWindowHeaderTextCell(index);
  if(element != null) {
   var link = ASPx.GetNodeByTagName(element, "A", 0);
   return link || element;
  }
  return null;
 },
 GetWindowHeaderLinkElement: function(index) {
  var element = this.GetWindowHeaderElement(index);
  return element ? ASPx.GetNodeByClassName(element, PopupControlCssClasses.LinkCssClassName) : null;
 },
 GetWindowHeaderImageCell: function(index) {
  return this.GetWindowChild(index, "_PWH" + index + "I");
 },
 GetWindowFooterTextCell: function(index) {
  return this.GetWindowChild(index, "_PWF" + index + "T");
 },
 GetWindowFooterTextElement: function(index) {
  var element = this.GetWindowFooterTextCell(index);
  if(element != null) {
   var link = ASPx.GetNodeByTagName(element, "A", 0);
   return link || element;
  }
  return null;
 },
 GetWindowFooterLinkElement: function(index) {
  var element = this.GetWindowFooterElement(index);
  return element ? ASPx.GetNodeByClassName(element, PopupControlCssClasses.LinkCssClassName) : null;
 },
 GetWindowFooterImageCell: function(index) {
  return this.GetWindowChild(index, "_PWF" + index + "I");
 },
 GetWindowHeaderImageUrl: function(index) {
  var element = this.GetWindowHeaderImageCell(index);
  return element ? element.src : "";
 },
 SetWindowHeaderImageUrl: function(index, url) {
  var element = this.GetWindowHeaderImageCell(index);
  if(element != null) {
   element.src = url;
  }
 },
 GetWindowFooterImageUrl: function(index) {
  var element = this.GetWindowFooterImageCell(index);
  return element ? element.src : "";
 },
 SetWindowFooterImageUrl: function(index, url) {
  var element = this.GetWindowFooterImageCell(index);
  if(element != null) {
   element.src = url;
  }
 },
 GetWindowHeaderNavigateUrl: function(index) {
  var link = this.GetWindowHeaderLinkElement(index);
  if(link)
   return link.href || ASPx.Attr.GetAttribute(linkEl, "savedhref");
  return "";
 },
 SetWindowHeaderNavigateUrl: function(index, url) {
  var link = this.GetWindowHeaderLinkElement(index);
  if(link) {
   if(ASPx.Attr.IsExistsAttribute(link, "savedhref"))
    ASPx.Attr.SetAttribute(link, "savedhref", url);
   else if(ASPx.Attr.IsExistsAttribute(link, "href"))
    link.href = url;
  }
 },
 GetWindowFooterNavigateUrl: function(index) {
  var link = this.GetWindowFooterLinkElement(index);
  if(link)
   return link.href || ASPx.Attr.GetAttribute(linkEl, "savedhref");
  return "";
 },
 SetWindowFooterNavigateUrl: function(index, url) {
  var link = this.GetWindowFooterLinkElement(index);
  if(link) {
   if(ASPx.Attr.IsExistsAttribute(link, "savedhref"))
    ASPx.Attr.SetAttribute(link, "savedhref", url);
   else if (ASPx.Attr.IsExistsAttribute(link, "href"))
    link.href = url;
  }
 },
 GetWindowHeaderText: function(index) {
  var element = this.GetWindowHeaderTextElement(index);
  if(element != null) 
    return element.innerHTML;
  return "";
 },
 SetWindowHeaderText: function(index, text) {
  var element = this.GetWindowHeaderTextElement(index);
  if(element != null) {
   element.innerHTML = text;
   this.CorrectHeaderContentElementHeight(index);
   this.CorrectElementVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetWindowHeaderElement(index), true);
  }
 },
 GetWindowFooterText: function(index) {
  var element = this.GetWindowFooterTextElement(index);
  if(element != null) 
   return element.innerHTML;
  return "";
 },
 SetWindowFooterText: function(index, text) {
  var element = this.GetWindowFooterTextElement(index);
  if(element != null) {
   element.innerHTML = text;
   this.CorrectWindowSizeGripPositionLite(index);
  }
 },
 CorrectWindowSizeGripPositionLite: function(index) {
  var sizeGrip = this.GetWindowSizeGripElement(index);
  if(!sizeGrip || sizeGrip.corrected) return;
  sizeGrip.style[this.rtl ? "marginRight" : "marginLeft"] = "-" + sizeGrip.offsetWidth + "px";
  sizeGrip.style.marginTop = "-" + sizeGrip.offsetHeight + "px";
  sizeGrip.corrected = true;
 },
 GetHeaderFooterHeightCore: function(index) {
  var extenders = [
   this.GetWindowHeaderElement(index),
   this.GetWindowFooterElement(index)
  ], height = 0;
  for(var i = 0; i < extenders.length; i++) {
   if(extenders[i])
    height += extenders[i].offsetHeight;
  }
  return height;
 },
 GetHeaderImageUrl: function() {
  return this.GetWindowHeaderImageUrl(-1);
 },
 SetHeaderImageUrl: function(value) {
  this.SetWindowHeaderImageUrl(-1, value);
 },
 GetFooterImageUrl: function() {
  return this.GetWindowFooterImageUrl(-1);
 },
 SetFooterImageUrl: function(value) {
  this.SetWindowFooterImageUrl(-1, value);
 },
 GetHeaderNavigateUrl: function() {
  return this.GetWindowHeaderNavigateUrl(-1);
 },
 SetHeaderNavigateUrl: function(value) {
  this.SetWindowHeaderNavigateUrl(-1, value);
 },
 GetFooterNavigateUrl: function() {
  return this.GetWindowFooterNavigateUrl(-1);
 },
 SetFooterNavigateUrl: function(value) {
  this.SetWindowFooterNavigateUrl(-1, value);
 },
 GetHeaderText: function() {
  return this.GetWindowHeaderText(-1);
 },
 SetHeaderText: function(value) {
  this.SetWindowHeaderText(-1, value);
 },
 GetFooterText: function() {
  return this.GetWindowFooterText(-1);
 },
 SetFooterText: function(value) {
  this.SetWindowFooterText(-1, value);
 },
 GetVisible: function() {
  return this.IsVisible();
 },
 SetVisible: function(visible) {
  if(visible && !this.IsVisible())
   this.Show();
  else if(!visible && this.IsVisible())
   this.Hide();
 },
 GetStateHiddenFieldName: function() {
  return this.uniqueID + "State";
 },
 GetWindowCountCore: function() {
  return 0; 
 },
 IsWindowElementsIDAssigned: function(index) {
  var contentElement = this.GetWindowContentElement(index);
  return ASPx.IsExistsElement(contentElement);
 },
 InitializeDOM: function () {
  var windowElement = this.GetWindowElement(this.GetWindowCountCore() - 1);
  if(windowElement)
   windowElement.dxinit = true;
 },
 IsDOMInitialized: function() {
  var windowElement = this.GetWindowElement(this.GetWindowCountCore() - 1);
  return windowElement && windowElement.dxinit;
 },
 IsDOMDisposed: function() { 
  var windowElement = this.GetWindowElement(this.GetWindowCountCore() - 1);
  return !ASPx.IsExistsElement(windowElement);
 },
 OnDispose: function() {
  ASPxClientControl.prototype.OnDispose.call(this);
  this.ClearPopupElementConnection();
 },
 RegisterInControlTree: function(tree) {
  var mainNode = tree.createNode(null, this);
  if(this.HasDefaultWindow())
   this.RegisterRelatedNodeForWindowElement(tree, -1, mainNode);
  for(var i = 0; i < this.GetWindowCount() ; i++)
   this.RegisterRelatedNodeForWindowElement(tree, i, mainNode);
 },
 RegisterRelatedNodeForWindowElement: function(tree, windowElementIndex, mainNode) {
  var windowElement = this.GetWindowElement(windowElementIndex);
  if(windowElement) {
   var childNode = tree.createNode(windowElement.id, null);
   tree.addRelatedNode(mainNode, childNode);
  }
 },
 CorrectWindowHeaderText: function(index) {
  var headerElement = this.GetWindowHeaderElement(index);
  if(!headerElement || headerElement.corrected) return;
  var leftChildrenWidth = 0, rightChildrenWidth = 0, headerContentElement;
  for(var i = 0; i < headerElement.childNodes.length; i++) {
   var child = headerElement.childNodes[i];
   if(!child.offsetWidth) continue;
   if(ASPx.GetElementFloat(child) === "right")
    rightChildrenWidth += child.offsetWidth + ASPx.GetLeftRightMargins(child);
   else if(ASPx.GetElementFloat(child) === "left")
    leftChildrenWidth += child.offsetWidth + ASPx.GetLeftRightMargins(child);
   else if(!headerContentElement)
    headerContentElement = child;
  }
  if(headerContentElement && (leftChildrenWidth > 0 || rightChildrenWidth > 0)) {
   var headerContentElementStyle = ASPx.GetCurrentStyle(headerContentElement);
   var originalMarginLeft = parseInt(headerContentElementStyle.marginLeft);
   var originalMarginRight = parseInt(headerContentElementStyle.marginRight);
   ASPx.SetStyles(headerContentElement, {
    marginLeft: leftChildrenWidth + originalMarginLeft,
    marginRight: rightChildrenWidth + originalMarginRight
   });
   this.CorrectHeaderContentElementHeight(index);
  }
  headerElement.corrected = true;
 },
 CorrectHeaderContentElementHeight: function(index) {
  var headerElement = this.GetWindowHeaderElement(index),
   headerContentElement = ASPx.GetChildByClassName(headerElement, PopupControlCssClasses.HeaderContentCssClassName);
  if(!headerElement || !headerContentElement) return;
  if(headerContentElement.style.height)
   headerContentElement.style.height = "";
  var contentElementHeight = ASPx.GetClearClientHeight(headerElement) - this.getTopBottomBordersAndPaddingsSummaryValue(headerContentElement),
   lineHeightForTextVerticalAlign = contentElementHeight,
   windowHeaderTextCell = this.GetWindowHeaderTextCell(index);
  if(windowHeaderTextCell)
   lineHeightForTextVerticalAlign -= this.getTopBottomBordersAndPaddingsSummaryValue(windowHeaderTextCell);
  ASPx.SetStyles(headerContentElement, { lineHeight: lineHeightForTextVerticalAlign, height: contentElementHeight }, false);
 },
 CorrectFooterTextElementWidth: function(index) {
  var footerElement = this.GetWindowFooterElement(index);
  var footerContentElement = ASPx.GetChildByClassName(footerElement, PopupControlCssClasses.FooterContentCssClassName);
  var footerTextElement = this.GetWindowFooterTextElement(index);
  var footerImageElement = this.GetWindowFooterImageCell(index);
  if(!footerElement || !footerContentElement || !footerTextElement)
   return;
  var footerTextMaxWidth = "";
  if(footerImageElement) {
   var footerTextMaxWidthCorrection = footerImageElement.offsetWidth + ASPx.GetLeftRightMargins(footerImageElement);
   footerTextMaxWidth = "calc(100% - " + footerTextMaxWidthCorrection + "px)";
  }
  ASPx.SetStyles(footerTextElement, { maxWidth: footerTextMaxWidth }, false);
 },
 OnBeforeDropdownShow: function() {
  var element = this.GetWindowElement(-1);
  if(!ASPx.GetElementDisplay(element)) {
   element.style.visibility = "hidden";
  }
  this.SetWindowDisplay(-1, true);
  if(this.adaptivityEnabled) {
   ASPx.SetElementDisplay(this.GetModalWrapperElement(-1), true);
   this.SetAdaptiveModalMode(-1, this.NeedAdaptiveModalMode());
  }
 },
 SetWindowDisplay: function(index, value) {
  var pcwElement = this.GetWindowElement(index);
  ASPx.SetElementDisplay(pcwElement, value);
 },
 getWindowHorizontalAlign: function(element) {
  return this.popupHorizontalAlign;
 },
 getWindowVerticalAlign: function(element) {
  return this.popupVerticalAlign;
 },
 getWindowHorizontalOffset: function(element) {
  return this.popupHorizontalOffset;
 },
 getWindowVerticalOffset: function(element) {
  return this.popupVerticalOffset;
 },
 GetHorizontalAlign: function() {
  return this.popupHorizontalAlign;
 },
 GetVerticalAlign: function() {
  return this.popupVerticalAlign;
 },
 GetPopupHorizontalOffset: function() {
  return this.popupHorizontalOffset;
 },
 SetPopupHorizontalOffset: function(offset) {
  this.popupHorizontalOffset = offset;
 },
 SetPopupVerticalOffset: function(offset) {
  this.popupVerticalOffset = offset;
 },
 GetPopupVerticalOffset: function() {
  return this.popupVerticalOffset;
 },
 ShowAtElement: function(htmlElement, savePopupElement) {
  this.ShowWindowAtElementByIndex(-1, htmlElement, savePopupElement);
 },
 ShowAtElementByID: function(id) {
  var htmlElement = document.getElementById(id);
  this.ShowAtElement(htmlElement);
 },
 ShowWindowAtElementByIndex: function(index, htmlElement, savePopupElement) {
  var lastIndexBackup = this.GetLastShownPopupElementIndex(index);
  this.ShowWindowByIndex(index, this.AddPopupElementInternal(index, htmlElement));
  if(!savePopupElement)
   this.RemovePopupElementInternal(index, htmlElement);
  this.SetLastShownPopupElementIndex(index, lastIndexBackup);
 },
 ShowWindowByIndex: function(index, popupElementIndex) {
  if(!this.isInitialized)
   return;
  if(popupElementIndex === undefined)
   popupElementIndex = this.GetLastShownPopupElementIndex(index);
  this.DoShowWindowCore(index, ASPx.InvalidPosition, ASPx.InvalidPosition, popupElementIndex, false, true);
 },
 DoShowWindowCore: function(index, x, y, popupElementIndex, closeOtherWindows, allowChangeZIndex, evt, closeOtherReason) {
 },
 DoShowWindow: function(index, popupElementIndex, evt) {
  if(!this.InternalIsWindowVisible(index)) {
   var x = ASPx.Evt.GetEventX(evt);
   var y = ASPx.Evt.GetEventY(evt);
   this.DoShowWindowCore(index, x, y, popupElementIndex, true, true, evt, ASPxClientPopupControlCloseReason.OuterMouseClick);
  }
 },
 SetWindowPos: function(index, element, x, y) {
  ASPx.SetStyles(element, { left: x, top: y });
  this.DoShowWindowIFrame(index, x, y, ASPx.InvalidDimension, ASPx.InvalidDimension);
  this.SetIsDragged(index, true);
  this.SetWindowLeft(index, ASPx.GetAbsoluteX(element));
  this.SetWindowTop(index, ASPx.GetAbsoluteY(element));
  this.UpdateWindowsStateCookie();
 },
 CorrectPopupPositionForClientWindow: function(element, popupPosition, isX) {
  if(element.isPopupPositionCorrectionOn && this.isPopupFullCorrectionOn || this.forceAdjustPositionToClientScreen) {
   popupPosition.position = ASPx.PopupUtils.AdjustPositionToClientScreen(element, popupPosition.position, this.rtl, isX);
  }
  return popupPosition;
 },
 GetClientPopupPos: function(element, popupElement, pos, isX, isDragged) {
  var index = this.GetWindowIndex(element);
  var popupPosition = null;
  if(this.GetIsMaximizedOnWebKitTouch(index))
   return new ASPx.PopupPosition(ASPx.PrepareClientPosForElement(0, element, isX), false);
  if(isDragged)
   popupPosition = new ASPx.PopupPosition(!this.IsValidPosition(pos) ? this.GetPosition(index, isX) : pos, false);
  else
   popupPosition = isX ? this.GetClientPopupPosX(element, popupElement, pos) : this.GetClientPopupPosY(element, popupElement, pos);
  popupPosition.position = ASPx.PrepareClientPosForElement(popupPosition.position, element, isX);
  if(ASPx.Browser.Firefox && ASPx.Browser.Version < 3 && this.GetWindowModalElement(index))
   popupPosition.position -= isX ? ASPx.GetDocumentScrollLeft() : ASPx.GetDocumentScrollTop();
  return popupPosition;
 },
 GetClientPopupPosX: function(element, popupElement, x) {
  var mainElement = this.GetWindowMainCell(element);
  var popupPosition = ASPx.PopupUtils.GetPopupAbsoluteX(mainElement, popupElement, this.getWindowHorizontalAlign(element), this.getWindowHorizontalOffset(element),
   x, this.GetWindowLeft(this.GetWindowIndex(element)), this.rtl, this.isPopupFullCorrectionOn);
  return this.CorrectPopupPositionForClientWindow(element, popupPosition, true);
 },
 GetClientPopupPosY: function(element, popupElement, y) {
  var mainElement = this.GetWindowMainCell(element);
  var popupPosition = ASPx.PopupUtils.GetPopupAbsoluteY(mainElement, popupElement, this.getWindowVerticalAlign(element), this.getWindowVerticalOffset(element),
   y, this.GetWindowTop(this.GetWindowIndex(element)), this.isPopupFullCorrectionOn, this.usedInDropDown, this.usedInDropDown);
  return this.usedInDropDown ? popupPosition : this.CorrectPopupPositionForClientWindow(element, popupPosition, false);
 },
 UpdateWindowPositionInternal: function(index, popupElement) {
  var positionUpdated = false,
   element = this.GetWindowElement(index);
  if(this.InternalIsWindowVisible(index) && element != null) {
   var horizontalPopupPosition;
   if(this.popupHorizontalAlign === ASPx.PopupUtils.WindowCenterAlignIndicator && window.innerWidth <= element.offsetWidth) {
    var scrollDiff = aspxGetPopupControlCollection().GetDocScrollDifference(),
     scrollInProgress = scrollDiff.horizontal !== 0 || scrollDiff.vertical !== 0;
    horizontalPopupPosition = scrollInProgress ? ASPx.PxToInt(element.style.left) : this.GetClientPopupPos(element, popupElement, ASPx.InvalidPosition, true, false);
   } else
    horizontalPopupPosition = this.GetClientPopupPos(element, popupElement, ASPx.InvalidPosition, true, false);
   var verticalPopupPosition = this.GetClientPopupPos(element, popupElement, ASPx.InvalidPosition, false, false);
   this.SetWindowPos(index, element, horizontalPopupPosition.position, verticalPopupPosition.position);
   positionUpdated = true;
  }
  return positionUpdated;
 },
 UpdatePositionAtElement: function(popupElement) {
  this.UpdateWindowPositionAtElement(null, popupElement);
 },
 UpdateWindowPositionAtElement: function(window, popupElement) {
  var index = (window != null) ? window.index : -1;
  this.UpdateWindowPositionInternal(index, popupElement);
 },
 TryAutoUpdatePosition: function(index) {
  if(this.GetAutoUpdatePosition(index))
   this.UpdateWindowPositionInternal(index, this.GetPopupElement(index, this.GetLastShownPopupElementIndex(index)));
 },
 GetLastShownPopupElementIndex: function(windowIndex) {
  var info = this.GetLastUsedPopupElementInfo(windowIndex);
  return ASPx.GetDefinedValue(info.shownPEIndex, 0);
 },
 SetLastShownPopupElementIndex: function(windowIndex, popupElementIndex) {
  var info = this.GetLastUsedPopupElementInfo(windowIndex);
  info.shownPEIndex = popupElementIndex;
 },
 GetLastUsedPopupElementInfo: function(index) {
  if(0 <= index && index < this.GetWindowCountCore())
   return this.windowsLastUsedPopupElementInfoList[index];
  return this.defaultLastUsedPopupElementInfo;
 },
 GetPopupElement: function(index, popupElementIndex) {
  var popupElement = this.GetPopupElementList(index)[popupElementIndex];
  return popupElement ? popupElement : null;
 },
 GetPopupElementList: function(index) {
  if(0 <= index && index < this.GetWindowCountCore())
   return this.windowsPopupElementList[index];
  return this.defaultWindowPopupElementList;
 },
 PopulatePopupElementsByIds: function(index) {
  var ids = this.GetPopupElementIDList(index);
  for(var i = 0; i < ids.length; i++) {
   var popupElement = ASPx.PopupUtils.FindPopupElementById(ids[i]);
   if(popupElement)
    this.AddWindowPopupElement(index, popupElement);
  }
 },
 PopulatePopupElements: function(index) {
  this.PopulatePopupElementsByIds(index);
 },
 SetPopupElementIDByIndex: function(index, popupElementId) {
  this.RemoveWindowAllPopupElements(index);
  this.SetPopupElementIDs(index, popupElementId.split(';'));
  if(aspxGetPopupControlCollection().IsDisappearTimerActive()) {
   aspxGetPopupControlCollection().ClearDisappearTimer();
   this.Hide(index);
  }
  this.PopulatePopupElements(index);
 },
 RefreshPopupElementConnection: function() {
  this.ClearPopupElementConnection();
  var index = this.HasDefaultWindow() ? -1 : 0;
  for(; index < this.GetWindowCount(); index++)
   this.PopulatePopupElements(index);
 },
 ClearPopupElementConnection: function() {
  var index = this.HasDefaultWindow() ? -1 : 0;
  for(; index < this.GetWindowCount(); index++)
   this.RemoveWindowAllPopupElements(index);
 },
 GetPopupElementIDList: function(index) {
  if(0 <= index && index < this.GetWindowCountCore())
   return this.windowsPopupElementIDList[index];
  return this.defaultWindowPopupElementIDList;
 },
 SetPopupElementIDs: function(index, ids) {
  if(0 <= index && index < this.GetWindowCountCore())
   this.windowsPopupElementIDList[index] = ids;
  this.defaultWindowPopupElementIDList = ids;
 },
 AddPopupElementInternal: function(index, element) {
  var popupElements = this.GetPopupElementList(index);
  for(var i = 0; i < popupElements.length; i++) {
   if(!popupElements[i]) {
    popupElements[i] = element;
    return i;
   }
  }
  popupElements.push(element);
  return popupElements.length - 1;
 },
 RemovePopupElementInternal: function(index, element) {
  var popupElements = this.GetPopupElementList(index);
  for(var i = 0; i < popupElements.length; i++) {
   if(popupElements[i] == element) {
    popupElements[i] = null;
    return;
   }
  }
 },
 AddPopupElement: function(popupElement) {
  this.AddWindowPopupElement(-1, popupElement);
 },
 AddWindowPopupElement: function(index, popupElement) {
  var popupElementIndex = this.AddPopupElementInternal(index, popupElement);
  this.SetPopupElementReference(index, popupElement, popupElementIndex, true);
 },
 RemovePopupElement: function(popupElement) {
  this.RemoveWindowPopupElement(-1, popupElement);
 },
 RemoveWindowPopupElement: function(index, popupElement) {
  this.RemovePopupElementInternal(index, popupElement);
  this.SetPopupElementReference(index, popupElement, null, false);
 },
 SetPopupElementReference: function(index, popupElement, popupElementIndex, attach) {
  if(!ASPx.IsExistsElement(popupElement)) return;
  var setReferenceFunction = this.getAttachReferenceFunction(attach);
  var setContextMenuReferenceFunction = attach ? ASPx.Evt.AttachContextMenuToElement : ASPx.Evt.DetachContextMenuFromElement;
  var windowPopupAction = this.GetWindowPopupAction(index);
  if(windowPopupAction == "LeftMouseClick")
   setReferenceFunction(popupElement, "mouseup", aspxPEMEvent);
  else if(windowPopupAction == "RightMouseClick")
   setContextMenuReferenceFunction(popupElement, aspxPEMEvent);
  else if(windowPopupAction == "MouseOver") {
   var windowElement = this.GetWindowElement(index);
   setReferenceFunction(popupElement, "mouseover", ASPx.PopupUtils.OverControl.OnMouseOver);
   setReferenceFunction(windowElement, "mouseover", aspxPWEMOver);
   if(attach)
    this.SetMSTouchMouseOverReference(popupElement, windowElement, this.name, index, this.appearAfter);
  }
  if(windowPopupAction == "LeftMouseClick" || windowPopupAction == "RightMouseClick") {
   setReferenceFunction(popupElement, "mousedown", aspxPEMEvent);
  }
  if(attach) {
   popupElement.DXPopupElementControl = this;
   popupElement.DXPopupWindowIndex = index;
   popupElement.DXPopupElementIndex = popupElementIndex;
  } else
   popupElement.DXPopupElementControl = popupElement.DXPopupWindowIndex = popupElement.DXPopupElementIndex = undefined;
 },
 getAttachReferenceFunction: function(attach) {
  return attach ? ASPx.Evt.AttachEventToElement : ASPx.Evt.DetachEventFromElement;
 },
 SetMSTouchMouseOverReference: function(popupElement, windowElement, popupName, index, appearAfter) {
  if(!ASPx.TouchUIHelper.pointerEnabled) return;
  popupElement.dxMsTouchGesture = popupElement.dxMsTouchGesture ||
   ASPx.TouchUIHelper.msTouchCreateGesturesWrapper(popupElement, function(evt) {
    window.setTimeout(function() {
     aspxGetPopupControlCollection().SetAppearTimer(popupName, index, popupElement.DXPopupElementIndex, appearAfter, evt);
    }, 0);
   });
  windowElement.dxMsTouchGesture = windowElement.dxMsTouchGesture || ASPx.TouchUIHelper.msTouchCreateGesturesWrapper(windowElement, function(evt) {
   window.setTimeout(function() {
    aspxGetPopupControlCollection().ClearDisappearTimer();
   }, 0);
  });
 },
 GetLastOverPopupElementIndex: function(windowIndex) {
  var info = this.GetLastUsedPopupElementInfo(windowIndex);
  return ASPx.GetDefinedValue(info.overPEIndex, -1);
 },
 SetLastOverPopupElementIndex: function(windowIndex, popupElementIndex) {
  var info = this.GetLastUsedPopupElementInfo(windowIndex);
  info.overPEIndex = popupElementIndex;
 },
 OnPopupElementMouseOver: function(evt, popupElement) {
  if(popupElement != null) {
   var index = popupElement.DXPopupWindowIndex;
   var isVisible = this.InternalIsWindowVisible(index);
   var popupElementIndex = popupElement.DXPopupElementIndex;
   if(this.GetLastOverPopupElementIndex(index) != popupElementIndex) {
    if(aspxGetPopupControlCollection().IsAppearTimerActive())
     aspxGetPopupControlCollection().ClearAppearTimer();
    if(aspxGetPopupControlCollection().IsDisappearTimerActive())
     aspxGetPopupControlCollection().ClearDisappearTimer();
    if(isVisible) {
     this.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.MouseOut);
     isVisible = false;
    }
   }
   if(!isVisible) {
    aspxGetPopupControlCollection().SetAppearTimer(this.name, index, popupElement.DXPopupElementIndex, this.appearAfter, evt);
    aspxGetPopupControlCollection().InitOverObject(this, index, evt);
   }
   this.SetLastOverPopupElementIndex(index, popupElementIndex);
  }
 },
 OnPopupElementMouseOut: function(evt, popupElement) {
 },
 RemoveAllPopupElements: function() {
  this.RemoveWindowAllPopupElements(-1);
 },
 RemoveWindowAllPopupElements: function(index) {
  var popupElements = this.GetPopupElementList(index);
  for(var i = 0; i < popupElements.length; i++)
   this.RemoveWindowPopupElement(index, popupElements[i]);
 },
 GetWindowCurrentPopupElementByIndex: function(index) {
  var popupElement = this.GetPopupElement(index, this.GetLastShownPopupElementIndex(index));
  if(popupElement && popupElement.DXPopupElementControl)
   return popupElement;
  return null;
 },
 GetWindowCurrentPopupElementIndexByWindowIndex: function(windowIndex) {
  var popupElement = this.GetWindowCurrentPopupElementByIndex(windowIndex);
  return popupElement ? popupElement.DXPopupElementIndex : -1;
 },
 GetIsMaximizedOnWebKitTouch: function(index) {
  return false;
 },
 ProcessAccessibleElementOnHide: function() {
  if(this.accessibilityCompliant) {
   var focusElement = this.accessibleFocusElement ? this.accessibleFocusElement : this.GetCurrentPopupElement();
   ASPx.AccessibilityUtils.SetFocusAccessibleCore(focusElement);
   this.accessibleFocusElement = null;
  }
 },
 OnControlsInitialized: function() {
  this.InitializeAccessibleNavigationCore();
  setTimeout(function() {
   ASPx.GetControlCollection().ControlsInitialized.RemoveHandler(this.OnControlsInitialized, this);
  }.aspxBind(this), 0);
 },
 InitializeAccessibleNavigation: function() {
  this.Shown.AddHandler(this.InitializeAccessibleNavigationCore.aspxBind(this));
 },
 InitializeAccessibleNavigationCore: function() {
  this.resetFocusableElements();
  var focusableElement = this.getFirstFocusableElement();
  if(focusableElement) {
   var currentWindowContentCell = this.GetWindowContentElement(-1);
   var contentFirstActionElement = ASPx.FindFirstChildActionElement(currentWindowContentCell);
   if(contentFirstActionElement && contentFirstActionElement !== focusableElement)
    focusableElement = contentFirstActionElement;
   if(!this.preventAccessibilityFocus)
    ASPx.AccessibilityUtils.SetFocusAccessible(focusableElement);
   this.SetLoopingFocusHandlers();
  }
 },
 resetFocusableElements: function() {
  if(this.firstFocusableElement)
   ASPx.Evt.DetachEventFromElement(this.firstFocusableElement, "keydown", this.focusLastElementHandler);
  if(this.lastFocusableElement)
   ASPx.Evt.DetachEventFromElement(this.lastFocusableElement, "keydown", this.focusFirstElementHandler);
  this.firstFocusableElement = null;
  this.lastFocusableElement = null;
 },
 getFirstFocusableElement: function() {
  if(!this.firstFocusableElement)
   this.firstFocusableElement = ASPx.FindFirstChildActionElement(this.GetCurrentWindowElement());
  return this.firstFocusableElement;
 },
 getLastFocusableElement: function() {
  if(!this.lastFocusableElement)
   this.lastFocusableElement = ASPx.FindLastChildActionElement(this.GetCurrentWindowElement());
  return this.lastFocusableElement;
 },
 SetLoopingFocusHandlers: function() {
  ASPx.Evt.AttachEventToElement(this.getFirstFocusableElement(), "keydown", this.focusLastElementHandler);
  ASPx.Evt.AttachEventToElement(this.getLastFocusableElement(), "keydown", this.focusFirstElementHandler);
 },
 loopFocusHandler: function(evt, isLastFocusableElement) {
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  if(keyCode !== ASPx.Key.Tab)
   return;
  var targetElement = isLastFocusableElement ? this.getLastFocusableElement() : this.getFirstFocusableElement();
  if(ASPx.Evt.GetEventSource(evt) !== targetElement)
   return;
  var elementToFocus = null;
  if(!isLastFocusableElement && evt.shiftKey)
   elementToFocus = this.getLastFocusableElement();
  else if(isLastFocusableElement && !evt.shiftKey)
   elementToFocus = this.getFirstFocusableElement();
  if(elementToFocus) {
   ASPx.AccessibilityUtils.SetFocusAccessible(elementToFocus);
   ASPx.Evt.PreventEventAndBubble(evt);
  }
 },
 getLeftRightBordersAndPaddingsSummaryValue: function(element, currentStyle) {
  return ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element, currentStyle);
 },
 getTopBottomBordersAndPaddingsSummaryValue: function(element, currentStyle) {
  return ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element, currentStyle);
 },
 AdjustModalElementBounds: function(element) {
 },
 RefreshDimensionsAfterCreateIframe: function(index) {
 },
 UpdatePositionAfterCallback: function(windowIndex) {
 }
});
ASPxClientPopupControlBase.AnimationType = {
 Fade: "fade",
 Slide: "slide",
 Auto: "auto",
 None: "none"
};
var ASPxClientPopupControl = ASPx.CreateClass(ASPxClientPopupControlBase, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.popupActionArray = [];
  this.windowsPopupElementIDList = [];
  this.windowsPopupElementList = [];
  this.windowsLastUsedPopupElementInfoList = [];
  this.windowsIsPopupedList = [];
  this.windowsPopupReasonMouseEventList = [];
  this.defaultPopupReasonMouseEvent = null;
  this.modal = false;
  this.modalArray = [];
  this.isDraggedArray = [];
  this.closeActionArray = [];
  this.showOnPageLoadArray = [];
  this.windows = [];
  this.windowCount = 0;
  this.closeOnEscapeArray = [];
  this.leftArray = [];
  this.contentUrlArray = [];
  this.contentUrlIFrameTitleArray = [];
  this.iframeLoadingArray = [];
  this.iframeAdjustingPostponedArray = [];
  this.isResizedArray = [];
  this.zIndexArray = [];
  this.topArray = [];
  this.shownArray = [];
  this.heightArray = [];
  this.widthArray = [];
  this.widthFromServer = false;
  this.widthFromServerArray = [];
  this.minHeightArray = [];
  this.minWidthArray = [];
  this.maxHeightArray = [];
  this.maxWidthArray = [];
  this.hideBodyScrollWhenModal = true;
  this.hideBodyScrollWhenModalArray = [];
  this.hideBodyScrollWhenMaximized = true;
  this.canScrollViewPort = false;
  this.canScrollViewPortArray = [];
  this.autoUpdatePositionArray = [];
  this.cachedSizeArray = [];
  this.enableContentScrollingArray = [];
  this.contentOverflowXArray = [];
  this.contentOverflowYArray = [];
  this.isPinned = false;
  this.isPinnedArray = [];
  this.pinX = 0;
  this.pinXArray = [];
  this.pinY = 0;
  this.pinYArray = [];
  this.lockScroll = 0;
  this.isCollapsed = false;
  this.isCollapsedArray = [];
  this.isCollapsedInit = false;
  this.isCollapsedInitArray = [];
  this.collapseExecutingLockCount = 0;
  this.isMaximized = false;
  this.isMaximizedArray = [];
  this.isMaximizedInit = false;
  this.isMaximizedInitArray = [];
  this.maximizationExecutingLockCount = 0;
  this.restoredWindowValues = {};
  this.restoredWindowValuesArray = [];
  this.browserResizingForMaxWindowLockCount = 0;
  this.updateRestoredWindowSizeLockCount = 0;
  this.touchUIScrollers = {};
  this.adaptivityEnabled = false;
  this.DefaultModalMaxWidth = 500;
  this.DefaultModalMinWidth = 0;
  this.stretchVertically = false;
  this.stretchVerticallyArray = [];
  this.fixedHeader = true;
  this.fixedHeaderArray = [];
  this.fixedFooter = true;
  this.fixedFooterArray = [];
  this.modalMinHeight = null;
  this.modalMinHeightArray = [];
  this.modalMinWidth = null;
  this.modalMinWidthArray = [];
  this.modalMaxHeight = null;
  this.modalMaxHeightArray = [];
  this.modalMaxWidth = null;
  this.modalMaxWidthArray = [];
  this.modalVerticalAlign = ModalAlign.WindowTop;
  this.modalHorizontalAlign = ModalAlign.WindowCenter;
  this.adaptiveModalMode = false;
  this.adaptiveModalModeArray = [];
  this.switchAtWindowInnerWidth = ASPx.MaxMobileWindowWidth;
  this.PinnedChanged = new ASPxClientEvent();
  this.AdaptiveModeChanged = new ASPxClientEvent();
 },
 SetData: function(data){
  if(data.windows)
   this.CreateWindows(data.windows);
 },
 InlineInitialize: function() {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  this.InitializeArrayCores();
 },
 Initialize: function() {
  ASPxClientPopupControlBase.prototype.Initialize.call(this);
  aspxGetPopupControlCollection().EnsureSaveScrollState();
  if(this.HasDefaultWindow())
   this.InitializeWindow(-1);
  for(var i = 0; i < this.GetWindowCount() ; i++)
   this.InitializeWindow(i);
  this.InitializeScrollbars();
 },
 InitializeEnableContentScrolling: function() {
  for(var windowIndex = 0; windowIndex < this.GetWindowCount() ; windowIndex++) {
   var contentOverflowX = this.GetWindowOverflowX(windowIndex);
   var contentOverflowY = this.GetWindowOverflowY(windowIndex);
   this.enableContentScrollingArray.push(contentOverflowX != "None" || contentOverflowY != "None");
  }
  ASPxClientPopupControlBase.prototype.InitializeEnableContentScrolling.call(this);
 },
 InitializeScrollbars: function() {
  if(!ASPx.Browser.WebKitTouchUI && !ASPx.Browser.MSTouchUI && (!ASPx.Browser.WindowsPhonePlatform || !ASPx.Browser.IE))
   return;
  this.ForEachWindow(function(windowIndex) {
   if(this.GetEnableContentScrolling(windowIndex)) {
    var scrollElement = this.getTouchScrollerElement(windowIndex);
    if(scrollElement) {
     if(ASPx.Browser.MSTouchUI)
      scrollElement.style.touchAction = "auto";
     else {
      var options = this.GetWindowTouchScrollOptions(windowIndex);
      if(!this.HasIframeOnIos(windowIndex))
       this.touchUIScrollers[windowIndex] = ASPx.TouchUIHelper.MakeScrollable(scrollElement, options);
     }
    }
   }
  }.aspxBind(this));
 },
 GetWindowTouchScrollOptions: function (index) {
  var contentOverflowX = this.GetWindowOverflowX(index),
   contentOverflowY = this.GetWindowOverflowY(index);
  return {
   showHorizontalScrollbar: contentOverflowX === "Auto" || contentOverflowX === "Scroll",
   showVerticalScrollbar: contentOverflowY === "Auto" || contentOverflowY === "Scroll"
  };
 },
 ForEachWindow: function(callback) {
  var indices = [];
  if(this.HasDefaultWindow())
   indices.push(-1);
  else {
   for(var i = 0; i < this.GetWindowCount(); i++)
    indices.push(i);
  }
  ASPx.Data.ForEach(indices, callback);
 },
 GetMainElementId: function() {
  return null;
 },
 preventParentOverlowOnIos: function(index) {
  if(!ASPx.Browser.MacOSMobilePlatform) return;
  var parent = this.getParentPopupControl(index);
  if(parent) 
   parent.popupControl.changeContentOverflow(parent.windowIndex);
 },
 restoreParentOverflowOnIos: function(index) {
  if(!ASPx.Browser.MacOSMobilePlatform) return;
  var parent = this.getParentPopupControl(index);
  if(parent) 
   parent.popupControl.restoreContentOverflow(parent.windowIndex);
 },
 changeContentOverflow: function(index) {
  var scrollerElement = this.getTouchScrollerElement(index);
  if(!scrollerElement) return;
  ASPx.Attr.ChangeStyleAttribute(scrollerElement, "overflow", "visible");
  ASPx.Attr.ChangeStyleAttribute(scrollerElement, "overflowX", "visible");
  ASPx.Attr.ChangeStyleAttribute(scrollerElement, "overflowY", "visible");
 },
 restoreContentOverflow: function(index) {
  var scrollerElement = this.getTouchScrollerElement(index);
  if(!scrollerElement) return;
  ASPx.Attr.RestoreStyleAttribute(scrollerElement, "overflow");
  ASPx.Attr.RestoreStyleAttribute(scrollerElement, "overflowX");
  ASPx.Attr.RestoreStyleAttribute(scrollerElement, "overflowY");
 },
 UpdateScrollbar: function(index) {
  var touchUIScroller = this.touchUIScrollers[index];
  if(!touchUIScroller)
   return;
  var scrollElement = this.GetContentContainer(index);
  if(scrollElement)
   touchUIScroller.ChangeElement(scrollElement);
 },
 InitializeArrayCores: function() {
  if(this.GetWindowCountCore() > 0) {
   this.InitializeWindowPopupElementList();
   this.InitializeWindowPopupElementIDList();
   this.InitializeWindowLastUsedPopupElementInfoList();
   this.InitializeArray(this.shownArray);
   this.InitializeArray(this.windowsPopupReasonMouseEventList, null);
   this.InitializeArray(this.windowsIsPopupedList, false);
   this.InitializeArray(this.contentUrlArray, "");
   this.InitializeArray(this.contentUrlIFrameTitleArray, "");
   this.InitializeArray(this.popupActionArray, this.popupAction);
   this.InitializeArray(this.closeActionArray, this.closeAction);
   this.InitializeArray(this.showOnPageLoadArray, false);
   this.InitializeArray(this.isDraggedArray, false);
   this.InitializeArray(this.isPinnedArray, false);
   this.InitializeArray(this.isCollapsedArray, false);
   this.InitializeArray(this.isCollapsedInitArray, false);
   this.InitializeArray(this.isMaximizedArray, false);
   this.InitializeArray(this.isMaximizedInitArray, false);
   this.InitializeArray(this.restoredWindowValuesArray, {});
   this.InitializeArray(this.iframeAdjustingPostponedArray, {});
   this.InitializeArray(this.isResizedArray, false);
   this.InitializeArray(this.zIndexArray, -1);
   this.InitializeArray(this.leftArray, 0);
   this.InitializeArray(this.topArray, 0);
   this.InitializeArray(this.widthArray, constants.DEFAULT_WINDOW_WIDTH);
   this.InitializeArray(this.heightArray, constants.DEFAULT_WINDOW_HEIGHT);
   this.InitializeArray(this.widthFromServerArray, false);
   this.InitializeArray(this.pinXArray, 0);
   this.InitializeArray(this.pinYArray, 0);
   this.InitializeArray(this.minWidthArray, null);
   this.InitializeArray(this.minHeightArray, null);
   this.InitializeArray(this.maxWidthArray, null);
   this.InitializeArray(this.maxHeightArray, null);
   this.InitializeArray(this.cachedSizeArray, null);
   this.InitializeArray(this.iframeLoadingArray, false);
   this.InitializeArray(this.autoUpdatePositionArray, false);
   this.InitializeArray(this.hideBodyScrollWhenModalArray, true);
   this.InitializeArray(this.canScrollViewPortArray, false);
   this.InitializeArray(this.closeOnEscapeArray, this.closeOnEscape);
   this.InitializeArray(this.modalArray, false);
   this.InitializeArray(this.adaptiveModalModeArray, false);
   this.InitializeArray(this.fixedHeaderArray, true);
   this.InitializeArray(this.fixedFooterArray, true);
   this.InitializeArray(this.modalMinWidthArray, null);
   this.InitializeArray(this.modalMinHeightArray, null);
   this.InitializeArray(this.modalMaxWidthArray, null);
   this.InitializeArray(this.modalMaxHeightArray, null);
   this.InitializeArray(this.stretchVerticallyArray, false);
  }
 },
 InitializeArray: function(array, defaultValue) {
  if(array.length == 0) {
   for(var i = 0; i < this.GetWindowCountCore() ; i++)
    array[i] = defaultValue;
  }
 },
 InitializeWindowPopupElementIDList: function() {
  for(var i = 0; i < this.GetWindowCountCore() ; i++) {
   if(!this.windowsPopupElementIDList[i])
    this.windowsPopupElementIDList[i] = [];
  }
 },
 InitializeWindowPopupElementList: function() {
  for(var i = 0; i < this.GetWindowCountCore() ; i++) {
   if(!this.windowsPopupElementList[i])
    this.windowsPopupElementList[i] = [];
  }
 },
 InitializeWindowLastUsedPopupElementInfoList: function() {
  for(var i = 0; i < this.GetWindowCountCore() ; i++) {
   if(!this.windowsLastUsedPopupElementInfoList[i])
    this.windowsLastUsedPopupElementInfoList[i] = {};
  }
 },
 AllowMouseDown: function(evt, index) {
  return ASPxClientPopupControlBase.prototype.AllowMouseDown.call(this, evt, index) &&
   !this.PreventHeaderButtonMouseDownBubbling(evt, this.GetWindowPinButton(index)) &&
   !this.PreventHeaderButtonMouseDownBubbling(evt, this.GetWindowCollapseButton(index)) &&
   !this.PreventHeaderButtonMouseDownBubbling(evt, this.GetWindowMaximizeButton(index));
 },
 AssignHeaderButtonsEvents: function(index) {
  ASPxClientPopupControlBase.prototype.AssignHeaderButtonsEvents.call(this, index);
  this.AttachClickToHeaderButton(index, this.GetWindowPinButton(index), "ASPx.PWPBClick");
  this.AttachClickToHeaderButton(index, this.GetWindowCollapseButton(index), "ASPx.PWMNBClick");
  this.AttachClickToHeaderButton(index, this.GetWindowMaximizeButton(index), "ASPx.PWMXBClick");
 },
 InitializeWindow: function(index) {
  ASPxClientPopupControlBase.prototype.InitializeWindow.call(this, index);
  if(this.adaptivityEnabled) {
   ASPx.Evt.AttachEventToElement(this.GetModalWrapperElement(index), "scroll", function(e) { this.OnModalWrapperScroll(e, index); }.aspxBind(this));
   if(ASPx.Browser.WebKitTouchUI) {
    ASPx.Evt.AttachEventToElement(this.GetModalWrapperElement(index), "touchstart", function(e) { this.OnModalWrapperTouchStart(e); }.aspxBind(this));
    ASPx.Evt.AttachEventToElement(this.GetModalWrapperElement(index), "touchmove", function(e) { this.OnModalWrapperTouchMove(e, index); }.aspxBind(this));
   }
  } else {
   var modalElement = this.GetWindowModalElement(index);
   if(modalElement)
    ASPx.Evt.AttachEventToElement(modalElement, "mousedown", aspxPWMEMDown);
  }
 },
 BrowserWindowResizeSubscriber: function() {
  return true;
 },
 OnBrowserWindowResize: function(e) {
  window.setTimeout(this.SetPopupMaximizedPositionOnBrowserResize.aspxBind(this), 0);
  this.ForEachWindow(this.updateContentScrollIfNeeded.aspxBind(this));
 },
 SetPopupMaximizedPositionOnBrowserResize: function() {
  this.ForEachWindow(this.SetMaximizedPositionOnBrowserResize.aspxBind(this));
 },
 UpdateResizeCursor: function(index, element, verticalDirection, horizontalDirection) {
  if(this.GetAdaptiveModalMode(index))
   this.HideTemporaryCursor(element);
  else
   ASPxClientPopupControlBase.prototype.UpdateResizeCursor.call(this, index, element, verticalDirection, horizontalDirection);
 },
 SetMaximizedPositionOnBrowserResize: function(index) {
  var element = this.GetWindowElement(index);
  if(element && this.GetIsMaximized(index) && this.InternalIsWindowVisible(index)) {
   var left = this.GetMaximizedPosition(element, true);
   var top = this.GetMaximizedPosition(element, false);
   this.SetWindowPos(index, element, left, top);
  }
 },
 InitCollapsedWindows: function(index) {
  if((this.isCollapsedInit && index == -1) || (index >= 0 && index < this.isCollapsedInitArray.length && this.isCollapsedInitArray[index])) {
   if(this.InternalIsWindowVisible(index)) {
    this.DoCollapse(index, true);
    if(index == -1)
     this.isCollapsedInit = false;
    else
     this.isCollapsedInitArray[index] = false;
   }
  }
 },
 InitMaximizedWindows: function(index) {
  if(this.GetIsMaximizedInit(index) && this.InternalIsWindowVisible(index)) {
   this.DoMaximize(index, true);
   this.SetIsMaximizedInit(index, false);
  }
 },
 InitPinnedWindows: function(index) {
  if((this.isPinned && index == -1) || (index >= 0 && index < this.isPinnedArray.length && this.isPinnedArray[index]))
   this.HoldPosition(index, true);
 },
 AfterInitializeWindow: function(index) {
  if(this.contentOverflowX !== "None" && !this.GetWindowWidthFromServer(index))
   this.SetWindowWidth(index, 0);
  ASPxClientPopupControlBase.prototype.AfterInitializeWindow.call(this, index);
  this.InitPinnedWindows(index);
  this.InitMaximizedWindows(index);
  this.InitCollapsedWindows(index);
 },
 OnDragStop: function(index) {
  ASPxClientPopupControlBase.prototype.OnDragStop.call(this, index);
  if(this.adaptivityEnabled)
   ASPxClientPopupControl.WindowResizeHelper.Initialize(this.GetWindowElement(index));
  else
   this.updateContentScrollIfNeeded(index);
 },
 GetPropertyValue: function(index, propName) {
  if(0 <= index && index < this.GetWindowCountCore())
   return this[propName + "Array"][index];
  return ASPxClientPopupControlBase.prototype.GetPropertyValue.call(this, index, propName);
 },
 SetPropertyValue: function(index, propName, value) {
  if(0 <= index && index < this.GetWindowCountCore())
   this[propName + "Array"][index] = value;
  else
   ASPxClientPopupControlBase.prototype.SetPropertyValue.call(this, index, propName, value);
 },
 GetAdaptiveModalMode: function(index) {
  return this.GetPropertyValue(index, "adaptiveModalMode");
 },
 GetAutoUpdatePosition: function(index) {
  return this.GetPropertyValue(index, "autoUpdatePosition") && !this.GetAdaptiveModalMode(index);
 },
 SetAdaptiveModalMode: function(index, enabled) {
  ASPx.ToggleClassNameToElement(this.GetModalWrapperElement(index), this.GetModalSystemCssClass(), enabled);
  this.SetPropertyValue(index, "adaptiveModalMode", enabled);
 },
 GetIsPinned: function(index) {
  return this.GetPropertyValue(index, "isPinned");
 },
 SetIsPinned: function(index, value) {
  this.SetPropertyValue(index, "isPinned", value);
 },
 GetPinPosX: function(index) {
  return this.GetPropertyValue(index, "pinX");
 },
 SetPinPosX: function(index, pinX) {
  this.SetPropertyValue(index, "pinX", pinX);
 },
 GetPinPosY: function(index) {
  return this.GetPropertyValue(index, "pinY");
 },
 SetPinPosY: function(index, pinY) {
  this.SetPropertyValue(index, "pinY", pinY);
 },
 GetIsCollapsed: function(index) {
  return this.GetPropertyValue(index, "isCollapsed");
 },
 SetIsCollapsed: function(index, value) {
  this.SetPropertyValue(index, "isCollapsed", value);
 },
 GetIsMaximized: function(index) {
  return this.GetPropertyValue(index, "isMaximized");
 },
 GetIsMaximizedOnWebKitTouch: function(index) {
  return this.GetIsMaximized(index) && ASPx.Browser.WebKitTouchUI;
 },
 SetIsMaximized: function(index, value) {
  this.SetPropertyValue(index, "isMaximized", value);
 },
 GetIsMaximizedInit: function(index) {
  return this.GetPropertyValue(index, "isMaximizedInit");
 },
 SetIsMaximizedInit: function(index, value) {
  this.SetPropertyValue(index, "isMaximizedInit", value);
 },
 GetRestoredWindowData: function(index) {
  return ASPx.CloneObject(this.GetPropertyValue(index, "restoredWindowValues"));
 },
 GetEnableContentScrolling: function(index) {
  return this.GetPropertyValue(index, "enableContentScrolling");
 },
 GetWindowOverflowX: function(index) {
  return this.GetPropertyValue(index, "contentOverflowX");
 },
 GetWindowOverflowY: function(index) {
  return this.GetPropertyValue(index, "contentOverflowY");
 },
 SetRestoredWindowData: function(index, value) {
  this.SetPropertyValue(index, "restoredWindowValues", value);
 },
 GetWindowIsShown: function(index) {
  return this.GetPropertyValue(index, "shown");
 },
 SetWindowIsShown: function(index, shown) {
  this.SetPropertyValue(index, "shown", shown);
 },
 GetWindowWidthFromServer: function(index) {
  return this.GetPropertyValue(index, "widthFromServer");
 },
 GetHideBodyScrollWhenModal: function(index) {
  return this.GetPropertyValue(index, "hideBodyScrollWhenModal");
 },
 SetHideBodyScrollWhenModal: function(index, value) {
  this.SetPropertyValue(index, "hideBodyScrollWhenModal", value);
 },
 GetCanScrollViewPort: function(index) {
  return this.GetPropertyValue(index, "canScrollViewPort");
 },
 HasDefaultWindow: function() {
  return this.GetWindowCountCore() === 0;
 },
 GetWindowFooterHeightLite: function(index) {
  var footer = this.GetWindowFooterElement(index);
  if(footer)
   return footer.offsetHeight;
  return null;
 },
 SetWindowPopUpReasonMouseEvent: function(index, evt) {
  evt = ASPx.CloneObject(evt);
  if(evt === undefined)
   evt = null;
  if(0 <= index && index < this.GetWindowCountCore())
   this.windowsPopupReasonMouseEventList[index] = evt;
  this.defaultPopupReasonMouseEvent = evt;
 },
 GetPopUpReasonMouseEvent: function() {
  return this.GetWindowPopUpReasonMouseEvent(null);
 },
 GetWindowPopUpReasonMouseEvent: function(window) {
  var index = (window != null) ? window.index : -1;
  if(0 <= index && index < this.GetWindowCountCore())
   return this.windowsPopupReasonMouseEventList[index];
  return this.defaultPopupReasonMouseEvent;
 },
 GetWindowCountCore: function() {
  return (this.windows.length > 0) ? this.windows.length : this.windowCount;
 },
 SetClientModality: function(isModal) {
  this.SetWindowClientModality(-1, isModal);
 },
 SetWindowClientModality: function(index, isModal) {
  var modalElement = this.GetWindowModalElement(index);
  if(isModal && !ASPx.IsElementVisible(modalElement))
   this.DoShowWindowModalElement(index);
  if(!isModal && ASPx.IsElementVisible(modalElement)) {
   var element = this.GetWindowElement(index);
   this.DoHideWindowModalElement(element);
  }
 },
 GetWindowPinButton: function(index) {
  return ASPx.GetElementById(this.name + "_HPB" + index);
 },
 GetWindowCollapseButton: function(index) {
  return ASPx.GetElementById(this.name + "_HMNB" + index);
 },
 GetWindowMaximizeButton: function(index) {
  return ASPx.GetElementById(this.name + "_HMXB" + index);
 },
 GetWindowScrollDiv: function(index) {
  return this.GetWindowChild(index, "_CSD" + index);
 },
 GetWindowElementDisplayValue: function(windowHasAnyScrollbars, windowHeight) {
  return windowHasAnyScrollbars && windowHeight ? "block" : "table";
 },
 GetMainWindowWidth: function(index, noCache) {
  return this.GetClientWindowWidth(index, true, noCache);
 },
 GetClientWindowWidth: function(index, outerSize, noCache) {
  if(!noCache && (this.GetIsCollapsed(index) || this.GetIsMaximized(index))) {
   var cachedSize = this.GetWindowCachedSize(index);
   if(cachedSize != null)
    return cachedSize.width;
  }
  var element = this.GetWindowElement(index);
  if(element != null)
   return element.offsetWidth;
 },
 GetMainWindowHeight: function(index, noCache) {
  return this.GetClientWindowHeight(index, true, noCache);
 },
 GetClientWindowHeight: function(index, outerSize, noCache) {
  if(!noCache && (this.GetIsCollapsed(index) || this.GetIsMaximized(index))) {
   var cachedSize = this.GetWindowCachedSize(index);
   if(cachedSize != null)
    return cachedSize.height;
  }
  var element = this.GetWindowElement(index);
  if(element != null)
   return element.offsetHeight;
 },
 ShowModal: function() {
  this.ShowModalByIndex(-1);
 },
 ShowModalByIndex: function(index) {
  if(this.adaptivityEnabled) {
   this.SetAdaptiveModalMode(index, true);
   this.ResetModalStyles(index);
   this.ResetPopupStyles(index);
   this.DoShowModal(index, ASPx.InvalidPosition, ASPx.InvalidPosition, this.GetLastShownPopupElementIndex(index));
  }
 },
 DoShowWindowCore: function(index, x, y, popupElementIndex, closeOtherWindows, allowChangeZIndex, evt, closeOtherReason) {
  if(this.IsDOMDisposed()) return;
  this.SetWindowPopUpReasonMouseEvent(index, evt);
  if(this.adaptivityEnabled) {
   this.SetAdaptiveModalMode(index, this.NeedAdaptiveModalMode(index));
   this.ResetModalStyles(index);
   if(this.GetAdaptiveModalMode(index)) {
    this.ResetPopupStyles(index);
    this.DoShowModal(index, x, y, popupElementIndex);
    return;
   }
  }
  this.DoShowWindowAtPos(index, x, y, popupElementIndex, closeOtherWindows, allowChangeZIndex, evt, closeOtherReason);
 },
 NeedAdaptiveModalMode: function(index) {
  return window.innerWidth < this.GetSwitchAtWindowInnerWidth();
 },
 GetSwitchAtWindowInnerWidth: function() {
  return this.switchAtWindowInnerWidth;
 },
 GetModalSystemCssClass: function() {
  return "dxmodalSys";
 },
 DoShowWindowAtPos: function(index, x, y, popupElementIndex, closeOtherWindows, allowChangeZIndex, evt, closeOtherReason) {
  if(!this.isInitialized)
   this.PopulatePopupElements(index);
  var element = this.GetWindowElement(index);
  if(element != null && this.IsWindowElementsIDAssigned(index)) {
   this.StopCloseAnimation(index);
   this.PrepareToAdjustContentOnShow(index);
   if(closeOtherWindows)
    aspxGetPopupControlCollection().DoHideAllWindows(element, this.GetWindowElementId(index), false, closeOtherReason, 0);
   var isMoving = this.InternalIsWindowVisible(index);
   ASPx.SetElementDisplay(element, true);
   element.style.display = this.GetWindowElementDisplayValue(this.HasAnyScrollBars(index), this.GetPopupWindowDimensionFromCache(index, false));
   element.style.position = "absolute";
   var scrollDiv = this.GetWindowScrollDiv(index),
    shouldResetScrollSize = scrollDiv && this.GetEnableContentScrolling(index) && ASPx.GetDocumentMaxClientHeight() <= element.offsetHeight,
    savedScrollDivHeight = shouldResetScrollSize && scrollDiv.style.height;
   if(shouldResetScrollSize)
    scrollDiv.style.height = 0;
   this.RestoreWindowSizeFromCache(index);
   if(!this.GetWindowIsShown(index)) {
    var width = this.GetPopupWindowDimensionFromCache(index, true),
     height = this.GetPopupWindowDimensionFromCache(index, false);
    this.SetClientWindowSizeCoreLite(index, width, height);
    this.SetWindowIsShown(index, true);
   }
   var popupElement = this.GetPopupElement(index, popupElementIndex);
   if(popupElement)
    this.SetLastShownPopupElementIndex(index, popupElementIndex);
   if(this.GetIsMaximized(index)) {
    if(this.hideBodyScrollWhenMaximized)
     ASPx.PopupUtils.BodyScrollHelper.HideBodyScroll(element.id);
    this.NormalizeMaximizedWindowSize(index);
   }
   var isDragged = this.GetIsDragged(index);
   var horizontalPopupPosition = this.GetClientPopupPos(element, popupElement, x, true, isDragged);
   var verticalPopupPosition = this.GetClientPopupPos(element, popupElement, y, false, isDragged);
   var clientX = horizontalPopupPosition.position;
   var clientY = verticalPopupPosition.position;
   this.SetWindowPos(index, element, clientX, clientY);
   if(shouldResetScrollSize)
    scrollDiv.style.height = savedScrollDivHeight;
   this.DoShowWindowModalElement(index);
   this.SetVisibleWithAnimation(element, isMoving, index, horizontalPopupPosition, verticalPopupPosition);
   this.ShowWindowContentUrl(index);
   this.AdjustContentOnShow(index);
   scrollDiv = this.GetWindowScrollDiv(index);
   if(scrollDiv && this.GetEnableContentScrolling(index)) {
    var dimension = null;
    var windowMainCell = this.GetWindowMainCell(element);
    if(windowMainCell.style.width && windowMainCell.style.height)
     dimension = 'both';
    else if(windowMainCell.style.width)
     dimension = 'width';
    else if(windowMainCell.style.height)
     dimension = 'height';
    if(!dimension)
     return;
    ASPx.SetElementDisplay(scrollDiv, false);
    this.SetWindowScrollDivSize(scrollDiv, index, dimension);
    ASPx.SetElementDisplay(scrollDiv, true);
   }
   this.registerAndActivateWindow(element, index, allowChangeZIndex);
   this.RaisePopupOnShow(isMoving, index);
   this.CorrectWindowSizeGripPositionLite(index);
   this.CorrectWindowHeaderText(index);
   this.InitMaximizedWindows(index);
   this.InitCollapsedWindows(index);
   if(this.GetIsPinned(index)) window.setTimeout(function() { this.HoldPosition(index, true); }.aspxBind(this), 0);
   if(!this.GetShowOnPageLoad(index))
    this.CorrectElementVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetWindowHeaderElement(index));
   if(element.style.width.indexOf("px") > -1) {
    element.style.width = ASPx.GetCurrentStyle(element).width;
   }
   this.updateContentScrollIfNeeded(index);
  }
 },
 DoShowModal: function(index, x, y, popupElementIndex) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   this.StopCloseAnimation(index);
   this.EnsureIframeOnIosContentOverflow(index);
   this.PrepareToAdjustContentOnShow(index);
   if(!ASPx.Browser.WebKitTouchUI)
    ASPx.PopupUtils.BodyScrollHelper.HideBodyScroll(element.id);
   this.DoShowWindowModalElement(index);
   var isMoving = this.InternalIsWindowVisible(index);
   ASPx.SetElementDisplay(this.GetModalWrapperElement(index), true);
   this.ResetScroll(index);
   ASPx.SetElementDisplay(element, true);
   this.SetSizeBeforeShow(index);
   this.UpdateAlignment(index);
   var popupElement = this.GetPopupElement(index, popupElementIndex);
   if(popupElement)
    this.SetLastShownPopupElementIndex(index, popupElementIndex);
   this.SetContentElementsAdaptiveDisplayStyle(index);
   var horizontalPopupPosition = this.GetClientPopupPos(element, popupElement, x, true, false),
    verticalPopupPosition = this.GetClientPopupPos(element, popupElement, y, false, false);
   this.SetVisibleWithAnimation(element, isMoving, index, horizontalPopupPosition, verticalPopupPosition);
   this.ShowWindowContentUrl(index);
   this.AdjustContentOnShow(index);
   this.registerAndActivateWindow(element, index, true);
   this.RaisePopupOnShow(isMoving, index);
   this.CorrectWindowHeaderText(index);
   if(!this.GetShowOnPageLoad(index))
    this.CorrectElementVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetWindowHeaderElement(index));
  }
 },
 EnsureIframeOnIosContentOverflow: function(index) {
  if(this.HasIframeOnIos(index)) {
   var contentElement = this.GetWindowContentElement(index);
   if(contentElement.style.overflow === "")
    contentElement.style.overflow = "auto";
  }
 },
 SetWindowElementZIndex: function(element, zIndex) {
  ASPxClientPopupControlBase.prototype.SetWindowElementZIndex.call(this, element, zIndex);
  if(this.adaptivityEnabled)
   this.SetModalWrapperZIndex(this.GetWindowIndex(element), zIndex);
  else
   this.updateContentScrollIfNeeded(this.GetWindowIndex(element));
 },
 SetModalWrapperZIndex: function(index, zIndex) {
  if(!this.GetAdaptiveModalMode(index)) return;
  ASPx.SetStyles(this.GetModalWrapperElement(index), {
   zIndex: zIndex
  });
 },
 updateContentScrollIfNeeded: function(index) {
  var windowElement = this.GetWindowElement(index);
  var wrapper = this.getWindowWrapper(windowElement);
  var wrapperScroll = this.getWindowWrapperScroll(windowElement);
  if(!wrapper || !this.WindowIsModal(index) || !this.GetHideBodyScrollWhenModal(index))
   return;
  ASPx.PopupUtils.adjustViewportScrollWrapper(wrapper, wrapperScroll, windowElement);
 },
 getWindowWrapper: function(windowElement) {
  return ASPx.GetParentByClassName(windowElement, PopupControlCssClasses.WindowWrapperCssClassName);
 },
 getWindowWrapperScroll: function(windowElement) {
  return ASPx.GetParentByClassName(windowElement, PopupControlCssClasses.WindowWrapperScrollCssClassName);
 },
 SizeCanBeSet: function(index, isWindowMaximizedAndCollapsed) {
  return ASPxClientPopupControlBase.prototype.SizeCanBeSet.call(this, index, isWindowMaximizedAndCollapsed) && !this.GetAdaptiveModalMode(index);
 },
 GetPopupWindowDimensionFromCache: function(index, isWidth) {
  var dimension;
  if(isWidth) {
   dimension = this.GetWindowWidthInternal(index);
   if(ASPx.IsExists(dimension)) {
    dimension = Math.max(dimension, this.GetWindowMinWidth(index));
    var maxWidth = this.GetWindowMaxWidth(index);
    if(maxWidth)
     dimension = Math.min(dimension, maxWidth);
   }
  }
  else {
   dimension = this.GetWindowHeightInternal(index);
   if(ASPx.IsExists(dimension)) {
    if(this.HasAnyScrollBars(index) && dimension === constants.DEFAULT_WINDOW_HEIGHT)
     return undefined;
    dimension = Math.max(dimension, this.GetWindowMinHeight(index));
    var maxHeight = this.GetWindowMaxHeight(index);
    if(maxHeight)
     dimension = Math.min(dimension, maxHeight);
   }
  }
  return dimension;
 },
 NormalizeMaximizedWindowSize: function(index) {
  var width = this.GetPopupWindowDimensionFromCache(index, true),
   height = this.GetPopupWindowDimensionFromCache(index, false),
   dimensions = this.getDocumentDimensions(index),
   sizeNormalizationIsNeeded = width < dimensions.width || height < dimensions.height;
  if(sizeNormalizationIsNeeded)
   this.NormalizeWindowSize(index, true);
 },
 NormalizeWindowSize: function(index, isMaximized) {
  var width = this.GetClientWindowWidth(index),
   height = this.GetClientWindowHeight(index),
   normWidth = width,
   normHeight = height,
   maxWidth = this.GetWindowMaxWidth(index),
   minWidth = this.GetWindowMinWidth(index),
   maxHeight = this.GetWindowMaxHeight(index),
   minHeight = this.GetWindowMinHeight(index);
  if(maxWidth)
   normWidth = Math.min(normWidth, maxWidth);
  if(minWidth)
   normWidth = Math.max(normWidth, minWidth);
  if(maxHeight)
   normHeight = Math.min(normHeight, maxHeight);
  if(minHeight)
   normHeight = Math.max(normHeight, minHeight);
  if(normWidth !== width || normHeight !== height)
   this.SetWindowSize(this.GetWindow(index), normWidth, normHeight);
  if(isMaximized) {
   var dimensions = this.getDocumentDimensions(index);
   if(this.GetIsCollapsed(index)) {
    if(normWidth != dimensions.width) {
     this.SetWindowSizeByIndexCore(index, dimensions.width, normHeight, true);
    }
   } else {
    if(normWidth != dimensions.width || normHeight != dimensions.height) {
     this.SetWindowSizeByIndexCore(index, dimensions.width, dimensions.height, false);
    }
   }
  }
 },
 DoShowWindowModalElement: function(index) {
  if(this.CanManipulateWithModalElement(index)) {
   if(this.adaptivityEnabled) {
    this.DoShowWindowModalElementWithAdaptivity(index);
    return;
   }
   var modalElement = this.GetWindowModalElement(index);
   var bodyScrollHasJustBeingHidden = false;
   if(this.GetHideBodyScrollWhenModal(index) && (!this.IsWindowVisible(this.GetWindow(index)) || !ASPx.IsElementVisible(modalElement))) {
    bodyScrollHasJustBeingHidden = true;
    aspxGetPopupControlCollection().LockWindowResizeByBodyScrollVisibilityChanging();
    if(!ASPx.Browser.WebKitTouchUI)
     ASPx.PopupUtils.BodyScrollHelper.HideBodyScroll(this.GetWindowElementId(index));
   }
   ASPx.SetElementDisplay(modalElement, true);
   this.AdjustModalElementBounds(modalElement);
   this.SetModalElementVisibilityWithAnimation(modalElement, index);
   aspxGetPopupControlCollection().RegisterVisibleModalElement(modalElement);
   if(bodyScrollHasJustBeingHidden)
    aspxGetPopupControlCollection().UnlockWindowResizeByBodyScrollVisibilityChanging();
  }
 },
 DoShowWindowModalElementWithAdaptivity: function(index) {
  var overlayElement = this.GetOverlayElement(index);
  if(!overlayElement) return;
  ASPx.SetStyles(overlayElement, {
   right: 0,
   bottom: 0,
   width: "",
   height: ""
  });
  ASPx.SetElementDisplay(overlayElement, true);
  this.SetModalElementVisibilityWithAnimation(overlayElement, index);
  ASPx.GetPopupControlCollection().RegisterVisibleModalElement(overlayElement);
 },
 SetSizeBeforeShow: function(index) {
  if(this.GetModalMaxWidth(index) && this.GetModalMaxWidth(index) !== this.DefaultModalMaxWidth)
   this.SetAdaptiveMaxWidthByIndex(index, this.GetModalMaxWidth(index));
  if(this.GetModalMinWidth(index) !== this.DefaultModalMinWidth)
   this.SetAdaptiveMinWidthByIndex(index, this.GetModalMinWidth(index));
  this.UpdateHeightDimensions(index);
 },
 UpdateHeightDimensions: function(index) {
  this.UpdateAdaptiveMinHeight(index);
  this.UpdateAdaptiveMaxHeight(index);
 },
 UpdateAdaptiveMinHeight: function(index) {
  if(this.GetModalMinHeight(index) !== null)
   this.SetAdaptiveHeightDimension(index, "minHeight", this.GetModalMinHeight(index));
 },
 UpdateAdaptiveMaxHeight: function(index) {
  if(this.GetModalMaxHeight(index) !== null)
   this.SetAdaptiveHeightDimension(index, "maxHeight", this.GetModalMaxHeight(index));
 },
 GetClientPopupPos: function(element, popupElement, pos, isX, isDragged) {
  if(!this.GetAdaptiveModalMode(this.GetWindowIndex(element)))
   return ASPxClientPopupControlBase.prototype.GetClientPopupPos.call(this, element, popupElement, pos, isX, isDragged);
  var getPosFunc = isX ? ASPx.GetAbsolutePositionX : ASPx.GetAbsolutePositionY;
  return { position: getPosFunc(element) };
 },
 GetAnimationVerticalDirection: function(index, verticalPopupPosition) {
  if(!this.GetAdaptiveModalMode(index))
   return ASPxClientPopupControlBase.prototype.GetAnimationVerticalDirection.call(this, index, verticalPopupPosition);
  return ASPxClientPopupControl.Animation.GetVerticalDirection(this.modalVerticalAlign, this.modalHorizontalAlign);
 },
 GetAnimationHorizontalDirection: function(index, horizontalPopupPosition) {
  if(!this.GetAdaptiveModalMode(index))
   return ASPxClientPopupControlBase.prototype.GetAnimationHorizontalDirection.call(this, index, horizontalPopupPosition);
  return ASPxClientPopupControl.Animation.GetHorizontalDirection(this.modalHorizontalAlign);
 },
 GetDefaultVerticalOffset: function() {
  return this.IsSmallDisplay() ? 10 : 30;
 },
 IsSmallDisplay: function() {
  return window.innerWidth < this.GetScreenLimitForCss();
 },
 GetScreenLimitForCss: function() {
  return ASPx.MaxMobileWindowWidth;
 },
 StartAutoAnimation: function(element, index, horizontalPopupPosition, verticalPopupPosition) {
  if(this.adaptivityEnabled) {
   if(this.NeedFadeAnimation(index, this.popupAnimationType))
    this.StartFadeAnimation(element, index);
   else
    this.StartSlideAnimation(element, index, horizontalPopupPosition, verticalPopupPosition);
  } else 
   ASPxClientPopupControlBase.prototype.StartAutoAnimation.call(this, element, index, horizontalPopupPosition, verticalPopupPosition);
 },
 DoHideWindowWithAutoAnimation: function(index, element, closeReason) {
  if(this.NeedFadeAnimation(index, this.closeAnimationType))
   this.DoHideWindowWithFadeAnimation(index, element, closeReason);
  else
   this.DoHideWindowWithSlideAnimation(index, closeReason);
 },
 IsDraggingAllowed: function(index) {
  return this.allowDragging && (!this.GetAdaptiveModalMode(index) || this.allowDraggingInAdaptiveMode);
 },
 IsResizeAllowed: function(index) {
  return ASPxClientPopupControlBase.prototype.IsResizeAllowed.call(this, index) && !this.GetAdaptiveModalMode(index);
 },
 IsFadeCloseAnimation: function(index) {
  return ASPxClientPopupControlBase.prototype.IsFadeCloseAnimation.call(this, index) || this.NeedFadeAnimation(index, this.closeAnimationType);
 },
 NeedFadeAnimation: function(index, animationType) {
  return ASPxClientPopupControl.Animation.NeedFadeAnimation(this.modalHorizontalAlign, this.modalVerticalAlign,
   animationType, this.popupHorizontalAlign, this.popupVerticalAlign, this.GetAdaptiveModalMode(index));
 },
 AllowModalElementAnimation: function(index) {
  if(this.GetAdaptiveModalMode(index))
   return this.HasOpenAnimation();
  return ASPxClientPopupControlBase.prototype.AllowModalElementAnimation.call(this, index);
 },
 DoHideWindowCore: function(index, closeReason) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   if(this.HasCloseAnimation())
    this.PrepareElementAfterCloseAnimation(index, element);
   element.isHiding = true;
   element.style.zIndex = this.GetDefaultZIndexFromServer();
   this.SetIsDragged(index, false);
   this.UpdateWindowsStateCookie();
   element.isHiding = false;
   this.StopShowAnimation(index);
   if(ASPx.Browser.WebKitTouchUI || ASPx.Browser.Safari) {
    var dummy = element.offsetWidth; 
   }
   ASPx.SetElementDisplay(element, false);
   ASPx.SetElementVisibility(element, false);
   if(this.adaptivityEnabled) {
    ASPx.SetElementDisplay(this.GetModalWrapperElement(index), "");
    if(!ASPx.Browser.WebKitTouchUI)
     ASPx.PopupUtils.BodyScrollHelper.RestoreBodyScroll(element.id);
    this.SetWrapperScrollVisible(index, true);
    this.SetIsDragged(index, false);
   }
   if(this.hideBodyScrollWhenMaximized && this.GetIsMaximized(index))
    ASPx.PopupUtils.BodyScrollHelper.RestoreBodyScroll(element.id);
   this.DoHideWindowModalElement(element, closeReason);
   this.DoHideWindowIFrame(element);
   aspxGetPopupControlCollection().UnregisterVisibleWindow(element);
   this.ProcessAccessibleElementOnHide();
   this.HideWindowLoadingPanel(index);
  }
 },
 OnAnimationStop: function(index) {
  if(this.adaptivityEnabled) {
   this.SetWrapperScrollVisible(index, true);
   this.UnlockWrapperScrollEventEvent();
  }
  ASPxClientPopupControlBase.prototype.OnAnimationStop.call(this, index);
  if(!this.adaptivityEnabled && ASPx.Browser.Firefox)
   this.GetWindowElement(index).style.display = "table";
 },
 ResetModalStyles: function(index) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   ASPx.SetStyles(element, {
    minWidth: "",
    maxWidth: "",
    marginTop: "",
    marginLeft: "",
    marginRight: "",
    position: ""
   });
   ASPx.SetStyles(this.GetWindowContentElement(index), {
    minHeight: "",
    maxHeight: "",
   });
   this.FixateFooter(index, false, 0);
   this.FixateHeader(index, false, 0);
   this.SetIsDragged(false);
   this.DoHideWindowModalElement(element);
  }
 },
 ResetPopupStyles: function(index) {
  var element = this.GetWindowElement(index);
  if(element != null) {
   ASPx.SetStyles(element, {
    left: "",
    top: "",
    width: "",
    height: "",
   });
   ASPx.SetStyles(this.GetWindowContentWrapperElement(index), {
    height: "",
    width: "",
    display: ""
   });
   ASPx.SetStyles(this.GetWindowContentElement(index), {
    display: "",
    width: "",
    height: ""
   });
   this.SetWindowIsShown(index, false);
  }
 },
 InitDivPosForHideSlideAnimation: function(animationDivElement) {
  ASPx.PopupUtils.InitAnimationDivCore(animationDivElement);
 },
 DoHideWindow: function(index, dontRaiseClosing, closeReason) {
  var cancel = ASPxClientPopupControlBase.prototype.DoHideWindow.call(this, index, dontRaiseClosing, closeReason);
  this.updateContentScrollIfNeeded(index);
  return cancel;
 },
 OnWindowShown: function(windowIndex) {
  this.EnsureContent(windowIndex, false);
  this.EnsureIFrameHeightAdjusted(windowIndex);
  if(this.GetAdaptiveModalMode(windowIndex))
   this.ChangeFooterFixed(windowIndex);
  else {
   var isMaximized = this.GetIsMaximized(windowIndex);
   if(isMaximized || this.HasAnyScrollBars(windowIndex))
    this.NormalizeWindowSize(windowIndex, isMaximized);
  }
  this.RaiseShown(windowIndex);
  var loadingElementsWillNotBeShown = !this.lpTimers[windowIndex] || this.lpTimers[windowIndex] < 0;
  if(this.InWindowCallback(windowIndex) && loadingElementsWillNotBeShown) {
   this.ShowWindowLoadingElementsInternal(windowIndex);
  }
  if(this.GetAdaptiveModalMode(windowIndex))
   this.UpdateAdaptiveMinHeight(windowIndex);
 },
 SetWrapperScrollVisible: function(index, visible) {
  if(!this.GetAdaptiveModalMode(index)) return;
  var modalWrapper = this.GetModalWrapperElement(index);
  if(visible) {
   ASPx.Attr.RestoreStyleAttribute(modalWrapper, "overflow-x");
   ASPx.Attr.RestoreStyleAttribute(modalWrapper, "overflow-y");
  } else {
   if(this.modalVerticalAlign === ModalAlign.WindowBottom && this.GetWindowElement(index).offsetHeight <= window.innerHeight)
    ASPx.Attr.ChangeStyleAttribute(modalWrapper, "overflow-y", "hidden");
   if(this.modalHorizontalAlign === ModalAlign.WindowRight)
    ASPx.Attr.ChangeStyleAttribute(modalWrapper, "overflow-x", "hidden");
  }
 },
 GetDragCorrection: function(index, element, isX) {
  if(this.adaptivityEnabled) {
   var offset = isX ? element.offsetLeft : element.offsetTop;
   offset -= ASPx.PxToInt(element.style[isX ? "left" : "top"]);
   return ASPx.GetPositionElementOffset(this.GetModalWrapperElement(index), isX) + offset;
  } else
   return ASPxClientPopupControlBase.prototype.GetDragCorrection.call(this, index, element, isX);
 },
 GetSlideAnimationDuration: function(index) {
  return !this.GetAdaptiveModalMode(index) ? ASPxClientPopupControlBase.prototype.GetSlideAnimationDuration.call(this, index) : 300;
 },
 GetSlideOffsetCoefficient: function(index) {
  return !this.GetAdaptiveModalMode(index) ? ASPxClientPopupControlBase.prototype.GetSlideOffsetCoefficient.call(this, index) : 0.25;
 },
 InitDivPosForShowSlideAnimation: function(index, animationDivElement, clientX, clientY, onAnimStopCallString) {
  if(!this.GetAdaptiveModalMode(index))
   ASPxClientPopupControlBase.prototype.InitDivPosForShowSlideAnimation.call(this, index, animationDivElement, clientX, clientY, onAnimStopCallString);
  else
   ASPx.PopupUtils.InitAnimationProperties(animationDivElement, onAnimStopCallString);
 },
 BeforeAnySlideAnimation: function(index) {
  this.FixateFooter(index, false, 0);
  this.FixateHeader(index, false, 0);
  this.SetWrapperScrollVisible(index, false);
 },
 StartSlideAnimation: function(animationDivElement, index, horizontalPopupPosition, verticalPopupPosition) {
  if(this.adaptivityEnabled) {
   this.LockWrapperScrollEvent();
   this.BeforeAnySlideAnimation(index);
  }
  ASPxClientPopupControlBase.prototype.StartSlideAnimation.call(this, animationDivElement, index, horizontalPopupPosition, verticalPopupPosition);
 },
 DoHideWindowWithSlideAnimation: function(index, closeReason) {
  if(this.adaptivityEnabled)
   this.BeforeAnySlideAnimation(index);
  ASPxClientPopupControlBase.prototype.DoHideWindowWithSlideAnimation.call(this, index, closeReason);
 },
 UpdatePositionAfterCallback: function(windowIndex) {
  if(!this.InternalIsWindowVisible(windowIndex)) return;
  if(this.adaptivityEnabled)
   this.TryAutoUpdatePosition(windowIndex);
  else if(this.contentLoadingMode === LoadContentViaCallback.OnFirstShow)
   this.UpdateWindowPositionInternal(windowIndex, this.GetPopupElement(windowIndex, this.GetLastShownPopupElementIndex(windowIndex)));
 },
 CreateLoadingDiv: function(parentElement, offsetElement, windowIndex) {
  if(typeof (windowIndex) != "undefined") { 
   var loadingDiv = ASPxClientControl.prototype.CreateLoadingDiv.call(this, parentElement, offsetElement);
   loadingDiv.id += windowIndex;
   return loadingDiv;
  }
 },
 CreateLoadingPanelWithAbsolutePosition: function(parentElement, offsetElement, windowIndex) {
  if(typeof (windowIndex) != "undefined") { 
   var loadingPanel = ASPxClientControl.prototype.CreateLoadingPanelWithAbsolutePosition.call(this, parentElement, offsetElement);
   loadingPanel.id += windowIndex;
   return loadingPanel;
  }
 },
 PerformWindowCallback: function(window, parameter, onSuccess) {
  ASPxClientPopupControlBase.prototype.PerformWindowCallback.call(this, window, parameter, onSuccess);
 },
 SetIframeVisibleForDragging: function(index, visible) {
  var iframeElement = this.GetWindowContentIFrameElement(index);
  if(ASPx.Browser.Edge)
   iframeElement.style.pointerEvents = visible ? "" : "none";
  ASPx.SetElementVisibility(iframeElement, visible);
 },
 OnResizeStop: function(evt, index, cursor, resizePanel) {
  ASPxClientPopupControlBase.prototype.OnResizeStop.call(this, evt, index, cursor, resizePanel);
  if(this.IsResizeAllowed(index))
   this.SetWindowCachedSize(index, this.GetClientWindowWidth(index), this.GetClientWindowHeight(index));
  this.updateContentScrollIfNeeded(index);
 },
 OnMouseDownModalElement: function(evt, index) {
  aspxGetPopupControlCollection().DoHideAllWindows(ASPx.Evt.GetEventSource(evt), "", false, ASPxClientPopupControlCloseReason.OuterMouseClick, evt.offsetX);
  this.SetIsPopuped(index, true);
 },
 IsRaiseAfterResizingLocked: function() {
  return this.CollapseExecuting() || this.MaximizationExecuting();
 },
 GetContentElementChildren: function(index, contentElement) {
  var cache = this.GetResizeSessionCache();
  if(!cache.contentElementChildren || !cache.contentElementChildren[index]) {
   cache.contentElementChildren = [];
   cache.contentElementChildren[index] = contentElement.getElementsByTagName("*");
  }
  return cache.contentElementChildren[index];
 },
 GetContentElementChildrenScroll: function(index, contentElementChildren) {
  var cache = this.GetResizeSessionCache();
  if(!cache.contentElementChildrenScroll || !cache.contentElementChildrenScroll[index]) {
   cache.contentElementChildrenScroll = [];
   cache.contentElementChildrenScroll[index] = [];
   for(var i = 0, len = contentElementChildren.length; i < len; i++) {
    var child = contentElementChildren[i];
    if(!!child.scrollLeft || !!child.scrollTop)
     cache.contentElementChildrenScroll[index].push([i, child.scrollLeft, child.scrollTop]);
   }
  }
  return cache.contentElementChildrenScroll[index];
 },
 GetElementBordersAndPaddings: function(index, element, leftRight) {
  var cache = this.GetResizeSessionCache();
  if(!cache.elementBordersAndPaddings || !cache.elementBordersAndPaddings[index]) {
   cache.elementBordersAndPaddings = [];
   var style = ASPx.GetCurrentStyle(element);
   cache.elementBordersAndPaddings[index] = {
    leftRight: this.getLeftRightBordersAndPaddingsSummaryValue(element, style),
    topBottom: this.getTopBottomBordersAndPaddingsSummaryValue(element, style)
   };
  }
  return leftRight ? cache.elementBordersAndPaddings[index].leftRight : cache.elementBordersAndPaddings[index].topBottom;
 },
 GetHeaderFooterHeight: function(index) {
  var cache = this.GetResizeSessionCache();
  if(!cache.headerFooterHeight || !cache.headerFooterHeight[index]) {
   cache.headerFooterHeight = [];
   cache.headerFooterHeight[index] = this.GetHeaderFooterHeightCore(index);
  }
  return cache.headerFooterHeight[index];
 },
 getContentElementDisplay: function(correctContentElementSize, contentUrl) {
  return correctContentElementSize || contentUrl ? "block" : "table-cell";
 },
 SetContentWrapperHeightLite: function(index, actualHeight, windowElem, contentWrapper) {
  if(!windowElem.style.height || ASPx.IsPercentageSize(windowElem.style.height))
   return;
  var borderOwner = this.GetWindowBorderOwnerElement(windowElem);
  var height = borderOwner == windowElem ? actualHeight : actualHeight - (borderOwner ? ASPx.GetTopBottomBordersAndPaddingsSummaryValue(borderOwner) : 0);
  height -= this.GetHeaderFooterHeight(index);
  if(height > 0)
   contentWrapper.style.height = height + "px";
 },
 SetWindowScrollDivSize: function(scrollDiv, index, dimension) {
  var windowClientTable = this.GetWindowClientTable(index);
  var headerElement = this.GetWindowHeaderElement(index);
  var height = windowClientTable.offsetHeight;
  if(headerElement)
   height -= headerElement.offsetHeight;
  height -= this.GetWindowFooterHeightLite(index);
  if(dimension == 'height' || dimension == 'both')
   ASPx.SetOffsetHeight(scrollDiv, height);
  if(dimension == 'width' || dimension == 'both') {
   var width = windowClientTable.offsetWidth;
   var contentElement = this.GetWindowContentElement(index);
   width -= this.getLeftRightBordersAndPaddingsSummaryValue(scrollDiv) + ASPx.GetHorizontalBordersWidth(contentElement);
   if(width > -1)
    scrollDiv.style.width = width + "px";
  }
  scrollDiv.style.marginRight = "0px";
 },
 AdjustIFrameHeight: function(index, iframe) {
  ASPxClientPopupControlBase.prototype.AdjustIFrameHeight.call(this, index, iframe);
  if(!this.InternalIsWindowVisible(index) || !iframe || this.GetAdaptiveModalMode(index)) return;
  this.SetIframeAdjustingPostponed(index, false);
  var content = this.GetContentContainer(index);
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  iframe.style.verticalAlign = "text-bottom";
  var iframeHeight = contentWrapper.offsetHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(content);
  if(iframeHeight >= 0)
   iframe.style.height = iframeHeight + "px";
 },
 OnPinButtonClick: function(index) {
  var value = this.GetIsPinned(index);
  this.SetPinCore(index, !value);
 },
 SetPinCore: function(index, value) {
  if(this.GetIsPinned(index) != value) {
   this.SetIsPinned(index, value);
   this.HoldPosition(index, value);
   this.UpdateWindowsStateCookie();
   this.OnPinned(index, value);
  }
 },
 OnPinned: function(index, pinned) {
  this.RaisePinnedChanged(index, pinned);
 },
 HoldPosition: function(index, hold, element) {
  if(hold) {
   element = element || this.GetWindowElement(index);
   if(!element) return;
   var x = ASPx.GetAbsoluteX(element);
   var y = ASPx.GetAbsoluteY(element);
   scrollX = ASPx.GetDocumentScrollLeft();
   scrollY = ASPx.GetDocumentScrollTop();
   this.SetPinPosX(index, x - scrollX);
   this.SetPinPosY(index, y - scrollY);
  }
  this.UpdateHeaderButtonSelected(index, "GetWindowPinButton", hold);
  this.CheckHeaderCursor(index);
 },
 GetBodyWidth: function() {
  return aspxGetPopupControlCollection().GetSavedBodyWidth();
 },
 GetBodyHeight: function() {
  return aspxGetPopupControlCollection().GetSavedBodyHeight();
 },
 GetIsOutFromViewPort: function(index) {
  var element = this.GetWindowElement(index);
  if(!element) return false;
  var pinXTarget = this.GetPinPosX(index);
  var pinYTarget = this.GetPinPosY(index);
  var popupWindowWidth = this.GetClientWindowWidth(index);
  var docClientWidth = ASPx.GetDocumentClientWidth();
  var rightOutOffset = (pinXTarget + popupWindowWidth) - docClientWidth;
  var popupWindowHeight = this.GetClientWindowHeight(index);
  var docClientHeight = ASPx.GetDocumentClientHeight();
  var bottomOutOffset = (pinYTarget + popupWindowHeight) - docClientHeight;
  return (rightOutOffset > 0 || bottomOutOffset > 0);
 },
 needToHidePinnedOutFromViewPort: function(index) {
  return this.GetIsPinned(index) && this.GetIsOutFromViewPort(index);
 },
 AdjustPinPositionWhileScroll: function(index) {
  var element = this.GetWindowElement(index);
  if(!element) return;
  var x = ASPx.GetAbsoluteX(element);
  var y = ASPx.GetAbsoluteY(element);
  var scrollX = ASPx.GetDocumentScrollLeft();
  var scrollY = ASPx.GetDocumentScrollTop();
  var pinX = x - scrollX;
  var pinY = y - scrollY;
  var pinXTarget = this.GetPinPosX(index);
  var pinYTarget = this.GetPinPosY(index);
  if((pinX != pinXTarget) || (pinY != pinYTarget)) {
   this.lockScroll++;
   var xNew = pinXTarget + scrollX;
   var yNew = pinYTarget + scrollY;
   var bodyWidth = this.GetBodyWidth();
   var bodyHeight = this.GetBodyHeight();
   var popupWindowWidth = this.GetClientWindowWidth(index);
   var docClientWidth = ASPx.GetDocumentClientWidth();
   var rightOutOffset = (pinXTarget + popupWindowWidth) - docClientWidth;
   var popupWindowHeight = this.GetClientWindowHeight(index);
   var docClientHeight = ASPx.GetDocumentClientHeight();
   var bottomOutOffset = (pinYTarget + popupWindowHeight) - docClientHeight;
   var cancelScrollX = false;
   if(xNew + (popupWindowWidth - rightOutOffset) > bodyWidth) {
    xNew -= (xNew + (popupWindowWidth - rightOutOffset) - bodyWidth);
    cancelScrollX = true;
   }
   var cancelScrollY = false;
   if(yNew + (popupWindowHeight - bottomOutOffset) > bodyHeight) {
    yNew -= (yNew + (popupWindowHeight - bottomOutOffset) - bodyHeight);
    cancelScrollY = true;
   }
   xNew = ASPx.PrepareClientPosForElement(xNew, element, true);
   yNew = ASPx.PrepareClientPosForElement(yNew, element, false);
   this.SetWindowPos(index, element, xNew, yNew);
   if(cancelScrollX) {
    var scrollLeftMax = bodyWidth - ASPx.GetDocumentClientWidth();
    if((rightOutOffset > 0) && (scrollX > scrollLeftMax)) {
     this.lockScroll++;
     ASPx.SetDocumentScrollLeft(scrollLeftMax);
     this.lockScroll--;
    }
   }
   if(cancelScrollY) {
    var scrollTopMax = bodyHeight - ASPx.GetDocumentClientHeight();
    if((bottomOutOffset > 0) && (scrollY > scrollTopMax)) {
     this.lockScroll++;
     ASPx.SetDocumentScrollTop(scrollTopMax);
     this.lockScroll--;
    }
   }
   this.lockScroll--;
  }
 },
 OnCollapseButtonClick: function(index) {
  this.SetCollapsedCore(index, !this.GetIsCollapsed(index));
 },
 SetCollapsedCore: function(index, minimization) {
  if(this.GetIsCollapsed(index) == minimization) return;
  this.DoCollapse(index, minimization);
  this.OnCollapsed(index, minimization);
 },
 DoCollapse: function(index, minimization) {
  if(this.GetIsCollapsed(index) == minimization) return;
  this.StartCollapse();
  if(minimization) {
   var cachedWidth = this.GetClientWindowWidth(index);
   var cachedHeight = this.GetClientWindowHeight(index);
   var shouldUpdateRestoredSize = this.ShoulUpdatedRestoredWindowSizeOnCollapse(index);
   var width = this.GetMainWindowWidth(index, !shouldUpdateRestoredSize);
   var height = this.GetMainWindowHeight(index, !shouldUpdateRestoredSize);
   this.SetWindowSizeByIndex(index, width, 0);
   this.SetWindowContentVisible(index, false);
   this.SetWindowFooterVisible(index, false);
   this.ResetWindowHeight(index);
   this.SetIsCollapsed(index, minimization);
   this.SetWindowCachedSize(index, cachedWidth, cachedHeight);
   if(shouldUpdateRestoredSize)
    this.UpdateRestoredWindowSize(index, width, height);
  }
  else {
   if(this.MaximizationExecuting()) {
    var element = this.GetWindowElement(index);
    if(element) {
     element.style.left = ASPx.GetDocumentScrollLeft();
     element.style.top = ASPx.GetDocumentScrollTop();
    }
   }
   this.SetWindowContentVisible(index, true);
   this.SetWindowFooterVisible(index, true);
   this.SetIsCollapsed(index, minimization);
   if(this.GetIsMaximized(index)) {
    var documentClientWidth = ASPx.PopupUtils.GetDocumentClientWidthForPopup();
    var documentClientHeight = ASPx.PopupUtils.GetDocumentClientHeightForPopup();
    this.SetWindowSizeByIndex(index, documentClientWidth, documentClientHeight);
   } else {
    var restoredWindowData = this.GetRestoredWindowData(index);
    this.SetWindowSizeByIndex(index, restoredWindowData.width, restoredWindowData.height);
   }
   ASPx.GetControlCollection().AdjustControls(this.GetWindowElement(index));
  }
  this.UpdateHeaderButtonSelected(index, "GetWindowCollapseButton", minimization);
  this.EndCollapse();
  this.UpdateWindowsStateCookie();
 },
 ResetWindowHeight: function(index) {
  var element = this.GetWindowElement(index);
  if(element)
   element.style.height = "";
 },
 ShoulUpdatedRestoredWindowSizeOnCollapse: function(index) {
  return !this.GetIsMaximized(index);
 },
 OnCollapsed: function(index, value) {
  if(value)
   this.RaiseCollapsed(index);
  else
   this.RaiseExpanded(index);
  this.RaiseAfterResizing(index);
 },
 OnMaximizeButtonClick: function(index) {
  this.SetMaximizedCore(index, !this.GetIsMaximized(index));
 },
 SetMaximizedCore: function(index, maximization) {
  if(this.GetIsMaximized(index) == maximization) return;
  this.DoMaximize(index, maximization);
  this.OnMaximizedChanged(index, maximization);
 },
 GetMaximizedPosition: function(element, isX) {
  if(ASPx.Browser.WebKitTouchUI)
   return ASPx.PrepareClientPosForElement(0, element, isX);
  return ASPx.PrepareClientPosForElement(isX ? ASPx.GetDocumentScrollLeft() : ASPx.GetDocumentScrollTop(), element, isX);
 },
 PerformMaximaze: function (index, maximization, element) {
  if (this.hideBodyScrollWhenMaximized)
   ASPx.PopupUtils.BodyScrollHelper.HideBodyScroll(element.id);
  if (this.GetIsCollapsed(index))
   this.DoCollapse(index, false);
  var cachedWidth = this.GetClientWindowWidth(index);
  var cachedHeight = this.GetClientWindowHeight(index);
  var restoredWindowData = this.GetInitRestoredWindowData(index);
  var documentClientWidth = ASPx.PopupUtils.GetDocumentClientWidthForPopup();
  var documentClientHeight = ASPx.PopupUtils.GetDocumentClientHeightForPopup();
  var windowClientTable = this.GetWindowClientTable(index);
  var windowClientTableParent = windowClientTable.parentNode;
  childStyle = ASPx.GetCurrentStyle(windowClientTableParent);
  var left = this.GetMaximizedPosition(element, true);
  var top = this.GetMaximizedPosition(element, false);
  this.SetWindowPos(index, element, left, top);
  this.SetWindowSizeByIndex(index, documentClientWidth, documentClientHeight);
  this.SetWindowCachedSize(index, cachedWidth, cachedHeight);
  this.SetRestoredWindowData(index, restoredWindowData);
  this.SetIsMaximized(index, maximization);
 },
 PerformMinimize: function (index, maximization, element) {
  var restoredWindowData = this.GetRestoredWindowData(index);
  var width = restoredWindowData.width || this.GetMainWindowWidth(index);
  var height = restoredWindowData.height || this.GetMainWindowHeight(index);
  this.SetIsMaximized(index, maximization);
  var left = ASPx.PrepareClientPosForElement(restoredWindowData.left, element, true);
  var top = ASPx.PrepareClientPosForElement(restoredWindowData.top, element, false);
  this.SetWindowPos(index, element, left, top);
  this.SetWindowSizeByIndex(index, width, height);
  if (this.GetIsCollapsed(index)) {
   this.SetIsCollapsed(index, false);
   this.UpdateRestoredWindowSizeLock();
   this.DoCollapse(index, true);
   this.UpdateRestoredWindowSizeUnlock();
  }
  if (this.hideBodyScrollWhenMaximized)
   ASPx.PopupUtils.BodyScrollHelper.RestoreBodyScroll(element.id);
 },
 DoMaximize: function(index, maximization) {
  if(this.GetIsMaximized(index) == maximization) return;
  var element = this.GetWindowElement(index);
  if(!element) return;
  this.StartMaximization();
  if(maximization)
   this.PerformMaximaze(index, maximization, element);
  else
   this.PerformMinimize(index, maximization, element);
  if(this.GetIsPinned(index))
   this.HoldPosition(index, true, element);
  this.UpdateHeaderButtonSelected(index, "GetWindowMaximizeButton", maximization);
  this.EndMaximization();
  this.UpdateWindowsStateCookie();
  this.CheckHeaderCursor(index);
 },
 OnMaximizedChanged: function(index, value) {
  if(value)
   this.RaiseMaximized(index);
  else
   this.RaiseRestoredAfterMaximized(index);
  this.RaiseAfterResizing(index);
 },
 GetInitRestoredWindowData: function(index) {
  var restoredWindowData = this.GetRestoredWindowData(index);
  restoredWindowData.left = this.GetCurrentLeft(index);
  restoredWindowData.top = this.GetCurrentTop(index);
  restoredWindowData.width = this.GetMainWindowWidth(index);
  restoredWindowData.height = this.GetMainWindowHeight(index);
  return restoredWindowData;
 },
 getDocumentDimensions: function(index) {
  var documentClientWidth = ASPx.PopupUtils.GetDocumentClientWidthForPopup(),
   documentClientHeight = ASPx.PopupUtils.GetDocumentClientHeightForPopup();
  return { width: documentClientWidth, height: documentClientHeight };
 }, 
 UpdateMaximizedWindowSizeOnResize: function(index) {
  this.StartUpdateMaximizedWindowSizeOnResize();
  var dimensions = this.getDocumentDimensions(index);
  if(this.GetIsCollapsed(index)) dimensions.height = 0;
  this.SetWindowSizeByIndex(index, dimensions.width, dimensions.height);
  if(this.GetIsCollapsed(index)) {
   this.CorrectCollapsedSize(index);
  }
  window.setTimeout(function() { this.SetMaximizedWindowSizeAfterOnResize(index); }.aspxBind(this), 0);
  this.EndUpdateMaximizedWindowSizeOnResize();
 },
 SetMaximizedWindowSizeAfterOnResize: function(index) {
  this.StartUpdateMaximizedWindowSizeOnResize();
  var dimensions = this.getDocumentDimensions(index);
  windowWidthCurrent = this.GetMainWindowWidth(index, true);
  windowHeightCurrent = this.GetMainWindowHeight(index, true);
  if(this.GetIsCollapsed(index))
   dimensions.height = 0;
  if(dimensions.width != windowWidthCurrent || dimensions.height != windowHeightCurrent) {
   this.SetWindowSizeByIndex(index, dimensions.width, dimensions.height);
   if(this.GetIsCollapsed(index)) {
    this.CorrectCollapsedSize(index);
   }
  }
  this.EndUpdateMaximizedWindowSizeOnResize();
 },
 CorrectCollapsedSize: function(index) {
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  if(contentWrapper && ASPx.IsElementVisible(contentWrapper))
   contentWrapper.style.display = 'none';
 },
 UpdateHeaderButtonSelected: function(index, methodGetWindowButton, flagSelected) {
  if(typeof (ASPx.GetStateController) != "undefined") {
   button = this[methodGetWindowButton](index);
   var method = flagSelected ? "SelectElementBySrcElement" : "DeselectElementBySrcElement";
   ASPx.GetStateController()[method](button);
  }
 },
 CheckHeaderCursor: function(index) {
  if(!this.allowDragging) return;
  var dragElement = this.GetDragElement(index);
  if(!dragElement) return;
  var styleCursor = dragElement.style.cursor;
  var isPinned = this.GetIsPinned(index);
  var isMaximized = this.GetIsMaximized(index);
  if((isPinned || isMaximized) && styleCursor != "default")
   dragElement.style.cursor = "default";
  else if(!isPinned && !isMaximized && styleCursor != "move")
   dragElement.style.cursor = "move";
 },
 StartCollapse: function() {
  this.collapseExecutingLockCount++;
 },
 EndCollapse: function() {
  this.collapseExecutingLockCount--;
 },
 CollapseExecuting: function() {
  return this.collapseExecutingLockCount > 0;
 },
 StartMaximization: function() {
  this.maximizationExecutingLockCount++;
 },
 EndMaximization: function() {
  this.maximizationExecutingLockCount--;
 },
 MaximizationExecuting: function() {
  return this.maximizationExecutingLockCount > 0;
 },
 StartUpdateMaximizedWindowSizeOnResize: function() {
  this.browserResizingForMaxWindowLockCount++;
 },
 EndUpdateMaximizedWindowSizeOnResize: function() {
  this.browserResizingForMaxWindowLockCount--;
 },
 ResizingForMaxWindowLocked: function() {
  return this.browserResizingForMaxWindowLockCount > 0;
 },
 UpdateRestoredWindowSizeLock: function() {
  this.updateRestoredWindowSizeLockCount++;
 },
 UpdateRestoredWindowSizeUnlock: function() {
  this.updateRestoredWindowSizeLockCount--;
 },
 UpdateRestoredWindowSizeLocked: function() {
  return this.updateRestoredWindowSizeLockCount > 0;
 },
 UpdateRestoredWindowSize: function(index, width, height) {
  if(!this.UpdateRestoredWindowSizeLocked()) {
   restoredMinWindowData = this.GetRestoredWindowData(index);
   restoredMinWindowData.width = width;
   restoredMinWindowData.height = height;
   this.SetRestoredWindowData(index, restoredMinWindowData);
  }
 },
 GetWindowsState: function() {
  var state = ASPxClientPopupControlBase.prototype.GetWindowsState.call(this);
  for(var i = 0; i < this.GetWindowCountCore() ; i++) {
   state += this.GetWindowState(i);
   if(i < this.GetWindowCountCore() - 1) state += ";";
  }
  return state;
 },
 CreateWindows: function(windowsNames) {
  for(var i = 0; i < windowsNames.length; i++) {
   var window = new ASPxClientPopupWindow(this, i, windowsNames[i]);
   this.windows.push(window);
  }
 },
 RaiseCloseButtonClick: function(index) {
  ASPxClientPopupControlBase.prototype.RaiseCloseButtonClick.call(this, index);
 },
 RaisePinnedChanged: function(index, pinned) {
  var window = index < 0 ? null : this.GetWindow(index);
  if(!this.PinnedChanged.IsEmpty()) {
   var args = new ASPxClientPopupWindowPinnedChangedEventArgs(window, pinned);
   this.PinnedChanged.FireEvent(this, args);
  }
 },
 RaiseCollapsed: function(index) {
  this.RaiseResize(index, ASPxClientPopupControlResizeState.Collapsed);
 },
 RaiseExpanded: function(index) {
  this.RaiseResize(index, ASPxClientPopupControlResizeState.Expanded);
 },
 RaiseMaximized: function(index) {
  this.RaiseResize(index, ASPxClientPopupControlResizeState.Maximized);
 },
 RaiseRestoredAfterMaximized: function(index) {
  this.RaiseResize(index, ASPxClientPopupControlResizeState.RestoredAfterMaximized);
 },
 GetContentWidth: function() {
  return this.GetWindowContentWidth(null);
 },
 GetContentHeight: function() {
  return this.GetWindowContentHeight(null);
 },
 SetSize: function(width, height) {
  ASPxClientPopupControlBase.prototype.SetSize.call(this, width, height);
 },
 GetWindowDimension: function(window, isWidth, forceFromCache) {
  var index = (window != null) ? window.index : -1;
  return this.GetWindowDimensionByIndex(index, isWidth, forceFromCache);
 },
 GetWindowContentDimension: function(window, isWidth) {
  var index = (window != null) ? window.index : -1,
   contentElem = this.GetWindowContentElement(index),
   dimensionHolder = contentElem.parentNode,
   paddingsHolder = contentElem;
  return isWidth ?
  (dimensionHolder.offsetWidth - this.getLeftRightBordersAndPaddingsSummaryValue(paddingsHolder)) :
  (dimensionHolder.offsetHeight - this.getTopBottomBordersAndPaddingsSummaryValue(paddingsHolder));
 },
 GetWindowContentWidth: function(window) {
  return this.GetWindowContentDimension(window, true);
 },
 GetWindowContentHeight: function(window) {
  return this.GetWindowContentDimension(window, false);
 },
 GetWindowHeight: function(window) {
  return this.GetWindowDimension(window, false);
 },
 GetWindowWidth: function(window) {
  return this.GetWindowDimension(window, true);
 },
 SetWindowSize: function(window, width, height) {
  return ASPxClientPopupControlBase.prototype.SetWindowSize.call(this, window, width, height);
 },
 GetContentHTML: function() {
  return this.GetContentHtml();
 },
 SetContentHTML: function(html) {
  this.SetContentHtml(html);
 },
 SetWindowPopupElementID: function(window, popupElementId) {
  var index = (window != null) ? window.index : -1;
  this.SetPopupElementIDByIndex(index, popupElementId);
 },
 SetPopupElementID: function(popupElementId) {
  this.SetPopupElementIDByIndex(-1, popupElementId);
 },
 GetCurrentPopupElementIndex: function() {
  return this.GetWindowCurrentPopupElementIndexByWindowIndex(-1);
 },
 GetWindowCurrentPopupElementIndex: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetWindowCurrentPopupElementIndexByWindowIndex(index);
 },
 GetCurrentPopupElement: function() {
  return this.GetWindowCurrentPopupElementByIndex(-1);
 },
 GetWindowCurrentPopupElement: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetWindowCurrentPopupElementByIndex(index);
 },
 ShowAtPos: function(x, y) {
  this.ShowWindowAtPos(null, Math.round(x), Math.round(y));
 },
 BringToFront: function() {
  this.BringWindowToFront(null);
 },
 IsWindowVisible: function(window) {
  return ASPxClientPopupControlBase.prototype.IsWindowVisible.call(this, window);
 },
 GetWindow: function(index) {
  return ASPxClientPopupControlBase.prototype.GetWindow.call(this, index);
 },
 GetWindowByName: function(name) {
  for(var i = 0; i < this.windows.length; i++)
   if(this.windows[i].name == name) return this.windows[i];
  return null;
 },
 GetWindowCount: function() {
  return this.GetWindowCountCore();
 },
 ShowWindow: function(window, popupElementIndex) {
  var index = (window != null) ? window.index : -1;
  this.ShowWindowByIndex(index, popupElementIndex);
 },
 ShowWindowAtElement: function(window, htmlElement) {
  var index = (window != null) ? window.index : -1;
  this.ShowWindowAtElementByIndex(index, htmlElement);
 },
 ShowWindowAtElementByID: function(window, id) {
  var htmlElement = document.getElementById(id);
  this.ShowWindowAtElement(window, htmlElement);
 },
 ShowWindowAtPos: function(window, x, y) {
  if(!this.isInitialized)
   return;
  var index = (window != null) ? window.index : -1;
  this.DoShowWindowCore(index, x, y, -1, false, true);
 },
 BringWindowToFront: function(window) {
  var index = (window != null) ? window.index : -1;
  var element = this.GetWindowElement(index);
  aspxGetPopupControlCollection().ActivateWindowElement(element, undefined, this.GetPopupType(), this.GetDefaultZIndexFromServer(), this.GetPopupControlZIndex());
 },
 HideWindow: function(window) {
  ASPxClientPopupControlBase.prototype.HideWindow.call(this, window);
 },
 GetWindowContentHTML: function(window) {
  return this.GetWindowContentHtml(window);
 },
 SetWindowContentHTML: function(window, html) {
  this.SetWindowContentHtml(window, html);
 },
 GetWindowContentHtml: function(window) {
  return ASPxClientPopupControlBase.prototype.GetWindowContentHtml.call(this, window);
 },
 SetWindowContentHtml: function(window, html, useAnimation) {
  ASPxClientPopupControlBase.prototype.SetWindowContentHtml.call(this, window, html, useAnimation);
 },
 AfterSetWindowContentHtml: function(index, contentContainer, useAnimation) {
  if(this.GetAdaptiveModalMode(index))
   this.TryAutoUpdatePosition(index);
  else if(this.InternalIsWindowVisible(index))
   this.RecalculateWindowSize(index);
  ASPxClientPopupControlBase.prototype.AfterSetWindowContentHtml.call(this, index, contentContainer, useAnimation);
  this.UpdateScrollbar(index);
 },
 UpdateAlignment: function(index) {
  if(this.GetIsDragged(index)) return;
  var element = this.GetWindowElement(index),
   wrapperStyle = getComputedStyle(this.GetModalWrapperElement(index)),
   top = ASPxClientPopupControl.AligmentCalculator.CalculateTopMargin(this.modalVerticalAlign, element.offsetHeight, this.GetDefaultVerticalOffset()),
   left = ASPxClientPopupControl.AligmentCalculator.CalculateLeftRightMargin(this.modalHorizontalAlign, ModalAlign.WindowLeft, wrapperStyle.paddingLeft),
   right = ASPxClientPopupControl.AligmentCalculator.CalculateLeftRightMargin(this.modalHorizontalAlign, ModalAlign.WindowRight, wrapperStyle.paddingRight);
  ASPx.SetStyles(element, {
   marginTop: top,
   marginLeft: left,
   marginRight: right
  });
 },
 GetOverlayElement: function(index) {
  return this.GetWindowModalElement(index);
 },
 GetModalWrapperElement: function(index) {
  if(!this.adaptivityEnabled) return null;
  var windowElement = this.GetWindowElement(index);
  return !!windowElement ? windowElement.parentNode : null;
 },
 GetWindowHeightWithoutContent: function(index) {
  var element = this.GetWindowElement(index),
   borderOwner = this.GetWindowBorderOwnerElement(element);
  return this.GetHeaderFooterHeightCore(index) + ASPx.GetVerticalBordersWidth(borderOwner);
 },
 StretchVertically: function() {
  this.StretchVerticallyByIndex(-1, true);
 },
 WindowStretchVertically: function(window) {
  var index = (window != null) ? window.index : -1;
  this.StretchVerticallyByIndex(index, true);
 },
 StretchVerticallyByIndex: function(index, value) {
  if(this.GetStretchVerticallyByIndex(index) !== value) {
   this.SetPropertyValue(index, "stretchVertically", value);
   var oldMinHeight = !!this.GetModalMinHeight(index) ? this.GetModalMinHeight(index) : 0;
   this.SetPropertyValue(index, "modalMinHeight", value ? "100vh" : this.minHeightBackup);
   this.minHeightBackup = oldMinHeight;
   this.UpdateHeightDimensions(index);
  }
 },
 SetAdaptiveMinWidth: function(minWidth) {
  this.SetAdaptiveMinWidthByIndex(-1, minWidth);
 },
 SetWindowAdaptiveMinWidth: function(window, minWidth) {
  var index = (window != null) ? window.index : -1;
  this.SetAdaptiveMinWidthByIndex(index, minWidth);
 },
 SetAdaptiveMaxWidth: function(maxWidth) {
  this.SetAdaptiveMaxWidthByIndex(-1, maxWidth);
 },
 SetWindowAdaptiveMaxWidth: function(window, maxWidth) {
  var index = (window != null) ? window.index : -1;
  this.SetAdaptiveMaxWidthByIndex(index, maxWidth);
 },
 SetAdaptiveMinHeight: function(minHeight) {
  this.SetAdaptiveMinHeightByIndex(-1, minHeight);
 },
 SetWindowAdaptiveMinHeight: function(window, minHeight) {
  var index = (window != null) ? window.index : -1;
  this.SetAdaptiveMinHeightByIndex(index, minHeight);
 },
 SetAdaptiveMaxHeight: function(maxHeight) {
  this.SetAdaptiveMaxHeightByIndex(-1, maxHeight);
 },
 SetWindowAdaptiveMaxHeight: function(window, maxHeight) {
  var index = (window != null) ? window.index : -1;
  this.SetAdaptiveMaxHeightByIndex(index, maxHeight);
 },
 SetAdaptiveHeightDimension: function(index, propertyName, value) {
  value = this.ConvertDimensionValueToString(value);
  value = value.indexOf("%") > -1 ? value.replace("%", "vh") : value;
  var margins = 0;
  if(this.stretchVertically && propertyName === "minHeight")
   margins = ASPx.GetTopBottomMargins(this.GetWindowElement(index));
  var contentElement = this.GetWindowContentElement(index);  
  var iframe = this.GetWindowContentIFrameElement(index);
  var additionalHeight = this.GetWindowHeightWithoutContent(index) + margins;
  var adaptiveHeight = "calc(" + value + " - " + additionalHeight + "px)";
  contentElement.style[propertyName] = adaptiveHeight;
  if (contentElement.style.minHeight) {
   if (iframe || this.HasAnyScrollBars(index))
    contentElement.style.height = "1px";
   else if (propertyName === "minHeight")
    this.SetContentWrapperAdaptiveHeight(index, adaptiveHeight);
  }
  if(iframe) {
   iframe.style.verticalAlign = "text-bottom";
   iframe.style.height = "100%";
  }
 },
 ConvertDimensionValueToString: function(value) {
  if(typeof value === "number")
   return value + "px";
  if(typeof value === "string")
   return value;
 },
 CanBeClosedByClickOnElement: function(index, srcElement, posX, id) {
  return ASPxClientPopupControlBase.prototype.CanBeClosedByClickOnElement.call(this, index, srcElement, posX, id) &&
   (!this.GetAdaptiveModalMode(index) || srcElement != this.GetModalWrapperElement(index) || posX < srcElement.offsetWidth - ASPx.GetVerticalScrollBarWidth());
 },
 SetWindowDisplay: function(index, value) {
  ASPxClientPopupControlBase.prototype.SetWindowDisplay.call(this, index, value);
  if(this.adaptivityEnabled) {
   var wrapper = this.GetModalWrapperElement(index);
   ASPx.SetElementDisplay(wrapper, value);
  }
 },
 HaveSpecialDivForAnimation: function() {
  return ASPxClientPopupControlBase.prototype.HaveSpecialDivForAnimation.call(this) || this.adaptivityEnabled;
 },
 WindowIsModal: function(index) {
  return ASPxClientPopupControlBase.prototype.WindowIsModal.call(this, index) || this.GetAdaptiveModalMode(index);
 },
 RecalculateWindowSize: function(index) {
  var window = this.GetWindowElement(index);
  var displayAfterSetSize = window.style.display;
  this.SetClientWindowSizeCoreLite(index, this.GetWindowWidthInternal(index), this.GetWindowHeightInternal(index), this.GetIsCollapsed(index));
  window.style.display = displayAfterSetSize;
  if(this.HasAnyScrollBars(index))
   this.NormalizeWindowSize(index, this.GetIsMaximized(index));
 },
 GetWindowContentIFrame: function(window) {
  return ASPxClientPopupControlBase.prototype.GetWindowContentIFrame.call(this, window);
 },
 GetWindowContentUrl: function(window) {
  return ASPxClientPopupControlBase.prototype.GetWindowContentUrl.call(this, window);
 },
 SetWindowContentUrl: function(window, url) {
  ASPxClientPopupControlBase.prototype.SetWindowContentUrl.call(this, window, url);
 },
 RefreshDimensionsAfterCreateIframe: function(index) {
  if(ASPx.IsElementVisible(this.GetWindowElement(index), true)) {
   var windowWidth = this.GetWindowDimensionByIndex(index, true, false);
   var windowHeight = this.GetWindowDimensionByIndex(index, false, false);
   this.SetClientWindowSizeCoreLite(index, windowWidth, windowHeight);
  }
 },
 GetPinned: function() {
  return this.GetIsPinned(-1);
 },
 SetPinned: function(value) {
  this.SetPinCore(-1, value);
 },
 GetWindowPinned: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetIsPinned(index);
 },
 SetWindowPinned: function(window, value) {
  var index = (window != null) ? window.index : -1;
  this.SetPinCore(index, value);
 },
 GetMaximized: function() {
  return this.GetIsMaximized(-1);
 },
 SetMaximized: function(value) {
  this.SetMaximizedCore(-1, value);
 },
 GetWindowMaximized: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetIsMaximized(index);
 },
 SetWindowMaximized: function(window, value) {
  var index = (window != null) ? window.index : -1;
  this.SetMaximizedCore(index, value);
 },
 GetCollapsed: function() {
  return this.GetIsCollapsed(-1);
 },
 SetCollapsed: function(value) {
  this.SetCollapsedCore(-1, value);
 },
 GetWindowCollapsed: function(window) {
  var index = (window != null) ? window.index : -1;
  return this.GetIsCollapsed(index);
 },
 SetWindowCollapsed: function(window, value) {
  var index = (window != null) ? window.index : -1;
  this.SetCollapsedCore(index, value);
 },
 RefreshWindowContentUrl: function(window) {
  ASPxClientPopupControlBase.prototype.RefreshWindowContentUrl.call(this, window);
 },
 SetWindowContentVisible: function(index, visible) {
  var contentElement = this.GetWindowContentWrapperElement(index);
  if(contentElement)
   this.SetWindowPartVisibleCore(contentElement, "DXPopupWindowContentDisplay", visible);
 },
 SetWindowFooterVisible: function(index, visible) {
  var footerElement = this.GetWindowFooterElement(index);
  if(footerElement)
   this.SetWindowPartVisibleCore(footerElement, "DXPopupWindowFooterDisplay", visible);
 },
 SetWindowPartVisibleCore: function(partElement, displayCacheName, visible) {
  var nothingChanged = ASPx.IsElementVisible(partElement) && visible;
  if(nothingChanged) return;
  if(!(ASPx.IsExists(partElement[displayCacheName])))
   partElement[displayCacheName] = partElement.style.display;
  partElement.style.display = visible ? partElement[displayCacheName] : 'none';
 },
 UpdatePosition: function() {
  this.UpdatePositionAtElement(this.GetPopupElement(-1, this.GetLastShownPopupElementIndex(-1)));
 },
 UpdatePositionAtElement: function(popupElement) {
  ASPxClientPopupControlBase.prototype.UpdatePositionAtElement.call(this, popupElement);
 },
 UpdateWindowPosition: function(window) {
  var index = (window != null) ? window.index : -1;
  this.UpdateWindowPositionAtElement(window, this.GetPopupElement(index, this.GetLastShownPopupElementIndex(index)));
 },
 UpdateWindowPositionAtElement: function(window, popupElement) {
  ASPxClientPopupControlBase.prototype.UpdateWindowPositionAtElement.call(this, window, popupElement);
 },
 UpdateWindowPositionInternal: function(index, popupElement) {
  if(this.GetAdaptiveModalMode(index)) {
   this.TryAutoUpdatePosition(index);
   return;
  }
  if(!ASPxClientPopupControlBase.prototype.UpdateWindowPositionInternal.call(this, index, popupElement))
   this.DoShowWindowAtPos(index, ASPx.InvalidDimension, ASPx.InvalidDimension, this.GetLastShownPopupElementIndex(index), false, false);
 },
 UpdateMode: function(index) {
  if(!this.adaptivityEnabled) return;
  var currentMode = this.GetAdaptiveModalMode(index),
   newMode = this.NeedAdaptiveModalMode(index);
  if(currentMode != newMode) {
   this.SetAdaptiveModalMode(index, newMode);
   if(!newMode && !ASPx.Browser.WebKitTouchUI) {
    var element = this.GetWindowElement(index);
    ASPx.PopupUtils.BodyScrollHelper.RestoreBodyScroll(element.id);
   }
   this.ShowWindowByIndex(-1);
   this.RaiseAdaptiveModeChanged();
  }
 },
 RaiseAdaptiveModeChanged: function() {
  if(!this.AdaptiveModeChanged.IsEmpty()) {
   var args = new ASPxClientEventArgs();
   this.AdaptiveModeChanged.FireEvent(this, args);
  }
 },
 TryAutoUpdatePosition: function(index) {
  this.UpdateMode(index);
  ASPxClientPopupControlBase.prototype.TryAutoUpdatePosition.call(this, index);
  if(this.GetAdaptiveModalMode(index)) {
   this.CorrectScrollPositionOnAndroid(index, false);
   this.ResetWebkitScrolling(this.GetModalWrapperElement(index), 100);
   this.UpdateHeightDimensions(index);
   this.ChangeHeaderFixed(index);
   this.UpdateAlignment(index);
   this.ChangeFooterFixed(index);
   if(this.GetIsDragged(index) &&
    ASPxClientPopupControl.WindowResizeHelper.AdjustModalOnWindowResize(this.GetWindowElement(index)))
    this.SetIsDragged(index, false);
  }
  if(this.GetIsMaximized(index)) {
   this.CorrectScrollPositionOnAndroid(index, true);
   this.UpdateMaximizedWindowSizeOnResize(index);
  }
 },
 CorrectScrollPositionOnAndroid: function(index, checkElementIsInPopup) {
  if(ASPx.Browser.AndroidMobilePlatform) {
   var activeElement = this.GetActiveElementIncludingIframes();
   if(activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA") &&
    (!checkElementIsInPopup || this.GetWindowElement(index).contains(activeElement)))
    window.setTimeout(function() {
     if(activeElement.scrollIntoViewIfNeeded)
      activeElement.scrollIntoViewIfNeeded();
    }, 100);
  }
 },
 GetActiveElementIncludingIframes: function(document) {
  document = document || window.document;
  if(document.body === document.activeElement || document.activeElement.tagName === "IFRAME") {
   var iframes = document.getElementsByTagName("iframe");
   for(var i = 0; i < iframes.length; i++) {
    var iFrameDocument = null;
    try {
     iFrameDocument = iframes[i].contentWindow.document;
    }
    catch(e) {  }
    if(iFrameDocument !== null) {
     var focused = this.GetActiveElementIncludingIframes(iframes[i].contentWindow.document);
     if(focused !== false) {
      return focused;
     }
    }
   }
  } else 
   return document.activeElement;
  return false;
 },
 OnModalWrapperScroll: function(e, index) {
  if(!this.GetAdaptiveModalMode(index) || this.IsWrapperScrollEventLocked()) return;
  this.ChangeHeaderFixed(index);
  this.ChangeFooterFixed(index);
 },
 OnModalWrapperTouchStart: function(e) {
  this.touchStartY = e.touches[0].clientY;
 },
 OnModalWrapperTouchMove: function (e, index) {
  if(e.touches.length > 1)
   return;
  var preventScroll = this.RequirePreventScrollForAdaptiveMode(e, index);
  if(preventScroll)
   ASPx.Evt.PreventEvent(e);
  this.touchStartY = e.touches[0].clientY;
 },
 RequirePreventScrollForAdaptiveMode: function(e, index) {
  var modalWrapper = this.GetModalWrapperElement(index),
   zoom = modalWrapper.offsetWidth / window.innerWidth,
   activeElement = document.activeElement,
   activeTyping = !!activeElement && (activeElement["type"] === "text" || activeElement["type"] === "textarea"); 
  if(zoom !== 1 || activeTyping)
   return false;
  var currentY = e.touches[0].clientY,
   preventScroll = currentY > this.touchStartY && modalWrapper.scrollTop === 0 ||
    currentY < this.touchStartY && modalWrapper.scrollTop + modalWrapper.clientHeight >= modalWrapper.scrollHeight;
  if(!preventScroll)
   return false;
  var targetElement = ASPx.Evt.GetEventSource(e),
   contentWrapper = this.GetWindowContentWrapperElement(index);
  while(targetElement && targetElement !== contentWrapper && targetElement.tagName !== 'BODY') {
   if(this.ElementHasScroll(targetElement))
    return false;
   targetElement = targetElement.parentNode;
  }
  return true;
 },
 ElementHasScroll: function(elem) {
  var style = window.getComputedStyle(elem);
  return ["overflow", "overflow-x", "overflow-y"].some(function(prop) {
   return ASPx.Data.ArrayContains(["scroll","auto"], style[prop]);
  });
 },
 GetFixedHeaderMaxBottom: function(index) {
  var contentWrapper = this.GetWindowContentWrapperElement(index);
  return ASPx.GetAbsolutePositionY(contentWrapper) + contentWrapper.offsetHeight;
 },
 GetFixedFooterMaxTop: function(index) {
  var header = this.GetWindowHeaderElement(index),
   contentWrapper = this.GetWindowContentWrapperElement(index),
   headerBottom = !!header ? ASPx.GetAbsolutePositionY(header) + header.offsetHeight : ASPx.GetAbsolutePositionY(contentWrapper);
  return window.innerHeight - headerBottom;
 },
 ChangeHeaderFixed: function(index) {
  if(!this.GetFixedHeader(index)) return;
  var element = this.GetWindowElement(index),
   modalWrapper = this.GetModalWrapperElement(index),
   isHeaderPartiallyHidden = modalWrapper.scrollTop > element.offsetTop,
   maxBottom = isHeaderPartiallyHidden ? this.GetFixedHeaderMaxBottom(index) : 0;
  this.FixateHeader(index, isHeaderPartiallyHidden, maxBottom);
 },
 ChangeFooterFixed: function(index) {
  if(!this.GetFixedFooter(index) || !this.GetWindowFooterElement(index)) return;
  var element = this.GetWindowElement(index),
   modalWrapper = this.GetModalWrapperElement(index),
   isFooterPartiallyHidden = element.offsetTop + element.offsetHeight - modalWrapper.scrollTop > window.innerHeight,
   maxTop = isFooterPartiallyHidden ? this.GetFixedFooterMaxTop(index) : 0;
  this.FixateFooter(index, isFooterPartiallyHidden, maxTop);
 },
 ChangeHeaderFooterFixed: function(index, elementToFix, isFixed, fixedClassName, offsetName, maxPos) {
  if(!elementToFix) return;
  var element = this.GetWindowElement(index),
   contentWrapper = this.GetWindowContentWrapperElement(index),
   changeClassNameFunc = isFixed ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement,
   elementToFixHeight = elementToFix.offsetHeight;
  if(isFixed) {
   var borderOwner = this.GetWindowBorderOwnerElement(element),
    width = ASPx.GetClearClientWidth(borderOwner);
   ASPx.SetOffsetWidth(elementToFix, width);
   elementToFix.style[offsetName] = maxPos < elementToFixHeight ? maxPos - elementToFixHeight + "px" : "";
  } else
   elementToFix.style.width = "";
  contentWrapper.style["margin-" + offsetName] = isFixed ? elementToFixHeight + "px" : 0;
  changeClassNameFunc(elementToFix, fixedClassName);
 },
 FixateFooter: function(index, isFixed, maxTop) {
  this.ChangeHeaderFooterFixed(index, this.GetWindowFooterElement(index), isFixed, "dxFixedFooter", "bottom", maxTop);
 },
 FixateHeader: function(index, isFixed, maxBottom) {
  this.ChangeHeaderFooterFixed(index, this.GetWindowHeaderElement(index), isFixed, "dxFixedHeader", "top", maxBottom);
 },
 LockWrapperScrollEvent: function() {
  this.wrapperScrollEventLocked = true;
 },
 UnlockWrapperScrollEventEvent: function() {
  this.wrapperScrollEventLocked = false;
 },
 IsWrapperScrollEventLocked: function() {
  return this.wrapperScrollEventLocked;
 },
 ResetScroll: function(index) {
  if(!this.GetAdaptiveModalMode(index)) return;
  this.LockWrapperScrollEvent();
  this.GetModalWrapperElement(index).scrollTop = 0;
  this.UnlockWrapperScrollEventEvent();
 },
 AdjustModalElementBounds: function(element) {
  if(!ASPx.IsExistsElement(element)) return;
  ASPx.SetStyles(element, {
   left: 0,
   top: 0,
   right: 0,
   bottom: 0,
   width: "",
   height: ""
  });
 },
 RefreshPopupElementConnection: function() {
  ASPxClientPopupControlBase.prototype.RefreshPopupElementConnection.call(this);
 }
});
ASPxClientPopupControl.AligmentCalculator = (function() {
 function CalculateTopMargin(verticalAlign, elementHeight, defaultOffset) {
  if(verticalAlign === ModalAlign.WindowTop)
   return "";
  if(elementHeight < window.innerHeight) {
   var freeSpace = window.innerHeight - elementHeight;
   switch(verticalAlign) {
    case ModalAlign.WindowCenter:
     return freeSpace / 2;
    case ModalAlign.WindowBottom:
     return freeSpace - defaultOffset;
   }
  }
  return "";
 }
 function CalculateLeftRightMargin(horizontalAlign, forAligmenment, wrapperPadding) {
  if(horizontalAlign === forAligmenment) {
   if(ASPx.PxToInt(wrapperPadding) !== 0)
    return 0;
   return 10;
  }
  return "";
 }
 return {
  CalculateTopMargin: CalculateTopMargin,
  CalculateLeftRightMargin: CalculateLeftRightMargin
 };
})();
ASPxClientPopupControl.Animation = (function() {
 function GetVerticalDirection(verticalAlign, horizontalAlign) {
  switch(verticalAlign) {
   case ModalAlign.WindowTop:
    return -1;
   case ModalAlign.WindowCenter:
    if(horizontalAlign === ModalAlign.WindowCenter)
     return -1;
    return 0;
   case ModalAlign.WindowBottom:
    return 1;
  }
 }
 function GetHorizontalDirection(horizontalAlign) {
  switch(horizontalAlign) {
   case ModalAlign.WindowLeft:
    return -1;
   case ModalAlign.WindowCenter:
    return 0;
   case ModalAlign.WindowRight:
    return 1;
  }
 }
 function NeedFadeAnimation(horizontalAlign, verticalAlign, animationType, popupHorizontalAlign, popupVerticalAlign, adaptiveModalMode) {
  if(animationType === ASPxClientPopupControlBase.AnimationType.Auto) {
   if(adaptiveModalMode)
    return horizontalAlign === ModalAlign.WindowCenter && verticalAlign === ModalAlign.WindowCenter;
   else
    return popupHorizontalAlign === ASPx.PopupUtils.WindowCenterAlignIndicator && popupVerticalAlign === ASPx.PopupUtils.WindowCenterAlignIndicator;
  }
  return false;
 }
 return {
  GetVerticalDirection: GetVerticalDirection,
  GetHorizontalDirection: GetHorizontalDirection,
  NeedFadeAnimation: NeedFadeAnimation
 };
})();
ASPxClientPopupControl.WindowResizeHelper = (function() {
 var previousInnerWidth = 0,
  previousMargin = 0;
 function AdjustModalOnWindowResize(element) {
  var offsetLeft = element.offsetLeft,
   offsetWidth = element.offsetWidth,
   windowWidth = window.innerWidth,
   expectedLeft = windowWidth / 2 - offsetWidth / 2,
   toTheRightOfCenter = offsetLeft > expectedLeft,
   dw = windowWidth - previousInnerWidth,
   computedStyle = getComputedStyle(element),
   left = ASPx.PxToFloat(computedStyle.left),
   currentMargin = ASPx.PxToFloat(computedStyle.marginLeft),
   dm = currentMargin - previousMargin,
   newLeft = left - dm;
  if(toTheRightOfCenter)
   newLeft += dw;
  ASPx.SetStyles(element, { left: newLeft + "px" });
  if(Math.abs(offsetLeft - expectedLeft) <= 10 || dw < 0 && toTheRightOfCenter !== (element.offsetLeft > expectedLeft)) {
   ASPx.SetStyles(element, { left: "" });
   ASPx.Attr.RestoreStyleAttribute(element, "top");
   ASPx.Attr.RestoreStyleAttribute(element, "margin-top");
   return true;
  }
  previousMargin = currentMargin;
  previousInnerWidth = windowWidth;
  return false;
 }
 function Initialize(element) {
  previousInnerWidth = window.innerWidth;
  ASPx.Attr.ChangeStyleAttribute(element, "top", element.offsetTop + "px");
  ASPx.Attr.ChangeStyleAttribute(element, "margin-top", "0");
  previousMargin = ASPx.PxToFloat(getComputedStyle(element).marginLeft);
 }
 return {
  Initialize: Initialize,
  AdjustModalOnWindowResize: AdjustModalOnWindowResize
 };
})();
ASPxClientPopupControl.Cast = ASPxClientControl.Cast;
ASPxClientPopupControl.GetPopupControlCollection = function() {
 return aspxGetPopupControlCollection();
};
var ASPxClientPopupWindow = ASPx.CreateClass(null, {
 constructor: function(popupControl, index, name) {
  this.popupControl = popupControl;
  this.index = index;
  this.name = name;
 },
 GetHeaderImageUrl: function() {
  return this.popupControl.GetWindowHeaderImageUrl(this.index);
 },
 SetHeaderImageUrl: function(value) {
  this.popupControl.SetWindowHeaderImageUrl(this.index, value);
 },
 GetFooterImageUrl: function() {
  return this.popupControl.GetWindowFooterImageUrl(this.index);
 },
 SetFooterImageUrl: function(value) {
  this.popupControl.SetWindowFooterImageUrl(this.index, value);
 },
 GetHeaderNavigateUrl: function() {
  return this.popupControl.GetWindowHeaderNavigateUrl(this.index);
 },
 SetHeaderNavigateUrl: function(value) {
  this.popupControl.SetWindowHeaderNavigateUrl(this.index, value);
 },
 GetFooterNavigateUrl: function() {
  return this.popupControl.GetWindowFooterNavigateUrl(this.index);
 },
 SetFooterNavigateUrl: function(value) {
  this.popupControl.SetWindowFooterNavigateUrl(this.index, value);
 },
 GetHeaderText: function() {
  return this.popupControl.GetWindowHeaderText(this.index);
 },
 SetHeaderText: function(value) {
  this.popupControl.SetWindowHeaderText(this.index, value);
 },
 GetFooterText: function() {
  return this.popupControl.GetWindowFooterText(this.index);
 },
 SetFooterText: function(value) {
  this.popupControl.SetWindowFooterText(this.index, value);
 }
});
var ASPxClientPopupWindowEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(window) {
  this.constructor.prototype.constructor.call(this);
  this.window = window;
 }
});
var ASPxClientPopupWindowCancelEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(window, closeReason) {
  this.constructor.prototype.constructor.call(this);
  this.window = window;
  this.closeReason = closeReason;
 }
});
var ASPxClientPopupWindowCloseUpEventArgs = ASPx.CreateClass(ASPxClientPopupWindowEventArgs, {
 constructor: function(window, closeReason) {
  this.constructor.prototype.constructor.call(this, window);
  this.closeReason = closeReason;
 }
});
var ASPxClientPopupWindowResizeEventArgs = ASPx.CreateClass(ASPxClientPopupWindowEventArgs, {
 constructor: function(window, resizeState) {
  this.constructor.prototype.constructor.call(this, window);
  this.resizeState = resizeState;
 }
});
var ASPxClientPopupWindowPinnedChangedEventArgs = ASPx.CreateClass(ASPxClientPopupWindowEventArgs, {
 constructor: function(window, pinned) {
  this.constructor.prototype.constructor.call(this, window);
  this.pinned = pinned;
 }
});
var ASPxClientPopupControlCollection = ASPx.CreateClass(ASPxClientControlCollection, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
  this.draggingControl = null;
  this.draggingWindowIndex = -1;
  this.gragXOffset = 0;
  this.gragYOffset = 0;
  this.visibleModalElements = [];
  this.visiblePopupWindowIds = [];
  this.windowResizeByBodyScrollVisibilityChangingLockCount = 0;
  this.savedBodyWidth = 0;
  this.savedBodyHeight = 0;
  this.overControl = null;
  this.overWindowIndex = -1;
  this.overXPos = ASPx.InvalidPosition;
  this.overYPos = ASPx.InvalidPosition;
  this.appearTimerID = -1;
  this.disappearTimerID = -1;
  this.scrollEventLockCount = 0;
  this.currentActiveWindowElement = null;
  this.resizeControl = null;
  this.resizeIndex = -2;
  this.resizeCursor = "";
  this.resizePanel = null;
  this.selectBanned = false;
  this.pcWindowsAreRestrictedByDocumentWindow = true;
  this.docScrollLeft = -1;
  this.docScrollTop = -1;
  this.EnsureSaveScrollState();
 },
 GetCollectionType: function(){
  return "Popup";
 },
 Remove: function(popupControl) {
  for(var i = this.visibleModalElements.length - 1; i >= 0; i--) {
   var modalElement = this.visibleModalElements[i];
   if(modalElement && modalElement.DXModalPopupControl === popupControl)
    this.UnregisterVisibleModalElement(modalElement);
  }
  for(var j = this.visiblePopupWindowIds.length - 1; j >= 0; j--) {
   var id = this.visiblePopupWindowIds[j];
   if(!ASPx.IsExists(id)) continue;
   var popupWindow = this.GetPopupWindowFromID(id);
   if(popupWindow.popupControl === popupControl) {
    var windowElement = popupControl.GetWindowElement(popupWindow.windowIndex);
    if(windowElement)
     this.UnregisterVisibleWindow(windowElement);
    else
     ASPx.Data.ArrayRemove(this.visiblePopupWindowIds, id);
   }
  }
  ASPxClientControlCollection.prototype.Remove.call(this, popupControl);
 },
 EnsureSaveScrollState: function() {
  if(ASPx.documentLoaded && this.docScrollLeft < 0 && this.docScrollTop < 0)
   this.SaveScrollState();
 },
 GetPopupWindowFromID: function(id) {
  var pos = id.lastIndexOf(ASPx.PCWIdSuffix);
  var name = id.substring(0, pos);
  var index = id.substr(pos + ASPx.PCWIdSuffix.length);
  var popupControl = aspxGetPopupControlCollection().Get(name);
  return { popupControl: popupControl, windowIndex: index };
 },
 DoHideAllWindows: function(srcElement, excptId, applyToAll, closeReason, posX) {
  for(var i = this.visiblePopupWindowIds.length - 1; i >= 0; i--) {
   var id = this.visiblePopupWindowIds[i];
   if(id == excptId) continue;
   var popupWindow = this.GetPopupWindowFromID(id),
    windowIndex = popupWindow.windowIndex,
    popupControl = popupWindow.popupControl;
   if(!popupControl.CanBeClosedByClickOnElement(windowIndex, srcElement, posX, id)) continue;
   if(popupControl != null) {
    var popupWindowZIndexArray = ASPx.PopupUtils.GetElementZIndexArray(popupControl.GetWindowElement(windowIndex));
    var isPopupHigherSrcElement = ASPx.PopupUtils.IsHigher(popupWindowZIndexArray, ASPx.PopupUtils.GetElementZIndexArray(srcElement)) || !popupControl.HasDefaultWindow();
    var windowCloseAction = popupControl.GetWindowCloseAction(windowIndex);
    if ((windowCloseAction != "CloseButton" && windowCloseAction != "None") && isPopupHigherSrcElement || applyToAll)
     popupControl.DoHideWindow(parseInt(windowIndex), false, closeReason);
   }
  }
 },
 DoShowAtCurrentPos: function(name, index, popupElementIndex, evtClone) {
  var pc = this.Get(name);
  if(pc != null && !pc.InternalIsWindowVisible(index))
   pc.DoShowWindowCore(index, this.overXPos, this.overYPos, popupElementIndex, true, true, evtClone, ASPxClientPopupControlCloseReason.MouseOut);
 },
 WindowZIndexWasInitialized: function(zIndex, pcZIndex) {
  return pcZIndex <= zIndex;
 },
 ActivateWindowElement: function(element, evt, popupType, defZIndex, zIndex) {
  var maxZIndex = this.GetMaxZIndex(popupType, defZIndex),
   topZIndex = this.WindowZIndexWasInitialized(maxZIndex, zIndex) ? parseInt(maxZIndex) : zIndex;
  if(this.WindowZIndexWasInitialized(element.style.zIndex, zIndex) && element.style.zIndex != topZIndex) {
   this.DeleteWindowFromZIndexOrder(element);
  }
  if(!this.WindowZIndexWasInitialized(element.style.zIndex, zIndex))
   topZIndex += 2;
  var popupWindow = this.GetPopupWindowFromID(element.id);
  popupWindow.popupControl.SetWindowElementZIndex(element, topZIndex);
  var pcWElementEventSource = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupWindowElement);
  if(!evt || (evt && pcWElementEventSource == element)) { 
   if(this.GetCurrentActiveWindowElement() != element) {
    this.RefreshTabIndexes(false);
    this.SaveCurrentActiveWindowElement(element);
   }
  }
 },
 RefreshTabIndexes: function(forceRecalculate) {
  var topModalWindow = this.GetTopModalWindow();
  if(topModalWindow != null || forceRecalculate) {
   var topModalWindowZIndexArray = ASPx.PopupUtils.GetElementZIndexArray(topModalWindow);
   this.CalculateTabIndexes(topModalWindowZIndexArray);
  }
 },
 ElementHasTabIndex: function(element) {
  return ASPx.IsExists(ASPx.Attr.GetAttribute(element, "tabindex"));
 },
 IsElementCanBeActive: function(element) { 
  return element.tagName === "INPUT" || element.tagName === "A" ||
   element.tagName === "BUTTON" || element.tagName === "TEXTAREA" ||
   element.tagName === "SELECT" || this.ElementHasTabIndex(element);
 },
 GetCanBeActiveElements: function() { 
  var elements = document.getElementsByTagName("*"),
   canBeActiveElements = [];
  for(var i = 0; i < elements.length; i++) {
   if(this.IsElementCanBeActive(elements[i]))
    canBeActiveElements.push(elements[i]);
  }
  return canBeActiveElements;
 },
 GetEditableDivs: function(){
  if(document.querySelectorAll)
   return document.querySelectorAll("div[contenteditable=true]");
  var editableDivs = [ ];
  var allDivs = document.getElementsByTagName("DIV");
  for(var i = 0; i < allDivs.length; i++){
   var div = allDivs[i];
   if(div.getAttribute("contenteditable") == 'true')
    editableDivs.push(div);
  }
  return editableDivs;
 },
 CalculateTabIndexes: function(topModalWindowZIndexArray) {
  var elements = this.GetCanBeActiveElements();
  for(var i = 0; i < elements.length; i++) {
   var currentElementZIndexArray = ASPx.PopupUtils.GetElementZIndexArray(elements[i]),
    manager = ASPx.ControlTabIndexManager.getInstance(),
    tabIndexManagerGroupId = "pcCollection";
   if(ASPx.PopupUtils.IsHigher(currentElementZIndexArray, topModalWindowZIndexArray))
    manager.restoreTabIndexAttribute(elements[i], tabIndexManagerGroupId);
   else
    manager.changeTabIndexAttribute(elements[i], tabIndexManagerGroupId);
  }
 },
 PopupWindowIsModalByVisibleIndex: function(visiblePopupWindowIndex) {
  return this.PopupWindowIsModalByID(this.visiblePopupWindowIds[visiblePopupWindowIndex]);
 },
 PopupWindowIsModalByID: function(windowElementID) {
  var popupWindow = this.GetPopupWindowFromID(windowElementID);
  return popupWindow.popupControl.WindowIsModal(popupWindow.windowIndex);
 },
 SaveCurrentActiveWindowElement: function(windowElement) {
  this.currentActiveWindowElement = windowElement;
 },
 SkipCurrentActiveWindowElement: function(element) {
  if(element == this.GetCurrentActiveWindowElement())
   this.SaveCurrentActiveWindowElement(null);
 },
 GetCurrentActiveWindowElement: function() {
  return this.currentActiveWindowElement;
 },
 GetMaxZIndex: function (type, defaultZIndex) {
  var maxZIndex = defaultZIndex;
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var id = this.visiblePopupWindowIds[i];
   if(type !== undefined && this.GetPopupWindowFromID(id).popupControl.GetPopupType() !== type)
    continue;
   var currentWindow = ASPx.GetElementById(id);
   if(!!currentWindow && ASPx.IsElementVisible(currentWindow) && currentWindow.style && currentWindow.style.zIndex > maxZIndex)
    maxZIndex = currentWindow.style.zIndex;
  }
  return maxZIndex;
 },
 GetTopModalWindow: function() {
  return this.GetTopWindow(true);
 },
 GetTopWindow: function(onlyModal) {
  var topWindow = null;
  var topWindowZIndexArray = null;
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var currentWindow = ASPx.GetElementById(this.visiblePopupWindowIds[i]);
   if(onlyModal && !this.PopupWindowIsModalByVisibleIndex(i))
    continue;
   if(ASPx.IsElementVisible(currentWindow)) {
    var currentWindowZIndexArray = ASPx.PopupUtils.GetElementZIndexArray(currentWindow);
    if(topWindow == null || ASPx.PopupUtils.IsHigher(currentWindowZIndexArray, topWindowZIndexArray)) {
     topWindow = currentWindow;
     topWindowZIndexArray = currentWindowZIndexArray;
    }
   }
  }
  return topWindow;
 },
 DeleteWindowFromZIndexOrder: function(element) {
  for(var i = this.visiblePopupWindowIds.length - 1; i >= 0; i--) {
   var windowElement = ASPx.GetElementById(this.visiblePopupWindowIds[i]);
   if(!windowElement)
    ASPx.Data.ArrayRemoveAt(this.visiblePopupWindowIds, i);
   else if(windowElement.style.zIndex > element.style.zIndex) {
    var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
    popupWindow.popupControl.SetWindowElementZIndex(windowElement, windowElement.style.zIndex - 2);
   }
  }
 },
 AdjustModalElementsBounds: function() {
  for(var i = 0; i < this.visibleModalElements.length; i++)
   this.visibleModalElements[i].DXModalPopupControl.AdjustModalElementBounds(this.visibleModalElements[i]);
 },
 ClearAppearTimer: function() {
  this.appearTimerID = ASPx.Timer.ClearTimer(this.appearTimerID);
 },
 ClearDisappearTimer: function() {
  this.disappearTimerID = ASPx.Timer.ClearTimer(this.disappearTimerID);
 },
 IsAppearTimerActive: function() {
  return this.appearTimerID > -1;
 },
 IsDisappearTimerActive: function() {
  return this.disappearTimerID > -1;
 },
 SetAppearTimer: function(name, index, popupElementIndex, timeout, evt) {
  var evtClone = ASPx.CloneObject(evt);
  this.appearTimerID = window.setTimeout(function() {
   aspxGetPopupControlCollection().DoShowAtCurrentPos(name, index, popupElementIndex, evtClone);
  }, timeout);
 },
 SetDisappearTimer: function(name, index, timeout) {
  this.disappearTimerID = window.setTimeout(function() {
   aspxGetPopupControlCollection().OnPWDisappearTimer(name, index);
  }, timeout);
 },
 GetDocScrollDifference: function() {
  return new _aspxScrollDifference(ASPx.GetDocumentScrollLeft() - this.docScrollLeft, ASPx.GetDocumentScrollTop() - this.docScrollTop);
 },
 IsDocScrolled: function(scroll) {
  return scroll.horizontal != 0 || scroll.vertical != 0;
 },
 SaveScrollState: function() {
  this.docScrollLeft = ASPx.GetDocumentScrollLeft();
  this.docScrollTop = ASPx.GetDocumentScrollTop();
 },
 InitDragObject: function(control, index, x, y, xClientCorrection, yClientCorrection) {
  this.draggingControl = control;
  this.draggingWindowIndex = index;
  this.gragXOffset = x;
  this.gragYOffset = y;
  this.xClientCorrection = xClientCorrection;
  this.yClientCorrection = yClientCorrection;
  this.SetDocumentSelectionBan(true);
 },
 InitOverObject: function(control, index, evt) {
  this.overControl = control;
  this.overWindowIndex = index;
  if(evt)
   this.SaveCurrentMouseOverPos(evt);
 },
 InitResizeObject: function(control, index, cursor, resizePanel) {
  this.resizeControl = control;
  this.resizeIndex = index;
  this.resizeCursor = cursor;
  this.resizePanel = resizePanel;
  this.SetDocumentSelectionBan(true);
 },
 SetDocumentSelectionBan: function(value) {
  if(this.selectBanned === value)
   return;
  this.selectBanned = value;
  if(ASPx.Browser.WebKitFamily) {
   if(value) {
    if(!this.webkitUserSelectBackup && document.body.style.webkitUserSelect)
     this.webkitUserSelectBackup = document.body.style.webkitUserSelect;
    document.body.style.webkitUserSelect = "none";
   } else {
    if(this.webkitUserSelectBackup) {
     document.body.style.webkitUserSelect = this.webkitUserSelectBackup;
     delete this.webkitUserSelectBackup;
    } else
     document.body.style.webkitUserSelect = "auto";
   }
  }
 },
 IsResizeInint: function() {
  return this.resizeControl != null;
 },
 ClearDragObject: function() {
  this.draggingControl = null;
  this.draggingWindowIndex = -1;
  this.gragXOffset = 0;
  this.gragYOffset = 0;
  this.SetDocumentSelectionBan(this.resizeControl != null);
 },
 ClearResizeObject: function() {
  this.resizeControl = null;
  this.resizeIndex = -2;
  this.resizeCursor = "";
  this.SetDocumentSelectionBan(this.draggingControl != null);
  this.resizePanel.parentNode.removeChild(this.resizePanel);
 },
 Drag: function(evt) {
  if(ASPx.tableColumnResizing || ASPx.currentDragHelper || !ASPx.Evt.IsLeftButtonPressed(evt)) return;
  var x = ASPx.Evt.GetEventX(evt);
  var y = ASPx.Evt.GetEventY(evt);
  if(this.pcWindowsAreRestrictedByDocumentWindow && ASPx.PopupUtils.CoordinatesInDocumentRect(x, y)) {
   x += this.gragXOffset;
   y += this.gragYOffset;
   this.draggingControl.OnDrag(this.draggingWindowIndex, x, y, this.xClientCorrection, this.yClientCorrection, evt);
   if(ASPx.Browser.WebKitTouchUI)
    ASPx.Evt.PreventEvent(evt);
  }
 },
 DragStop: function() {
  this.draggingControl.OnDragStop(this.draggingWindowIndex);
  this.ClearDragObject();
 },
 ResizeStop: function(evt) {
  this.resizeControl.OnResizeStop(evt, this.resizeIndex, this.resizeCursor, this.resizePanel);
  aspxGetPopupControlCollection().ClearResizeObject();
 },
 setIframesMouseMoveEnabled: function(enabled) {
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
   var popupControl = popupWindow.popupControl;
   if(popupControl) {
    var iframe = popupControl.GetWindowContentIFrameElement(popupWindow.windowIndex);
    if(iframe)
     iframe.style.pointerEvents = enabled ? "" : "none";
   }
  }
 },
 OnPWMouseMove: function(evt, name, index) {
  if(this.draggingControl == null &&
   this.overControl == null &&
   this.resizeControl == null) {
   var pc = aspxGetPopupControlCollection().Get(name);
   if(pc != null) pc.OnMouseMove(evt, index);
  }
 },
 OnPWMouseOver: function(evt) {
  if(!this.overControl || this.draggingControl) return;
  if(this.IsOverPopupWindow(evt))
   this.ClearDisappearTimer();
 },
 IsOverPopupWindow: function(evt) {
  return ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupControlOverElement) != null;
 },
 OnDocumentKeyDown: function(evt) {
  var windowElement = this.GetTopWindow(false);
  if(windowElement) {
   var window = this.GetPopupWindowFromID(windowElement.id);
   if(window.popupControl);
    window.popupControl.OnDocumentKeyDown(evt, windowElement);
  }
 },
 OnDocumentMouseDown: function(evt) {
  var popupElement = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupControlElement);
  var excptId = popupElement == null ? "" :
   popupElement.DXPopupElementControl.GetWindowElementId(popupElement.DXPopupWindowIndex);
  this.OnMouseDownCore(evt, excptId);
 },
 OnMouseDown: function(evt) {
  this.OnMouseDownCore(evt, "");
 },
 OnMouseDownCore: function(evt, excptId) {
  var srcElement = ASPx.Evt.GetEventSource(evt);
  this.DoHideAllWindows(srcElement, excptId, false, ASPxClientPopupControlCloseReason.OuterMouseClick, ASPx.Evt.GetEventX(evt));
  aspxGetPopupControlCollection().ClearAppearTimer();
 },
 OnMouseMove: function (evt) {
  if(ASPx.Browser.WebKitTouchUI && ASPx.TouchUIHelper.isGesture)
   return;
  if(this.draggingControl != null) {
   this.Drag(evt);
  }
  else if(this.overControl != null) {
   this.OnMouseOver(evt);
  }
  else if(this.resizeControl != null) {
   this.resizeControl.OnResize(evt, this.resizeIndex, this.resizeCursor, this.resizePanel);
  }
 },
 OnMouseOver: function(evt) {
  var element = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupControlOverElement);
  var curPopupElement = this.overControl.GetWindowCurrentPopupElementByIndex(this.overWindowIndex);
  var popup = element != null ? element.DXPopupElementControl : null;
  var isPopupActionMouseOver = popup && popup.GetWindowPopupAction(this.overWindowIndex) == 'MouseOver';
  var isCurPopupElement = element !== null && element === curPopupElement;
  var isCurPopupWindow = element != null && element.id === this.overControl.GetWindowElementId(this.overWindowIndex);
  var isCurPopupElementOrCurPopupWindow = isCurPopupElement || isCurPopupWindow || isPopupActionMouseOver;
  if(isCurPopupElementOrCurPopupWindow) {
   var clearTimer = true;
   popup = element.DXPopupElementControl;
   if(popup && popup.GetLastShownPopupElementIndex(element.DXPopupWindowIndex) != element.DXPopupElementIndex)
    clearTimer = false;
   if(clearTimer)
    this.ClearDisappearTimer();
   this.SaveCurrentMouseOverPos(evt);
   return;
  }
  this.OnMouseOut();
 },
 OnMouseOut: function(evt) {
  if(!this.overControl || this.draggingControl) return;
  this.ClearAppearTimer();
  var windowCloseAction = this.overControl.GetWindowCloseAction(this.overWindowIndex);
  if(windowCloseAction == "MouseOut" && this.overControl.InternalIsWindowVisible(this.overWindowIndex)) {
   if(!this.IsDisappearTimerActive() && this.IsDisappearAllowedByMouseOut(evt))
    this.SetDisappearTimer(this.overControl.name, this.overWindowIndex, this.overControl.disappearAfter);
  }
  else
   this.OverStop();
 },
 IsDisappearAllowedByMouseOut: function(evt) {
  return ASPx.Browser.Firefox || ASPx.Browser.Chrome ? !this.IsOverPopupWindow(evt) : true;  
 },
 OnMouseUp: function(evt) {
  if(this.draggingControl != null)
   this.DragStop();
  if(this.resizeControl != null)
   this.ResizeStop(evt);
 },
 OnResize: function(evt) {
  this.AutoUpdateElementsPosition();
  this.AdjustModalElementsBounds();
 },
 OnScroll: function(evt) {
  if(this.scrollEventLockCount > 0)
   return;
  var scroll = this.GetDocScrollDifference();
  if(this.IsDocScrolled(scroll)) { 
   this.CorrectPositionAtScroll(scroll);
   this.AdjustModalElementsBounds();
   this.SaveScrollState();
  }
  this.CalculateDocumentDimensionsWithoutPinnedWindows(evt);
  this.FireScrollEventToWindows(evt);
 },
 GetSavedBodyWidth: function() {
  if(this.savedBodyWidth == 0)
   this.CalculateDocumentDimensionsWithoutPinnedWindows();
  return this.savedBodyWidth;
 },
 GetSavedBodyHeight: function() {
  if(this.savedBodyHeight == 0)
   this.CalculateDocumentDimensionsWithoutPinnedWindows();
  return this.savedBodyHeight;
 },
 HidePinnedPopupsThatOutFromViewPort: function() {
  var popupsToRestoreVisible = [];
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
   var popupControl = popupWindow.popupControl;
   if(!popupControl.needToHidePinnedOutFromViewPort(popupWindow.windowIndex))
    continue;
   var element = popupControl.GetWindowElement(popupWindow.windowIndex);
   if(!element) continue;
   var restoreData = {};
   restoreData.element = element;
   restoreData.display = element.style.display;
   element.style.display = "none";
   popupsToRestoreVisible.push(restoreData);
  }
  return popupsToRestoreVisible;
 },
 RestorePinnedPopupsThatOutFromViewPort: function(popupsToRestoreVisible) {
  if(popupsToRestoreVisible.length > 0) {
   for(var i = 0; i < popupsToRestoreVisible.length; i++) {
    var restoreData = popupsToRestoreVisible[i];
    restoreData.element.style.display = restoreData.display;
   }
  }
 },
 CalculateDocumentDimensionsWithoutPinnedWindows: function(evt) { 
  var popupsToRestoreVisible = [];
  var needToHideRestorePopupsThatOutFromViewPort = !!evt && ASPx.Evt.GetEventSource(evt) == document;
  if(needToHideRestorePopupsThatOutFromViewPort)
   popupsToRestoreVisible = this.HidePinnedPopupsThatOutFromViewPort();
  this.savedBodyWidth = ASPx.GetDocumentWidth();
  this.savedBodyHeight = ASPx.GetDocumentHeight();
  if(needToHideRestorePopupsThatOutFromViewPort)
   this.RestorePinnedPopupsThatOutFromViewPort(popupsToRestoreVisible);
 },
 FireScrollEventToWindows: function(evt) {
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
   var popupControl = popupWindow.popupControl;
   popupControl.OnScroll(evt, popupWindow.windowIndex);
  }
 },
 LockScrollEvent: function() {
  this.scrollEventLockCount++;
 },
 UnlockScrollEvent: function() {
  this.scrollEventLockCount--;
 },
 CorrectPositionAtScroll: function(scroll) {
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
   var popupControl = popupWindow.popupControl;
   if(popupControl != null && popupControl.InternalIsWindowVisible(popupWindow.windowIndex)) {
    if(popupControl.GetAutoUpdatePosition(popupWindow.windowIndex))
     popupWindow.popupControl.TryAutoUpdatePosition(popupWindow.windowIndex);
   }
  }
 },
 OnSelectStart: function() {
  return !this.selectBanned;
 },
 OverStop: function() {
  this.overControl = null;
  this.overWindowIndex = -1;
 },
 OnPWDisappearTimer: function(name, index) {
  var pc = this.Get(name);
  if(pc != null) {
   if(!pc.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.MouseOut))
    this.OverStop();
   this.ClearDisappearTimer();
  }
 },
 SaveCurrentMouseOverPos: function(evt) {
  this.overXPos = ASPx.Evt.GetEventX(evt);
  this.overYPos = ASPx.Evt.GetEventY(evt);
 },
 RegisterVisibleModalElement: function(element) {
  if(ASPx.Data.ArrayIndexOf(this.visibleModalElements, element) == -1)
   this.visibleModalElements.push(element);
 },
 UnregisterVisibleModalElement: function(element) {
  ASPx.Data.ArrayRemove(this.visibleModalElements, element);
 },
 RegisterVisibleWindow: function(element, popupControl, index) {
  if(ASPx.Data.ArrayIndexOf(this.visiblePopupWindowIds, element.id) == -1) {
   this.visiblePopupWindowIds.push(element.id);
   if(popupControl && popupControl.GetWindowCloseAction(index) == "MouseOut")
    aspxGetPopupControlCollection().InitOverObject(popupControl, index, null);
   this.OnRegisteredVisibleWindow(element);
  }
 },
 OnRegisteredVisibleWindow: function(element) {
  var elementIndex = ASPx.Data.ArrayIndexOf(this.visiblePopupWindowIds, element.id);
  if(this.PopupWindowIsModalByVisibleIndex(elementIndex))
   ASPx.RemoveFocus(element);
 },
 UnregisterVisibleWindow: function(element) {
  this.DeleteWindowFromZIndexOrder(element);
  ASPx.Data.ArrayRemove(this.visiblePopupWindowIds, element.id);
  var forceRecalculate = this.PopupWindowIsModalByID(element.id);
  this.RefreshTabIndexes(forceRecalculate);
  this.SkipCurrentActiveWindowElement(element);
 },
 AutoUpdateElementsPosition: function() {
  for(var i = 0; i < this.visiblePopupWindowIds.length; i++) {
   var popupWindow = this.GetPopupWindowFromID(this.visiblePopupWindowIds[i]);
   var popupControl = popupWindow.popupControl;
   if(popupControl != null && popupControl.InternalIsWindowVisible(popupWindow.windowIndex))
    popupControl.TryAutoUpdatePosition(popupWindow.windowIndex);
  }
 },
 LockWindowResizeByBodyScrollVisibilityChanging: function() {
  this.windowResizeByBodyScrollVisibilityChangingLockCount++;
 },
 UnlockWindowResizeByBodyScrollVisibilityChanging: function() {
  this.windowResizeByBodyScrollVisibilityChangingLockCount--;
 },
 WindowResizeByBodyScrollVisibilityChangingLocked: function() {
  return this.windowResizeByBodyScrollVisibilityChangingLockCount > 0;
 },
 HideAllWindows: function() {
  this.DoHideAllWindows(null, "", true, ASPxClientPopupControlCloseReason.API, 0);
 }
});
var ASPxClientPopupControlResizeState = {
 Resized: 0,
 Collapsed: 1,
 Expanded: 2,
 Maximized: 3,
 RestoredAfterMaximized: 4
};
var ASPxClientPopupControlCloseReason = {
 API: "API",
 CloseButton: "CloseButton",
 OuterMouseClick: "OuterMouseClick",
 MouseOut: "MouseOut",
 Escape: "Escape"
};
var popupControlCollection = null;
function aspxGetPopupControlCollection() {
 if(popupControlCollection == null)
  popupControlCollection = new ASPxClientPopupControlCollection();
 return popupControlCollection;
}
function _aspxScrollDifference(horizontal, vertical) {
 this.horizontal = horizontal;
 this.vertical = vertical;
}
function aspxPWEMOver(evt) {
 aspxGetPopupControlCollection().OnPWMouseOver(evt);
}
ASPx.PWHMDown = function(evt) {
 return ASPx.Evt.CancelBubble(evt);
};
ASPx.PWCBClick = function(evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnPWHBClickCore(evt, index, "OnCloseButtonClick");
};
ASPx.PWPBClick = function(evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnPWHBClickCore(evt, index, "OnPinButtonClick");
};
ASPx.PWRBClick = function(evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnPWHBClickCore(evt, index, "OnRefreshButtonClick");
};
ASPx.PWMNBClick = function(evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnPWHBClickCore(evt, index, "OnCollapseButtonClick");
};
ASPx.PWMXBClick = function(evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnPWHBClickCore(evt, index, "OnMaximizeButtonClick");
};
ASPx.PWDGMDown = function (evt, name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 return ASPx.PWMDown(evt, name, index, pc.IsDraggingAllowed(index));
};
ASPx.PWGripMDown = function(evt, name, index) {
 aspxPWMDownCore(evt, name, index, false);
 return ASPx.PWHMDown(evt);
};
ASPx.PWMMove = function(evt, name, index) {
 aspxGetPopupControlCollection().OnPWMouseMove(evt, name, index);
};
ASPx.PWMDown = function(evt, name, index, isWindowContentDraggingAllowed) { 
 var pointOnScrollBar = false;
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc && pc.GetEnableContentScrolling(index)) {
  var rtl = pc.rtl && (ASPx.Browser.Firefox || ASPx.Browser.Opera);
  pointOnScrollBar = aspxPointOnElementScrollBar(pc.GetContentContainer(index), evt.clientX, evt.clientY, rtl);
 }
 aspxPWMDownCore(evt, name, index, isWindowContentDraggingAllowed, pointOnScrollBar);
 if(isWindowContentDraggingAllowed) { 
  aspxGetPopupControlCollection().OnDocumentMouseDown(evt); 
  if(typeof (ASPx.GetDropDownCollection) == "function")
   ASPx.GetDropDownCollection().OnDocumentMouseDown(evt); 
  if(!pointOnScrollBar) {
   if(!ASPx.Browser.WebKitTouchUI && ASPx.Evt.GetEventSource(evt).tagName == "IMG") 
    ASPx.Evt.PreventEvent(evt);
  }
 }
};
function aspxPWMDownCore(evt, name, index, isDraggingAllowed, pointOnScrollBar) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) {
  pc.OnActivate(index, evt);
  pc.OnMouseDown(evt, index, isDraggingAllowed, pointOnScrollBar);
 }
}
function aspxPWMEMDown(evt) {
 var internalScrollableModalDiv = ASPx.Browser.AndroidDefaultBrowser ? ASPx.Evt.GetEventSource(evt) : null;
 var modalDiv = internalScrollableModalDiv ? internalScrollableModalDiv.parentNode : ASPx.Evt.GetEventSource(evt);
 if(modalDiv != null) 
  modalDiv.DXModalPopupControl.OnMouseDownModalElement(evt, modalDiv.DXModalPopupWindowIndex);
}
function aspxPEMEvent(evt) {
 var element = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupControlElement);
 if(element != null) {
  var popupControl = element.DXPopupElementControl;
  var index = element.DXPopupWindowIndex;
  if(evt.type == "mousedown") {
   popupControl.SetIsPopuped(index, popupControl.InternalIsWindowVisible(index));
   aspxGetPopupControlCollection().OnMouseDown(evt);
  }
  else {
   var windowPopupAction = popupControl.GetWindowPopupAction(element.DXPopupWindowIndex);
   var leftMouseButtonAction = windowPopupAction == "LeftMouseClick" && ASPx.Evt.IsLeftButtonPressed(evt);
   var isAccessibleKeyboardAction = popupControl.accessibilityCompliant && ASPx.Evt.IsActionKeyPressed(evt);
   var rightMouseButtonAction = windowPopupAction == "RightMouseClick" && !ASPx.Evt.IsLeftButtonPressed(evt);
   if(leftMouseButtonAction || rightMouseButtonAction || isAccessibleKeyboardAction) {
    if(rightMouseButtonAction)
     ASPx.PopupUtils.PreventContextMenu(evt);
    var windowCloseAction = popupControl.GetWindowCloseAction(index);
    var isPopuped = popupControl.GetIsPopuped(index);
    var isNewPopupElement = popupControl.GetLastShownPopupElementIndex(index) != element.DXPopupElementIndex;
    if(isPopuped && isNewPopupElement) {
     popupControl.DoHideWindow(index, false, ASPxClientPopupControlCloseReason.OuterMouseClick);
     aspxGetPopupControlCollection().ClearDisappearTimer();
     isPopuped = false;
    }
    if(!(isPopuped && windowCloseAction == "OuterMouseClick")) {
     popupControl.DoShowWindow(index, element.DXPopupElementIndex, evt);
    }
    if(windowCloseAction == "MouseOut")
     aspxGetPopupControlCollection().InitOverObject(popupControl, element.DXPopupWindowIndex, evt);
    return false;
   }
  }
 }
}
ASPx.PopupElementMouseEvent = aspxPEMEvent;
function aspxPointOnElementScrollBar(element, x, y, rtl) {
 var scrollWidth = ASPx.GetVerticalScrollBarWidth();
 var hasHorizontalScroll = element.scrollWidth > element.clientWidth;
 var hasVerticalScroll = element.scrollHeight > element.clientHeight;
 var ceilX = rtl ? ASPx.GetAbsoluteX(element) + scrollWidth :
  ASPx.GetAbsoluteX(element) + (element.offsetWidth - ASPx.GetHorizontalBordersWidth(element));
 var ceilY = ASPx.GetAbsoluteY(element) + (element.offsetHeight - ASPx.GetVerticalBordersWidth(element));
 return (hasVerticalScroll && x >= ceilX - scrollWidth && x <= ceilX) ||
   (hasHorizontalScroll && y >= ceilY - scrollWidth && y <= ceilY);
}
ASPx.PCAStop = function(name, index) {
 var pc = aspxGetPopupControlCollection().Get(name);
 if(pc != null) pc.OnAnimationStop(index);
};
ASPx.PCIframeLoad = function(evt) {
 var srcElement = ASPx.Evt.GetEventSource(evt);
 if(srcElement) {
  var pcName = srcElement.popupControlName;
  var pcWndIndex = srcElement.pcWndIndex;
  if(pcName) {
   var pc = aspxGetPopupControlCollection().Get(pcName);
   if(pc) pc.OnIFrameLoad(pcWndIndex);
  }
 }
};
function aspxTestPopupWindowElement(element) {
 return !!element.DXPopupWindowElement;
}
function aspxTestPopupControlElement(element) {
 return element.DXPopupElementControl && ASPx.IsExists(element.DXPopupWindowIndex);
}
function aspxTestPopupControlOverElement(element) {
 var collection = aspxGetPopupControlCollection();
 var popupControl = collection.overControl;
 var index = collection.overWindowIndex;
 var windowId = popupControl.GetWindowElementId(index);
 if(element.id == windowId)
  return true;
 var popupElements = popupControl.GetPopupElementList(index);
 for(var i = 0; i < popupElements.length; i++)
  if(popupElements[i] == element)
   return true;
 return false;
}
ASPx.Evt.AttachEventToDocument("keydown", function(evt) {
 aspxGetPopupControlCollection().OnDocumentKeyDown(evt);
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, function(evt) {
 aspxGetPopupControlCollection().OnDocumentMouseDown(evt);
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, function(evt) {
 return aspxGetPopupControlCollection().OnMouseUp(evt);
});
ASPx.Evt.AttachEventToElement(window, ASPx.TouchUIHelper.touchMouseMoveEventName, function(evt) {
 if(typeof(aspxGetPopupControlCollection) != "undefined")
  aspxGetPopupControlCollection().OnMouseMove(evt);
}, false, !ASPx.Browser.WebKitTouchUI);
ASPx.Evt.AttachEventToDocument("mouseout", function(evt) {
 if(typeof (aspxGetPopupControlCollection) != "undefined")
  aspxGetPopupControlCollection().OnMouseOut(evt);
});
 ASPx.Evt.AttachEventToElement(window, "resize", function(evt) {
 aspxGetPopupControlCollection().OnResize(evt);
});
ASPx.Evt.AttachEventToElement(window, "scroll", function(evt) {
 aspxGetPopupControlCollection().OnScroll(evt);
});
ASPx.Evt.AttachEventToDocument("selectstart", function(evt) {
 var ret = aspxGetPopupControlCollection().OnSelectStart(evt);
 if(!ret) return false; 
});
var currViewPortSize = null,
 viewPortSizeInterval = null;
function getViewPortSize() {
 return { 
  w: window.innerWidth, 
  h: window.innerHeight,
  x: window.pageXOffset,
  y: window.pageYOffset
 }; 
}
function ensureViewPortSizeInterval() {
 if(!!viewPortSizeInterval) return;
 viewPortSizeInterval = setInterval(function() {
  var size = getViewPortSize();
  if(currViewPortSize && (size.w != currViewPortSize.w || size.h != currViewPortSize.h || size.x != currViewPortSize.x || size.y != currViewPortSize.y)) {
   var controlCollection = aspxGetPopupControlCollection();
   controlCollection.ForEachControl(function(popupControl) {
    if(popupControl.GetCanScrollViewPort(-1) && popupControl.IsVisible()) {
     popupControl.updateContentScrollIfNeeded(-1);
     popupControl.UpdatePosition();
    }
   });
  }
  currViewPortSize = size;
 }, 50);
}
window.ASPxClientPopupControlBase = ASPxClientPopupControlBase;
window.ASPxClientPopupControl = ASPxClientPopupControl;
window.ASPxClientPopupWindow = ASPxClientPopupWindow;
window.ASPxClientPopupWindowEventArgs = ASPxClientPopupWindowEventArgs;
window.ASPxClientPopupWindowCancelEventArgs = ASPxClientPopupWindowCancelEventArgs;
window.ASPxClientPopupWindowResizeEventArgs = ASPxClientPopupWindowResizeEventArgs;
window.ASPxClientPopupWindowPinnedChangedEventArgs = ASPxClientPopupWindowPinnedChangedEventArgs;
window.ASPxClientPopupControlCollection = ASPxClientPopupControlCollection;
window.ASPxClientPopupControlResizeState = ASPxClientPopupControlResizeState;
window.ASPxClientPopupControlCloseReason = ASPxClientPopupControlCloseReason;
ASPx.GetPopupControlCollection = aspxGetPopupControlCollection;
ASPx.PopupControlCssClasses = PopupControlCssClasses;
})();

(function() {
var DockZoneBag = ASPx.CreateClass(null, {
 constructor: function() {
  this.zones = {};
 },
 ForEachZone: function(action) {
  for(var key in this.zones) {
   if(!this.zones.hasOwnProperty(key))
    continue;
   action(this.zones[key]);
  }
 },
 RegisterZone: function(zone) {
  this.zones[zone.zoneUID] = zone;
 },
 GetZoneByUID: function(zoneUID) {
  return this.zones[zoneUID];
 },
 GetZoneList: function() {
  var zoneList = [];
  this.ForEachZone(function(zone) {
   if(zone.GetMainElement())
    zoneList.push(zone);
  });
  return zoneList;
 }
});
DockZoneBag.instance = null;
DockZoneBag.Get = function() {
 if(!DockZoneBag.instance)
  DockZoneBag.instance = new DockZoneBag();
 return DockZoneBag.instance;
};
var ASPxClientDockZone = ASPx.CreateClass(ASPxClientControl, {
 HorizontalOrientationCssClassName: 'dxdzControlHor',
 FillOrientationCssClassName: 'dxdzControlFill',
 PanelPlaceHolderCssClassName: 'dxdz-pnlPlcHolder',
 StyleSheetIDPostfix: '_SS',
 DefaultHorizontalOrientationWidth: 400,
 DefaultHorizontalOrientationHeight: 200,
 DefaultVerticalOrientationWidth: 200,
 DefaultVerticalOrientationHeight: 400,
 DefaultFillOrientationWidth: 400,
 DefaultFillOrientationHeight: 400,
 BeforeDockServerEventName: "BeforeDock",
 AfterDockServerEventName: "AfterDock",
 RaiseBeforeDockEventCommand: "EBD",
 RaiseAfterDockEventCommand: "EAD",
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.zoneUID = null;
  this.allowGrow = true;
  this.panelSpacing = 0;
  if(this.IsFillOrientation()) {
   this.initialWidth = this.DefaultFillOrientationWidth;
   this.initialHeight = this.DefaultFillOrientationHeight;
  } else {
   var isHorizontal = this.IsHorizontalOrientation();
   this.initialWidth = isHorizontal ? this.DefaultHorizontalOrientationWidth : this.DefaultVerticalOrientationWidth;
   this.initialHeight = isHorizontal ? this.DefaultHorizontalOrientationHeight : this.DefaultVerticalOrientationHeight;
  }
  this.inPostback = false;
  this.initialStyleDimensions = {
   width: '',
   height: ''
  };
  this.dockedPanels = {};
  this.zoneStyleSheet = ASPx.GetCurrentStyleSheet();
  this.dockingAllowedClassName = '';
  this.dockingForbiddenClassName = '';
  this.BeforeDock = new ASPxClientEvent();
  this.AfterDock = new ASPxClientEvent();
 },
 SendPostBack: function(params) {
  if(!this.inPostback) {
   this.inPostback = true;
   ASPxClientControl.prototype.SendPostBack.call(this, params);
  }
 },
 SetData: function(data){
  if(data.stylesInfo){
   this.dockingForbiddenClassName = this.CreateClientCssStyle(data.stylesInfo.dfs);
   this.dockingAllowedClassName = this.CreateClientCssStyle(data.stylesInfo.das);
  }
 },
 InlineInitialize: function() {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  var panelPlaceholder = this.GetPanelPlaceholder();
  ASPx.SetElementDisplay(panelPlaceholder, false);
  var mainElement = this.GetMainElement();
  this.initialStyleDimensions.width = mainElement.style.width;
  this.initialStyleDimensions.height = mainElement.style.height;
  this.InitializeBoxSizing(); 
  DockZoneBag.Get().RegisterZone(this);
 },
 InitializeBoxSizing: function() {
  if(this.IsPercentageWidth()) 
   this.GetMainElement().style.boxSizing = "border-box";
 },
 AdjustControlCore: function() {
  var mainElement = this.GetMainElement();
  mainElement.style.overflow = 'hidden';
  if(this.IsHorizontalOrientation()) {
   if(this.IsPercentageWidth())
    this.CorrectWidthOnAdjust();
   this.correctPanelsDimensionsOnAdjust(this.IsPercentageHeigth(), false);
  } else if(!this.IsFillOrientation()) {
   if(this.IsPercentageHeigth())
    this.CorrectHeightOnAdjust();
   this.correctPanelsDimensionsOnAdjust(false, this.IsPercentageWidth());
  } else {
   this.correctPanelsDimensionsOnAdjust(this.IsPercentageHeigth(), this.IsPercentageWidth());
   if(this.IsPercentageWidth())
    this.CorrectWidthOnAdjust();
   if(this.IsPercentageHeigth())
    this.CorrectHeightOnAdjust();
  }
  mainElement.style.overflow = '';
 },
 correctPanelsDimensionsOnAdjust: function(height, width) {
  if(height) this.correctPanelsOnAdjust(true);
  if(width) this.correctPanelsOnAdjust(false);
 },
 correctPanelsOnAdjust: function(isHeight) {
  var mainElement = this.GetMainElement();
  if(isHeight)
   this.initialHeight = mainElement.offsetHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(mainElement);
  else
   this.initialWidth = mainElement.offsetWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainElement);
  this.ForEachDockedPanel(function(panel) {
   panel.UpdateRestoredWindowSizeLock();
   if(isHeight) panel.SetHeightInternal(this.initialHeight);
   else panel.SetWidthInternal(this.initialWidth);
   panel.UpdateRestoredWindowSizeUnlock();
  }.aspxBind(this));
 },
 CorrectWidthOnAdjust: function() {
  var mainElement = this.GetMainElement();
  this.initialWidth = 0;
  this.CorrectWidth();
  var contentWidth = ASPx.GetClearClientWidth(mainElement);
  mainElement.style.width = this.initialStyleDimensions.width;
  var percentageWidth = ASPx.GetClearClientWidth(mainElement);
  if(contentWidth > percentageWidth)
   mainElement.style.width = contentWidth + 'px';
  else
   this.initialWidth = percentageWidth;
 },
 CorrectHeightOnAdjust: function() {
  var mainElement = this.GetMainElement();
  this.initialHeight = 0;
  this.CorrectHeight();
  var contentHeight = ASPx.GetClearClientHeight(mainElement);
  mainElement.style.height = this.initialStyleDimensions.height;
  var percentageHeight = ASPx.GetClearClientHeight(mainElement);
  if(contentHeight > percentageHeight)
   mainElement.style.height = contentHeight + 'px';
  else
   this.initialHeight = percentageHeight;
 },
 IsPercentageWidth: function() {
  return ASPx.IsPercentageSize(this.initialStyleDimensions.width);
 },
 IsPercentageHeigth: function() {
  return ASPx.IsPercentageSize(this.initialStyleDimensions.height);
 },
 BrowserWindowResizeSubscriber: function() {
  return true;
 },
 OnBrowserWindowResize: function() {
  this.AdjustControl();
 },
 IsCursorInsideZone: function(cursorPos) {
  var mainElement = this.GetMainElement();
  var width = mainElement.offsetWidth;
  var height = mainElement.offsetHeight;
  var x = ASPx.GetAbsoluteX(mainElement);
  var y = ASPx.GetAbsoluteY(mainElement);
  var bordersAndPaddingsValues = this.GetBordersAndPaddingsValues();
  var bounds = {
   left: x + bordersAndPaddingsValues.left,
   top: y + bordersAndPaddingsValues.top,
   right: x + width - bordersAndPaddingsValues.right,
   bottom: y + height - bordersAndPaddingsValues.bottom
  };
  return cursorPos.x >= bounds.left && cursorPos.x <= bounds.right &&
   cursorPos.y >= bounds.top && cursorPos.y <= bounds.bottom;
 },
 GetBordersAndPaddingsValues: function() {
  var mainElement = this.GetMainElement();
  var currentStyle = ASPx.GetCurrentStyle(mainElement);
  var leftValue = ASPx.PxToInt(currentStyle.paddingLeft);
  if(currentStyle.borderLeftStyle != "none")
   leftValue += ASPx.PxToInt(currentStyle.borderLeftWidth);
  var topValue = ASPx.PxToInt(currentStyle.paddingTop);
  if(currentStyle.borderTopStyle != "none")
   topValue += ASPx.PxToInt(currentStyle.borderTopWidth);
  var rightValue = ASPx.PxToInt(currentStyle.paddingRight);
  if(currentStyle.borderRightStyle != "none")
   rightValue += ASPx.PxToInt(currentStyle.borderRightWidth);
  var bottomValue = ASPx.PxToInt(currentStyle.paddingBottom);
  if(currentStyle.borderBottomStyle != "none")
   bottomValue += ASPx.PxToInt(currentStyle.borderBottomWidth);
  return { left: leftValue, top: topValue, right: rightValue, bottom: bottomValue };
 },
 IsHorizontalOrientation: function() {
  var mainElement = this.GetMainElement();
  return ASPx.ElementHasCssClass(mainElement, this.HorizontalOrientationCssClassName);
 },
 IsFillOrientation: function() {
  var mainElement = this.GetMainElement();
  return ASPx.ElementHasCssClass(mainElement, this.FillOrientationCssClassName);
 },
 GetDockedPanelsSummaryHeight: function() {
  var dockedPanelsSummaryHeight = 0;
  this.ForEachDockedPanel(function(panel) {
   if(!panel.IsVisible())
    return;
   var panelMainElement = panel.GetMainElement();
   dockedPanelsSummaryHeight += panel.GetHeight() + ASPx.PxToInt(panelMainElement.style.marginTop);
  });
  return dockedPanelsSummaryHeight;
 },
 GetDockedPanelsSummaryWidth: function() {
  var dockedPanelsSummaryWidth = 0;
  this.ForEachDockedPanel(function(panel) {
   if(!panel.IsVisible())
    return;
   var panelMainElement = panel.GetMainElement();
   dockedPanelsSummaryWidth += panel.GetWidth() + ASPx.PxToInt(panelMainElement.style.marginLeft);
  });
  return dockedPanelsSummaryWidth;
 },
 CorrectHeight: function() {
  var height = this.GetDockedPanelsSummaryHeight();
  var panelPlaceholder = this.GetPanelPlaceholder();
  var mainElement = this.GetMainElement();
  if(ASPx.GetElementDisplay(panelPlaceholder))
   height += panelPlaceholder.offsetHeight + ASPx.PxToInt(panelPlaceholder.style.marginTop);
  height = Math.max(height, this.initialHeight);
  mainElement.style.height = height + 'px';
 },
 CorrectWidth: function() {
  var width = this.GetDockedPanelsSummaryWidth();
  var panelPlaceholder = this.GetPanelPlaceholder();
  var mainElement = this.GetMainElement();
  if(ASPx.GetElementDisplay(panelPlaceholder))
   width += panelPlaceholder.offsetWidth + ASPx.PxToInt(panelPlaceholder.style.marginLeft);
  width = Math.max(width, this.initialWidth);
  mainElement.style.width = width + 'px';
 },
 CorrectResizableDimension: function() {
  if(!this.allowGrow)
   return;
  this.CorrectResizableDimensionCore();
 },
 CorrectResizableDimensionCore: function() {
  if(this.IsHorizontalOrientation())
   this.CorrectWidth();
  else
   this.CorrectHeight();
 },
 ContainsZone: function(anotherZone) {
  return this.GetMainElement().contains(anotherZone.GetMainElement());
 },
 GetPanelPlaceholder: function() {
  return ASPx.GetChildByClassName(this.GetMainElement(), this.PanelPlaceHolderCssClassName);
 },
 GetPanelPlaceholderPositionForElement: function(element) {
  var placeholder = this.GetPanelPlaceholder();
  if(placeholder.style.display === "none" && this.IsFillOrientation())
   placeholder.style.display = "";
  return {
   x: ASPx.PrepareClientPosForElement(ASPx.GetAbsoluteX(placeholder), element, true),
   y: ASPx.PrepareClientPosForElement(ASPx.GetAbsoluteY(placeholder), element, false)
  };
 },
 MovePanelPlaceholder: function(cursorPos) {
  var cursorOverPanelLocation = null;
  var mainElement = this.GetMainElement();
  var panelPlaceholder = this.GetPanelPlaceholder();
  var isHorizontal = this.IsHorizontalOrientation();
  for(var key in this.dockedPanels) {
   if(!this.dockedPanels.hasOwnProperty(key))
    continue;
   var panel = this.dockedPanels[key];
   cursorOverPanelLocation = panel.GetCursorOverPanelLocation(cursorPos, this.panelSpacing, isHorizontal);
   if(cursorOverPanelLocation === 'top' || cursorOverPanelLocation === 'left') {
    mainElement.insertBefore(panelPlaceholder, panel.GetMainElement());
    this.ApplyPanelSpacing();
    return;
   }
   if(cursorOverPanelLocation === 'bottom' || cursorOverPanelLocation === 'right') {
    var panelElementSibling = panel.GetMainElement().nextSibling;
    mainElement.insertBefore(panelPlaceholder, panelElementSibling);
    this.ApplyPanelSpacing();
    return;
   }
  }
  if(panelPlaceholder.style.display === 'none') {
   mainElement.appendChild(panelPlaceholder);
   this.ApplyPanelSpacing();
  }
 },
 MovePanelPlaceholderToPanel: function(panel) {
  var panelPlaceholder = this.GetPanelPlaceholder();
  var mainElement = this.GetMainElement();
  var panelMainElement = panel.GetMainElement();
  mainElement.insertBefore(panelPlaceholder, panelMainElement.nextSibling);
 },
 ShowPanelPlaceholder: function(panel) {
  var panelPlaceholder = this.GetPanelPlaceholder();
  var isHorizontal = this.IsHorizontalOrientation();
  var isFill = this.IsFillOrientation();
  var panelDockedDimensions = null;
  var canDockPanel = panel.mode != ASPxClientDockPanelModes.FloatOnly && !panel.freezed && !panel.IsZoneForbidden(this);
  if(isFill) {
   panelDockedDimensions = { width: this.initialWidth, height: this.initialHeight };
   canDockPanel &= this.CanDockPanel();
  } else {
   var zoneResizableDimension = isHorizontal ? this.initialHeight : this.initialWidth;
   panelDockedDimensions = panel.GetDockedDimensions(zoneResizableDimension, isHorizontal);
   canDockPanel &= this.CanDockPanel(isHorizontal ? panelDockedDimensions.width : panelDockedDimensions.height);
  }
  if(canDockPanel) {
   var panelPlaceholderWidth = panelDockedDimensions.width - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(panelPlaceholder);
   var panelPlaceholderHeight = panelDockedDimensions.height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(panelPlaceholder);
   ASPx.SetStyles(panelPlaceholder, {
    width: panelPlaceholderWidth,
    height: panelPlaceholderHeight,
    display: ""
   });
   if(!isFill)
    this.ApplyPanelSpacing();
   this.CorrectResizableDimension();
   this.AdjustControlCore();
  }
 },
 HidePanelPlaceholder: function() {
  var panelPlaceholder = this.GetPanelPlaceholder();
  ASPx.SetElementDisplay(panelPlaceholder, false);
  this.ApplyPanelSpacing();
  this.CorrectResizableDimension();
  this.AdjustControlCore();
 },
 ForEachDockedPanel: function(action) {
  for(var key in this.dockedPanels) {
   if(!this.dockedPanels.hasOwnProperty(key))
    continue;
   action(this.dockedPanels[key]);
  }
 },
 DockPanel: function(panel, dockedDimensions, considerVisibleIndex, directOrder) {
  panel.ResizeForDock(dockedDimensions);
  this.HidePanelPlaceholder();
  this.ConsumePanelElement(panel, considerVisibleIndex, directOrder);
  this.ApplyPanelSpacing();
  this.dockedPanels[panel.panelUID] = panel;
  panel.SetZoneUID(this.zoneUID);
  if(!considerVisibleIndex)
   this.UpdatePanelsVisibleIndices();
  this.CorrectResizableDimension();
 },
 ConsumePanelElement: function(panel, considerVisibleIndex, directOrder) {
  var mainElement = this.GetMainElement();
  var panelMainElement = panel.GetMainElement();
  if(!considerVisibleIndex) {
   var panelPlaceholder = this.GetPanelPlaceholder();
   mainElement.insertBefore(panelMainElement, panelPlaceholder);
   return;
  }
  var nextPanel = null;
  var directOrderPrevPanel = null;
  var visibleIndex = panel.GetVisibleIndex();
  this.ForEachDockedPanel(function(dockedPanel) {
   var dockedPanelVisibleIndex = dockedPanel.GetVisibleIndex();
   if(!dockedPanel.IsVisible() && dockedPanelVisibleIndex === visibleIndex)
    return;
   if(directOrder && dockedPanelVisibleIndex === visibleIndex) {
    directOrderPrevPanel = dockedPanel.GetMainElement();
    return;
   }
   if(dockedPanelVisibleIndex >= visibleIndex) {
    if(nextPanel && nextPanel.GetVisibleIndex() <= dockedPanelVisibleIndex)
     return;
    nextPanel = dockedPanel;
   }
  });
  if(directOrder && !!directOrderPrevPanel) {
   ASPx.InsertElementAfter(panelMainElement, directOrderPrevPanel);
   return;
  }
  var insertBeforeNode = null;
  if(nextPanel)
   insertBeforeNode = nextPanel.GetMainElement();
  mainElement.insertBefore(panelMainElement, insertBeforeNode);
 },
 CanDockPanel: function(resizableDimension) {
  if(this.IsFillOrientation())
   return !this.HasDockedPanels();
  if(this.allowGrow)
   return true;
  var panelPlaceholder = this.GetPanelPlaceholder();
  var spacing = 0;
  if(panelPlaceholder.prevSibling && panelPlaceholder.prevSibling.nodeType === 1)
   spacing = this.panelSpacing;
  if(this.IsHorizontalOrientation())
   return this.GetDockedPanelsSummaryWidth() + resizableDimension + spacing <= this.initialWidth;
  return this.GetDockedPanelsSummaryHeight() + resizableDimension + spacing <= this.initialHeight;
 },
 UpdatePanelsVisibleIndices: function() {
  var zoneChildElements = this.GetMainElement().childNodes;
  var index = 0;
  for(var i = 0; i < zoneChildElements.length; i++) {
   if(zoneChildElements[i].panelUID) {
    var panel = this.dockedPanels[zoneChildElements[i].panelUID];
    if(!panel.IsVisible())
     continue;
    panel.SetVisibleIndexCore(index);
    index++;
   }
  }
 },
 EnsurePanelsVisibleIndicesAfterFirstShow: function() {
  var controlCollection = ASPx.GetPopupControlCollection(),
   panelsFirstShowCompleted = true;
  var currentZone = this.zoneUID;
  controlCollection.ForEachControl(function (control) {
   if (control && control instanceof ASPxClientDockPanel && !control.firstShowProcessed && control.GetZoneUID() == currentZone) {
    panelsFirstShowCompleted = false;
   }
  });
  if(panelsFirstShowCompleted)
   this.UpdatePanelsVisibleIndices();
 },
 GetDockedPanelsMaxVisibleIndex: function() {
  var maxIndex = 0;
  this.ForEachDockedPanel(function(panel) {
   maxIndex = Math.max(panel.GetVisibleIndex(), maxIndex);
  });
  return maxIndex;
 },
 GetPanelAfterPlaceholderVisibleIndex: function() {
  var placeholder = this.GetPanelPlaceholder();
  var sibling = placeholder.previousSibling;
  while(sibling) {
   if(sibling.panelUID) {
    var panel = this.dockedPanels[sibling.panelUID];
    if(panel.IsVisible())
     return panel.GetVisibleIndex();
   }
   sibling = sibling.previousSibling;
  }
  return -1;
 },
 GetOrderedPanelsList: function(startFromPanel) {
  var panels = [];
  var mainElement = this.GetMainElement();
  var element = startFromPanel ? startFromPanel.GetMainElement() : mainElement.firstChild;
  while(element) {
   if(element.panelUID) {
    var panel = this.dockedPanels[element.panelUID];
    if(panel)
     panels.push(panel);
   }
   element = element.nextSibling;
  }
  return panels;
 },
 FixatePanels: function(startFromPanel) {
  var mainElement = this.GetMainElement();
  mainElement.style.position = 'relative';
  mainElement.style.top = 0;
  mainElement.style.left = 0;
  var panels = this.GetOrderedPanelsList(startFromPanel);
  for(var i = panels.length - 1; i >= 0; i--)
   panels[i].Fixate();
 },
 RemovePanelsFixation: function() {
  var panels = this.GetOrderedPanelsList();
  for(var i = 0; i < panels.length; i++)
   panels[i].RemoveFixation();
  var mainElement = this.GetMainElement();
  mainElement.style.position = 'static';
 },
 UndockPanel: function(panel) {
  delete this.dockedPanels[panel.panelUID];
  panel.SetZoneUID(null);
  this.RemovePanelSpacing(panel.GetMainElement());
  this.UpdatePanelsVisibleIndices();
  this.ApplyPanelSpacing();
  this.CorrectResizableDimension();
 },
 HasDockedPanels: function() {
  for(var key in this.dockedPanels) {
   if(this.dockedPanels.hasOwnProperty(key))
    return true;
  }
  return false;
 },
 ApplyPanelSpacing: function() {
  if(!this.panelSpacing)
   return;
  var mainElement = this.GetMainElement();
  var instance = this;
  var elements = ASPx.GetChildElementNodesByPredicate(mainElement, function(element) {
   var isPlaceholder = ASPx.ElementHasCssClass(element, instance.PanelPlaceHolderCssClassName);
   return (element.panelUID || isPlaceholder) && ASPx.GetElementDisplay(element);
  });
  for(var i = 0; i < elements.length; i++) {
   var element = elements[i];
   this.RemovePanelSpacing(element);
   if(i > 0) {
    if(this.IsHorizontalOrientation())
     element.style.marginLeft = this.panelSpacing + 'px';
    else
     element.style.marginTop = this.panelSpacing + 'px';
   }
  }
 },
 RemovePanelSpacing: function(panelMainElement) {
  panelMainElement.style.marginTop = '';
  panelMainElement.style.marginLeft = '';
 },
 CreateClientCssStyle: function(style) {
  if(!style)
   return '';
  var result = style.className;
  if(style.inlineStyle)
   result += " " + ASPx.CreateImportantStyleRule(this.zoneStyleSheet, style.inlineStyle);
  return ASPx.Str.Trim(result);
 },
 ApplyDockingAllowedStyle: function() {
  this.ApplyZoneCssClass(this.dockingAllowedClassName);
 },
 RemoveDockingAllowedStyle: function() {
  this.RemoveZoneCssClass(this.dockingAllowedClassName);
 },
 ApplyDockingForbiddenStyle: function() {
  this.ApplyZoneCssClass(this.dockingForbiddenClassName);
 },
 RemoveDockingForbiddenStyle: function() {
  this.RemoveZoneCssClass(this.dockingForbiddenClassName);
 },
 ApplyZoneCssClass: function(cssClassName) {
  var mainElement = this.GetMainElement();
  var tempClassName = mainElement.className.replace(cssClassName, "");
  mainElement.className = ASPx.Str.Trim(tempClassName + " " + cssClassName);
 },
 RemoveZoneCssClass: function(cssClassName) {
  var mainElement = this.GetMainElement();
  mainElement.className = mainElement.className.replace(cssClassName, "");
 },
 GetBeforeDockPostbackArgs: function(panel) {
  return [
   this.RaiseBeforeDockEventCommand,
   panel.panelUID,
   this.GetPanelAfterPlaceholderVisibleIndex() + 1
  ];
 },
 GetAfterDockPostbackArgs: function(panel) {
  return [
   this.RaiseAfterDockEventCommand,
   panel.panelUID
  ];
 },
 RaiseBeforeDock: function(panel) {
  var processOnServer = this.IsServerEventAssigned(this.BeforeDockServerEventName);
  var args = new ASPxClientDockZoneCancelEventArgs(processOnServer, panel);
  if(!this.BeforeDock.IsEmpty())
   this.BeforeDock.FireEvent(this, args);
  if(!args.cancel && args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetBeforeDockPostbackArgs(panel);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  return !args.cancel;
 },
 RaiseAfterDock: function(panel) {
  var processOnServer = this.IsServerEventAssigned(this.AfterDockServerEventName);
  var args = new ASPxClientDockZoneProcessingModeEventArgs(processOnServer, panel);
  if(!this.AfterDock.IsEmpty())
   this.AfterDock.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetAfterDockPostbackArgs(panel);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
 },
 SetWidth: function(width) {
  var mainElement = this.GetMainElement();
  var actualWidth = width - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainElement);
  this.initialWidth = actualWidth;
  mainElement.style.width = actualWidth + "px";
  if(!this.IsHorizontalOrientation())
   this.ForEachDockedPanel(function(panel) { panel.SetWidthInternal(actualWidth); });
 },
 SetHeight: function(height) {
  var mainElement = this.GetMainElement();
  var actualHeight = height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(mainElement);
  this.initialHeight = actualHeight;
  mainElement.style.height = actualHeight + "px";
  if(this.IsHorizontalOrientation())
   this.ForEachDockedPanel(function(panel) { panel.SetHeightInternal(actualHeight); });
 },
 IsVertical: function() {
  return !this.IsHorizontalOrientation();
 },
 GetAllowGrowing: function() {
  return this.allowGrow;
 },
 GetPanelCount: function() {
  return this.GetOrderedPanelsList().length;
 },
 GetPanelByUID: function(panelUID) {
  var panels = this.GetOrderedPanelsList();
  for(var i = 0; i < panels.length; i++) {
   if(panels[i].panelUID === panelUID)
    return panels[i];
  }
  return null;
 },
 GetPanelByVisibleIndex: function(visibleIndex) {
  this.UpdatePanelsVisibleIndices();
  var panels = this.GetOrderedPanelsList();
  return panels[visibleIndex];
 },
 GetPanels: function(filterPredicate) {
  var panels = this.GetOrderedPanelsList();
  return ASPx.RetrieveByPredicate(panels, filterPredicate);
 }
});
ASPxClientDockZone.Cast = ASPxClientControl.Cast;
var ASPxClientDockZoneCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
 constructor: function(processOnServer, panel) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.panel = panel;
 }
});
var ASPxClientDockZoneProcessingModeEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(processOnServer, panel) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.panel = panel;
 }
});
ASPx.DockZoneBag = DockZoneBag;
window.ASPxClientDockZone = ASPxClientDockZone;
window.ASPxClientDockZoneCancelEventArgs = ASPxClientDockZoneCancelEventArgs;
window.ASPxClientDockZoneProcessingModeEventArgs = ASPxClientDockZoneProcessingModeEventArgs;
})();

(function() {
var DockPanelStateObserver = ASPx.CreateClass(null, {
 constructor: function(observedPanel) {
  this.panel = observedPanel;
  this.trackState = true;
  this.previousState = {
   zone: null
  };
  this.currentState = {
   zone: this.panel.zone
  };
 },
 UpdateState: function() {
  if(!this.trackState)
   return;
  this.previousState = this.currentState;
  this.currentState = {
   zone: this.panel.zone
  };
 },
 IsBeingDocked: function() {
  return this.currentState.zone && this.previousState.zone != this.currentState.zone;
 },
 IsBeingFloated: function() {
  return this.previousState.zone && !this.currentState.zone;
 }
});
var ASPxClientDockPanelModes = {
 All: "All",
 DockedOnly: "DockedOnly",
 FloatOnly: "FloatOnly"
};
var ASPxClientDockPanel = ASPx.CreateClass(ASPxClientPopupControl, {
 DefaultWindowIndex: -1,
 AnimationDelay: 30,
 MaxAnimationTime: 400,
 AnimationOffset: 20,
 UndockOnDoubleClickOffset: 5,
 StateHiddenInputIDPostfix: '_SHF',
 BeforeDockServerEventName: "BeforeDock",
 AfterDockServerEventName: "AfterDock",
 BeforeFloatServerEventName: "BeforeFloat",
 AfterFloatServerEventName: "AfterFloat",
 RaiseBeforeDockEventCommand: "EBD",
 RaiseAfterDockEventCommand: "EAD",
 RaiseBeforeFloatEventCommand: "EBF",
 RaiseAfterFloatEventCommand: "EAF",
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.panelUID = null;
  this.forbiddenZones = [];
  this.mode = ASPxClientDockPanelModes.All;
  this.requireFreezingLayout = false;
  this.zone = null;
  this.initialParentNode = null;
  this.trackDimensions = true;
  this.fixated = false;
  this.initialShadowVisible = false;
  this.freezed = false;
  this.allowEnsureContent = true;
  this.firstShowProcessed = false;
  this.floatingState = true;
  this.completeSwitchingToFloatingStateOnCallback = false;
  this.floatingStateAllowResize = false;
  this.floatingStateEnableContentScrolling = false;
  this.animationLocked = false;
  this.inUndockedState = false;
  this.contentFlexibilityEnabled = false;
  this.widthFixed = false;
  this.heightFixed = false;
  this.inPostback = false;
  this.dockRestorePanelData = null;
  this.dockedDimensionsCalculating = false;
  this.floatingStateDimensions = {
   width: 0,
   height: 0,
   minWidth: 0,
   minHeight: 0,
   maxWidth: 0,
   maxHeight: 0
  };
  this.floatingStateContentOverflow = {
   x: 'visible',
   y: 'visible',
   both: 'visible'
  };
  this.stateObserver = new DockPanelStateObserver(this);
  this.shouldProcessFirstShowWindow = false;
  this.loopFocusHandler = function() { };
  this.BeforeDock = new ASPxClientEvent();
  this.AfterDock = new ASPxClientEvent();
  this.BeforeFloat = new ASPxClientEvent();
  this.AfterFloat = new ASPxClientEvent();
  this.StartDragging = new ASPxClientEvent();
  this.EndDragging = new ASPxClientEvent();
 },
 SendPostBack: function(params) {
  if(!this.inPostback) {
   this.inPostback = true;
   ASPxClientControl.prototype.SendPostBack.call(this, params);
  }
 },
 GetMainElementId: function() {
  return this.name + ASPx.PCWIdSuffix + this.DefaultWindowIndex;
 },
 GetContentScrollbarsOwner: function() {
  return this.GetWindowContentElement(this.DefaultWindowIndex);
 },
 InlineInitialize: function() {
  ASPxClientPopupControl.prototype.InlineInitialize.call(this);
  var mainElement = this.GetMainElement();
  this.initialParentNode = mainElement.parentNode;
  mainElement.panelUID = this.panelUID;
  this.heightFixed = this.height > 0;
  ASPx.DockPanelBag.Get().RegisterPanel(this);
 },
 Initialize: function() {
  ASPxClientPopupControl.prototype.Initialize.call(this);
  this.AfterResizing.AddHandler(function(s, e) {
   s.StoreFloatingStateDimensions();
  });
  this.StartDragging.AddHandler(function(s, e) {
   if(!s.GetCollapsed() && s.floatingState) {
    var storedTrackDimensions = s.trackDimensions;
    s.trackDimensions = true;
    s.StoreFloatingStateDimensions();
    s.trackDimensions = storedTrackDimensions;
   }
  });
  this.Shown.AddHandler(function(s, e) {
   s.UpdateManagerClientLayoutState();
  });
  if(this.allowDragging)
   this.AssignDoubleClickEventHandlers();
 },
 InitializeWindow: function(index) {
  ASPxClientPopupControl.prototype.InitializeWindow.call(this, index);
  if(!this.GetShowOnPageLoad(index) && this.GetZoneUID()) {
   var savedShown = this.Shown,
    savedCloseUp = this.CloseUp,
    savedClosing = this.Closing,
    eventStub = new ASPxClientEvent();
   this.Shown = eventStub;
   this.CloseUp = eventStub;
   this.Closing = eventStub;
   this.allowEnsureContent = false;
   this.FirstShowWindow(index, false);
   this.Hide();
   this.allowEnsureContent = true;
   this.Shown = savedShown;
   this.CloseUp = savedCloseUp;
   this.Closing = savedClosing;
  }
 },
 InitializeZone: function() {
  var zoneUID = this.GetZoneUID();
  if(!zoneUID)
   return;
  var zoneList = ASPx.DockZoneBag.Get().GetZoneList();
  for(var i = 0; i < zoneList.length; i++) {
   if(zoneList[i].zoneUID === zoneUID) {
    this.zone = zoneList[i];
    break;
   }
  }
 },
 InitializeAccessibleNavigation: function() { },
 InitializeAccessibleNavigationCore: function() { },
 AssignDoubleClickEventHandlers: function() {
  if(this.isWindowDragging) {
   var mainElement = this.GetMainElement();
   ASPx.Evt.AttachEventToElement(mainElement, 'dblclick', this.GetDoubleClickHandler());
  } else {
   var header = this.GetWindowHeaderElement(this.DefaultWindowIndex);
   if(header)
    ASPx.Evt.AttachEventToElement(header, 'dblclick', this.GetDoubleClickHandler());
  }
 },
 GetDoubleClickHandler: function() {
  var headerBtns = [
   this.GetWindowCloseButton(this.DefaultWindowIndex),
   this.GetWindowPinButton(this.DefaultWindowIndex),
   this.GetWindowRefreshButton(this.DefaultWindowIndex),
   this.GetWindowCollapseButton(this.DefaultWindowIndex),
   this.GetWindowMaximizeButton(this.DefaultWindowIndex)
  ];
  var instance = this;
  return function(evt) {
   var source = ASPx.Evt.GetEventSource(evt);
   for(var i = 0; i < headerBtns.length; i++) {
    if(headerBtns[i] && ASPx.GetIsParent(headerBtns[i], source))
     return;
   }
   instance.ProcessMouseDoubleClick();
  };
 },
 StoreInitialSettings: function() {
  var contentCurrentStyle = ASPx.GetCurrentStyle(this.GetContentScrollbarsOwner());
  this.floatingStateContentOverflow.x = contentCurrentStyle.overflowX;
  this.floatingStateContentOverflow.y = contentCurrentStyle.overflowY;
  this.floatingStateContentOverflow.both = contentCurrentStyle.overflow;
  this.floatingStateDimensions.minWidth = this.minWidth;
  this.floatingStateDimensions.minHeight = this.minHeight;
  this.floatingStateDimensions.maxWidth = this.maxWidth;
  this.floatingStateDimensions.maxHeight = this.maxHeight;
  this.floatingStateAllowResize = this.allowResize;
  this.floatingStateEnableContentScrolling = this.enableContentScrolling;
  this.initialShadowVisible = this.shadowVisible;
 },
 SetPanelElementsVisibility: function(visible) {
  var elements = [
   this.GetWindowHeaderElement(this.DefaultWindowIndex),
   this.GetWindowContentElement(this.DefaultWindowIndex),
   this.GetWindowFooterElement(this.DefaultWindowIndex)
  ];
  for(var i = 0; i < elements.length; i++) {
   if(elements[i])
    ASPx.SetElementVisibility(elements[i], visible);
  }
 },
 GetIsDragged: function() {
  return true;
 },
 FirstShowWindow: function(index, allowChangeZIndex) {
  ASPxClientPopupControl.prototype.FirstShowWindow.call(this, index, allowChangeZIndex);
  this.SetPanelElementsVisibility(false);
  var iFrame = ASPx.GetNodeByTagName(this.GetMainElement(), 'IFRAME', 0);
  if(iFrame) 
   this.shouldProcessFirstShowWindow = true;
  else
   this.ProcessFirstShowWindow();
 },
 OnGlobalControlsInitialized: function(args) { 
  if(!this.shouldProcessFirstShowWindow) return;
  window.setTimeout(function() { this.ProcessFirstShowWindow(); }.aspxBind(this), 0);
  this.shouldProcessFirstShowWindow = false;
 },
 ProcessFirstShowWindow: function() {
  if(this.firstShowProcessed)
   return;
  if(this.GetIsCollapsed() || this.GetIsMaximized()) {
   var restoredWindowData = this.GetRestoredWindowData();
   this.StoreFloatingStateDimensionsCore(restoredWindowData.width, restoredWindowData.height);
   this.UpdateManagerClientLayoutState();
  } else
   this.StoreFloatingStateDimensions();
  this.DockOnFirstShow();
  if(this.requireFreezingLayout) {
   this.freezed = true;
   if(this.zone)
    this.DisableDragging();
  }
  this.SetPanelElementsVisibility(true);
  this.SetLastFloatState();
  this.firstShowProcessed = true;
  if(this.zone)
   this.zone.EnsurePanelsVisibleIndicesAfterFirstShow();
  this.ShowWindowContentUrl(this.DefaultWindowIndex);
 },
 LayoutCanBeObtained: function() {
  return this.firstShowProcessed || !this.GetZoneUID();
 },
 ShowWindowContentUrl: function(index) {
  if(this.firstShowProcessed)
   ASPxClientPopupControl.prototype.ShowWindowContentUrl.call(this, index);
 },
 ProcessMouseDoubleClick: function() {
  if(this.zone && !this.floatingState && this.mode != ASPxClientDockPanelModes.DockedOnly) {
   if(!this.GetLastFloatPosition()) {
    var position = this.GetDefaultUndockPosition();
    this.SetWindowLeft(this.DefaultWindowIndex, position.x);
    this.SetWindowTop(this.DefaultWindowIndex, position.y);
    this.UpdateWindowsStateCookie();
   }
   if(!this.RaiseBeforeFloat())
    return;
   this.zone.HidePanelPlaceholder();
   this.MakeFloatInternal(this.GetLastFloatPosition());
   if(this.stateObserver.IsBeingFloated())
    this.RaiseAfterFloat();
  }
  else if(this.mode === ASPxClientDockPanelModes.All) {
   if(this.GetIsMaximized(-1)) return;
   var lastDockedState = this.GetState().lastDockedState;
   var zone = ASPx.DockZoneBag.Get().GetZoneByUID(lastDockedState.zoneUID);
   if(!zone || !this.RaiseBeforeDock(zone))
    return;
   this.StoreFloatingStateDimensions();
   this.DockToLastZone();
   if(this.stateObserver.IsBeingDocked())
    this.RaiseAfterDock();
  }
 },
 GetState: function() {
  var state = this.dockState;
  return {
   zoneUID: state[0],
   visibleIndex: state[1],
   lastDockedState: {
    zoneUID: state[2],
    visibleIndex: state[3]
   },
   lastFloatState: {
    left: state[4],
    top: state[5]
   }
  };
 },
 GetZoneUID: function() {
  return this.GetState().zoneUID;
 },
 SetZoneUID: function(zoneUID) {
  var state = this.GetState();
  this.dockState = [zoneUID || '', state.visibleIndex, state.lastDockedState.zoneUID, state.lastDockedState.visibleIndex, state.lastFloatState.left, state.lastFloatState.top];
 },
 SetLastDockedState: function(lastDockedState) {
  var state = this.GetState();
  this.dockState = [state.zoneUID, state.visibleIndex, lastDockedState.zoneUID, lastDockedState.visibleIndex, state.lastFloatState.left, state.lastFloatState.top];
 },
 SetLastFloatState: function() {
  if(!this.floatingState)
   return;
  var state = this.GetState();
  var position = this.GetElementPosInInitialParentNode(this.GetMainElement());
  position.x = Math.round(position.x);
  position.y = Math.round(position.y);
  this.dockState = [state.zoneUID, state.visibleIndex, state.lastDockedState.zoneUID, state.lastDockedState.visibleIndex, position.x, position.y];
 },
 GetLastFloatPosition: function() {
  var lastFloatState = this.GetState().lastFloatState;
  if(lastFloatState.left && lastFloatState.top) {
   return {
    x: lastFloatState.left,
    y: lastFloatState.top
   };
  }
  return null;
 },
 GetLayoutStateObject: function() {
  return [
   this.GetVisible(),
   this.mode,
   this.GetZoneUID(),
   this.widthFixed ? (this.floatingStateDimensions.width + '') : '0',
   this.heightFixed ? (this.floatingStateDimensions.height + '') : '0',
   Math.ceil(this.GetCurrentLeft(this.DefaultWindowIndex)),
   Math.ceil(this.GetCurrentTop(this.DefaultWindowIndex)),
   this.GetVisibleIndex()
  ];
 },
 UpdateManagerClientLayoutState: function() {
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.UpdatePanelsLayoutState();
 },
 UpdateStateObject: function(){
  ASPxClientPopupControl.prototype.UpdateStateObject.call(this);
  this.UpdateStateObjectWithObject({ dockState: this.dockState });
 },
 GetCursorOverPanelLocation: function(cursorPos, panelSpacing, isHorizontal) {
  var mainElement = this.GetMainElement();
  var x = ASPx.GetAbsoluteX(mainElement);
  var y = ASPx.GetAbsoluteY(mainElement);
  var width = this.GetWidth();
  var height = this.GetHeight();
  if(isHorizontal)
   width += panelSpacing;
  else
   height += panelSpacing;
  if(cursorPos.x < x || cursorPos.x > x + width || cursorPos.y < y || cursorPos.y > y + height)
   return null;
  if(isHorizontal)
   return cursorPos.x > (x + width / 2) ? 'right' : 'left';
  return cursorPos.y > (y + height / 2) ? 'bottom' : 'top';
 },
 GetDockedDimensions: function(zoneResizableDimension, isHorizontal) {
  this.UpdateRestoredWindowSizeLock();
  var storedDimensions = this.floatingState ? this.floatingStateDimensions :
   { width: this.GetWidth(), height: this.GetHeight() };
  if(this.floatingState)
   this.EnableContentFlexibility();
  var storedContentFlexibilityEnabled = this.contentFlexibilityEnabled;
  var dimensions;
  if(isHorizontal) {
   if(this.floatingStateDimensions.height < zoneResizableDimension && !this.widthFixed) {
    if(storedContentFlexibilityEnabled)
     this.DisableContentFlexibility();
    this.SetSizeInternal(1, zoneResizableDimension);
    if(storedContentFlexibilityEnabled)
     this.EnableContentFlexibility();
   } else
    this.SetSizeInternal(this.floatingStateDimensions.width, zoneResizableDimension);
   dimensions = { width: this.GetWidth(), height: zoneResizableDimension };
  }
  else {
   if(this.floatingStateDimensions.width < zoneResizableDimension && !this.heightFixed) {
    if(storedContentFlexibilityEnabled)
     this.DisableContentFlexibility();
    this.SetSizeInternal(zoneResizableDimension, 1);
    if(storedContentFlexibilityEnabled)
     this.EnableContentFlexibility();
   } else
    this.SetSizeInternal(zoneResizableDimension, this.floatingStateDimensions.height);
   dimensions = { width: zoneResizableDimension, height: this.GetIsCollapsed() ? this.floatingStateDimensions.height : this.GetHeight() };
  }
  if(this.floatingState)
   this.DisableContentFlexibility();
  if(storedDimensions.width !== dimensions.width || storedDimensions.height !== dimensions.height)
   this.SetSizeInternal(storedDimensions.width, storedDimensions.height);
  this.UpdateRestoredWindowSizeUnlock();
  return dimensions;
 },
 StoreFloatingStateDimensions: function() {
  if(this.trackDimensions) {
   this.StoreFloatingStateDimensionsCore(this.GetWidth(), this.GetHeight());
   this.UpdateManagerClientLayoutState();
  }
 },
 StoreFloatingStateDimensionsCore: function(width, height) {
  this.floatingStateDimensions.width = width;
  this.floatingStateDimensions.height = height;
 },
 GetCurrentWindowWidth: function(index) {
  if(!this.widthFixed)
   return ASPx.InvalidDimension;
  if(!this.floatingState)
   return this.floatingStateDimensions.width;
  return ASPxClientPopupControl.prototype.GetCurrentWindowWidth.call(this, index);
 },
 GetCurrentWindowHeight: function(index) {
  if(!this.heightFixed)
   return this.GetDefaultWindowHeight(index);
  if(!this.floatingState)
   return this.floatingStateDimensions.height;
  return ASPxClientPopupControl.prototype.GetCurrentWindowHeight.call(this, index);
 },
 GetDefaultWindowHeight: function(index) {
  var result = null;
  var useDockedDimensionsHeight = !this.dockedDimensionsCalculating && this.IsDocked() && this.CollapseExecuting();
  if(useDockedDimensionsHeight) {
   try {
    this.dockedDimensionsCalculating = true;
    result = this.GetDockingInfo().dimensions.height;
   }
   finally {
    this.dockedDimensionsCalculating = false;
   }
  }
  else
   result = ASPx.InvalidDimension;
  return result;
 },
 ShoulUpdatedRestoredWindowSizeOnCollapse: function(index) {
  var baseValue = ASPxClientPopupControl.prototype.ShoulUpdatedRestoredWindowSizeOnCollapse.call(this, index);
  return baseValue && this.floatingState;
 },
 SetShadowVisibility: function(visible) {
  this.shadowVisible = visible;
  this.SetShadowVisibilityLite(visible);
 },
 SetShadowVisibilityLite: function(visible) {
  var mainElement = this.GetWindowMainCell(this.GetMainElement());
  var shadowClassName = ASPx.PopupControlCssClasses.ShadowLiteCssClassName;
  if(visible) {
   if(!ASPx.ElementHasCssClass(mainElement, shadowClassName))
    mainElement.className = ASPx.Str.Trim(mainElement.className) + ' ' + shadowClassName;
  } else
   mainElement.className = ASPx.Str.Trim(mainElement.className.replace(shadowClassName, ''));
 },
 EnableContentFlexibility: function() {
  var contentElement = this.GetContentScrollbarsOwner();
  this.enableContentScrolling = true;
  this.contentFlexibilityEnabled = true;
  contentElement.style.overflow = 'auto';
  contentElement.style.overflowX = 'auto';
  contentElement.style.overflowY = 'auto';
  this.minWidth = null;
  this.minHeight = null;
  this.maxWidth = null;
  this.maxHeight = null;
  this.contentFlexibilityEnabled = true;
 },
 DisableContentFlexibility: function() {
  var contentElement = this.GetContentScrollbarsOwner();
  contentElement.style.overflow = this.floatingStateContentOverflow.both;
  contentElement.style.overflowX = this.floatingStateContentOverflow.x;
  contentElement.style.overflowY = this.floatingStateContentOverflow.y;
  this.enableContentScrolling = this.floatingStateEnableContentScrolling;
  this.minWidth = this.floatingStateDimensions.minWidth;
  this.minHeight = this.floatingStateDimensions.minHeight;
  this.maxWidth = this.floatingStateDimensions.maxWidth;
  this.maxHeight = this.floatingStateDimensions.maxHeight;
  this.contentFlexibilityEnabled = false;
 },
 SetAllowResize: function(allowResize) {
  this.allowResize = allowResize;
  this.SetAllowResizeLite(allowResize);
 },
 SetAllowResizeLite: function(allowResize) {
  var windowElement = this.GetWindowElement(this.DefaultWindowIndex);
  var windowMainCell = this.GetWindowMainCell(windowElement);
  var windowHeader = this.GetWindowHeaderElement(this.DefaultWindowIndex);
  var sizeGrip = this.GetWindowSizeGripElement(this.DefaultWindowIndex);
  var storedHanlder = this.GetWindowElementMouseMoveEventHandler(this.DefaultWindowIndex);
  if(allowResize) {
   ASPx.Attr.RestoreStyleAttribute(windowElement, 'cursor');
   ASPx.Evt.AttachEventToElement(windowElement, 'mousemove', storedHanlder);
  } else {
   ASPx.Attr.ChangeStyleAttribute(windowElement, 'cursor', 'default');
   ASPx.Attr.RemoveStyleAttribute(windowMainCell, 'cursor');
   if(windowHeader)
    windowHeader.style.cursor = 'move';
   ASPx.Evt.DetachEventFromElement(windowElement, 'mousemove', storedHanlder);
  }
  if(sizeGrip)
   ASPx.SetElementDisplay(sizeGrip, allowResize);
 },
 ResizeForDock: function(dockedDimensions) {
  this.SetSizeInternal(dockedDimensions.width, dockedDimensions.height);
 },
 OnResize: function(evt, index, cursor, resizePanel) {
  ASPxClientPopupControl.prototype.OnResize.call(this, evt, index, cursor, resizePanel);
  this.widthFixed = cursor.horizontalDirection == "w" || cursor.horizontalDirection == "e";
  this.heightFixed = cursor.verticalDirection == "n" || cursor.verticalDirection == "s";
 },
 needToHidePinnedOutFromViewPort: function(index) {
  return !this.zone && ASPxClientPopupControl.prototype.needToHidePinnedOutFromViewPort.call(this, index);
 },
 Fixate: function() {
  var mainElement = this.GetMainElement();
  var offset = {
   x: mainElement.offsetLeft,
   y: mainElement.offsetTop
  };
  mainElement.style.left = offset.x + 'px';
  mainElement.style.top = offset.y + 'px';
  mainElement.style.position = 'absolute';
  this.fixated = true;
 },
 RemoveFixation: function() {
  var mainElement = this.GetMainElement();
  mainElement.style.position = 'static';
  this.fixated = false;
 },
 EnsureContent: function(windowIndex, isInit) {
  if(this.contentLoadingMode != 'OnDock' && this.contentLoadingMode != 'OnFloating' &&
   this.contentLoadingMode != 'OnDockStateChange' && this.allowEnsureContent) {
   ASPxClientPopupControl.prototype.EnsureContent.call(this, windowIndex, isInit);
  }
 },
 OnCallbackInternal: function(html, windowIndex, isError) {
  ASPxClientPopupControl.prototype.OnCallbackInternal.call(this, html, windowIndex, isError);
  ASPx.SetElementVisibility(this.GetContentContainer(windowIndex), true);
  var instance = this;
  window.setTimeout(function() {
   if(instance.completeSwitchingToFloatingStateOnCallback) {
    instance.CompleteSwitchingToFloatingState();
    instance.completeSwitchingToFloatingStateOnCallback = false;
   }
   instance.StoreFloatingStateDimensions();
  }, 0);
 },
 LoadContent: function() {
  var mainElement = this.GetMainElement();
  if(!mainElement.loading) {
   mainElement.loading = true;
   this.CreateWindowCallback(this.DefaultWindowIndex, this.DefaultWindowIndex);
  }
 },
 DisableDragging: function() {
  this.allowDragging = false;
  var elements = [
   this.GetWindowHeaderElement(this.DefaultWindowIndex),
   this.GetWindowMainCell(this.GetMainElement())
  ];
  for(var i = 0; i < elements.length; i++) {
   if(elements[i])
    elements[i].style.cursor = 'default';
  }
 },
 OnDragStart: function(evt, index) {
  if(!this.allowDragging || this.animationLocked)
   return;
  this.ApplyZonesAllowedStyle();
  this.ApplyZonesForbiddenStyle();
  var instance = this;
  window.setTimeout(function() {
   ASPxClientPopupControl.prototype.OnDragStart.call(instance, evt, index);
  }, 0);
 },
 OnDrag: function(index, x, y, xClientCorrection, yClientCorrection, evt) {
  var retValue = ASPxClientPopupControl.prototype.OnDrag.call(this, index, x, y, xClientCorrection, yClientCorrection);
  if(!this.inUndockedState && !this.animationLocked) {
   this.trackDimensions = false;
   var cursorPos = {
    x: ASPx.Evt.GetEventX(evt),
    y: ASPx.Evt.GetEventY(evt)
   };
   if(this.zone) {
    this.UndockInternal(true);
    ASPxClientPopupControl.prototype.InitDragInfo.call(this, index, evt);
   }
   this.SearchForCurrentZone(cursorPos);
   this.RaiseStartDragging();
   this.inUndockedState = true;
  }
  var popupCollection = ASPx.GetPopupControlCollection();
  var cursorPos = {
   x: x - popupCollection.gragXOffset,
   y: y - popupCollection.gragYOffset
  };
  if(!evt.ctrlKey)
   this.SearchForCurrentZone(cursorPos);
  else if(this.zone) {
   this.zone.HidePanelPlaceholder();
   this.zone = null;
  }
  return retValue;
 },
 SearchForCurrentZone: function(cursorPos) {
  var newZone = null;
  var innerZone = null;
  var keepOldZonePlaceholder = false;
  var zoneList = ASPx.DockZoneBag.Get().GetZoneList();
  for(var i = 0; i < zoneList.length; i++) {
   var zone = zoneList[i];
   if(zone.IsCursorInsideZone(cursorPos)) {
    if(!!this.zone) {
     if(this.zone.zoneUID === zone.zoneUID) 
      var keepOldZonePlaceholder = true;
     else {
      if(this.zone.ContainsZone(zone) && (!innerZone || innerZone.ContainsZone(zone)))
       innerZone = zone;
     }
    }
    newZone = zone;
   }
  }
  if(keepOldZonePlaceholder && !innerZone) {
   this.zone.MovePanelPlaceholder(cursorPos);
   return;
  }
  if(this.zone) {
   this.zone.HidePanelPlaceholder();
   this.zone = null;
  }
  if(newZone) {
   this.zone = !!innerZone ? innerZone : newZone;
   this.zone.MovePanelPlaceholder(cursorPos);
   this.zone.ShowPanelPlaceholder(this);
  }
 },
 OnDragStop: function(index) {
  ASPxClientPopupControl.prototype.OnDragStop.call(this, index);
  this.RemoveZonesAllowedStyle();
  this.RemoveZonesForbiddenStyle();
  if(!this.inUndockedState)
   return;
  this.inUndockedState = false;
  this.RaiseEndDragging();
  var dockingInfo = this.GetDockingInfo();
  if(dockingInfo && dockingInfo.canDock && this.RaiseBeforeDock(this.zone)) {
   this.DockInternal(dockingInfo.dimensions);
   return;
  }
  if(this.zone)
   this.zone.HidePanelPlaceholder();
  var lastDockedState = this.GetState().lastDockedState;
  if(this.mode === ASPxClientDockPanelModes.DockedOnly && lastDockedState.zoneUID) {
   this.stateObserver.trackState = false;
   this.DockToLastZone();
   this.stateObserver.trackState = true;
   return;
  }
  if(this.stateObserver.IsBeingDocked() && !this.RaiseBeforeFloat()) {
   this.stateObserver.trackState = false;
   this.DockToLastZone();
   this.stateObserver.trackState = true;
   return;
  }
  this.SwitchToFloatingState();
  this.SetLastFloatState();
  if(this.stateObserver.IsBeingFloated())
   this.RaiseAfterFloat();
 },
 IsZoneForbidden: function(zone) {
  for(var i = 0; i < this.forbiddenZones.length; i++) {
   if(this.forbiddenZones[i] === zone.zoneUID)
    return true;
  }
  return false;
 },
 GetDockingInfo: function() {
  if(!this.zone)
   return null;
  var dockedDimensions = null;
  var canDock = this.mode != ASPxClientDockPanelModes.FloatOnly && !this.freezed && !this.IsZoneForbidden(this.zone);
  if(canDock) {
   if(this.zone.IsFillOrientation()) {
    dockedDimensions = { width: this.zone.initialWidth, height: this.zone.initialHeight };
    canDock &= this.zone.CanDockPanel();
   } else {
    var isHorizontalZone = this.zone.IsHorizontalOrientation();
    var zoneResizableDimension = isHorizontalZone ? this.zone.initialHeight : this.zone.initialWidth;
    dockedDimensions = this.GetDockedDimensions(zoneResizableDimension, isHorizontalZone);
    canDock &= this.zone.CanDockPanel(isHorizontalZone ? dockedDimensions.width : dockedDimensions.height);
   }
  }
  return {
   canDock: canDock,
   dimensions: dockedDimensions
  };
 },
 SwitchToFloatingState: function() {
  var isFloatingStateChanging = !this.floatingState;
  var requireContentUpdate = isFloatingStateChanging &&
   (this.contentLoadingMode === 'OnFloating' || this.contentLoadingMode === 'OnDockStateChange');
  this.zone = null;
  this.floatingState = true;
  if(this.floatingStateAllowResize)
   this.SetAllowResize(true);
  this.DisableContentFlexibility();
  if(requireContentUpdate) {
   this.LoadContent();
   this.completeSwitchingToFloatingStateOnCallback = true;
  } else
   this.CompleteSwitchingToFloatingState(!isFloatingStateChanging);
 },
 CompleteSwitchingToFloatingState: function(lockSizeChanging) {
  this.UpdateRestoredWindowSizeLock();
  this.stateObserver.UpdateState();
  if(!lockSizeChanging)
   this.SetSizeInternal(this.floatingStateDimensions.width, this.floatingStateDimensions.height);
  this.trackDimensions = true;
  if(!this.GetIsCollapsed())
   this.StoreFloatingStateDimensions();
  if(this.IsVisible())
   this.AdjustContentOnDockStateChanged();
  this.UpdateManagerClientLayoutState();
  this.UpdateRestoredWindowSizeUnlock();
 },
 CompleteDocking: function(mainElement, dockedDimensions, onFirstShow, directOrder) {
  this.zone.DockPanel(this, dockedDimensions, onFirstShow, directOrder);
  this.stateObserver.UpdateState();
  mainElement.style.position = 'static';
  var requireRefreshContent = this.stateObserver.IsBeingDocked() &&
   (this.contentLoadingMode === 'OnDock' || this.contentLoadingMode === 'OnDockStateChange');
  if(requireRefreshContent)
   this.LoadContent();
  if(!onFirstShow)
   this.RaiseAfterDock();
  this.UpdateManagerClientLayoutState();
  this.zone.AdjustControlCore();
  if(this.IsVisible())
   this.AdjustContentOnDockStateChanged();
  this.SetLastDockedState({ zoneUID: this.GetZoneUID(), visibleIndex: this.GetVisibleIndex() });
  var windowIFrame = this.FindWindowIFrame(this.DefaultWindowIndex);
  if(windowIFrame)
   ASPx.SetElementDisplay(windowIFrame, false);
  if(this.animationLocked)
   this.animationLocked = false;
  this.UpdateRestoredWindowSizeUnlock();
  this.HideNativeScrollbarsOnAndroid();
  if(this.GetCollapsed()) {
   var restoredWindowData = ASPxClientPopupControl.prototype.GetRestoredWindowData.call(this);
   if(restoredWindowData.width && restoredWindowData.height)
    this.StoreFloatingStateDimensionsCore(restoredWindowData.width, restoredWindowData.height);
  }
 },
 HideNativeScrollbarsOnAndroid: function() {
  if(ASPx.Browser.AndroidMobilePlatform) {
   var contentElement = this.GetContentScrollbarsOwner();
   contentElement.style.overflow = 'hidden';
   contentElement.style.overflowX = 'hidden';
   contentElement.style.overflowY = 'hidden';
  }
 },
 AdjustContentOnDockStateChanged: function() {
  var contentElement = this.GetContentContainer(this.DefaultWindowIndex);
  ASPx.GetControlCollection().AdjustControls(contentElement);
 },
 DockOnFirstShow: function() {
  var zoneUID = this.GetZoneUID();
  if(!zoneUID)
   return;
  this.InitializeZone(); 
  if(this.zone)
   this.zone.AdjustControl();
  this.trackDimensions = false;
  var dockingInfo = this.GetDockingInfo();
  if(dockingInfo && dockingInfo.canDock)
   this.DockInternal(dockingInfo.dimensions, true, true);
  else
   this.SwitchToFloatingState();
 },
 DockToLastZone: function() {
  var lastDockedState = this.GetState().lastDockedState;
  if(!lastDockedState.zoneUID)
   return;
  var zoneBag = ASPx.DockZoneBag.Get();
  var zone = zoneBag.GetZoneByUID(lastDockedState.zoneUID);
  if(zone)
   this.Dock(zone, lastDockedState.visibleIndex);
 },
 DockInternal: function(dockedDimensions, onFirstShow, directOrder) {
  this.UpdateRestoredWindowSizeLock();
  var mainElement = this.GetMainElement();
  this.floatingState = false;
  if(this.floatingStateAllowResize)
   this.SetAllowResize(false);
  if(this.initialShadowVisible)
   this.SetShadowVisibility(false);
  this.EnableContentFlexibility();
  if(this.zone.IsHorizontalOrientation())
   ASPx.SetElementFloat(mainElement, 'left');
  if(this.enableAnimation && !onFirstShow)
   this.StartDockAnimation(mainElement, dockedDimensions);
  else
   this.CompleteDocking(mainElement, dockedDimensions, onFirstShow, directOrder);
 },
 UndockInternal: function(showPlaceholder) {
  var mainElement = this.GetMainElement();
  var position = this.GetUndockToPosition();
  if(showPlaceholder) {
   this.zone.FixatePanels(this);
   this.zone.MovePanelPlaceholderToPanel(this);
  }
  this.initialParentNode.appendChild(mainElement);
  mainElement.style.position = 'absolute';
  ASPx.SetElementFloat(mainElement, 'none');
  this.SetWindowPos(this.DefaultWindowIndex, mainElement, position.x, position.y);
  if(!this.IsVisible()) {
   this.SetWindowLeft(this.DefaultWindowIndex, position.x);
   this.SetWindowTop(this.DefaultWindowIndex, position.y);
  }
  if(this.initialShadowVisible)
   this.SetShadowVisibility(true);
  this.zone.UndockPanel(this);
  if(showPlaceholder)
   this.zone.RemovePanelsFixation();
  var windowIFrame = this.FindWindowIFrame(this.DefaultWindowIndex);
  if(windowIFrame)
   ASPx.SetElementDisplay(windowIFrame, true);
  this.zone = null;
 },
 GetUndockToPosition: function() {
  var mainElement = this.GetMainElement();
  if(this.IsVisible())
   return this.GetElementPosInInitialParentNode(mainElement);
  var storedDisplay = mainElement.style.display;
  mainElement.style.display = 'block';
  var position = this.GetElementPosInInitialParentNode(mainElement);
  mainElement.style.display = storedDisplay;
  return position;
 },
 MakeFloatInternal: function(position) {
  if(this.floatingState)
   return;
  this.UndockInternal();
  this.SwitchToFloatingState();
  if(!position)
   position = this.GetDefaultUndockPosition();
  this.SetWindowPos(this.DefaultWindowIndex, this.GetMainElement(), position.x, position.y);
  if(!this.IsVisible()) {
   this.SetWindowLeft(this.DefaultWindowIndex, position.x);
   this.SetWindowTop(this.DefaultWindowIndex, position.y);
  }
 },
 GetDefaultUndockPosition: function() {
  var undockToPos = this.GetUndockToPosition();
  return {
   x: undockToPos.x + this.UndockOnDoubleClickOffset,
   y: undockToPos.y + this.UndockOnDoubleClickOffset
  };
 },
 StartDockAnimation: function(mainElement, dockedDimensions) {
  this.animationLocked = true;
  mainElement.animationIterationCount = 0;
  mainElement.dockedDimensions = dockedDimensions;
  mainElement.destPosition = this.zone.GetPanelPlaceholderPositionForElement(mainElement);
  mainElement.isHorizontalZone = this.zone.IsHorizontalOrientation();
  this.IntializeAnimationOffsets(mainElement, dockedDimensions);
  mainElement.animationStart = new Date();
  this.HandleDockAnimation();
 },
 IntializeAnimationOffsets: function(mainElement, dockedDimensions) {
  var intialHeight = this.GetHeight();
  var initialWidth = this.GetWidth();
  var position = this.GetElementPosInInitialParentNode(mainElement);
  mainElement.moveAnimationOffset = {
   horizontal: position.x > mainElement.destPosition.x ? -this.AnimationOffset : this.AnimationOffset,
   vertical: position.y > mainElement.destPosition.y ? -this.AnimationOffset : this.AnimationOffset
  };
  mainElement.resizeAnimationOffset = {
   horizontal: initialWidth > dockedDimensions.width ? -this.AnimationOffset : this.AnimationOffset,
   vertical: intialHeight > dockedDimensions.height ? -this.AnimationOffset : this.AnimationOffset
  };
 },
 GetAnimationState: function(mainElement) {
  var moveIterationCoeff = Math.log(mainElement.animationIterationCount);
  var resizeIterationCoeff = Math.sqrt(mainElement.animationIterationCount);
  var position = this.GetElementPosInInitialParentNode(mainElement);
  var dimensions = {
   width: this.GetWidth(),
   height: this.GetHeight()
  };
  var newPosition = {
   x: position.x + moveIterationCoeff * mainElement.moveAnimationOffset.horizontal,
   y: position.y + moveIterationCoeff * mainElement.moveAnimationOffset.vertical
  };
  var newDimensions = {
   width: dimensions.width + resizeIterationCoeff * mainElement.resizeAnimationOffset.horizontal,
   height: dimensions.height + resizeIterationCoeff * mainElement.resizeAnimationOffset.vertical
  };
  var positionReached = {
   x: mainElement.moveAnimationOffset.horizontal > 0 ?
    newPosition.x >= mainElement.destPosition.x :
    newPosition.x <= mainElement.destPosition.x,
   y: mainElement.moveAnimationOffset.vertical > 0 ?
    newPosition.y >= mainElement.destPosition.y :
    newPosition.y <= mainElement.destPosition.y
  };
  var dimensionReached = {
   width: mainElement.resizeAnimationOffset.horizontal > 0 ?
    newDimensions.width >= mainElement.dockedDimensions.width :
    newDimensions.width <= mainElement.dockedDimensions.width,
   height: mainElement.resizeAnimationOffset.vertical > 0 ?
    newDimensions.height >= mainElement.dockedDimensions.height :
    newDimensions.height <= mainElement.dockedDimensions.height
  };
  return {
   newPosition: newPosition,
   newDimensions: newDimensions,
   positionReached: positionReached,
   dimensionReached: dimensionReached
  };
 },
 HandleDockAnimation: function() {
  var mainElement = this.GetMainElement();
  mainElement.animationIterationCount++;
  var state = this.GetAnimationState(mainElement);
  var finished = (state.positionReached.x && state.positionReached.y && state.dimensionReached.width &&
   state.dimensionReached.height) || (new Date() - mainElement.animationStart > this.MaxAnimationTime);
  if(finished) {
   this.CompleteDocking(mainElement, mainElement.dockedDimensions);
   return;
  }
  this.SetWindowPos(this.DefaultWindowIndex, mainElement,
   state.positionReached.x ? mainElement.destPosition.x : state.newPosition.x,
   state.positionReached.y ? mainElement.destPosition.y : state.newPosition.y);
  this.SetSizeInternal(state.dimensionReached.width ? mainElement.dockedDimensions.width : state.newDimensions.width,
   state.dimensionReached.height ? mainElement.dockedDimensions.height : state.newDimensions.height);
  var instance = this;
  window.setTimeout(function() { instance.HandleDockAnimation(); }, this.AnimationDelay);
 },
 ShowLoadingPanel: function(windowIndex) {
  ASPx.SetElementVisibility(this.GetContentContainer(windowIndex), false);
  ASPxClientPopupControl.prototype.ShowLoadingPanel.call(this, windowIndex);
 },
 ApplyZonesAllowedStyle: function() {
  this.ProcessZones(this.GetAllowedZones(), function(zone) {
   zone.ApplyDockingAllowedStyle();
  });
 },
 RemoveZonesAllowedStyle: function() {
  this.ProcessZones(this.GetAllowedZones(), function(zone) {
   zone.RemoveDockingAllowedStyle();
  });
 },
 ApplyZonesForbiddenStyle: function() {
  this.ProcessZones(this.GetForbiddenZones(), function(zone) {
   zone.ApplyDockingForbiddenStyle();
  });
 },
 RemoveZonesForbiddenStyle: function() {
  this.ProcessZones(this.GetForbiddenZones(), function(zone) {
   zone.RemoveDockingForbiddenStyle();
  });
 },
 ProcessZones: function(zones, action) {
  for(var i = 0; i < zones.length; i++)
   action(zones[i]);
 },
 GetForbiddenZones: function() {
  var forbiddenZones = [];
  var zoneBag = ASPx.DockZoneBag.Get();
  for(var i = 0; i < this.forbiddenZones.length; i++) {
   var zone = zoneBag.GetZoneByUID(this.forbiddenZones[i]);
   if(zone)
    forbiddenZones.push(zone);
  }
  return forbiddenZones;
 },
 GetAllowedZones: function() {
  var zoneCollection = ASPx.DockZoneBag.Get().GetZoneList();
  var allowedZones = [];
  for(var i = 0; i < zoneCollection.length; i++) {
   var zone = zoneCollection[i];
   if(!this.IsZoneForbidden(zone))
    allowedZones.push(zone);
  }
  return allowedZones;
 },
 GetBeforeDockPostbackArgs: function(zone) {
  return [
   this.RaiseBeforeDockEventCommand,
   zone.zoneUID,
   zone.GetPanelAfterPlaceholderVisibleIndex() + 1
  ];
 },
 GetBeforeFloatPostbackArgs: function() {
  return [
   this.RaiseBeforeFloatEventCommand,
   this.GetState().lastDockedState.zoneUID
  ];
 },
 GetAfterFloatPostbackArgs: function() {
  return [
   this.RaiseAfterFloatEventCommand,
   this.GetState().lastDockedState.zoneUID
  ];
 },
 RaiseBeforeDock: function(zone) {
  var processOnServer = this.IsServerEventAssigned(this.BeforeDockServerEventName);
  var args = new ASPxClientDockPanelProcessingModeCancelEventArgs(processOnServer, zone);
  if(!this.BeforeDock.IsEmpty())
   this.BeforeDock.FireEvent(this, args);
  if(!args.cancel && args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetBeforeDockPostbackArgs(zone);
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  var dockManager = ASPxClientDockManager.Get();
  return !args.cancel && zone.RaiseBeforeDock(this) &&
   (dockManager ? dockManager.RaiseBeforeDock(this, zone) : true);
 },
 RaiseAfterDock: function() {
  var processOnServer = this.IsServerEventAssigned(this.AfterDockServerEventName);
  var args = new ASPxClientProcessingModeEventArgs(processOnServer);
  if(!this.AfterDock.IsEmpty())
   this.AfterDock.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   this.SendPostBack(ASPx.Json.ToJson([this.RaiseAfterDockEventCommand]));
   return;
  }
  this.zone.RaiseAfterDock(this);
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaiseAfterDock(this, this.zone);
 },
 RaiseBeforeFloat: function() {
  var processOnServer = this.IsServerEventAssigned(this.BeforeFloatServerEventName);
  var zone = ASPx.DockZoneBag.Get().GetZoneByUID(this.GetState().lastDockedState.zoneUID);
  var args = new ASPxClientDockPanelProcessingModeCancelEventArgs(processOnServer, zone);
  if(!this.BeforeFloat.IsEmpty())
   this.BeforeFloat.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetBeforeFloatPostbackArgs();
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager && !args.cancel)
   return dockManager.RaiseBeforeFloat(this, zone);
  return !args.cancel;
 },
 RaiseAfterFloat: function() {
  var processOnServer = this.IsServerEventAssigned(this.AfterFloatServerEventName);
  var zone = ASPx.DockZoneBag.Get().GetZoneByUID(this.GetState().lastDockedState.zoneUID);
  var args = new ASPxClientDockPanelProcessingModeEventArgs(processOnServer, zone);
  if(!this.AfterFloat.IsEmpty())
   this.AfterFloat.FireEvent(this, args);
  if(args.processOnServer && this.isInitialized) {
   var postbackArgs = this.GetAfterFloatPostbackArgs();
   this.SendPostBack(ASPx.Json.ToJson(postbackArgs));
   return;
  }
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager) {
   dockManager.RaiseAfterFloat(this, zone);
  }
 },
 RaiseStartDragging: function() {
  if(!this.StartDragging.IsEmpty())
   this.StartDragging.FireEvent(this, new ASPxClientEventArgs());
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaiseStartPanelDragging(this);
 },
 RaiseEndDragging: function() {
  if(!this.EndDragging.IsEmpty())
   this.EndDragging.FireEvent(this, new ASPxClientEventArgs());
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaiseEndPanelDragging(this);
 },
 RaiseClosing: function(index, closeReason) {
  var dockManager = ASPxClientDockManager.Get();
  var managerCancel = false;
  if(dockManager)
   managerCancel = dockManager.RaisePanelClosing(this);
  if(!this.Closing.IsEmpty())
   return ASPxClientPopupControl.prototype.RaiseClosing.call(this, index, closeReason);
  return managerCancel;
 },
 RaiseCloseUp: function(index, closeReason) {
  ASPxClientPopupControl.prototype.RaiseCloseUp.call(this, index, closeReason);
  this.UpdateManagerClientLayoutState(); 
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaisePanelCloseUp(this);
 },
 RaisePopUp: function(index) {
  ASPxClientPopupControl.prototype.RaisePopUp.call(this, index);
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaisePanelPopUp(this);
 },
 RaiseShown: function(index) {
  ASPxClientPopupControl.prototype.RaiseShown.call(this, index);
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaisePanelShown(this);
 },
 RaiseResize: function(index, resizeState) {
  ASPxClientPopupControl.prototype.RaiseResize.call(this, index, resizeState);
  var dockManager = ASPxClientDockManager.Get();
  if(dockManager)
   dockManager.RaisePanelResize(this);
 },
 DoShowWindowAtPos: function(index, x, y, ignorePopupElement, closeOtherWindows, allowChangeZIndex, closeOtherReason) {
  if(this.floatingState) {
   ASPxClientPopupControl.prototype.DoShowWindowAtPos.call(this, index, x, y, ignorePopupElement,
    false, allowChangeZIndex, closeOtherReason);
   this.StoreInitialSettings();
   return;
  }
  var visible = ASPxClientPopupControl.prototype.InternalIsWindowVisible.call(this, this.DefaultWindowIndex);
  if(visible)
   return;
  this.RaisePopUp(this.DefaultWindowIndex);
  var mainElement = this.GetMainElement();
  mainElement.style.display = this.storedMainElementDisplay;
  ASPx.SetElementVisibility(mainElement, true);
  this.AdjustContentOnShow(index);
  this.ApplyPanelCachedSize(index);
  if(this.zone) {
   this.zone.UpdatePanelsVisibleIndices();
   this.zone.ApplyPanelSpacing();
   this.zone.CorrectResizableDimensionCore();
  }
  this.registerAndActivateWindow(mainElement, index, allowChangeZIndex);
  this.UpdateWindowsStateCookie();
  ASPxClientPopupControl.prototype.OnWindowShown.call(this, this.DefaultWindowIndex);
 },
 ApplyPanelCachedSize: function() {
  var cachedSize = this.GetWindowCachedSize(this.DefaultWindowIndex);
  if(cachedSize != null) {
   this.SetWindowSizeInternal(this.GetWindow(this.DefaultWindowIndex), cachedSize.width, cachedSize.height);
   this.ResetWindowCachedSize(this.DefaultWindowIndex);
  }
 },
 DoHideWindowCore: function(index) {
  this.MakeFloatBeforeHideInZoneWithFillOrientation();
  var mainElement = this.GetMainElement();
  this.storedMainElementDisplay = mainElement.style.display;
  ASPxClientPopupControl.prototype.DoHideWindowCore.call(this, index);
  if(this.zone) {
   this.zone.UpdatePanelsVisibleIndices();
   this.zone.ApplyPanelSpacing();
   this.zone.CorrectResizableDimensionCore();
  }
 },
 MakeFloatBeforeHideInZoneWithFillOrientation: function() {
  if(this.zone && this.zone.IsFillOrientation() && !this.floatingState)
   this.MakeFloatInternal();
 },
 DoCollapse: function(index, minimization) {
  ASPxClientPopupControl.prototype.DoCollapse.call(this, index, minimization);
  if(this.zone)
   this.zone.CorrectResizableDimension();
 },
 SetWindowSize: function(window, width, height) {
  if(this.floatingState) {
   this.SetWindowSizeInternal(window, width, height);
   if(!this.IsVisible()) {
    this.StoreFloatingStateDimensionsCore(width, height);
    this.UpdateManagerClientLayoutState();
   }
   return;
  }
  this.StoreFloatingStateDimensionsCore(width, height);
  this.UpdateManagerClientLayoutState();
 },
 SetSize: function(width, height) {
  ASPxClientPopupControl.prototype.SetSize.call(this, width, height);
  this.widthFixed = true;
  this.heightFixed = true;
 },
 SetWidth: function(width) {
  ASPxClientPopupControl.prototype.SetWidth.call(this, width);
  this.widthFixed = true;
 },
 SetHeight: function(height) {
  ASPxClientPopupControl.prototype.SetHeight.call(this, height);
  this.heightFixed = true;
 },
 SetSizeInternal: function(width, height) {
  this.SetWindowSizeInternal(null, width, height);
 },
 SetHeightInternal: function(height) {
  this.SetSizeInternal(this.GetWidth(), height);
 },
 SetWidthInternal: function(width) {
  this.SetSizeInternal(width, this.GetHeight());
 },
 SetWindowSizeInternal: function(window, width, height) {
  ASPxClientPopupControl.prototype.SetWindowSize.call(this, window, width, height);
 },
 GetOwnerZone: function() {
  if(!this.zone && !this.firstShowProcessed)
   this.InitializeZone();
  return this.zone;
 },
 Dock: function(zone, visibleIndex) {
  var destinationZoneExists = zone && zone.zoneUID;
  if(!destinationZoneExists || this.IsDockInSamePlace(zone, visibleIndex))
   return;
  if(this.IsDockInSameZone(zone)) {
   this.SetVisibleIndex(visibleIndex);
   return;
  }
  if(this.zone)
   this.MakeFloatInternal();
  this.zone = zone;
  this.trackDimensions = false;
  var dockingInfo = this.GetDockingInfo();
  var canDock = dockingInfo && dockingInfo.canDock;
  if(!canDock) {
   this.zone = null;
   return;
  }
  this.SetVisibleIndexCore(ASPx.IsExists(visibleIndex) ?
   visibleIndex : this.zone.GetDockedPanelsMaxVisibleIndex() + 1);
  this.DockInternal(dockingInfo.dimensions, true, false);
  this.zone.UpdatePanelsVisibleIndices();
 },
 MakeFloat: function(x, y) {
  if(ASPx.IsExists(x) && ASPx.IsExists(y))
   this.MakeFloatInternal({ x: x, y: y });
  else
   this.MakeFloatInternal();
 },
 GetVisibleIndex: function() {
  return this.GetState().visibleIndex;
 },
 SetVisibleIndex: function(visibleIndex) {
  if(this.floatingState) {
   this.SetVisibleIndexCore(visibleIndex);
   return;
  }
  this.zone.GetMainElement().insertBefore(this.GetMainElement(), this.GetInsertBeforePanelNode(visibleIndex));
  this.zone.UpdatePanelsVisibleIndices();
  this.zone.ApplyPanelSpacing();
 },
 IsDocked: function() {
  return !!this.zone;
 },
 SetVisibleIndexCore: function(visibleIndex) {
  var state = this.GetState();
  this.dockState = [state.zoneUID, visibleIndex, state.lastDockedState.zoneUID, state.lastDockedState.visibleIndex, state.lastFloatState.left, state.lastFloatState.top];
 },
 IsDockInSameZone: function(destinationZone) {
  return this.zone && this.zone.zoneUID === destinationZone.zoneUID;
 },
 IsDockInSamePlace: function(destinationZone, visibleIndex) {
  if(!this.IsDockInSameZone(destinationZone))
   return false;
  var dockedPanels = this.zone.GetOrderedPanelsList();
  return ASPx.IsExists(visibleIndex) ?
   this.GetVisibleIndex() === visibleIndex : dockedPanels[dockedPanels.length - 1].panelUID === this.panelUID;
 },
 GetInsertBeforePanelNode: function(visibleIndex) {
  var panels = this.zone.GetOrderedPanelsList();
  var result = [];
  for(var i = 0; i < panels.length; i++) {
   if(panels[i].panelUID !== this.panelUID && panels[i].IsVisible())
    result.push(panels[i]);
  }
  var insertBeforePanel = result[visibleIndex];
  return insertBeforePanel ? insertBeforePanel.GetMainElement() : null;
 },
 GetElementPosInInitialParentNode: function(element) {
  return {
   x: ASPx.PrepareClientPosElementForOtherParent(ASPx.GetAbsoluteX(element), element, this.initialParentNode, true),
   y: ASPx.PrepareClientPosElementForOtherParent(ASPx.GetAbsoluteY(element), element, this.initialParentNode, false)
  };
 },
 OnMaximizeButtonClick: function(index) {
  var maximizing = !this.GetIsMaximized(index);
  if(maximizing) {
   this.dockRestorePanelData = { zone: this.GetOwnerZone() };
   if(this.dockRestorePanelData.zone) {
    this.dockRestorePanelData.visibleIndex = this.GetVisibleIndex();
    this.MakeFloat();
   }
  }
  ASPxClientPopupControl.prototype.OnMaximizeButtonClick.call(this, index);
  if(!maximizing) {
   if(this.dockRestorePanelData && this.dockRestorePanelData.zone)
    this.Dock(this.dockRestorePanelData.zone, this.dockRestorePanelData.visibleIndex);
   this.dockRestorePanelData = null;
  }
 },
 GetRestoredWindowData: function(index) {
  var restoredWindowData = ASPxClientPopupControl.prototype.GetRestoredWindowData.call(this, index);
  if(this.zone) {
   restoredWindowData.width = this.UseZoneSize(true) ? ASPx.GetClearClientWidth(this.zone.GetMainElement()) : this.GetCurrentWindowWidth(index);
   restoredWindowData.height = this.UseZoneSize(false) ? ASPx.GetClearClientHeight(this.zone.GetMainElement()) : this.GetCurrentWindowHeight(index);
  }
  return restoredWindowData;
 },
 UseZoneSize: function(isWidth) {
  return this.zone.IsFillOrientation() || isWidth && !this.zone.IsHorizontalOrientation() || !isWidth && this.zone.IsHorizontalOrientation();
 }
});
ASPxClientDockPanel.Cast = ASPxClientControl.Cast;
var ASPxClientDockPanelProcessingModeCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
 constructor: function(processOnServer, zone) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.zone = zone;
 }
});
var ASPxClientDockPanelProcessingModeEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(processOnServer, zone) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.zone = zone;
 }
});
window.ASPxClientDockPanelModes = ASPxClientDockPanelModes;
window.ASPxClientDockPanel = ASPxClientDockPanel;
window.ASPxClientDockPanelProcessingModeCancelEventArgs = ASPxClientDockPanelProcessingModeCancelEventArgs;
window.ASPxClientDockPanelProcessingModeEventArgs = ASPxClientDockPanelProcessingModeEventArgs;
})();

(function() {
var MVCxClientDockPanel = ASPx.CreateClass(ASPxClientDockPanel, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 PerformCallback: function(data, onSuccess) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientDockPanel.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function() {
  if(this.callbackUrl != "")
   this.callBack = function(arg) { MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, null, this.callbackCustomArgs); };
  ASPxClientDockPanel.prototype.InlineInitialize.call(this);
 },
 InitializeWindow: function(index) {
  this.TryToLoadStateFromDockManager();
  ASPxClientDockPanel.prototype.InitializeWindow.call(this, index);
 },
 TryToLoadStateFromDockManager: function() {
  if(ASPx.Ident.scripts.ASPxClientDockManager && ASPxClientDockManager.Get()) {
   var panelLayoutState = ASPxClientDockManager.Get().clientLayoutState[this.panelUID];
   if(!panelLayoutState) return;
   this.showOnPageLoad = !!panelLayoutState[0];
   this.mode = panelLayoutState[1];
   this.SetZoneUID(panelLayoutState[2]);
   var width = parseInt(panelLayoutState[3].replace('px', '')),
    height = parseInt(panelLayoutState[4].replace('px', ''));
   this.width = width;
   this.height = height;
   this.left = panelLayoutState[5];
   this.top = panelLayoutState[6];
   this.SetVisibleIndexCore(panelLayoutState[7]);
  }
 },
 DoHideWindowCore: function(index) {
  if(!this.GetWindowCachedSize(index))
   this.SetWindowCachedSize(index, this.GetWidth(), this.GetHeight());
  ASPxClientDockPanel.prototype.DoHideWindowCore.call(this, index);
 },
 GetLayoutStateObject: function() {
  var state = ASPxClientDockPanel.prototype.GetLayoutStateObject.call(this);
  if(!parseInt(state[3]))
   state[3] = this.GetStoredDimensionValue(true);
  if(!parseInt(state[4]))
   state[4] = this.GetStoredDimensionValue(false);
  return state;
 },
 GetStoredDimensionValue: function(isWidth) {
  var cachedSize = this.GetWindowCachedSize();
  var dimensionValue = cachedSize ? cachedSize[isWidth ? "width" : "height"] : this[isWidth ? "GetWidth" : "GetHeight"]();
  return dimensionValue + '';
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 CreateCallbackCore: function(arg, command, callbackID){
  if(this.callbackCustomArgs != {})
   window.setTimeout(function(){ this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientDockPanel.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 EvalCallbackResult: function(resultString) {
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2) {
   var resultObj = ASPxClientDockPanel.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientDockPanel.prototype.EvalCallbackResult.call(this, resultString);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientDockPanel.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientDockPanel.Cast = ASPxClientControl.Cast;
window.MVCxClientDockPanel = MVCxClientDockPanel;
})();

(function() {
var ASPxClientEditBase = ASPx.CreateClass(ASPxClientControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.EnabledChanged = new ASPxClientEvent();
  this.captionPosition = ASPx.Position.Left;
  this.showCaptionColon = true;
  this.scPrefix = "dxe";
 },
 InlineInitialize: function(){
  ASPxClientControl.prototype.InlineInitialize.call(this);
  this.InitializeEnabled(); 
  this.InitializeEvents();
 },
 InitializeEnabled: function() {
  this.SetEnabledInternal(this.clientEnabled, true);
 },
 InitializeEvents: function() { },
 AddDefaultReadOnlyStateControllerItem: function(cssClass, mainElementId) {
  ASPx.AddReadOnlyItems(mainElementId, [[[cssClass], [''], ['']]]);
 },
 AddDefaultDisabledStateControllerItem: function(cssClass, mainElementId) {
  ASPx.AddDisabledItems(mainElementId, [[[cssClass], [''], ['']]]);
 },
 GetValue: function() {
  var element = this.GetMainElement();
  if(ASPx.IsExistsElement(element))
   return element.innerHTML;
  return "";
 },
 GetValueString: function(){
  var value = this.GetValue();
  return (value == null) ? null : value.toString();
 },
 EnsureValueStringIsActual: function() {
  if(this.maskInfo != null)
   this.ParseValue();
 },
 SetValue: function(value) {
  if(value == null)
   value = "";
  var element = this.GetMainElement();
  if(ASPx.IsExistsElement(element))
   element.innerHTML = value;
 },
 GetEnabled: function(){
  return this.enabled && this.clientEnabled;
 },
 SetEnabled: function(enabled){
  if(this.clientEnabled != enabled) {
   var errorFrameRequiresUpdate = this.GetIsValid && !this.GetIsValid();
   if(errorFrameRequiresUpdate && !enabled)
    this.UpdateErrorFrameAndFocus(false , null , true );
   this.clientEnabled = enabled;
   this.SetEnabledInternal(enabled, false);
   if(errorFrameRequiresUpdate && enabled)
    this.UpdateErrorFrameAndFocus(false );
   this.RaiseEnabledChangedEvent();
  }
 },
 SetEnabledInternal: function(enabled, initialization){
  if(!this.enabled) return;
  if(!initialization || !enabled)
   this.ChangeEnabledStateItems(enabled);
  this.ChangeEnabledAttributes(enabled);
  if(ASPx.Browser.Chrome) {   
   var mainElement = this.GetMainElement();
   if(mainElement)
    mainElement.className = mainElement.className;
  } 
 },
 ChangeEnabledAttributes: function(enabled){
 },
 ChangeEnabledStateItems: function(enabled){
 },
 RaiseEnabledChangedEvent: function(){
  if(!this.EnabledChanged.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.EnabledChanged.FireEvent(this, args);
  }
 },
 GetDecodeValue: function (value) { 
  if(typeof (value) == "string" && value.length > 1)
   value = this.SimpleDecodeHtml(value);
  return value;
 },
 SimpleDecodeHtml: function (html) {
  return ASPx.Str.ApplyReplacement(html, [
   [/&lt;/g, '<'],
   [/&amp;/g, '&'],
   [/&quot;/g, '"'],
   [/&#39;/g, '\''],
   [/&#32;/g, ' ']
  ]);
 },
 GetCachedElementById: function(idSuffix) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.name + idSuffix);
 },
 GetCaptionCell: function() {
  return this.GetCachedElementById(EditElementSuffix.CaptionCell);
 },
 GetExternalTable: function() {
  return this.GetCachedElementById(EditElementSuffix.ExternalTable);
 },
 getCaptionRelatedCellCount: function() {
  if(!this.captionRelatedCellCount)
   this.captionRelatedCellCount = ASPx.GetNodesByClassName(this.GetExternalTable(), CaptionRelatedCellClassName).length;
  return this.captionRelatedCellCount;
 },
 addCssClassToCaptionRelatedCells: function() {
  if(this.captionPosition == ASPx.Position.Left || this.captionPosition == ASPx.Position.Right) {
   var captionRelatedCellsIndex = this.captionPosition == ASPx.Position.Left ? 0 : this.GetCaptionCell().cellIndex;
   for(var i = 0; i < this.GetExternalTable().rows.length; i++)
    ASPx.AddClassNameToElement(this.GetExternalTable().rows[i].cells[captionRelatedCellsIndex], CaptionRelatedCellClassName);
  }
  if(this.captionPosition == ASPx.Position.Top || this.captionPosition == ASPx.Position.Bottom)
   for(var i = 0; i < this.GetCaptionCell().parentNode.cells.length; i++)
    ASPx.AddClassNameToElement(this.GetCaptionCell().parentNode.cells[i], CaptionRelatedCellClassName);
 },
 GetCaption: function() {
  if(ASPx.IsExists(this.GetCaptionCell()))
   return this.getCaptionInternal();
  return "";
 },
 SetCaption: function(caption) {
  if(!ASPx.IsExists(this.GetCaptionCell()))
   return;
  if(this.getCaptionRelatedCellCount() == 0)
   this.addCssClassToCaptionRelatedCells();
  if(caption !== "")
   ASPx.RemoveClassNameFromElement(this.GetExternalTable(), ASPxEditExternalTableClassNames.TableWithEmptyCaptionClassName);
  else
   ASPx.AddClassNameToElement(this.GetExternalTable(), ASPxEditExternalTableClassNames.TableWithEmptyCaptionClassName);
  this.setCaptionInternal(caption);
 },
 getCaptionTextNode: function() {
  var captionElement = ASPx.GetNodesByPartialClassName(this.GetCaptionCell(), CaptionElementPartialClassName)[0];
  return ASPx.GetNormalizedTextNode(captionElement);
 },
 getCaptionInternal: function() {
  var captionText = this.getCaptionTextNode().nodeValue;
  if(captionText !== "" && captionText[captionText.length - 1] == ":")
   captionText = captionText.substring(0, captionText.length - 1);
  return captionText;
 },
 setCaptionInternal: function(caption) {
  caption = ASPx.Str.Trim(caption);
  var captionTextNode = this.getCaptionTextNode();
  if(this.showCaptionColon && caption[caption.length - 1] != ":" && caption !== "")
   caption += ":";
  captionTextNode.nodeValue = caption;
 },
 onVirtualKeyboardUITouchStart: function(evt) { }
});
var ValidationPattern = ASPx.CreateClass(null, {
 constructor: function(errorText) {
  this.errorText = errorText;
 }
});
var RequiredFieldValidationPattern = ASPx.CreateClass(ValidationPattern, {
 constructor: function(errorText) {
  this.constructor.prototype.constructor.call(this, errorText);
 },
 EvaluateIsValid: function(value) {
  return value != null && (value.constructor == Array || ASPx.Str.Trim(value.toString()) != "");
 }
});
var RegularExpressionValidationPattern = ASPx.CreateClass(ValidationPattern, {
 constructor: function(errorText, pattern) {
  this.constructor.prototype.constructor.call(this, errorText);
  this.pattern = pattern;
 },
 EvaluateIsValid: function(value) {
  if(value == null) 
   return true;
  var strValue = value.toString();
  if(ASPx.Str.Trim(strValue).length == 0)
   return true;
  var regEx = new RegExp(this.pattern);
  var matches = regEx.exec(strValue);
  return matches != null && strValue == matches[0];
 }
});
function _aspxIsEditorFocusable(inputElement) {
 return ASPx.IsFocusableCore(inputElement, function(container) {
  return container.getAttribute("errorFrame") == "errorFrame";
 });
}
var invalidEditorToBeFocused = null;
var ValidationType = {
 PersonalOnValueChanged: "ValueChanged",
 PersonalViaScript: "CalledViaScript",
 MassValidation: "MassValidation"
};
var ErrorFrameDisplay = {
 None: "None",
 Static: "Static",
 Dynamic: "Dynamic"
};
var EditElementSuffix = {
 ExternalTable: "_ET",
 ControlCell: "_CC",
 ErrorCell: "_EC",
 ErrorTextCell: "_ETC",
 ErrorImage: "_EI",
 CaptionCell: "_CapC",
 AccessibilityAdditionalTextRow: "_AHTR"
};
var ASPxEditExternalTableClassNames = {
 ValidStaticTableClassName: "dxeValidStEditorTable",
 ValidDynamicTableClassName: "dxeValidDynEditorTable",
 TableWithEmptyCaptionClassName: "tableWithEmptyCaption"
};
var CaptionRelatedCellClassName = "dxeCaptionRelatedCell";
var CaptionElementPartialClassName = "dxeCaption";
var AccessibilityAssistantID = "AcAs";
var ASPxClientEdit = ASPx.CreateClass(ASPxClientEditBase, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.isASPxClientEdit = true;
  this.inputElement = null;
  this.convertEmptyStringToNull = true;
  this.readOnly = false;
  this.clientReadOnly = false;
  this.focused = false;
  this.focusEventsLocked = false;
  this.focusEventsLockCount = 0;
  this.receiveGlobalMouseWheel = true;
  this.styleDecoration = null;
  this.heightCorrectionRequired = false;
  this.customValidationEnabled = false;
  this.display = ErrorFrameDisplay.Static;
  this.initialErrorText = "";
  this.causesValidation = false;
  this.validateOnLeave = true;
  this.validationGroup = "";
  this.sendPostBackWithValidation = null;
  this.validationPatterns = [];
  this.setFocusOnError = false;
  this.errorDisplayMode = "it";
  this.errorText = "";
  this.isValid = true;
  this.errorImageIsAssigned = false;
  this.notifyValidationSummariesToAcceptNewError = false;
  this.isErrorFrameRequired = false;
  this.enterProcessed = false;
  this.keyDownHandlers = {};
  this.keyPressHandlers = {};
  this.keyUpHandlers = {};
  this.onKeyDownHandler = null;
  this.onKeyPressHandler = null;
  this.onKeyUpHandler = null;
  this.onGotFocusHandler = null;
  this.onLostFocusHandler = null;
  this.GotFocus = new ASPxClientEvent();
  this.LostFocus = new ASPxClientEvent();
  this.Validation = new ASPxClientEvent();
  this.ValueChanged = new ASPxClientEvent();
  this.KeyDown = new ASPxClientEvent();
  this.KeyPress = new ASPxClientEvent();
  this.KeyUp = new ASPxClientEvent();
  this.eventHandlersInitialized = false;
  this.errorCellVisibilityChanged = new ASPxClientEvent();
  this.ariaExplanatoryTextManager = null;
  this.InitializeEventHandlers();
 },
 SetData: function(data){
  if(data.decorationStyles){
   for(var i = 0; i < data.decorationStyles.length; i++)
    this.AddDecorationStyle(data.decorationStyles[i].key, 
     data.decorationStyles[i].className, 
     data.decorationStyles[i].cssText);
  }
 },
 Initialize: function() {
  this.initialErrorText = this.errorText;
  ASPxClientEditBase.prototype.Initialize.call(this);
  this.InitializeKeyHandlers();
  this.UpdateClientValidationState();
  this.UpdateValidationSummaries(null , true );
 },
 InlineInitialize: function() {
  if(this.UseDelayedSpecialFocus())
   this.InitializeDelayedSpecialFocus();
  ASPxClientEditBase.prototype.InlineInitialize.call(this);
  this.UpdateStyleDecorations();
  var externalTable = this.GetExternalTable();
  if(externalTable && ASPx.IsPercentageSize(externalTable.style.width)) {
   this.width = "100%";
   this.GetMainElement().style.width = "100%";
   if(this.isErrorFrameRequired)
    externalTable.setAttribute("errorFrame", "errorFrame");
  }
  this.ariaExplanatoryTextManager = this.CreateAriaExplanatoryTextManager();
  if(this.clientReadOnly)
   this.SetReadOnlyInternal(true);
  this.UpdateErrorCellParentRowVisibility();
 }, 
 AfterInitialize: function() {
  this.ariaExplanatoryTextManager.SetCaptionAssociating();
  this.ariaExplanatoryTextManager.UpdateText();
  this.ariaExplanatoryTextManager.UpdateValidationState();
  ASPxClientEditBase.prototype.AfterInitialize.call(this);
 },
 UpdateStyleDecorations: function() {
  if(this.styleDecoration)
   this.styleDecoration.Update();
 },
 UseSpecialKeyboardHandling: function() {
  return false;
 },
 InitializeKeyHandlers: function() {
 },
 AddKeyDownHandler: function(key, handler) {
  this.keyDownHandlers[key] = handler;
 },
 AddKeyPressHandler: function(key, handler) {
  this.keyPressHandlers[key] = handler;
 },
 InitializeEventHandlers: function() {
  this.onGotFocusHandler = function(evt) { ASPx.EGotFocus(this.name); }.bind(this);
  this.onLostFocusHandler = function(evt) { ASPx.ELostFocus(this.name); }.bind(this);
  if(this.UseSpecialKeyboardHandling()) {
   this.onKeyDownHandler = function(evt) { ASPx.KBSIKeyDown(this.name, evt); }.bind(this);
   this.onKeyPressHandler = function(evt) { ASPx.KBSIKeyPress(this.name, evt); }.bind(this);
   this.onKeyUpHandler = function(evt) { ASPx.KBSIKeyUp(this.name, evt); }.bind(this);
  }
 },
 ChangeSpecialInputEnabledAttributes: function(element, method, doNotChangeAutoComplete) {
  if(!doNotChangeAutoComplete) 
   element.autocomplete = "off";
  if(this.onKeyDownHandler != null)
   method(element, "keydown", this.onKeyDownHandler);
  if(this.onKeyPressHandler != null)
   method(element, "keypress", this.onKeyPressHandler);
  if(this.onKeyUpHandler != null)
   method(element, "keyup", this.onKeyUpHandler);
  if(this.onGotFocusHandler != null)
   method(element, "focus", this.onGotFocusHandler);
  if(this.onLostFocusHandler != null)
   method(element, "blur", this.onLostFocusHandler);
 },
 CreateAriaExplanatoryTextManager: function() {
  if(this.accessibilityCompliant)
   return new EditAccessibilityExplanatoryTextManager(this);
  else 
   return new DisableAccessibilityExplanatoryTextManager(this);
 },
 UpdateClientValidationState: function() {
  if(!this.customValidationEnabled)
   return;
  var mainElement = this.GetMainElement();
  if(mainElement) {
   var validationState = !this.GetIsValid() ? ("-" + this.GetErrorText()) : "";
   this.UpdateStateObjectWithObject({ validationState: validationState });
  }
 },
 UpdateValidationSummaries: function(validationType, initializing) {
  if(ASPx.Ident.scripts.ASPxClientValidationSummary) {
   var summaryCollection = ASPx.GetClientValidationSummaryCollection();
   summaryCollection.OnEditorIsValidStateChanged(this, validationType, initializing && this.notifyValidationSummariesToAcceptNewError);
  }
 },
 FindInputElement: function(){
  return null;
 },
 GetInputElement: function(){
  if(!ASPx.IsExistsElement(this.inputElement))
   this.inputElement = this.FindInputElement();
  return this.inputElement;
 },
 GetFocusableInputElement: function() {
  return this.GetInputElement();
 },
 GetAccessibilityActiveElements: function() {
  return [this.GetInputElement()];
 },
 GetAccessibilityFirstActiveElement: function() {
  return this.accessibilityHelper ? 
    this.accessibilityHelper.getMainElement() : 
    this.GetAccessibilityActiveElements()[0];
 },
 GetAccessibilityAssistantElement: function() {
  return this.GetChildElement(AccessibilityAssistantID);
 },
 GetErrorImage: function() {
  return this.GetCachedElementById(EditElementSuffix.ErrorImage);
 },
 GetControlCell: function() {
  return this.GetCachedElementById(EditElementSuffix.ControlCell);
 },
 GetErrorCell: function() {
  return this.GetCachedElementById(EditElementSuffix.ErrorCell);
 },
 GetErrorTextCell: function() {
  return this.GetCachedElementById(this.errorImageIsAssigned ? EditElementSuffix.ErrorTextCell : EditElementSuffix.ErrorCell);
 },
 GetReadOnly: function() {
  return this.readOnly || this.clientReadOnly;
 },
 SetReadOnly: function(readOnly) {
  readOnly = !!readOnly;
  if(this.clientReadOnly === readOnly || this.readOnly)
   return;
  this.SetReadOnlyInternal(readOnly);
 },
 SetReadOnlyInternal: function(readOnly) {
  this.clientReadOnly = readOnly;
  this.ChangeReadOnlyStateItems(readOnly);
 },
 ChangeReadOnlyStateItems: function(readOnly) {
  ASPx.GetStateController().SetElementReadOnly(this.GetMainElement(), readOnly);
 },
 SetVisible: function (isVisible) {
  if(this.clientVisible == isVisible)
   return;
  var externalTable = this.GetExternalTable();
  if(externalTable) {
   ASPx.SetElementDisplay(externalTable, isVisible);
   if(this.customValidationEnabled) {
    var isValid = !isVisible ? true : void (0);
    this.UpdateErrorFrameAndFocus(false , true , isValid );
   }
  }
  ASPxClientControl.prototype.SetVisible.call(this, isVisible);
 },
 GetStateHiddenFieldName: function() {
  return this.uniqueID + "$State";
 },
 GetValueInputToValidate: function() {
  return this.GetInputElement();
 },
 IsVisible: function() {
  if(!this.clientVisible)
   return false;
  var element = this.GetMainElement();
  if(!element) 
   return false;
  while(element && element.tagName != "BODY") {
   if(element.getAttribute("errorFrame") != "errorFrame" && (!ASPx.GetElementVisibility(element) || !ASPx.GetElementDisplay(element)))
    return false;
   element = element.parentNode;
  }
  return true;
 },
 AdjustControlCore: function() {
  this.CollapseEditor();
  this.UnstretchInputElement();
  if(this.heightCorrectionRequired)
   this.CorrectEditorHeight();
 },
 CorrectEditorHeight: function() {
 },
 UnstretchInputElement: function() {
 },
 UseDelayedSpecialFocus: function() {
  return false;
 },
 GetInnerEditors: function() {
  return [];
 },
 GetDelayedSpecialFocusTriggers: function() {
  return [ this.GetMainElement() ];
 },
 InitializeDelayedSpecialFocus: function() {
  this.specialFocusTimer = -1;    
  var handler = function(evt) { this.OnDelayedSpecialFocusMouseDown(evt); }.aspxBind(this);
  var triggers = this.GetDelayedSpecialFocusTriggers();
  for(var i = 0; i < triggers.length; i++)
   ASPx.Evt.AttachEventToElement(triggers[i], "mousedown", handler);
 },
 OnDelayedSpecialFocusMouseDown: function(evt) {
  window.setTimeout(function() { this.SetFocus(); }.aspxBind(this), 0);
 },
 IsFocusEventsLocked: function() {
  return this.focusEventsLocked || this.focusEventsLockCount !== 0;
 },
 BeginFocusUpdate: function() {
  this.focusEventsLockCount++;
 },
 EndFocusUpdate: function() {
  this.focusEventsLockCount--;
  if(this.focusEventsLockCount === 0)
   if(this.focused && !this.IsEditorElement(document.activeElement)) 
    this.OnLostFocus();
 },
 LockFocusEvents: function() {
  if(!this.focused) return;
  this.focusEventsLocked = true;
 },
 UnlockFocusEvents: function() {
  this.focusEventsLocked = false;
 },
 ForceRefocusEditor: function(evt, isNativeFocus) {
  if(ASPx.Browser.VirtualKeyboardSupported && !this.ownerListBox) {
   var focusedEditor = ASPx.VirtualKeyboardUI.getFocusedEditor();
   if(ASPx.VirtualKeyboardUI.getInputNativeFocusLocked() && (!focusedEditor || focusedEditor === this))
     return;
   ASPx.VirtualKeyboardUI.setInputNativeFocusLocked(!isNativeFocus);
  }
  this.LockFocusEvents();
  this.BlurInputElement();
  window.setTimeout(function() { 
   if(ASPx.Browser.VirtualKeyboardSupported && !this.ownerListBox) {
    ASPx.VirtualKeyboardUI.setFocusToEditor(this);
   } else {
    this.SetFocus();
   }
  }.aspxBind(this), 0);
 },
 BlurInputElement: function() {
  var inputElement = this.GetFocusableInputElement();
  if(inputElement && inputElement.blur)
   inputElement.blur();
 },
 IsEditorElement: function(element) {
  return this.GetMainElement() == element || ASPx.GetIsParent(this.GetMainElement(), element);
 },
 IsClearButtonElement: function(element) {
  return false;
 },
 IsElementBelongToInputElement: function(element) {
  return this.GetInputElement() == element;
 },
 OnFocusCore: function() {
  if(this.UseDelayedSpecialFocus())
   this.specialFocusTimer = ASPx.Timer.ClearTimer(this.specialFocusTimer);
  if(!this.IsFocusEventsLocked()){
   this.focused = true;
   ASPx.SetFocusedEditor(this);
   if(this.styleDecoration)
    this.styleDecoration.Update();
   if(this.isInitialized)
    this.RaiseFocus();
  }
  else
   this.UnlockFocusEvents();
 },
 OnLostFocusCore: function() {
  if(!this.IsFocusEventsLocked()){
   this.focused = false;
   if(ASPx.GetFocusedEditor() === this)
    ASPx.SetFocusedEditor(null);
   if(this.styleDecoration)
    this.styleDecoration.Update();
   this.RaiseLostFocus();
  }
 },
 OnFocus: function() {
  var focusedEditor = ASPx.GetFocusedEditor();
  if(focusedEditor && focusedEditor.UseDelayedSpecialFocus() && focusedEditor !== this && focusedEditor.GetInnerEditors().indexOf(this) === -1 && ASPx.IsElementVisible(focusedEditor.GetMainElement())) {
   var lostFocusHandler = function() {
    focusedEditor.LostFocus.RemoveHandler(lostFocusHandler);
    this.OnFocusCore();
   }.bind(this);
   focusedEditor.LostFocus.AddHandler(lostFocusHandler);
  }
  else {
   this.OnFocusCore();
  }  
 },
 OnLostFocus: function() {
  if(this.isInitialized)
   this.OnLostFocusCore();
 },
 OnMouseWheel: function(evt){
 },
 OnValidation: function(validationType) {
  if(this.customValidationEnabled && this.isInitialized && ASPx.IsExistsElement(this.GetMainElement()) &&
   (!this.IsErrorFrameDisplayed() || this.GetElementRequiredForErrorFrame())) {
   this.BeginErrorFrameUpdate();
   try {
    if(this.validateOnLeave || validationType != ValidationType.PersonalOnValueChanged) {
     this.SetIsValid(true, true );
     this.SetErrorText(this.initialErrorText, true );
     this.ValidateWithPatterns();
     this.RaiseValidation();
    }
    this.UpdateErrorFrameAndFocus(this.editorFocusingRequired(validationType));
   } finally {
    this.EndErrorFrameUpdate();
   }
   this.UpdateValidationSummaries(validationType);
   this.ariaExplanatoryTextManager.UpdateValidationState(validationType);
  }
 },
 GetElementRequiredForErrorFrame: function() {
  return this.GetExternalTable();
 },
 editorFocusingRequired: function(validationType) {
  return !this.GetIsValid() &&
   validationType == ValidationType.PersonalViaScript && this.setFocusOnError;
 },
 OnValueChanged: function() {
  if(this.getProcessOnServerOnValueChanged())
   this.SendPostBackInternal("");
 },
 getProcessOnServerOnValueChanged: function() {
  var processOnServer = this.RaiseValidationInternal();
  return this.RaiseValueChangedEvent() && processOnServer;
 },
 ParseValue: function() {
 },
 RaisePersonalStandardValidation: function() {
  if(ASPx.IsFunction(window.ValidatorOnChange)) {
   var inputElement = this.GetValueInputToValidate();
   if(inputElement && inputElement.Validators)
    window.ValidatorOnChange({ srcElement: inputElement });
  }
 },
 RaiseValidationInternal: function() {
  if(this.isPostBackAllowed() && this.causesValidation && this.validateOnLeave)
   return ASPxClientEdit.ValidateGroup(this.validationGroup);
  else {
   this.OnValidation(ValidationType.PersonalOnValueChanged);
   return this.GetIsValid();
  }
 },
 RaiseValueChangedEvent: function(){
  return this.RaiseValueChanged();
 },
 SendPostBackInternal: function(postBackArg) {
  if(ASPx.IsFunction(this.sendPostBackWithValidation))
   this.sendPostBackWithValidation(postBackArg);
  else
   this.SendPostBack(postBackArg);
 },
 SetElementToBeFocused: function() {
  if(this.IsVisible())
   invalidEditorToBeFocused = this;
 },
 GetFocusSelectAction: function() {
  return null;
 },
 SetFocus: function() {
  var inputElement = this.GetFocusableInputElement();
  if(!inputElement) return; 
  if((ASPx.GetActiveElement() != inputElement) && _aspxIsEditorFocusable(inputElement))
   ASPx.SetFocus(inputElement, this.GetFocusSelectAction());
 },
 SetFocusOnError: function() {
  if(invalidEditorToBeFocused == this) {
   this.SetFocus();
   invalidEditorToBeFocused = null;
  }
 },
 BeginErrorFrameUpdate: function() {
  if(!this.errorFrameUpdateLocked)
   this.errorFrameUpdateLocked = true;
 },
 EndErrorFrameUpdate: function() {
  this.errorFrameUpdateLocked = false;
  var args = this.updateErrorFrameAndFocusLastCallArgs;
  if(args) {
   this.UpdateErrorFrameAndFocus(args[0], args[1]);
   delete this.updateErrorFrameAndFocusLastCallArgs;
  }
 },
 UpdateErrorFrameAndFocus: function(setFocusOnError, ignoreVisibilityCheck, isValid) {
  if(!ignoreVisibilityCheck && !this.GetVisible())
   return;
  if(this.errorFrameUpdateLocked) {
   this.updateErrorFrameAndFocusLastCallArgs = [ setFocusOnError, ignoreVisibilityCheck ];
   return;
  }
  if(this.styleDecoration)
   this.styleDecoration.Update();
  if(typeof(isValid) == "undefined")
   isValid = this.GetIsValid();
  if(isValid && this.IsErrorFrameDisplayed())
   this.ChangeErrorFrameVisibility(false);
  else {
   var editorLocatedWithinVisibleContainer = this.IsVisible();
   if(this.IsErrorFrameDisplayed()) {
    this.UpdateErrorCellContent();
    this.ChangeErrorFrameVisibility(true);
   }
   if(editorLocatedWithinVisibleContainer) {
    if(setFocusOnError && this.setFocusOnError && invalidEditorToBeFocused == null) {
     this.SetElementToBeFocused();
     this.SetFocusOnError();
    }
   }
  }
 },
 ChangeErrorFrameVisibility: function(visible) {
  var externalTable = this.GetExternalTable();
  var isStaticDisplay = this.display == ErrorFrameDisplay.Static;
  if(!isStaticDisplay && visible) {
   this.EnsureControlCellStylesLoaded();
   this.RestoreControlCellStyles();
  }
  this.ChangeErrorCellVisibility(visible, isStaticDisplay);
  if(!isStaticDisplay && !visible) {
   this.EnsureControlCellStylesLoaded();
   this.ClearControlCellStyles();
  }
  var validExternalTableClassName = isStaticDisplay ? ASPxEditExternalTableClassNames.ValidStaticTableClassName
   : ASPxEditExternalTableClassNames.ValidDynamicTableClassName;
  ASPx.ToggleClassNameToElement(externalTable, validExternalTableClassName, !visible);
  this.UpdateErrorCellParentRowVisibility();
 },
 ChangeErrorCellVisibility: function(visible, useVisibilityAttribute) {
  var errorCell = this.GetErrorCell();
  if(errorCell) {
   if(useVisibilityAttribute)
    ASPx.SetElementVisibility(errorCell, visible);
   else {
    ASPx.SetElementDisplay(errorCell, visible);
    this.raiseErrorCellVisibilityChanged();
   }
  }
 },
 raiseErrorCellVisibilityChanged: function() {
  if(!this.errorCellVisibilityChanged.IsEmpty())
   this.errorCellVisibilityChanged.FireEvent(this);
 },
 UpdateErrorCellParentRowVisibility: function() {
  var errorCell = this.GetErrorCell();
  if(!errorCell || this.display == ErrorFrameDisplay.Static)
   return;
  var displayedCellCount = 0;
  var errorCellParentRow = errorCell.parentNode;
  for(var i = 0; i < errorCellParentRow.cells.length; i++) {
   var cell = errorCellParentRow.cells[i];
   if(ASPx.GetElementDisplay(cell))
    displayedCellCount++;
  }
  ASPx.SetElementDisplay(errorCellParentRow, displayedCellCount > 0);
 },
 EnsureControlCellStylesLoaded: function() {
  if(typeof(this.controlCellStyles) == "undefined") {
   var controlCell = this.GetControlCell();
   this.controlCellStyles = {
    cssClass: controlCell.className,
    style: this.ExtractElementStyleStringIgnoringVisibilityProps(controlCell)
   };
  }
 },
 ClearControlCellStyles: function() {
  this.ClearElementStyle(this.GetControlCell());
 },
 RestoreControlCellStyles: function() {
  var controlCell = this.GetControlCell();
  controlCell.className = this.controlCellStyles.cssClass;
  controlCell.style.cssText = this.controlCellStyles.style;
 },
 ExtractElementStyleStringIgnoringVisibilityProps: function(element) {
  var savedVisibility = element.style.visibility;
  var savedDisplay = element.style.display;
  element.style.visibility = "";
  element.style.display = "";
  var styleStr = element.style.cssText;
  element.style.visibility = savedVisibility;
  element.style.display = savedDisplay;
  return styleStr;
 },
 ClearElementStyle: function(element) {
  if(!element)
   return;
  element.className = "";
  var excludedAttrNames = [
   "width", "display", "visibility",
   "position", "left", "top", "z-index",
   "margin", "margin-top", "margin-right", "margin-bottom", "margin-left",
   "float", "clear"
  ];
  var savedAttrValues = { };
  for(var i = 0; i < excludedAttrNames.length; i++) {
   var attrName = excludedAttrNames[i];
   var attrValue = element.style[attrName];
   if(attrValue)
    savedAttrValues[attrName] = attrValue;
  }
  element.style.cssText = "";
  for(var styleAttrName in savedAttrValues)
   if(savedAttrValues.hasOwnProperty(styleAttrName))
    element.style[styleAttrName] = savedAttrValues[styleAttrName];
 },
 Clear: function() {
  this.SetValue(null);
  this.SetIsValid(true);
  return true;
 },
 ResetEditorState: function() { },
 UpdateErrorCellContent: function() {
  if(this.errorDisplayMode.indexOf("t") > -1)
   this.UpdateErrorText();
  if(this.errorDisplayMode == "i")
   this.UpdateErrorImage();
 },
 UpdateErrorImage: function() {
  var image = this.GetErrorImage();
  if(ASPx.IsExistsElement(image)) {
   if(this.accessibilityCompliant) {
    ASPx.Attr.SetAttribute(image, "aria-label", this.errorText);
    var innerImg = ASPx.GetNodeByTagName(image, "IMG", 0);
    if(ASPx.IsExists(innerImg))
     innerImg.alt = this.errorText;
   }
   image.alt = this.errorText;
   image.title = this.errorText;
  } else {
   this.UpdateErrorText();
  }
 },
 UpdateErrorText: function() {
  var errorTextCell = this.GetErrorTextCell();
  if(ASPx.IsExistsElement(errorTextCell))
   errorTextCell.innerHTML = this.HtmlEncode(this.errorText);
 },
 ValidateWithPatterns: function() {
  if(this.validationPatterns.length > 0) {
   var value = this.GetValue();
   for(var i = 0; i < this.validationPatterns.length; i++) {
    var validator = this.validationPatterns[i];
    if(!validator.EvaluateIsValid(value)) {
     this.SetIsValid(false, true );
     this.SetErrorText(validator.errorText, true );
     return;
    }
   }
  }
 },
 OnSpecialKeyDown: function(evt){
  this.RaiseKeyDown(evt);
  var handler = this.keyDownHandlers[evt.keyCode];
  if(handler) 
   return this[handler](evt);
  return false;
 },
 OnSpecialKeyPress: function(evt){
  this.RaiseKeyPress(evt);
  var handler = this.keyPressHandlers[evt.keyCode];
  if(handler) 
   return this[handler](evt);
  if(ASPx.Browser.NetscapeFamily || ASPx.Browser.Opera){
   if(evt.keyCode == ASPx.Key.Enter)
    return this.enterProcessed;
  }
  return false;
 },
 OnSpecialKeyUp: function(evt){
  this.RaiseKeyUp(evt);
  var handler = this.keyUpHandlers[evt.keyCode];
  if(handler) 
   return this[handler](evt);
  return false;
 },
 OnKeyDown: function(evt) {
  if(!this.UseSpecialKeyboardHandling())
   this.RaiseKeyDown(evt);
 },
 OnKeyPress: function(evt) {
  if(!this.UseSpecialKeyboardHandling())
   this.RaiseKeyPress(evt);
 },
 OnKeyUp: function(evt) {
  if(!this.UseSpecialKeyboardHandling())
   this.RaiseKeyUp(evt);
 },
 RaiseKeyDown: function(evt){
  if(!this.KeyDown.IsEmpty()){
   var args = new ASPxClientEditKeyEventArgs(evt);
   this.KeyDown.FireEvent(this, args);
  }
 },
 RaiseKeyPress: function(evt){
  if(!this.KeyPress.IsEmpty()){
   var args = new ASPxClientEditKeyEventArgs(evt);
   this.KeyPress.FireEvent(this, args);
  }
 },
 RaiseKeyUp: function(evt){
  if(!this.KeyUp.IsEmpty()){
   var args = new ASPxClientEditKeyEventArgs(evt);
   this.KeyUp.FireEvent(this, args);
  }
 },
 RaiseFocus: function(){
  if(!this.GotFocus.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.GotFocus.FireEvent(this, args);
  }
 },
 RaiseLostFocus: function(){
  if(!this.LostFocus.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.LostFocus.FireEvent(this, args);
  }
 },
 RaiseValidation: function() {
  if(this.customValidationEnabled && !this.Validation.IsEmpty()) {
   var currentValue = this.GetValue();
   var args = new ASPxClientEditValidationEventArgs(currentValue, this.errorText, this.GetIsValid());
   this.Validation.FireEvent(this, args);
   this.SetErrorText(args.errorText, true );
   this.SetIsValid(args.isValid, true );
   if(args.value != currentValue)
    this.SetValue(args.value);
  }
 },
 RaiseValueChanged: function(){
  var processOnServer = this.isPostBackAllowed();
  if(!this.ValueChanged.IsEmpty()){
   var args = new ASPxClientProcessingModeEventArgs(processOnServer);
   this.ValueChanged.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;  
 },
 isPostBackAllowed: function() {
  return this.autoPostBack;
 },
 AddDecorationStyle: function(key, className, cssText) {
  if(!this.styleDecoration) 
   this.RequireStyleDecoration();
  this.styleDecoration.AddStyle(key, className, cssText);
 }, 
 RequireStyleDecoration: function() {
  this.styleDecoration = this.CreateStyleDecoration();
  this.PopulateStyleDecorationPostfixes();
 },
 CreateStyleDecoration: function() {
  return new ASPx.EditorStyleDecoration(this);
 },
 PopulateStyleDecorationPostfixes: function() {
  this.styleDecoration.AddPostfix("");
 },
 LockStyleDecorationUpdate: function() {
  if(this.styleDecoration)
   this.styleDecoration.LockUpdate();
 },
 UnlockStyleDecorationUpdate: function() {
  if(this.styleDecoration)
   this.styleDecoration.UnlockUpdate();
 },
 Focus: function(){
  this.SetFocus();
 },
 GetIsValid: function() {
  var hasRequiredInputElement = !this.RequireInputElementToValidate() || ASPx.IsExistsElement(this.GetInputElement());
  if(!hasRequiredInputElement || this.IsErrorFrameDisplayed() && !ASPx.IsExistsElement(this.GetElementRequiredForErrorFrame()))
   return true;
  return this.isValid;
 },
 RequireInputElementToValidate: function() {
  return true;
 },
 IsErrorFrameDisplayed: function() {
  return this.display !== ErrorFrameDisplay.None;
 },
 GetErrorText: function(){
  return this.errorText;
 },
 SetIsValid: function(isValid, validating){
  if(this.customValidationEnabled && this.isValid != isValid) {
   this.isValid = isValid;
   this.UpdateErrorFrameAndFocus(false );
   this.UpdateClientValidationState();
   if(!validating)
    this.UpdateValidationSummaries(ValidationType.PersonalViaScript);
  }
 },
 SetErrorText: function(errorText, validating){
  if(this.customValidationEnabled && this.errorText != errorText) {
   this.errorText = errorText;
   this.UpdateErrorFrameAndFocus(false );
   this.UpdateClientValidationState();
   if(!validating)
    this.UpdateValidationSummaries(ValidationType.PersonalViaScript);
  }
 },
 Validate: function(){
  this.ParseValue();
  this.OnValidation(ValidationType.PersonalViaScript);
 },
 GetModifyEvent: function() {
  return this.ValueChanged;
 },
 EnsureRequiredNativeAttributesExists: function() { }
});
ASPx.Ident.scripts.ASPxClientEdit = true;
ASPx.focusedEditorName = "";
ASPx.GetFocusedEditor = function() {
 var focusedEditor = ASPx.GetControlCollection().Get(ASPx.focusedEditorName);
 if(focusedEditor && !focusedEditor.focused){
  ASPx.SetFocusedEditor(null);
  focusedEditor = null;
 }
 return focusedEditor;
};
ASPx.SetFocusedEditor = function(editor) {
 ASPx.focusedEditorName = editor ? editor.name : "";
};
ASPx.FindAssociatedLabelElements = function(editor) {
 var assocciatedLabels = [];
 var inputElement = editor.GetInputElement();
 if(!ASPx.IsExists(inputElement) || !inputElement.id) 
  return assocciatedLabels;
 var labels = ASPx.GetNodesByTagName(document, "LABEL");
 for(var i = 0; i < labels.length; i++) {
  if(!!labels[i].htmlFor && labels[i].htmlFor === inputElement.id)
   assocciatedLabels.push(labels[i]);
 }
 return assocciatedLabels;
};
var DisableAccessibilityExplanatoryTextManager = ASPx.CreateClass(null, {
 constructor: function(editor) {
  this.editor = editor;
 },
 GetAdditionalTextRowId: function() {
  return this.editor.name + EditElementSuffix.AccessibilityAdditionalTextRow;
 },
 GetErrorTextElement: function () {
  return !!this.editor.GetErrorTextCell() ? this.editor.GetErrorTextCell() : this.editor.GetErrorImage();
 },
 GetTextElement: function() { return null; },
 SetCaptionAssociating: function() { },
 UpdateText: function() { },
 UpdateValidationState: function(validationType) { },
 ToggleErrorAlert: function() { },
 SetOrRemoveText: function(accessibilityElements, textElement, setText, isLabel, isFirst) { }
});
var EditAccessibilityExplanatoryTextManager = ASPx.CreateClass(DisableAccessibilityExplanatoryTextManager, {
 constructor: function(editor) {
  this.constructor.prototype.constructor.call(this, editor);
  this.invisibleRowCssClassName = "dxAIR";
 },
 GetTextElement: function() {
  var mainElement = this.editor.GetMainElement();
  if(!mainElement) return null;
  var explanatoryText = "";
  var explanatoryTextElement = null;
  if(!!this.editor.nullText)
   explanatoryText = this.editor.nullText;
  else if(!!this.editor.helpTextObj)
   explanatoryTextElement = this.editor.helpTextObj.helpTextElement;
  else if(!!mainElement.title)
   explanatoryText = mainElement.title;
  if(explanatoryText && mainElement.tagName == "TABLE") {
   var assistantElement = this.editor.GetAccessibilityFirstActiveElement();
   if(assistantElement)
    ASPx.Attr.Aria.AppendLabel(assistantElement, explanatoryText, true);
  }
  return explanatoryTextElement;
 },
 SetCaptionAssociating: function() {
  var captionCell = this.editor.GetCaptionCell();
  if(!captionCell || captionCell.childNodes[0].tagName == "LABEL") return;
  var labelElement = captionCell.childNodes[0];
  ASPx.EditAccessibilityExplanatoryTextManager.SetLabelAssociating(this.editor, this.editor.GetAccessibilityFirstActiveElement(), labelElement);
 },
 UpdateText: function() {
  var additionalTextElement = this.GetTextElement();
  if(ASPx.IsExists(additionalTextElement)) {
   var pronounceElement = this.editor.GetAccessibilityFirstActiveElement();
   var hasAnyLabel = !!ASPx.Attr.GetAttribute(pronounceElement, "aria-label") || 
    !!ASPx.Attr.GetAttribute(pronounceElement, "aria-labelledby") ||
    ASPx.FindAssociatedLabelElements(this.editor).length > 0;
   this.SetOrRemoveText([pronounceElement], additionalTextElement, true, !hasAnyLabel, false);
  }
 },
 UpdateValidationState: function(validationType) {
  if(validationType == ValidationType.PersonalOnValueChanged && this.editor.accessibilityHelper) return;
  var accessibilityElements = this.editor.GetAccessibilityActiveElements();
  var errorTextElement = this.GetErrorTextElement();
  this.SetOrRemoveText(accessibilityElements, errorTextElement, !this.editor.isValid, false, true);
  if(accessibilityElements.length > 0 && !!errorTextElement) {
   for(var i = 0; i < accessibilityElements.length; i++) {
    if(!ASPx.IsExists(accessibilityElements[i])) continue;
    ASPx.Attr.SetOrRemoveAttribute(accessibilityElements[i], "aria-invalid", !this.editor.isValid);
   }
  }
 },
 ToggleErrorAlert: function() {
  var errorTextElement = this.GetErrorTextElement();
  ASPx.SetElementDisplay(errorTextElement, false);
  ASPx.Attr.SetAttribute(errorTextElement, 'role', 'alert');
  ASPx.SetElementDisplay(errorTextElement, true);
  setTimeout(function() { ASPx.Attr.RemoveAttribute(errorTextElement, 'role'); }, 500);
 },
 SetOrRemoveText: function(accessibilityElements, textElement, setText, isLabel, isFirst) {
  var idsRefAttribute = isLabel ? ASPx.Attr.Aria.labelled : ASPx.Attr.Aria.described;
  if(!textElement) return;
  var textId = !!textElement.id ? textElement.id : textElement.parentNode.id;
  for(var i = 0; i < accessibilityElements.length; i++) {
   if(!accessibilityElements[i]) continue;
   var descRefString = ASPx.Attr.GetAttribute(accessibilityElements[i], idsRefAttribute);
   var descRefIds = !!descRefString ? descRefString.split(" ") : [ ];
   var descIndex = descRefIds.indexOf(textId);
   if(setText && descIndex == -1) {
    if(isFirst)
     descRefIds.unshift(textId);
    else
     descRefIds.push(textId);
   }
   else if(!setText && descIndex > -1)
    descRefIds.splice(descIndex, 1);
   ASPx.Attr.SetOrRemoveAttribute(accessibilityElements[i], idsRefAttribute, descRefIds.join(" "));
  }
 }
});
ASPx.DisableAccessibilityExplanatoryTextManager = DisableAccessibilityExplanatoryTextManager;
ASPx.EditAccessibilityExplanatoryTextManager = EditAccessibilityExplanatoryTextManager;
ASPx.EditAccessibilityExplanatoryTextManager.SetLabelAssociating = function(editor, activeElement, labelElement) {
 var clickHandler = function(evt) {
  if(editor && editor.OnAssociatedLabelClick)
   editor.OnAssociatedLabelClick(evt);
  else
   activeElement.click();
 };
 ASPx.Evt.AttachEventToElement(labelElement, "click", clickHandler);
 if(!!editor) {
  var hasAriaLabel = !!ASPx.Attr.GetAttribute(activeElement, "aria-label");
  editor.ariaExplanatoryTextManager.SetOrRemoveText([activeElement], labelElement, true, !hasAriaLabel, true);
 }
};
ASPxClientEdit.ClearEditorsInContainer = function(container, validationGroup, clearInvisibleEditors) {
 invalidEditorToBeFocused = null;
 ASPx.ProcessEditorsInContainer(container, ASPx.ClearProcessingProc, ASPx.ClearChoiceCondition, validationGroup, clearInvisibleEditors, true );
 ASPxClientEdit.ClearExternalControlsInContainer(container, validationGroup, clearInvisibleEditors, true );
};
ASPxClientEdit.ClearEditorsInContainerById = function(containerId, validationGroup, clearInvisibleEditors) {
 var container = document.getElementById(containerId);
 this.ClearEditorsInContainer(container, validationGroup, clearInvisibleEditors);
};
ASPxClientEdit.ClearGroup = function(validationGroup, clearInvisibleEditors) {
 return this.ClearEditorsInContainer(null, validationGroup, clearInvisibleEditors);
};
ASPxClientEdit.ValidateEditorsInContainer = function(container, validationGroup, validateInvisibleEditors) {
 var summaryCollection;
 if(ASPx.Ident.scripts.ASPxClientValidationSummary) {
  summaryCollection = ASPx.GetClientValidationSummaryCollection();
  summaryCollection.AllowNewErrorsAccepting(validationGroup);
 }
 var validationResult = ASPx.ProcessEditorsInContainer(container, ASPx.ValidateProcessingProc, _aspxValidateChoiceCondition, validationGroup, validateInvisibleEditors,
  false );
 validationResult.isValid = ASPxClientEdit.ValidateExternalControlsInContainer(container, validationGroup, validateInvisibleEditors,
  false ) && validationResult.isValid;
 if(typeof(validateInvisibleEditors) == "undefined")
  validateInvisibleEditors = false;
 if(typeof(validationGroup) == "undefined")
  validationGroup = null;    
 validationResult.isValid = ASPx.GetControlCollection().RaiseValidationCompleted(container, validationGroup,
 validateInvisibleEditors, validationResult.isValid, validationResult.firstInvalid, validationResult.firstVisibleInvalid);
 if(summaryCollection)
  summaryCollection.ForbidNewErrorsAccepting(validationGroup);
 if(!validationResult.isValid && !!validationResult.firstVisibleInvalid && validationResult.firstVisibleInvalid.accessibilityCompliant && !validationResult.firstVisibleInvalid.setFocusOnError) {
  var accessInvalidControl = validationResult.firstVisibleInvalid;
  if(!summaryCollection && !accessInvalidControl.focused) {
   var beforeDelayActiveElement = ASPx.GetActiveElement();
   setTimeout(function() {
    var currentActiveElement = ASPx.GetActiveElement();
    if(accessInvalidControl.focused || (currentActiveElement != beforeDelayActiveElement && ASPx.Attr.IsExistsAttribute(currentActiveElement, 'role')))
     return;
    accessInvalidControl.ariaExplanatoryTextManager.ToggleErrorAlert();
   }, 500);    
  }
 }
 return validationResult.isValid;
};
ASPxClientEdit.ValidateEditorsInContainerById = function(containerId, validationGroup, validateInvisibleEditors) {
 var container = document.getElementById(containerId);
 return this.ValidateEditorsInContainer(container, validationGroup, validateInvisibleEditors);
};
ASPxClientEdit.ValidateGroup = function(validationGroup, validateInvisibleEditors) {
 return this.ValidateEditorsInContainer(null, validationGroup, validateInvisibleEditors);
};
ASPxClientEdit.AreEditorsValid = function(containerOrContainerId, validationGroup, checkInvisibleEditors) {
 var container = typeof(containerOrContainerId) == "string" ? document.getElementById(containerOrContainerId) : containerOrContainerId;
 var checkResult = ASPx.ProcessEditorsInContainer(container, ASPx.EditorsValidProcessingProc, _aspxEditorsValidChoiceCondition, validationGroup,
  checkInvisibleEditors, false );
 checkResult.isValid = ASPxClientEdit.AreExternalControlsValidInContainer(containerOrContainerId, validationGroup,
  checkInvisibleEditors, false ) && checkResult.isValid;
 return checkResult.isValid;
};
ASPxClientEdit.AreExternalControlsValidInContainer = function(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors) {
 if(ASPx.Ident.scripts.ASPxClientHtmlEditor)
  return ASPxClientHtmlEditor.AreEditorsValidInContainer(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors);
 return true;
};
ASPxClientEdit.ClearExternalControlsInContainer = function(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors) {
 if(ASPx.Ident.scripts.ASPxClientHtmlEditor)
  return ASPxClientHtmlEditor.ClearEditorsInContainer(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors);
 return true;
};
ASPxClientEdit.ValidateExternalControlsInContainer = function(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors) {
 if(ASPx.Ident.scripts.ASPxClientHtmlEditor)
  return ASPxClientHtmlEditor.ValidateEditorsInContainer(containerId, validationGroup, validateInvisibleEditors, processDisabledEditors);
 return true;
};
ASPxClientEdit.AttachEditorModificationListener = function(handler, predicate) {
 var processAction = function(event) { event.AddHandler(handler); };
 ASPxClientEdit.ProcessEditorModificationListener(handler, processAction, predicate);
};
ASPxClientEdit.DetachEditorModificationListener = function(handler, predicate) {
 var processAction = function(event) { event.RemoveHandler(handler); };
 ASPxClientEdit.ProcessEditorModificationListener(handler, processAction, predicate);
};
ASPxClientEdit.ProcessEditorModificationListener = function(handler, action, predicate) {
 ASPx.GetControlCollection().ForEachControl(function(control) {
  if(control.GetModifyEvent && predicate(control)) {
   if(control.isNative)
    control.EnsureRequiredNativeAttributesExists();
   action(control.GetModifyEvent());
  }
 });
};
var ASPxClientEditKeyEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(htmlEvent) {
  this.constructor.prototype.constructor.call(this);
  this.htmlEvent = htmlEvent;
 }
});
var ASPxClientEditValidationEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(value, errorText, isValid) {
  this.constructor.prototype.constructor.call(this);
  this.errorText = errorText;
  this.isValid = isValid;
  this.value = value;
 }
});
ASPx.ProcessEditorsInContainer = function(container, processingProc, choiceCondition, validationGroup, processInvisibleEditors, processDisabledEditors) {
 var allProcessedSuccessfull = true;
 var firstInvalid = null;
 var firstVisibleInvalid = null;
 var invalidEditorToBeFocused = null;
 ASPx.GetControlCollection().ForEachControl(function(control) {
  var canValidate = ASPx.CanValidateControl(control, container, processingProc, choiceCondition, validationGroup, processInvisibleEditors, processDisabledEditors);
  if(!canValidate) return;
  var isSuccess = processingProc(control);
  if(!isSuccess) {
   allProcessedSuccessfull = false;
   if(firstInvalid == null)
    firstInvalid = control;
   var isVisible = control.IsVisible();
   if(isVisible && firstVisibleInvalid == null)
    firstVisibleInvalid = control;
   if(control.setFocusOnError && invalidEditorToBeFocused == null && isVisible)
    invalidEditorToBeFocused = control;
  }
 }, this);
 if(invalidEditorToBeFocused != null)
  invalidEditorToBeFocused.SetFocus();
 return new ASPxValidationResult(allProcessedSuccessfull, firstInvalid, firstVisibleInvalid);
};
ASPx.CanValidateControl = function(control, container, processingProc, choiceCondition, validationGroup, processInvisibleEditors, processDisabledEditors) {
 var needToProcessRatingControl = window.ASPxClientRatingControl && (control instanceof ASPxClientRatingControl) && processingProc === ASPx.ClearProcessingProc;
 var mainElement = control.GetMainElement(); 
 if(!ASPx.Ident.IsASPxClientEdit(control) && !needToProcessRatingControl)
  return false;
 if(ASPx.Ident.isDialogInvisibleControl(control) || ASPx.Ident.isBatchEditUnusedEditor(control))
  return false; 
 if(!processDisabledEditors && !control.GetEnabled())
  return false;
 if(!mainElement || (container && !ASPx.GetIsParent(container, mainElement)))
  return false;
 if(!processInvisibleEditors && !control.IsVisible())
  return false;
 if(choiceCondition && !choiceCondition(control, validationGroup))
  return false;
 return true;
};
var ASPxValidationResult = ASPx.CreateClass(null, {
 constructor: function(isValid, firstInvalid, firstVisibleInvalid) {
  this.isValid = isValid;
  this.firstInvalid = firstInvalid;
  this.firstVisibleInvalid = firstVisibleInvalid;
 }
});
ASPx.ClearChoiceCondition = function(edit, validationGroup) {
 return !ASPx.IsExists(validationGroup) || (edit.validationGroup == validationGroup);
};
function _aspxValidateChoiceCondition(edit, validationGroup) {
 return ASPx.ClearChoiceCondition(edit, validationGroup) && edit.customValidationEnabled;
}
function _aspxEditorsValidChoiceCondition(edit, validationGroup) {
 return _aspxValidateChoiceCondition(edit, validationGroup);
}
function wrapLostFocusHandler(handler) {
 if(ASPx.Browser.Edge) {
  return function(name) {
   var edit = ASPx.GetControlCollection().Get(name);
   if(edit && !ASPx.IsElementVisible(edit.GetMainElement()))
    setTimeout(handler, 0, name);
   else
    handler(name);
  };
 }
 return handler;
}
ASPx.EGotFocus = function(name) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit) {
  if(edit.isInitialized) {
   if(ASPx.Browser.VirtualKeyboardSupported && !edit.ownerListBox)
    ASPx.VirtualKeyboardUI.processEditorGotFocus(edit);
   else
    edit.OnFocus();
  }
  else {
   var inputElement = edit.GetFocusableInputElement();
   if(inputElement && inputElement === document.activeElement) {
    if(ASPx.Browser.Firefox)
     window.setTimeout(function() { document.activeElement.blur(); }, 0);
    else
     document.activeElement.blur();
   }
  }
 }
};
ASPx.ELostFocusCore = function(name) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(ASPx.Browser.VirtualKeyboardSupported && (!edit || !edit.ownerListBox)) {
  var supressLostFocus = ASPx.VirtualKeyboardUI.isInputNativeBluring();
  if(!supressLostFocus)
   ASPx.VirtualKeyboardUI.resetFocusedEditorCore();
  else 
   return;
 }
 if(edit && edit.focused) {
  if(edit.UseDelayedSpecialFocus()) {
   if(edit.specialFocusTimer === -1)
    edit.specialFocusTimer = ASPx.Timer.SetControlBoundTimeout(function() { edit.OnLostFocus(); }, edit, 30);
  }
  else {
   edit.OnLostFocus();
  }
 }
};
ASPx.ELostFocus = wrapLostFocusHandler(ASPx.ELostFocusCore);
ASPx.EValueChanged = function(name) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit != null)
  edit.OnValueChanged();
};
ASPx.VirtualKeyboardUI = (function() {
 var result = {
  focusedEditor: null,
  inputNativeFocusLocked: false,
  elementBelongsToEditor: function(element) {
   if(!element) return false;
   var isBelongsToEditor = false;
   ASPx.GetControlCollection().ForEachControl(function(control) {
    if(ASPx.Ident.IsASPxClientEdit(control) && control.IsEditorElement(element)) {
     isBelongsToEditor = true;
     return true;
    }
   }, this);
   return isBelongsToEditor;
  },
  elementBelongsToFocusedEditor: function (element) {
   return this.focusedEditor && this.focusedEditor.IsEditorElement(element);
  },
  onTouchStart: function (evt) {
   if (!ASPx.Browser.VirtualKeyboardSupported || this.isGooglePlaceAutocompleteElementTap(evt)) return;
   this.setInputNativeFocusLocked(false);
   if(this.focusedEditor)
    this.focusedEditor.onVirtualKeyboardUITouchStart(evt);
  },
  onTouchEnd: function(evt) {
   if(ASPx.TouchUIHelper.pointerEnabled) {  
    if(!window.testingTouchMode) { 
     if(evt.pointerType !== ASPx.TouchUIHelper.pointerType.Touch)
      return;
    }
    this.processFocusEditorControl(evt);
   } else
    ASPx.TouchUIHelper.handleFastTapIfRequired(evt,
     function() {
      this.processFocusEditorControl(evt);
     }.aspxBind(this), false);
  },
  processFocusEditorControl: function(evt) {
   var evtSource = ASPx.Evt.GetEventSource(evt);
   var focusedEditorIsTimeEdit = this.focusedEditor && (ASPx.Ident.IsASPxClientTimeEdit && ASPx.Ident.IsASPxClientTimeEdit(this.focusedEditor));
   var focusedTimeEditBelongsToDateEdit = focusedEditorIsTimeEdit && this.focusedEditor.OwnerDateEdit && this.focusedEditor.OwnerDateEdit.GetShowTimeSection();
   if(focusedTimeEditBelongsToDateEdit) {
    this.focusedEditor.OwnerDateEdit.ForceRefocusTimeSectionTimeEdit(evtSource);
    return;
   }
   var elementWithNativeFocus = ASPx.GetActiveElement();
   var someEditorInputIsFocused = this.elementBelongsToEditor(elementWithNativeFocus);
   var touchKeyboardIsVisible = someEditorInputIsFocused;
   var tapOutsideEditorAndInputs = !this.elementBelongsToEditor(evtSource) && !ASPx.Ident.IsFocusableElementRegardlessTabIndex(evtSource)
    && !this.isGooglePlaceAutocompleteElementTap(evt);
   var blurToHideTouchKeyboard = touchKeyboardIsVisible && tapOutsideEditorAndInputs;
   if(blurToHideTouchKeyboard) {
    elementWithNativeFocus.blur();
    return;
   }
   var tapOutsideFocusedEditor = this.focusedEditor && !this.elementBelongsToFocusedEditor(evtSource);
   if(tapOutsideFocusedEditor) {
    if(!this.elementBelongsToFocusedEditor(elementWithNativeFocus))
     this.resetFocusedEditor();
   }
  },
  focusEditor: function(edit) {
   if(!edit.focused) {
    this.setInputNativeFocusLocked(true);
    this.setFocusToEditor(edit);
   } else {
    edit.ForceRefocusEditor();
   }
  },
  setFocusToEditor: function(edit) {
   if(ASPx.Browser.MacOSMobilePlatform) {
    var timeoutDuration = ASPx.Browser.Chrome ? 250 : 30;
    window.setTimeout(function() {
     edit.SetFocus();
    }, timeoutDuration);
   } else {
    edit.SetFocus();
   }
  },
  processEditorGotFocus: function(edit) {
   if(this.focusedEditor === edit) {
    this.focusedEditor.UnlockFocusEvents();
    if(this.focusedEditor.EnsureClearButtonVisibility)
     this.focusedEditor.EnsureClearButtonVisibility();
   }
   else {
    this.setFocusedEditor(edit);
    if(this.getInputNativeFocusLocked())
     edit.BlurInputElement();
   }
  },
  setFocusedEditor: function(edit) {
   this.resetFocusedEditor();
   this.focusedEditor = edit;
   this.focusedEditor.Disposed.AddHandler(this.onFocusedEditorDisposed);
   this.focusedEditor.OnFocus();
   ASPx.SetFocusedEditor(this.focusedEditor);
  },
  isInputNativeBluring: function() {
   return this.focusedEditor && this.getInputNativeFocusLocked();
  },
  setInputNativeFocusLocked: function(locked) {
   this.inputNativeFocusLocked = locked;
  },
  getInputNativeFocusLocked: function() {
   return this.inputNativeFocusLocked;
  },
  resetFocusedEditor: function() {
   if(this.focusedEditor) {
    var curEditorName = this.focusedEditor.name;
    var focusedEditorInputElementExists = this.focusedEditor.GetInputElement();
    this.resetFocusedEditorCore();
    if(focusedEditorInputElementExists)
     ASPx.ELostFocusCore(curEditorName);
   }
  },
  resetFocusedEditorCore: function() { 
   if(this.focusedEditor)
    this.focusedEditor.Disposed.RemoveHandler(this.onFocusedEditorDisposed);
   this.focusedEditor = null;
  },
  getFocusedEditor: function() {
   return this.focusedEditor;
  },
  focusableInputElementIsActive: function(edit) {
   var inputElement = edit.GetFocusableInputElement();
   return !!inputElement ? ASPx.GetActiveElement() === inputElement : false;
  },
  isGooglePlaceAutocompleteElementTap: function(evt) {
   var googlePlaceAutocompleteContainer = ASPx.GetNodeByClassName(document.body, "pac-container", 0);
   if(!googlePlaceAutocompleteContainer)
    return false;
   return ASPx.GetParentByClassName(ASPx.Evt.GetEventSource(evt), "pac-container") != null;
  }
 };
 result.onFocusedEditorDisposed = function() {
  this.resetFocusedEditor();
 }.bind(result);
 return result;
})();
if(ASPx.Browser.VirtualKeyboardSupported) {
 var touchStartEventName = ASPx.TouchUIHelper.pointerEnabled ? ASPx.TouchUIHelper.pointerDownEventName : 'touchstart';
 var touchEndEventName = ASPx.TouchUIHelper.pointerEnabled ? ASPx.TouchUIHelper.pointerUpEventName : 'touchend';
 ASPx.Evt.AttachEventToDocument(touchStartEventName, function(evt) { ASPx.VirtualKeyboardUI.onTouchStart(evt); });
 ASPx.Evt.AttachEventToDocument(touchEndEventName, function(evt) { ASPx.VirtualKeyboardUI.onTouchEnd(evt); });
}
ASPx.Evt.AttachEventToDocument("mousedown", function(evt) {
 var editor = ASPx.GetFocusedEditor();
 if(!editor) 
  return;
 var evtSource = ASPx.Evt.GetEventSource(evt);
 if(editor.IsClearButtonElement(evtSource))
  return;
 if(editor.OwnerDateEdit && editor.OwnerDateEdit.GetShowTimeSection()) {
  editor.OwnerDateEdit.ForceRefocusTimeSectionTimeEdit(evtSource);
  return;
 }
 if(editor.ownerListBox && editor.ownerListBox.IsEditorElement(evtSource) && !editor.IsEditorElement(evtSource)) {
  editor.ownerListBox.ForceRefocusEditor(evt);
  ASPx.SetFocusedEditor(editor.ownerListBox);
  return;
 }
 if(editor.IsEditorElement(evtSource) && !editor.IsElementBelongToInputElement(evtSource))
  editor.ForceRefocusEditor(evt);
});
ASPx.Evt.AttachEventToDocument(ASPx.Evt.GetMouseWheelEventName(), function(evt) {
 var editor = ASPx.GetFocusedEditor();
 if(editor != null && ASPx.IsExistsElement(editor.GetMainElement()) && editor.focused && editor.receiveGlobalMouseWheel)
  editor.OnMouseWheel(evt);
});
ASPx.KBSIKeyDown = function(name, evt){
 var control = ASPx.GetControlCollection().Get(name);
 if(control != null){
  var isProcessed = control.OnSpecialKeyDown(evt);
  if(isProcessed)
   return ASPx.Evt.PreventEventAndBubble(evt);
 }
};
ASPx.KBSIKeyPress = function(name, evt){
 var control = ASPx.GetControlCollection().Get(name);
 if(control != null){
  var isProcessed = control.OnSpecialKeyPress(evt);
  if(isProcessed)
   return ASPx.Evt.PreventEventAndBubble(evt);
 }
};
ASPx.KBSIKeyUp = function(name, evt){
 var control = ASPx.GetControlCollection().Get(name);
 if(control != null){
  var isProcessed = control.OnSpecialKeyUp(evt);
  if(isProcessed)
   return ASPx.Evt.PreventEventAndBubble(evt);
 }
};
ASPx.ClearProcessingProc = function(edit) {
 return edit.Clear();
};
ASPx.ValidateProcessingProc = function(edit) {
 edit.OnValidation(ValidationType.MassValidation);
 return edit.GetIsValid();
};
ASPx.EditorsValidProcessingProc = function(edit) {
 return edit.GetIsValid();
};
var CheckEditElementHelper = ASPx.CreateClass(ASPx.CheckableElementHelper, {
 AttachToMainElement: function(internalCheckBox) {
  ASPx.CheckableElementHelper.prototype.AttachToMainElement.call(this, internalCheckBox);
  this.AttachToLabelElement(this.GetLabelElement(internalCheckBox.container), internalCheckBox);
 },
 AttachToLabelElement: function(labelElement, internalCheckBox) {
  var _this = this;
  if(labelElement) {
   ASPx.Evt.AttachEventToElement(labelElement, "click", 
    function (evt) { 
     _this.InvokeClick(internalCheckBox, evt);
    }
   );
   ASPx.Evt.AttachEventToElement(labelElement, "mousedown",
    function (evt) {
     internalCheckBox.Refocus();
    }
   );
  }
 },
 GetLabelElement: function(container) {
  var labelElement = ASPx.GetNodeByTagName(container, "LABEL", 0);
  if(!labelElement) {
   var labelCell = ASPx.GetNodeByClassName(container, "dxichTextCellSys", 0);
   labelElement = ASPx.GetNodeByTagName(labelCell, "SPAN", 0);
  }
  return labelElement;
 }
});
CheckEditElementHelper.Instance = new CheckEditElementHelper();
var CalendarSharedParameters = ASPx.CreateClass(null, {
 updateCalendarCallbackCommand: "UPDATE",
 constructor: function() {
  this.minDate = null;
  this.maxDate = null;
  this.disabledDates = [];
  this.calendarCustomDraw = false;
  this.hasCustomDisabledDatesViaCallback = false;
  this.dateRangeMode = false;
  this.currentDateEdit = null;
  this.DaysSelectingOnMouseOver = new ASPxClientEvent();
  this.VisibleDaysMouseOut = new ASPxClientEvent();
  this.CalendarSelectionChangedInternal = new ASPxClientEvent();
 },
 Assign: function(source) {
  this.minDate = source.minDate ? source.minDate : null;
  this.maxDate = source.maxDate ? source.maxDate : null;
  this.calendarCustomDraw = source.calendarCustomDraw ? source.calendarCustomDraw : false;
  this.hasCustomDisabledDatesViaCallback = source.hasCustomDisabledDatesViaCallback ? source.hasCustomDisabledDatesViaCallback : false;
  this.disabledDates = source.disabledDates ? source.disabledDates : [];
  this.currentDateEdit = source.currentDateEdit ? source.currentDateEdit : null;
 },
 GetUpdateCallbackParameters: function() {
  var callbackArgs = this.GetCallbackArgs();
  callbackArgs = this.FormatCallbackArg(this.updateCalendarCallbackCommand, callbackArgs);
  return callbackArgs;
 },
 GetCallbackArgs: function() {
  var args = {};
  if(this.minDate)
   args.clientMinDate = ASPx.DateUtils.GetInvariantDateString(this.minDate);
  if(this.maxDate)
   args.clientMaxDate = ASPx.DateUtils.GetInvariantDateString(this.maxDate);
  if(args.clientMinDate || args.clientMaxDate) {
   var jsonArgs = JSON.stringify(args);
   return ASPx.Str.EncodeHtml(jsonArgs);
  }
  return null;
 },
 FormatCallbackArg: function(prefix, arg) {
  if(!arg) return prefix;
  return [prefix, '|', arg.length, ';', arg, ';'].join('');
 }
});
ASPx.CalendarSharedParameters = CalendarSharedParameters;
ASPx.ValidationType = ValidationType;
ASPx.ErrorFrameDisplay = ErrorFrameDisplay;
ASPx.EditElementSuffix = EditElementSuffix;
ASPx.ValidationPattern = ValidationPattern;
ASPx.RequiredFieldValidationPattern = RequiredFieldValidationPattern;
ASPx.RegularExpressionValidationPattern = RegularExpressionValidationPattern;
ASPx.CheckEditElementHelper = CheckEditElementHelper;
ASPx.IsEditorFocusable = _aspxIsEditorFocusable;
window.ASPxClientEditBase = ASPxClientEditBase;
window.ASPxClientEdit = ASPxClientEdit;
window.ASPxClientEditKeyEventArgs = ASPxClientEditKeyEventArgs;
window.ASPxClientEditValidationEventArgs = ASPxClientEditValidationEventArgs;
})();

(function() {
ASPx.TEInputSuffix = "_I";
ASPx.PasteCheckInterval = 50;
ASPx.CheckUserInputInterval = 10;
ASPx.TEHelpTextElementSuffix = "_HTE";
ASPx.TempHiddenInputSuffix = "_THI";
var passwordInputClonedSuffix = "_CLND";
var CHROME_AUTOFILL_SELECTOR = ":-webkit-autofill";
var BrowserHelper = {
 SAFARI_SYSTEM_CLASS_NAME: "dxeSafariSys",
 MOBILE_SAFARI_SYSTEM_CLASS_NAME: "dxeIPadSys",
 GetBrowserSpecificSystemClassName: function() {
  if(ASPx.Browser.Safari)
   return ASPx.Browser.MacOSMobilePlatform ? this.MOBILE_SAFARI_SYSTEM_CLASS_NAME : this.SAFARI_SYSTEM_CLASS_NAME;
  return "";
 }
};
var focusedNullTextClassName = "dxeFNTextSys";
var NullTextDisplayMode = {
 Unfocused: "Unfocused",
 UnfocusedAndFocused: "UnfocusedAndFocused"
};
ASPx.NullTextDisplayMode = NullTextDisplayMode;
var ASPxClientTextEdit = ASPx.CreateClass(ASPxClientEdit, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);      
  this.isASPxClientTextEdit = true;
  this.nullText = "";
  this.nullTextDisplayMode = NullTextDisplayMode.Unfocused;
  this.nullTextOnFocusCssText = "";
  this.focusedNullTextTimerID = -1;
  this.escCount = 0;
  this.raiseValueChangedOnEnter = true;
  this.autoResizeWithContainer = false;
  this.lastChangedValue = null;
  this.autoCompleteAttribute = null;
  this.isTextSelectionOnClickEnabled = false;
  this.trySelectInputTextOnClick = true;
  this.passwordNullTextIntervalID = -1;
  this.nullTextInputElement = null;
  this.helpText = "";
  this.helpTextObj = null;  
  this.helpTextStyle = [];
  this.externalTableStyle = [];
  this.helpTextPosition = ASPx.Position.Right;
  this.helpTextMargins = null;
  this.helpTextHAlign = ASPxClientTextEditHelpTextHAlign.Left;
  this.helpTextVAlign = ASPxClientTextEditHelpTextVAlign.Top;
  this.enableHelpTextPopupAnimation = true;
  this.helpTextDisplayMode = ASPxClientTextEditHelpTextDisplayMode.Inline;
  this.maskInfo = null;  
  this.maskValueBeforeUserInput = "";
  this.maskValueChangedByPassKeyPressOnAndroid = false;
  this.maskPasteTimerID = -1;
  this.maskPasteLock = false;    
  this.maskPasteCounter = 0;
  this.maskTextBeforePaste = "";    
  this.maskHintHtml = "";
  this.maskHintTimerID = -1;
  this.errorCellPosition = ASPx.Position.Right;
  this.inlineInitializeInputValue = null;
  this.initializeInputValue = null;
  this.displayFormat = null;
  this.TextChanged = new ASPxClientEvent();
  this.UserInput = new ASPxClientEvent();
  this.userInputEventTimerID = -1;
 },
 AddDefaultReadOnlyStateControllerItem: function(cssClass, mainElementId) {
  ASPx.AddReadOnlyItems(mainElementId, [[[cssClass], [''], ['', 'I']]]);
 },
 AddDefaultDisabledStateControllerItem: function(cssClass, mainElementId) {
  ASPx.AddDisabledItems(mainElementId, [[[cssClass], [''], ['', 'I']]]);
 },
 SetData: function(data){
  ASPxClientEdit.prototype.SetData.call(this, data);
  if(data.maskInfo) {
   var maskProperties = data.maskInfo.properties;
   var useInvariantCultureDecimalSymbol = maskProperties && maskProperties.useInvariantCultureDecimalSymbol || false;
   this.maskInfo = ASPx.MaskInfo.Create(data.maskInfo.maskText, data.maskInfo.dateTimeOnly, data.maskInfo.allowEscapingInEnums, useInvariantCultureDecimalSymbol);
   this.SetProperties(data.maskInfo.properties, this.maskInfo);
  }
 },
 InlineInitialize: function() {
  this.SaveInputValue(true);
  ASPxClientEdit.prototype.InlineInitialize.call(this);
  if(this.maskInfo != null)
   this.InitMask();
  this.ApplyBrowserSpecificClassName();
  this.helpTextInitialize();
 },
 Initialize: function(){
  this.SaveInputValue(false);
  this.SaveChangedValue();
  ASPxClientEdit.prototype.Initialize.call(this);
  if(ASPx.Browser.WebKitFamily)  
   this.CorrectMainElementWhiteSpaceStyle();
  this.InitializeTextDecoration();
  this.InitializeAutocompleteAttribute();
  if(this.IsValueRestoredByBrowser())
   this.SynchronizeRestoredValue();
 },
 InitializeEvents: function() {
  ASPxClientEdit.prototype.InitializeEvents.call(this);
  ASPx.Evt.AttachEventToElement(this.GetInputElement(), "keydown", this.OnKeyDown.aspxBind(this));
  ASPx.Evt.AttachEventToElement(this.GetInputElement(), "keyup", this.OnKeyUp.aspxBind(this));
  ASPx.Evt.AttachEventToElement(this.GetInputElement(), "keypress", this.OnKeyPress.aspxBind(this));
  if(this.isTextSelectionOnClickEnabled) {
   ASPx.Evt.AttachEventToElement(this.GetInputElement(), ASPx.TouchUIHelper.touchMouseDownEventName, this.OnMouseDown.aspxBind(this));
   ASPx.Evt.AttachEventToElement(this.GetInputElement(), "click", this.OnClick.aspxBind(this));
  }
  this.Unload.AddHandler(this.OnUnload.aspxBind(this));
 },
 InitializeTextDecoration: function() {
  var input = this.GetInputElement();
  if(input.type === "password" && !this.IsInputPasswordFilledAutomaticallyByChrome())
   this.ToggleTextDecoration();
 },
 IsInputPasswordFilledAutomaticallyByChrome: function() {
  if(!ASPx.Browser.Chrome)
   return false;
  var input = this.GetInputElement();
  return ASPx.ElementMatchesSelector(input, CHROME_AUTOFILL_SELECTOR);
 },
 OnMouseDown: function() {
  this.trySelectInputTextOnClick = ASPx.GetActiveElement() !== this.GetInputElement() && !this.IsFocusEventsLocked();
 },
 OnClick: function() {
  if(this.trySelectInputTextOnClick) {
   var input = this.GetInputElement();
   setTimeout(function() {
    var inputSelection = ASPx.Selection.GetInfo(input);
    if (inputSelection.startPos === inputSelection.endPos)
     ASPx.Selection.Set(input);
   }, 0);
  }
 },
 InitializeAutocompleteAttribute: function() {
  var input = this.GetInputElement();
  if(this.IsVCardAttributeRequired())
   ASPx.Attr.SetAttribute(input, this.autoCompleteAttribute.name, this.autoCompleteAttribute.value);
  else if(this.IsAutocompleteOffRequiredOnInitialize())
   ASPx.Attr.SetAttribute(input, "autocomplete", "off");
 },
 SaveInputValue: function(isInlineInitialize) {
  var input = this.GetInputElement();
  if(!input)
   return;
  var inputValue = input.value;
  if(inputValue === null)
   inputValue = "";
  if(isInlineInitialize)
   this.inlineInitializeInputValue = inputValue;
  else
   this.initializeInputValue = inputValue;
 },
 IsValueRestoredByBrowser: function() {
  if(this.displayFormat || this.isNative || this.inlineInitializeInputValue === null || this.initializeInputValue === null)
   return false;
  if(ASPx.Browser.Chrome)
   return this.IsValueRestoredByChrome();
  else if(ASPx.Browser.Firefox)
   return this.IsValueRestoredByFirefox();
  else
   return this.IsValueRestoredByBrowserCore();
 },
 IsValueRestoredByBrowserCore: function() {
  return this.IsValueChangedBeforeInitialize() || this.IsClientValueNotExists() || this.IsValueChangedOnMaskInitialize();
 },
 IsValueRestoredByChrome: function() {
  return this.IsValueRestoredByBrowserCore();
 },
 IsValueRestoredByFirefox: function() {
  return this.IsValueRestoredByBrowserCore();
 },
 IsValueChangedBeforeInitialize: function() {
  return this.inlineInitializeInputValue !== this.initializeInputValue;
 },
 IsClientValueNotExists: function() {
  return this.inlineInitializeInputValue !== "" &&
      this.inlineInitializeInputValue !== this.nullText &&
      this.inlineInitializeInputValue !== this.GetValue() &&
      this.inlineInitializeInputValue !== this.GetText();
 },
 IsValueChangedOnMaskInitialize: function() {
  return this.maskInfo && this.inlineInitializeInputValue !== this.GetInputElement().value;
 },
 SynchronizeRestoredValue: function() {
  this.SetText(this.initializeInputValue);
 },
 AdjustControl: function() {
  ASPxClientEdit.prototype.AdjustControl.call(this);
  this.ensureAdjustFocusedNullTextElement();
 },
 correctInputElementHeight: function() {
  var mainElement = this.GetMainElement();
  if(mainElement) {
   var mainElementHeight = mainElement.style.height;
   var mainElementHeightSpecified = mainElementHeight && mainElementHeight.indexOf('px') !== -1; 
   if(mainElementHeightSpecified) {
    var inputElement = this.GetInputElement();
    var inputElementHeight = this.getInputElementHeight();
    inputElement.style.height = inputElementHeight + "px";
    if(!ASPx.Ident.IsASPxClientMemo(this))
     inputElement.style.lineHeight = inputElementHeight + "px";
   }
  }
 },
 getInputElementHeight: function() {
  var mainElement = this.GetMainElement(),
   inputElement = this.GetInputElement();
  var inputElementHeight = ASPx.PxToInt(mainElement.style.height) - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(mainElement);
  var inputElementContainer = inputElement.parentNode,
   inputContainerStyle = ASPx.GetCurrentStyle(inputElementContainer);
  inputElementHeight -= ASPx.GetTopBottomBordersAndPaddingsSummaryValue(inputElementContainer, inputContainerStyle) 
   + ASPx.GetTopBottomMargins(inputElementContainer, inputContainerStyle);
  var mainElementCellspacing = ASPx.GetCellSpacing(mainElement);
  if(mainElementCellspacing)
   inputElementHeight -= mainElementCellspacing * 2;
  var inputStyle = ASPx.GetCurrentStyle(inputElement);
  inputElementHeight -= ASPx.GetTopBottomBordersAndPaddingsSummaryValue(inputElement, inputStyle) 
   + ASPx.GetTopBottomMargins(inputElement, inputStyle);
  return inputElementHeight;
 },
 getInputCell: function() {
  var inputElement = this.GetInputElement();
  if(inputElement)
   return inputElement.parentNode;
 },
 ensureOutOfRangeWarningManager: function (minValue, maxValue, defaultMinValue, defaultMaxValue, valueFormatter) {
  if (!this.outOfRangeWarningManager)
   this.outOfRangeWarningManager = new ASPxOutOfRangeWarningManager(this, minValue, maxValue, defaultMinValue, defaultMaxValue,
    this.showOutOfRangeWarningElementAtBottom() ? ASPx.Position.Bottom : ASPx.Position.Right, valueFormatter);
 },
 showOutOfRangeWarningElementAtBottom: function() {
  return this.hasRightPopupHelpText();
 },
 GetOutOfRangeWarningElementPrevSibling: function() {
  return this.GetMainElement();
 },
 helpTextInitialize: function () {
  if(this.helpText) {
   this.helpTextObj = new ASPxClientTextEditHelpText(this, this.helpTextStyle, this.helpText, this.helpTextPosition,
    this.helpTextHAlign, this.helpTextVAlign, this.helpTextMargins, this.enableHelpTextPopupAnimation, this.helpTextDisplayMode);
  }
 },
 hasPopupHelpText: function() {
  return this.helpText && this.helpTextDisplayMode === ASPxClientTextEditHelpTextDisplayMode.Popup;
 },
 hasRightPopupHelpText: function() {
  return this.hasPopupHelpText() && this.helpTextPosition === ASPx.Position.Right;
 },
 showHelpText: function () {
  if(this.helpTextObj)
   this.helpTextObj.show();
 },
 hideHelpText: function () {
  if(this.helpTextObj)
   this.helpTextObj.hide();
 },
 ApplyBrowserSpecificClassName: function() {
  var mainElement = this.GetMainElement();
  if(ASPx.IsExistsElement(mainElement)) {
   var className = BrowserHelper.GetBrowserSpecificSystemClassName();
   if(className)
    mainElement.className += " " + className;
  }
 },
  CorrectMainElementWhiteSpaceStyle: function() {
  var inputElement = this.GetInputElement();
  if(inputElement && inputElement.parentNode) {
   if(this.IsElementHasWhiteSpaceStyle(inputElement.parentNode))
    inputElement.parentNode.style.whiteSpace = "normal";
  }
 },
 IsElementHasWhiteSpaceStyle: function(element) {
  var currentStyle = ASPx.GetCurrentStyle(element);
  return currentStyle.whiteSpace == "nowrap" || currentStyle.whiteSpace == "pre";  
 },
 FindInputElement: function(){
  return this.isNative ? this.GetMainElement() : ASPx.GetElementById(this.name + ASPx.TEInputSuffix);
 },
 DecodeRawInputValue: function(value) {
  return value;
 },
 GetRawValue: function(value){
  return ASPx.IsExists(this.stateObject) ? this.stateObject.rawValue : null;
 },
 SetRawValue: function(value){
  if(ASPx.IsExists(value))
   value = value.toString();
  this.UpdateStateObjectWithObject({ rawValue: value });
 },
 SyncRawValue: function() {
  if(this.maskInfo != null)
   this.SetRawValue(this.maskInfo.GetValue(true));
  else
   this.SetRawValue(this.GetInputElement().value);
 },
 HasTextDecorators: function() {
  return this.nullText != "" || this.displayFormat != null;
 },
 CanApplyTextDecorators: function(){
  return !this.focused;
 },
 CreateStyleDecoration: function () {
  return new ASPx.TextEditorStyleDecoration(this);
 },
 CanApplyNullTextDecoration: function() {
  var value = this.GetValue();
  return this.IsNull(value);
 },
 GetDecoratedText: function(value) {
  var result = value;
  if(this.IsNull(value) && this.nullText != "" && this.CanApplyNullTextDecoration())
   result = this.nullText;
  else if(this.displayFormat != null)
   result = this.GetDisplayFormatText(value);
  else if(this.maskInfo != null)
   result = this.maskInfo.GetText();
  else if(value == null)
   result = "";
  return result;
 },
 GetDisplayFormatText: function(value) {
  return ASPx.Formatter.Format(this.displayFormat, value);
 },
 ToggleTextDecoration: function() {
  if(this.HasTextDecorators()) {
   if(this.focused) {
    var input = this.GetInputElement();
    var oldValue = input.value;
    var sel = ASPx.Selection.GetExtInfo(input);
    this.ToggleTextDecorationCore();
    this.ensureActivateFocusedNullTextMechanism();
    if(oldValue != input.value || !ASPx.Selection.AreEqual(sel, ASPx.Selection.GetExtInfo(input))) {
     if(sel.startPos == 0 && sel.endPos == oldValue.length)
      sel.endPos = input.value.length;
     else
      sel.endPos = sel.startPos;
     if(!this.accessibilityCompliant || ASPx.GetActiveElement() == input)
      this.SetSelectionOnToggleTextDecoration(input, sel);
    }
   } else {
    this.ToggleTextDecorationCore();
    this.ensureDeactivateFocusedNullTextMechanism();
   }
  }
 },
 SetSelectionOnToggleTextDecoration: function(input, sel) {
  ASPx.Selection.Set(input, sel.startPos, sel.endPos);
 },
 ToggleTextDecorationCore: function() {
  if(this.maskInfo != null) {   
   this.ApplyMaskInfo(false);
  } else {
   var input = this.GetInputElement();
   var rawValue = this.GetRawValue();
   var value = this.CanApplyTextDecorators() ? this.GetDecoratedText(rawValue) : rawValue;
   if(input.value != value) {
    if(input.type == "password")
     this.TogglePasswordInputTextDecoration(value);
    else
     input.value = value;
   }
  }
 },
 GetPasswordNullTextInputElement: function() {
  if(!this.isPasswordNullTextInputElementExists())
   this.nullTextInputElement = this.createPasswordNullTextInputElement();
  return this.nullTextInputElement;
 },
 createPasswordNullTextInputElement: function() {
  var inputElement = this.GetInputElement(),
   nullTextInputElement = document.createElement("INPUT");
  nullTextInputElement.className = inputElement.className;
  nullTextInputElement.style.cssText = inputElement.style.cssText;
  nullTextInputElement.id = inputElement.id + passwordInputClonedSuffix;
  nullTextInputElement.type = "text";
  if(ASPx.IsExists(inputElement.tabIndex))
   nullTextInputElement.tabIndex = inputElement.tabIndex;
  nullTextInputElement.disabled = inputElement.disabled;
  var onFocusEventHandler = function() {
   var inputElement = this.GetInputElement(),
    nullTextInputElement = this.GetPasswordNullTextInputElement();
   if(inputElement) {
    this.LockFocusEvents();  
    ASPx.SetElementDisplay(inputElement, true);
    if((ASPx.Browser.MacOSMobilePlatform && ASPx.Browser.PlaformMajorVersion >= 14) || (ASPx.Browser.MacOSPlatform && ASPx.Browser.Safari && ASPx.Browser.Version >= 14)) { 
     ASPx.GetCurrentStyle(inputElement).display; 
    }
    inputElement.focus();
    ASPx.SetElementDisplay(nullTextInputElement, false);
    this.ensureAdjustFocusedNullTextElement();
    this.ReplaceAssociatedIdInLabels(nullTextInputElement.id, inputElement.id);
   }
  }.aspxBind(this);
  ASPx.Evt.AttachEventToElement(nullTextInputElement, "focus", onFocusEventHandler);
  return nullTextInputElement;
 },
 isPasswordNullTextInputElementExists: function() {
  return ASPx.IsExistsElement(this.nullTextInputElement);
 },
 TogglePasswordNullTextTimeoutChecker: function() {
  if(this.passwordNullTextIntervalID < 0) {
   var timeoutChecker = function() {
    var inputElement = this.GetInputElement();
    if(ASPx.GetControlCollection().GetByName(this.name) !== this || inputElement == null) {
     window.clearTimeout(this.passwordNullTextIntervalID);
     this.passwordNullTextIntervalID = -1;
     return;
    } else {
     if(!this.focused) {
      var passwordNullTextInputElement = this.GetPasswordNullTextInputElement();
      if(passwordNullTextInputElement.value != this.nullText && inputElement.value == "") { 
       passwordNullTextInputElement.value = this.nullText;
       this.SetValue(null);
      }
      if(inputElement.value != "") {
       if(inputElement.style.display == "none") {
        this.SetValue(inputElement.value);
        this.UnhidePasswordInput();
       }
      } else {
       if(inputElement.style.display != "none") {
        this.SetValue(null);
        this.HidePasswordInput();
       }
      }
     }
     else {
      var passwordNullTextInputElement = this.GetPasswordNullTextInputElement();
      if(passwordNullTextInputElement.value !== this.nullText && passwordNullTextInputElement.value !== "") { 
       if(inputElement.value === "")
        inputElement.value = passwordNullTextInputElement.value;
       passwordNullTextInputElement.value = this.nullText;
      }
     }
    }
   }.aspxBind(this);
   timeoutChecker(); 
   this.passwordNullTextIntervalID = window.setInterval(timeoutChecker, 100);
  }
 },
 TogglePasswordInputTextDecoration: function(value) {
  var inputElement = this.GetInputElement();
  var nullTextInputElement = this.GetPasswordNullTextInputElement();
  nullTextInputElement.value = value;
  var parentNode = inputElement.parentNode;
  if(ASPx.Data.ArrayIndexOf(parentNode.childNodes, nullTextInputElement) < 0) {
   ASPx.Attr.ChangeStyleAttribute(nullTextInputElement, "display", "none");
   ASPx.InsertElementAfter(nullTextInputElement, inputElement);
  }
  this.HidePasswordInput();
  this.TogglePasswordNullTextTimeoutChecker();
 },
 HidePasswordInput: function() {
  ASPx.Attr.ChangeStyleAttribute(this.GetInputElement(), "display", "none");
  ASPx.Attr.ChangeStyleAttribute(this.GetPasswordNullTextInputElement(), "display", "");
  this.ReplaceAssociatedIdInLabels(this.GetInputElement().id, this.GetPasswordNullTextInputElement().id);
 },
 UnhidePasswordInput: function() {
  ASPx.Attr.ChangeStyleAttribute(this.GetInputElement(), "display", "");
  ASPx.Attr.ChangeStyleAttribute(this.GetPasswordNullTextInputElement(), "display", "none");
  this.ReplaceAssociatedIdInLabels(this.GetPasswordNullTextInputElement().id, this.GetInputElement().id);
 },
 ReplaceAssociatedIdInLabels: function(oldId, newId) {
  var labels = document.getElementsByTagName("LABEL");
  for(var i = 0; i < labels.length; i++) {
   if(labels[i].attributes["for"] && labels[i].attributes["for"].value == oldId)
    labels[i].attributes["for"].value = newId;
  }
 },
 GetFormattedText: function() {
  var value = this.GetValue();
  if(this.IsNull(value) && this.nullText != "")
   return this.GetText();
  return this.GetDecoratedText(value);
 },
 IsNull: function(value) {
  return value == null || value === "";
 },
 PopulateStyleDecorationPostfixes: function() {
  ASPxClientEdit.prototype.PopulateStyleDecorationPostfixes.call(this);
  this.styleDecoration.AddPostfix(ASPx.TEInputSuffix);
  if(this.GetInputElement().type === "password" && this.nullText !== "")
   this.styleDecoration.AddPostfix(ASPx.TEInputSuffix + passwordInputClonedSuffix);
 },
 GetValue: function() {
  var value = null;
  if(this.maskInfo != null)
   value = this.maskInfo.GetValue();
  else if(this.HasTextDecorators())
   value = this.GetRawValue();
  else {
   var input = this.GetInputElement();
   value = input ? input.value : null;
  }
  return (value == "" && this.convertEmptyStringToNull) ? null : value;
 },
 SetValue: function(value) {
  if(value == null || value === undefined) 
   value = "";
  if(this.maskInfo != null) {
   this.maskInfo.SetValue(value.toString());
   this.ApplyMaskInfo(false);
   this.SavePrevMaskValue();
  } 
  else if(this.HasTextDecorators()) {
   this.SetRawValue(value);
   this.GetInputElement().value = this.CanApplyTextDecorators() && this.GetInputElement().type != "password" ? this.GetDecoratedText(value) : value;
  }
  else
   this.GetInputElement().value = value;
  this.UpdateStyleDecorations(); 
  this.SaveChangedValue();   
 },
 SetVisible: function(visible) {
  ASPxClientEdit.prototype.SetVisible.call(this, visible);
  if(this.helpTextDisplayMode === ASPxClientTextEditHelpTextDisplayMode.Inline) {
   if(visible)
    this.showHelpText();
   else
    this.hideHelpText();
  }
 },
 UnstretchInputElement: function(){
  var inputElement = this.GetInputElement();
  var mainElement = this.GetMainElement();
  var mainElementCurStyle = ASPx.GetCurrentStyle(mainElement);
  if(ASPx.IsExistsElement(mainElement) && ASPx.IsExistsElement(inputElement) && ASPx.IsExists(mainElementCurStyle) && 
   inputElement.style.width == "100%" &&
   (mainElementCurStyle.width == "" || mainElementCurStyle.width == "auto"))
   inputElement.style.width = "";
 },
 RestoreActiveElement: function(activeElement) {
  if(activeElement && activeElement.setActive && activeElement.tagName != "IFRAME")
   activeElement.setActive();
 },
 RaiseValueChangedEvent: function() {
  var processOnServer = ASPxClientEdit.prototype.RaiseValueChangedEvent.call(this);
  processOnServer = this.RaiseTextChanged(processOnServer);
  return processOnServer;
 },
 InitMask: function() {
  var rawValue = this.GetRawValue();
  this.SetValue(rawValue.length ? this.DecodeRawInputValue(rawValue) : this.maskInfo.GetValue());
  this.validationPatterns.unshift(new MaskValidationPattern(this.maskInfo.errorText, this.maskInfo));
 },
 SetMaskPasteTimer: function() {
  this.ClearMaskPasteTimer();
  this.maskPasteTimerID = ASPx.Timer.SetControlBoundInterval(this.MaskPasteTimerProc, this, ASPx.PasteCheckInterval);
 },
 ClearMaskPasteTimer: function() {
  this.maskPasteTimerID = ASPx.Timer.ClearInterval(this.maskPasteTimerID);
 },
 SavePrevMaskValue: function() {
  this.maskValueBeforeUserInput = this.maskInfo.GetValue();
 },
 FillMaskInfo: function() {
  var input = this.GetInputElement();
  if(!input) return; 
  var sel = ASPx.Selection.GetInfo(input);
  this.maskInfo.SetCaret(sel.startPos, sel.endPos - sel.startPos);  
 },
 ApplyMaskInfo: function(applyCaret) {
  this.SyncRawValue();
  var input = this.GetInputElement();
  var text = this.GetMaskDisplayText();
  this.maskTextBeforePaste = text;
  if(input.value != text)
   input.value = text;
  if(applyCaret)
   ASPx.Selection.Set(input, this.maskInfo.caretPos, this.maskInfo.caretPos + this.maskInfo.selectionLength);
 },
 GetMaskDisplayText: function() {
  if(!this.focused && this.HasTextDecorators())
   return this.GetDecoratedText(this.maskInfo.GetValue());
  return this.maskInfo.GetText();
 },
 ShouldCancelMaskKeyProcessing: function(htmlEvent, keyDownInfo) {
  return ASPx.Evt.IsEventPrevented(htmlEvent);
 }, 
 HandleMaskKeyDown: function(evt) {
  var keyInfo = ASPx.MaskManager.CreateKeyInfoByEvent(evt);
  ASPx.MaskManager.keyCancelled = this.ShouldCancelMaskKeyProcessing(evt, keyInfo);
  if(ASPx.MaskManager.keyCancelled) {
   ASPx.Evt.PreventEvent(evt);
   return;
  }
  this.maskPasteLock = true;
  this.FillMaskInfo();  
  var canHandle = ASPx.MaskManager.CanHandleControlKey(keyInfo);   
  ASPx.MaskManager.savedKeyDownKeyInfo = keyInfo;
  if(canHandle) {   
   ASPx.MaskManager.OnKeyDown(this.maskInfo, keyInfo);
   this.ApplyMaskInfo(true);
   ASPx.Evt.PreventEvent(evt);
  }
  ASPx.MaskManager.keyDownHandled = canHandle;
  this.maskPasteLock = false;
  this.UpdateMaskHintHtml();
 },
 HandleMaskKeyPress: function(evt) {
  var keyInfo = ASPx.MaskManager.CreateKeyInfoByEvent(evt);
  ASPx.MaskManager.keyCancelled = ASPx.MaskManager.keyCancelled || this.ShouldCancelMaskKeyProcessing(evt, ASPx.MaskManager.savedKeyDownKeyInfo);
  if(ASPx.MaskManager.keyCancelled) {
   ASPx.Evt.PreventEvent(evt);
   return;
  }
  this.maskPasteLock = true;  
  var printable = ASPx.MaskManager.savedKeyDownKeyInfo != null && ASPx.MaskManager.IsPrintableKeyCode(ASPx.MaskManager.savedKeyDownKeyInfo);
  if(printable) {
   ASPx.MaskManager.OnKeyPress(this.maskInfo, keyInfo);
   this.ApplyMaskInfo(true);
  }
  if(printable || ASPx.MaskManager.keyDownHandled)   
   ASPx.Evt.PreventEvent(evt); 
  this.maskPasteLock = false;
  this.UpdateMaskHintHtml();
 },
 MaskPasteTimerProc: function() {
  if(this.maskPasteLock || !this.maskInfo) return;
  this.maskPasteCounter++;
  var inputElement = this.inputElement;
  if(!inputElement || this.maskPasteCounter > 40) {
   this.maskPasteCounter = 0;
   inputElement = this.GetInputElement();
   if(!ASPx.IsExistsElement(inputElement)) {
    this.ClearMaskPasteTimer();
    return;
   }
  }
  if(this.maskTextBeforePaste !== inputElement.value)
   this.ProcessInputValueChangedOnTimer();
  if(!this.focused)
   this.ClearMaskPasteTimer();
 },
 ProcessInputValueChangedOnTimer: function() {
  var inputElement = this.inputElement;
  var selectionInfo = ASPx.Selection.GetInfo(inputElement);
  var startCaretPosition = selectionInfo.startPos;
  var endCaretPosition = selectionInfo.endPos;
  var oldText = this.maskTextBeforePaste;
  var newText = inputElement.value;
  var isAndroidBackSpacePressed = this.isAndroidBackSpacePressed(oldText, newText, startCaretPosition, endCaretPosition);
  var isLastTypedCharacter = newText.indexOf(oldText) == 0 && newText.length > oldText.length;
  if(isAndroidBackSpacePressed || isLastTypedCharacter) {
   this.SetText(newText);
   this.SetCaretPosition(endCaretPosition);
   this.maskValueChangedByPassKeyPressOnAndroid = true;
  } else {
   this.maskInfo.ProcessPaste(newText, endCaretPosition);
   this.ApplyMaskInfo(true);
  }
 },
 isAndroidBackSpacePressed: function(oldText, newText, startCaretPosition, endCaretPosition) {
  if(!ASPx.Browser.AndroidMobilePlatform || startCaretPosition !== endCaretPosition || newText.length >= oldText.length)
   return false;
  var startSubstring = newText.substring(0, startCaretPosition);
  var endSubstring = newText.substring(startCaretPosition);
  var isStartSubstringMatches = oldText.indexOf(startSubstring) == 0;
  var isEndSubstringMatches = endSubstring == "" || oldText.lastIndexOf(endSubstring) == oldText.length - endSubstring.length;
  return isStartSubstringMatches && isEndSubstringMatches;
 },
 BeginShowMaskHint: function() {
  if(!this.GetReadOnly() && this.maskHintTimerID == -1)
   this.maskHintTimerID = window.setInterval(ASPx.MaskHintTimerProc, 500);
 },
 EndShowMaskHint: function() {
  window.clearInterval(this.maskHintTimerID);
  this.maskHintTimerID = -1;
 },
 MaskHintTimerProc: function() {  
  if(this.maskInfo) {
   this.FillMaskInfo();
   this.UpdateMaskHintHtml();
  } else {
   this.EndShowMaskHint();
  }
 },
 UpdateMaskHintHtml: function() {  
  var hint =  this.GetMaskHintElement();
  if(!ASPx.IsExistsElement(hint))
   return;
  var html = ASPx.MaskManager.GetHintHtml(this.maskInfo);
  if(html == this.maskHintHtml)
   return;
  if(html != "") {
   var mainElement = this.GetMainElement();
   if(ASPx.IsExistsElement(mainElement)) {
    hint.innerHTML = html;
    hint.style.position = "absolute";  
    hint.style.left = ASPx.PrepareClientPosForElement(ASPx.GetAbsoluteX(mainElement), mainElement, true) + "px";
    hint.style.top = (ASPx.PrepareClientPosForElement(ASPx.GetAbsoluteY(mainElement), mainElement, false) + mainElement.offsetHeight + 2) + "px";
    hint.style.display = "block";    
   }   
  } else {
   hint.style.display = "none";
  }
  this.maskHintHtml = html;
 },
 HideMaskHint: function() {
  var hint =  this.GetMaskHintElement();
  if(ASPx.IsExistsElement(hint))
   hint.style.display = "none";
  this.maskHintHtml = "";
 },
 GetMaskHintElement: function() {
  return ASPx.GetElementById(this.name + "_MaskHint");
 },
 OnLostFocus: function() {
  if(this.IsAutocompleteOffRequiredOnLostFocus())
   ASPx.Attr.SetAttribute(this.GetInputElement(), "autocomplete", "off");
  ASPxClientEdit.prototype.OnLostFocus.call(this);
 },
 OnMouseWheel: function(evt){
  if(this.GetReadOnly() || this.maskInfo == null || !this.maskInfo.allowMouseWheel)
   return;
  this.FillMaskInfo();
  ASPx.MaskManager.OnMouseWheel(this.maskInfo, ASPx.Evt.GetWheelDelta(evt) < 0 ? -1 : 1);
  this.ApplyMaskInfo(true);
  ASPx.Evt.PreventEvent(evt);
  this.UpdateMaskHintHtml();
 }, 
 OnBrowserWindowResize: function(e) {
  if(!this.autoResizeWithContainer)
   this.AdjustControl();
 },
 IsValueChanged: function() {
  return this.GetValue() != this.lastChangedValue; 
 },
 OnKeyDown: function(evt) {        
  if(this.NeedPreventBrowserUndoBehaviour(evt))
   return ASPx.Evt.PreventEvent(evt);
  if(this.RequireHandleMaxlenManually()) {
   this.onKeyDownInputValue = this.GetInputElement().value;
   var selectionInfo = ASPx.Selection.GetExtInfo(this.GetInputElement());
   this.onKeyDownCursorPos = selectionInfo.startPos;
  }
  this.escCount = 0;
  ASPxClientEdit.prototype.OnKeyDown.call(this, evt);
  if(!this.IsRaiseStandardOnChange(evt)) {
   if(!this.GetReadOnly() && this.maskInfo != null)
    this.HandleMaskKeyDown(evt);
  }
 },
 IsCtrlZ: function(evt) {
  return evt.ctrlKey && !evt.altKey && !evt.shiftKey && (ASPx.Evt.GetKeyCode(evt) == 122 || ASPx.Evt.GetKeyCode(evt) == 90);
 },
 NeedPreventBrowserUndoBehaviour: function(evt) {
  var inputElement = this.GetInputElement();
  return this.IsCtrlZ(evt) && !!inputElement && !inputElement.value;
 },
 OnKeyPress: function(evt) {
  ASPxClientEdit.prototype.OnKeyPress.call(this, evt);
  if(!this.GetReadOnly() && this.maskInfo != null && !this.IsRaiseStandardOnChange(evt))
   this.HandleMaskKeyPress(evt);
  if(this.NeedOnKeyEventEnd(evt, true))
   this.OnKeyEventEnd(evt);
 },
 OnKeyUp: function(evt) {
  if(ASPx.Browser.Firefox && !this.focused && ASPx.Evt.GetKeyCode(evt) === ASPx.Key.Tab)
   return;
  if(this.NeedOnKeyEventEnd(evt, false)) {
   var proccessNextCommingPress = ASPx.Evt.GetKeyCode(evt) === ASPx.Key.Alt; 
   this.OnKeyEventEnd(evt, proccessNextCommingPress);
  }
  if(this.RequireHandleMaxlenManually()) {
   var inputValueLength = this.GetInputElement().value.length;
   var maxLength = this.GetInputMaxLength();
   if(inputValueLength > maxLength && inputValueLength > this.onKeyDownInputValue.length) {
    this.GetInputElement().value = this.onKeyDownInputValue;
    this.SetCaretPosition(this.onKeyDownCursorPos);
   }
  }
  ASPxClientEdit.prototype.OnKeyUp.call(this, evt);
 },
 RequireHandleMaxlenManually: function() { 
  return ASPx.Browser.AndroidMobilePlatform && ASPx.Browser.SamsungAndroidDevice && ASPx.Browser.PlaformMajorVersion < 6 && this.GetInputMaxLength() !== -1;
 },
 GetInputMaxLength: function() {
  var input = this.GetInputElement();
  if(ASPx.Attr.IsExistsAttribute(input, "maxlength"))
   return input.maxLength;
  return -1;
 },
 NeedOnKeyEventEnd: function(evt, isKeyPress) { 
  var handleKeyPress = this.maskInfo != null && evt.keyCode == ASPx.Key.Enter;
  return handleKeyPress == isKeyPress;
 },
 OnKeyEventEnd: function(evt, withDelay){
  if(!this.GetReadOnly()) {
   if(this.IsRaiseStandardOnChange(evt))
    this.RaiseStandardOnChange();
   this.SyncRawValueIfHasTextDecorators(withDelay);
  }
 },
 SyncRawValueIfHasTextDecorators: function(withDelay) {
  if(this.HasTextDecorators()) {
   if(withDelay) {
    window.setTimeout(function() {
     this.SyncRawValue();
    }.aspxBind(this), 0);
   } else 
    this.SyncRawValue();
  }
 },
 IsRaiseStandardOnChange: function(evt){
  return !this.UseSpecialKeyboardHandling() && this.raiseValueChangedOnEnter && evt.keyCode == ASPx.Key.Enter;
 },
 GetFocusSelectAction: function() {
  if (this.maskInfo)
   return this.maskInfo.IsEmpty() ? null : "start";
  return "all"; 
 },
 CorrectFocusWhenDisabled: function() {
  if(!this.GetEnabled()) {
   var inputElement = this.GetInputElement();
   if(inputElement)
    inputElement.blur();
   return true;
  }
  return false;
 },
 EnsureShowPopupHelpText: function() {
  if(this.helpTextDisplayMode === ASPxClientTextEditHelpTextDisplayMode.Popup)
   this.showHelpText();
 },
 EnsureHidePopupHelpText: function() {
  if(this.helpTextDisplayMode === ASPxClientTextEditHelpTextDisplayMode.Popup)
   this.hideHelpText();
 },
 OnFocusCore: function() {
  if(this.maskInfo != null && !ASPx.GetControlCollection().InCallback()) {
   this.TrySetCursorToStartPosition();
   this.SetMaskPasteTimer();
  }
  if(this.IsAutocompleteDropDownListRequiredOnFocus())
   ASPx.Attr.RemoveAttribute(this.GetInputElement(), "autocomplete");
  if(this.CorrectFocusWhenDisabled())
   return;
  var wasLocked = this.IsFocusEventsLocked();
  ASPxClientEdit.prototype.OnFocusCore.call(this);
  if(this.maskInfo != null) {
   this.SavePrevMaskValue();
   this.BeginShowMaskHint();
  }
  if(!wasLocked) {
   this.ToggleTextDecoration();
   this.startUserInputEventTimerIfRequired();
  }
  if(this.isPasswordNullTextInputElementExists())
   setTimeout(function() { this.EnsureShowPopupHelpText(); }.aspxBind(this), 0);
  else
   this.EnsureShowPopupHelpText();
 },
 startUserInputEventTimerIfRequired: function () {
  if(this.shouldStartUserInputTimer() && this.userInputEventTimerID === -1) {
   this.prevInputValue = this.GetInputElement().value;
   this.userInputEventTimerID = ASPx.Timer.SetControlBoundInterval(this.processUserInputEventTimer, this, ASPx.CheckUserInputInterval);
  }
 },
 shouldStartUserInputTimer: function() {
  return !this.UserInput.IsEmpty();
 },
 restartCurrentUserInputTimer: function() {
  if(this.userInputEventTimerID !== -1) {
   this.processUserInputEventTimer(true);
   this.clearUserInputEventTimerIfRequired();
   this.startUserInputEventTimerIfRequired();
  }
 },
 clearUserInputEventTimerIfRequired: function () {
  if (this.userInputEventTimerID !== -1)
   this.userInputEventTimerID = ASPx.Timer.ClearInterval(this.userInputEventTimerID);
 },
 processUserInputEventTimer: function(onRestart) {
  var currentInputValue = this.GetInputElement().value;
  if(currentInputValue !== this.prevInputValue) {
   this.onInputChangedOnUserInputTimer(onRestart);
   this.prevInputValue = currentInputValue;
  }
 },
 onInputChangedOnUserInputTimer: function(onRestart) {
  if(this.raiseUserInputTimeout > -1)
   clearTimeout(this.raiseUserInputTimeout);
  this.raiseUserInputTimeout = setTimeout(function() {
   this.RaiseUserInput();
   this.raiseUserInputTimeout = -1;
  }.bind(this), 0);
 },
 ensureFocusedNullTextElement: function () {
  if(!this.focusedNullTextElement)
   this.createFocusedNullTextElement();
 },
 getFocusedNullTextElementClassName: function() {
  return focusedNullTextClassName;
 },
 getFocusedNullTextElementTagName: function() {
  return "INPUT";
 },
 getCopyFromInputElementStyles: function() {
  return [ "paddingLeft", "paddingTop", "paddingRight", "paddingBottom", "borderCollapse", "borderLeftWidth", "borderTopWidth", "borderRightWidth", "borderBottomWidth" ];
 },
 copyStylesFromInputElementToFocusedNullTextElement: function() {
  var input = this.GetInputElement();
  var inputStyle = ASPx.GetCurrentStyle(input);
  var stylesToCopy = this.getCopyFromInputElementStyles();
  for(var i = 0; i < stylesToCopy.length; i++)
   this.focusedNullTextElement.style[stylesToCopy[i]] = inputStyle[stylesToCopy[i]];
 },
 createFocusedNullTextElement: function() {
  this.focusedNullTextElement = document.createElement(this.getFocusedNullTextElementTagName());
  this.focusedNullTextElement.value = this.nullText;
  this.focusedNullTextElement.className = this.getFocusedNullTextElementClassName();
  this.focusedNullTextElement.tabIndex = -1;
  ASPx.SetElementDisplay(this.focusedNullTextElement, false);
  if(this.accessibilityCompliant) {
   ASPx.Attr.SetAttribute(this.focusedNullTextElement, "aria-label", this.nullText);
   ASPx.Attr.SetAttribute(this.focusedNullTextElement, "aria-hidden", true);
  }
  this.copyStylesFromInputElementToFocusedNullTextElement();
  if (this.nullTextOnFocusCssText) {
   var styleSheet = ASPx.GetCurrentStyleSheet();
   this.focusedNullTextElement.className += " " + ASPx.CreateImportantStyleRule(styleSheet, this.nullTextOnFocusCssText);
  }
  var inputElement = this.GetInputElement();
  inputElement.parentNode.insertBefore(this.focusedNullTextElement, inputElement.nextSibling);
 },
 ensureActivateFocusedNullTextMechanism: function() {
  if (this.nullTextDisplayMode === NullTextDisplayMode.UnfocusedAndFocused) {
   if(this.IsNull(this.GetValue()))
    this.changeFocusedNullTextElementVisibility(true);
   this.setFocusedNullTextTimer();
  }
 },
 ensureDeactivateFocusedNullTextMechanism: function () {
  if (this.nullTextDisplayMode === NullTextDisplayMode.UnfocusedAndFocused) {
   this.clearFocusedNullTextTimer();
   this.changeFocusedNullTextElementVisibility(false);
  }
 },
 setFocusedNullTextTimer: function () {
  if(this.focusedNullTextTimerID === -1)
   this.focusedNullTextTimerID = ASPx.Timer.SetControlBoundInterval(this.onFocusedNullTextVisibilityCheck, this, ASPx.PasteCheckInterval);
 },
 clearFocusedNullTextTimer: function () {
  this.focusedNullTextTimerID = ASPx.Timer.ClearInterval(this.focusedNullTextTimerID);
 },
 onFocusedNullTextVisibilityCheck: function (evt) {
  if(!this.needShowFocusedNullText() && this.isFocusedNullTextElementDisplayed())
   this.changeFocusedNullTextElementVisibility(false);
  else if(this.needShowFocusedNullText() && !this.isFocusedNullTextElementDisplayed())
   this.changeFocusedNullTextElementVisibility(true);
 },
 isFocusedNullTextElementDisplayed: function() {
  return this.focusedNullTextElement && ASPx.GetElementDisplay(this.focusedNullTextElement);
 },
 needShowFocusedNullText: function() {
  if(this.focusedNullTextTimerID === -1)
   return this.IsNull(this.GetValue());
  var result = this.GetInputElement().value === "";
  if(this.CanApplyNullTextDecoration)
   result = result && this.CanApplyNullTextDecoration();
  return result;
 }, 
 changeFocusedNullTextElementVisibility: function (visible) {
  this.ensureFocusedNullTextElement();
  ASPx.SetElementDisplay(this.focusedNullTextElement, visible);
  if(visible)
   this.adjustFocusedNullTextElement();  
 },
 getInputElementAbsoluteX: function(input) {
  var result = ASPx.GetAbsoluteX(input);
  if(ASPx.Browser.Opera || ASPx.Browser.AndroidMobilePlatform) 
   result++;
  return result;
 },
 getInputElementAbsoluteY: function (input) {
  var result = ASPx.GetAbsoluteY(input);
  if(ASPx.Browser.Opera || ASPx.Browser.AndroidMobilePlatform) 
   result++;
  return result;
 },
 adjustFocusedNullTextElement: function() {
  var input = this.GetInputElement();
  this.focusedNullTextElement.style.width = input.offsetWidth + "px";
  this.focusedNullTextElement.style.height = input.offsetHeight + "px";
  var inputXPos = this.getInputElementAbsoluteX(input);
  var inputYPos = this.getInputElementAbsoluteY(input);
  ASPx.SetAbsoluteX(this.focusedNullTextElement, inputXPos);
  ASPx.SetAbsoluteY(this.focusedNullTextElement, inputYPos);
  var shiftByX = inputXPos - ASPx.GetAbsoluteX(this.focusedNullTextElement);
  var shiftByY = inputYPos - ASPx.GetAbsoluteY(this.focusedNullTextElement);
  if (shiftByX !== 0)
   this.focusedNullTextElement.style.left = ASPx.PxToFloat(this.focusedNullTextElement.style.left) + shiftByX + "px";
  if (shiftByY !== 0)
   this.focusedNullTextElement.style.top = ASPx.PxToFloat(this.focusedNullTextElement.style.top) + shiftByY + "px";
 },
 ensureAdjustFocusedNullTextElement: function () {
  if(this.isFocusedNullTextElementDisplayed())
   this.adjustFocusedNullTextElement(this.focusedNullTextElement);
 },
 TrySetCursorToStartPosition: function() {
  var input = this.GetInputElement();
  var sel = ASPx.Selection.GetInfo(input);
  if (sel.startPos === sel.endPos && this.IsMaskInfoEmpty()) {
   var pos = this.maskInfo.GetFirstNonLiteralPosition();
   var setCaret = ASPx.Selection.SetCaretPosition.bind(this, input, pos);
   setTimeout(function() {
    if (document.activeElement === input) {
     setCaret();
     setTimeout(setCaret, 50);
    }
   }, 0);
  }
 },
 IsMaskInfoEmpty: function() {
  return this.maskInfo.IsEmpty();
 },
 OnLostFocusCore: function() {
  var wasLocked = this.IsFocusEventsLocked();
  ASPxClientEdit.prototype.OnLostFocusCore.call(this);
  if(this.maskInfo != null) {
   this.EndShowMaskHint();
   this.HideMaskHint();   
   if(this.maskInfo.ApplyFixes(null))
    this.ApplyMaskInfo(false);
   this.RaiseStandardOnChange();
  }
  if(!wasLocked) {
   this.clearUserInputEventTimerIfRequired();
   this.ToggleTextDecoration();
  }
  this.escCount = 0;
  this.EnsureHidePopupHelpText();
 },
 SetFocus: function() {
  if(this.isPasswordNullTextInputElementExists()) {
   this.GetPasswordNullTextInputElement().focus();
  } else {
     ASPxClientEdit.prototype.SetFocus.call(this);
  }
 },
 OnValueChanged: function() {
  if(this.maskInfo != null) {
   if(!this.maskValueChangedByPassKeyPressOnAndroid && this.maskInfo.GetValue() == this.maskValueBeforeUserInput && !this.IsValueChangeForced())
    return;
   if(this.maskValueChangedByPassKeyPressOnAndroid)
    this.maskValueChangedByPassKeyPressOnAndroid = false;
   this.SavePrevMaskValue();
  }
  if(this.HasTextDecorators())
   this.SyncRawValue();
  if(!this.IsValueChanged() && !this.IsValueChangeForced())
   return;
  this.SaveChangedValue(); 
  ASPxClientEdit.prototype.OnValueChanged.call(this);
 },
 IsValueChangeForced: function() {
  return false;
 },
 OnTextChanged: function() {
 },
 ForceTextChanged: function() {
  this.OnTextChanged();
 },
 SaveChangedValue: function() {
  this.lastChangedValue = this.GetValue();
 },
 RaiseStandardOnChange: function(){
  var element = this.GetInputElement();
  if(element && element.onchange) {
   element.onchange({ target: this.GetInputElement() });
  }
  else if(this.ValueChanged) {
   this.ValueChanged.FireEvent(this);
  }
 },
 RaiseTextChanged: function(processOnServer){
  if(!this.TextChanged.IsEmpty()){
   var args = new ASPxClientProcessingModeEventArgs(processOnServer);
   this.TextChanged.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;  
 },
 RaiseUserInput: function () {
  if(!this.UserInput.IsEmpty()) {
   var args = new ASPxClientEventArgs();
   this.UserInput.FireEvent(this, args);
  }
 },
 GetText: function(){
  if(this.maskInfo != null) {
   return this.maskInfo.GetText();
  } else {
   var value = this.GetValue();
   return value != null ? value : "";
  }
 },
 SetText: function (value){
  if(this.maskInfo != null) {
   this.maskInfo.SetText(value);
   this.ApplyMaskInfo(false);
   this.SavePrevMaskValue();
  } else {
   this.SetValue(value);
  }
 },
 SelectAll: function() {
  this.SetSelection(0, -1, false);
 },
 SetCaretPosition: function(pos) {
  var inputElement = this.GetInputElement();
  ASPx.Selection.SetCaretPosition(inputElement, pos);
 },
 GetCaretPosition: function() {
  var inputElement = this.GetInputElement();
  return ASPx.Selection.GetCaretPosition(inputElement);
 },
 SetSelection: function(startPos, endPos, scrollToSelection) { 
  var inputElement = this.GetInputElement();
  ASPx.Selection.Set(inputElement, startPos, endPos, scrollToSelection, true);
 },
 ChangeEnabledAttributes: function(enabled){
  var inputElement = this.GetInputElement();
  if(inputElement){
   this.ChangeInputEnabledAttributes(inputElement, ASPx.Attr.ChangeAttributesMethod(enabled), enabled);
   this.ChangeSpecialInputEnabledAttributes(inputElement, ASPx.Attr.ChangeEventsMethod(enabled), true);
   this.ChangeInputEnabled(inputElement, enabled, this.GetReadOnly());
   if(this.isPasswordNullTextInputElementExists())
    this.GetPasswordNullTextInputElement().disabled = inputElement.disabled;
  }
 },
 SetReadOnlyInternal: function(readOnly) {
  ASPxClientEdit.prototype.SetReadOnlyInternal.call(this, readOnly);
  this.ChangeInputReadOnly(readOnly);
 },
 ChangeReadOnlyStateItems: function(readOnly) {
  ASPxClientEdit.prototype.ChangeReadOnlyStateItems.call(this, readOnly);
  ASPx.GetStateController().SetElementReadOnly(this.GetInputElement(), readOnly);
  if(this.isPasswordNullTextInputElementExists())
   ASPx.GetStateController().SetElementReadOnly(this.GetPasswordNullTextInputElement(), readOnly);
 },
 ChangeInputReadOnly: function(readOnly) {
  var inputElement = this.GetInputElement();
  if(inputElement)
   inputElement.readOnly = readOnly || !this.GetEnabled() && this.UseReadOnlyForDisabled();
 },
 ChangeEnabledStateItems: function(enabled){
  if(!this.isNative) {
   var sc = ASPx.GetStateController();
   sc.SetElementEnabled(this.GetMainElement(), enabled);
   sc.SetElementEnabled(this.GetInputElement(), enabled);
   if(this.isPasswordNullTextInputElementExists())
    sc.SetElementEnabled(this.GetPasswordNullTextInputElement(), enabled);
  }
 },
 ChangeInputEnabled: function(element, enabled, readOnly) {
  if(this.UseReadOnlyForDisabled())
   element.readOnly = !enabled || readOnly;
  else
   element.disabled = !enabled;
 },
 ChangeInputEnabledAttributes: function(element, method, enabled) {
  method(element, "tabIndex");
  if(!enabled) element.tabIndex = -1;
  method(element, "onclick");
  method(element, "onkeydown");
  method(element, "onkeypress");
  method(element, "onkeyup");
 },
 UseReadOnlyForDisabled: function() {
  return false;
 },
 OnPostFinalization: function(args) {
  this.TryRestoreDisabledOnPost(args);
  this.TryClearInputTextDecorationOnPost(args);
 },
 TryRestoreDisabledOnPost: function(args) { 
  if(this.GetEnabled() || !this.UseReadOnlyForDisabled() || args.isDXCallback)
   return;
  var inputElement = this.GetInputElement();
  if(inputElement) {
   var inputDisabled = inputElement.disabled;
   inputElement.disabled = true;
   window.setTimeout(function() {
    inputElement.disabled = inputDisabled;
   }, 0);
  }
 },
 GetTempHiddenInputID: function() {
  return this.name + ASPx.TempHiddenInputSuffix;
 },
 TryClearInputTextDecorationOnPost: function(args) {
  if(ASPx.Platform === "NETCORE")
   return;
  if(this.HasTextDecorators() && !ASPx.IsExists(this.GetValue())) {
   var inputElement = this.GetInputElement();
   if(inputElement) {
    var name = ASPx.Attr.GetAttribute(inputElement, "name");
    if(name)
     this.TryClearInputTextDecorationOnPostCore(inputElement, name);
   }
  }
 },
 TryClearInputTextDecorationOnPostCore: function(inputElement, name) {
  var hiddenInput = ASPx.CreateHiddenField(name, this.GetTempHiddenInputID(), inputElement.parentNode);
  ASPx.Attr.SetAttribute(inputElement, "data-name", name);
  ASPx.Attr.RemoveAttribute(inputElement, "name");
  setTimeout(function() {
   ASPx.Attr.SetAttribute(inputElement, "name", name);
   ASPx.Attr.RemoveAttribute(inputElement, "data-name");
   ASPx.RemoveElement(hiddenInput);
  }, 0);
 },
 OnUnload: function() {
  var input = this.GetInputElement();
  if(!input)
   return;
  if(this.IsAutocompleteOffNotRequiredOnUnload())
   ASPx.Attr.RemoveAttribute(input, "autocomplete");
  if(this.focusedNullTextElement)
   ASPx.RemoveElement(this.focusedNullTextElement);
 },
 IsVCardAttributeRequired: function() {
  return this.autoCompleteAttribute && this.autoCompleteAttribute.name !== "autocomplete";
 },
 IsAutocompleteDropDownListRequiredOnFocus: function() {
  return !this.autoCompleteAttribute || this.IsVCardAttributeRequired();
 },
 IsAutocompleteOffRequiredOnInitialize: function() {
  return !this.isNative && (this.autoCompleteAttribute && this.autoCompleteAttribute.name === "autocomplete" || ASPx.Browser.WebKitFamily);
 },
 IsAutocompleteOffRequiredOnLostFocus: function() {
  return !this.autoCompleteAttribute && this.IsNullTextVisible() && !this.IsVCardAttributeRequired();
 },
 IsAutocompleteOffNotRequiredOnUnload: function() {
  return !this.IsNullTextVisible() || this.IsVCardAttributeRequired() || (this.maskInfo != null && this.GetValue() == null);
 },
 IsNullTextVisible: function() {
  return this.nullText && !this.GetValue() && !this.GetText();
 },
 GetModifyEvent: function() {
  return this.UserInput;
 }
});
MaskValidationPattern = ASPx.CreateClass(ASPx.ValidationPattern, {
 constructor: function(errorText, maskInfo) {
  this.constructor.prototype.constructor.call(this, errorText);
  this.maskInfo = maskInfo;
 },
 EvaluateIsValid: function(value) {
  return this.maskInfo.IsValid();
 }
});
ASPx.Ident.IsASPxClientTextEdit = function(obj) {
 return !!obj.isASPxClientTextEdit;
};
var ASPxClientTextBoxBase = ASPx.CreateClass(ASPxClientTextEdit, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.sizingConfig.allowSetHeight = false;
  this.sizingConfig.adjustControl = true;
 }
});
var ASPxClientTextBox = ASPx.CreateClass(ASPxClientTextBoxBase, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.isASPxClientTextBox = true;
  this.isCaptchaTextBox = false;
 },
 NeedProcessUnload: function() {
  return ASPxClientTextBoxBase.prototype.NeedProcessUnload.call(this) && !this.isCaptchaTextBox;
 },
 IsValueRestoredByBrowser: function() {
  if(this.isCaptchaTextBox)
   return this.initializeInputValue !== "" && this.initializeInputValue !== this.nullText;
  return  ASPxClientTextBoxBase.prototype.IsValueRestoredByBrowser.call(this);
 },
 SynchronizeRestoredValue: function() {
  if(this.isCaptchaTextBox)
   this.SetText(null);
  else
   ASPxClientTextBoxBase.prototype.SynchronizeRestoredValue.call(this);
 },
});
ASPxClientTextBox.Cast = ASPxClientControl.Cast;
ASPx.Ident.IsASPxClientTextBox = function(obj) {
 return !!obj.isASPxClientTextBox;
};
var ASPxClientMemo = ASPx.CreateClass(ASPxClientTextEdit, { 
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);        
  this.isASPxClientMemo = true;
  this.raiseValueChangedOnEnter = false;
  this.maxLength = 0;
  this.pasteTimerID = -1;
  this.pasteTimerActivatorCount = 0;
 },
 Initialize: function() {
  ASPxClientTextEdit.prototype.Initialize.call(this);
  this.SaveChangedValue();
  this.maxLengthRestricted = this.maxLength > 0;
 },
 CutString: function() {
  var text = this.GetText();
  if(text.length > this.maxLength) {
   text = text.substring(0, this.maxLength);
   this.SetText(text);
  }
 },
 EventKeyCodeChangesTheInput: function(evt) {
  if(ASPx.IsPasteShortcut(evt))
   return true;
  else if(evt.ctrlKey)
   return false;
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  var isSystemKey = ASPx.Key.Windows <= keyCode && keyCode <= ASPx.Key.ContextMenu;
  var isFKey = ASPx.Key.F1 <= keyCode && keyCode <= 127; 
  return ASPx.Key.Delete < keyCode && !isSystemKey && !isFKey || keyCode == ASPx.Key.Enter || keyCode == ASPx.Key.Space;
 },
 OnTextChangingCheck: function() {
  if(this.maxLengthRestricted)  
   this.CutString(); 
 },
 StartTextChangingTimer: function() {
  if(this.maxLengthRestricted) {
   if(this.pasteTimerActivatorCount == 0) 
    this.SetTextChangingTimer();
   this.pasteTimerActivatorCount ++;
  }
 },
 EndTextChangingTimer: function() {
  if(this.maxLengthRestricted) {
   this.pasteTimerActivatorCount --;
   if(this.pasteTimerActivatorCount == 0) 
    this.ClearTextChangingTimer();
  }
 },
 CollapseEditor: function() {
  if(!this.IsAdjustmentRequired()) return;
  var mainElement = this.GetMainElement();
  var inputElement = this.GetInputElement();
  if(!ASPx.IsExistsElement(mainElement) || !ASPx.IsExistsElement(inputElement))
   return;
  ASPxClientTextEdit.prototype.CollapseEditor.call(this);
  var mainElementCurStyle = ASPx.GetCurrentStyle(mainElement);
  if(this.heightCorrectionRequired && mainElement && inputElement) {
   if(mainElement.style.height == "100%" || mainElementCurStyle.height == "100%") {
    mainElement.style.height = "0";
    mainElement.wasCollapsed = true;
   }
   inputElement.style.height = "0";
  }
 },
 SetWidth: function(width) {
  ASPxClientTextEdit.prototype.SetWidth.call(this, width);
 },
 ClearErrorFrameElementsStyles: function() {
  var textarea = this.GetInputElement();
  if(!textarea)
   return;
  var scrollBarPosition = textarea.scrollTop;
  ASPxClientTextEdit.prototype.ClearErrorFrameElementsStyles.call(this);
  if(ASPx.Browser.Firefox)
   textarea.scrollTop = scrollBarPosition;
 },
 OnMouseOver: function() {
  this.StartTextChangingTimer();
 },  
 OnMouseOut: function() {
  this.EndTextChangingTimer();
 },
 OnFocusCore: function() {  
  this.StartTextChangingTimer();
  ASPxClientTextEdit.prototype.OnFocusCore.call(this);
 },
 OnLostFocus: function() {
  this.EndTextChangingTimer();
  ASPxClientTextEdit.prototype.OnLostFocus.call(this);
 },
 OnKeyDown: function(evt) { 
  if(this.NeedPreventBrowserUndoBehaviour(evt))
   return ASPx.Evt.PreventEvent(evt);
  if(this.maxLengthRestricted){
   var selection = ASPx.Selection.GetInfo(this.GetInputElement()); 
   var noCharToReplace = selection.startPos == selection.endPos;
   if(this.GetText().length >= this.maxLength && noCharToReplace && this.EventKeyCodeChangesTheInput(evt)) {
    return ASPx.Evt.PreventEvent(evt);
   }
  }
  ASPxClientEdit.prototype.OnKeyDown.call(this, evt);
 },
 SetTextChangingTimer: function() {
  this.pasteTimerID = ASPx.Timer.SetControlBoundInterval(this.OnTextChangingCheck, this, ASPx.PasteCheckInterval);
 },
 ClearTextChangingTimer: function() {
  this.pasteTimerID = ASPx.Timer.ClearInterval(this.pasteTimerID);
 },
 getFocusedNullTextElementTagName: function() {
  return "TEXTAREA";
 },
 getCopyFromInputElementStyles: function() {
  var result = ASPxClientTextEdit.prototype.getCopyFromInputElementStyles.call(this);
  result.push("resize");
  return result;
 }
});
ASPxClientMemo.Cast = ASPxClientControl.Cast;
ASPx.Ident.IsASPxClientMemo = function(obj) { return obj && !!obj.isASPxClientMemo; };
var CLEAR_BUTTON_INDEX = -100;
var HIDE_CONTENT_CSS_CLASS_NAME = "dxHideContent";
var setContentVisibility = function(clearButtonElement, value) {
 var action = value ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
 action(clearButtonElement, HIDE_CONTENT_CSS_CLASS_NAME);
};
var CLEAR_BUTTON_DISPLAY_MODE = {
 AUTO: 'Auto',
 ALWAYS: 'Always',
 NEVER: 'Never',
 ON_HOVER: 'OnHover'
};
var AccessibilityFocusedButtonClassName = "dxAFB";
var ButtonEditButtonLeftSystemClassName = "dxeButtonLeft";
var ASPxClientButtonEditBase = ASPx.CreateClass(ASPxClientTextBoxBase, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);        
  this.allowUserInput = true;
  this.isValueChanging = false;
  this.allowMouseWheel = true;
  this.isMouseOver = false;
  this.buttonCount = 0;
  this.emptyValueMaskDisplayText = "";
  this.clearButtonDisplayMode = CLEAR_BUTTON_DISPLAY_MODE.AUTO;
  this.forceShowClearButtonAlways = false;
  this.recoverClearButtonVisibility = false;
  this.ButtonClick = new ASPxClientEvent();
 },
 Initialize: function() {
  ASPxClientTextBoxBase.prototype.Initialize.call(this);
  this.EnsureEmptyValueMaskDisplayText();
  if(this.HasClearButton())
   this.InitializeClearButton();
  this.InitAccessibilityCompliant();
 },
 InlineInitialize: function() {
  ASPxClientTextBoxBase.prototype.InlineInitialize.call(this);
  if(this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.AUTO) {
   this.clearButtonDisplayMode = this.IsClearButtonVisibleAuto() || this.forceShowClearButtonAlways ?
    CLEAR_BUTTON_DISPLAY_MODE.ALWAYS : CLEAR_BUTTON_DISPLAY_MODE.NEVER;
  }
  this.EnsureClearButtonVisibility();
 },
 InitializeClearButton: function() {
  if(this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.ON_HOVER) {
   ASPx.Evt.AttachMouseEnterToElement(this.GetHoverElementToShowClearButton(), this.OnMouseOver.aspxBind(this), this.OnMouseOut.aspxBind(this));
  }
 },
 GetHoverElementToShowClearButton: function() {
  return this.GetMainElement();
 },
 IsClearButtonVisibleAuto: function() {
  return ASPx.Browser.MobileUI;
 },
 SetEnabled: function(enabled) {
  ASPxClientTextBoxBase.prototype.SetEnabled.call(this, enabled);
  this.EnsureClearButtonVisibility();
 },
 EnsureEmptyValueMaskDisplayText: function() {
  if(this.maskInfo && this.HasClearButton()) {
   var savedText = this.maskInfo.GetText();
   this.maskInfo.SetText("");
   this.emptyValueMaskDisplayText = this.maskInfo.GetText();
   this.maskInfo.SetText(savedText);
  }
 },
 GetButton: function(number) {
  return this.GetChildElement("B" + number);
 },
 GetCustomButtonCollection: function() {
  var buttonElements = [];
  for(var i = 0; i < this.buttonCount; i++) {
   var button =  this.GetButton(i);
   if(!!button)
    buttonElements.push(button);
  }
  return buttonElements;
 },
 GetButtonCollection: function() {
  var buttonElements = [];
  var clearButton = this.GetClearButton();
  if(!!clearButton)
   buttonElements.push(clearButton);
  return buttonElements.concat(this.GetCustomButtonCollection());
 },
 GetAccessibilityAnchor: function(buttonElement) {
  var firstChild = buttonElement.firstElementChild;
  var isExistsAnchorElement = ASPx.Attr.GetAttribute(firstChild, "role") === "button";
  return isExistsAnchorElement ? firstChild : null;
 },
 GetButtonByAccessibilityAnchor: function(anchorElement) {
  return anchorElement.parentNode;
 },
 SetAccessibilityAnchorEnabled: function(buttonElement, enabled) {
  var anchorElement = this.GetAccessibilityAnchor(buttonElement);
  if(ASPx.IsExists(anchorElement))
   ASPx.Attr.SetOrRemoveAttribute(anchorElement, "tabindex", enabled ? "0" : "");
 },
 InitAccessibilityCompliant: function() {
  if(!this.accessibilityCompliant) return;
  var buttonElements = this.GetButtonCollection();
  var labelElements = ASPx.FindAssociatedLabelElements(this);
  for(var i = 0; i < buttonElements.length; i++) {
   this.InitAccessibilityAnchor(this.GetAccessibilityAnchor(buttonElements[i]), labelElements);
   ASPx.Evt.AttachEventToElement(buttonElements[i], "mousedown", this.Button_MouseDown.bind(this));
  }
 },
 InitAccessibilityAnchor: function(anchorElement, labelElements) {
  if(!ASPx.IsExists(anchorElement))
   return;
  for(var i = 0; i < labelElements.length; i++)
   this.ariaExplanatoryTextManager.SetOrRemoveText([anchorElement], labelElements[i], true, false, false);
  this.InitAccessibilityAnchorEvents(anchorElement);
 },
 InitAccessibilityAnchorEvents: function(anchorElement) {
  ASPx.Evt.AttachEventToElement(anchorElement, "keydown", function(evt) { this.OnButtonKeysHandling(evt); }.aspxBind(this));
  ASPx.Evt.AttachEventToElement(anchorElement, "keyup", function(evt) { this.OnButtonKeysHandling(evt); }.aspxBind(this));
  ASPx.Evt.AttachEventToElement(anchorElement, "focus", function(evt) { this.OnButtonGotFocus(evt); }.aspxBind(this));
  ASPx.Evt.AttachEventToElement(anchorElement, "blur", function(evt) { this.OnButtonLostFocus(evt); }.aspxBind(this));
 },
 EmulateButtonMouseEvent: function(sourceElement) {
  var buttonElement = this.GetButtonByAccessibilityAnchor(sourceElement);
  var mouseEvent = buttonElement.onclick || buttonElement.onmousedown || buttonElement.ontouchstart || buttonElement.onpointerdown;
  var emulateMouseEvtArgs = { button: 0, which: 1, srcElement: buttonElement, target: buttonElement };
  if(!!mouseEvent) {
   ASPx.Attr.SetAttribute(sourceElement, "aria-pressed", true);
   setTimeout(function() {
    mouseEvent(emulateMouseEvtArgs);
    ASPx.Attr.RemoveAttribute(sourceElement, "aria-pressed");
   }, 300);
  }
 },
 OnButtonKeysHandling: function(evt) {
  var isKeyUp = evt.type == "keyup";
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  var sourceElement = ASPx.Evt.GetEventSource(evt);
  if((keyCode == ASPx.Key.Space && isKeyUp) || (keyCode == ASPx.Key.Enter && !isKeyUp))
   this.EmulateButtonMouseEvent(sourceElement);
  if(keyCode != ASPx.Key.Tab)
   ASPx.Evt.PreventEventAndBubble(evt);
  return false;
 },
 OnButtonGotFocus: function(evt) {
  this.UnlockFocusEvents();
  var editor = ASPx.GetControlCollection().Get(this.name);
  var sourceElement = ASPx.Evt.GetEventSource(evt);
  if(!!editor && !editor.CorrectAccessibilityButtonFocus(sourceElement)) {
   var buttonElement = editor.GetButtonByAccessibilityAnchor(sourceElement);
   ASPx.AddClassNameToElement(buttonElement, this.GetAccessibilityFocusedButtonClassName());
   ASPx.EGotFocus(editor.name);
  }
 },
 OnButtonLostFocus: function(evt) {
  var editor = ASPx.GetControlCollection().Get(this.name);
  var sourceElement = ASPx.Evt.GetEventSource(evt);
  if(!!editor) {
   var buttonElement = editor.GetButtonByAccessibilityAnchor(sourceElement);
   ASPx.RemoveClassNameFromElement(buttonElement, this.GetAccessibilityFocusedButtonClassName());
  }
  setTimeout(function() {
   if(!!editor && !editor.IsEditorElement(ASPx.GetActiveElement())) {
    ASPx.ELostFocus(editor.name);
   }
  }.aspxBind(this), 0);
 },
 Button_MouseDown: function(evt) {
  var editor = ASPx.GetControlCollection().Get(this.name);
  if(!!editor) {
   var sourceElement = ASPx.Evt.GetEventSource(evt);
   if(document.activeElement !== sourceElement)
    this.LockFocusEvents();
  }
 },
 ForceRefocusEditor: function(evt, isNativeFocus) {
  if(this.accessibilityCompliant) {
   var srcElement = ASPx.Evt.GetEventSource(evt);
   var customButtons = this.GetCustomButtonCollection();
   for(var i = 0; i < customButtons.length; i++)
    if(customButtons[i] == srcElement || ASPx.GetIsParent(customButtons[i], srcElement))
     return;
  }
  ASPxClientEdit.prototype.ForceRefocusEditor.call(this, evt, isNativeFocus);
  if(this.GetInputElement().type == "password") {
   window.setTimeout(function() { this.GetInputElement().focus(); }.bind(this), 0);
  }
 },
 CorrectAccessibilityButtonFocus: function(sourceElement) {
  if(ASPx.Attr.IsExistsAttribute(sourceElement, "tabindex"))
   return false;
  setTimeout(function() {
   var buttonElements = this.GetButtonCollection();
   for(var i = 0; i < buttonElements.length; i++)
    if(ASPx.GetIsParent(buttonElements[i], sourceElement))
     this.GetAccessibilityAnchor(buttonElements[i]).focus();
  }.aspxBind(this), 0);
  return true;
 },
 OnKeyDown: function(evt) { 
  if(this.NeedEnsureClearButtonVisibilityOnKeyDown()) {
   var hasClearButtonOnHover = this.HasClearButton() && this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.ON_HOVER;
   this.recoverClearButtonVisibility = hasClearButtonOnHover && ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Tab && !evt.shiftKey;
  }
  if(this.accessibilityCompliant) {
   var hasVisibleFocusableButtonToTheRIGHT = this.GetButtonCollection().some(function(buttonElement) {
    return this.IsButtonVisible(buttonElement)
     && !ASPx.ElementHasCssClass(buttonElement, ButtonEditButtonLeftSystemClassName)
     && this.GetAccessibilityAnchor(buttonElement) !== null;
   }, this);
   var hasVisibleFocusableButtonToTheLEFT = this.GetButtonCollection().some(function(buttonElement) {
    return this.IsButtonVisible(buttonElement)
     && ASPx.ElementHasCssClass(buttonElement, ButtonEditButtonLeftSystemClassName)
     && this.GetAccessibilityAnchor(buttonElement) !== null;
   }, this);
   if((ASPx.Evt.GetKeyCode(evt) === ASPx.Key.Tab && !evt.shiftKey && hasVisibleFocusableButtonToTheRIGHT) ||
    (ASPx.Evt.GetKeyCode(evt) === ASPx.Key.Tab && evt.shiftKey && hasVisibleFocusableButtonToTheLEFT ))
    this.LockFocusEvents();
  }
  ASPxClientTextBoxBase.prototype.OnKeyDown.call(this, evt);
 },
 NeedEnsureClearButtonVisibilityOnKeyDown: function() {
  return this.accessibilityCompliant;
 },
 GetAccessibilityFocusedButtonClassName: function() {
  return AccessibilityFocusedButtonClassName;
 },
 SetButtonVisible: function(number, value) {
  var button = this.GetButton(number);
  if(!button)
   return;
  var isClearButton = number === CLEAR_BUTTON_INDEX;
  var visibilityModifier = isClearButton ? setContentVisibility : ASPx.SetElementDisplay;
  if(isClearButton && this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.ALWAYS && this.accessibilityCompliant && this.enabled)
   this.SetAccessibilityAnchorEnabled(button, value);
  visibilityModifier(button, value);
 },
 GetButtonVisible: function(number) {
  var button = this.GetButton(number);
  return this.IsButtonVisible(button);
 },
 IsButtonVisible: function(button) {
  var result = false;
  if(button) {
   if(this.IsClearButtonElement(button) && this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.ALWAYS)
    result = !ASPx.ElementHasCssClass(button, this.GetHideContentCssClassName());
   else
    result = ASPx.IsElementVisible(button);
  }
  return result;
 },
 GetHideContentCssClassName: function() {
  return HIDE_CONTENT_CSS_CLASS_NAME;
 },
 ProcessInternalButtonClick: function(buttonIndex) {
  return false;
 },
 OnButtonClick: function(number) {
  var processOnServer = this.RaiseButtonClick(number);
  if(!this.ProcessInternalButtonClick(number) && processOnServer)
   this.SendPostBack('BC:' + number);
 },
 GetLastSuccesfullValue: function() {
  return this.lastChangedValue;
 },
 OnClear: function() {
  this.startUserInputEventTimerIfRequired();
  this.ClearEditorValueAndForceOnChange();
  this.ForceRefocusEditor(null, true);
  window.setTimeout(this.EnsureClearButtonVisibility.aspxBind(this), 0);
 },
 ClearEditorValueAndForceOnChange: function() {
  if(this.GetReadOnly() || !this.GetButtonVisible(CLEAR_BUTTON_INDEX))
   return;
  var raiseOnChange = this.ClearEditorValueByClearButton();
  if(raiseOnChange)
   this.ForceStandardOnChange();
 },
 ClearEditorValueByClearButton: function() {
  var prevValue = this.GetLastSuccesfullValue();
  this.ClearEditorValueByClearButtonCore();
  return prevValue !== this.GetValue();
 },
 ClearEditorValueByClearButtonCore: function() {
  this.Clear();
  this.GetInputElement().value = '';
 },
 ForceStandardOnChange: function() {
  this.forceValueChanged = true;
  this.RaiseStandardOnChange();
  this.forceValueChanged = false;
 },
 IsValueChangeForced: function() {
  return this.forceValueChanged || ASPxClientTextBoxBase.prototype.IsValueChangeForced.call(this);
 },
 IsValueChanging: function() { return this.isValueChanging; },
 StartValueChanging: function() { this.isValueChanging = true; },
 EndValueChanging: function() { this.isValueChanging = false; },
 IsClearButtonElement: function(element) {
  return ASPx.GetIsParent(this.GetClearButton(), element);
 },
 OnFocusCore: function() {
  if(this.accessibilityCompliant) {
   if(this.focused) 
    this.UnlockFocusEvents();   
   else 
    ASPxClientTextBoxBase.prototype.OnFocusCore.call(this);
  }
  else
   ASPxClientTextBoxBase.prototype.OnFocusCore.call(this);
  this.EnsureClearButtonVisibility();
 },
 OnLostFocusCore: function() {
  ASPxClientTextBoxBase.prototype.OnLostFocusCore.call(this);
  this.EnsureClearButtonVisibility();
  this.recoverClearButtonVisibility = false;
 },
 GetClearButton: function() {
  return this.GetButton(CLEAR_BUTTON_INDEX);
 },
 HasClearButton: function() {
  return !!this.GetClearButton();
 },
 RequireShowClearButton: function() {
  return !this.IsClearButtonDisabled() && !this.IsClearButtonNotRequired() && this.RequireShowClearButtonInternal();
 },
 IsClearButtonDisabled: function() {
  return !this.clientEnabled || !this.HasClearButton() || this.clearButtonDisplayMode === CLEAR_BUTTON_DISPLAY_MODE.NEVER;
 },
 IsClearButtonNotRequired: function() {
  return !this.IsFocused() && !this.isMouseOver && this.clearButtonDisplayMode !== CLEAR_BUTTON_DISPLAY_MODE.ALWAYS && !this.recoverClearButtonVisibility;
 },
 RequireShowClearButtonInternal: function () {
  return this.IsFocused() && this.RequireShowClearButtonCore() || !this.IsNullState();
 },
 RequireShowClearButtonCore: function() {
  var inputText = this.GetInputElement().value;
  return inputText !== this.GetEmptyValueDisplayText();
 },
 IsFocused: function() {
  return this === ASPx.GetFocusedEditor();
 },
 IsNullState: function() {
  var value = this.GetValue();
  return this.IsNull(value) || value === this.GetEmptyValueDisplayText();
 },
 GetEmptyValueDisplayText: function() { 
  return this.maskInfo ? this.emptyValueMaskDisplayText : "";
 },
 EnsureClearButtonVisibility: function() {
  this.SetButtonVisible(CLEAR_BUTTON_INDEX, this.RequireShowClearButton());
 },
 OnMouseOver: function() {
  this.isMouseOver = true;
  this.EnsureClearButtonVisibility();
 },
 OnMouseOut: function() {
  this.isMouseOver = false;
  this.EnsureClearButtonVisibility();
 },
 OnKeyPress: function(evt) {
  if(this.allowUserInput)
   ASPxClientTextBoxBase.prototype.OnKeyPress.call(this, evt);
 },
 OnKeyEventEnd: function(evt, withDelay) {
  ASPxClientTextBoxBase.prototype.OnKeyEventEnd.call(this, evt, withDelay);
  this.EnsureClearButtonVisibility();
 },
 RaiseButtonClick: function(number){
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned("ButtonClick");
  if(!this.ButtonClick.IsEmpty()){
   var args = new ASPxClientButtonEditClickEventArgs(processOnServer, number);
   this.ButtonClick.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 ChangeEnabledAttributes: function(enabled){
  ASPxClientTextEdit.prototype.ChangeEnabledAttributes.call(this, enabled);
  for(var i = 0; i < this.buttonCount; i++){
   var element = this.GetButton(i);
   if(element)
    this.ChangeButtonEnabledAttributes(element, this.GetChangeButtonEnabledAttributesMethod(enabled));
  }
  if(this.accessibilityCompliant)
   this.ChangeAccessibilityButtonEnabledAttributes(enabled);
 },
 ChangeEnabledStateItems: function(enabled){
  ASPxClientTextEdit.prototype.ChangeEnabledStateItems.call(this, enabled);
  for(var i = 0; i < this.buttonCount; i++){
   var element = this.GetButton(i);
   if(element) 
    ASPx.GetStateController().SetElementEnabled(element, enabled);
  }
 },
 GetChangeButtonEnabledAttributesMethod: function(enabled) {
  return ASPx.Attr.ChangeAttributesMethod(enabled);
 },
 ChangeButtonEnabledAttributes: function(element, method){
  method(element, "onclick");
  method(element, "ondblclick");
  if(ASPx.Browser.Edge)
   method(element, "onmousedown");
  method(element, "on" + ASPx.TouchUIHelper.touchMouseDownEventName);
  method(element, "on" + ASPx.TouchUIHelper.touchMouseUpEventName);
 },
 ChangeInputEnabled: function(element, enabled, readOnly) {
  ASPxClientTextEdit.prototype.ChangeInputEnabled.call(this, element, enabled, readOnly || !this.allowUserInput);
 },
 ChangeAccessibilityButtonEnabledAttributes: function(enabled) {
  var buttonElements = this.GetButtonCollection();
  for(var i = 0; i < buttonElements.length; i++)
   this.SetAccessibilityAnchorEnabled(buttonElements[i], enabled);
 },
 SetValue: function(value) {
  ASPxClientTextEdit.prototype.SetValue.call(this, value);
  if(!this.IsFocused())
   this.EnsureClearButtonVisibility();
 },
 OnAssociatedLabelClick: function(focusableElement) {
  var isValidElement = focusableElement && ASPx.IsActionElement(focusableElement) && ASPx.GetIsParent(this.GetMainElement(), focusableElement) && ASPx.IsElementVisible(focusableElement);
  if(isValidElement)
   focusableElement.focus();
  else
   this.SetFocus();
 },
 onClearButtonClick: function() {
  var requireFocus = !ASPx.Browser.VirtualKeyboardSupported || ASPx.Browser.MSTouchUI;
  if(this.ownerListBox)
   this.ownerListBox.ForceLockFocusEvents();
  if((requireFocus && !this.IsFocused()) || this.accessibilityCompliant)
   this.GetInputElement().focus();
  if(this.IsFocused() || !requireFocus) {
   if(this.ownerListBox)
    this.ownerListBox.UnlockFocusEvents();
   else if(this.accessibilityCompliant)
    this.UnlockFocusEvents();
   this.OnClear();
  }
  else
   window.setTimeout(this.onClearButtonClick.bind(this), 100);
 }
});
var ASPxClientButtonEdit = ASPx.CreateClass(ASPxClientButtonEditBase, {
});
ASPxClientButtonEdit.Cast = ASPxClientControl.Cast;
var ASPxClientButtonEditClickEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(processOnServer, buttonIndex){
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.buttonIndex = buttonIndex;
 }
});
var ASPxClientTextEditHelpTextHAlign = {
 Left: "Left",
 Right: "Right",
 Center: "Center"
};
var ASPxClientTextEditHelpTextVAlign = {
 Top: "Top",
 Bottom: "Bottom",
 Middle: "Middle"
};
var ASPxClientTextEditHelpTextDisplayMode = {
 Inline: "Inline",
 Popup: "Popup"
};
var ASPxClientTextEditHelpTextConsts = {
 VERTICAL_ORIENTATION_CLASS_NAME: "dxeVHelpTextSys",
 HORIZONTAL_ORIENTATION_CLASS_NAME: "dxeHHelpTextSys"
};
var ASPxClientTextEditHelpText = ASPx.CreateClass(null, {
 constructor: function (editor, helpTextStyle, helpText, position, hAlign, vAlign, margins, animationEnabled, helpTextDisplayMode) {
  this.hAlign = hAlign;
  this.vAlign = vAlign;
  this.animationEnabled = animationEnabled;
  this.displayMode = helpTextDisplayMode;
  this.editor = editor;
  this.editorMainElement = editor.GetMainElement();
  this.margins = margins ? { Top: margins[0], Right: margins[1], Bottom: margins[2], Left: margins[3] } : null;
  this.defaultMargins = { Top: 10, Right: 10, Bottom: 10, Left: 10 };
  this.position = position;
  this.helpTextElement = this.createHelpTextElement();
  this.setHelpTextZIndex(true);
  this.prepareHelpTextElement(helpTextStyle, helpText);
 },
 getRows: function (table) {
  return ASPx.GetChildNodesByTagName(table, "TR");
 },
 getCells: function (row) {
  return ASPx.GetChildNodesByTagName(row, "TD");
 },
 getCellByIndex: function(row, cellIndex) {
  return this.getCells(row)[cellIndex];
 },
 getCellIndex: function(row, cell) {
  var cells = this.getCells(row);
  for(var i = 0; i < cells.length; i++) {
   if(cells[i] === cell)
    return i;
  }
 },
 isHorizontal: function(position) {
  return position === ASPx.Position.Left || position === ASPx.Position.Right;
 },
 isVertical: function (position) {
  return position === ASPx.Position.Top || position === ASPx.Position.Bottom;
 },
 createEmptyCell: function(assignClassName) {
  var cell = document.createElement("TD");
  if(assignClassName)
   cell.className = "dxeFakeEmptyCell";
  return cell;
 },
 addHelpTextCellToExternalTableWithTwoCells: function (captionCell, errorCell, helpTextCell, errorTableBody, tableRows) {
  var captionPosition = this.editor.captionPosition;
  var errorCellPosition = this.editor.errorCellPosition;
  var helpTextRow = this.isVertical(this.position) ? document.createElement("TR") : null;
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Left && this.isHorizontal(errorCellPosition))
   captionCell.parentNode.insertBefore(helpTextCell, captionCell.nextSibling);
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Right && this.isHorizontal(errorCellPosition))
   captionCell.parentNode.insertBefore(helpTextCell, captionCell);
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Right && this.isHorizontal(errorCellPosition))
   tableRows[0].appendChild(helpTextCell);
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Left && this.isHorizontal(errorCellPosition))
   tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
  if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Bottom && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.appendChild(helpTextRow);
  }
  if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Top && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
  }
  if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Top && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.insertBefore(helpTextRow, captionCell.parentNode.nextSibling);
  }
  if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Bottom && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.insertBefore(helpTextRow, captionCell.parentNode);
  }
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Top && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   helpTextRow.appendChild(this.createEmptyCell());
   errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
  }
  if(this.position === ASPx.Position.Bottom) {
   if(captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Top || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Right) {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell());
    errorTableBody.appendChild(helpTextRow);
   }
  }
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Top && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(this.createEmptyCell());
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
  }
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Bottom && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(this.createEmptyCell());
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.appendChild(helpTextRow);
  }
  if(this.position === ASPx.Position.Right) {
   if(captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Left || captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Top
    || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Right) {
    tableRows[1].appendChild(helpTextCell);
    tableRows[0].appendChild(this.createEmptyCell());
   }
   if(captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Bottom || captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Left) {
    tableRows[0].appendChild(helpTextCell);
    tableRows[1].appendChild(this.createEmptyCell());
   }
  }
  if(this.position === ASPx.Position.Left) {
   if(captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Top || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Right
    || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Left) {
    tableRows[1].insertBefore(helpTextCell, tableRows[1].childNodes[0]);
    tableRows[0].insertBefore(this.createEmptyCell(), tableRows[0].childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Top || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Bottom) {
    tableRows[1].insertBefore(helpTextCell, tableRows[1].childNodes[0]);
    tableRows[0].insertBefore(this.createEmptyCell(errorCellPosition === ASPx.Position.Top), tableRows[0].childNodes[0]);
    tableRows[2].insertBefore(this.createEmptyCell(errorCellPosition !== ASPx.Position.Top), tableRows[2].childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Top) {
    tableRows[2].insertBefore(helpTextCell, tableRows[2].childNodes[0]);
    tableRows[0].insertBefore(this.createEmptyCell(false), tableRows[0].childNodes[0]);
    tableRows[1].insertBefore(this.createEmptyCell(true), tableRows[1].childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Bottom) {
    tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
    tableRows[1].insertBefore(this.createEmptyCell(true), tableRows[1].childNodes[0]);
    tableRows[2].insertBefore(this.createEmptyCell(false), tableRows[2].childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Left || captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Bottom
    || captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Right) {
    tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
    tableRows[1].insertBefore(this.createEmptyCell(), tableRows[1].childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Left && this.isVertical(errorCellPosition)) {
    captionCell.parentNode.insertBefore(helpTextCell, captionCell.nextSibling);
    var emptyCellParentRow = errorCellPosition === ASPx.Position.Top ? tableRows[0] : tableRows[1];
    var helpTextCellIndex = this.getCellIndex(helpTextCell.parentNode, helpTextCell);
    emptyCellParentRow.insertBefore(this.createEmptyCell(), this.getCellByIndex(emptyCellParentRow, helpTextCellIndex));
   }
  }
  if(this.position === ASPx.Position.Right) {
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Top || captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Bottom) {
    tableRows[1].appendChild(helpTextCell);
    tableRows[0].appendChild(this.createEmptyCell(errorCellPosition === ASPx.Position.Top));
    tableRows[2].appendChild(this.createEmptyCell(errorCellPosition !== ASPx.Position.Top));
   }
   if(captionPosition === ASPx.Position.Top && errorCellPosition === ASPx.Position.Top) {
    tableRows[2].appendChild(helpTextCell);
    tableRows[0].appendChild(this.createEmptyCell(false));
    tableRows[1].appendChild(this.createEmptyCell(true));
   }
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Bottom) {
    tableRows[0].appendChild(helpTextCell);
    tableRows[1].appendChild(this.createEmptyCell(true));
    tableRows[2].appendChild(this.createEmptyCell(false));
   }
   if(captionPosition === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Right) {
    tableRows[0].appendChild(helpTextCell);
    tableRows[1].appendChild(this.createEmptyCell());
   }
   if(captionPosition === ASPx.Position.Right && this.isVertical(errorCellPosition)) {
    captionCell.parentNode.insertBefore(helpTextCell, captionCell);
    var emptyCellParentRow = errorCellPosition === ASPx.Position.Top ? tableRows[0] : tableRows[1];
    var helpTextCellIndex = this.getCellIndex(helpTextCell.parentNode, helpTextCell);
    emptyCellParentRow.insertBefore(this.createEmptyCell(), this.getCellByIndex(emptyCellParentRow, helpTextCellIndex));
   }
  }
  if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Top && this.isHorizontal(errorCellPosition)) {
   if(errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(helpTextCell);
   }
   else {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell());
   }
   errorTableBody.insertBefore(helpTextRow, captionCell.parentNode.nextSibling);
  }
  if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Top && this.isHorizontal(errorCellPosition)) {
   if(errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(helpTextCell);
   }
   else {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell());
   }
   errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
  }
  if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Bottom && this.isHorizontal(errorCellPosition)) {
   if(errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(helpTextCell);
   }
   else {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell());
   }
   errorTableBody.insertBefore(helpTextRow, captionCell.parentNode);
  }
  if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Left) {
   helpTextRow.appendChild(this.createEmptyCell(true));
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.appendChild(helpTextRow);
  }
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Bottom && errorCellPosition === ASPx.Position.Bottom) {
   helpTextRow.appendChild(helpTextCell);
   helpTextRow.appendChild(this.createEmptyCell());
   errorTableBody.appendChild(helpTextRow);
  }
  if(this.position === ASPx.Position.Bottom) {
   if(captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Right || captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(errorCellPosition !== ASPx.Position.Right));
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell(errorCellPosition === ASPx.Position.Right));
    errorTableBody.appendChild(helpTextRow);
   }
   if(captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(false));
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(helpTextCell);
    errorTableBody.appendChild(helpTextRow);
   }
   if(captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Right) {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(this.createEmptyCell(false));
    errorTableBody.appendChild(helpTextRow);
   }   
  }
  if(this.position === ASPx.Position.Top) {
   if(captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Right || captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(errorCellPosition !== ASPx.Position.Right));
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell(errorCellPosition === ASPx.Position.Right));
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Left && errorCellPosition === ASPx.Position.Left) {
    helpTextRow.appendChild(this.createEmptyCell(false));
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(helpTextCell);
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   }
   if(captionPosition === ASPx.Position.Right && errorCellPosition === ASPx.Position.Right) {
    helpTextRow.appendChild(helpTextCell);
    helpTextRow.appendChild(this.createEmptyCell(true));
    helpTextRow.appendChild(this.createEmptyCell(false));
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   }
  }
 },
 addHelpTextCellToExternalTableWithErrorCell: function (errorCell, helpTextCell, errorTableBody, tableRows) {
  var errorCellPosition = this.editor.errorCellPosition;
  var helpTextRow = document.createElement("TR");
  if(this.position === ASPx.Position.Left && this.isHorizontal(errorCellPosition))
   tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
  if(this.position === ASPx.Position.Right && this.isHorizontal(errorCellPosition))
   tableRows[0].appendChild(helpTextCell);
  if(this.position === ASPx.Position.Top && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
  }
  if(this.position === ASPx.Position.Bottom && this.isVertical(errorCellPosition)) {
   helpTextRow.appendChild(helpTextCell);
   errorTableBody.appendChild(helpTextRow);
  }
  if(errorCellPosition === ASPx.Position.Left && this.isVertical(this.position)) {
   helpTextRow.appendChild(this.createEmptyCell(true));
   helpTextRow.appendChild(helpTextCell);
   if(this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   else
    errorTableBody.appendChild(helpTextRow);
  }
  if(errorCellPosition === ASPx.Position.Right && this.isVertical(this.position)) {
   helpTextRow.appendChild(helpTextCell);
   helpTextRow.appendChild(this.createEmptyCell(true));
   if(this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   else
    errorTableBody.appendChild(helpTextRow);
  }
  if(this.position === ASPx.Position.Left && this.isVertical(errorCellPosition)) {
   var helpTextParentRowIndex = errorCellPosition === ASPx.Position.Top ? 1 : 0;
   var emptyCellRowIndex = helpTextParentRowIndex === 0 ? 1 : 0;
   tableRows[helpTextParentRowIndex].insertBefore(helpTextCell, tableRows[helpTextParentRowIndex].childNodes[0]);
   tableRows[emptyCellRowIndex].insertBefore(this.createEmptyCell(true), tableRows[emptyCellRowIndex].childNodes[0]);
  }
  if(this.position === ASPx.Position.Right && this.isVertical(errorCellPosition)) {
   var helpTextParentRowIndex = errorCellPosition === ASPx.Position.Top ? 1 : 0;
   var emptyCellRowIndex = helpTextParentRowIndex === 0 ? 1 : 0;
   tableRows[helpTextParentRowIndex].appendChild(helpTextCell);
   tableRows[emptyCellRowIndex].appendChild(this.createEmptyCell(true));
  }
 },
 addHelpTextCellToExternalTableWithCaption: function (captionCell, helpTextCell, errorTableBody, tableRows) {
  var captionPosition = this.editor.captionPosition;
  var helpTextRow = document.createElement("TR");
  if(captionPosition === ASPx.Position.Left && this.isVertical(this.position)) {
   helpTextRow.appendChild(this.createEmptyCell());
   helpTextRow.appendChild(helpTextCell);
   if(this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   else
    errorTableBody.appendChild(helpTextRow);
  }
  if(this.position === ASPx.Position.Left && this.isVertical(captionPosition)) {
   var helpTextParentRowIndex = captionPosition === ASPx.Position.Top ? 1 : 0;
   var emptyCellParentRowIndex = helpTextParentRowIndex === 0 ? 1 : 0;
   tableRows[helpTextParentRowIndex].insertBefore(helpTextCell, tableRows[helpTextParentRowIndex].childNodes[0]);
   tableRows[emptyCellParentRowIndex].insertBefore(this.createEmptyCell(), tableRows[emptyCellParentRowIndex].childNodes[0]);
  }
  if(this.position === ASPx.Position.Right && this.isVertical(captionPosition)) {
   var helpTextParentRowIndex = captionPosition === ASPx.Position.Top ? 1 : 0;
   var emptyCellParentRowIndex = helpTextParentRowIndex === 0 ? 1 : 0;
   tableRows[helpTextParentRowIndex].appendChild(helpTextCell);
   tableRows[emptyCellParentRowIndex].appendChild(this.createEmptyCell());
  }
  if(captionPosition === ASPx.Position.Right && this.isVertical(this.position)) {
   helpTextRow.appendChild(helpTextCell);
   helpTextRow.appendChild(this.createEmptyCell());
   if(this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   else
    errorTableBody.appendChild(helpTextRow);
  }
  if(this.isVertical(captionPosition) && this.isVertical(this.position)) {
   helpTextRow.appendChild(helpTextCell);
   if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, captionCell.parentNode.nextSibling);
   if(captionPosition === ASPx.Position.Top && this.position === ASPx.Position.Bottom)
    errorTableBody.appendChild(helpTextRow);
   if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   if(captionPosition === ASPx.Position.Bottom && this.position === ASPx.Position.Bottom)
    errorTableBody.insertBefore(helpTextRow, captionCell.parentNode);
  }
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Left)
   captionCell.parentNode.insertBefore(helpTextCell, captionCell.nextSibling);
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Right)
   captionCell.parentNode.insertBefore(helpTextCell, captionCell);
  if(captionPosition === ASPx.Position.Left && this.position === ASPx.Position.Right)
   tableRows[0].appendChild(helpTextCell);
  if(captionPosition === ASPx.Position.Right && this.position === ASPx.Position.Left)
   tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
 },
 addHelpTextCellToExternalTableWithEditorOnly: function (helpTextCell, errorTableBody, tableRows) {
  if(this.isHorizontal(this.position)) {
   if(this.position === ASPx.Position.Left)
    tableRows[0].insertBefore(helpTextCell, tableRows[0].childNodes[0]);
   else
    tableRows[0].appendChild(helpTextCell);
  }
  else {
   var helpTextRow = document.createElement("TR");
   helpTextRow.appendChild(helpTextCell);
   if(this.position === ASPx.Position.Top)
    errorTableBody.insertBefore(helpTextRow, errorTableBody.childNodes[0]);
   else
    errorTableBody.appendChild(helpTextRow);
  }
 },
 addHelpTextCellToExternalTable: function (errorTable, helpTextCell) {
  var errorTableBody = ASPx.GetNodeByTagName(errorTable, "TBODY", 0);
  var tableRows = this.getRows(errorTableBody);
  var captionCell = this.editor.GetCaptionCell();
  var errorCell = this.editor.GetErrorCell();
  if(captionCell) {
   if(errorCell)
    this.addHelpTextCellToExternalTableWithTwoCells(captionCell, errorCell, helpTextCell, errorTableBody, tableRows);
   else
    this.addHelpTextCellToExternalTableWithCaption(captionCell, helpTextCell, errorTableBody, tableRows);
  }
  else if(errorCell)
   this.addHelpTextCellToExternalTableWithErrorCell(errorCell, helpTextCell, errorTableBody, tableRows);
  else
   this.addHelpTextCellToExternalTableWithEditorOnly(helpTextCell, errorTableBody, tableRows);
 },
 createExternalTable: function () {
  var externalTable = document.createElement("TABLE");
  externalTable.id = this.editor.name + ASPx.EditElementSuffix.ExternalTable;
  externalTable.cellPadding = 0;
  externalTable.cellSpacing = 0;
  this.applyExternalTableStyle(externalTable);
  var editorWidth = this.editorMainElement.style.width;
  if(ASPx.IsPercentageSize(editorWidth)) {
   externalTable.style.width = editorWidth;
   this.editorMainElement.style.width = "100%";
   this.editor.width = "100%";
  }
  var externalTableBody = document.createElement("TBODY");
  var externalTableRow = document.createElement("TR");
  var externalTableCell = document.createElement("TD");
  externalTable.appendChild(externalTableBody);
  externalTableBody.appendChild(externalTableRow);
  externalTableRow.appendChild(externalTableCell);
  this.editorMainElement.parentNode.appendChild(externalTable);
  ASPx.ChangeElementContainer(this.editorMainElement, externalTableCell, true);
  if(this.editor.accessibilityCompliant)
   ASPx.Attr.SetAttribute(externalTable, "role", "presentation");
  return externalTable;
 },
 applyExternalTableStyle: function (externalTable) {
  var externalTableStyle = this.editor.externalTableStyle;
  if(externalTableStyle.length > 0) {
   this.applyStyleToElement(externalTable, externalTableStyle);
  }
 },
 applyStyleToElement: function(element, style) {
  element.className = style[0];
  if(style[1]) {
   var styleSheet = ASPx.GetCurrentStyleSheet();
   element.className += " " + ASPx.CreateImportantStyleRule(styleSheet, style[1]);
  }
 },
 createInlineHelpTextElement: function () {
  var helpTextElement = document.createElement("TD");
  var externalTable = this.editor.GetExternalTable();
  if(!externalTable)
   externalTable = this.createExternalTable();
  this.addHelpTextCellToExternalTable(externalTable, helpTextElement);
  return helpTextElement;
 },
 createPopupHelpTextElement: function () {
  var helpTextElement = document.createElement("DIV");
  ASPx.InsertElementAfter(helpTextElement, this.editor.GetMainElement());
  ASPx.AnimationHelper.setOpacity(helpTextElement, 0);
  ASPx.SetElementDisplay(helpTextElement, false);
  return helpTextElement;
 },
 createHelpTextElement: function () {
  return this.displayMode === ASPxClientTextEditHelpTextDisplayMode.Popup ?
   this.createPopupHelpTextElement() : this.createInlineHelpTextElement();
 },
 prepareHelpTextElement: function (helpTextStyle, helpText) {
  this.helpTextElement.id = this.getHelpTextElementId();
  this.applyStyleToElement(this.helpTextElement, helpTextStyle);
  ASPx.SetInnerHtml(this.helpTextElement, "<SPAN>" + helpText + "</SPAN>");
  if(this.displayMode === ASPxClientTextEditHelpTextDisplayMode.Popup)
   this.updatePopupHelpTextPosition();
  else {
   var isVerticalOrientation = this.position === ASPx.Position.Top || this.position === ASPx.Position.Bottom;
   var orientationClassName = isVerticalOrientation ? ASPxClientTextEditHelpTextConsts.VERTICAL_ORIENTATION_CLASS_NAME :
    ASPxClientTextEditHelpTextConsts.HORIZONTAL_ORIENTATION_CLASS_NAME;
   this.helpTextElement.className += " " + orientationClassName;
   this.setInlineHelpTextElementAlign();
   ASPx.SetElementDisplay(this.helpTextElement, this.editor.clientVisible);
  }
 },
 getHelpTextElementId: function() {
  return this.editor.name + ASPx.TEHelpTextElementSuffix;
 },
 setInlineHelpTextElementAlign: function() {
  var hAlignValue = "", vAlignValue = "";
  switch(this.hAlign) {
   case ASPxClientTextEditHelpTextHAlign.Left: hAlignValue = "left"; break;
   case ASPxClientTextEditHelpTextHAlign.Right: hAlignValue = "right"; break;
   case ASPxClientTextEditHelpTextHAlign.Center: hAlignValue = "center"; break;
  }
  switch(this.vAlign) {
   case ASPxClientTextEditHelpTextVAlign.Top: vAlignValue = "top"; break;
   case ASPxClientTextEditHelpTextVAlign.Bottom: vAlignValue = "bottom"; break;
   case ASPxClientTextEditHelpTextVAlign.Middle: vAlignValue = "middle"; break;
  }
  this.helpTextElement.style.textAlign = hAlignValue;
  this.helpTextElement.style.verticalAlign = vAlignValue;
 },
 getHelpTextMargins: function() {
  if(this.margins)
   return this.margins;
  var result = this.defaultMargins;
  if(this.position === ASPx.Position.Top || this.position === ASPx.Position.Bottom)
   result.Left = result.Right = 0;
  else
   result.Top = result.Bottom = 0;
  return result;
 },
 updatePopupHelpTextPosition: function (editorMainElement) {
  var editorWidth = this.editorMainElement.offsetWidth;
  var editorHeight = this.editorMainElement.offsetHeight;
  var helpTextWidth = this.helpTextElement.offsetWidth;
  var helpTextHeight = this.helpTextElement.offsetHeight;
  var editorX = ASPx.GetAbsoluteX(this.editorMainElement);
  var editorY = ASPx.GetAbsoluteY(this.editorMainElement);
  var helpTextX = 0, helpTextY = 0;
  var margins = this.getHelpTextMargins();
  if(this.position === ASPx.Position.Top || this.position === ASPx.Position.Bottom) {
   if(this.position === ASPx.Position.Top)
    helpTextY = editorY - margins.Bottom - helpTextHeight;
   else if(this.position === ASPx.Position.Bottom)
    helpTextY = editorY + editorHeight + margins.Top;
   if(this.hAlign === ASPxClientTextEditHelpTextHAlign.Left)
    helpTextX = editorX + margins.Left;
   else if(this.hAlign === ASPxClientTextEditHelpTextHAlign.Right)
    helpTextX = editorX + editorWidth - helpTextWidth - margins.Right;
   else if(this.hAlign === ASPxClientTextEditHelpTextHAlign.Center) {
    var editorCenterX = editorX + editorWidth / 2;
    var helpTextWidthWithMargins = helpTextWidth + margins.Left + margins.Right;
    helpTextX = editorCenterX - helpTextWidthWithMargins / 2 + margins.Left;
   }
  } else {
   if(this.position === ASPx.Position.Left)
    helpTextX = editorX - margins.Right - helpTextWidth;
   else if(this.position === ASPx.Position.Right)
    helpTextX = editorX + editorWidth + margins.Left;
   if(this.vAlign === ASPxClientTextEditHelpTextVAlign.Top)
    helpTextY = editorY + margins.Top;
   else if(this.vAlign === ASPxClientTextEditHelpTextVAlign.Bottom)
    helpTextY = editorY + editorHeight - helpTextHeight - margins.Bottom;
   else if(this.vAlign === ASPxClientTextEditHelpTextVAlign.Middle) {
    var editorCenterY = editorY + editorHeight / 2;
    var helpTextHeightWithMargins = helpTextHeight + margins.Top + margins.Bottom;
    helpTextY = editorCenterY - helpTextHeightWithMargins / 2 + margins.Top;
   }
  }
  helpTextX = helpTextX < 0 ? 0 : helpTextX;
  helpTextY = helpTextY < 0 ? 0 : helpTextY;
  ASPx.SetAbsoluteX(this.helpTextElement, helpTextX);
  ASPx.SetAbsoluteY(this.helpTextElement, helpTextY);
 },
 setHelpTextZIndex: function (hide) { 
  var newZIndex = 41998 * (hide ? -1 : 1);
  if(this.helpTextElement.style.zIndex != newZIndex)
   this.helpTextElement.style.zIndex = newZIndex;
 },
 hide: function () {
  if(this.displayMode === ASPxClientTextEditHelpTextDisplayMode.Inline) {
   ASPx.SetElementDisplay(this.helpTextElement, false);
  }
  else
   this.hidePopupHelpText();
 },
 hidePopupHelpText: function() {
  var onHidePopupHelpTextComplete = function () {
   this.setHelpTextZIndex(true);
   ASPx.SetElementDisplay(this.helpTextElement, false);
  }.aspxBind(this);
  if(this.animationEnabled)
   ASPx.AnimationHelper.fadeOut(this.helpTextElement, onHidePopupHelpTextComplete);
  else {
   ASPx.AnimationHelper.setOpacity(this.helpTextElement, 0);
   onHidePopupHelpTextComplete();
  }    
 },
 show: function () {
  if(this.displayMode === ASPxClientTextEditHelpTextDisplayMode.Inline) {
   ASPx.SetElementDisplay(this.helpTextElement, true);
  }
  else
   this.showPopupHelpText();
 },
 showPopupHelpText: function () {
  ASPx.SetElementDisplay(this.helpTextElement, true);
  this.updatePopupHelpTextPosition();
  if(this.animationEnabled)
   ASPx.AnimationHelper.fadeIn(this.helpTextElement);
  else
   ASPx.AnimationHelper.setOpacity(this.helpTextElement, 1);
  this.setHelpTextZIndex(false);
 }
});
var ASPxOutOfRangeWarningManager = ASPx.CreateClass(null, {
 constructor: function (editor, minValue, maxValue, defaultMinValue, defaultMaxValue, outOfRangeWarningElementPosition, valueFormatter) {
  this.editor = editor;
  this.outOfRangeWarningElementPosition = outOfRangeWarningElementPosition;
  this.minValue = minValue;
  this.maxValue = maxValue;
  this.defaultMinValue = defaultMinValue;
  this.defaultMaxValue = defaultMaxValue;
  this.minMaxValueFormatter = valueFormatter;
  this.animationDuration = 150;
  this.CreateOutOfRangeWarningElement();
 },
 SetMinValue: function (minValue) {
  this.minValue = minValue;
  this.UpdateOutOfRangeWarningElementText();
 },
 SetMaxValue: function (maxValue) {
  this.maxValue = maxValue;
  this.UpdateOutOfRangeWarningElementText();
 },
 CreateOutOfRangeWarningElement: function () {
  this.outOfRangeWarningElement = document.createElement("DIV");
  this.outOfRangeWarningElement.id = this.editor.name + "OutOfRWarn";
  ASPx.InsertElementAfter(this.outOfRangeWarningElement, this.editor.GetOutOfRangeWarningElementPrevSibling());
  ASPx.AnimationHelper.setOpacity(this.outOfRangeWarningElement, 0);
  this.outOfRangeWarningElement.className = this.editor.outOfRangeWarningClassName;
  this.UpdateOutOfRangeWarningElementText();
 },
 IsValueInRange: function (value) {
  return (!this.IsMinValueExists() || value >= this.minValue)
   && (!this.IsMaxValueExists() || value <= this.maxValue);
 },
 IsMinValueExists: function() {
  return ASPx.IsExists(this.minValue) && !isNaN(this.minValue) && this.minValue !== this.defaultMinValue;
 },
 IsMaxValueExists: function () {
  return ASPx.IsExists(this.maxValue) && !isNaN(this.maxValue) && this.maxValue !== this.defaultMaxValue;
 },
 GetFormattedTextByValue: function(value) {
  if (this.minMaxValueFormatter)
   return this.minMaxValueFormatter.Format(value);
  return value;
 },
 GetWarningText: function() {
  var textTemplate = arguments[0];
  var valueTexts = [];
  for (var i = 1; i < arguments.length; i++) {
   var valueText = this.GetFormattedTextByValue(arguments[i]);
   valueTexts.push(valueText);
  }
  return ASPx.Formatter.Format(textTemplate, valueTexts);
 },
 UpdateOutOfRangeWarningElementText: function () {
  var text = "";
  if (this.IsMinValueExists() && this.IsMaxValueExists())
   text = this.GetWarningText(this.editor.outOfRangeWarningMessages[0], this.minValue, this.maxValue);
  if (this.IsMinValueExists() && !this.IsMaxValueExists())
   text = this.GetWarningText(this.editor.outOfRangeWarningMessages[1], this.minValue);
  if (!this.IsMinValueExists() && this.IsMaxValueExists())
   text = this.GetWarningText(this.editor.outOfRangeWarningMessages[2], this.maxValue);
  ASPx.SetInnerHtml(this.outOfRangeWarningElement, "<LABEL>" + text + "</LABEL>");
 },
 UpdateOutOfRangeWarningElementVisibility: function (currentValue) {
  var isValidValue = currentValue == null || this.IsValueInRange(currentValue);
  if (!isValidValue && !this.outOfRangeWarningElementShown)
   this.ShowOutOfRangeWarningElement();
  if (isValidValue && this.outOfRangeWarningElementShown)
   this.HideOutOfRangeWarningElement();
 },
 GetOutOfRangeWarningElementCoordinates: function() {
  var editorMainElement = this.editor.GetMainElement();
  var editorWidth = editorMainElement.offsetWidth;
  var editorHeight = editorMainElement.offsetHeight;
  var editorX = ASPx.GetAbsoluteX(editorMainElement);
  var editorY = ASPx.GetAbsoluteY(editorMainElement);
  var outOfRangeWarningElementX = this.outOfRangeWarningElementPosition === ASPx.Position.Right ? editorX + editorWidth : editorX;
  var outOfRangeWarningElementY = this.outOfRangeWarningElementPosition === ASPx.Position.Right ? editorY : editorY + editorHeight;
  outOfRangeWarningElementX = outOfRangeWarningElementX < 0 ? 0 : outOfRangeWarningElementX;
  outOfRangeWarningElementY = outOfRangeWarningElementY < 0 ? 0 : outOfRangeWarningElementY;
  return {
   x: outOfRangeWarningElementX,
   y: outOfRangeWarningElementY
  };
 },
 ShowOutOfRangeWarningElement: function () {
  this.outOfRangeWarningElement.style.display = "inline";
  var outOfRangeWarningElementCoordinates = this.GetOutOfRangeWarningElementCoordinates();
  ASPx.SetAbsoluteX(this.outOfRangeWarningElement, outOfRangeWarningElementCoordinates.x);
  ASPx.SetAbsoluteY(this.outOfRangeWarningElement, outOfRangeWarningElementCoordinates.y);
  ASPx.AnimationHelper.fadeIn(this.outOfRangeWarningElement, null, this.animationDuration);
  this.ScrollToWarningElementIfRequired(outOfRangeWarningElementCoordinates);
  this.outOfRangeWarningElementShown = true;
 },
 HideOutOfRangeWarningElement: function () {
  ASPx.AnimationHelper.fadeOut(this.outOfRangeWarningElement, function () {
   ASPx.SetElementDisplay(this.outOfRangeWarningElement, false);
  }.aspxBind(this), this.animationDuration);
  this.outOfRangeWarningElementShown = false;
 },
 ScrollToWarningElementIfRequired: function (outOfRangeWarningElementCoordinates) {
  if(this.outOfRangeWarningElementPosition === ASPx.Position.Right) {
   var warnElementRightPos = outOfRangeWarningElementCoordinates.x
    + ASPx.PxToInt(ASPx.GetCurrentStyle(this.outOfRangeWarningElement).marginLeft)
    + this.outOfRangeWarningElement.offsetWidth;
   if(warnElementRightPos > ASPx.GetDocumentClientWidth() + ASPx.GetDocumentScrollLeft())
    ASPx.SetDocumentScrollLeft(warnElementRightPos - ASPx.GetDocumentClientWidth());
  }
  if(this.outOfRangeWarningElementPosition === ASPx.Position.Bottom) {
   var warnElementBottomPos = outOfRangeWarningElementCoordinates.y
    + ASPx.PxToInt(ASPx.GetCurrentStyle(this.outOfRangeWarningElement).marginTop)
    + this.outOfRangeWarningElement.offsetHeight;
   if(warnElementBottomPos > ASPx.GetDocumentClientHeight() + ASPx.GetDocumentScrollTop())
    ASPx.SetDocumentScrollTop(warnElementBottomPos - ASPx.GetDocumentClientHeight());
  }
 }
});
ASPx.MMMouseOut = function(name, evt) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit != null) edit.OnMouseOut(evt);
};
ASPx.MMMouseOver = function(name, evt) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit != null) edit.OnMouseOver(evt);
};
ASPx.MaskHintTimerProc = function() {
 var focusedEditor = ASPx.GetFocusedEditor();
 if(focusedEditor != null && ASPx.IsFunction(focusedEditor.MaskHintTimerProc))
  focusedEditor.MaskHintTimerProc();
};
ASPx.ETextChanged = function(name) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit != null) edit.OnTextChanged(); 
};
ASPx.BEClick = function(name,number){
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit != null) edit.OnButtonClick(number);
};
ASPx.BEClear = function(name, evt) {
 var edit = ASPx.GetControlCollection().Get(name);
 if(edit && (evt.button === 0 || ASPx.Browser.TouchUI))
  edit.onClearButtonClick();
};
ASPx.SetFocusToTextEditWithDelay = function(name) {
 window.setTimeout(function() {
  var edit = ASPx.GetControlCollection().Get(name);
  if(edit)
   edit.SetFocus();
 }, 500);
};
window.ASPxClientTextEdit = ASPxClientTextEdit;
window.ASPxClientTextBoxBase = ASPxClientTextBoxBase;
window.ASPxClientTextBox = ASPxClientTextBox;
window.ASPxClientMemo = ASPxClientMemo;
window.ASPxClientButtonEditBase = ASPxClientButtonEditBase;
window.ASPxClientButtonEdit = ASPxClientButtonEdit;
window.ASPxClientButtonEditClickEventArgs = ASPxClientButtonEditClickEventArgs;
})();

(function(){
 var ScrollingManager = ASPx.CreateClass(null, {
  constructor: function(owner, options) {
   this.owner = owner;
   this.scrollableArea = options.scrollableArea;
   this.orientation = options.orientation;
   this.animationDelay = 1;
   this.animationStep = 2;
   this.animationOffset = 5;
   this.animationAcceleration = 0;
   this.scrollSessionInterval = 10;
   this.stopScrolling = true;
   this.busy = false;
   this.currentAcceleration = 0;
   this.startPos = 0;
   this.onBeforeScrolling = options.onBeforeScrolling;
   this.onAfterScrolling = options.onAfterScrolling;
   this.emulationMode = options.forseEmulation === true || !ASPx.Browser.TouchUI;
   this.useMarginForPosition = options.useMarginForPosition;
   this.handleMouseWheel = !!options.handleMouseWheel;
   this.Initialize();
  },
  Initialize: function(){
   this.setParentNodeOverflow();
   if(this.emulationMode) {
    this.wrapper = new ScrollingManager.scrollWrapper(this.scrollableArea, this.useMarginForPosition);
   } else {
    this.wrapper = new ScrollingManager.scrollWrapperTouchUI(this.scrollableArea, function(direction){
     if(this.onAfterScrolling)
      this.onAfterScrolling(this, direction);
    }.aspxBind(this)); 
   }
   if(this.handleMouseWheel)
    ASPx.Evt.AttachEventToElement(this.scrollableArea, ASPx.Evt.GetMouseWheelEventName(), this.onMouseWheel.aspxBind(this));
  },
  onMouseWheel: function(e) {
   ASPx.Evt.PreventEvent(e);
   var delta = ASPx.Evt.GetWheelDelta(e);
   if(ASPx.Browser.Firefox && ASPx.Browser.Version < 89)
    delta = delta / 0.03;
   this.DoScrollSessionToOffset(-delta);
  },
  setParentNodeOverflow: function() {
   if(ASPx.Browser.MSTouchUI){
    this.scrollableArea.parentNode.style.overflow = "auto";
    this.scrollableArea.parentNode.style["-ms-overflow-style"] = "-ms-autohiding-scrollbar";
   } 
  },
  GetScrolledAreaPosition: function() {
   return this.wrapper.GetScrollLeft() * this.orientation[0]
    + this.wrapper.GetScrollTop() * this.orientation[1];
  },
  SetScrolledAreaPosition: function(pos) {
   this.wrapper.SetScrollLeft(pos * this.orientation[0]);
   this.wrapper.SetScrollTop(pos * this.orientation[1]);
  },
  PrepareForScrollAnimation: function() {
   if(!this.scrollableArea)
    return;  
   this.currentAcceleration = 0;
   this.startPos = this.GetScrolledAreaPosition();
   this.busy = false;
  },
  GetAnimationStep: function(dir) {
   var step = dir * (this.animationStep + this.currentAcceleration);
   var newPos = this.GetScrolledAreaPosition() + step;
   var requiredPos = this.startPos + dir * this.animationOffset;
   if((dir == 1 && newPos >= requiredPos) || (dir == -1 && newPos <= requiredPos)) {
    step = requiredPos - this.GetScrolledAreaPosition();
   } 
   return step;
  },
  DoScrollSessionToOffset: function(offset) {
   var newScrollPos = this.GetScrolledAreaPosition() - offset;
   this.stopScrolling = false;
   if(this.onBeforeScrolling)
    this.onBeforeScrolling(this, offset);
   if(this.stopScrolling) return;
   newScrollPos = Math.min(newScrollPos, 0);
   this.SetScrolledAreaPosition(newScrollPos);
   if(this.onAfterScrolling)
    this.onAfterScrolling(this, offset); 
  },
  DoScrollSessionAnimation: function(direction) {
   if(!this.scrollableArea)
    return;
   this.SetScrolledAreaPosition(this.GetScrolledAreaPosition() + this.GetAnimationStep(direction));
   var self = this;
   if(!this.ShouldStopScrollSessionAnimation()) {
    this.busy = true;
    this.currentAcceleration += this.animationAcceleration;
    window.setTimeout(function() { self.DoScrollSessionAnimation(direction); }, this.animationDelay);
   } else {
    this.busy = false;
    if(this.onAfterScrolling)
     this.onAfterScrolling(this, -direction);   
    this.currentAcceleration = 0;
    window.setTimeout(function() { self.DoScroll(direction); }, this.scrollSessionInterval);
   }
  },
  ShouldStopScrollSessionAnimation: function() {
   return (Math.abs(this.GetScrolledAreaPosition() - this.startPos) >= Math.abs(this.animationOffset));
  },
  DoScroll: function(direction) {
   if(!this.scrollableArea)
    return; 
   if(!this.busy && !this.stopScrolling) {
    if(this.onBeforeScrolling)
     this.onBeforeScrolling(this, -direction);
    if(this.stopScrolling) return;
    this.PrepareForScrollAnimation();
    this.DoScrollSessionAnimation(direction);
   } 
  },
  StartScrolling: function(direction, delay, step) {
   this.stopScrolling = false;
   this.animationDelay = delay;
   this.animationStep = step;
   this.DoScroll(-direction);
  },
  StopScrolling: function() {
   this.stopScrolling = true;
  },
  IsStopped: function() {
   return this.stopScrolling;
  },
  IsInProgress: function() {
   return this.busy;
  }
 });
 var MouseScrollingManager = ASPx.CreateClass(ScrollingManager, {
  constructor: function(owner, options) {
   this.mouseEventsElement = options.mouseEventsElement;
   this.preventOuterScroll = options.preventOuterScroll;
   this.enableMouseScrollInternal = true;
   this.constructor.prototype.constructor.call(this, owner, options);
  },
  Initialize: function() {
   ASPx.ScrollingManager.prototype.Initialize.call(this);
   this.initializeMouseScroll();
  },
  initializeMouseScroll: function() {
   this.mouseDown = false;
   this.vx = 0;
   this.prevX = 0;
   this.scrollTime = null;
   this.mouseScrollAcceleration = 0.7;
   this.mouseScrollTimeStep = 30;
   ASPx.Evt.AttachEventToElement(this.mouseEventsElement, ASPx.TouchUIHelper.touchMouseDownEventName, this.startMouseScroll.aspxBind(this));
  },
  scrollToOffset: function(mouseOffset) {
   var newOffset = this.GetScrolledAreaPosition() - mouseOffset;
   if(this.getValidNewScrollOffset)
    newOffset = this.getValidNewScrollOffset(newOffset);
   this.SetScrolledAreaPosition(newOffset);
  },
  preventTextSelectionAndOuterDivScrollOnScroll: function(e) {
   if(this.preventOuterScroll)
    ASPx.Evt.PreventEvent(e);
   ASPx.Selection.Clear();
  },
  mouseScroll: function(e) {
   if(!this.mouseDown) return;
   this.preventTextSelectionAndOuterDivScrollOnScroll(e);
   var x = ASPx.Evt.GetEventX(e),
    dx = this.prevX - x,
    dt = new Date() - this.scrollTime;
   if(dt < 1) dt = 1;
   this.vx = dx / dt;
   this.scrollToOffset(dx);
   this.prevX = x;
   this.scrollTime = new Date();
  },
  startMouseScroll: function(e) {
   if(!this.enableMouseScrollInternal) return;
   this.detachMouseEvents();
   this.mouseMoveHandler = this.mouseScroll.aspxBind(this);
   this.mouseUpHandler = this.stopMouseScroll.aspxBind(this);
   ASPx.Evt.AttachEventToElement(document, ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
   ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
   this.mouseDown = true;
   window.clearTimeout(this.inertialStopTimerId);
   this.prevX = ASPx.Evt.GetEventX(e);
   this.scrollTime = new Date();
  },
  detachMouseEvents: function() {
   ASPx.Evt.DetachEventFromElement(document, ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
   ASPx.Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
  },
  stopMouseScroll: function() {
   this.detachMouseEvents();
   this.mouseDown = false;
   this.inertialStopTimerId = window.setTimeout(function() {
    this.vx *= this.mouseScrollAcceleration;
    if(Math.abs(this.vx) < 0.1) {
     this.vx = 0;
     if(this.onAfterScrolling)
      this.onAfterScrolling(this);
     return;
    }
    var dx = Math.ceil(this.vx * this.mouseScrollTimeStep);
    this.scrollToOffset(dx);
    this.stopMouseScroll();
   }.aspxBind(this), this.mouseScrollTimeStep);
  }
 });
 ScrollingManager.scrollWrapper = function(scrollableArea, useMarginForPosition) {
  this.scrollableArea = scrollableArea;
  this.useMarginForPosition = useMarginForPosition;
  this.Initialize();
 };
 ScrollingManager.scrollWrapper.prototype = {
  Initialize: function() {
   if(this.useMarginForPosition) {
    this.leftScrollProperty = "margin-left";
    this.topScrollProperty = "margin-top";
   } else {
    this.scrollableArea.style.position = "relative";
    this.scrollableArea.parentNode.style.position = "relative";
    this.leftScrollProperty = "left";
    this.topScrollProperty = "top";
   }
  },
  GetScrollLeft: function() { return ASPx.PxToFloat(this.scrollableArea.style[this.leftScrollProperty]); },
  GetScrollTop: function() { return ASPx.PxToFloat(this.scrollableArea.style[this.topScrollProperty]); },
  SetScrollLeft: function(value) {
   this.scrollableArea.style[this.leftScrollProperty] = value + "px";
  },
  SetScrollTop: function(value) {
   this.scrollableArea.style[this.topScrollProperty] = value + "px";
  }
 };
 ScrollingManager.scrollWrapperTouchUI = function(scrollableArea, onScroll){
  this.scrollableArea = scrollableArea;
  this.scrollTimerId = -1;
  this.onScroll = onScroll;
  this.Initialize(onScroll);
 };
 ScrollingManager.scrollWrapperTouchUI.prototype = {
  Initialize: function(){
   var div = this.scrollableArea.parentNode;
   var timeout = ASPx.Browser.MSTouchUI ? 500 : 1000;
   var nativeScrollSupported = ASPx.TouchUIHelper.nativeScrollingSupported();
   this.onScrollCore = function(){
     ASPx.Timer.ClearTimer(this.scrollTimerId);
     if(this.onScrollLocked) return;
     this.scrollTimerId = window.setTimeout(this.onScrollByTimer, timeout);
    }.aspxBind(this);
   this.onScrollByTimer = function(){
     if(this.onScrollLocked) return;
     var direction = this.lastScrollTop < div.scrollTop ? 1 : -1;
     this.lastScrollTop = div.scrollTop;
     this.onScrollLocked = true;
     this.onScroll(direction);
     this.onScrollLocked = false;
    }.aspxBind(this);
   this.lastScrollTop = div.scrollTop;
   var onscroll = nativeScrollSupported ? this.onScrollCore : this.onScrollByTimer;
   ASPx.Evt.AttachEventToElement(div, "scroll", onscroll);
   if(ASPx.Browser.WebKitTouchUI)
    this.scrollExtender = ASPx.TouchUIHelper.MakeScrollable(div, {showHorizontalScrollbar: false});
  },
  GetScrollLeft: function(){ return -this.scrollableArea.parentNode.scrollLeft; },
  GetScrollTop:  function(){ return -this.scrollableArea.parentNode.scrollTop; },
  SetScrollLeft: function(value){ 
   this.onScrollLocked = true;
   this.scrollableArea.parentNode.scrollLeft = -value; 
   this.onScrollLocked = false;
  },
  SetScrollTop:  function(value){ 
   this.onScrollLocked = true;
   this.scrollableArea.parentNode.scrollTop  = -value; 
   this.onScrollLocked = false;
  }
 };
 ASPx.ScrollingManager = ScrollingManager;
 ASPx.MouseScrollingManager = MouseScrollingManager;
})();
(function() {
var Constants = {
 MIIdSuffix: "_DXI",
 MMIdSuffix: "_DXM",
 SBIdSuffix: "_DXSB",
 SBUIdEnd: "_U",
 SBDIdEnd: "_D",
 ATSIdSuffix: "_ATS",
 SampleCssClassNameForImageElement: "SAMPLE_CSS_CLASS",
 ImagePostfix: "Img",
 PopupImagePostfix: "PImg",
 ItemPopoutElementPostfix: "P",
 ItemContentElementPostfix: "T"
};
var SLIDE_DURATION_VALUE = 300;
var SIDE_MENU_ZINDEX_VALUE = 10000;
var MENU_PREFIX_CLASS_NAME = 'dxm';
var SLIDE_PANEL_EXPANDED_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-expanded';
var BREAD_CRUMBS_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-bread-crumbs';
var OVERLAY_PANEL_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-overlay';
var BURGER_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-side-menu-button';
var BACK_ICON_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-back-icon';
var NO_MAIN_POP_OUT_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-no-main-popout';
var TEMPORARY_VISIBILITY_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-temp-visibility';
var SIDE_MENU_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-side-menu-mode';
var PRE_HOVERED_ELEMENT_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-pre-hovered';
var PRE_SELECTED_ELEMENT_CLASS_NAME = MENU_PREFIX_CLASS_NAME + '-pre-selected';
var MenuItemInfo = ASPx.CreateClass(null, {
 constructor: function(menu, indexPath) {
  var itemElement = menu.GetItemElement(indexPath);
  this.clientHeight = itemElement.clientHeight;
  this.clientWidth = itemElement.clientWidth;
  this.clientTop = ASPx.GetClientTop(itemElement);
  this.clientLeft = ASPx.GetClientLeft(itemElement);
  this.offsetHeight = itemElement.offsetHeight;
  this.offsetWidth = itemElement.offsetWidth;
  this.offsetTop = 0;
  this.offsetLeft = 0;
 }
});
var MenuCssClasses = {};
MenuCssClasses.Prefix = "dxm-";
MenuCssClasses.Menu = "dxmLite";
MenuCssClasses.BorderCorrector = "dxmBrdCor";
MenuCssClasses.Disabled = MenuCssClasses.Prefix + "disabled";
MenuCssClasses.MainMenu = MenuCssClasses.Prefix + "main";
MenuCssClasses.PopupMenu = MenuCssClasses.Prefix + "popup";
MenuCssClasses.ItemTemplate = MenuCssClasses.Prefix + "tmpl";
MenuCssClasses.HorizontalMenu = MenuCssClasses.Prefix + "horizontal";
MenuCssClasses.VerticalMenu = MenuCssClasses.Prefix + "vertical";
MenuCssClasses.NoWrapMenu = MenuCssClasses.Prefix + "noWrap";
MenuCssClasses.AutoWidthMenu = MenuCssClasses.Prefix + "autoWidth";
MenuCssClasses.CalculateMenu = MenuCssClasses.Prefix + "calc";
MenuCssClasses.DX = "dx";
MenuCssClasses.Separator = MenuCssClasses.Prefix + "separator";
MenuCssClasses.Spacing = MenuCssClasses.Prefix + "spacing";
MenuCssClasses.AlignSpacing = MenuCssClasses.Prefix + "alignSpacing";
MenuCssClasses.Gutter = MenuCssClasses.Prefix + "gutter";
MenuCssClasses.WithoutImages = MenuCssClasses.Prefix + "noImages";
MenuCssClasses.Item = MenuCssClasses.Prefix + "item";
MenuCssClasses.ItemHovered = MenuCssClasses.Prefix + "hovered";
MenuCssClasses.ItemSelected = MenuCssClasses.Prefix + "selected";
MenuCssClasses.ItemChecked = MenuCssClasses.Prefix + "checked";
MenuCssClasses.ItemWithoutImage = MenuCssClasses.Prefix + "noImage";
MenuCssClasses.ItemWithSubMenu = MenuCssClasses.Prefix + "subMenu";
MenuCssClasses.ItemDropDownMode = MenuCssClasses.Prefix + "dropDownMode";
MenuCssClasses.ItemWithoutSubMenu = MenuCssClasses.Prefix + "noSubMenu"; 
MenuCssClasses.AdaptiveMenuItem = MenuCssClasses.Prefix + "ami";
MenuCssClasses.AdaptiveFakeMenuItem = MenuCssClasses.Prefix + "fami";
MenuCssClasses.AdaptiveMenuItemSpacing = MenuCssClasses.Prefix + "amis";
MenuCssClasses.AdaptiveMenu = MenuCssClasses.Prefix + "am";
MenuCssClasses.AdaptiveMenuHiddenElement = MenuCssClasses.Prefix + "amhe";
MenuCssClasses.ContentContainer = MenuCssClasses.Prefix + "content";
MenuCssClasses.ContentContainerWithVerticalAlignment = MenuCssClasses.Prefix + "valign";
MenuCssClasses.Image = MenuCssClasses.Prefix + "image";
MenuCssClasses.PopOutContainer = MenuCssClasses.Prefix + "popOut";
MenuCssClasses.PopOutImage = MenuCssClasses.Prefix + "pImage";
MenuCssClasses.ImageLeft = MenuCssClasses.Prefix + "image-l";
MenuCssClasses.ImageRight = MenuCssClasses.Prefix + "image-r";
MenuCssClasses.ImageTop = MenuCssClasses.Prefix + "image-t";
MenuCssClasses.ImageBottom = MenuCssClasses.Prefix + "image-b";
MenuCssClasses.ScrollArea = MenuCssClasses.Prefix + "scrollArea";
MenuCssClasses.ScrollUpButton = MenuCssClasses.Prefix + "scrollUpBtn";
MenuCssClasses.ScrollDownButton = MenuCssClasses.Prefix + "scrollDownBtn";
MenuCssClasses.ItemClearElement = MenuCssClasses.DX + "-clear";
MenuCssClasses.ItemTextElement = MenuCssClasses.Prefix + "contentText";
MenuCssClasses.SmallImage = MenuCssClasses.DX + "-small-image";
var MenuRenderHelper = ASPx.CreateClass(null, {
 constructor: function(menu) {
  this.menu = menu;
  this.itemLinkMode = "ContentBounds";
  this.elementsToHide = [];
 },
 InlineInitializeElements: function() {
  if(!this.menu.isPopupMenu)
   this.InlineInitializeMainMenuElements(this.menu.GetMainElement());
  else
   this.InlineInitializePopupMenuElements(this.menu.GetMainElement());
  var popupMenuElements = this.GetPopupMenuElements(this.menu.GetMainElement());
  for(var i = 0; i < popupMenuElements.length; i++) {
   if(popupMenuElements[i] == this.menu.GetMainElement()) continue;
   this.InlineInitializePopupMenuElements(popupMenuElements[i]);
  }
 },
 InlineInitializeSubMenuElements: function(parentItemIndexPath) {
  var popupMenuElements = this.GetPopupMenuElements(this.menu.GetMainElement());
  for(var i = 0; i < popupMenuElements.length; i++) {
   if(popupMenuElements[i].id.indexOf(Constants.MMIdSuffix + parentItemIndexPath + "_") > 0)
    this.InlineInitializePopupMenuElements(popupMenuElements[i]);
  }
 },
 InlineInitializeScrollElements: function(indexPath, menuElement) {
  var scrollArea = ASPx.GetNodeByClassName(menuElement, MenuCssClasses.ScrollArea);
  if(scrollArea) scrollArea.id = this.menu.GetScrollAreaId(indexPath);
  this.InitializeScrollButton(menuElement, MenuCssClasses.ScrollUpButton, this.menu.GetScrollUpButtonId(indexPath));
  this.InitializeScrollButton(menuElement, MenuCssClasses.ScrollDownButton, this.menu.GetScrollDownButtonId(indexPath));
 },
 InitializeScrollButton: function(menuElement, buttonClassName, id) {
  var scrollButton = ASPx.GetNodeByClassName(menuElement, buttonClassName);
  if(!scrollButton) return;
  scrollButton.id = id;
  if(this.menu.NeedCreateItemsOnClientSide()) {
   ASPx.GetStateController().AddHoverItem(id, ["dxm-scrollBtnHovered"], [""]);
   ASPx.GetStateController().AddPressedItem(id, ["dxm-scrollBtnPressed"], [""]);
  }
 },
 InlineInitializeMainMenuElements: function(menuElement) {
  this.menu.CheckElementsCache(menuElement);
  var contentElement = this.GetContentElement(menuElement);
  if(contentElement.className.indexOf("dxm-ti") > 1)
   this.itemLinkMode = "TextAndImage";
  else if(contentElement.className.indexOf("dxm-t") > -1)
   this.itemLinkMode = "TextOnly";
  var itemElements = this.GetItemElements(menuElement);
  for(var i = 0; i < itemElements.length; i++)
   this.InlineInitializeItemElement(itemElements[i], "", i);
  this.InlineInitializeScrollElements("", menuElement);
 },
 InlineInitializePopupMenuElements: function(parentElement) {
  parentElement.style.position = "absolute";
  var indexPath = this.GetSubMenuIndexPathByMenuParentElement(parentElement);
  var borderCorrectorElement = ASPx.GetNodeByClassName(parentElement, MenuCssClasses.BorderCorrector);
  if(borderCorrectorElement != null) {
   borderCorrectorElement.id = this.menu.GetMenuBorderCorrectorElementId(indexPath);
   borderCorrectorElement.style.position = "absolute";
   parentElement.removeChild(borderCorrectorElement);
   parentElement.parentNode.appendChild(borderCorrectorElement);
  }
  this.InlineInitializePopupMenuMenuElement(parentElement, indexPath);
 },
 GetSubMenuIndexPathByMenuParentElement: function(element){
  return this.menu.GetMenuIndexPathById(element.id);
 },
 InlineInitializePopupMenuMenuElement: function(parentElement, indexPath) {
  var menuElement = ASPx.GetNodeByClassName(parentElement, MenuCssClasses.PopupMenu);
  menuElement.id = this.menu.GetMenuMainElementId(indexPath);
  this.InlineInitializePopupMenuContentElements(parentElement, menuElement, indexPath);
 },
 InlineInitializePopupMenuContentElements: function(parentElement, menuElement, indexPath) {
  this.menu.CheckElementsCache(menuElement);
  var contentElement = this.GetContentElement(menuElement);
  if(contentElement != null) {
   var itemElements = this.GetItemElements(menuElement);
   var parentIndexPath = parentElement == this.menu.GetMainElement() ? "" : indexPath;
   for(var i = 0; i < itemElements.length; i++) {
    var itemElementId = itemElements[i].id;
    if(itemElementId && aspxGetMenuCollection().GetMenu(itemElementId) != this.menu)
     continue;
    this.InlineInitializeItemElement(itemElements[i], parentIndexPath, i);
   }
  }
  this.InlineInitializeScrollElements(indexPath, menuElement);
 },
 HasSubMenuTemplate: function(menuElement) {
  var contentElement = this.GetContentElement(menuElement);
  return contentElement && (contentElement.tagName != "UL" || !ASPx.GetNodesByPartialClassName(contentElement, MenuCssClasses.ContentContainer).length);
 },
 InlineInitializeItemElement: function(itemElement, parentIndexPath, visibleIndex) {
  function getItemIndex(visibleIndex) {
   var itemData = parentItemData[Math.max(visibleIndex, 0)];
   return itemData.constructor == Array
    ? itemData[0]
    : itemData;
  }
  var parentItemData = this.menu.renderData[parentIndexPath],
   prepareItemOnClick = parentItemData[visibleIndex].constructor == Array,
   indexPathPrefix = parentIndexPath + (parentIndexPath != "" ? ASPx.ItemIndexSeparator : ""),
   indexPath = indexPathPrefix + getItemIndex(visibleIndex);
  itemElement.id = this.menu.GetItemElementId(indexPath);
  if(this.canAssignAccessibilityEventsToChildrenLinks())
   ASPx.AssignAccessibilityEventsToChildrenLinks(itemElement, true);
  if(this.canContainSeparators()) {
   var separatorElement = itemElement.previousSibling;
   if(separatorElement && separatorElement.className) {
    if(ASPx.ElementContainsCssClass(separatorElement, MenuCssClasses.Spacing))
     separatorElement.id = this.menu.GetItemIndentElementId(indexPath);
    else if(ASPx.ElementContainsCssClass(separatorElement, MenuCssClasses.Separator))
     separatorElement.id = this.menu.GetItemSeparatorElementId(indexPath);
   }
  }
  var contentElement = this.GetItemContentElement(itemElement);
  if(contentElement != null) {
   contentElement.id = this.menu.GetItemContentElementId(indexPath);
   if (this.canContainImageElement()) {
    var imageElement = ASPx.GetNodeByClassName(contentElement, MenuCssClasses.Image);
    if(imageElement == null) {
     var hyperLinkElement = ASPx.GetNodeByClassName(contentElement, MenuCssClasses.DX);
     if(hyperLinkElement != null)
      imageElement = ASPx.GetNodeByClassName(hyperLinkElement, MenuCssClasses.Image);
    }
    if(imageElement != null)
     imageElement.id = this.menu.GetItemImageId(indexPath);
   }
  }
  else
   prepareItemOnClick = false;
  this.InlineInitializeItemPopOutElement(itemElement, indexPath);
  if(prepareItemOnClick)
   this.InlineInitializeItemOnClick(itemElement, indexPath);
  if(ASPx.ElementContainsCssClass(itemElement, MenuCssClasses.ItemSelected)) 
   this.menu.serverSideSelectedItemPath = indexPath;
 },
 canAssignAccessibilityEventsToChildrenLinks: function () { return true; },
 canContainSeparators: function () { return true; },
 canContainImageElement: function () { return true; },
 InlineInitializeItemPopOutElement: function(itemElement, indexPath) {
  var popOutElement = this.GetItemPopOutElement(itemElement);
  if(popOutElement != null) {
   popOutElement.id = this.menu.GetItemPopOutElementId(indexPath);
   var popOutImageElement = ASPx.GetNodeByClassName(popOutElement, MenuCssClasses.PopOutImage);
   if(popOutImageElement != null)
    popOutImageElement.id = this.menu.GetItemPopOutImageId(indexPath);
  }
 },
 InlineInitializeItemOnClick: function(itemElement, indexPath) {
  var name = this.menu.name;
  var onclick = this.GetItemOnClick(name, itemElement, indexPath);
  if(this.menu.IsDropDownItem(indexPath)) {
   var contentElement = this.menu.GetItemContentElement(indexPath);
   var dropDownElement = this.menu.GetItemPopOutElement(indexPath);
   var dropDownOnclick = this.GetItemDropdownOnClick(name, itemElement, indexPath);
   this.AssignItemOnClickToElement(contentElement, this.itemLinkMode, onclick);
   this.AssignItemOnClickToElement(dropDownElement, this.itemLinkMode, dropDownOnclick);
  }
  else
   this.AssignItemOnClickToElement(itemElement, this.itemLinkMode, onclick);
 },
 AssignItemOnClickToElement: function(element, itemLinkMode, method) {
  switch(itemLinkMode){
   case "ContentBounds":
    this.AssignItemOnClickToElementCore(element, method);
    break;
   case "TextOnly":
    var textElement = ASPx.GetNodeByTagName(element, "A");
    if(!textElement)
     textElement = ASPx.GetNodeByTagName(element, "SPAN");
    if(textElement)
     this.AssignItemOnClickToElementCore(textElement, method);
    break;
   case "TextAndImage":
    var linkElement = ASPx.GetNodeByTagName(element, "A");
    if(linkElement)
     this.AssignItemOnClickToElementCore(linkElement, method);
    else{
     var textElement = ASPx.GetNodeByTagName(element, "SPAN");
     if(textElement)
      this.AssignItemOnClickToElementCore(textElement, method);
     var imageElement = ASPx.GetNodeByTagName(element, "IMG");
     if(imageElement)
      this.AssignItemOnClickToElementCore(imageElement, method);
    }
    break;
  }
 },
 AssignItemOnClickToElementCore: function(element, method) {
  ASPx.Evt.AttachEventToElement(element, "click", method);
 },
 GetItemOnClick: function(name, itemElement, indexPath) { 
  var menu = this.menu;
  var sendPostBackHandler = function() {
   menu.SendPostBack("CLICK:" + indexPath);
  };
  var itemClickHandler = function(e) {
   ASPx.MIClick(e, name, indexPath);
  };
  var itemLink = this.GetItemLinkElement(itemElement);
  var handler = menu.autoPostBack && !menu.IsClientSideEventsAssigned() && (!itemLink || itemLink.href === "")
   ? sendPostBackHandler
   : itemClickHandler;
  return function(e) {
   if(!itemElement.clientDisabled)
    handler(e);
  };
 },
 GetItemDropdownOnClick: function(name, itemElement, indexPath) {
  return function(e) {
   if(!itemElement.clientDisabled)
    ASPx.MIDDClick(e, name, indexPath);
  };
 },
 ChangeItemEnabledAttributes: function(itemElement, enabled, accessibilityCompliant) {
  if(!itemElement) return;
  itemElement.clientDisabled = !enabled;
  ASPx.Attr.ChangeStyleAttributesMethod(enabled)(itemElement, "cursor");
  var hyperLink = this.GetItemLinkElement(itemElement);
  if(hyperLink)
   this.ChangeItemLinkEnabledAttributes(hyperLink, itemElement, enabled, accessibilityCompliant);
 },
 ChangeItemLinkEnabledAttributes: function(hyperLink, itemElement, enabled, accessibilityCompliant) {
  if(accessibilityCompliant) {
   var action = enabled ? ASPx.Attr.RemoveAttribute : ASPx.Attr.SetAttribute;
   action(hyperLink, "aria-disabled", "true");
  }
  ASPx.Attr.ChangeAttributesMethod(enabled)(hyperLink, "href");
  if(accessibilityCompliant && !enabled && itemElement.enabled)
   hyperLink.href = ASPx.AccessibilityEmptyUrl;
 },
 GetPopupMenuElements: function(menuElement) {
  return ASPx.GetChildNodesByTagName(menuElement.parentNode, "DIV");
 },
 GetContentElement: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "contentElement", 
   function() {
    var contentElement = ASPx.GetNodeByTagName(menuElement, "DIV", 0);
    if(contentElement && contentElement.className == MenuCssClasses.DX && contentElement.parentNode == menuElement) 
     return contentElement;
    contentElement = ASPx.GetNodeByTagName(menuElement, "UL", 0);
    if(contentElement)
     return contentElement;
    return ASPx.GetNodeByTagName(menuElement, "TABLE", 0); 
   }, menuElement);
 },
 GetItemElements: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElements(this, "itemElements", 
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodesByClassName(contentElement, MenuCssClasses.Item) : null;
   }, menuElement);
 },
 GetSpacingElements: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElements(this, "spacingElements", 
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodesByClassName(contentElement, MenuCssClasses.Spacing) : null;
   }, menuElement);
 },
 GetAlignSpacingElements: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElements(this, "alignSpacingElements",
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodesByClassName(contentElement, MenuCssClasses.AlignSpacing) : null;
   }, menuElement);
 },
 GetSeparatorElements: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElements(this, "separatorElements", 
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodesByClassName(contentElement, MenuCssClasses.Separator) : null;
   }, menuElement);
 },
 GetItemContentElement: function(itemElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "contentElement", 
   function() {
    return ASPx.GetNodeByClassName(itemElement, MenuCssClasses.ContentContainer);
   }, itemElement);
 },
 GetItemPopOutElement: function(itemElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "popOutElement", 
   function() {
    return ASPx.GetNodeByClassName(itemElement, MenuCssClasses.PopOutContainer);
   }, itemElement);
 },
 GetAdaptiveMenuItemElement: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "adaptiveMenuItemElement", 
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodeByClassName(contentElement, this.menu.getAdaptiveMenuItemCssClass()) : null;
   }, menuElement);
 },
 GetAdaptiveMenuItemSpacingElement: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "adaptiveMenuItemSpacingElement", 
   function() {
    var contentElement = this.GetContentElement(menuElement);
    return contentElement ? ASPx.GetNodeByClassName(contentElement, this.menu.getAdaptiveMenuItemSpacingCssClass()) : null;
   }, menuElement);
 },
 GetAdaptiveMenuElement: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "adaptiveMenuElement", 
   function() {
    var adaptiveItemElement = this.GetAdaptiveMenuItemElement(menuElement);
    if(adaptiveItemElement){
     var adaptiveItemIndexPath = this.menu.GetIndexPathById(adaptiveItemElement.id);
     var adaptiveMenuParentElement = this.menu.GetMenuElement(adaptiveItemIndexPath);
     if(adaptiveMenuParentElement) 
      return this.menu.GetMenuMainElement(adaptiveMenuParentElement);
    }
    return null;
   }, menuElement);
 },
 GetAdaptiveMenuContentElement: function(menuElement) {
  return ASPx.CacheHelper.GetCachedElement(this, "adaptiveMenuContentElement", 
   function() {
    var adaptiveMenuElement = this.GetAdaptiveMenuElement(menuElement);
    return adaptiveMenuElement ? this.GetContentElement(adaptiveMenuElement) : null;
   }, menuElement);
 },
 GetItemLinkElement: function(itemElement) {
  return ASPx.GetNodeByTagName(itemElement, "A", 0);
 },
 CalculateMenuControl: function(menuElement, recalculate) {
  if(menuElement.offsetWidth === 0) return;
  this.PrecalculateMenuPopOuts(menuElement);
  var isVertical = this.menu.IsVertical("");
  var isAutoWidth = ASPx.ElementContainsCssClass(menuElement, MenuCssClasses.AutoWidthMenu);
  var isNoWrap = ASPx.ElementContainsCssClass(menuElement, MenuCssClasses.NoWrapMenu);
  var contentElement = this.GetContentElement(menuElement);
  if(this.menu.enableAdaptivity) 
   this.CalculateAdaptiveMainMenu(menuElement, contentElement, isVertical, isAutoWidth, isNoWrap, recalculate);
  else
   this.CalculateMainMenu(menuElement, contentElement, isVertical, isAutoWidth, isNoWrap, recalculate);
 },
 CalculateMainMenu: function(menuElement, contentElement, isVertical, isAutoWidth, isNoWrap, recalculate) {
  var itemElements = this.GetItemElements(menuElement);
  this.PrecalculateMenuItems(menuElement, itemElements, recalculate);
  this.CalculateMenuItemsAutoWidth(menuElement, itemElements, isVertical, isAutoWidth);
  this.CalculateMinSize(menuElement, contentElement, itemElements, isVertical, isAutoWidth, isNoWrap, recalculate);
  this.CalculateMenuItems(menuElement, contentElement, itemElements, isVertical, recalculate);
  this.CalculateSeparatorsAndSpacers(menuElement, itemElements, contentElement, isVertical);
 },
 PrecalculateMenuPopOuts: function(menuElement) {
  if(menuElement.popOutsPreCalculated) return;
  var elements = this.GetItemElements(menuElement);
  for(var i = 0; i < elements.length; i++) {
   var popOutElement = this.GetItemPopOutElement(elements[i]);
   if (popOutElement)
    popOutElement.style.display = "block";
  }
  menuElement.popOutsPreCalculated = true;
 },
 PrecalculateMenuItems: function(menuElement, itemElements, recalculate) {
  if(!recalculate) return;
  for(var i = 0; i < itemElements.length; i++) {
   var itemContentElement = this.GetItemContentElement(itemElements[i]);
   if(!itemContentElement || itemContentElement.offsetWidth === 0) continue;
   ASPx.SetElementFloat(itemContentElement, "");
   ASPx.Attr.RestoreStyleAttribute(itemContentElement, "padding-left");
   ASPx.Attr.RestoreStyleAttribute(itemContentElement, "padding-right");
     this.ReCalculateMenuItemContent(itemElements[i], itemContentElement);
  }
 },
 ReCalculateMenuItemContent: function(itemElement, itemContentElement) {
  for(var j = 0; j < itemElement.childNodes.length; j++) {
   var child = itemElement.childNodes[j];
   if(!child.offsetWidth) continue;
   if(child !== itemContentElement) {
    ASPx.Attr.RestoreStyleAttribute(child, "margin-top");
    ASPx.Attr.RestoreStyleAttribute(child, "margin-bottom");
   }
  }
 },
 CalculateMenuItemsAutoWidth: function(menuElement, itemElements, isVertical, isAutoWidth) {
  if(!isAutoWidth) return;
  for(var i = 0; i < itemElements.length; i++) 
   ASPx.Attr.RestoreStyleAttribute(itemElements[i], "width");
  if(!isVertical) {
   var autoWidthItemCount = 0;
   var adaptiveItemCssClass = this.menu.getAdaptiveMenuItemCssClass();
   for(var i = 0; i < itemElements.length; i++) {
    if(ASPx.GetElementDisplay(itemElements[i]) && !ASPx.ElementHasCssClass(itemElements[i], adaptiveItemCssClass))
     autoWidthItemCount++;
   }
   for(var i = 0; i < itemElements.length; i++) {
    if(autoWidthItemCount > 0 && !ASPx.ElementHasCssClass(itemElements[i], adaptiveItemCssClass) && (itemElements[i].style.width === "" || itemElements[i].autoWidth)) {
     ASPx.Attr.ChangeStyleAttribute(itemElements[i], "width", (100 / autoWidthItemCount) + "%");
     itemElements[i].autoWidth = true;
    }
   }
  }
 },
 CalculateMenuItems: function(menuElement, contentElement, itemElements, isVertical, recalculate) {
  if(contentElement.itemsCalculated && recalculate)
   contentElement.itemsCalculated = false;
  if(menuElement.offsetWidth === 0) return;
  if(contentElement.style.margin === "0px auto")
   ASPx.SetStyles(contentElement, { float: "none" }); 
  var menuWidth = ASPx.GetCurrentStyle(menuElement).width;
  var menuRequireItemCorrection = isVertical && menuWidth;
  this.ApplyItemsVerticalAlignment(menuElement, itemElements);
  for(var i = 0; i < itemElements.length; i++) {
   if(!itemElements[i].style.width && !menuRequireItemCorrection) continue;
   if(ASPx.IsPercentageSize(itemElements[i].style.width) && contentElement.style.width === "")
    contentElement.style.width = "100%"; 
   var itemContentElement = this.GetItemContentElement(itemElements[i]);
   if(!itemContentElement || itemContentElement.offsetWidth === 0) continue;
   if(!contentElement.itemsCalculated) {
    ASPx.Attr.RestoreStyleAttribute(itemContentElement, "padding-left");
    ASPx.Attr.RestoreStyleAttribute(itemContentElement, "padding-right");
    ASPx.SetElementFloat(itemContentElement, "none");
    var itemContentCurrentStyle = ASPx.GetCurrentStyle(itemContentElement);
    if(!isVertical || (itemContentCurrentStyle.textAlign != "center" && menuWidth)) {
     var originalPaddingLeft = parseInt(itemContentCurrentStyle.paddingLeft);
     var originalPaddingRight = parseInt(itemContentCurrentStyle.paddingRight);
     var leftChildrenWidth = 0, rightChildrenWidth = 0;
     for(var j = 0; j < itemElements[i].childNodes.length; j++) {
      var child = itemElements[i].childNodes[j];
      if(!child.offsetWidth) continue;
      if(child !== itemContentElement) {
       if(ASPx.GetElementFloat(child) === "right")
        rightChildrenWidth += child.offsetWidth + ASPx.GetLeftRightMargins(child);
       else if(ASPx.GetElementFloat(child) === "left")
        leftChildrenWidth += child.offsetWidth + ASPx.GetLeftRightMargins(child);
      }
     }
     if(leftChildrenWidth > 0 || rightChildrenWidth > 0){
      ASPx.Attr.ChangeStyleAttribute(itemContentElement, "padding-left", (leftChildrenWidth + originalPaddingLeft) + "px");
      ASPx.Attr.ChangeStyleAttribute(itemContentElement, "padding-right", (rightChildrenWidth + originalPaddingRight) + "px");
     }
    }
   }
   ASPx.AdjustWrappedTextInContainer(itemContentElement);
   this.CalculateMenuItemContent(itemElements[i], itemContentElement);
  }
  contentElement.itemsCalculated = true;
 },
 ApplyItemsVerticalAlignment: function(menuElement, itemElements) {
  var menuAlignmentInProgressClassName = "miva";
  ASPx.AddClassNameToElement(menuElement, menuAlignmentInProgressClassName);
  if(!ASPx.IsExists(itemElements))
   itemElements = this.GetItemElements(menuElement);
  for(var i = 0; i < itemElements.length; i++) {
   var itemContentElement = this.GetItemContentElement(itemElements[i]);
   if(itemContentElement && itemContentElement.offsetWidth !== 0 && itemContentElement.style.verticalAlign) {
    this.CalculateItemContentLineHeight(itemElements[i], itemContentElement);
    ASPx.RemoveClassNameFromElement(itemContentElement, MenuCssClasses.ContentContainerWithVerticalAlignment);
   }
  }
  ASPx.RemoveClassNameFromElement(menuElement, menuAlignmentInProgressClassName);
 },
 CalculateItemContentLineHeight: function(itemElement, itemContentElement) {
  var lineHeight = 0;
  var maxHeight = itemElement.getBoundingClientRect().height - this.GetBordersAndPaddingSummaryHeight(itemElement);
  if(itemContentElement && itemContentElement.offsetHeight != maxHeight)
   lineHeight = maxHeight - this.GetBordersAndPaddingSummaryHeight(itemContentElement);
  if(lineHeight > 0) {
   var link = this.GetItemLinkElement(itemElement);
   if(link)
    ASPx.SetStyles(link, { lineHeight: lineHeight }, false);
   else
    ASPx.SetStyles(itemContentElement, { lineHeight: lineHeight }, false);
  }
 },
 GetBordersAndPaddingSummaryHeight: function(element) {
  var elementStyle = getComputedStyle(element);
  return ASPx.GetVerticalBordersWidth(element, elementStyle) + ASPx.PxToFloat(elementStyle.paddingTop) + ASPx.PxToFloat(elementStyle.paddingBottom);
 },
 CalculateMenuItemContent: function(itemElement, itemContentElement) {
  var itemContentFound = false;
  for(var j = 0; j < itemElement.childNodes.length; j++) {
   var child = itemElement.childNodes[j];
   if(!child.offsetWidth) continue;
   var contentHeight = itemContentElement.offsetHeight;
   if(child !== itemContentElement) {
    if(itemContentFound)
     ASPx.Attr.ChangeStyleAttribute(child, "margin-top", "-" + contentHeight + "px");
    else
     ASPx.Attr.ChangeStyleAttribute(child, "margin-bottom", "-" + contentHeight + "px");
   }
   else
    itemContentFound = true;
  }
 },
 CalculateSubMenu: function(parentElement, recalculate) {
  var menuElement = this.menu.GetMenuMainElement(parentElement);
  var contentElement = this.GetContentElement(menuElement);
  if(!parentElement.isSubMenuCalculated || recalculate) {
   menuElement.style.width = "";
   menuElement.style.display = "table";
   menuElement.style.borderSpacing = "0px";
   parentElement.isSubMenuCalculated = true;
   if(contentElement.tagName === "UL") {
    if(contentElement.offsetWidth > 0) {
     menuElement.style.width = contentElement.offsetWidth + "px";
     menuElement.style.display = "";
     if(ASPx.IsPercentageSize(contentElement.style.width))
      contentElement.style.width = menuElement.style.width;
    }
    else
     parentElement.isSubMenuCalculated = false;
   }
  }
  this.CalculateSubMenuItems(menuElement, contentElement, recalculate);
 },
 CalculateSubMenuItems: function(menuElement, contentElement, recalculate) {
  var itemElements = this.GetItemElements(menuElement);
  this.PrecalculateMenuItems(menuElement, itemElements, recalculate);
  this.CalculateMenuItems(menuElement, contentElement, itemElements, true, recalculate);
 },
 ResetMinSize: function() {
  var menuElement = this.menu.GetMainElement();
  if(!menuElement.isMinSizeCalculated || this.menu.isVertical) return;
  var itemElements = this.GetItemElements(menuElement);
  var contentElement = this.GetContentElement(menuElement);
  if(!!contentElement.adaptiveInfo)
   itemElements = itemElements.concat(contentElement.adaptiveInfo.elements);
  for(var i = 0; i < itemElements.length; i++)
   this.ResetItemMinSize(itemElements[i]);
  menuElement.isMinSizeCalculated = false;
 },
 ResetItemMinSize: function(itemElement) {
  itemElement.style.minWidth = "";
  itemElement.isMinSizeCalculated = false;
 },
 CalculateMinSize: function(menuElement, contentElement, itemElements, isVertical, isAutoWidth, isNoWrap, recalculate) {
  if(menuElement.isMinSizeCalculated && !recalculate) return;
  if(isVertical) {
   menuElement.style.minWidth = "";
   if(!this.menu.IsSidePanelExpanded()) {
    ASPx.Attr.ChangeStyleAttribute(contentElement, "width", "1px");
    for(var i = 0; i < itemElements.length; i++) {
     var itemContentElement = this.GetItemContentElement(itemElements[i]);
     if(!itemContentElement || itemElements[i].offsetWidth === 0) continue;
     this.CalculateItemMinSize(itemElements[i], recalculate);
    }
    ASPx.Attr.RestoreStyleAttribute(contentElement, "width");
   }
  }
  else {
   ASPx.RemoveClassNameFromElement(menuElement, MenuCssClasses.NoWrapMenu);
   ASPx.RemoveClassNameFromElement(menuElement, MenuCssClasses.AutoWidthMenu);
   if(isAutoWidth || isNoWrap)
    menuElement.style.minWidth = "";
   ASPx.Attr.ChangeStyleAttribute(menuElement, "width", "1px");
   for(var i = 0; i < itemElements.length; i++) {
    var itemContentElement = this.GetItemContentElement(itemElements[i]);
    if((!itemContentElement || itemElements[i].offsetWidth === 0) && !ASPx.ElementHasCssClass(itemElements[i], MenuCssClasses.ItemTemplate)) continue;
    var textContainer = ASPx.GetNodeByTagName(itemContentElement, "SPAN", 0);
    if(textContainer && ASPx.GetCurrentStyle(textContainer).whiteSpace !== "nowrap")
     ASPx.AdjustWrappedTextInContainer(itemContentElement);
    this.CalculateItemMinSize(itemElements[i], recalculate);
   }
   if(isAutoWidth)
    ASPx.AddClassNameToElement(menuElement, MenuCssClasses.AutoWidthMenu);
   if(isNoWrap)
    ASPx.AddClassNameToElement(menuElement, MenuCssClasses.NoWrapMenu);
   if(isAutoWidth || isNoWrap)
    menuElement.style.minWidth = (contentElement.offsetWidth + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(menuElement)) + "px";
   ASPx.Attr.RestoreStyleAttribute(menuElement, "width");
  }
  menuElement.isMinSizeCalculated = true;
 },
 CalculateItemMinSize: function(itemElement, recalculate) {
  if(itemElement.isMinSizeCalculated && !recalculate) return;
  itemElement.style.minWidth = "";
  var childrenWidth = 0;
  if(ASPx.ElementHasCssClass(itemElement, MenuCssClasses.ItemTemplate)) {
   ASPx.Attr.ChangeStyleAttribute(itemElement, "display", "table");
   childrenWidth += itemElement.getBoundingClientRect().width;
   ASPx.Attr.RestoreStyleAttribute(itemElement, "display");
   if(ASPx.Browser.Edge && ASPx.Browser.MajorVersion >= 16)
    var dummy = itemElement.clientWidth;
  } 
  else {
   for(var j = 0; j < itemElement.childNodes.length; j++) {
    var child = itemElement.childNodes[j];
    if(!child.offsetWidth) continue;
    var float = ASPx.GetElementFloat(child);
    if(float === "none") {
     childrenWidth = child.getBoundingClientRect().width;
     break;
    }
    else
     childrenWidth += child.getBoundingClientRect().width;
   }
  }
  itemElement.style.minWidth = Math.ceil(childrenWidth) + "px";
  itemElement.isMinSizeCalculated = true;
 },
 CalculateSeparatorsAndSpacers: function(menuElement, itemElements, contentElement, isVertical, isAutoWidth, isNoWrap) {
  var spacerElements = this.GetSpacingElements(menuElement);
  var spacerAndSeparatorElements = spacerElements.concat(this.GetSeparatorElements(menuElement));
  for(var i = 0; i < spacerAndSeparatorElements.length; i++) {
   ASPx.Attr.RestoreStyleAttribute(spacerAndSeparatorElements[i], "height");
   if(ASPx.Browser.Edge) {
    var savedDisplay = spacerAndSeparatorElements[i].style.display;
    spacerAndSeparatorElements[i].style.display = "none";
    var temp = spacerAndSeparatorElements[i].offsetHeight; 
    spacerAndSeparatorElements[i].style.display = savedDisplay;
   }
  }
  if(!isVertical && itemElements) {
   var menuHeight = 0;
   if(!isAutoWidth && !isNoWrap) {
    for(var i=0; i < itemElements.length; i++) {
     var newHeight = itemElements[i].getBoundingClientRect().height;
     if(newHeight > menuHeight)
      menuHeight = newHeight;
    }
   }
   for(var i = 0; i < spacerAndSeparatorElements.length; i++){
    var separatorHeight = menuHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(spacerAndSeparatorElements[i]) - ASPx.GetTopBottomMargins(spacerAndSeparatorElements[i]);
    ASPx.Attr.ChangeStyleAttribute(spacerAndSeparatorElements[i], "height", separatorHeight + "px");
   }
   for(var i = 0; i < spacerElements.length; i++){
    if(!ASPx.ElementContainsCssClass(spacerElements[i], this.menu.getAdaptiveMenuItemSpacingCssClass()))
     spacerElements[i].style.minWidth = spacerElements[i].style.width; 
   }
   this.calculateAlignSpacings(menuElement, contentElement);
  }
 },
 calculateAlignSpacings: function(menuElement, contentElement) {
  var separatorElements = this.GetAlignSpacingElements(menuElement),
   separatorsCount = separatorElements.length;
  if(separatorsCount === 0) return;
  ASPx.Data.ForEach(separatorElements, function(separator) {
   separator.style.width = "0";
  });
  var unit = this.menu.enableAdaptivity ? "%" : "px";
  var width = this.menu.enableAdaptivity ? 100 / separatorsCount :
   (ASPx.GetClearClientWidth(menuElement) - contentElement.offsetWidth) / separatorsCount;
  ASPx.Data.ForEach(separatorElements, function(separator) {
   separator.style.width = width + unit;
  });
  if(!this.menu.enableAdaptivity)
   separatorElements[0].style.width = (width - 1) + unit;
 },
 CalculateAdaptiveMainMenu: function(menuElement, contentElement, isVertical, isAutoWidth, isNoWrap, recalculate) {
  var adaptiveItemElement = this.GetAdaptiveMenuItemElement(menuElement);
  if(!adaptiveItemElement) return;
  var adaptiveItemSpacing = this.GetAdaptiveMenuItemSpacingElement(menuElement);
  if(adaptiveItemSpacing) adaptiveItemSpacing.style.width = "";
  var adaptiveMenuElement = this.GetAdaptiveMenuElement(menuElement);
  if(!adaptiveMenuElement) return;
  var adaptiveMenuContentElement = this.GetAdaptiveMenuContentElement(menuElement);
  var adaptiveFakeMenuItem = ASPx.GetNodeByClassName(adaptiveMenuContentElement, MenuCssClasses.AdaptiveFakeMenuItem);
  if(adaptiveFakeMenuItem) ASPx.RemoveElement(adaptiveFakeMenuItem);
  if(!contentElement.adaptiveInfo)
   this.InitAdaptiveInfo(contentElement);
  var wasAdaptivity = contentElement.adaptiveInfo.hasAdaptivity;
  if(wasAdaptivity) {
   var previousSibling = this.GetAdaptiveItemElementPreviousSibling(adaptiveItemSpacing || adaptiveItemElement);
   this.RestoreAdaptiveItems(previousSibling, contentElement, isVertical);
  }
  if(!isVertical) {
   ASPx.SetElementDisplay(adaptiveItemElement, true);
   if(adaptiveItemSpacing) ASPx.SetElementDisplay(adaptiveItemSpacing, true);
   ASPx.AddClassNameToElement(menuElement, MenuCssClasses.CalculateMenu);
   ASPx.RemoveClassNameFromElement(menuElement, MenuCssClasses.NoWrapMenu);
   menuElement.style.minWidth = "";
   var adaptiveItemWidth = adaptiveItemElement.offsetWidth;
   if(isAutoWidth) {
    ASPx.Attr.ChangeStyleAttribute(contentElement, "display", "none");
    ASPx.Attr.ChangeStyleAttribute(menuElement, "min-width", "");
   }
   var menuWidth = menuElement.offsetWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(menuElement) - adaptiveItemWidth;
   if(isAutoWidth) {
    ASPx.Attr.RestoreStyleAttribute(contentElement, "display");
    ASPx.Attr.RestoreStyleAttribute(menuElement, "min-width");
   }
   var additionalWidth = adaptiveItemWidth;
   if(adaptiveItemSpacing) {
    menuWidth -= adaptiveItemSpacing.offsetWidth;
    additionalWidth += adaptiveItemSpacing.offsetWidth;
   }
   var hasAdaptivity = this.HideAdaptiveItems(menuWidth, additionalWidth, contentElement, adaptiveMenuContentElement);
   contentElement.adaptiveInfo.hasAdaptivity = hasAdaptivity;
   this.SetAdaptiveItemElementVisibility(adaptiveItemElement, adaptiveItemSpacing, hasAdaptivity);
   contentElement.style.width = hasAdaptivity ? "100%" : "";
   if(hasAdaptivity){
    ASPx.CacheHelper.DropCache(adaptiveMenuElement);
    this.CalculateSubMenu(adaptiveMenuElement, true);
    this.CalculateSeparatorsAndSpacers(adaptiveMenuElement, null, adaptiveMenuContentElement, true);
   }
   if(isNoWrap) {
    ASPx.AddClassNameToElement(menuElement, MenuCssClasses.NoWrapMenu);
    if(adaptiveItemSpacing) adaptiveItemSpacing.style.width = hasAdaptivity ? "100%" : "";
   }
   ASPx.RemoveClassNameFromElement(menuElement, MenuCssClasses.CalculateMenu);
  }
  else {
   this.SetAdaptiveItemElementVisibility(adaptiveItemElement, adaptiveItemSpacing, false);
  }
  if(wasAdaptivity || contentElement.adaptiveInfo.hasAdaptivity)
   ASPx.CacheHelper.DropCache(menuElement);
  if(!ASPx.GetNodesByTagName(adaptiveMenuContentElement, "li").length)
   adaptiveMenuContentElement.innerHTML = "<li class='" + MenuCssClasses.AdaptiveFakeMenuItem + "' role='menuitem'></li>";
  this.CalculateMainMenu(menuElement, contentElement, isVertical, isAutoWidth, isNoWrap, wasAdaptivity || contentElement.adaptiveInfo.hasAdaptivity || recalculate);
 },
 InitAdaptiveInfo: function(contentElement) {
  if(contentElement.adaptiveInfo) return;
  contentElement.adaptiveInfo = { };
  contentElement.adaptiveInfo.elements = this.CreateAdaptiveElementsArray(contentElement);
  contentElement.adaptiveInfo.hasAdaptivity = false;
 },
 GetAdaptiveItemElementByIndex: function(adaptiveInfo, index) {
  return adaptiveInfo.elements[index];
 },
 GetAdaptiveItemElementParent: function(adaptiveInfo, index) {
  return undefined;
 },
 GetAdaptiveItemElementPreviousSibling: function(defaultPreviousSibling) {
  return defaultPreviousSibling;
 },
 RestoreAdaptiveItems: function(previousSibling, contentElement, isVertical) {
  this.SetLastSeparatorsVisible(true, contentElement);
  for(var i = 0; i < contentElement.adaptiveInfo.elements.length; i++) {
   var element = this.GetAdaptiveItemElementByIndex(contentElement.adaptiveInfo, i);
   var isReplacedIndent = !element.parent;
   if(isReplacedIndent)
    ASPx.RemoveElement(ASPx.GetElementById(element.id));
   var itemParentElement = this.GetAdaptiveItemElementParent(contentElement.adaptiveInfo, i) || contentElement;
   itemParentElement.insertBefore(element, previousSibling);
   ASPx.Attr.RestoreStyleAttribute(element, "width");
   if(!isVertical)
    this.SetItemItemPopOutImageHorizontal(element);
   if(ASPx.ElementContainsCssClass(element, MenuCssClasses.Separator) || ASPx.ElementContainsCssClass(element, MenuCssClasses.Spacing))
    ASPx.RemoveClassNameFromElement(element, MenuCssClasses.AdaptiveMenuHiddenElement);
  }
  if(this.menu.GetRootItem()) {
   for(var i = this.elementsToHide.length - 1; i >= 0; i--) {
    if(!this.elementsToHide[i]) continue;
    var indexPath = this.elementsToHide[i].indexPath;
    if(this.menu.GetItemByIndexPath(indexPath).GetVisible())
     this.menu.UpdateItemCssClasses(indexPath, true);
    this.elementsToHide[i] = null;
   }
  }
  this.elementsToHide = [];
 },
 SetLastSeparatorsVisible: function(isVisible, contentElement) {
  var elements = ASPx.GetChildElementNodes(contentElement);
  for(var i = 0; i < elements.length; i++) {
   var element = elements[i];
   if(ASPx.ElementContainsCssClass(element, MenuCssClasses.Separator) || ASPx.ElementContainsCssClass(element, MenuCssClasses.Spacing))
    ASPx.RemoveClassNameFromElement(element, MenuCssClasses.AdaptiveMenuHiddenElement);
   else
    break;
  }
 },
 CreateAdaptiveElementsArray: function(contentElement) {
  var result = [];
  var elements = ASPx.GetChildElementNodes(contentElement);
  for(var i = 0; i < elements.length; i++) {
   if(this.CheckElementIsAdaptive(elements[i]))
    result.push(elements[i]);
  }
  return result;
 },
 SetItemItemPopOutImageHorizontal: function(element) {
  var popOutElements = ASPx.GetNodesByPartialClassName(element, "dxWeb_mVerticalPopOut");
  for(var i = 0; i < popOutElements.length; i++)
   popOutElements[i].className = popOutElements[i].className.replace("Vertical", "Horizontal");
 },
 CheckElementIsAdaptive: function(element) {
  return !ASPx.ElementHasCssClass(element, this.menu.getAdaptiveMenuItemCssClass()) && !ASPx.ElementHasCssClass(element, this.menu.getAdaptiveMenuItemSpacingCssClass());
 },
 CheckAdaptiveItemsWidth: function(contentElement, menuWidth, additionalWidth) {
  var itemsWidth = 0;
  var elements = ASPx.GetChildElementNodes(contentElement);
  for(var i = 0; i < elements.length; i++) {
   var element = elements[i];
   if(this.CheckElementIsAdaptive(element) && element.offsetWidth > 0)
    itemsWidth += this.GetAdaptiveElementWidth(element);
   if(itemsWidth > menuWidth + additionalWidth)
    return false;
  }
  return true;
 },
 GetAdaptiveElementWidth: function(element) {
  return element.style.minWidth !== "" ? parseInt(element.style.minWidth) + ASPx.GetHorizontalBordersWidth(element) : element.offsetWidth;
 },
 HideAdaptiveItems: function(menuWidth, additionalWidth, contentElement, adaptiveMenuContentElement) {
  if(this.CheckAdaptiveItemsWidth(contentElement, menuWidth, additionalWidth))
   return false;
  this.elementsToHide = [];
  var elementsToHide = this.elementsToHide;
  var adaptiveItemSpacingCssClass = this.menu.getAdaptiveMenuItemSpacingCssClass();
  var addToHide = function(index, indexPath, itemElement, separatorElement, indentElement, insteadSeparatorElement) {
   if(!itemElement) return;
   if(separatorElement && ASPx.ElementHasCssClass(separatorElement, adaptiveItemSpacingCssClass))
    separatorElement = null;
   if(indentElement && ASPx.ElementHasCssClass(indentElement, adaptiveItemSpacingCssClass))
    indentElement = null;
   elementsToHide[index] = { indexPath: indexPath, itemElement: itemElement, separatorElement: separatorElement, indentElement: indentElement, insteadSeparatorElement: insteadSeparatorElement };
   ASPx.Attr.ChangeStyleAttribute(itemElement, "display", "none");
   if(separatorElement) {
    var elementForHide = insteadSeparatorElement || separatorElement;
    ASPx.Attr.ChangeStyleAttribute(elementForHide, "display", "none");
   }
   if(indentElement)
    ASPx.Attr.ChangeStyleAttribute(indentElement, "display", "none");
  };
  for(var i = 0; i < this.menu.adaptiveItemsOrder.length; i++){
   var indexPath = this.menu.adaptiveItemsOrder[i],
    index = parseInt(indexPath, 10),
    itemToKeepSeparator = this.menu.GetRootItem() ? this.GetItemForKeepSeparator(index) : null,
    insteadSeparatorElement = itemToKeepSeparator ? this.menu.GetItemIndentElement(itemToKeepSeparator.indexPath) : null;
   addToHide(index, indexPath, this.menu.GetItemElement(indexPath), this.menu.GetItemSeparatorElement(indexPath), this.menu.GetItemIndentElement(indexPath), insteadSeparatorElement);
   var actualAdditionalWidth = this.NeedShowAdaptiveItemForHiddenElements(elementsToHide) ? 0 : additionalWidth;
   if(this.CheckAdaptiveItemsWidth(contentElement, menuWidth, actualAdditionalWidth))
    break;
  }
  var hasImages = false;
  for(var i = 0; i < elementsToHide.length; i++) {
   if(!elementsToHide[i]) continue;
   ASPx.Attr.RestoreStyleAttribute(elementsToHide[i].itemElement, "display");
   if(elementsToHide[i].separatorElement) {
    var elementForRestore = elementsToHide[i].insteadSeparatorElement || elementsToHide[i].separatorElement;
    ASPx.Attr.RestoreStyleAttribute(elementForRestore, "display");
   }
   if(elementsToHide[i].indentElement)
    ASPx.Attr.RestoreStyleAttribute(elementsToHide[i].indentElement, "display");
   this.menu.UpdateItemCssClasses(elementsToHide[i].indexPath, false);
   if(elementsToHide[i].separatorElement) {
    if(this.menu.GetRootItem())
     this.KeepSeparatorInRoot(i);
    adaptiveMenuContentElement.appendChild(elementsToHide[i].separatorElement);
   }
   else if(this.menu.GetRootItem())
    this.InsertSeparatorInAdaptiveMenu(i, elementsToHide[i].indexPath);
   if(elementsToHide[i].indentElement)
    adaptiveMenuContentElement.appendChild(elementsToHide[i].indentElement);
   adaptiveMenuContentElement.appendChild(elementsToHide[i].itemElement);
   this.PrepareHiddenAdaptiveItemElement(elementsToHide[i].itemElement);
   if(ASPx.GetNodeByClassName(elementsToHide[i].itemElement, "dxm-image"))
    hasImages = true;
  }
  for(var i = 0; i < elementsToHide.length; i++) {
   if(!elementsToHide[i]) continue;
   if(elementsToHide[i].separatorElement) 
    ASPx.AddClassNameToElement(elementsToHide[i].separatorElement, MenuCssClasses.AdaptiveMenuHiddenElement);
   if(elementsToHide[i].indentElement) 
    ASPx.AddClassNameToElement(elementsToHide[i].indentElement, MenuCssClasses.AdaptiveMenuHiddenElement);
   break;
  }
  this.SetLastSeparatorsVisible(false, contentElement);
  this.PrepareAdaptiveMenuContentElement(adaptiveMenuContentElement, hasImages);
  return elementsToHide.length > 0;
 },
 PrepareHiddenAdaptiveItemElement: function(itemElement) {
  ASPx.Attr.ChangeStyleAttribute(itemElement, "width", "auto");
  this.SetItemPopOutImageVertical(itemElement);
 },
 PrepareAdaptiveMenuContentElement: function(contentElement, hasImages) {
  if(hasImages)
   ASPx.RemoveClassNameFromElement(contentElement, MenuCssClasses.WithoutImages);
  else
   ASPx.AddClassNameToElement(contentElement, MenuCssClasses.WithoutImages);
 },
 SetAdaptiveItemElementVisibility: function(adaptiveItemElement, adaptiveItemSpacing, visible) {
  ASPx.SetElementDisplay(adaptiveItemElement, visible);
  if(adaptiveItemSpacing)
   ASPx.SetElementDisplay(adaptiveItemSpacing, visible);
 },
 NeedShowAdaptiveItemForHiddenElements: function(elementsToHide) {
  return true;
 },
 KeepSeparatorInRoot: function(index) {
  var nextItemInGroup = this.GetItemForKeepSeparator(index);
  if(nextItemInGroup) {
   var separatorElement = this.elementsToHide[index].separatorElement;
   this.ReplaceIndentElement(nextItemInGroup.indexPath, separatorElement);
  }
 },
 InsertSeparatorInAdaptiveMenu: function(index, indexPath) {
  var itemWithSeparator = this.GetItemWithSeparatorForAdaptiveMenu(index);
  if(itemWithSeparator) {
   var separatorElement = this.menu.GetItemSeparatorElement(itemWithSeparator.indexPath);
   if(!separatorElement) return;
   this.elementsToHide[index].indentElement = this.ReplaceIndentElement(indexPath, separatorElement);
  }
 },
 ReplaceIndentElement: function(indexPath, separatorElement) {
  var itemElement = this.menu.GetItemElement(indexPath),
   itemIndent = this.menu.GetItemIndentElement(indexPath),
   newIndentElement = separatorElement.cloneNode(true),
   parentNode = itemElement.parentNode;
  newIndentElement.id = this.menu.GetItemIndentElementId(indexPath);
  if(itemIndent)
   itemIndent.parentNode.removeChild(itemIndent);
  parentNode.insertBefore(newIndentElement, itemElement);
  return newIndentElement;
 },
 GetItemForKeepSeparator: function(index) {
  var rootItem = this.menu.GetRootItem(),
   nextItemInGroup = this.menu.GetNextVisibleItemInGroup(rootItem, index, true);
  if(nextItemInGroup && this.IsItemInAdaptiveMenu(nextItemInGroup.index)) {
   while(nextItemInGroup && this.IsItemInAdaptiveMenu(nextItemInGroup.index))
    nextItemInGroup = this.menu.GetNextVisibleItemInGroup(rootItem, nextItemInGroup.index, true);
  }
  return nextItemInGroup;
 },
 GetItemWithSeparatorForAdaptiveMenu: function(index) {
  var rootItem = this.menu.GetRootItem(),
   prevItemInGroup = this.menu.GetPrevVisibleItemInGroup(rootItem, index);
  if(prevItemInGroup && !this.IsItemInAdaptiveMenu(prevItemInGroup.index) && !this.menu.IsItemBeginsGroup(prevItemInGroup)) {
   while(prevItemInGroup && !this.IsItemInAdaptiveMenu(prevItemInGroup.index) && !this.menu.IsItemBeginsGroup(prevItemInGroup))
    prevItemInGroup = this.menu.GetPrevVisibleItemInGroup(rootItem, prevItemInGroup.index);
  }
  return prevItemInGroup && !this.IsItemInAdaptiveMenu(prevItemInGroup.index) ? prevItemInGroup : null;
 },
 IsItemInAdaptiveMenu: function(index) {
  return this.elementsToHide.length >= index ? !!this.elementsToHide[index] : false;
 },
 SetItemPopOutImageVertical: function(element) {
  var popOutElements = ASPx.GetNodesByPartialClassName(element, "dxWeb_mHorizontalPopOut");
  for(var i = 0; i < popOutElements.length; i++)
   popOutElements[i].className = popOutElements[i].className.replace("Horizontal", "Vertical");
 },
 ChangeItemsPopOutImages: function(menuElement, isVertical) {
  var itemElements = this.GetItemElements(menuElement);
  for(var i = 0; i < itemElements.length; i++){
   if(isVertical)
    this.SetItemPopOutImageVertical(itemElements[i]);
   else
    this.SetItemItemPopOutImageHorizontal(itemElements[i]);
  }
 },
 ChangeOrientaion: function(menuElement, isVertical) {
  var oldCssSelector = isVertical ? MenuCssClasses.HorizontalMenu : MenuCssClasses.VerticalMenu;
  var newCssSelector = isVertical ? MenuCssClasses.VerticalMenu : MenuCssClasses.HorizontalMenu;
  menuElement.className = menuElement.className.replace(oldCssSelector, newCssSelector);
  this.ChangeItemsPopOutImages(menuElement, isVertical);
  this.CalculateMenuControl(menuElement, true);
  this.ChangeItemsPopOutImages(menuElement, isVertical);
 }
});
var MenuScrollingManager = ASPx.CreateClass(ASPx.ScrollingManager, {
 constructor: function(menuScrollHelper) {
  this.constructor.prototype.constructor.call(this, menuScrollHelper, {
   scrollableArea: menuScrollHelper.scrollingAreaElement,
   orientation: [0, 1],
   onBeforeScrolling: function(manager, direction) {
    manager.owner.OnBeforeScrolling(direction);
   },
   onAfterScrolling: function(manager, direction) {
    manager.owner.OnAfterScrolling(direction);
   },
   forseEmulation: false,
   useMarginForPosition: true,
   handleMouseWheel: menuScrollHelper.handleMouseWheel
  });
 },
 setParentNodeOverflow: function() { 
  if(ASPx.Browser.MSTouchUI) {
   this.scrollableArea.parentNode.style.overflow = "auto";
   this.scrollableArea.parentNode.style["-ms-overflow-style"] = "none";
  }  
 }
});
var MenuScrollHelper = ASPx.CreateClass(null, {
 constructor: function(menu, indexPath) {
  this.menu = menu;
  this.indexPath = indexPath;
  this.scrollingAreaElement = null;
  this.manager = null;
  this.initialized = false;
  this.visibleItems = [];
  this.itemsHeight = 0;
  this.scrollHeight = 0;
  this.scrollUpButtonHeight = 0;
  this.scrollDownButtonHeight = 0;
  this.scrollAreaHeight = null;
  this.scrollUpButtonVisible = false;
  this.scrollDownButtonVisible = false;
  this.handleMouseWheel = true;
 },
 Initialize: function() {
  if(this.initialized && !this.menu.NeedCreateItemsOnClientSide()) return;
  this.scrollingAreaElement = this.menu.GetScrollContentItemsContainer(this.indexPath);
  this.manager = new MenuScrollingManager(this);
  this.ShowScrollButtons();
  var scrollUpButton = this.menu.GetScrollUpButtonElement(this.indexPath);
  if(scrollUpButton) {
   this.scrollUpButtonHeight = this.GetScrollButtonHeight(scrollUpButton);
   ASPx.Selection.SetElementSelectionEnabled(scrollUpButton, false);
  }
  var scrollDownButton = this.menu.GetScrollDownButtonElement(this.indexPath);
  if(scrollDownButton) {
   this.scrollDownButtonHeight = this.GetScrollButtonHeight(scrollDownButton);
   ASPx.Selection.SetElementSelectionEnabled(scrollDownButton, false);
  }
  if(ASPx.Browser.WebKitTouchUI) {
   var preventDefault = function(event) { event.preventDefault(); };
   ASPx.Evt.AttachEventToElement(scrollUpButton, "touchstart", preventDefault);
   ASPx.Evt.AttachEventToElement(scrollDownButton, "touchstart", preventDefault);
  }
  this.HideScrollButtons();
  this.initialized = true;
 },
 GetScrollButtonHeight: function(button) {
  var style = ASPx.GetCurrentStyle(button);
  return button.offsetHeight + ASPx.PxToInt(style.marginTop) + ASPx.PxToInt(style.marginBottom);
 },
 FillVisibleItemsList: function() {
  var index = 0;
  this.visibleItems = [];
  while(true) {
   var childIndexPath = (this.indexPath != "" ? this.indexPath + ASPx.ItemIndexSeparator : "") + index;
   var itemElement = this.menu.GetItemElement(childIndexPath);
   if(itemElement == null)
    break;
   if(ASPx.GetElementDisplay(itemElement))
    this.visibleItems.push(itemElement);
   index++;
  }
 },
 CanCalculate: function() {
  return this.scrollingAreaElement && ASPx.IsElementDisplayed(this.scrollingAreaElement);
 },
 Calculate: function(scrollHeight) {
  if(!this.CanCalculate()) return;
  this.FillVisibleItemsList();
  this.itemsHeight = 0;
  this.scrollHeight = scrollHeight;
  var itemsContainer = this.menu.GetScrollContentItemsContainer(this.indexPath);
  if(itemsContainer) this.itemsHeight = itemsContainer.offsetHeight;
  this.SetPosition(0);
  this.CalculateScrollingElements(-1);
 },
 GetPosition: function() {
  return -this.manager.GetScrolledAreaPosition();
 },
 SetPosition: function(pos) {
  this.manager.SetScrolledAreaPosition(-pos);
 },
 CalculateScrollingElements: function(direction) {
  if(this.itemsHeight <= this.scrollHeight) {
   this.scrollUpButtonVisible = false;
   this.scrollDownButtonVisible = false;
   this.scrollAreaHeight = null;
   this.SetPosition(0);
  }
  else {
   var scrollTop = this.GetPosition();
   this.scrollAreaHeight = this.scrollHeight;
   if(direction > 0) {
    var showScrollUpButton = !this.scrollUpButtonVisible;
    this.scrollUpButtonVisible = true;
    this.scrollAreaHeight -= this.scrollUpButtonHeight;
    this.scrollDownButtonVisible = this.itemsHeight - this.scrollAreaHeight - scrollTop > this.scrollDownButtonHeight;
    if(this.scrollDownButtonVisible) {
     this.scrollAreaHeight -= this.scrollDownButtonHeight;
     if(showScrollUpButton)
      this.SetPosition(this.GetPosition() + this.scrollUpButtonHeight);
    }
    else {
     this.SetPosition(this.itemsHeight - this.scrollAreaHeight);
    }
   }
   else {
    this.scrollDownButtonVisible = true;
    this.scrollAreaHeight -= this.scrollDownButtonHeight;
    this.scrollUpButtonVisible = scrollTop > this.scrollUpButtonHeight;
    if(this.scrollUpButtonVisible)
     this.scrollAreaHeight -= this.scrollUpButtonHeight;
    else
     this.SetPosition(0);
   }
   if(this.scrollAreaHeight < 1) this.scrollAreaHeight = 1;
  }
  this.UpdateScrollingElements();
 },
 UpdateScrollingElements: function() {
  this.UpdateScrollAreaHeight();
  this.UpdateScrollButtonsVisibility();
 },
 UpdateScrollAreaHeight: function() {
  var scrollAreaElement = this.menu.GetScrollAreaElement(this.indexPath);
  if(scrollAreaElement)
   scrollAreaElement.style.height = (this.scrollAreaHeight) ? (this.scrollAreaHeight + "px") : "";
 },
 UpdateScrollButtonsVisibility: function() {
  var scrollUpButton = this.menu.GetScrollUpButtonElement(this.indexPath);
  if(scrollUpButton) ASPx.SetElementDisplay(scrollUpButton, this.scrollUpButtonVisible);
  var scrollDownButton = this.menu.GetScrollDownButtonElement(this.indexPath);
  if(scrollDownButton) ASPx.SetElementDisplay(scrollDownButton, this.scrollDownButtonVisible);
 },
 ChangeScrollButtonsVisibility: function(visible) {
  this.scrollUpButtonVisible = visible;
  this.scrollDownButtonVisible = visible;
  this.UpdateScrollButtonsVisibility();
 },
 ShowScrollButtons: function() {
  this.ChangeScrollButtonsVisibility(true);
 },
 HideScrollButtons: function() {
  this.ChangeScrollButtonsVisibility(false);
 },
 ResetScrolling: function() {
  if(!this.initialized)
   return;
  this.HideScrollButtons();
  this.SetPosition(0);
  this.scrollAreaHeight = null;
  this.UpdateScrollAreaHeight();
 },
 GetScrollAreaHeight: function() {
  var scrollAreaElement = this.menu.GetScrollAreaElement(this.indexPath);
  if(scrollAreaElement)
   return scrollAreaElement.offsetHeight;
  return 0;
 },
 OnAfterScrolling: function(direction) {
  this.CalculateScrollingElements(direction);
 },
 OnBeforeScrolling: function(direction) {
  var scrollButton = (direction > 0) ? this.menu.GetScrollDownButtonElement(this.indexPath) :
   this.menu.GetScrollUpButtonElement(this.indexPath);
  if(!scrollButton || !ASPx.GetElementDisplay(scrollButton))
   this.manager.StopScrolling();
 },
 StartScrolling: function(direction, delay, step) {
  this.manager.StartScrolling(direction, delay, step);
 },
 StopScrolling: function() {
  this.manager.StopScrolling();
 }
});
MenuScrollHelper.GetMenuByScrollButtonId = function(id) {
 var menuName = aspxGetMenuCollection().GetMenuNameBySuffixes(id, [Constants.SBIdSuffix]);
 return aspxGetMenuCollection().Get(menuName);
};
var ASPxClientMenuBase = ASPx.CreateClass(ASPxClientControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.renderData = null;
  this.renderHelper = this.CreateRenderHelper();
  this.sampleItemsFlags = {
   TextOnly: 0,
   SubItems: 1,
   Image: 2,
   NavigateUrl: 4,
   DropDownMode: 8,
   CheckBox: 16,
   ImageClassName: 32,
   Svg: 64
  };
  this.rootMenuSample = null;
  this.dropElementsCache = false;
  this.allowSelectItem = false;
  this.allowCheckItems = false;
  this.allowMultipleCallbacks = false;
  this.appearAfter = 300;
  this.slideAnimationDuration = 60;
  this.disappearAfter = 500;
  this.enableAnimation = true;
  this.enableAdaptivity = false;
  this.adaptiveItemsOrder = [];
  this.enableSubMenuFullWidth = false;
  this.checkedItems = [];
  this.isVertical = true;
  this.itemCheckedGroups = [];
  this.itemCheckedGroups.groupNames = {};
  this.lockHoverEvents = false;
  this.popupToLeft = false;
  this.popupCount = 0;
  this.rootItem = null;
  this.showSubMenus = false;
  this.savedCallbackHoverItem = null;
  this.savedCallbackHoverElement = null;
  this.selectedItemIndexPath = "";
  this.checkedState = null;
  this.scrollInfo = [];
  this.scrollHelpers = {};
  this.scrollVertOffset = 1;
  this.keyboardHelper = null;
  this.isContextMenu = false;
  this.accessibleFocusElement = null;
  this.rootSubMenuFIXOffset = 0;
  this.rootSubMenuFIYOffset = 0;
  this.rootSubMenuLIXOffset = 0;
  this.rootSubMenuLIYOffset = 0;
  this.rootSubMenuXOffset = 0;
  this.rootSubMenuYOffset = 0;
  this.subMenuFIXOffset = 0;
  this.subMenuFIYOffset = 0;
  this.subMenuLIXOffset = 0;
  this.subMenuLIYOffset = 0;
  this.subMenuXOffset = 0;
  this.subMenuYOffset = 0;
  this.maxHorizontalOverlap = -3;
  this.sizingConfig.allowSetHeight = false;
  this.ItemClick = new ASPxClientEvent();
  this.ItemMouseOver = new ASPxClientEvent();
  this.ItemMouseOut = new ASPxClientEvent();
  this.PopUp = new ASPxClientEvent();
  this.CloseUp = new ASPxClientEvent();
  aspxGetMenuCollection().Add(this);
 },
 SetData: function(data) {
  if(data.items)
   this.CreateItems(data.items);
 },
 InlineInitialize: function() {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  if(!this.NeedCreateItemsOnClientSide())
   this.renderHelper.InlineInitializeElements();
  else
   this.renderHelper.InlineInitializeScrollElements("", this.GetMainElement());
  this.InitializeInternal(true);
  if(this.IsCallbacksEnabled()) {
   this.showSubMenus = this.GetLoadingPanelElement() != null;
   this.CreateCallback("DXMENUCONTENT");
  }
  else
   this.showSubMenus = true;
  this.popupToLeft = this.rtl;
 },
 InitializeInternal: function(inline) {
  if(!this.NeedCreateItemsOnClientSide()) {
   this.InitializeCheckedItems();
   this.InitializeSelectedItem();
  }
  this.InitializeEnabledAndVisible(!inline || !this.IsCallbacksEnabled());
  if(!this.IsCallbacksEnabled())
   this.InitializeScrollableMenus();
  this.InitializeKeyboardHelper();
 },
 InitializeEnabledAndVisible: function(recursive) {
  if(this.rootItem == null) return;
  for(var i = 0; i < this.rootItem.items.length; i++)
   this.rootItem.items[i].InitializeEnabledAndVisible(recursive);
 },
 InitializeScrollableMenus: function() {
  var info = eval(this.scrollInfo);
  this.scrollHelpers = {};
  for(var i = 0; i < info.length; i++)
   this.InitializeScrollableMenu(info[i]);
 },
 InitializeScrollableMenu: function(indexPath) {
  if(!this.scrollHelpers[indexPath])
   this.scrollHelpers[indexPath] = new MenuScrollHelper(this, indexPath);
 },
 GetScrollHelper: function(indexPath) {
  var scrollsEnabledOnServer = this.scrollInfo.length > 0;
  if(this.NeedCreateItemsOnClientSide() && scrollsEnabledOnServer)
   this.InitializeScrollableMenu(indexPath);
  return this.scrollHelpers[indexPath];
 },
 InitializeKeyboardHelper: function() {
  this.keyboardHelper = new ASPxMenuKeyboardHelper(this);
 },
 InitializeMenuSamples: function() {
  this.rootMenuSample = this.GetSampleNode(this.samples.root);
  this.samples.spacing = this.GetSampleNode(this.samples.spacing);
  this.samples.separator = this.GetSampleNode(this.samples.separator);
  this.InitializeItemsSamples(this.samples.rootItems);
  if(this.samples.submenu) {
   this.samples.submenu = this.GetSampleNode(this.samples.submenu);
   this.InitializeItemsSamples(this.samples.submenuItems);
  }
 },
 InitializeItemsSamples: function(itemsSamples) {
  for(var sampleProperty in itemsSamples) {
   if(itemsSamples.hasOwnProperty(sampleProperty)) {
    itemsSamples[sampleProperty] = itemsSamples[sampleProperty].replace(/DXFAKE/, "");
    itemsSamples[sampleProperty] = this.GetSampleNode(itemsSamples[sampleProperty]);
   }
  }
 },
 CheckElementsCache: function(menuElement){
  if(this.dropElementsCache) {
   ASPx.CacheHelper.DropCache(menuElement);
   this.dropElementsCache = false;
  }
 },
 NeedCreateItemsOnClientSide: function() {
  return false;
 },
 IsClientSideEventsAssigned: function() {
  return !this.ItemClick.IsEmpty()
   || !this.ItemMouseOver.IsEmpty()
   || !this.ItemMouseOut.IsEmpty()
   || !this.PopUp.IsEmpty()
   || !this.CloseUp.IsEmpty()
   || !this.Init.IsEmpty();
 },
 IsCallbacksEnabled: function() {
  return ASPx.IsFunction(this.callBack);
 },
 ShouldHideExistingLoadingElements: function() {
  return false;
 },
 CreateRenderHelper: function(){
  return new MenuRenderHelper(this);
 },
 IsSidePanelExpanded: function() {
  return false;
 },
 GetMenuElementId: function(indexPath) {
  return this.name + Constants.MMIdSuffix + indexPath + "_";
 },
 GetMenuMainElementId: function(indexPath) {
  return this.name + "_DXME" + indexPath + "_";
 },
 GetMenuBorderCorrectorElementId: function(indexPath) {
  return this.name + "_DXMBC" + indexPath + "_";
 },
 GetMenuIFrameElementId: function(indexPath) {
  return this.name + "_DXMIF" + this.GetMenuLevel(indexPath);
 },
 GetScrollAreaId: function(indexPath) {
  return this.name + "_DXSA" + indexPath;
 },
 GetMenuTemplateContainerID: function(indexPath) {
  return this.name + "_MTCNT" + indexPath;
 },
 GetItemTemplateContainerID: function(indexPath) {
  return this.name + "_ITCNT" + indexPath;
 },
 GetScrollUpButtonId: function(indexPath) {
  return this.name + Constants.SBIdSuffix + indexPath + Constants.SBUIdEnd;
 },
 GetScrollDownButtonId: function(indexPath) {
  return this.name + Constants.SBIdSuffix + indexPath + Constants.SBDIdEnd;
 },
 GetItemElementId: function(indexPath) {
  return this.name + Constants.MIIdSuffix + indexPath + "_";
 },
 GetItemContentElementId: function(indexPath) {
  return this.GetItemElementId(indexPath) + Constants.ItemContentElementPostfix;
 },
 GetItemPopOutElementId: function(indexPath) {
  return this.GetItemElementId(indexPath) + Constants.ItemPopoutElementPostfix;
 },
 GetItemImageId: function(indexPath) {
  return this.GetItemElementId(indexPath) + Constants.ImagePostfix;
 },
 GetItemPopOutImageId: function(indexPath) {
  return this.GetItemElementId(indexPath) + Constants.PopupImagePostfix;
 },
 GetItemIndentElementId: function(indexPath) {
  return this.GetItemElementId(indexPath) + "II";
 },
 GetItemSeparatorElementId: function(indexPath) {
  return this.GetItemElementId(indexPath) + "IS";
 },
 GetMenuElement: function (indexPath) { 
  if(indexPath == "")
   return this.GetMainElement();
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetMenuElementId(indexPath));
 },
 GetMenuIFrameElement: function(indexPath) {
  var elementId = this.GetMenuIFrameElementId(indexPath);
  var element = ASPx.GetElementById(elementId);
  if(!element && this.renderIFrameForPopupElements)
   return this.CreateIFrameElement(elementId);
  return element;
 },
 CreateIFrameElement: function(elementId) {
  var element = document.createElement("IFRAME");
  ASPx.Attr.SetAttribute(element, "id", elementId);
  ASPx.Attr.SetAttribute(element, "src", "javascript:false");
  ASPx.Attr.SetAttribute(element, "scrolling", "no");
  ASPx.Attr.SetAttribute(element, "frameborder", "0");
  if(this.accessibilityCompliant)
   ASPx.Attr.SetAttribute(element, "title", ASPx.AccessibilitySR.AccessibilityIFrameTitle);
  element.style.position = "absolute";
  element.style.display = "none";
  element.style.zIndex = "19997";
  element.style.filter = "progid:DXImageTransform.Microsoft.Alpha(Style=0, Opacity=0)";
  ASPx.InsertElementAfter(element, this.GetMainElement());
  return element;
 },
 GetMenuBorderCorrectorElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetMenuBorderCorrectorElementId(indexPath));
 },
 GetMenuMainElement: function(element) {
  var indexPath = this.GetIndexPathById(element.id, true);
  return ASPx.CacheHelper.GetCachedElement(this, "menuMainElement" + indexPath, 
   function() { 
    var shadowTable = ASPx.GetElementById(this.GetMenuMainElementId(indexPath));
    return shadowTable != null ? shadowTable : element;
   });
 },
 GetScrollAreaElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetScrollAreaId(indexPath));
 },
 GetScrollContentItemsContainer: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElement(this, "scrollContentItemsContainer" + indexPath, 
   function() { 
    return ASPx.GetNodeByTagName(this.GetScrollAreaElement(indexPath), "UL", 0);
   });
 },
 GetScrollUpButtonElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetScrollUpButtonId(indexPath));
 },
 GetScrollDownButtonElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetScrollDownButtonId(indexPath));
 },
 GetItemElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetItemElementId(indexPath));
 },
 GetItemTemplateElement: function(indexPath) { 
  return this.GetItemTextTemplateContainer(indexPath);
 },
 GetItemTemplateContainer: function(indexPath) {
  return this.GetItemElement(indexPath);
 },
 GetItemTextTemplateContainer: function(indexPath) {
  return this.GetItemContentElement(indexPath);
 },
 GetItemContentElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetItemContentElementId(indexPath));
 },
 GetItemPopOutElement: function(indexPath) {
  return ASPx.CacheHelper.GetCachedElementById(this, this.GetItemPopOutElementId(indexPath));
 },
 GetPopOutElements: function() {
  return ASPx.GetNodesByClassName(this.GetMainElement().parentNode, "dxm-popOut");
 },
 GetPopOutImages: function() {
  return ASPx.GetNodesByClassName(this.GetMainElement().parentNode, "dxm-pImage");
 },
 GetSubMenuXPosition: function(indexPath, isVertical) {
  var itemElement = this.GetItemElement(indexPath);
  var pos = ASPx.GetAbsoluteX(itemElement) + (isVertical ? itemElement.clientWidth + itemElement.clientLeft : 0);
  if(ASPx.Browser.WebKitFamily && !this.IsParentElementPositionStatic(indexPath))
   pos -= document.body.offsetLeft;
  return pos;
 },
 GetSubMenuYPosition: function(indexPath, isVertical) {
  var position = 0;
  var element = this.GetItemElement(indexPath);
  if(element != null) {
   if(isVertical) {
    position = ASPx.GetAbsoluteY(element); 
   }
   else {
    if(ASPx.Browser.Opera && ASPx.Browser.Version >= 9 || ASPx.Browser.AndroidDefaultBrowser)
     position = ASPx.GetAbsoluteY(element) + element.offsetHeight - ASPx.GetClientTop(element);
    else
     position = ASPx.GetAbsoluteY(element) + element.clientHeight + ASPx.GetClientTop(element);
   }
  }
  if(ASPx.Browser.WebKitFamily && !this.IsParentElementPositionStatic(indexPath))
   position -= document.body.offsetTop;
  return position;
 },
 GetClientSubMenuXPosition: function(element, x, indexPath, isVertical) {
  var docClientWidth = ASPx.GetDocumentClientWidth();
  if(isVertical)
   return this.GetClientSubMenuXPositionVerticalCore(element, x, indexPath, isVertical, docClientWidth);
  return this.GetClientSubMenuXPositionHorizontalCore(element, x, indexPath, isVertical, docClientWidth);
 },
 GetClientSubMenuXPositionVerticalCore: function(element, x, indexPath, isVertical, docClientWidth) {
  var itemInfo = new MenuItemInfo(this, indexPath);
  var itemWidth = itemInfo.clientWidth;
  var subMenuWidth = this.GetMenuMainElement(element).offsetWidth;
  var left = x - ASPx.GetDocumentScrollLeft();
  var right = left + subMenuWidth;
  var toLeftX = x - subMenuWidth - itemWidth;
  var toLeftLeft = left - subMenuWidth - itemWidth;
  if(this.IsCorrectionDisableMethodRequired(indexPath))
   return this.GetCorrectionDisabledResult(x, toLeftX);
  if(this.popupToLeft) {
   if(toLeftLeft > this.maxHorizontalOverlap)
    return toLeftX;
   if(docClientWidth - right > this.maxHorizontalOverlap || !this.rtl) {
    this.popupToLeft = false;
    return x;
   }
   return ASPx.InvalidPosition;
  }
  else {
   if(docClientWidth - right > this.maxHorizontalOverlap)
    return x;
   if(toLeftLeft > this.maxHorizontalOverlap || this.rtl) {
    this.popupToLeft = true;
    return toLeftX;
   }
   return ASPx.InvalidPosition;
  }
 },
 GetClientSubMenuXPositionHorizontalCore: function(element, x, indexPath, isVertical, docClientWidth) {
  var itemInfo = new MenuItemInfo(this, indexPath);
  var itemOffsetWidth = itemInfo.offsetWidth;
  var subMenuWidth = this.GetMenuMainElement(element).offsetWidth;
  var left = x - ASPx.GetDocumentScrollLeft();
  if(this.popupToLeft) {
   var rtlX = left - subMenuWidth + itemOffsetWidth;
   return rtlX < 0 ? 0 : rtlX;
  }
  else {
   if(docClientWidth - (left + subMenuWidth) < 0) {
    x = docClientWidth - subMenuWidth;
    if(x < 0)
     x = 0;
    return x;
   }
   return x;
  }
 },
 GetClientSubMenuYPosition: function(element, y, indexPath, isVertical) {
  var itemInfo = new MenuItemInfo(this, indexPath);
  var itemHeight = itemInfo.offsetHeight;
  var subMenuHeight = this.GetMenuMainElement(element).offsetHeight;
  var menuItemTop = y - ASPx.GetDocumentScrollTop();
  var subMenuBottom = menuItemTop + subMenuHeight;
  var docClientHeight = ASPx.GetDocumentClientHeight();
  var clientSubMenuYPos = y;
  if(isVertical) {
   var notEnoughSpaceToShowDown = subMenuBottom > docClientHeight;
   var menuItemBottom = menuItemTop + itemHeight;
   if(menuItemBottom > docClientHeight) {
    menuItemBottom = docClientHeight;
    itemHeight = menuItemBottom - menuItemTop;
   }
   var notEnoughSpaceToShowUp = menuItemBottom < subMenuHeight;
   var subMenuIsFitToDisplayFrames = docClientHeight >= subMenuHeight;
   if(!subMenuIsFitToDisplayFrames) clientSubMenuYPos = y - menuItemTop;
   else if(notEnoughSpaceToShowDown) {
    if(notEnoughSpaceToShowUp) {
     var docClientBottom = ASPx.GetDocumentScrollTop() + docClientHeight;
     clientSubMenuYPos = docClientBottom - subMenuHeight;
    } else
     clientSubMenuYPos = y + itemHeight - subMenuHeight;
   }
  }
  else {
   if(this.IsHorizontalSubmenuNeedInversion(subMenuBottom, docClientHeight, menuItemTop, subMenuHeight, itemHeight))
    clientSubMenuYPos = y - subMenuHeight - itemHeight;
  }
  return clientSubMenuYPos;
 },
 IsHorizontalSubmenuNeedInversion: function(subMenuBottom, docClientHeight, menuItemTop, subMenuHeight, itemHeight) {
  return subMenuBottom > docClientHeight && menuItemTop - subMenuHeight - itemHeight > docClientHeight - subMenuBottom;
 },
 IsCorrectionDisableMethodRequired: function(indexPath) {
  return false;
 },
 HasChildren: function(indexPath) {
  return (this.GetMenuElement(indexPath) != null);
 },
 IsVertical: function(indexPath) {
  return true;
 },
 IsRootItem: function(indexPath) {
  return this.GetMenuLevel(indexPath) <= 1;
 },
 IsParentElementPositionStatic: function(indexPath) {
  return this.IsRootItem(indexPath);
 },
 GetItemIndexPath: function(indexes) {
  return aspxGetMenuCollection().GetItemIndexPath(indexes);
 },
 GetItemIndexes: function(indexPath) {
  return aspxGetMenuCollection().GetItemIndexes(indexPath);
 },
 GetItemIndexPathById: function(id) {
  return aspxGetMenuCollection().GetIndexPathById(id, Constants.MIIdSuffix);
 },
 GetMenuIndexPathById: function(id) {
  return aspxGetMenuCollection().GetIndexPathById(id, Constants.MMIdSuffix);
 },
 GetScrollButtonIndexPathById: function(id) {
  return aspxGetMenuCollection().GetIndexPathById(id, Constants.SBIdSuffix);
 },
 GetIndexPathById: function(id, checkMenu) {
  var indexPath = this.GetItemIndexPathById(id);
  if(indexPath == "" && checkMenu)
   indexPath = this.GetMenuIndexPathById(id);
  return indexPath;
 },
 GetMenuLevelInternal: function(indexPath) {
  if(indexPath == "")
   return 0;
  else {
   var indexes = this.GetItemIndexes(indexPath);
   return indexes.length;
  }
 },
 GetMenuLevel: function(indexPath) {
  var level = this.GetMenuLevelInternal(indexPath);
  if(this.IsAdaptiveMenuItem(indexPath))
   level ++;
  return level;
 },
 IsAdaptiveMenuItem: function(indexPath){
  var level = this.GetMenuLevelInternal(indexPath);
  while(level > 1){
   indexPath = this.GetParentIndexPath(indexPath);
   level = this.GetMenuLevelInternal(indexPath);
  }
  var itemElement = this.GetItemElement(indexPath);
  if(itemElement && ASPx.GetParentByClassName(itemElement, this.getAdaptiveMenuCssClass()))
   return true;
  return false;
 },
 IsAdaptiveItem: function(indexPath){
  var itemElement = this.GetItemElement(indexPath);
  if(itemElement && ASPx.ElementContainsCssClass(itemElement, this.getAdaptiveMenuItemCssClass()))
   return true;
  return false;
 },
 GetParentIndexPath: function(indexPath) {
  var indexes = this.GetItemIndexes(indexPath);
  indexes.length--;
  return (indexes.length > 0) ? this.GetItemIndexPath(indexes) : "";
 },
 IsLastElement: function(element) {
  return element && (!element.nextSibling || !element.nextSibling.tagName);
 },
 IsLastItem: function(indexPath) {
  var itemElement = this.GetItemElement(indexPath);
  return this.IsLastElement(itemElement);
 },
 IsFirstElement: function(element) {
  return element && (!element.previousSibling || !element.previousSibling.tagName);
 },
 IsFirstItem: function(indexPath) {
  var itemElement = this.GetItemElement(indexPath);
  return this.IsFirstElement(itemElement);
 },
 IsItemElement: function(element) {
  return ASPx.ElementContainsCssClass(element, MenuCssClasses.Item);
 },
 GetPreviousItem: function(itemPath, isItemNameUsed) {
  var indexPath = itemPath;
  if(isItemNameUsed) {
   var indexPath = this.GetMenuIndexPathById(itemPath);
   if(indexPath == "")
    indexPath = this.GetItemIndexPathById(itemPath);
  }
  var currentItem = this.GetItemByIndexPath(indexPath),
   previousItem = null;
  if(currentItem) {
   for(var i = currentItem.index - 1; i >= 0 && previousItem === null; i--) {
    if(currentItem.parent.items[i].GetVisible())
     previousItem = currentItem.parent.items[i];
   }
  }
  return previousItem;
 },
 GetClientSubMenuPos: function(element, indexPath, pos, isVertical, isXPos) {
  if(!ASPx.IsValidPosition(pos)) {
   pos = isXPos ? this.GetSubMenuXPosition(indexPath, isVertical) : this.GetSubMenuYPosition(indexPath, isVertical);
  }
  var clientPos = isXPos ? this.GetClientSubMenuXPosition(element, pos, indexPath, isVertical) : this.GetClientSubMenuYPosition(element, pos, indexPath, isVertical);
  var isInverted = pos != clientPos;
  if(clientPos !== ASPx.InvalidPosition){
   var offset = isXPos ? this.GetSubMenuXOffset(indexPath) : this.GetSubMenuYOffset(indexPath);
   clientPos += isInverted ? -offset : offset;
   clientPos -= ASPx.GetPositionElementOffset(this.GetMenuElement(indexPath), isXPos);
  }
  return new ASPx.PopupPosition(clientPos, isInverted);
 },
 GetSubMenuXOffset: function(indexPath) {
  if(indexPath == "")
   return 0;
  else if(this.IsRootItem(indexPath)) {
   if(this.IsFirstItem(indexPath))
    return this.rootSubMenuFIXOffset;
   else if(this.IsLastItem(indexPath))
    return this.rootSubMenuLIXOffset;
   else
    return this.rootSubMenuXOffset;
  }
  else {
   if(this.IsFirstItem(indexPath))
    return this.subMenuFIXOffset;
   else if(this.IsLastItem(indexPath))
    return this.subMenuLIXOffset;
   else
    return this.subMenuXOffset;
  }
 },
 GetSubMenuYOffset: function(indexPath) {
  if(indexPath == "")
   return 0;
  else if(this.IsRootItem(indexPath)) {
   if(this.IsFirstItem(indexPath))
    return this.rootSubMenuFIYOffset;
   else if(this.IsLastItem(indexPath))
    return this.rootSubMenuLIYOffset;
   else
    return this.rootSubMenuYOffset;
  }
  else {
   if(this.IsFirstItem(indexPath))
    return this.subMenuFIYOffset;
   else if(this.IsLastItem(indexPath))
    return this.subMenuLIYOffset;
   else
    return this.subMenuYOffset;
  }
 },
 CalculateSubMenuPosition: function(element, x, y, indexPath, enableAnimation) {
  var isVertical = this.IsVertical(indexPath);
  var horizontalPopupPosition = this.GetClientSubMenuPos(element, indexPath, x, isVertical, true);
  if(horizontalPopupPosition.position === ASPx.InvalidPosition) {
   isVertical = !isVertical;
   horizontalPopupPosition = this.GetClientSubMenuPos(element, indexPath, x, isVertical, true);
  }
  var verticalPopupPosition = this.GetClientSubMenuPos(element, indexPath, y, isVertical, false);
  var clientX = horizontalPopupPosition.position;
  var clientY = verticalPopupPosition.position;
  var toTheLeft = horizontalPopupPosition.isInverted;
  var toTheTop = verticalPopupPosition.isInverted;
  clientY += this.GetScrollingCorrection(element, indexPath, clientY);
  verticalPopupPosition.position = clientY;
  var parentElement = this.GetItemContentElement(indexPath);
  var prevParentPos = ASPx.GetAbsoluteX(parentElement);
  ASPx.SetStyles(element, {
   left: clientX, top: clientY
  });
  clientX += ASPx.GetAbsoluteX(parentElement) - prevParentPos;
  if(enableAnimation) {
   this.StartAnimation(element, indexPath, horizontalPopupPosition, verticalPopupPosition, isVertical);
  }
  else {
   ASPx.SetStyles(element, { left: clientX, top: clientY });
   ASPx.SetElementVisibility(element, true);
   if(this.enableSubMenuFullWidth)
    this.ApplySubMenuFullWidth(element);
   this.DoShowPopupMenuIFrame(element, clientX, clientY, ASPx.InvalidDimension, ASPx.InvalidDimension, indexPath);
   this.DoShowPopupMenuBorderCorrector(element, clientX, clientY, indexPath, toTheLeft, toTheTop);
  }
 },
 StartScrolling: function(buttonId, delay, step) {
  var indexPath = this.GetScrollButtonIndexPathById(buttonId);
  var level = this.GetMenuLevel(indexPath);
  aspxGetMenuCollection().DoHidePopupMenus(null, level, this.name, false, "");
  var direction = (buttonId.lastIndexOf(Constants.SBDIdEnd) == buttonId.length - Constants.SBDIdEnd.length) ? 1 : -1;
  var scrollHelper = this.GetScrollHelper(indexPath);
  if(scrollHelper) scrollHelper.StartScrolling(direction, delay, step);
 },
 StopScrolling: function(buttonId) {
  var indexPath = this.GetScrollButtonIndexPathById(buttonId);
  var scrollHelper = this.GetScrollHelper(indexPath);
  if(scrollHelper) scrollHelper.StopScrolling();
 },
 ClearAppearTimer: function() {
  aspxGetMenuCollection().ClearAppearTimer();
 },
 ClearDisappearTimer: function() {
  aspxGetMenuCollection().ClearDisappearTimer();
 },
 IsAppearTimerActive: function() {
  return aspxGetMenuCollection().IsAppearTimerActive();
 },
 IsDisappearTimerActive: function() {
  return aspxGetMenuCollection().IsDisappearTimerActive();
 },
 IsAdaptiveItemAnimationActive: function() {
  return this.inSubmenuShowAnimation;
 },
 GetAppearAfter: function(indexPath) {
  return this.appearAfter;
 },
 SetAppearTimer: function(indexPath, preventSubMenu) {
  aspxGetMenuCollection().SetAppearTimer(this.name, indexPath, this.GetAppearAfter(indexPath), preventSubMenu);
 },
 GetDisappearAfter: function() {
  return this.disappearAfter;
 },
 SetDisappearTimer: function() {
  aspxGetMenuCollection().SetDisappearTimer(this.name, this.GetDisappearAfter());
 },
 IsDropDownItem: function(indexPath) {
  return ASPx.ElementContainsCssClass(this.GetItemElement(indexPath), MenuCssClasses.ItemDropDownMode);
 },
 DoItemClick: function(indexPath, hasItemLink, htmlEvent) {
  aspxGetMenuCollection().LockMenusVisibility();
  var processOnServer = this.RaiseItemClick(indexPath, htmlEvent);
  if(processOnServer && !hasItemLink) {
   if(ASPx.Browser.Edge) { 
    var activeElement = document.activeElement;
    if(activeElement)
     activeElement.blur();
   }
   this.SendPostBack("CLICK:" + indexPath);
  }
  else {
   this.ClearDisappearTimer();
   this.ClearAppearTimer();
   if(this.CanCloseSubMenuOnClick(indexPath) && (!this.HasChildren(indexPath) || this.IsDropDownItem(indexPath)))
    aspxGetMenuCollection().DoHidePopupMenus(null, -1, this.name, false, "");
   else if(this.IsItemEnabled(indexPath) && !this.IsDropDownItem(indexPath))
    this.ShowSubMenu(indexPath);
  }
  aspxGetMenuCollection().UnlockMenusVisibility();
 },
 CanCloseSubMenuOnClick: function(indexPath) {
  return true;
 },
 HasContent: function(mainCell) {
  for(var i = 0; i < mainCell.childNodes.length; i++)
   if(mainCell.childNodes[i].tagName)
    return true;
  return false;
 },
 DoShowPopupMenu: function(element, x, y, indexPath) {
  var parent = this.GetItemByIndexPath(indexPath);
  var menuElement = this.GetMenuMainElement(element);
  var popupMenuHasVisibleContent = menuElement && (this.renderHelper.HasSubMenuTemplate(menuElement) || 
   ASPx.ElementContainsCssClass(menuElement, this.getAdaptiveMenuCssClass())) ||
   parent && this.HasVisibleItems(parent);
  if(popupMenuHasVisibleContent === false)
   return;
  if(element && this.IsCallbacksEnabled())
   this.ShowLoadingPanelInMenu(element);
  if(ASPx.GetElementVisibility(element))
   ASPx.SetStyles(element, { left: ASPx.InvalidPosition, top: ASPx.InvalidPosition });
  ASPx.SetElementDisplay(element, true);
  if(parent) {
   for(var i = 0; i < parent.GetItemCount() ; i++) {
    var item = parent.GetItem(i);
    this.SetPopOutElementVisible(item.indexPath, this.HasVisibleItems(item));
   }
  }
  this.renderHelper.CalculateSubMenu(element, false);
  if(this.popupCount == 0) this.popupToLeft = this.rtl;
  this.RaisePopUp(indexPath);
  this.CalculateSubMenuPosition(element, x, y, indexPath, this.enableAnimation);
  aspxGetMenuCollection().RegisterVisiblePopupMenu(this.name, element.id);
  this.popupCount++;
  ASPx.GetControlCollection().AdjustControls(element);
  this.CorrectVerticalAlignment(ASPx.AdjustHeight, this.GetPopOutElements, "PopOut");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetPopOutImages, "PopOutImg");
 },
 ShowLoadingPanelInMenu: function(element) {
  var lpParent = this.GetMenuMainElement(element);
  if(lpParent && !this.HasContent(lpParent))
   this.CreateLoadingPanelInsideContainer(lpParent);
 },
 GetScrollSubMenuYCorrection: function(element, scrollHelper, clientY) {
  var absoluteClientY = clientY + ASPx.GetPositionElementOffset(element);
  var excessTop = this.GetScrollExcessTop(absoluteClientY);
  var excessBottom = this.GetScrollExcessBottom(element, absoluteClientY);
  var correction = 0;
  if(excessTop > 0)
   correction += excessTop + this.scrollVertOffset;
  if(excessBottom > 0 && (absoluteClientY + correction == ASPx.GetDocumentScrollTop())) {
   excessBottom += this.scrollVertOffset;
   correction += this.scrollVertOffset;
  }
  this.PrepareScrolling(element, scrollHelper, excessTop, excessBottom);
  return correction;
 },
 GetScrollExcessTop: function(clientY) {
  return ASPx.GetDocumentScrollTop() - clientY;
 },
 GetScrollExcessBottom: function(element, clientY) {
  ASPx.SetElementDisplay(element, false);
  var docHeight = ASPx.GetDocumentClientHeight();
  ASPx.SetElementDisplay(element, true);
  return clientY + element.offsetHeight - ASPx.GetDocumentScrollTop() - docHeight;
 },
 PrepareScrolling: function(element, scrollHelper, excessTop, excessBottom) {
  scrollHelper.Initialize();
  var corrector = element.offsetHeight - scrollHelper.GetScrollAreaHeight() + this.scrollVertOffset;
  if(excessTop > 0)
   scrollHelper.Calculate(element.offsetHeight - excessTop - corrector);
  if(excessBottom > 0)
   scrollHelper.Calculate(element.offsetHeight - excessBottom - corrector);
 },
 ApplySubMenuFullWidth: function(element) {
  ASPx.SetStyles(element, { left: 0, right: 0, width: "auto" });
  var menuElement = this.GetMenuMainElement(element);
  ASPx.SetStyles(menuElement, { width: "100%", "box-sizing": "border-box" });
  var templateElement = ASPx.GetChildByClassName(menuElement, "dx");
  if(templateElement) ASPx.SetStyles(templateElement, { width: "100%" });
 },
 DoShowPopupMenuIFrame: function(element, x, y, width, height, indexPath) {
  if(!this.renderIFrameForPopupElements) return;
  var iFrame = element.overflowElement;
  if(!iFrame) {
   iFrame = this.GetMenuIFrameElement(indexPath);
   element.overflowElement = iFrame;
  }
  if(iFrame) {
   var menuElement = this.GetMenuMainElement(element);
   if(width < 0)
    width = menuElement.offsetWidth;
   if(height < 0)
    height = menuElement.offsetHeight;
   ASPx.SetStyles(iFrame, {
    width: width, height: height,
    left: x, top: y, display: ""
   });
  }
 },
 DoShowPopupMenuBorderCorrector: function(element, x, y, indexPath, toTheLeft, toTheTop) {
  var borderCorrectorElement = this.GetMenuBorderCorrectorElement(indexPath);
  if(borderCorrectorElement) {
   var params = this.GetPopupMenuBorderCorrectorPositionAndSize(element, x, y, indexPath, toTheLeft, toTheTop);
   ASPx.SetStyles(borderCorrectorElement, {
    width: params.width, height: params.height,
    left: params.left, top: params.top,
    display: "", visibility: "visible"
   });
   element.borderCorrectorElement = borderCorrectorElement;
  }
 },
 GetPopupMenuBorderCorrectorPositionAndSize: function(element, x, y, indexPath, toTheLeft, toTheTop) {
  var result = {};
  var itemInfo = new MenuItemInfo(this, indexPath);
  var menuXOffset = ASPx.GetClientLeft(this.GetMenuMainElement(element));
  var menuYOffset = ASPx.GetClientTop(this.GetMenuMainElement(element));
  var menuElement = this.GetMenuMainElement(element);
  var menuClientWidth = menuElement.clientWidth;
  var menuClientHeight = menuElement.clientHeight;
  if(this.IsVertical(indexPath)) {
   var commonClientHeight = itemInfo.clientHeight < menuClientHeight
    ? itemInfo.clientHeight
    : menuClientHeight;
   result.width = menuXOffset;
   result.height = commonClientHeight + itemInfo.clientTop - menuYOffset;
   result.left = x;
   if(toTheLeft)
    result.left += menuClientWidth + menuXOffset;
   result.top = y + menuYOffset;
   if(toTheTop)
    result.top += menuClientHeight - result.height;
  }
  else {
   var itemWidth = itemInfo.clientWidth;
   if(this.IsDropDownItem(indexPath))
    itemWidth = this.GetItemContentElement(indexPath).clientWidth;
   var commonClientWidth = itemWidth < menuClientWidth
    ? itemWidth
    : menuClientWidth;
   result.width = commonClientWidth + itemInfo.clientLeft - menuXOffset;
   result.height = menuYOffset;
   result.left = x + menuXOffset;
   if(toTheLeft)
    result.left += menuClientWidth - result.width;
   result.top = y;
   if(toTheTop)
    result.top += menuClientHeight + menuYOffset;
  }
  return result;
 },
 DoHidePopupMenu: function(evt, element) {
  this.DoHidePopupMenuBorderCorrector(element);
  this.DoHidePopupMenuIFrame(element);
  var menuElement = this.GetMenuMainElement(element);
  ASPx.PopupUtils.StopAnimation(element, menuElement);
  ASPx.SetElementVisibility(element, false);
  ASPx.SetElementDisplay(element, false);
  this.CancelSubMenuItemHoverItem(element);
  aspxGetMenuCollection().UnregisterVisiblePopupMenu(this.name, element.id);
  this.popupCount--;
  var indexPath = this.GetIndexPathById(element.id, true);
  this.DoResetScrolling(element, indexPath);
  this.RaiseCloseUp(indexPath);
 },
 DoResetScrolling: function(element, indexPath) {
  var scrollHelper = this.GetScrollHelper(indexPath);
  if(scrollHelper) {
   element.style.height = "";
   scrollHelper.ResetScrolling();
  }
 },
 DoHidePopupMenuIFrame: function(element) {
  if(!this.renderIFrameForPopupElements) return;
  var iFrame = element.overflowElement;
  if(iFrame)
   ASPx.SetElementDisplay(iFrame, false);
 },
 DoHidePopupMenuBorderCorrector: function(element) {
  var borderCorrectorElement = element.borderCorrectorElement;
  if(borderCorrectorElement) {
   ASPx.SetElementVisibility(borderCorrectorElement, false);
   ASPx.SetElementDisplay(borderCorrectorElement, false);
   element.borderCorrectorElement = null;
  }
 },
 MarkPrecedingItem: function(currentItemName, className, isItemNameUsed) {
  this.MarkPrecedingItemCore(currentItemName, className, true, isItemNameUsed);
 },
 UnmarkPrecedingItem: function(currentItemName, className, isItemNameUsed) {
  this.MarkPrecedingItemCore(currentItemName, className, false, isItemNameUsed);
 },
 MarkPrecedingItemCore: function(currentItemName, className, addClass, isItemNameUsed) {
  var previousItem = this.GetPreviousItem(currentItemName, isItemNameUsed);
  if(previousItem) {
   var element = this.GetItemElement(previousItem.indexPath);
   if(addClass)
    ASPx.AddClassNameToElement(element, className);
   else
    ASPx.RemoveClassNameFromElement(element, className);
  }
 },
 SetHoverElement: function(element) {
  if(!this.IsStateControllerEnabled()) return;
  this.lockHoverEvents = true;
  ASPx.GetStateController().SetCurrentHoverElementBySrcElement(element);
  this.lockHoverEvents = false;
 },
 ApplySubMenuItemHoverItem: function(element, hoverItem, hoverElement) {
  if(!element.hoverItem && ASPx.GetElementDisplay(element)) {
   var newHoverItem = hoverItem.Clone();
   element.hoverItem = newHoverItem;
   element.hoverElement = hoverElement;
   newHoverItem.Apply(hoverElement);
  }
 },
 CancelSubMenuItemHoverItem: function(element) {
  if(element.hoverItem) {
   element.hoverItem.Cancel(element.hoverElement);
   element.hoverItem = null;
   element.hoverElement = null;
  }
 },
 ShowSubMenu: function(indexPath) {
  var element = this.GetMenuElement(indexPath);
  if(element != null) {
   var level = this.GetMenuLevel(indexPath);
   aspxGetMenuCollection().DoHidePopupMenus(null, level - 1, this.name, false, this.getExceptIdsForShowSubMenu(indexPath, element.id));
   if(!this.isSubMenuElementVisible(element) && this.IsItemEnabled(indexPath))
    this.DoShowPopupMenu(element, ASPx.InvalidPosition, ASPx.InvalidPosition, indexPath);
  }
  this.ClearAppearTimer();
 },
 getExceptIdsForShowSubMenu: function (itemIndexPath, exceptId) {
  return [exceptId];
 },
 isSubMenuElementVisible: function(subMenuElement) {
  return ASPx.GetElementDisplay(subMenuElement);
 },
 SelectItem: function(indexPath) {
  if(!this.IsStateControllerEnabled()) return;
  var element = this.GetItemContentElement(indexPath);
  if(element != null) {
   ASPx.GetStateController().SelectElementBySrcElement(element);
   if(this.sideMenuModeOn)
    this.MarkPrecedingItem(indexPath, PRE_SELECTED_ELEMENT_CLASS_NAME, false);
  }
 },
 DeselectItem: function(indexPath) {
  if(!this.IsStateControllerEnabled()) return;
  var element = this.GetItemContentElement(indexPath);
  if(element != null) {
   var hoverItem = null;
   var hoverElement = null;
   var menuElement = this.GetMenuElement(indexPath);
   if(menuElement && menuElement.hoverItem) {
    hoverItem = menuElement.hoverItem;
    hoverElement = menuElement.hoverElement;
    this.CancelSubMenuItemHoverItem(menuElement);
   }
   ASPx.GetStateController().DeselectElementBySrcElement(element);
   if(menuElement != null && hoverItem != null)
    this.ApplySubMenuItemHoverItem(menuElement, hoverItem, hoverElement);
   if(this.sideMenuModeOn)
    this.UnmarkPrecedingItem(indexPath, PRE_SELECTED_ELEMENT_CLASS_NAME, false);
  }
 },
 InitializeSelectedItem: function() {
  if(!this.allowSelectItem && !this.HasServerSideSelectedItem()) return;
  this.SelectItem(this.GetSelectedItemIndexPath());
  this.InitializeServerSideSelectedItem();
 },
 InitializeServerSideSelectedItem: function() {
  if(!this.allowSelectItem && this.sideMenuModeOn && this.HasServerSideSelectedItem())
   this.MarkPrecedingItem(this.serverSideSelectedItemPath, PRE_SELECTED_ELEMENT_CLASS_NAME, false);
 },
 HasServerSideSelectedItem: function() {
  return typeof (this.serverSideSelectedItemPath) !== "undefined";
 },
 GetSelectedItemIndexPath: function() {
  return this.selectedItemIndexPath;
 },
 SetSelectedItemInternal: function(indexPath, modifyHotTrackSelection) {
  if(modifyHotTrackSelection)
   this.SetHoverElement(null);
  this.DeselectItem(this.selectedItemIndexPath);
  this.selectedItemIndexPath = indexPath;
  var item = this.GetItemByIndexPath(indexPath);
  if(item == null || item.GetEnabled())
   this.SelectItem(this.selectedItemIndexPath);
  if(modifyHotTrackSelection) {
   var element = this.GetItemContentElement(indexPath);
   if(element != null)
    this.SetHoverElement(element);
  }
 },
 InitializeCheckedItems: function() {
  if(!this.allowCheckItems) return;
  var indexPathes = this.checkedState.split(";");
  for(var i = 0; i < indexPathes.length; i++) {
   if(indexPathes[i] != "") {
    this.checkedItems.push(indexPathes[i]);
    this.SelectItem(indexPathes[i]);
   }
  }
 },
 ChangeCheckedItem: function(indexPath) {
  this.SetHoverElement(null);
  var itemsGroup = this.GetItemsGroup(indexPath);
  if(itemsGroup != null) {
   if(itemsGroup.length > 1) {
    if(!this.IsCheckedItem(indexPath)) {
     for(var i = 0; i < itemsGroup.length; i++) {
      if(itemsGroup[i] == indexPath) continue;
      if(this.IsCheckedItem(itemsGroup[i])) {
       ASPx.Data.ArrayRemove(this.checkedItems, itemsGroup[i]);
       this.DeselectItem(itemsGroup[i]);
      }
     }
     this.SelectItem(indexPath);
     this.checkedItems.push(indexPath);
    }
   }
   else {
    if(this.IsCheckedItem(indexPath)) {
     ASPx.Data.ArrayRemove(this.checkedItems, indexPath);
     this.DeselectItem(indexPath);
    }
    else {
     this.SelectItem(indexPath);
     this.checkedItems.push(indexPath);
    }
   }
  }
  var element = this.GetItemContentElement(indexPath);
  if(element != null)
   this.SetHoverElement(element);
 },
 GetItemsGroup: function(indexPath) {
  for(var i = 0; i < this.itemCheckedGroups.length; i++) {
   if(ASPx.Data.ArrayIndexOf(this.itemCheckedGroups[i], indexPath) > -1)
    return this.itemCheckedGroups[i];
  }
  return null;
 },
 IsCheckedItem: function(indexPath) {
  return ASPx.Data.ArrayIndexOf(this.checkedItems, indexPath) > -1;
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ selectedItemIndexPath: this.selectedItemIndexPath, checkedState: this.GetCheckedState() });
 },
 GetCheckedState: function() {
  return this.checkedItems.map(function(checkedItem) {
   return this.GetCheckedItemInfo(checkedItem);
  }.bind(this)).join(";");
 },
 GetCheckedItemInfo: function(itemIndexPath) {
  return itemIndexPath;
 },
 GetAnimationVerticalDirection: function(indexPath, popupPosition, isVertical) {
  var verticalDirection = (this.IsRootItem(indexPath) && !isVertical) ? -1 : 0;
  if(popupPosition.isInverted) verticalDirection *= -1;
  return verticalDirection;
 },
 GetAnimationHorizontalDirection: function(indexPath, popupPosition, isVertical) {
  var horizontalDirection = (this.IsRootItem(indexPath) && !isVertical) ? 0 : -1;
  if(popupPosition.isInverted) horizontalDirection *= -1;
  return horizontalDirection;
 },
 skipPopupMenuSizeInit: function() {
  return false;
 },
 StartAnimation: function(animationDivElement, indexPath, horizontalPopupPosition, verticalPopupPosition, isVertical) {
  this.inSubmenuShowAnimation = true;
  var element = this.GetMenuMainElement(animationDivElement);
  var clientX = horizontalPopupPosition.position;
  var clientY = verticalPopupPosition.position;
  ASPx.PopupUtils.InitAnimationDiv(animationDivElement, clientX, clientY, this.OnAnimationFinished.aspxBind(this), this.skipPopupMenuSizeInit());
  var verticalDirection = this.GetAnimationVerticalDirection(indexPath, verticalPopupPosition, isVertical);
  var horizontalDirection = this.GetAnimationHorizontalDirection(indexPath, horizontalPopupPosition, isVertical);
  var yPos = verticalDirection * element.offsetHeight;
  var xPos = horizontalDirection * element.offsetWidth;
  ASPx.SetStyles(element, { left: xPos, top: yPos });
  ASPx.SetElementVisibility(animationDivElement, true);
  if(this.enableSubMenuFullWidth)
   this.ApplySubMenuFullWidth(animationDivElement);
  this.DoShowPopupMenuIFrame(animationDivElement, clientX, clientY, 0, 0, indexPath);
  this.DoShowPopupMenuBorderCorrector(animationDivElement, clientX, clientY, indexPath,
   horizontalPopupPosition.isInverted, verticalPopupPosition.isInverted);
  ASPx.PopupUtils.StartSlideAnimation(animationDivElement, element, this.GetMenuIFrameElement(indexPath), this.slideAnimationDuration, this.enableSubMenuFullWidth, false);
 },
 OnAnimationFinished: function() {
  window.setTimeout(function() { this.inSubmenuShowAnimation = false; }.aspxBind(this), 100);
 },
 OnItemClick: function(indexPath, evt) {
  var sourceElement = ASPx.Evt.GetEventSource(evt);
  var clickedLinkElement = ASPx.GetParentByTagName(sourceElement, "A");
  var isLinkClicked = (clickedLinkElement != null && clickedLinkElement.href != ASPx.AccessibilityEmptyUrl);
  var element = this.GetItemContentElement(indexPath);
  var linkElement = (element != null) ? (element.tagName === "A" ? element : ASPx.GetNodeByTagName(element, "A", 0)) : null;
  if(linkElement != null && linkElement.href == ASPx.AccessibilityEmptyUrl)
   linkElement = null;
  if(this.allowSelectItem)
   this.SetSelectedItemInternal(indexPath, true);
  if(this.allowCheckItems || this.canCheckItem(element))
   this.ChangeCheckedItem(indexPath);
  this.DoItemClick(indexPath, isLinkClicked || (linkElement != null), evt);
  if(!isLinkClicked && linkElement != null && !(ASPx.Browser.WebKitTouchUI && this.HasChildren(indexPath)))
   ASPx.Url.NavigateByLink(linkElement);
 },
 canCheckItem: function (itemElement) {
  return false;
 },
 OnItemDropDownClick: function(indexPath, evt) {
  if(this.IsItemEnabled(indexPath)) {
   if(this.IsAdaptiveItem(indexPath))
    this.toggleAdaptiveSubmenu(indexPath);
   else
    this.keyboardHelper.ShowSubMenuAccessible(indexPath);
  }
 },
 toggleAdaptiveSubmenu: function(indexPath) {
  var element = this.GetMenuElement(indexPath);
  if(ASPx.GetElementDisplay(element) && !this.IsAdaptiveItemAnimationActive())
   this.DoHidePopupMenu(null, element);
  else
   this.keyboardHelper.ShowSubMenuAccessible(indexPath);
 },
 AfterItemOverAllowed: function(hoverItem) {
  return hoverItem.name != "" && !this.lockHoverEvents;
 },
 OnAfterItemOver: function(hoverItem, hoverElement) {
  if(!this.AfterItemOverAllowed(hoverItem)) return;
  if(!this.showSubMenus) {
   this.savedCallbackHoverItem = hoverItem;
   this.savedCallbackHoverElement = hoverElement;
   return;
  }
  this.ClearDisappearTimer();
  this.ClearAppearTimer();
  var indexPath = this.GetMenuIndexPathById(hoverItem.name);
  if(indexPath == "") {
   indexPath = this.GetItemIndexPathById(hoverItem.name);
   var canShowSubMenu = true;
   if(this.IsDropDownItem(indexPath)) {
    var popOutImageElement = this.GetItemPopOutElement(indexPath);
    if(popOutImageElement != null && popOutImageElement != hoverElement) {
     hoverItem.needRefreshBetweenElements = true;
     canShowSubMenu = false;
    }
   }
   var preventSubMenu = !(canShowSubMenu && hoverItem.enabled && hoverItem.kind == ASPx.HoverItemKind);
   this.SetAppearTimer(indexPath, preventSubMenu);
   this.RaiseItemMouseOver(indexPath);
  }
 },
 OnBeforeItemOver: function(hoverItem, hoverElement) {
  if(ASPx.Browser.NetscapeFamily && ASPx.IsExists(hoverElement.offsetParent) &&
    hoverElement.offsetParent.style.borderCollapse == "collapse") {
   hoverElement.offsetParent.style.borderCollapse = "separate";
   hoverElement.offsetParent.style.borderCollapse = "collapse";
  }
  var indexPath = this.GetItemIndexPathById(hoverItem.name);
  var element = this.GetMenuElement(indexPath);
  if(element) this.CancelSubMenuItemHoverItem(element);
 },
 OnItemOverTimer: function(indexPath, preventSubMenu) {
  var element = this.GetMenuElement(indexPath);
  if(element == null || preventSubMenu) {
   var level = this.GetMenuLevel(indexPath);
   aspxGetMenuCollection().DoHidePopupMenus(null, level - 1, this.name, false, this.getExceptIdsForItemOverTimer(indexPath));
  }
  if(this.IsAppearTimerActive() && !preventSubMenu) {
   this.ClearAppearTimer();
   if(this.GetItemContentElement(indexPath) != null || this.GetItemPopOutElement(indexPath) != null) {
    this.ShowSubMenu(indexPath);
   }
  }
 },
 getExceptIdsForItemOverTimer: function(indexPath) {
  var result = [];
  aspxGetMenuCollection().ForEachControl(function(menu) {
   var isPopupMenu = ASPx.IsExists(menu.popupAction) && ASPx.IsExists(menu.closeAction);
   if(isPopupMenu && menu.closeAction === "OuterMouseClick")
    result.push(menu.GetMainElementId());
  }, this);
  return result;
 },
 OnBeforeItemDisabled: function(disabledItem, disabledElement) {
  this.ClearAppearTimer();
  var indexPath = this.GetItemIndexPathById(disabledElement.id);
  if(indexPath != "") {
   var element = this.GetMenuElement(indexPath);
   if(element != null) this.DoHidePopupMenu(null, element);
  }
 },
 OnAfterItemOut: function(hoverItem, hoverElement, newHoverElement) {
  if(!this.showSubMenus) {
   this.savedCallbackHoverItem = null;
   this.savedCallbackHoverElement = null;
  }
  if(hoverItem.name == "" || this.lockHoverEvents) return;
  if(hoverItem.IsChildElement(newHoverElement)) return;
  var indexPath = this.GetItemIndexPathById(hoverItem.name);
  var element = this.GetMenuElement(indexPath);
  this.ClearDisappearTimer();
  this.ClearAppearTimer();
  if(element == null || !ASPx.GetIsParent(element, newHoverElement))
   this.SetDisappearTimer();
  if(element != null)
   this.ApplySubMenuItemHoverItem(element, hoverItem, hoverElement);
  if(indexPath != "")
   this.RaiseItemMouseOut(indexPath);
 },
 OnItemOutTimer: function() {
  if(this.IsDisappearTimerActive()) {
   this.ClearDisappearTimer();
   if(aspxGetMenuCollection().CheckFocusedElement())
    this.SetDisappearTimer();
   else
    this.OnHideByItemOut();
  }
 },
 OnHideByItemOut: function() {
  aspxGetMenuCollection().DoHidePopupMenus(null, 0, this.name, true, "");
 },
 TryFocusItem: function(itemIndex) {
  var item = this.GetItem(itemIndex);
  if(item.GetVisible() && item.GetEnabled()) {
   this.FocusItemByIndexPath(item.GetIndexPath());
   return true;
  }
  return false;
 },
 Focus: function() {
  if(this.rootItem != null) { 
   for(var i = 0; i < this.GetItemCount() ; i++) {
    if(this.TryFocusItem(i))
     return true;
   }
  }
  else
   this.keyboardHelper.FocusNextItem("-1");
 },
 FocusLastItem: function() {
  if(this.rootItem != null) { 
   for(var i = this.GetItemCount() - 1; i >= 0; i--) {
    if(this.TryFocusItem(i))
     return true;
   }
  }
  else
   this.keyboardHelper.FocusPrevItem(this.GetItemCount() - 1);
 },
 FocusItemByIndexPath: function(indexPath) {
  this.keyboardHelper.FocusItemByIndexPath(indexPath);
 },
 OnFocusedItemKeyDown: function(evt, focusedItem) {
  this.keyboardHelper.OnFocusedItemKeyDown(evt, focusedItem);
 },
 ProcessLostFocus: function(evt) {
  if(!this.isContextMenu || !this.accessibilityCompliant) return;
  if(this.accessibleFocusElement)
   this.accessibleFocusElement.focus();
  this.Hide();
  if(evt)
   ASPx.Evt.PreventEventAndBubble(evt);
 },
 OnCallback: function(result) {
  ASPx.InitializeScripts(); 
  this.InitializeScrollableMenus();
  for (var indexPath in result) {
   if(result.hasOwnProperty(indexPath)) {
    var menuElement = this.GetMenuElement(indexPath);
    if(menuElement) {
     var menuResult = result[indexPath];
     if(aspxGetMenuCollection().IsSubMenuVisible(menuElement.id))
      this.ShowPopupSubMenuAfterCallback(menuElement, menuResult);
     else
      this.SetSubMenuInnerHtml(menuElement, menuResult);
    }
   }
  }
  this.ClearVerticalAlignedElementsCache();
  this.CorrectVerticalAlignment(ASPx.AdjustHeight, this.GetPopOutElements, "PopOut");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetPopOutImages, "PopOutImg");
  this.InitializeInternal(false);
  if(!this.showSubMenus) {
   this.showSubMenus = true;
   if(this.savedCallbackHoverItem != null && this.savedCallbackHoverElement != null)
    this.OnAfterItemOver(this.savedCallbackHoverItem, this.savedCallbackHoverElement);
   this.savedCallbackHoverItem = null;
   this.savedCallbackHoverElement = null;
  }
 },
 SetSubMenuInnerHtml: function(menuElement, html) {
  ASPx.SetInnerHtml(this.GetMenuMainElement(menuElement), html);
  this.dropElementsCache = true;
  this.renderHelper.InlineInitializePopupMenuMenuElement(menuElement, this.GetIndexPathById(menuElement.id, true));
  this.renderHelper.CalculateSubMenu(menuElement, true);
 },
 ShowPopupSubMenuAfterCallback: function(element, callbackResult) {
  var indexPath = this.GetIndexPathById(element.id, true);
  var currentX = ASPx.PxToInt(element.style.left);
  var currentY = ASPx.PxToInt(element.style.top);
  var showedToTheTop = this.ShowedToTheTop(element, indexPath);
  var showedToTheLeft = this.ShowedToTheLeft(element, indexPath);
  ASPx.SetStyles(element, {
   left: ASPx.InvalidPosition, top: ASPx.InvalidPosition
  });
  this.SetSubMenuInnerHtml(element, callbackResult);
  var vertPos = this.GetClientSubMenuPos(element, indexPath, ASPx.InvalidPosition, this.IsVertical(indexPath), false);
  var clientY = vertPos.position;
  var toTheTop = vertPos.isInverted;
  if(!this.IsVertical(indexPath) && showedToTheTop != toTheTop) {
   clientY = currentY;
   toTheTop = showedToTheTop;
  }
  clientY += this.GetScrollingCorrection(element, indexPath, clientY);
  ASPx.SetStyles(element, { left: currentX, top: clientY });
  if(this.enableSubMenuFullWidth)
   this.ApplySubMenuFullWidth(element);
  this.DoShowPopupMenuIFrame(element, currentX, clientY, ASPx.InvalidDimension, ASPx.InvalidDimension, indexPath);
  this.DoShowPopupMenuBorderCorrector(element, currentX, clientY, indexPath, showedToTheLeft, toTheTop);
  ASPx.GetControlCollection().AdjustControls(element);
 },
 GetScrollingCorrection: function(element, indexPath, clientY) {
  var scrollHelper = this.GetScrollHelper(indexPath);
  if(scrollHelper) {
   var yClientCorrection = this.GetScrollSubMenuYCorrection(element, scrollHelper, clientY);
   if(yClientCorrection > 0)
    return yClientCorrection;
  }
  return 0;
 },
 ShowedToTheTop: function(element, indexPath) {
  var currentY = ASPx.PxToInt(element.style.top);
  var parentBottomY = this.GetSubMenuYPosition(indexPath, this.IsVertical(indexPath));
  return currentY < parentBottomY;
 },
 ShowedToTheLeft: function(element, indexPath) {
  var currentX = ASPx.PxToInt(element.style.left);
  var parentX = this.GetSubMenuXPosition(indexPath, this.IsVertical(indexPath));
  return currentX < parentX;
 },
 CreateItems: function(items) {
  if (items.length == 0)
   return;
  if(this.NeedCreateItemsOnClientSide())
   this.CreateClientItems(items);
  else
   this.CreateServerItems(items);
 },
 AddItem: function(item) {
  this.CreateClientItems([item]);
 },
 CreateClientItems: function(items) {
  this.PreInitializeClientMenuItems();
  this.rootItem.CreateItems(items);
  this.RenderItems(this.rootItem.items);
  this.InitializeClientItems();
 },
 CreateServerItems: function(items) {
  this.CreateRootItemIfRequired();
  this.rootItem.CreateItems(items);
 },
 PreInitializeClientMenuItems: function() {
  if(!this.rootMenuSample)
   this.InitializeMenuSamples();
  this.CreateRootItemIfRequired();
  if(!this.renderData)
   this.CreateRenderData();
 },
 InitializeClientItems: function() {
  this.dropElementsCache = true;
  this.renderHelper.InlineInitializeElements();
  this.ApplyItemsProperties(this.rootItem.items);
  this.InitializeEnabledAndVisible(true);
  if(this.isPopupMenu)
   this.renderHelper.CalculateSubMenu(this.GetMainElement(), true);
  else
   this.renderHelper.CalculateMenuControl(this.GetMainElement(), true);
 },
 ApplyItemsProperties: function(items) {
  var itemsCount = items.length;
  if(itemsCount == 0)
   return;
  for(var i = 0; i < itemsCount; i++) {
   var item = items[i];
   this.ApplyItemProperties(item);
   this.ApplyItemsProperties(item.items);
  }
 },
 ApplyItemProperties: function(item) {
  var indexPath = item.GetIndexPath();
  if(item.imageUrl)
   this.SetItemImageUrl(indexPath, item.imageUrl);
  if(item.imageClassName) {
   this.AddItemImageClassName(indexPath, item.imageClassName);
   this.AddItemAdditionalImageClassName(indexPath, item.imageClassName);
  }
  if(item.navigateUrl)
   this.SetItemNavigateUrl(indexPath, item.navigateUrl, item.target);
  if(item.tooltip != "")
   this.SetItemTooltip(indexPath, item.tooltip);
  var textNode = this.FindTextNode(indexPath);
  if(textNode)
   textNode.parentNode.innerHTML = this.HtmlEncode(item.text);
  this.SetItemChecked(indexPath, item.checked);
  if(item.textTemplate)
   this.SetItemTextTemplate(indexPath, item.textTemplate);
 },
 ProcessItemGroupName: function(item, groupName) {
  if(this.allowSelectItem || !groupName)
   return;
  this.allowCheckItems = true;
  var groupNames = this.itemCheckedGroups.groupNames;
  if(groupNames[groupName])
   groupNames[groupName].push(item.indexPath);
  else {
   groupNames[groupName] = [item.indexPath];
   this.itemCheckedGroups.push(groupNames[groupName]);
  }
  item.checkedGroup = groupNames[groupName];
 },
 CreateRootItemIfRequired: function() {
  if(!this.rootItem) {
   var itemType = this.GetClientItemType();
   this.rootItem = new itemType(this, null, 0, "");
  }
 },
 ClearRootMenuElement: function() {
  var wrapperElement = this.GetMainElement().parentNode;
  wrapperElement.innerHTML = "";
  wrapperElement.appendChild(this.rootMenuSample.cloneNode(true));
  this.renderHelper.InlineInitializeScrollElements("", this.GetMainElement());
 }, 
 NeedAppendToRenderData: function(item) {
  return this.NeedCreateItemsOnClientSide() && item.visible || typeof(item.visible) == "undefined";
 },
 ClearItems: function() {
  this.PreInitializeClientMenuItems();
  this.ClearRootMenuElement();
  this.ClearRenderData();
  this.rootItem.items = [];
  this.checkedItems = [];
 },
 GetSampleNode: function(sampleHtml) {
  return ASPx.CreateHtmlElementFromString(sampleHtml);
 },
 GetParentItem: function(rootItemIndexPath) {
  if(!rootItemIndexPath)
   return this.rootItem;
  return this.GetItemByIndexPath(rootItemIndexPath);
 },
 RenderItems: function(items) {
  for(var i=0; i < items.length; i++) {
   var item = items[i];
   this.RenderItemIfRequired(item);
   this.RenderItems(item.items);
  }
 },
 RenderItemIfRequired: function(item) {
  if(!this.GetItemElement(item.indexPath)) {
   var isRootItem = !this.GetItemElement(item.parent.indexPath);
   var rootMenuElement = this.GetOrRenderRootItem(item, isRootItem);
   this.RenderItemInternal(rootMenuElement, item, isRootItem);
   this.ApplyStylesToRenderItem(item, isRootItem);
  }
 },
 ApplyStylesToRenderItem: function(item, isRootItem) {
  var styles = JSON.parse(JSON.stringify(isRootItem ? this.samples.itemsStyles : this.samples.subitemsStyles));
  var hoverStyle = styles.hover;
  var disabledStyle = styles.disable;
  var selectedStyle = styles.select;
  var checkedStyle = styles.check;
  var itemElementId = this.GetItemElementId(item.indexPath);
  if(item.styles && item.styles.ho) {
   var itemHover = item.styles.ho;
   if(!!itemHover.style)
    hoverStyle.cssTexts[0] = itemHover.style;
   if(!!itemHover.cssClass)
    hoverStyle.classNames[0] += " " + itemHover.cssClass;
  }
  if(item.styles && item.styles.st) {
   var itemElement = this.GetItemElement(item.indexPath);
   var style = item.styles.st;
   itemElement.setAttribute("style", style.style);
   if(!!style.cssClass)
    ASPx.AddClassNameToElement(itemElement, style.cssClass);
  }
  ASPx.GetStateController().AddHoverItem(itemElementId, hoverStyle.classNames || [MenuCssClasses.ItemHovered], hoverStyle.cssTexts || [""], hoverStyle.postfixes || [""], item.imageHottrackSrc ? [item.imageHottrackSrc] : null, [Constants.ImagePostfix, Constants.PopupImagePostfix], false);
  ASPx.GetStateController().AddDisabledItem(itemElementId, disabledStyle.classNames || [MenuCssClasses.Disabled], disabledStyle.cssTexts || [""], disabledStyle.postfixes || [""], null, null, false);
  if(selectedStyle && this.allowSelectItem)
   ASPx.GetStateController().AddSelectedItem(itemElementId, selectedStyle.classNames || [MenuCssClasses.ItemSelected], selectedStyle.cssTexts || [""], selectedStyle.postfixes || [""], null, null, false);
  else if (checkedStyle && this.allowCheckItems && item.checkedGroup.length) {
   var checkedClassName = null;
   if(!item.imageClassName)
    checkedClassName = [this.samples.checkedClassName];
   ASPx.GetStateController().AddSelectedItem(itemElementId, checkedStyle.classNames || [MenuCssClasses.ItemChecked], checkedStyle.cssTexts || [""], checkedStyle.postfixes || [""], checkedClassName, ['Img'], false);
  }
 },
 GetOrRenderRootItem: function(item, isRootItem) {
  if(!isRootItem) {
   var rootMenuElement = this.GetMenuElement(item.parent.indexPath);
   return rootMenuElement ? rootMenuElement : this.RenderSubMenuItem(item.parent.indexPath);
  } else
   return this.GetMenuElement("");
 },
 RenderItemInternal: function(rootItem, item, isRootItem) {
  var contentElement = this.renderHelper.GetContentElement(rootItem);
  var element = this.CreateItemElement(item, isRootItem);
  this.RenderSeparatorElementIfRequired(contentElement, item);
  this.RenderSpaceElementIfRequired(contentElement, item);
  contentElement.appendChild(element);
 },
 RenderSeparatorElementIfRequired: function(rootItem, item) {
  if(item.beginGroup && item.index > 0) {
   var separatorElement = this.CreateSeparatorElement(item.indexPath);
   rootItem.appendChild(separatorElement);
  }
 },
 RenderSpaceElementIfRequired: function(rootItem, item) {
  if(!item.beginGroup && item.index > 0 && rootItem.childNodes.length > 0) {
   if(this.samples.spacing) {
    var spacingElement = this.CreateSpacingElement(item.indexPath);
    rootItem.appendChild(spacingElement);
   }
  }
 },
 RenderSubMenuItem: function(indexPath) {
  var subMenuElement = this.CreateSubMenuElement(indexPath);
  this.GetMainElement().parentElement.appendChild(subMenuElement);
  return subMenuElement;
 },
 HasSeparatorOnCurrentPosition: function(itemElements, position) {
  return itemElements[position - 1 > 0 ? position - 1 : 0].className.indexOf(MenuCssClasses.Separator) > -1;
 },
 CreateItemElement: function(item, isRootItem) {
  var itemSample = isRootItem ? this.GetRootItemSample(item) : this.GetSubitemSample(item);
  var itemElement = itemSample.cloneNode(true);
  itemElement.id = this.GetItemElementId(item.indexPath);
  return itemElement;
 },
 GetRootItemSample: function(item) {
  return this.GetItemSample(this.samples.rootItems, item);
 },
 GetSubitemSample: function(item) {
  return this.GetItemSample(this.samples.submenuItems, item);
 },
 GetItemSample: function(samples, item) {
  var key = this.sampleItemsFlags.TextOnly;
  if(item.items.length > 0)
   key = key | this.sampleItemsFlags.SubItems;
  if(item.imageUrl)
   key = key | this.sampleItemsFlags.Image;
  if(item.navigateUrl)
   key = key | this.sampleItemsFlags.NavigateUrl;
  if(item.dropDownMode)
   key = key | this.sampleItemsFlags.DropDownMode;
  if(item.checkedGroup.length)
   key = key | this.sampleItemsFlags.CheckBox;
  if(item.imageClassName)
   key = key | this.sampleItemsFlags.ImageClassName;
  if(item.isSvg)
   key = key | this.sampleItemsFlags.Svg;
  return samples[key];
 },
 CreateSpacingElement: function(indexPath) {
  var item = this.samples.spacing.cloneNode();
  item.id = this.GetItemIndentElementId(indexPath);
  return item;
 },
 CreateSeparatorElement: function(indexPath) {
  var item = this.samples.separator.cloneNode(true);
  item.id = this.GetItemSeparatorElementId(indexPath);
  return item;
 },
 CreateSubMenuElement: function(indexPath) {
  var subMenu = this.samples.submenu.cloneNode(true);
  subMenu.id =  this.name + Constants.MMIdSuffix + indexPath + "_";
  return subMenu;
 },
 AppendToRenderData: function(rootItemIndexPath, index) {
  if(rootItemIndexPath) {
   if(!this.renderData[rootItemIndexPath])
    this.renderData[rootItemIndexPath] = [[index]];
   this.renderData[rootItemIndexPath][index] = [index];
  } else {
   this.renderData[""].push([[index]]);
  }
 },
 CreateRenderData: function() {
  this.renderData = {"" : []};
 },
 ClearRenderData: function() {
  this.renderData = null;
 },
 GetClientItemType: function() {
  return ASPxClientMenuItem;
 },
 GetItemByIndexPath: function(indexPath) {
  var item = this.rootItem;
  if(indexPath != "" && item != null) {
   var indexes = this.GetItemIndexes(indexPath);
   for(var i = 0; i < indexes.length; i++)
    item = item.GetItem(indexes[i]);
  }
  return item;
 },
 GetLinkElementByIndexPath: function(indexPath) {
  var itemElement = this.GetItemElement(indexPath);
  return this.renderHelper.GetItemLinkElement(itemElement);
 },
 SetItemChecked: function(indexPath, checked) {
  var itemsGroup = this.GetItemsGroup(indexPath);
  if(itemsGroup != null) {
   if(!checked && this.IsCheckedItem(indexPath)) {
    ASPx.Data.ArrayRemove(this.checkedItems, indexPath);
    this.DeselectItem(indexPath);
   }
   else if(checked && !this.IsCheckedItem(indexPath)) {
    if(itemsGroup.length > 1) {
     for(var i = 0; i < itemsGroup.length; i++) {
      if(itemsGroup[i] == indexPath) continue;
      if(this.IsCheckedItem(itemsGroup[i])) {
       ASPx.Data.ArrayRemove(this.checkedItems, itemsGroup[i]);
       this.DeselectItem(itemsGroup[i]);
      }
     }
    }
    this.SelectItem(indexPath);
    this.checkedItems.push(indexPath);
   }
   if(this.accessibilityCompliant) {
    var link = this.GetLinkElementByIndexPath(indexPath);
    if(link)
     ASPx.Attr.SetAttribute(link, "aria-checked", checked ? "true" : "false");
   }
  }
 },
 ChangeItemEnabledAttributes: function(indexPath, enabled) {
  this.renderHelper.ChangeItemEnabledAttributes(this.GetItemElement(indexPath), enabled, this.accessibilityCompliant);
 },
 IsItemEnabled: function(indexPath) {
  var item = this.GetItemByIndexPath(indexPath);
  return (item != null) ? item.GetEnabled() : true;
 },
 SetItemEnabled: function(indexPath, enabled, initialization) {
  if(indexPath == "" || !this.GetItemByIndexPath(indexPath).enabled) return;
  if(!enabled) {
   if(this.GetSelectedItemIndexPath() == indexPath)
    this.DeselectItem(indexPath);
  }
  if(!initialization || !enabled)
   this.ChangeItemEnabledStateItems(indexPath, enabled);
  this.ChangeItemEnabledAttributes(indexPath, enabled);
  if(enabled) {
   if(this.GetSelectedItemIndexPath() == indexPath)
    this.SelectItem(indexPath);
  }
 },
 ChangeItemEnabledStateItems: function(indexPath, enabled) {
  if(!this.IsStateControllerEnabled()) return;
  this.UpdateHoverableItems(indexPath, enabled);
  var element = this.GetItemElement(indexPath);
  if(element)
   ASPx.GetStateController().SetElementEnabled(element, enabled);
 },
 UpdateHoverableItems: function(indexPath, enabled) {
  var menuItemElement = this.GetItemElement(indexPath);
  if(menuItemElement) {
   var postfixes = ["", Constants.ItemPopoutElementPostfix, Constants.ItemContentElementPostfix];
   for(var i = 0; i < postfixes.length; i++) {
    var element = ASPx.CacheHelper.GetCachedElementById(this, this.GetItemElementId(indexPath) + postfixes[i]);
    if(element) {
     if(enabled) {
      var hoverItem = element.savedHoverItem;
      if(hoverItem)
       ASPx.GetStateController().AddHoverItem(hoverItem.name, hoverItem.classNames, hoverItem.cssTexts, hoverItem.postfixes, hoverItem.imageObjs, hoverItem.imagePostfixes, hoverItem.disableApplyingStyleToLink);
     }
     else {
      element.savedHoverItem = ASPx.GetStateController().GetHoverItem(element);
     }
    }
   }
   ASPx.GetStateController().ClearElementCacheInContainer(menuItemElement);
   if(!enabled)
    ASPx.GetStateController().RemoveItem(ASPx.GetStateController().hoverItems, this.GetItemElementId(indexPath), postfixes);
  }
 },
 GetItemImageUrl: function(indexPath) {
  var image = this.GetItemImage(indexPath);
  if(image)
   return image.src;
  return "";
 },
 SetItemImageUrl: function(indexPath, url) {
  var image = this.GetItemImage(indexPath);
  if(image)
   image.src = url;
 },
 AddItemImageClassName: function(indexPath, className) {
  var image = this.GetItemImage(indexPath);
  if(image) {
   var accessibilityElement = image.parentNode;
   if(accessibilityElement.tagName === "SPAN") {
    ASPx.AddClassNameToElement(accessibilityElement, className);
    ASPx.RemoveClassNameFromElement(accessibilityElement, "dx-acc-s");
   }
   else
    ASPx.AddClassNameToElement(image, className);
  }
  else {
   var svgElement = this.getSvgElement(indexPath);
   if(svgElement) {
    ASPx.AddClassNameToElement(svgElement, className);
    var useElement = ASPx.GetNodeByTagName(svgElement, "use", 0);
    useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', "#" + className);
   }
  }
 },
 AddItemAdditionalImageClassName: function(indexPath) {
 },
 getSvgElement: function(indexPath) {
  var element = this.GetItemContentElement(indexPath);
  if(element != null) {
   var svgElement = ASPx.GetNodeByTagName(element, "svg", 0);
   if(svgElement != null) {
    return svgElement;
   }
  }
 },
 GetItemImage: function(indexPath) {
  var element = this.GetItemContentElement(indexPath);
  if(element != null) {
   var img = ASPx.GetNodeByTagName(element, "IMG", 0);
   if(img != null)
    return img;
  }
 },
 GetItemNavigateUrl: function(indexPath) {
  var element = this.GetItemContentElement(indexPath);
  if(element != null && element.tagName === "A")
   return ASPx.Attr.GetAttribute(element, "savedhref") || element.href;
  if(element != null) {
   var link = ASPx.GetNodeByTagName(element, "A", 0);
   if(link != null)
    return ASPx.Attr.GetAttribute(link, "savedhref") || link.href;
  }
  return "";
 },
 SetUrl: function(link, url, target) {
  if(link != null) {
   if(ASPx.Attr.IsExistsAttribute(link, "savedhref"))
    ASPx.Attr.SetAttribute(link, "savedhref", url);
   else if(ASPx.Attr.IsExistsAttribute(link, "href"))
    link.href = url;
   if(!!target)
    link.target = target;
  }
 },
 SetItemNavigateUrl: function(indexPath, url, target) {
  var element = this.GetItemContentElement(indexPath);
  if(element != null) {
   if(element.tagName === "A")
    this.SetUrl(element, url, target);
   else {
    this.SetUrl(ASPx.GetNodeByTagName(element, "A", 0), url, target);
    this.SetUrl(ASPx.GetNodeByTagName(element, "A", 1), url, target);
   }
  }
 },
 FindTextNode: function(indexPath) {
  var contentElement = this.GetItemContentElement(indexPath);
  if(contentElement) {
   var link = this.GetLinkElementByIndexPath(indexPath);
   if(link)
    return ASPx.GetNormalizedTextNode(link);
   var textElement = this.GetContentTextElement(contentElement);
   if(textElement)
    return ASPx.GetNormalizedTextNode(textElement);
   return ASPx.GetNormalizedTextNode(contentElement);
  }
  return null;
 },
 GetContentTextElement: function(contentElement) {
  return ASPx.GetChildByClassName(contentElement, MenuCssClasses.ItemTextElement, 0);
 },
 GetItemText: function(indexPath) {
  var textNode = this.FindTextNode(indexPath);
  return textNode
   ? ASPx.Str.Trim(textNode.nodeValue) 
   : "";
 },
 SetItemText: function(indexPath, text) {
  var textNode = this.FindTextNode(indexPath);
  if(textNode) {
   textNode.nodeValue = text;
   var menuElement = this.GetMenuElement(this.GetParentIndexPath(indexPath));
   if(menuElement && (!this.IsRootItem(indexPath) || this.isPopupMenu))
    this.renderHelper.CalculateSubMenu(menuElement, true);
   if(this.IsRootItem(indexPath) && !this.isPopupMenu) {
    var itemElement = this.GetItemElement(indexPath);
    if(itemElement)
     this.renderHelper.CalculateItemMinSize(itemElement, true);
   }
   this.AdjustControl();
  }
 },
 SetItemTextTemplate: function(indexPath, textTemplate) {
  var contentElement = this.GetItemContentElement(indexPath);
  var textElement = this.GetContentTextElement(contentElement);
  if(textElement) {
   var container = document.createElement("DIV");
   container.innerHTML = textTemplate;
   contentElement.replaceChild(container.firstChild, textElement);
  }
 },
 SetItemTooltip: function(indexPath, tooltip) {
  var itemElement = this.GetItemElement(indexPath);
  if(itemElement && tooltip)
   itemElement.title = tooltip;
 },
 SetItemVisible: function(indexPath, visible, initialization) {
  var item = this.GetItemByIndexPath(indexPath);
  if(indexPath == "" || !item.visible) return;
  if(visible && initialization) return;
  var element = this.GetItemElement(indexPath);
  if(element != null)
   this.SetElementDisplay(element, visible);
  this.SetIndentsVisiblility(indexPath);
  var parentIndexPath = this.GetParentIndexPath(indexPath);
  if(this.isPopupMenu && this.inPopUpHandler)
   this.postponeSetItemVisible(parentIndexPath);
  else
   this.SetSeparatorsVisiblility(parentIndexPath);
  if(!this.IsItemInAdaptiveMenu(item))
   this.UpdateItemCssClasses(indexPath, visible);
  var parent = this.GetItemByIndexPath(indexPath).parent;
  var parentHasVisibleItems = this.HasVisibleItems(parent);
  if(this.IsRootItem(indexPath) && !this.isPopupMenu) {
   if(this.clientVisible)
    this.SetElementDisplay(this.GetMainElement(), parentHasVisibleItems);
  }
  else
   this.SetPopOutElementVisible(parent.indexPath, parentHasVisibleItems);
  if(this.GetMenuLevel(parentIndexPath) !== 0 || this.isPopupMenu && !this.inPopUpHandler)
   this.calculateSubMenuByIndexPath(parentIndexPath);
  if(this.IsRootItem(indexPath) && !this.isPopupMenu) 
   this.renderHelper.CalculateMenuControl(this.GetMainElement(), true);
 },
 SetElementDisplay: function (element, visible) {
  ASPx.SetElementDisplay(element, visible);
 },
 prepareSideMenuCssClasses: function(addClass) {
  if(this.sideMenuModeOn) {
   this.MarkPrecedingItemCore(this.GetSelectedItemIndexPath(), PRE_SELECTED_ELEMENT_CLASS_NAME, addClass, false);
   if(this.hoverItemName)
    this.MarkPrecedingItemCore(this.hoverItemName, PRE_HOVERED_ELEMENT_CLASS_NAME, addClass, true);
  }
 },
 calculateSubMenuByIndexPath: function(indexPath) {
  var menuElement = this.GetMenuElement(indexPath);
  if(menuElement)
   this.renderHelper.CalculateSubMenu(menuElement, true);
 },
 postponeSetItemVisible: function(indexPath) {
  if(!this.postponedIndexPath)
   this.postponedIndexPath = [];
  for(var i = 0; i < this.postponedIndexPath.length; i++) {
   if(this.postponedIndexPath[i] === indexPath)
    return;
  }
  this.postponedIndexPath.push(indexPath);
 },
 postponedSetItemVisible: function() {
  if(!!this.postponedIndexPath && this.postponedIndexPath.length > 0)
   ASPx.Data.ForEach(this.postponedIndexPath, function(indexPath) {
    this.SetSeparatorsVisiblility(indexPath);
    this.calculateSubMenuByIndexPath(indexPath);
   }.aspxBind(this));
  this.postponedIndexPath = [];
 },
 SetIndentsVisiblility: function(indexPath) {
  var parent = this.GetItemByIndexPath(indexPath).parent;
  for(var i = 0; i < parent.GetItemCount(); i++) {
   var item = parent.GetItem(i);
   var separatorVisible = this.HasPrevVisibleItems(parent, i) && item.GetVisible();
   var element = this.GetItemIndentElement(item.GetIndexPath());
   if(element != null) ASPx.SetElementDisplay(element, separatorVisible);
  }
 },
 SetSeparatorsVisiblility: function(indexPath) {
  var parent = this.GetItemByIndexPath(indexPath);
  for(var i = 0; i < parent.GetItemCount(); i++) {
   var item = parent.GetItem(i);
   var separatorVisible = this.HasPrevVisibleItems(parent, i) && (item.GetVisible() || this.HasNextVisibleItemInGroup(parent, i));
   var element = this.GetItemSeparatorElement(item.GetIndexPath());
   if(element != null) ASPx.SetElementDisplay(element, separatorVisible);
  }
 },
 UpdateItemCssClasses: function(indexPath, visible) {
 },
 SetPopOutElementVisible: function(indexPath, visible) {
  var popOutElement = this.GetItemPopOutElement(indexPath);
  if(popOutElement)
   popOutElement.style.display = visible ? 'block' : 'none';
 },
 GetPrevVisibleItemInGroup: function(parent, index, skipItemsInAdaptiveMenu) {
  if(this.IsItemBeginsGroup(parent.GetItem(index)))
   return null;
  for(var i = index - 1; i >= 0; i--) {
   var item = parent.GetItem(i);
   if(item.GetVisible() && !this.IsAdaptiveItem(item.indexPath) && (!skipItemsInAdaptiveMenu || !this.IsItemInAdaptiveMenu(item)))
    return item;
   if(this.IsItemBeginsGroup(item))
    return null;
  }
  return null;
 },
 GetNextVisibleItemInGroup: function(parent, index, skipItemsInAdaptiveMenu) {
  for(var i = index + 1; i < parent.GetItemCount(); i++) {
   var item = parent.GetItem(i);
   if(this.IsItemBeginsGroup(item))
    return null;
   if(item.GetVisible() && !this.IsAdaptiveItem(item.indexPath) && (!skipItemsInAdaptiveMenu || !this.IsItemInAdaptiveMenu(item)))
    return item;
  }
  return null;
 },
 HasNextVisibleItemInGroup: function(parent, index, skipItemsInAdaptiveMenu) {
  return !!this.GetNextVisibleItemInGroup(parent, index, skipItemsInAdaptiveMenu);
 },
 IsItemBeginsGroup: function(item) {
  var itemSeparator = this.GetItemSeparatorElement(item.GetIndexPath());
  return itemSeparator && ASPx.ElementContainsCssClass(itemSeparator, this.getSeparatorCssClass());
 },
 getSeparatorCssClass: function() {
  return MenuCssClasses.Separator;
 },
 getAdaptiveMenuItemCssClass: function() {
  return MenuCssClasses.AdaptiveMenuItem;
 },
 getAdaptiveMenuItemSpacingCssClass: function() {
  return MenuCssClasses.AdaptiveMenuItemSpacing;
 },
 getAdaptiveMenuCssClass: function() {
  return MenuCssClasses.AdaptiveMenu;
 },
 IsItemInAdaptiveMenu: function(item) {
  return this.enableAdaptivity ? this.renderHelper.IsItemInAdaptiveMenu(item.index) : false;
 },
 HasVisibleItems: function(parent) {
  for(var i = 0; i < parent.GetItemCount() ; i++) {
   if(parent.GetItem(i).GetVisible())
    return true;
  }
  return false;
 },
 HasNextVisibleItems: function(parent, index, skipItemsInAdaptiveMenu) {
  for(var i = index + 1; i < parent.GetItemCount() ; i++) {
   var item = parent.GetItem(i);
   if(item.GetVisible() && (!skipItemsInAdaptiveMenu || !this.IsItemInAdaptiveMenu(item)))
    return true;
  }
  return false;
 },
 HasPrevVisibleItems: function(parent, index, skipItemsInAdaptiveMenu) {
  for(var i = index - 1; i >= 0; i--) {
   var item = parent.GetItem(i);
   if(item.GetVisible() && (!skipItemsInAdaptiveMenu || !this.IsItemInAdaptiveMenu(item)))
    return true;
  }
  return false;
 },
 NeedCollapseControlCore: function() {
  return this.enableAdaptivity || ASPxClientControl.prototype.NeedCollapseControlCore.call(this);
 },
 GetItemIndentElement: function(indexPath) {
  return ASPx.GetElementById(this.GetItemIndentElementId(indexPath));
 },
 GetItemSeparatorElement: function(indexPath) {
  return ASPx.GetElementById(this.GetItemSeparatorElementId(indexPath));
 },
 CreateItemClickEventArgs: function(processOnServer, item, htmlElement, htmlEvent) {
  return new ASPxClientMenuItemClickEventArgs(processOnServer, item, htmlElement, htmlEvent);
 },
 CreateItemMouseEventArgs: function(item, htmlElement) {
  return new ASPxClientMenuItemMouseEventArgs(item, htmlElement);
 },
 CreateItemEventArgs: function(item) {
  return new ASPxClientMenuItemEventArgs(item);
 },
 RaiseItemClick: function(indexPath, htmlEvent) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned("ItemClick");
  if(!this.ItemClick.IsEmpty()) {
   var item = this.GetItemByIndexPath(indexPath);
   var htmlElement = this.GetItemElement(indexPath);
   var args = this.CreateItemClickEventArgs(processOnServer, item, htmlElement, htmlEvent);
   this.ItemClick.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 RaiseItemMouseOver: function(indexPath) {
  if(!this.ItemMouseOver.IsEmpty()) {
   var item = this.GetItemByIndexPath(indexPath);
   var htmlElement = this.GetItemContentElement(indexPath);
   var args = this.CreateItemMouseEventArgs(item, htmlElement);
   this.ItemMouseOver.FireEvent(this, args);
  }
 },
 RaiseItemMouseOut: function(indexPath) {
  if(!this.ItemMouseOut.IsEmpty()) {
   var item = this.GetItemByIndexPath(indexPath);
   var htmlElement = this.GetItemContentElement(indexPath);
   var args = this.CreateItemMouseEventArgs(item, htmlElement);
   this.ItemMouseOut.FireEvent(this, args);
  }
 },
 RaisePopUp: function(indexPath) {
  var item = this.GetItemByIndexPath(indexPath);
  if(!this.PopUp.IsEmpty()) {
   var args = this.CreateItemEventArgs(item);
   this.inPopUpHandler = true;
   this.PopUp.FireEvent(this, args);
   this.inPopUpHandler = false;
   this.postponedSetItemVisible();
  }
 },
 RaiseCloseUp: function(indexPath) {
  var item = this.GetItemByIndexPath(indexPath);
  if(!this.CloseUp.IsEmpty()) {
   var args = this.CreateItemEventArgs(item);
   this.CloseUp.FireEvent(this, args);
  }
 },
 SetEnabled: function(enabled) {
  for(var i = this.GetItemCount() - 1; i >= 0; i--) {
   var item = this.GetItem(i);
   item.SetEnabled(enabled);
  }
 },
 SetVisible: function(visible) {
  ASPxClientControl.prototype.SetVisible.call(this, visible);
  if(visible && !this.HasVisibleItems(this))
   ASPx.SetElementDisplay(this.GetMainElement(), false);
 },
 GetItemCount: function() {
  return (this.rootItem != null) ? this.rootItem.GetItemCount() : 0;
 },
 GetItem: function(index) {
  return (this.rootItem != null) ? this.rootItem.GetItem(index) : null;
 },
 GetItemByName: function(name) {
  return (this.rootItem != null) ? this.rootItem.GetItemByName(name) : null;
 },
 GetSelectedItem: function() {
  var indexPath = this.GetSelectedItemIndexPath();
  if(indexPath != "")
   return this.GetItemByIndexPath(indexPath);
  return null;
 },
 SetSelectedItem: function(item) {
  var indexPath = (item != null) ? item.GetIndexPath() : "";
  this.SetSelectedItemInternal(indexPath, false);
 },
 GetRootItem: function() {
  return this.rootItem;
 }
});
ASPxClientMenuBase.GetMenuCollection = function() {
 return aspxGetMenuCollection();
};
var ASPxMenuKeyboardHelper = ASPx.CreateClass(null, {
 constructor: function(menu) {
  this.menu = menu;
  this.accessibilityCompliant = menu.accessibilityCompliant;
  this.isContextMenu = menu.isContextMenu;
  this.rtl = menu.rtl;
 },
 OnFocusedItemKeyDown: function(evt, focusedItem) {
  var indexPath = this.menu.GetItemIndexPathById(focusedItem.name);
  if(!this.IsAllowedItemAction(evt, focusedItem.enabled, indexPath))
   ASPx.Evt.PreventEventAndBubble(evt);
  else
   this.OnFocusedItemKeyDownInternal(evt, indexPath);
 },
 OnFocusedItemKeyDownInternal: function(evt, indexPath) {
  if(!indexPath)
   return;
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  switch(keyCode) {
   case ASPx.Key.Tab:
    this.OnTab(indexPath, evt);
    break;
   case ASPx.Key.Down:
    this.OnArrowDown(indexPath, evt);
    break;
   case ASPx.Key.Up:
    this.OnArrowUp(indexPath, evt);
    break;
   case ASPx.Key.Left:
    if(this.rtl)
     this.OnArrowRight(indexPath, evt);
    else
     this.OnArrowLeft(indexPath, evt);
    break;
   case ASPx.Key.Right:
    if(this.rtl)
     this.OnArrowLeft(indexPath, evt);
    else
     this.OnArrowRight(indexPath, evt);
    break;
   case ASPx.Key.Esc:
    this.OnEscape(indexPath, evt);
    break;
   case ASPx.Key.Space: break;
   case ASPx.Key.Enter: break;
   case ASPx.Key.Shift: break;
   case ASPx.Key.Alt: break;
   case ASPx.Key.Ctrl: break;
   default:
    ASPx.Evt.PreventEventAndBubble(evt);
    break;
  }
 },
 OnTab: function(indexPath, evt) {
  var isRootItem = this.IsRootItem(indexPath);
  if(isRootItem && !this.accessibilityCompliant) return;
  if(this.IsLostFocus(indexPath, evt))
   this.menu.ProcessLostFocus(evt);
  else
   this.ProcessTab(indexPath, evt);
 },
 ProcessTab: function(indexPath, evt) {
  if(this.IsRootItem(indexPath))
   this.FocusRootItem(indexPath, evt);
  else
   this.FocusSubmenuItem(indexPath, evt);
 },
 OnArrowDown: function(indexPath, evt) {
  if(this.menu.IsVertical(indexPath))
   this.FocusNextItem(indexPath);
  else
   this.ShowSubMenuAccessible(indexPath);
  ASPx.Evt.PreventEventAndBubble(evt);
 },
 OnArrowUp: function(indexPath, evt) {
  if(this.menu.IsVertical(indexPath))
   this.FocusPrevItem(indexPath);
  else
   this.ShowSubMenuAccessible(indexPath);
  ASPx.Evt.PreventEventAndBubble(evt);
 },
 OnArrowLeft: function(indexPath, evt) {
  var isVertical = this.menu.IsVertical(indexPath);
  if(isVertical) {
   var isRootItem = this.IsRootItem(indexPath);
   if(isRootItem)
    this.FocusPrevItem(indexPath);
   else
    this.FocusItemByIndexPathAccessible(this.GetLeftParentIndexPath(indexPath));
  } else
   this.FocusPrevItem(indexPath);
  ASPx.Evt.PreventEventAndBubble(evt);
 },
 OnArrowRight: function(indexPath, evt) {
  var isVertical = this.menu.IsVertical(indexPath);
  if(isVertical) {
   var hasChildren = this.menu.HasChildren(indexPath);
   if(hasChildren)
    this.ShowSubMenuAccessible(indexPath);
   else
    this.FocusItemByIndexPathAccessible(this.GetRightRootParentIndexPath(indexPath));
  }
  else
   this.FocusNextItem(indexPath);
  ASPx.Evt.PreventEventAndBubble(evt);
 },
 OnEscape: function(indexPath, evt) {
  var needPreventEvent = true;
  if(this.IsRootItem(indexPath)) {
   aspxGetMenuCollection().DoHidePopupMenus(null, -1, this.name, false, "");
   this.menu.ProcessLostFocus(evt);
  }
  else {
   var parentIndexPath = this.menu.GetParentIndexPath(indexPath);
   this.FocusItemByIndexPathAccessible(parentIndexPath);
   var element = this.menu.GetMenuElement(parentIndexPath);
   if(element != null)
    this.menu.DoHidePopupMenu(null, element);
   else
    needPreventEvent = false;
  }
  if(needPreventEvent)
   ASPx.Evt.PreventEventAndBubble(evt);
 },
 IsLostFocus: function(indexPath, evt) {
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  var isRootItem = this.IsRootItem(indexPath); 
  if(keyCode !== ASPx.Key.Tab || !isRootItem)
   return false;
  var canPrevItemGetFocus = evt.shiftKey && this.GetPrevSiblingIndexPath(indexPath);
  var canNextItemGetFocus = !evt.shiftKey && this.GetNextSiblingIndexPath(indexPath);
  return !canPrevItemGetFocus && !canNextItemGetFocus;
 },
 FocusRootItem: function(indexPath, evt) {
  if(evt.shiftKey)
   this.FocusPrevItem(indexPath, evt);
  else
   this.FocusNextItem(indexPath, evt);
  var isFocusElementChanged = ASPx.Evt.GetEventSource(evt) !== document.activeElement;
  if(isFocusElementChanged)
   ASPx.Evt.PreventEventAndBubble(evt);
 },
 FocusSubmenuItem: function(indexPath, evt) {
  if(evt.shiftKey)
   this.FocusPreviousSubmenuItem(indexPath, evt);
  else
   this.FocusNextSubmenuItem(indexPath, evt);
 },
 FocusPreviousSubmenuItem: function(indexPath, evt) {
  if(!this.GetPrevSiblingIndexPath(indexPath)) {
   var parentIndexPath = this.menu.GetParentIndexPath(indexPath);
   this.FocusItemByIndexPathAccessible(parentIndexPath);
  } else
   this.FocusPrevItem(indexPath);
  ASPx.Evt.PreventEventAndBubble(evt);
 },
 FocusNextSubmenuItem: function(indexPath, evt) {
  var nextIndexPath = this.GetNextIndexPath(indexPath);
  if(nextIndexPath) {
   var isLevelChanged = this.IsLevelChanged(indexPath, nextIndexPath);
   this.FocusItemCore(nextIndexPath, isLevelChanged); 
   ASPx.Evt.PreventEventAndBubble(evt);
  } else
   this.menu.ProcessLostFocus(evt);
 },
 GetNextIndexPath: function(indexPath) {
  var result = this.GetNextSiblingIndexPath(indexPath);
  if(!result) {
   var parentIndexPath = this.menu.GetParentIndexPath(indexPath);
   if(parentIndexPath)
    result = this.GetNextIndexPath(parentIndexPath);
  }
  return result;
 },
 GetRightRootParentIndexPath: function(indexPath) {
  var parentIndexPath = this.GetParentRootIndexPath(indexPath);
  return this.GetNextFocusableItemIndexPath(parentIndexPath);
 },
 GetLeftParentIndexPath: function(indexPath) {
  var parentIndexPath = this.menu.GetParentIndexPath(indexPath);
  if(!this.menu.IsVertical(parentIndexPath))
   parentIndexPath = this.GetPrevFocusableItemIndexPath(parentIndexPath);
  return parentIndexPath;
 },
 GetParentRootIndexPath: function(indexPath) {
  while(!this.IsRootItem(indexPath))
   indexPath = this.menu.GetParentIndexPath(indexPath);
  return indexPath;
 },
 ShowSubMenuAccessible: function(indexPath) {
  var newIndexPath = this.GetFirstChildIndexPath(indexPath),
   element = this.menu.GetMenuElement(indexPath);
  if(element && !this.menu.isSubMenuElementVisible(element))
   this.menu.ShowSubMenu(indexPath);
  if(!!newIndexPath)
   this.FocusItemByIndexPathAccessible(newIndexPath);
 },
 FocusItemByIndexPathAccessible: function(indexPath) {
  this.FocusItemCore(indexPath, true);
 },
 IsAllowedItemAction: function(evt, isEnabled, indexPath) {
  var isVertical = this.menu.IsVertical(indexPath);
  return !this.accessibilityCompliant ||
      isEnabled ||
      this.IsAllowedFocusMoving(evt) ||
      this.IsAllowedHorizontalFocusMoving(evt, isVertical) ||
      this.IsAllowedVerticalFocusMoving(evt, isVertical);
 },
 IsAllowedFocusMoving: function(evt) {
  return evt.keyCode == ASPx.Key.Tab || evt.keyCode == ASPx.Key.Esc;
 },
 IsAllowedHorizontalFocusMoving: function(evt, isVertical) {
  return !isVertical && (evt.keyCode == ASPx.Key.Left || evt.keyCode == ASPx.Key.Right);
 },
 IsAllowedVerticalFocusMoving: function(evt, isVertical) {
  return isVertical && (evt.keyCode == ASPx.Key.Up || evt.keyCode == ASPx.Key.Down);
 },
 FocusItemByIndexPath: function(indexPath) {
  var link = this.menu.GetLinkElementByIndexPath(indexPath);
  if(link != null) {
   if(this.accessibilityCompliant && !link.href)
    link.href = ASPx.AccessibilityEmptyUrl;
   ASPx.SetFocus(link);
  } else
   this.FocusTemplateItemActionElement(indexPath);
 },
 FocusTemplateItemActionElement: function(indexPath) {
  var element = this.menu.GetItemElement(indexPath);
  var focusableElement = ASPx.FindFirstChildActionElement(element);
  if(focusableElement)
   ASPx.SetFocus(focusableElement);
  else {
   var parentIndexPath = this.menu.GetParentIndexPath(indexPath);
   this.tryFocusColorPickerByIndexPath(parentIndexPath);
  }
 },
 tryFocusColorPickerByIndexPath: function(indexPath) {
  var colorPicker = this.getColorPickerByIndexPath(indexPath);
  if(colorPicker)
   colorPicker.Focus();
 },
 getColorPickerByIndexPath: function(indexPath) {
  var menuItem = this.menu.GetItemByIndexPath(indexPath);
  return menuItem.colorPicker;
 },
 PronounceItemDescription: function(indexPath) {
  var link = this.menu.GetLinkElementByIndexPath(indexPath);
  var span = ASPx.GetNodeByTagName(link, "SPAN", 0);
  if(!link) return;
  if(!!span && !span.id) {
   var spanID = this.GetAccessibilityTextSpanID(indexPath);
   span.id = spanID;
   ASPx.Attr.SetAttribute(link, "aria-describedby", spanID);
  }
  ASPx.Attr.SetAttribute(link, "aria-label", this.GetAccessibilityItemDescription(indexPath));
 },
 RemoveAccessibilityDescription: function(indexPath) {
  var link = this.menu.GetLinkElementByIndexPath(indexPath);
  if(link && ASPx.Attr.GetAttribute(link, "aria-label"))
   ASPx.Attr.RemoveAttribute(link, "aria-label");
 },
 GetAccessibilityTextSpanID: function(indexPath) {
  return this.name + Constants.ATSIdSuffix + indexPath;
 },
 GetAccessibilityItemDescription: function(indexPath) {
  var descriptionParts = [];
  descriptionParts.push(this.menu.IsVertical(indexPath) ? ASPx.AccessibilitySR.MenuVerticalText : ASPx.AccessibilitySR.MenuHorizontalText);
  descriptionParts.push(this.IsRootItem(indexPath) ? ASPx.AccessibilitySR.MenuBarText : ASPx.AccessibilitySR.MenuText);
  descriptionParts.push(this.menu.GetMenuLevel(indexPath));
  descriptionParts.push(ASPx.AccessibilitySR.MenuLevelText);
  return descriptionParts.join(' ');
 },
 FocusNextItem: function(indexPath) {
  var newIndexPath = this.GetNextFocusableItemIndexPath(indexPath);
  if(newIndexPath)
   this.FocusItemCore(newIndexPath, false);
 },
 FocusPrevItem: function(indexPath) {
  var newIndexPath = this.GetPrevFocusableItemIndexPath(indexPath);
  if(newIndexPath)
   this.FocusItemCore(newIndexPath, false);
 },
 FocusItemCore: function(indexPath, needDescription) {
  if(this.accessibilityCompliant) {
   if(needDescription)
    this.PronounceItemDescription(indexPath);
   else
    this.RemoveAccessibilityDescription(indexPath);
  }
  this.FocusItemByIndexPath(indexPath);
 },
 GetNextFocusableItemIndexPath: function(indexPath) {
  var newIndexPath = this.GetNextSiblingIndexPath(indexPath);
  if(newIndexPath == null)
   newIndexPath = this.GetFirstSiblingIndexPath(indexPath);
  if(indexPath != newIndexPath)
   return newIndexPath;
 },
 GetPrevFocusableItemIndexPath: function(indexPath) {
  var newIndexPath = this.GetPrevSiblingIndexPath(indexPath);
  if(newIndexPath == null)
   newIndexPath = this.GetLastSiblingIndexPath(indexPath);
  if(indexPath != newIndexPath)
   return newIndexPath;
 },
 GetFirstChildIndexPath: function(indexPath) {
  var indexes = this.menu.GetItemIndexes(indexPath);
  indexes[indexes.length] = 0;
  var newIndexPath = this.menu.GetItemIndexPath(indexes);
  return this.GetFirstSiblingIndexPath(newIndexPath);
 },
 GetFirstSiblingIndexPath: function(indexPath) {
  var indexes = this.menu.GetItemIndexes(indexPath);
  var i = 0;
  while(true) {
   indexes[indexes.length - 1] = i;
   var newIndexPath = this.menu.GetItemIndexPath(indexes);
   if(!this.IsItemExist(newIndexPath))
    return null;
   if(this.IsFocusableItem(newIndexPath))
    return newIndexPath;
   i++;
  }
  return null;
 },
 GetLastSiblingIndexPath: function(indexPath) {
  var indexes = this.menu.GetItemIndexes(indexPath);
  var parentItem = this.menu.GetItemByIndexPath(this.menu.GetParentIndexPath(indexPath));
  var i = parentItem ? parentItem.GetItemCount() - 1 : 0;
  while(true) {
   indexes[indexes.length - 1] = i;
   var newIndexPath = this.menu.GetItemIndexPath(indexes);
   if(!this.IsItemExist(newIndexPath))
    return null;
   if(this.IsFocusableItem(newIndexPath))
    return newIndexPath;
   i--;
  }
  return null;
 },
 GetNextSiblingIndexPath: function(indexPath) {
  if(this.menu.IsLastItem(indexPath)) return null;
  var indexes = this.menu.GetItemIndexes(indexPath);
  var i = indexes[indexes.length - 1] + 1;
  while(true) {
   indexes[indexes.length - 1] = i;
   var newIndexPath = this.menu.GetItemIndexPath(indexes);
   if(!this.IsItemExist(newIndexPath))
    return null;
   if(this.IsFocusableItem(newIndexPath))
    return newIndexPath;
   i++;
  }
  return null;
 },
 GetPrevSiblingIndexPath: function(indexPath) {
  if(this.menu.IsFirstItem(indexPath)) return null;
  var indexes = this.menu.GetItemIndexes(indexPath);
  var i = indexes[indexes.length - 1] - 1;
  while(true) {
   indexes[indexes.length - 1] = i;
   var newIndexPath = this.menu.GetItemIndexPath(indexes);
   if(!this.IsItemExist(newIndexPath))
    return null;
   if(this.IsFocusableItem(newIndexPath))
    return newIndexPath;
   i--;
  }
  return null;
 },
 IsItemExist: function(indexPath) {
  return !!this.menu.GetItemByIndexPath(indexPath);
 },
 IsItemVisible: function(indexPath) {
  var item = this.menu.GetItemByIndexPath(indexPath);
  return item ? item.GetVisible() : false;
 },
 IsFocusableItem: function(indexPath) {
  return this.IsItemVisible(indexPath) && (this.menu.IsItemEnabled(indexPath) || this.IsItemAccessibleEnabled(indexPath));
 },
 IsRootItem: function(indexPath) {
  return this.menu.IsRootItem(indexPath);
 },
 IsItemAccessibleEnabled: function(indexPath) {
  var item = this.menu.GetItemByIndexPath(indexPath);
  return this.accessibilityCompliant && item && item.enabled;
 },
 IsLevelChanged: function(firstIndexPath, secondIndexPath) {
  return this.menu.GetMenuLevel(firstIndexPath) !== this.menu.GetMenuLevel(secondIndexPath);
 }
});
var ASPxClientMenuCollection = ASPx.CreateClass(ASPxClientControlCollection, {
 constructor: function() {
  this.constructor.prototype.constructor.call(this);
  this.appearTimerID = -1;
  this.disappearTimerID = -1;
  this.currentShowingPopupMenuName = null;
  this.visibleSubMenusMenuName = "";
  this.visibleSubMenuIds = [];
  this.overXPos = -1;
  this.overYPos = -1;
 },
 GetCollectionType: function(){
  return "Menu";
 },
 Remove: function(element) {
  if(element.name === this.visibleSubMenusMenuName) {
   this.visibleSubMenusMenuName = "";
   this.visibleSubMenuIds = [ ];
  }
  ASPxClientControlCollection.prototype.Remove.call(this, element);
 },
 RegisterVisiblePopupMenu: function(name, id) {
  this.visibleSubMenuIds.push(id);
  this.visibleSubMenusMenuName = name;
 },
 UnregisterVisiblePopupMenu: function(name, id) {
  ASPx.Data.ArrayRemove(this.visibleSubMenuIds, id);
  if(this.visibleSubMenuIds.length == 0)
   this.visibleSubMenusMenuName = "";
 },
 IsSubMenuVisible: function(subMenuId) {
  for(var i = 0; i < this.visibleSubMenuIds.length; i++) {
   if(this.visibleSubMenuIds[i] == subMenuId)
    return true;
  }
  return false;
 },
 GetMenu: function(id) {
  return this.Get(this.GetMenuName(id));
 },
 GetMenuName: function(id) {
  return this.GetMenuNameBySuffixes(id, [Constants.MMIdSuffix, Constants.MIIdSuffix]);
 },
 GetMenuNameBySuffixes: function(id, idSuffixes) {
  for(var i = 0; i < idSuffixes.length; i++) {
   var pos = id.lastIndexOf(idSuffixes[i]);
   if(pos > -1)
    return id.substring(0, pos);
  }
  return id;
 },
 ClearCurrentShowingPopupMenuName: function() {
  this.SetCurrentShowingPopupMenuName(null);
 },
 SetCurrentShowingPopupMenuName: function(value) {
  this.currentShowingPopupMenuName = value;
 },
 NowPopupMenuIsShowing: function() {
  return this.currentShowingPopupMenuName != null;
 },
 GetMenuLevelById: function(id) {
  var indexPath = this.GetIndexPathById(id, Constants.MMIdSuffix);
  var menu = this.GetMenu(id);
  return menu.GetMenuLevel(indexPath);
 },
 GetIndexPathById: function(id, idSuffix) {
  var pos = id.lastIndexOf(idSuffix);
  if(pos > -1) {
   id = id.substring(pos + idSuffix.length);
   pos = id.lastIndexOf("_");
   if(pos > -1)
    return id.substring(0, pos);
  }
  return "";
 },
 GetItemIndexPath: function(indexes) {
  var indexPath = "";
  for(var i = 0; i < indexes.length; i++) {
   indexPath += indexes[i];
   if(i < indexes.length - 1)
    indexPath += ASPx.ItemIndexSeparator;
  }
  return indexPath;
 },
 GetItemIndexes: function(indexPath) {
  var indexes = indexPath.split(ASPx.ItemIndexSeparator);
  for(var i = 0; i < indexes.length; i++)
   indexes[i] = parseInt(indexes[i]);
  return indexes;
 },
 ClearAppearTimer: function() {
  this.appearTimerID = ASPx.Timer.ClearTimer(this.appearTimerID);
 },
 ClearDisappearTimer: function() {
  this.disappearTimerID = ASPx.Timer.ClearTimer(this.disappearTimerID);
 },
 IsAppearTimerActive: function() {
  return this.appearTimerID > -1;
 },
 IsDisappearTimerActive: function() {
  return this.disappearTimerID > -1;
 },
 SetAppearTimer: function(name, indexPath, timeout, preventSubMenu) {
  var menu = aspxGetMenuCollection().Get(name);
  if(menu && !menu.sideMenuModeOn)
   this.appearTimerID = window.setTimeout(function() {
    var menu = aspxGetMenuCollection().Get(name);
    if(menu != null) menu.OnItemOverTimer(indexPath, preventSubMenu);
   }, timeout);
 },
 SetDisappearTimer: function(name, timeout) {
  var menu = aspxGetMenuCollection().Get(name);
  if(menu && !menu.sideMenuModeOn)
   this.disappearTimerID = window.setTimeout(function() {
    var menu = aspxGetMenuCollection().Get(name);
    if(menu != null)
     menu.OnItemOutTimer();
   }, timeout);
 },
 GetMouseDownMenuLevel: function(evt) {
  var srcElement = ASPx.Evt.GetEventSource(evt);
  for(var i = this.visibleSubMenuIds.length - 1; i >= 0; i--) {
   var element = ASPx.GetParentById(srcElement, this.visibleSubMenuIds[i]);
   var menu = this.GetMenu(this.visibleSubMenuIds[i]); 
   if(element != null || srcElement == menu.mainElement)
    return this.GetMenuLevelById(this.visibleSubMenuIds[i]) + 1;
  }
  if(this.visibleSubMenusMenuName != "") {
   var element = ASPx.GetParentById(srcElement, this.visibleSubMenusMenuName);
   if(element != null) return 1;
  }
  if(ASPx.GetParentByClassName(srcElement, MenuCssClasses.AdaptiveMenuItem))
   return 1;
  return -1;
 },
 CheckFocusedElement: function() {
  var isValid = false;
  try {
   var activeElement = document.activeElement;
   if(activeElement != null) {
    for(var i = 0; i < this.visibleSubMenuIds.length; i++) {
     var menuElement = ASPx.GetElementById(this.visibleSubMenuIds[i]);
     if(menuElement != null && ASPx.GetIsParent(menuElement, activeElement)) {
      var tagName = activeElement.tagName;
      if(tagName != "A" || 
         !ASPx.ElementHasCssClass(activeElement, MenuCssClasses.ContentContainer) || 
         this.GetMenu(this.visibleSubMenusMenuName).accessibilityCompliant)
          isValid = true;
      break;
     }
    }
   }
  } catch (e) {
  }
  return isValid;
 },
 LockMenusVisibility: function() {
  this.visibilityLocked = true;
  this.visibilityLockedIds = [];
  for(var i = this.visibleSubMenuIds.length - 1; i >= 0 ; i--)
   this.visibilityLockedIds.push(this.visibleSubMenuIds[i]);
 },
 UnlockMenusVisibility: function() {
  this.visibilityLocked = false;
  this.visibilityLockedIds = [];
 },
 CanHideSubMenu: function(subMenuId) {
  return !this.visibilityLocked || this.visibilityLocked && this.visibilityLockedIds.indexOf(subMenuId) > -1;
 },
 DoHidePopupMenus: function(evt, level, name, leavePopups, exceptIds) {
  exceptIds = typeof exceptIds === 'string' ? [exceptIds] : (exceptIds || []);
  for(var i = this.visibleSubMenuIds.length - 1; i >= 0 ; i--) {
   var subMenuId = this.visibleSubMenuIds[i];
   if(this.CanHideSubMenu(subMenuId)) {
    var menu = this.GetMenu(subMenuId);
    if(menu != null && !menu.sideMenuModeOn) {
     var menuLevel = this.GetMenuLevelById(subMenuId);
     if((!leavePopups || menuLevel > 0) && ASPx.Data.ArrayIndexOf(exceptIds, subMenuId) === -1) {
      if(menuLevel > level || (menu.name != name && name != "")) {
       var element = ASPx.GetElementById(subMenuId);
       if(element != null)
        menu.DoHidePopupMenu(evt, element);
      }
     }
    }
   }
  }
 },
 DoShowAtCurrentPos: function(name, indexPath) {
  var pc = this.Get(name);
  var element = pc.GetMainElement();
  if(pc != null && !ASPx.GetElementDisplay(element))
   pc.DoShowPopupMenu(element, this.overXPos, this.overYPos, indexPath);
 },
 SaveCurrentMouseOverPos: function(evt, popupElement) {
  if(!this.NowPopupMenuIsShowing()) return;
  var currentShowingPopupMenu = this.Get(this.currentShowingPopupMenuName);
  if(currentShowingPopupMenu.popupElement == popupElement)
   if(!currentShowingPopupMenu.IsMenuVisible()) {
    this.overXPos = ASPx.Evt.GetEventX(evt);
    this.overYPos = ASPx.Evt.GetEventY(evt);
   }
 },
 OnMouseDown: function(evt) {
  var menuLevel = this.GetMouseDownMenuLevel(evt);
  this.DoHidePopupMenus(evt, menuLevel, "", false, "");
  if (ASPx.Browser.TouchUI && menuLevel == -1) 
   ASPx.SetHoverState(null);
 },
 RecalculateAll: function() {
  var visibleSubMenusLength = this.visibleSubMenuIds.length;
  for(var i = 0; i < visibleSubMenusLength; i++) {
   var menu = this.GetMenu(this.visibleSubMenuIds[i]);
   if(menu != null) {
    var element = ASPx.GetElementById(this.visibleSubMenuIds[i]);
    if(element != null) {
     var indexPath = this.GetIndexPathById(this.visibleSubMenuIds[i], Constants.MMIdSuffix);
     menu.CalculateSubMenuPosition(element, ASPx.InvalidPosition, ASPx.InvalidPosition, indexPath, false);
    }
   }
  }
 },
 HideAll: function() {
  this.DoHidePopupMenus(null, -1, "", false, "");
 },
 IsAnyMenuVisible: function() {
  return this.visibleSubMenuIds.length != 0;
 }
});
var menuCollection = null;
function aspxGetMenuCollection() {
 if(menuCollection == null)
  menuCollection = new ASPxClientMenuCollection();
 return menuCollection;
}
var ASPxClientMenuItem = ASPx.CreateClass(null, {
 constructor: function(menu, parent, index, name) {
  this.menu = menu;
  this.parent = parent;
  this.index = index;
  this.name = name;
  this.indexPath = "";
  this.text = "";
  this.imageUrl = "";
  this.imageClassName = "";
  this.tooltip = "";
  this.target = "";
  this.beginGroup = false;
  this.dropDownMode = false;
  if(parent) {
   this.indexPath = this.CreateItemIndexPath(parent);
  }
  this.enabled = true;
  this.clientEnabled = true;
  this.visible = true;
  this.clientVisible = true;
  this.items = [];
  this.colorPicker = null;
  this.checkedGroup = [];
  this.checked = false;
 },
 CreateItemIndexPath: function(parent) {
  return parent.indexPath ? parent.indexPath + ASPx.ItemIndexSeparator + this.index.toString() : this.index.toString();
 },
 ClearRenderedChildItems: function() {
  if(this.items.length > 0) {
   var parentNode = this.menu.GetItemElement(this.items[0].indexPath).parentNode;
   parentNode.innerHTML = "";
   this.items = [];
  }
 },
 CreateItems: function(itemsProperties) {
  for(var i = 0, len = itemsProperties.length; i < len; i++) {
   var itemProperties = itemsProperties[i],
    item = this.CreateItemInternal(itemProperties);
   if(itemProperties.items && itemProperties.items.length > 0)
    item.CreateItems(itemProperties.items);
  }
 },
 CreateItemInternal: function(itemProperties) {
  var itemName = itemProperties.name || "";
  var index = this.items.length;
  var itemType = this.menu.GetClientItemType();
  var item = new itemType(this.menu, this, index, itemName);
  if(ASPx.IsExists(itemProperties.text))
   item.text = itemProperties.text;
  if(ASPx.IsExists(itemProperties.imageUrl))
   item.imageUrl = itemProperties.imageUrl;
  if(ASPx.IsExists(itemProperties.imageHottrackSrc))
   item.imageHottrackSrc = itemProperties.imageHottrackSrc;
  if(ASPx.IsExists(itemProperties.imageClassName))
   item.imageClassName = itemProperties.imageClassName;
  if(ASPx.IsExists(itemProperties.navigateUrl))
   item.navigateUrl = itemProperties.navigateUrl;
  if(ASPx.IsExists(itemProperties.beginGroup))
   item.beginGroup = itemProperties.beginGroup;
  if(ASPx.IsExists(itemProperties.enabled) && !this.menu.NeedCreateItemsOnClientSide())
   item.enabled = itemProperties.enabled;
  if((ASPx.IsExists(itemProperties.clientEnabled) && !itemProperties.clientEnabled) || (ASPx.IsExists(itemProperties.enabled) && !itemProperties.enabled))
   item.clientEnabled = false;
  if(ASPx.IsExists(itemProperties.visible))
   item.visible = itemProperties.visible;
  if(ASPx.IsExists(itemProperties.clientVisible))
   item.clientVisible = itemProperties.clientVisible;
  if(ASPx.IsExists(itemProperties.groupName)) {
   this.menu.ProcessItemGroupName(item, itemProperties.groupName);
   item.checked = !!itemProperties.checked;
  }
  if(ASPx.IsExists(itemProperties.tooltip))
   item.tooltip = itemProperties.tooltip;
  if(ASPx.IsExists(itemProperties.target))
   item.target = itemProperties.target;
  if(ASPx.IsExists(itemProperties.dropDownMode))
   item.dropDownMode = itemProperties.dropDownMode;
  if(ASPx.IsExists(itemProperties.textTemplate))
   item.textTemplate = itemProperties.textTemplate;
  if(ASPx.IsExists(itemProperties.styles))
   item.styles = itemProperties.styles;
  if(ASPx.IsExists(itemProperties.isSvg))
   item.isSvg = itemProperties.isSvg;
  if(this.menu.NeedAppendToRenderData(item))
   this.menu.AppendToRenderData(this.indexPath, index);
  this.items.push(item);
  return item;
 },
 GetIndexPath: function() {
  return this.indexPath;
 },
 GetItemCount: function() {
  return this.items.length;
 },
 GetItem: function(index) {
  return (0 <= index && index < this.items.length) ? this.items[index] : null;
 },
 GetItemByName: function(name) {
  for(var i = 0; i < this.items.length; i++)
   if(this.items[i].name == name) return this.items[i];
  for(var i = 0; i < this.items.length; i++) {
   var item = this.items[i].GetItemByName(name);
   if(item != null) return item;
  }
  return null;
 },
 GetChecked: function() {
  var indexPath = this.GetIndexPath();
  return this.menu.IsCheckedItem(indexPath);
 },
 SetChecked: function(value) {
  var indexPath = this.GetIndexPath();
  this.menu.SetItemChecked(indexPath, value);
 },
 GetEnabled: function() {
  return this.enabled && this.clientEnabled;
 },
 SetEnabled: function(value) {
  if(this.clientEnabled != value) {
   this.clientEnabled = value;
   this.menu.SetItemEnabled(this.GetIndexPath(), value, false);
  }
 },
 GetImage: function() {
  return this.menu.GetItemImage(this.GetIndexPath());
 },
 GetImageUrl: function() {
  return this.menu.GetItemImageUrl(this.GetIndexPath());
 },
 SetImageUrl: function(value) {
  var indexPath = this.GetIndexPath();
  this.menu.SetItemImageUrl(indexPath, value);
 },
 GetNavigateUrl: function() {
  var indexPath = this.GetIndexPath();
  return this.menu.GetItemNavigateUrl(indexPath);
 },
 SetNavigateUrl: function(value) {
  var indexPath = this.GetIndexPath();
  this.menu.SetItemNavigateUrl(indexPath, value);
 },
 GetText: function() {
  var indexPath = this.GetIndexPath();
  return this.menu.GetItemText(indexPath);
 },
 SetText: function(value) {
  var indexPath = this.GetIndexPath();
  this.menu.SetItemText(indexPath, value);
 },
 GetVisible: function() {
  return this.visible && this.clientVisible;
 },
 SetVisible: function(value) {
  if(this.clientVisible != value) {
   this.setClientVisibleInternal(value);
   this.menu.SetItemVisible(this.GetIndexPath(), value, false);
  }
 },
 InitializeEnabledAndVisible: function(recursive) {
  this.menu.SetItemEnabled(this.GetIndexPath(), this.clientEnabled, true);
  this.menu.SetItemVisible(this.GetIndexPath(), this.clientVisible, true);
  if(recursive) {
   for(var i = 0; i < this.items.length; i++)
    this.items[i].InitializeEnabledAndVisible(recursive);
  }
 },
 setClientVisibleInternal: function(value) {
  this.menu.prepareSideMenuCssClasses(false);
  this.clientVisible = value;
  this.menu.prepareSideMenuCssClasses(true);
 },
 GetOwnProperties: function() {
  return {
   menuItem: this,
   focusableElement: this.GetFocusableElement()
  };
 },
 GetFocusableElement: function() {
  return this.menu.GetLinkElementByIndexPath(this.indexPath);
 }
});
var subMenuStack = function() {
 this.stack = [];
 this.hasItems = function() {
  return this.stack.length > 1;
 };
 this.count = function() {
  return this.stack.length;
 };
 this.last = function() {
  return this.stack[this.stack.length - 1].element;
 };
 this.push = function(element, text) {
  this.stack.push({element: element, text: text});
 };
 this.pop = function() {
  return this.stack.pop().element;
 };
 this.text = function() {
  return this.stack[this.stack.length - 1].text;
 };
};
var appearPanelAction = ASPx.CreateClass({
 constructor: function(menu) {
  this.menu = menu;
  this.expanded = false;
  this.cashedHtmlOverflow = '';
  this.bodyLeftMargin = 0;
  this.clearWidth = 0;
  this.animationInProgress = false;
  this.panel = this.menu.GetMainElement().parentNode;
  this.burgerButton = this.createBurgerButton();
  this.overlayPanel = this.createOverlayElement();
  this.afterCollapsePanel = new ASPxClientEvent();
  ASPx.Evt.AttachEventToElement(this.burgerButton, 'click', function() { this.toggleExpanded(); }.bind(this), true);
  ASPx.Evt.AttachEventToElement(this.overlayPanel, 'click', function() { this.toggleExpanded(); }.bind(this), true);
 },
 get isLeftPosition() {
  return this.menu.position == 'left';
 },
 createBurgerButton: function() {
  var button = document.createElement('DIV');
  button.className = BURGER_CLASS_NAME;
  if(!!this.menu.hamburgerClass)
   ASPx.AddClassNameToElement(button, this.menu.hamburgerClass);
  var line = document.createElement('DIV');
  button.appendChild(line);
  this.panel.parentNode.appendChild(button);
  return button;
 },
 createOverlayElement: function() {
  var panel = document.createElement('DIV');
  panel.className = OVERLAY_PANEL_CLASS_NAME;
  this.panel.parentNode.appendChild(panel);
  return panel;
 },
 toggleExpanded: function() {
  this.setExpanded(!this.getExpanded());
 },
 getExpanded: function() {
  return this.expanded;
 },
 setExpanded: function(value) {
  if(this.expanded != value && !this.isAnimationInProgress()) {
   this.expanded = value;
   this.setExpandedCore();
  }
 },
 setExpandedCore: function() {
  if(this.expanded) {
   this.prepareForAnimateIn();
   this.animateIn();
  }
  else
   this.animateOut();
 },
 collapse: function() {
  this.expanded = false;
  this.rollbackAfterAnimateOut();
 },
 isAnimationInProgress: function() {
  return !!this.animationInProgress;
 },
 prepareForAnimateIn: function() {
  this.prepareDocument();
  this.prepareOverlayPanel();
  this.prepareSlidePanel();
 },
 prepareDocument: function() {
  this.cashedHtmlOverflow = document.documentElement.style.overflow;
  document.documentElement.style.overflow = 'hidden';
 },
 prepareOverlayPanel: function() {
  ASPx.SetStyles(this.overlayPanel, {
   opacity: '0',
   zIndex: SIDE_MENU_ZINDEX_VALUE,
   display: 'block'
  });
  ASPx.SetStyles(this.overlayPanel, {
   marginLeft: -ASPx.GetAbsoluteX(this.overlayPanel),
   marginTop: -ASPx.GetAbsoluteY(this.overlayPanel),
  });
 },
 prepareSlidePanel: function() {
  ASPx.SetStyles(this.panel, { display: 'block', width: '100%', zIndex: SIDE_MENU_ZINDEX_VALUE + 1 });
  this.menu.AdjustControl();
  var size = this.menu.calculateMaxSize();
  this.clearWidth = size.width;
  var width = size.width;
  var overflowY = '';
  if(size.height > window.innerHeight) {
   overflowY = 'scroll';
   width = size.width + ASPx.GetVerticalScrollBarWidth();
  }
  ASPx.SetStyles(this.panel, { 
   className: this.panel.className + ' ' + SLIDE_PANEL_EXPANDED_CLASS_NAME,
   overflowY: overflowY,
   width: width
  });
 },
 createTransition: function(element, obj) {
  return transition = ASPx.AnimationHelper.createAnimationTransition(element, {
   property: obj.property, unit: obj.unit, duration: SLIDE_DURATION_VALUE, transition: ASPx.AnimationConstants.Transitions.POW_EASE_OUT, onComplete: obj.onComplete
  });
 },
 getInTransitions: function() {
  var arr = [];
  arr.push({
   trans: this.createTransition(this.panel, { property: this.isLeftPosition ? 'left' : 'right', unit: 'px' }),
   start: -this.panel.offsetWidth,
   end: 0
  });
  arr.push({
   trans: this.createTransition(this.overlayPanel, {
    property: 'opacity',
    onComplete: function() {
     this.animationInProgress = false;
    }.aspxBind(this)
   }),
   start: 0,
   end: 100
  });
  return arr;
 },
 getOutTransitions: function() {
  var arr = [];
  arr.push({
   trans: this.createTransition(this.panel, { property: this.isLeftPosition ? 'left' : 'right', unit: 'px' }),
   start: 0,
   end: -this.panel.offsetWidth
  });
  arr.push({
   trans: this.createTransition(this.overlayPanel, {
    property: 'opacity',
    onComplete: function() {
     window.setTimeout(function() {
      this.rollbackAfterAnimateOut();
      this.animationInProgress = false;
     }.aspxBind(this), 0);
    }.aspxBind(this)
   }),
   start: 100,
   end: 0
  });
  return arr;
 },
 animateIn: function() {
  this.animate(this.getInTransitions());
 },
 animateOut: function() {
  this.animate(this.getOutTransitions());
 },
 animate: function(transitions) {
  this.animationInProgress = true;
  for(var i = 0, obj; obj = transitions[i]; i++)
   obj.trans.Start(obj.start, obj.end);
 },
 resetPanelStyle: function() {
  ASPx.SetStyles(this.panel, {
   className: this.panel.className.replace(SLIDE_PANEL_EXPANDED_CLASS_NAME, ''),
   left: '', width: '', display: '', zIndex: ''
  });
 },
 resetOverlayPanelStyle: function() {
  ASPx.SetStyles(this.overlayPanel, {
   display: '',
   zIndex: '',
   marginLeft: 0,
   marginTop: 0
  });
 },
 rollbackAfterAnimateOut: function() {
  this.resetPanelStyle();
  this.resetOverlayPanelStyle();
  document.documentElement.style.overflow = this.cashedHtmlOverflow;
  this.afterCollapsePanel.FireEvent();
 }
});
var appearPanelWithShiftBodyAction = ASPx.CreateClass(appearPanelAction, {
 constructor: function(menu) {
  this.cashedBodyMargin = '';
  this.cashedBodyWidth = '';
  this.constructor.prototype.constructor.call(this, menu);
 },
 getInTransitions: function() {
  var arr = appearPanelAction.prototype.getInTransitions.call(this);
  arr.push({
   trans: this.createTransition(document.body, { property: 'marginLeft', unit: 'px' }),
   start: this.bodyLeftMargin,
   end: (this.isLeftPosition ? 1 : -1) * (this.bodyLeftMargin + this.panel.offsetWidth)
  });
  return arr;
 },
 getOutTransitions: function() {
  var arr = appearPanelAction.prototype.getOutTransitions.call(this);
  arr.push({
   trans: this.createTransition(document.body, { property: 'marginLeft', unit: 'px' }),
   start: (this.isLeftPosition ? 1 : -1) * (this.bodyLeftMargin + this.panel.offsetWidth),
   end: this.bodyLeftMargin
  });
  return arr;
 },
 prepareForAnimateIn: function() {
  this.bodyLeftMargin = ASPx.PxToInt(ASPx.GetCurrentStyle(document.body).marginLeft);
  this.cashedBodyWidth = document.body.style.width;
  this.cashedBodyMargin = document.body.style.marginLeft;
  document.body.style.width = document.body.offsetWidth + 'px';
  appearPanelAction.prototype.prepareForAnimateIn.call(this);
 },
 rollbackAfterAnimateOut: function() {
  document.body.style.width = this.cashedBodyWidth;
  document.body.style.marginLeft = this.cashedBodyMargin;
  appearPanelAction.prototype.rollbackAfterAnimateOut.call(this);
 }
});
var ASPxClientMenu = ASPx.CreateClass(ASPxClientMenuBase, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.isVertical = false;
  this.orientationChanged = false;
  this.firstSubMenuDirection = "Auto";
  this.enableSideMenu = false;
  this.sideMenuWindowInnerWidth = ASPx.MaxMobileWindowWidth;
  this.enableCollapseToIcons = false;
  this.collapseToIconsWindowInnerWidth = ASPx.MaxMobileWindowWidth;
  this.showPopOutImages = false;
  this.sideMenuModeOn = false;
  this.iconsViewModeOn = false;
  this.position = 'left'; 
  this.expandMode = 0; 
  this.direction = this.position == 'left' ? 1 : -1;
  this.appearAction = null;
  this.subMenuStack = null;
  this.breadCrumb = null;
 },
 InlineInitialize: function() {
  var mainElement = this.GetMainElement();
  if(this.enableSideMenu) {
   mainElement.parentNode.className += ' dxm-' + this.position;
   this.subMenuStack = new subMenuStack();
   this.subMenuStack.push(this.GetMainElement());
   this.appearAction = this.createAppearAction();
   this.breadCrumb = this.createBreadCrumbs();
   this.updateBreadCrumbsText('TEMP'); 
   this.switchMenuView(true);
  }
  this.switchBetweenTextAndIcons();
  this.renderHelper.ApplyItemsVerticalAlignment(mainElement);
  ASPxClientMenuBase.prototype.InlineInitialize.call(this);
 },
 BrowserWindowResizeSubscriber: function() {
  return ASPxClientMenuBase.prototype.BrowserWindowResizeSubscriber.call(this) || this.enableSideMenu || this.enableCollapseToIcons;
 },
 SetData: function(data){
  ASPxClientMenuBase.prototype.SetData.call(this, data);
  if(data.adaptiveModeData)
   this.SetAdaptiveMode(data.adaptiveModeData);
 },
 IsVertical: function(indexPath) {
  return this.isVertical || !this.IsRootItem(indexPath) || this.IsAdaptiveMenuItem(indexPath);
 },
 IsSidePanelExpanded: function() {
  return this.enableSideMenu && this.appearAction.getExpanded();
 },
 IsCorrectionDisableMethodRequired: function(indexPath) {
  return (indexPath.indexOf("i") == -1) && (this.firstSubMenuDirection == "RightOrBottom" || this.firstSubMenuDirection == "LeftOrTop");
 },
 SetAdaptiveMode: function(data) {
  this.enableAdaptivity = true;
  if(ASPx.Ident.IsArray(data))
   this.adaptiveItemsOrder = data;
  else
   for(var i = data - 1; i >= 0; i--)
    this.adaptiveItemsOrder.push(i.toString());
 }, 
 OnBrowserWindowResize: function(e) {
  if(e && e.virtualKeyboardShownOnAndroid) return;
  this.switchMenuView();
  this.switchBetweenTextAndIcons();
  this.AdjustControl();
 },
 AdjustControlCore: function() {
  this.CorrectVerticalAlignment(ASPx.ClearHeight, this.GetPopOutElements, "PopOut", true);
  this.CorrectVerticalAlignment(ASPx.ClearVerticalMargins, this.GetPopOutImages, "PopOutImg", true);
  if(this.orientationChanged){
   this.renderHelper.ChangeOrientaion(this.GetMainElement(), this.isVertical);
   this.orientationChanged = false;
  }
  else
   this.renderHelper.CalculateMenuControl(this.GetMainElement());
  this.CorrectVerticalAlignment(ASPx.AdjustHeight, this.GetPopOutElements, "PopOut", true);
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, this.GetPopOutImages, "PopOutImg", true);
 },
 GetCorrectionDisabledResult: function(x, toLeftX) {
  switch (this.firstSubMenuDirection) {
   case "RightOrBottom": {
    this.popupToLeft = false;
    return x;
   }
   case "LeftOrTop": {
    this.popupToLeft = true;
    return toLeftX;
   }
  }
 },
 IsHorizontalSubmenuNeedInversion: function(subMenuBottom, docClientHeight, menuItemTop, subMenuHeight, itemHeight) {
  if(this.firstSubMenuDirection == "Auto")
   return ASPxClientMenuBase.prototype.IsHorizontalSubmenuNeedInversion.call(this, subMenuBottom, docClientHeight, menuItemTop, subMenuHeight, itemHeight);
  return this.firstSubMenuDirection == "LeftOrTop";
 },
 createAppearAction: function() {
  var appearAction = this.expandMode == 0 ? new appearPanelWithShiftBodyAction(this) : new appearPanelAction(this);
  appearAction.afterCollapsePanel.AddHandler(function() {
   while(this.subMenuStack.hasItems())
    this.performBack(true);
   ASPx.SetStyles(this.subMenuStack.last(), { left: '', opacity: '', display: '' });
   ASPx.RemoveElement(this.breadCrumb);
  }.aspxBind(this));
  return appearAction;
 },
 createBreadCrumbs: function() {
  var element = document.createElement('DIV');
  element.className = BREAD_CRUMBS_CLASS_NAME;
  ASPx.Evt.AttachEventToElement(element, 'click', function() { this.performBack(); }.bind(this), true);
  var breadCrumbsBackImage = document.createElement('IMG');
  breadCrumbsBackImage.src = ASPx.EmptyImageUrl;
  breadCrumbsBackImage.className = BACK_ICON_CLASS_NAME;
  element.appendChild(breadCrumbsBackImage);
  var breadCrumbsTitle = document.createElement('SPAN');
  element.appendChild(breadCrumbsTitle);
  return element;
 },
 updateBreadCrumbsText: function() {
  var text = this.subMenuStack.text();
  if(text)
   this.breadCrumb.children[1].innerHTML = this.subMenuStack.text();
 },
 calculateMaxSize: function() {
  var mainElement = this.GetMainElement();
  var cachedWidth = mainElement.style.width;
  mainElement.style.width = '';
  var size = { width: mainElement.offsetWidth, height: mainElement.offsetHeight };
  this.foreachSubMenus(function(item, element) {
   if(!element) return;
   element.className += ' ' + TEMPORARY_VISIBILITY_CLASS_NAME;
   if(element.offsetWidth > size.width)
    size.width = element.offsetWidth;
   if(element.offsetHeight > size.height)
    size.height = element.offsetHeight;
   element.className = element.className.replace(' ' + TEMPORARY_VISIBILITY_CLASS_NAME, '');
  }.bind(this));
  mainElement.style.width = cachedWidth;
  return size;
 },
 foreachSubMenus: function(menuItem, callback) {
  if(arguments.length == 1) {
   callback = menuItem;
   menuItem = this.GetRootItem();
  }
  for(var i = 0, item; item = menuItem.items[i]; i++)
   this.foreachSubMenus(item, callback);
  if(menuItem.indexPath && menuItem.items.length)
   callback(menuItem, this.GetMenuElement(menuItem.indexPath));
 },
 switchMenuView: function(force) {
  if(this.enableSideMenu) {
   aspxGetMenuCollection().DoHidePopupMenus(null, 0, this.name, true, "");
   var prevSideMenuOn = this.sideMenuModeOn;
   this.sideMenuModeOn = window.innerWidth < this.sideMenuWindowInnerWidth;
   if(this.sideMenuModeOn != prevSideMenuOn || force)
    this.switchMenuViewCore();
  }
 },
 switchBetweenTextAndIcons: function() {
  if(this.enableCollapseToIcons) {
   var newIconsViewModeOn = window.innerWidth <= this.collapseToIconsWindowInnerWidth;
   if(this.iconsViewModeOn != newIconsViewModeOn)
    this.ToggleRootItemsCollapsed();
  }
 },
 ToggleRootItemsCollapsed: function() {
  this.iconsViewModeOn = !this.iconsViewModeOn;
  ASPx.ToggleClassNameToElement(this.GetMainElement(), "dxm-onlyIcons", this.iconsViewModeOn);
  if(this.isInitialized) {
   this.renderHelper.ResetMinSize();
   this.renderHelper.CalculateMenuControl(this.GetMainElement(), true);
  }
 },
 switchMenuViewCore: function() {
  if(this.sideMenuModeOn)
   this.switchToSideMenuView();
  else
   this.switchToDefaultMenuView();
 },
 switchToSideMenuView: function() {
  this.SetOrientation('Vertical');
  this.switchSideMenuClass();
  if(!this.showPopOutImages) {
   var mainElement = this.GetMainElement();
   this.replacePopupOutImages(MenuCssClasses.ItemWithoutSubMenu, MenuCssClasses.ItemWithSubMenu);
   mainElement.className = mainElement.className.replace(NO_MAIN_POP_OUT_CLASS_NAME, '');
  }
 },
 switchToDefaultMenuView: function() {
  if(!this.showPopOutImages) {
   var mainElement = this.GetMainElement();
   this.replacePopupOutImages(MenuCssClasses.ItemWithSubMenu, MenuCssClasses.ItemWithoutSubMenu);
   if(mainElement.className.indexOf(NO_MAIN_POP_OUT_CLASS_NAME) == -1)
    mainElement.className += ' ' + NO_MAIN_POP_OUT_CLASS_NAME;
  }
  this.SetOrientation('Horizontal');
  this.switchSideMenuClass();
  this.appearAction.collapse();
 },
 switchSideMenuClass: function() {
  var rootElement = this.GetMainElement().parentNode.parentNode;
  if(this.sideMenuModeOn) {
   if(rootElement.className.indexOf(SIDE_MENU_CLASS_NAME) == -1)
    rootElement.className += ' ' + SIDE_MENU_CLASS_NAME;
  }
  else
   rootElement.className = rootElement.className.replace(' ' + SIDE_MENU_CLASS_NAME, '');
 },
 replacePopupOutImages: function(firstClass, secondClass) {
  var elements = this.renderHelper.GetItemElements(this.GetMainElement());
  for(var i = 0, item = null; item = elements[i]; i++) {
   if(item.className.indexOf(firstClass))
    item.className = item.className.replace(firstClass, secondClass);
  }
 },
 CalculateSubMenuPosition: function(element, x, y, indexPath, enableAnimation) {
  if(this.sideMenuModeOn)
   this.performForward(indexPath);
  else {
   this.setSubMenuOffset(element, '');
   ASPxClientMenuBase.prototype.CalculateSubMenuPosition.call(this, element, x, y, indexPath, enableAnimation);
  }
 },
 startPanelAnimation: function(element, props, onComplete) {
  ASPx.AnimationHelper.createMultipleAnimationTransition(element, {
   duration: SLIDE_DURATION_VALUE,
   transition: ASPx.AnimationConstants.Transitions.POW_EASE_OUT,
   onComplete: onComplete
  }).Start(props);
 },
 changeBreadCrumbsParent: function(parent) {
  if(this.subMenuStack.count() == 1 && !parent.querySelector('.' + BREAD_CRUMBS_CLASS_NAME))
   parent.appendChild(this.breadCrumb);
 },
 performForward: function(indexPath) {
  var element = this.GetMenuElement(indexPath);
  if(element != null) {
   var currentSubMenu = this.subMenuStack.last();
   var currentSubMenuWidth = currentSubMenu.offsetWidth;
   var nextSubMenu = this.GetMenuElement(indexPath);
   this.setSubMenuVisible(nextSubMenu);
   this.changeBreadCrumbsParent(nextSubMenu);
   this.subMenuStack.push(nextSubMenu, this.GetItemByIndexPath(indexPath).GetText());
   this.updateBreadCrumbsText();
   this.setSubMenuSize(indexPath, nextSubMenu);
   this.startPanelAnimation(currentSubMenu, {
    left: { from: 0, to: this.direction * -(currentSubMenuWidth / 3), unit: "px" },
    opacity: { from: 1, to: 0 }
   }, function(el) { el.style.display = 'none'; el.style.opacity = ''; });
   window.setTimeout(function() {
    this.startPanelAnimation(nextSubMenu, {
     left: { from: this.direction * currentSubMenuWidth, to: 0, unit: "px" },
     opacity: { from: 0, to: 1 }
    }, function(element) { this.onNextSubmenuAnimationEnd(element); }.bind(this));
   }.bind(this), SLIDE_DURATION_VALUE / 3);
  }
 },
 setSubMenuVisible: function(subMenu) {
  ASPx.SetStyles(subMenu, {
   top: '', display: '', visibility: '', opacity: 0
  });
 },
 setSubMenuSize: function(indexPath, subMenu) {
  var menuElement = this.GetMenuElement(indexPath);
  menuElement.style.width = this.appearAction.clearWidth + 'px';
  this.setSubMenuOffset(subMenu, this.breadCrumb.offsetHeight + 'px');
 },
 setSubMenuOffset: function(subMenu, offset) {
  subMenu.children[0].style.top = offset;
 },
 onNextSubmenuAnimationEnd: function(element) {
  if(element.children.length > 1)
   element.parentNode.appendChild(this.breadCrumb);
 },
 performBack: function(skipAnimation) {
  if(this.subMenuStack.hasItems()) {
   var currentSubMenu = this.subMenuStack.pop();
   var prevSubMenu = this.subMenuStack.last();
   if(skipAnimation)
    this.performBackWithoutAnimation(currentSubMenu, prevSubMenu);
   else
    this.performBackWithAnimation(currentSubMenu, prevSubMenu);
  }
 },
 performBackWithoutAnimation: function(currentSubMenu, prevSubMenu) {
  this.DoHidePopupMenu(null, currentSubMenu);
 },
 performBackWithAnimation: function(currentSubMenu, prevSubMenu) {
  this.updateBreadCrumbsText();
  this.changeBreadCrumbsParent(currentSubMenu);
  var width = currentSubMenu.offsetWidth;
  prevSubMenu.style.opacity = '0';
  prevSubMenu.style.display = '';
  this.startPanelAnimation(currentSubMenu, {
   left: { from: 0, to: this.direction * (width / 3), unit: "px" },
   opacity: { from: 1, to: 0 }
  }, function(el) { el.style.opacity = ''; el.style.display = 'none'; this.DoHidePopupMenu(null, el); }.bind(this));
  window.setTimeout(function() {
   this.startPanelAnimation(prevSubMenu, {
    left: { from: this.direction * -width, to: 0, unit: "px" },
    opacity: { from: 0, to: 1 }
   });
  }.bind(this), SLIDE_DURATION_VALUE / 3);
 },
 GetOrientation: function() {
  return this.isVertical ? "Vertical" : "Horizontal";
 },
 SetOrientation: function(orientation) {
  var isVertical = orientation === "Vertical";
  if(this.isVertical !== isVertical){
   this.isVertical = isVertical;
   this.orientationChanged = true;
   this.ResetControlAdjustment();
   this.AdjustControl();
  }
 },
 ToggleSideMenu: function() {
  if(this.sideMenuModeOn)
   this.appearAction.toggleExpanded();
 }
});
ASPx.Ident.scripts.ASPxClientMenu = true;
ASPxClientMenu.Cast = ASPxClientControl.Cast;
var ASPxClientMenuExt = ASPx.CreateClass(ASPxClientMenu, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
 },
 NeedCreateItemsOnClientSide: function() {
  return true;
 }
});
var ASPxClientMenuItemEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(item) {
  this.constructor.prototype.constructor.call(this);
  this.item = item;
 }
});
var ASPxClientMenuItemMouseEventArgs = ASPx.CreateClass(ASPxClientMenuItemEventArgs, {
 constructor: function(item, htmlElement) {
  this.constructor.prototype.constructor.call(this, item);
  this.htmlElement = htmlElement;
 }
});
var ASPxClientMenuItemClickEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(processOnServer, item, htmlElement, htmlEvent) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.item = item;
  this.htmlElement = htmlElement;
  this.htmlEvent = htmlEvent;
 }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, function(evt) {
 return aspxGetMenuCollection().OnMouseDown(evt);
});
function aspxAMIMOver(source, args) {
 var menu = aspxGetMenuCollection().GetMenu(args.item.name);
 if(menu != null) menu.OnAfterItemOver(args.item, args.element);
}
function aspxBMIMOver(source, args) {
 var menu = aspxGetMenuCollection().GetMenu(args.item.name);
 if(menu != null) menu.OnBeforeItemOver(args.item, args.element);
}
function aspxAMIMOut(source, args) {
 var menu = aspxGetMenuCollection().GetMenu(args.item.name);
 if(menu != null) menu.OnAfterItemOut(args.item, args.element, args.toElement);
}
function aspxMSBOver(source, args) {
 var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
 if(menu != null) menu.ClearDisappearTimer();
}
ASPx.AddAfterSetFocusedState(aspxAMIMOver);
ASPx.AddAfterClearFocusedState(aspxAMIMOut);
ASPx.AddAfterSetHoverState(aspxAMIMOver);
ASPx.AddAfterClearHoverState(aspxAMIMOut);
ASPx.AddBeforeSetFocusedState(aspxBMIMOver);
ASPx.AddBeforeSetHoverState(aspxBMIMOver);
ASPx.AddAfterSetHoverState(aspxMSBOver);
ASPx.AddAfterSetPressedState(aspxMSBOver);
ASPx.AddBeforeDisabled(function(source, args) {
 var menu = aspxGetMenuCollection().GetMenu(args.item.name);
 if(menu != null)
  menu.OnBeforeItemDisabled(args.item, args.element);
});
ASPx.AddFocusedItemKeyDown(function(source, args) {
 var menu = aspxGetMenuCollection().GetMenu(args.item.name);
 if(menu != null)
  menu.OnFocusedItemKeyDown(args.htmlEvent, args.item);
});
ASPx.AddAfterClearHoverState(function(source, args) {
 var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
 if(menu != null) menu.SetDisappearTimer();
});
ASPx.AddAfterSetPressedState(function(source, args) {
 var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
 if(menu) menu.StartScrolling(args.element.id, 1, 4);
});
ASPx.AddAfterClearPressedState(function(source, args) {
 var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
 if(menu) menu.StopScrolling(args.element.id);
});
if(!ASPx.Browser.TouchUI) {
 ASPx.AddAfterSetHoverState(function(source, args) {
  var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
  if(menu) menu.StartScrolling(args.element.id, 15, 1);
  if(!menu)
   menu = aspxGetMenuCollection().GetMenu(args.item.name);
  if(menu && menu.sideMenuModeOn && menu.IsItemElement(args.element)) {
   menu.hoverItemName = args.item.name;
   menu.MarkPrecedingItem(args.item.name, PRE_HOVERED_ELEMENT_CLASS_NAME, true);
  }
 });
 ASPx.AddAfterClearHoverState(function(source, args) {
  var menu = MenuScrollHelper.GetMenuByScrollButtonId(args.element.id);
  if(menu) menu.StopScrolling(args.element.id);
  if(!menu)
   menu = aspxGetMenuCollection().GetMenu(args.item.name);
  if(menu && menu.sideMenuModeOn && menu.IsItemElement(args.element)) {
   menu.hoverItemName = null;
   menu.UnmarkPrecedingItem(args.item.name, PRE_HOVERED_ELEMENT_CLASS_NAME, true);
  }
 });
}
ASPx.MIClick = function(evt, name, indexPath) {
 if(ASPx.TouchUIHelper.isMouseEventFromScrolling) return;
 var menu = aspxGetMenuCollection().Get(name);
 if(menu != null) menu.OnItemClick(indexPath, evt);
};
ASPx.MIDDClick = function(evt, name, indexPath) {
 var menu = aspxGetMenuCollection().Get(name);
 if(menu != null) menu.OnItemDropDownClick(indexPath, evt);
 if(!ASPx.Browser.NetscapeFamily)
  evt.cancelBubble = true;
};
ASPx.GetMenuCollection = aspxGetMenuCollection;
ASPx.MenuRenderHelper = MenuRenderHelper;
ASPx.MenuItemClasses = MenuCssClasses;
window.ASPxClientMenuBase = ASPxClientMenuBase;
window.ASPxClientMenuCollection = ASPxClientMenuCollection;
window.ASPxClientMenuItem = ASPxClientMenuItem;
window.ASPxClientMenu = ASPxClientMenu;
window.ASPxClientMenuExt = ASPxClientMenuExt;
window.ASPxClientMenuItemEventArgs = ASPxClientMenuItemEventArgs;
window.ASPxClientMenuItemMouseEventArgs = ASPxClientMenuItemMouseEventArgs;
window.ASPxClientMenuItemClickEventArgs = ASPxClientMenuItemClickEventArgs;
})();

(function () {
var TreeViewCssClasses = {};
TreeViewCssClasses.Prefix = "dxtv-";
TreeViewCssClasses.WRAP_TEXT = TreeViewCssClasses.Prefix + 'wrap-text';
TreeViewCssClasses.Disabled = "dxtvDisabled";
TreeViewCssClasses.Rtl = "dxtvRtl";
TreeViewCssClasses.Elbow = TreeViewCssClasses.Prefix + "elb";
TreeViewCssClasses.ElbowWithoutLine = TreeViewCssClasses.Prefix + "elbNoLn";
TreeViewCssClasses.Button = TreeViewCssClasses.Prefix + "btn";
TreeViewCssClasses.Node = TreeViewCssClasses.Prefix + "nd";
TreeViewCssClasses.Line = TreeViewCssClasses.Prefix + "lb";
TreeViewCssClasses.NodeCheckbox = TreeViewCssClasses.Prefix + "ndChk";
TreeViewCssClasses.NodeImage = TreeViewCssClasses.Prefix + "ndImg";
TreeViewCssClasses.NodeText = TreeViewCssClasses.Prefix + "ndTxt";
TreeViewCssClasses.NodeTemplate = TreeViewCssClasses.Prefix + "ndTmpl";
TreeViewCssClasses.AccessibleNode = TreeViewCssClasses.Prefix + "acc-n";
var TreeViewRenderHelper = ASPx.CreateClass(null, {
 constructor: function(treeView) {
  this.treeView = treeView;
  this.nodeClickHandler = function (e) { treeView.HandleNodeClick(e); };
  this.nodeDblClickHandler = function (e) { treeView.HandleNodeDblClick(e); };
  this.nodeMouseMove = function(e) { treeView.CorrectControlWidthOnHover(e.target); };
 },
 InlineInitializeElements: function() {
  this.InitializeNodeContainerElements(this.GetRootList(), "", null);
 },
 InitializeNodeContainerElements: function(nodeContainer, parentIndexPath, parentClientNode) {
  var listItems = this.treeView.GetListItems(nodeContainer);
  if(!listItems)
   return;
  for(var i = 0, nodeIndex = 0; i < listItems.length; i++, nodeIndex++) {
   var serverProvidedNodeIndex = this.GetServerProvidedNodeIndex(listItems[i]);
   if(serverProvidedNodeIndex)
    nodeIndex = serverProvidedNodeIndex;
   var nodeIndexPath = this.treeView.GetNodeIndexPath(nodeIndex, parentIndexPath);
   var clientNode = this.treeView.CreateClientNode(i, parentClientNode, nodeIndexPath);
   if(clientNode)
    clientNode.last = i == listItems.length - 1;
   this.InitializeNodeElements(listItems[i], nodeIndexPath, clientNode);
  }
 },
 InitializeNodeElements: function (listItem, indexPath, clientNode) {
  this.InitializeNodeContent(listItem, indexPath, clientNode);
  this.InitializeExpandButton(listItem);
  if(clientNode) {
   if(!clientNode.clientVisible)
    this.treeView.SetNodeClientVisible(clientNode, false);
   if(!clientNode.clientEnabled)
    this.treeView.SetNodeClientEnabled(clientNode, false);
  }
  var subnodesList = this.GetSubNodesList(listItem);
  if(subnodesList)
   this.InitializeNodeContainerElements(subnodesList, indexPath, clientNode);
 },
 GetServerProvidedNodeIndex: function (listItem) {
  var nodeContentElement = this.GetNodeContentElement(listItem);
  if(!nodeContentElement || !nodeContentElement.id)
   return null;
  var nodeIndexPath = this.treeView.GetNodeIndexPathByContentElementID(nodeContentElement.id);
  var nodeIndices = nodeIndexPath.split(this.treeView.IndexPathSeparator);
  return parseInt(nodeIndices[nodeIndices.length - 1]);
 },
 InitializeExpandButton: function (listItem) {
  var button = this.GetNodeButtonElement(listItem);
  if(button && this.CanAttachExpandButtonHandler(this.GetNodeContentElement(listItem)))
   this.treeView.ToggleExpandButtonHandlers(true, button);
 },
 CanAttachExpandButtonHandler: function(contentElement) {
  return !this.IsNodeDisabled(contentElement);
 },
 InitializeNodeContent: function (listItem, nodeIndexPath, clientNode) {
  var nodeContentElement = this.GetNodeContentElement(listItem);
  if(!nodeContentElement)
   return;
  var contentElementID = this.GetElementID(this.treeView.NodeIDPrefix, nodeIndexPath);
  if(clientNode) {
   clientNode.enabled = !this.IsNodeDisabled(nodeContentElement);
   clientNode.contentElementID = contentElementID;
   var textSpan = this.GetNodeTextElement(nodeContentElement);
   clientNode.text = textSpan ? ASPx.GetInnerText(textSpan) : "";
  }
  nodeContentElement.id = contentElementID;
  if(nodeContentElement.tagName === "A")
   ASPx.AssignAccessibilityEventsToLink(nodeContentElement);
  this.InitializeNodeOnClick(nodeContentElement);
  this.InitializeNodeImage(nodeContentElement, clientNode);
  var icbMainElement = this.GetNodeCheckBoxElement(nodeContentElement);
  if(icbMainElement) {
   var icbInputElement = ASPx.GetNodeByTagName(icbMainElement, "input", 0);
   icbInputElement.id = this.GetElementID(this.treeView.NodeCheckboxIDPostfix, nodeIndexPath);
   if(this.treeView.imageProperties)
    this.AddInternalCheckBoxToCollection(icbInputElement, nodeContentElement);
  }
 },
 InitializeNodeOnClick: function (nodeContentElement) {
  this.attachEventToElement(nodeContentElement, "click", this.nodeClickHandler);
  this.attachEventToElement(nodeContentElement, "dblclick", this.nodeDblClickHandler);
  if(this.treeView.contentBoundsMode && this.treeView.requireWidthRecalculationOnHover)
   this.attachEventToElement(nodeContentElement, "mousemove", this.nodeMouseMove);
 },
 attachEventToElement: function(element, eventName, handler) {
  ASPx.Evt.AttachEventToElement(element, eventName, handler);
 },
 InitializeNodeImage: function (nodeContentElement, clientNode) {
  var nodeImage = this.GetNodeImageElement(nodeContentElement);
  if(!nodeImage)
   return;
  nodeImage.id = nodeContentElement.id + this.treeView.NodeImageIDPostfix;
  this.InitializeNodeImageCore(nodeImage, clientNode);
 },
 InitializeNodeImageCore: function(nodeImage, clientNode) {
  var nodeImageLoaded = nodeImage.naturalWidth !== 0 && nodeImage.naturalHeight !== 0 && nodeImage.complete;
  if(!nodeImageLoaded) {
   var instance = this.treeView;
   ASPx.Evt.AttachEventToElement(nodeImage, "load", function (evt) {
    instance.CorrectControlWidth();
   });
   if(ASPx.Browser.WebKitFamily) {
    ASPx.Evt.AttachEventToElement(nodeImage, "error", function (evt) {
     instance.CorrectControlWidth();
    });
   }
  }
  if(clientNode)
   clientNode.imageUrl = nodeImage.src;
 },
 AddInternalCheckBoxToCollection: function (icbInputElement, contentElement) {
  var instance = this.treeView;
  var internalCheckBox = this.treeView.internalCheckBoxCollection.Add(contentElement.id, icbInputElement);
  internalCheckBox.SetEnabled(!this.IsNodeDisabled(contentElement));
  internalCheckBox.readOnly = this.treeView.readOnly;
  internalCheckBox.CreateFocusDecoration(this.treeView.icbFocusedStyle);
  internalCheckBox.CheckedChanged.AddHandler(
   function (s, e) {
    instance.UpdateCheckedInNodesState(s.inputElement, true);
    instance.OnNodeCheckboxClick(s.inputElement);
   }
  );
 },
 IsNodeDisabled: function (contentElement) {
  return ASPx.ElementContainsCssClass(contentElement, TreeViewCssClasses.Disabled);
 },
 GetElementID: function (IDPrefix, indexPath) {
  return this.treeView.name + IDPrefix + indexPath;
 },
 GetRootList: function(){
  return ASPx.GetNodeByTagName(this.treeView.GetMainElement(), "UL", 0);
 },
 GetSubNodesList: function(listItem) {
  return ASPx.GetChildByTagName(listItem, "UL");
 },
 GetNodeContentElement: function(listItem){
  var node = this.GetNodeByClassName(listItem, TreeViewCssClasses.Node);
  if(node && ASPx.GetParentByTagName(node, "LI") === listItem) return node;
  return this.GetNodeByClassName(listItem, TreeViewCssClasses.NodeTemplate);
 },
 GetNodeContentElementByClick: function(clickedElement){
  return ASPx.GetParentByClassName(clickedElement, TreeViewCssClasses.Node);
 },
 GetNodeTextElement: function(contentElement){
  return this.GetNodeByClassName(contentElement, TreeViewCssClasses.NodeText);
 },
 GetNodeImageElement: function(contentElement){
  var imageEl = this.GetNodeByClassName(contentElement, TreeViewCssClasses.NodeImage);
  if(imageEl && imageEl.tagName == "SPAN")
   imageEl = ASPx.GetChildByTagName(imageEl, "IMG", 0);
  return imageEl;
 },
 GetNodeButtonElement: function(listItem){
  return this.GetNodeByClassName(listItem, TreeViewCssClasses.Button);
 },
 GetNodeCheckBoxElement: function(contentElement){
  return this.HasCheckBox() ? this.GetNodeByClassName(contentElement, TreeViewCssClasses.NodeCheckbox) : null;
 },
 GetNodeByClassName: function(el, className) {
  return el.querySelector ? el.querySelector("." + className) : ASPx.GetNodesByPartialClassName(el, className)[0];
 },
 HasCheckBox: function() { return !!this.treeView.imageProperties; }
});
var ASPxClientTreeView = ASPx.CreateClass(ASPxClientControl, {
 IndexPathSeparator: "_",
 NodeIDPrefix: "_N",
 NodeImageIDPostfix: "I",
 NodeLoadingPanelIDPostfix: "NLP",
 SampleExpandButtonIDPostfix: "_SEB",
 SampleCollapseButtonIDPostfix: "_SCB",
 SampleNodeLoadingPanelIDPostfix: "_SNLP",
 ControlContentDivIDPostfix: "_CD",
 NodeCheckboxIDPostfix: "_CHK",
 ExpandNodeCommand: "E",
 ExpandAllNodesCommand: "EA",
 CheckNodeRecursiveCommand: "CHKNR",
 RaiseNodeClickEventCommand: "NCLK",
 RaiseExpandedChangingEventCommand: "ECHANGING",
 RaiseCheckedChangedEventCommand: "CCHNGD",
 PostRequestArgsSeparator: "|",
 NodeClickServerEventName: "NodeClick",
 ExpandedChangingServerEventName: "ExpandedChanging",
 CheckedChangedServerEventName: "CheckedChanged",
 WidthMeasurementIncrement: 1000,
 IE6WidthMeasurementDivWidth: 99999,
 AnimationDuration: 300,
 MinAnimationDuration: 200,
 HoverCorrectionDelay: 50,
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.enableAnimation = true;
  this.nodesInfo = null;
  this.nodesUrls = null;
  this.contentBoundsMode = true;
  this.checkNodesRecursive = false;
  this.allowSelectNode = false;
  this.virtualMode = false;
  this.imageProperties = null;
  this.icbFocusedStyle = [];
  this.requireWidthRecalculationOnHover = false;
  this.nodeLoadingPanelWidth = 0;
  this.nodeLoadingPanelHeight = 0;
  this.enableNodeTextWrapping = false;
  var instance = this;
  this.expandCollapseHandler = function (e) { instance.HandleExpandButtonClick(e); };
  this.accessibleMouseDownHandler = function(e) { instance.HandleExpandButtonAccessibleMouseDown(e); };
  this.accessibleBlurHandler = function(e) { instance.HandleExpandButtonAccessibleBlur(e); };
  var rootNodeType = this.GetClientNodeType();
  this.rootNode = new rootNodeType(this);
  this.selectedNodeContentElementID = null;
  this.requireRaiseExpandedChangedList = [];
  this.initialControlWidth = 0;
  this.requireClearExpandButtonOutline = false;
  this.renderHelper = this.CreateRenderHelper();
  this.NodeClick = new ASPxClientEvent();
  this.ExpandedChanged = new ASPxClientEvent();
  this.ExpandedChanging = new ASPxClientEvent();
  this.CheckedChanged = new ASPxClientEvent();
 },
 UpdateWordWrapNodesWidth: function(nodeContainer) {
  if(this.enableNodeTextWrapping) {
   var listItems = this.GetListItems(nodeContainer);
   if(listItems) {
    for(var i = 0, item; item = listItems[i]; i++) {
     var subNodes = this.renderHelper.GetSubNodesList(item);
     if(subNodes && ASPx.IsElementVisible(subNodes))
      this.UpdateWordWrapNodesWidth(subNodes);
     var displayValueCache = '';
     var span = item.childNodes[0];
     var content = item.childNodes[1];
     if(item.offsetWidth == 0) {
      displayValueCache = item.style.display;
      item.style.display = '';
     }
     content.style.width = item.getBoundingClientRect().width - span.getBoundingClientRect().width - ASPx.GetLeftRightMargins(span) - ASPx.GetLeftRightMargins(content) + 'px';
     if(displayValueCache != '')
      item.style.display = displayValueCache;
    }
   }
  }
 },
 applyAccessibilityAttributes: function(ariaDescriptor) {
  this.setAriaDescription("");
  this.setAriaDescription("expandButtons");
  this.setAriaDescription("listElement");
  this.setAriaDescription("treeItemRelationship");
  this.setAriaDescription("nodeCheckboxes");
 },
 ReplaceElementWithSampleElement: function (srcElement, sampleElement, copySrcInnerHtml) {
  var newElement = sampleElement.cloneNode(true);
  newElement.id = srcElement.id;
  if(copySrcInnerHtml && srcElement.innerHTML)
   ASPx.SetInnerHtml(newElement, srcElement.innerHTML);
  srcElement.parentNode.replaceChild(newElement, srcElement);
  ASPx.SetElementDisplay(newElement, true);
  return newElement;
 },
 ToggleExpandButtonHandlers: function (attach, button) {
  var method = attach ? ASPx.Evt.AttachEventToElement : ASPx.Evt.DetachEventFromElement;
  method(button, "click", this.expandCollapseHandler);
  if(this.accessibilityCompliant) {
   method(button, "mousedown", this.accessibleMouseDownHandler);
   method(button, "blur", this.accessibleBlurHandler);
  }
 },
 AddElementCssClass: function (element, className) {
  this.RemoveElementCssClass(element, className);
  element.className = element.className + " " + className;
 },
 RemoveElementCssClass: function (element, className) {
  var newElementClassName = element.className.replace(className, "");
  element.className = ASPx.Str.Trim(newElementClassName);
 },
 RemoveEmptyTextNodes: function (element) {
  var nonEmptyTextPattern = /\S/;
  var textNodeType = 3;
  var elementNodeType = 1;
  for(var i = 0; i < element.childNodes.length; i++) {
   if(element.childNodes[i].nodeType == textNodeType &&
    !nonEmptyTextPattern.test(element.childNodes[i].nodeValue)) {
    element.removeChild(element.childNodes[i]);
    i--;
   } else if(element.childNodes[i].nodeType == elementNodeType)
    this.RemoveEmptyTextNodes(element.childNodes[i]);
  }
 },
 GetNodeIDByContentElementID: function (contentElementID) {
  return ASPx.Str.Trim(contentElementID.replace(this.name + "_", ""));
 },
 GetNodeIndexPathByContentElementID: function (contentElementID) {
  return ASPx.Str.Trim(contentElementID.replace(this.name + this.NodeIDPrefix, ""));
 },
 CreatePostRequestArgs: function (command, arg1, arg2) {
  var args = command + this.PostRequestArgsSeparator + arg1;
  if(arg2 || arg2 === "")
   args += this.PostRequestArgsSeparator + arg2;
  return args;
 },
 MergeNodesData: function(srcData, destData) {
  for(var key in srcData)
   if(srcData.hasOwnProperty(key))
    destData[key] = srcData[key];
 },
 GetNodeListItem: function (clientNode) {
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  return ASPx.GetParentByTagName(contentElement, "LI");
 },
 SerializeBooleanValue: function (value) {
  return value ? "T" : "";
 },
 GetContentElementByNodeID: function (nodeID) {
  return ASPx.GetElementById(this.name + "_" + nodeID);
 },
 GetListItems: function (list) {
  var listNodes = ASPx.GetChildElementNodes(list);
  var listItems = [];
  if(!listNodes)
   return null;
  for(var i = 0; i < listNodes.length; i++) {
   if(listNodes[i].tagName == "LI")
    listItems.push(listNodes[i]);
  }
  return listItems;
 },
 GetClickedContentElementByEventArgs: function (e) {
  var clickedElement = ASPx.Evt.GetEventSource(e);
  var contentElement = this.renderHelper.GetNodeContentElementByClick(clickedElement);
  if(ASPx.ElementContainsCssClass(clickedElement, TreeViewCssClasses.NodeCheckbox))
   return null;
  if(!contentElement || this.renderHelper.IsNodeDisabled(contentElement))
   return null;
  return contentElement;
 },
 IsRightToLeft: function () {
  return ASPx.IsElementRightToLeft(this.GetMainElement());
 },
 InlineInitialize: function () {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  if(this.enableNodeTextWrapping)
   this.GetMainElement().className += ' ' + TreeViewCssClasses.WRAP_TEXT;
  this.SetInitialControlWidth();
  if(this.imageProperties)
   this.CreateInternalCheckBoxCollection();
  this.InitializeControlElements();
 },
 Initialize: function () {
  ASPxClientControl.prototype.Initialize.call(this);
  this.InitLoadingPanelSize();
 },
 OnBrowserWindowResize: function(e) {
  if(this.enableNodeTextWrapping)
   this.AdjustControl();
 },
 AdjustControlCore: function () {
  this.CorrectControlWidth();
  this.UpdateWordWrapNodesWidth(this.renderHelper.GetRootList());
 },
 CreateInternalCheckBoxCollection: function () {
  this.internalCheckBoxCollection = new ASPx.CheckBoxInternalCollection(this.imageProperties, true, undefined, undefined, undefined, this.accessibilityCompliant);
 },
 InitLoadingPanelSize: function () {
  var panel = this.GetSampleNodeLoadingPanel();
  if(panel) {
   this.nodeLoadingPanelWidth = panel.offsetWidth || panel.naturalWidth || panel.width;
   this.nodeLoadingPanelHeight = panel.offsetHeight || panel.naturalHeight || panel.width;
   ASPx.SetElementDisplay(panel, false);
   panel.style.visibility = "";
   panel.style.position = "";
  }
 },
 InitializeControlElements: function () {
  var mainElement = this.GetMainElement();
  if(ASPx.ElementContainsCssClass(mainElement, TreeViewCssClasses.Disabled))
   return;
  this.renderHelper.InlineInitializeElements();
  this.InitializeNodeSelection();
 },
 InitializeNodeSelection: function () {
  var contentElement = this.GetContentElementByNodeID(this.GetSelectedNodeIDFromState());
  if(contentElement)
   this.ApplySelectionToNode(contentElement);
  else if(this.allowSelectNode) { 
   var firstNodeId = this.NodeIDPrefix.replace("_", "") + this.GetNodeIndexPath(0, 0);
   ASPx.GetStateController().DeselectElementBySrcElement(this.GetContentElementByNodeID(firstNodeId));
  }
 },
 GetNodeIndexPath: function (listItemIndex, parentIndexPath) {
  if(!parentIndexPath)
   return listItemIndex.toString();
  return parentIndexPath + this.IndexPathSeparator + listItemIndex.toString();
 },
 CreateRenderHelper: function() {
  return new TreeViewRenderHelper(this);
 },
 ApplyServerProvidedClientNodeInfo: function (clientNode, indexPath) {
  if(!this.nodesInfo[indexPath])
   return;
  clientNode.clientEnabled = !!this.nodesInfo[indexPath][0];
  clientNode.clientVisible = !!this.nodesInfo[indexPath][1];
  clientNode.name = this.nodesInfo[indexPath][2];
  clientNode.navigateUrl = this.nodesInfo[indexPath][3];
  clientNode.target = this.nodesInfo[indexPath][4];
 },
 GetClientNodeType: function() {
  return ASPxClientTreeViewNode;
 },
 CreateClientNode: function (index, parentClientNode, indexPath) {
  if(!this.nodesInfo)
   return null;
  var nodeType = this.GetClientNodeType();
  var clientNode = new nodeType();
  clientNode.treeView = this;
  clientNode.parent = parentClientNode;
  clientNode.index = index;
  this.ApplyServerProvidedClientNodeInfo(clientNode, indexPath, null);
  if(parentClientNode)
   parentClientNode.nodes.push(clientNode);
  else
   this.rootNode.nodes.push(clientNode);
  return clientNode;
 },
 GetControlContentDiv: function () {
  return ASPx.GetElementById(this.name + this.ControlContentDivIDPostfix);
 },
 SetInitialControlWidth: function () {
  var mainElement = this.GetMainElement();
  if(mainElement.style.width && !ASPx.IsPercentageSize(mainElement.style.width))
   this.initialControlWidth = mainElement.offsetWidth;
 },
 CorrectControlWidthOnHover: function (nodeElement) {
  if(!this.requireWidthRecalculationOnHover)
   return;
  if(nodeElement.lastCorrectionOnHover && (new Date().getTime() - nodeElement.lastCorrectionOnHover <= this.HoverCorrectionDelay))
   return;
  this.CorrectControlWidth();
  nodeElement.lastCorrectionOnHover = new Date().getTime();
 },
 CorrectControlWidth: function() {
  if(this.enableNodeTextWrapping)
   return;
  var mainElement = this.GetMainElement();
  var controlContentDiv = this.GetControlContentDiv();
  var rootNodesList = this.renderHelper.GetRootList();
  if(!rootNodesList)
   return;
  mainElement.style.overflow = "hidden";
  ASPx.SetElementFloat(rootNodesList, "left");
  var prevListWidth = 0;
  do {
   prevListWidth = rootNodesList.offsetWidth;
   ASPx.SetOffsetWidth(controlContentDiv, controlContentDiv.offsetWidth + this.WidthMeasurementIncrement);
   if(ASPx.Browser.Opera) {
    rootNodesList.style.width = "100%";
    var dummy = rootNodesList.offsetWidth;
    rootNodesList.style.width = "";
   }
  } while(prevListWidth != rootNodesList.offsetWidth);
  if (rootNodesList.offsetWidth > this.initialControlWidth) {
   var isPercentageWidth = ASPx.IsPercentageSize(mainElement.style.width);
   var rootNodesListWidth = rootNodesList.getBoundingClientRect().width;
   mainElement.style[isPercentageWidth ? "minWidth" : "width"] = Math.ceil(rootNodesListWidth) + "px";
  }
  ASPx.SetElementFloat(rootNodesList, "");
  mainElement.style.overflow = "";
  controlContentDiv.style.width = "";
 },
 GetPreviousSiblingNodeListItem: function (clientNode) {
  var previousNodeIndex = clientNode.index - 1;
  if(previousNodeIndex < 0)
   return null;
  var previousClientNode = clientNode.parent ? clientNode.parent.GetNode(previousNodeIndex) :
   this.rootNode.nodes[previousNodeIndex];
  return this.GetNodeListItem(previousClientNode);
 },
 GetListItemElbowSpan: function (listItem) {
  return ASPx.GetNodesByPartialClassName(listItem, TreeViewCssClasses.Elbow)[0] ||
    ASPx.GetNodesByPartialClassName(listItem, TreeViewCssClasses.ElbowWithoutLine)[0];
 },
 SetNodeClientVisible: function (clientNode, clientVisible) {
  if(this.IsRootNode(clientNode))
   return;
  var listItem = this.GetNodeListItem(clientNode);
  ASPx.SetElementDisplay(listItem, clientVisible);
  this.CorrectControlWidth();
  if(!clientNode.last)
   return;
  var previousNodeListItem = this.GetPreviousSiblingNodeListItem(clientNode);
  if(!previousNodeListItem)
   return;
  var previousNodeElbowSpan = this.GetListItemElbowSpan(previousNodeListItem);
  if(ASPx.ElementContainsCssClass(previousNodeElbowSpan, TreeViewCssClasses.ElbowWithoutLine))
   return;
  this.renderHelper.InitializeExpandButton(previousNodeListItem);
  if(clientVisible)
   this.AddElementCssClass(previousNodeListItem, TreeViewCssClasses.Line);
  else
   this.RemoveElementCssClass(previousNodeListItem, TreeViewCssClasses.Line);
 },
 SetNodeClientEnabled: function (clientNode, clientEnabled) {
  if(this.IsRootNode(clientNode))
   return;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  ASPx.GetStateController().SetElementEnabled(contentElement, clientEnabled);
  if(this.internalCheckBoxCollection) {
   var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
   if(internalCheckBox)
    internalCheckBox.SetEnabled(clientEnabled);
  }
  var nodeLink = this.GetNodeLinkElement(clientNode);
  if(nodeLink)
   this.ChangeNodeLinkEnabledAttributes(nodeLink, clientNode, clientEnabled);
  var listItem = ASPx.GetParentByTagName(contentElement, "LI");
  var button = this.renderHelper.GetNodeButtonElement(listItem);
  if(button) {
   this.ToggleExpandButtonHandlers(clientEnabled, button);
   button.style.cursor = clientEnabled ? "pointer" : "default";
  }
 },
 ChangeNodeLinkEnabledAttributes: function (nodeLink, clientNode, clientEnabled) {
  if(!clientEnabled && nodeLink.href) {
   ASPx.Attr.SetAttribute(nodeLink, "savedhref", nodeLink.href);
   ASPx.Attr.RemoveAttribute(nodeLink, "href");
  }
  else if(clientEnabled && ASPx.Attr.GetAttribute(nodeLink, "savedhref")) {
   ASPx.Attr.SetAttribute(nodeLink, "href", ASPx.Attr.GetAttribute(nodeLink, "savedhref"));
   ASPx.Attr.RemoveAttribute(nodeLink, "savedhref");
  }
 },
 SetNodeText: function (clientNode, text) {
  if(this.IsRootNode(clientNode))
   return;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  var textSpan = this.renderHelper.GetNodeTextElement(contentElement);
  if(textSpan) {
   ASPx.SetInnerHtml(textSpan, text);
   this.CorrectControlWidth();
  }
 },
 SetNodeImageUrl: function (clientNode, url) {
  if(this.IsRootNode(clientNode))
   return;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  var nodeImage = this.renderHelper.GetNodeImageElement(contentElement);
  if(nodeImage)
   nodeImage.src = url;
 },
 GetNodeLinkElement: function (clientNode) {
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  return this.GetNodeLinkElementCore(contentElement);
 },
 GetNodeLinkElementCore: function(contentElement) {
  if(ASPx.ElementContainsCssClass(contentElement, TreeViewCssClasses.NodeTemplate))
   return null;
  return contentElement.tagName == "A" ? contentElement : ASPx.GetNodeByTagName(contentElement, "A", 0);
 },
 GetNodeNavigateUrl: function (clientNode) {
  if(this.contentBoundsMode || this.IsRootNode(clientNode))
   return clientNode.navigateUrl || "";
  var nodeLink = this.GetNodeLinkElement(clientNode);
  return nodeLink ? (nodeLink.href || ASPx.Attr.GetAttribute(nodeLink, "savedhref")) : "";
 },
 SetNodeNavigateUrl: function (clientNode, url) {
  if(this.IsRootNode(clientNode))
   return;
  var nodeLink = this.GetNodeLinkElement(clientNode);
  if(nodeLink) {
   if(ASPx.Attr.IsExistsAttribute(nodeLink, "savedhref"))
    ASPx.Attr.SetAttribute(nodeLink, "savedhref", url);
   else if(ASPx.Attr.IsExistsAttribute(nodeLink, "href"))
    nodeLink.href = url;
   clientNode.navigateUrl = url;
  }
 },
 GetInternalCheckBoxCheckedState: function(internalCheckBox) {
  return internalCheckBox.GetCurrentCheckState();
 },
 GetInternalCheckBoxInputKey: function(internalCheckBox) {
  return internalCheckBox.GetCurrentInputKey();
 },
 GetInternalCheckBoxInputElement: function(internalCheckBox) {
  return internalCheckBox.inputElement;
 },
 UpdateCheckedInNodesState: function (checkbox, needToSaveToCookies) {
  var contentElement = this.renderHelper.GetNodeContentElementByClick(checkbox);
  var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
  var value = this.GetInternalCheckBoxInputKey(internalCheckBox);
  var nodeID = this.GetNodeIDByContentElementID(contentElement.id);
  this.nodesState[2][nodeID] = value;
  if(needToSaveToCookies)
   this.UpdateNodesStateCookies();
 },
 UpdateRecursiveCheckedNodesStateOnCallback: function (checkState, nodeIDs) {
  this.HideLoadingPanel();
  for(var i = 0; i < nodeIDs.length; i++) {
   if(this.nodesState[2][nodeIDs[i]] != checkState)
    this.nodesState[2][nodeIDs[i]] = checkState;
  }
  this.UpdateNodesStateCookies();
 },
 UpdateInvisibleDescCheckedInNodesState: function(checkbox, checkState) {
  var contentElement = this.renderHelper.GetNodeContentElementByClick(checkbox),
   parentNodeID = this.GetNodeIDByContentElementID(contentElement.id),
   checkedNodesState = this.nodesState[2];
  for(var key in checkedNodesState) {
   if(checkedNodesState.hasOwnProperty(key) && key.indexOf(parentNodeID) === 0 && 
    parentNodeID !== key && !this.GetContentElementByNodeID(key))
    checkedNodesState[key] = checkState;
  }
 },
 CreateRecursiveNodeCheckRequest: function (contentElement) {
  var requestArgs = this.CreatePostRequestArgs(this.CheckNodeRecursiveCommand,
    this.GetNodeIDByContentElementID(contentElement.id));
  if(this.autoPostBack) {
   if(this.isInitialized)
    this.SendPostBack(requestArgs);
   return;
  }
  if(this.callBack) {
   var mainElement = this.GetMainElement();
   this.CreateLoadingDiv(mainElement);
   this.CreateLoadingPanelWithAbsolutePosition(mainElement);
   this.CreateCallback(requestArgs);
  }
 },
 OnNodeCheckboxClick: function (checkbox) {
  var contentElement = this.renderHelper.GetNodeContentElementByClick(checkbox);
  var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
  if(this.checkNodesRecursive) {
   var checkBoxState = this.GetInternalCheckBoxInputKey(internalCheckBox);
   this.UpdateCheckedStateRecursive(checkbox, checkBoxState);
  }
  var processOnServer = this.RaiseCheckedChanged(contentElement);
  if(this.checkNodesRecursive && !this.virtualMode && (this.autoPostBack || this.callBack))
   this.CreateRecursiveNodeCheckRequest(contentElement);
  else if(processOnServer) {
   var requestArgs = this.CreatePostRequestArgs(this.RaiseCheckedChangedEventCommand,
    this.GetNodeIDByContentElementID(contentElement.id));
   if(this.isInitialized)
    this.SendPostBack(requestArgs);
  }
 },
 UpdateCheckedStateRecursive: function(checkbox, state) {
  var listItem = ASPx.GetParentByTagName(checkbox, "LI");
  this.UpdateDescendantsCheckedState(listItem, state);
  this.UpdateInvisibleDescCheckedInNodesState(checkbox, state);
  this.UpdateAncestorsCheckedState(listItem);
  this.UpdateNodesStateCookies();
 },
 UpdateDescendantsCheckedState: function (listItem, state) {
  var subnodesList = this.renderHelper.GetSubNodesList(listItem);
  if(!subnodesList) {
   listItem.requireUpdateCheckedState = true;
   listItem.checkedState = state;
   return;
  }
  var descendantListItems = this.GetListItems(subnodesList);
  for(var i = 0; i < descendantListItems.length; i++) {
   var contentElement = this.renderHelper.GetNodeContentElement(descendantListItems[i]);
   var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
   if(internalCheckBox && internalCheckBox.GetValue() != state) {
    internalCheckBox.SetValue(state);
    this.UpdateCheckedInNodesState(this.GetInternalCheckBoxInputElement(internalCheckBox));
   }
   this.UpdateDescendantsCheckedState(descendantListItems[i], state);
  }
 },
 UpdateAncestorsCheckedState: function (listItem) {
  var parentSubnodesList = ASPx.GetParentByTagName(listItem, "UL");
  var parentListItem = ASPx.GetParentByTagName(parentSubnodesList, "LI");
  if(!parentListItem || !ASPx.GetParentById(parentListItem, this.name))
   return;
  var parentChecked = true;
  var parentUnchecked = true;
  var siblingListItems = this.GetListItems(parentSubnodesList);
  for(var i = 0; i < siblingListItems.length; i++) {
   var contentElement = this.renderHelper.GetNodeContentElement(siblingListItems[i]);
   var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
   if(internalCheckBox) {
    var currentCheckBoxState = this.GetInternalCheckBoxInputKey(internalCheckBox);
    if(currentCheckBoxState != ASPx.CheckBoxInputKey.Checked)
     parentChecked = false;
    if(currentCheckBoxState != ASPx.CheckBoxInputKey.Unchecked)
     parentUnchecked = false;
   }
  }
  var parentCheckboxContentElement = this.renderHelper.GetNodeContentElement(parentListItem);
  if(parentCheckboxContentElement) {
   var parentCheckBoxState = parentChecked ? ASPx.CheckBoxInputKey.Checked : (parentUnchecked ? ASPx.CheckBoxInputKey.Unchecked : ASPx.CheckBoxInputKey.Indeterminate);
   var parentInternalCheckBox = this.internalCheckBoxCollection.Get(parentCheckboxContentElement.id);
   if(parentInternalCheckBox && parentInternalCheckBox.GetValue() != parentCheckBoxState) {
    parentInternalCheckBox.SetValue(parentCheckBoxState);
    this.UpdateCheckedInNodesState(this.GetInternalCheckBoxInputElement(parentInternalCheckBox));
   }
  }
  this.UpdateAncestorsCheckedState(parentListItem);
 },
 SetNodeState: function (clientNode, state) {
  if(this.IsRootNode(clientNode))
   return;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  var checkbox = this.renderHelper.GetNodeCheckBoxElement(contentElement);
  var stateKey = ASPx.CheckBoxInputKey[state];
  var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
  if(internalCheckBox && internalCheckBox.GetValue() != stateKey) {
   internalCheckBox.SetValue(stateKey);
   this.UpdateCheckedInNodesState(this.GetInternalCheckBoxInputElement(internalCheckBox), true);
  }
  if(this.checkNodesRecursive && checkbox)
   this.UpdateCheckedStateRecursive(checkbox, stateKey);
 },
 GetNodeState: function (clientNode) {
  if(!this.internalCheckBoxCollection)
   return ASPx.CheckBoxCheckState.Unchecked;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  var internalCheckBox = this.internalCheckBoxCollection.Get(contentElement.id);
  return internalCheckBox ? this.GetInternalCheckBoxCheckedState(internalCheckBox) : ASPx.CheckBoxCheckState.Unchecked;
 },
 GetSelectedNodeIDFromState: function () {
  return this.nodesState ? this.nodesState[1] : "";
 },
 SetSelectedNodeIDToState: function (nodeID) {
  if(!this.nodesState || !ASPx.IsExists(this.nodesState[1]))
   return;
  this.nodesState[1] = nodeID;
  this.UpdateNodesStateCookies();
 },
 NavigateToNodeLink: function (contentElementID) {
  var navigateUrl = null;
  var target = null;
  if(this.rootNode.nodes.length > 0) {
   var clientNode = this.rootNode.GetNodeByContentElementID(contentElementID);
   navigateUrl = clientNode.navigateUrl;
   target = clientNode.target;
  } else {
   var nodeIndexPath = this.GetNodeIndexPathByContentElementID(contentElementID);
   if(!(this.nodesUrls && this.nodesUrls[nodeIndexPath]))
    return;
   navigateUrl = this.nodesUrls[nodeIndexPath][0];
   target = this.nodesUrls[nodeIndexPath][1];
  }
  if(navigateUrl)
   ASPx.Url.Navigate(navigateUrl, target || "");
 },
 ApplySelectionToNode: function (contentElement) {
  var previouslySelectedContentElement = ASPx.GetElementById(this.selectedNodeContentElementID);
  if(previouslySelectedContentElement)
   ASPx.GetStateController().DeselectElementBySrcElement(previouslySelectedContentElement);
  if(contentElement) {
   ASPx.GetStateController().SelectElementBySrcElement(contentElement);
   this.CorrectControlWidth();
   this.selectedNodeContentElementID = contentElement.id;
  } else
   this.selectedNodeContentElementID = null;
 },
 HandleNodeClick: function (e) {
  var contentElement = this.GetClickedContentElementByEventArgs(e);
  if(!contentElement)
   return;
  if(this.allowSelectNode && this.selectedNodeContentElementID != contentElement.id) {
   this.SetSelectedNodeIDToState(this.GetNodeIDByContentElementID(contentElement.id));
   ASPx.ClearHoverState();
   this.ApplySelectionToNode(contentElement);
   ASPx.UpdateHoverState(e);
  }
  var processEventOnServer = this.RaiseNodeClick(contentElement, e);
  if(contentElement.tagName != "A")
   this.NavigateToNodeLink(contentElement.id);
  var nodeLink = this.GetNodeLinkElementCore(contentElement);
  if(processEventOnServer && (!nodeLink || nodeLink.href === "" || nodeLink.href === ASPx.AccessibilityEmptyUrl)) {
   var postbackArgs = this.CreatePostRequestArgs(this.RaiseNodeClickEventCommand,
    this.GetNodeIDByContentElementID(contentElement.id));
   if(this.isInitialized)
    this.SendPostBack(postbackArgs);
  }
 },
 OnCallback: function (resultObj) {
  if(!resultObj)
   return;
  switch (resultObj[0]) {
   case this.ExpandNodeCommand: {
    if(resultObj[6]) {
     var newStateItemsScriptHtml = resultObj[6];
     eval(newStateItemsScriptHtml);
    }   
    if(resultObj[1])
     this.ProcessNodeExpandingOnCallback(resultObj[1], resultObj[2], resultObj[3], resultObj[4]);
    else
     this.ProcessAllNodesExpandingOnCallback(resultObj[2], resultObj[3], resultObj[4], resultObj[5][0]);
    break;
   }
   case this.CheckNodeRecursiveCommand:
    this.UpdateRecursiveCheckedNodesStateOnCallback(resultObj[1], resultObj[2]);
    break;
  }
  if(resultObj[5])
   this.UpdateNodesStateCookies();
 },
 OnCallbackFinalized: function() {
  this.InitializeNodeSelection();
 },
 GetSampleNodeLoadingPanel: function () {
  return ASPx.GetElementById(this.name + this.SampleNodeLoadingPanelIDPostfix);
 },
 GetNodeLoadingPanelID: function (nodeID) {
  return this.name + this.NodeLoadingPanelIDPostfix + nodeID;
 },
 ShowNodeLoadingPanel: function (button, nodeID) {
  var sampleLoadingPanel = this.GetSampleNodeLoadingPanel();
  if(!sampleLoadingPanel || !button) {
   var mainElement = this.GetMainElement();
   this.CreateLoadingDiv(mainElement);
   this.CreateLoadingPanelWithAbsolutePosition(mainElement);
  }
  else
   this.ShowNodeLoadingPanelCore(button, sampleLoadingPanel, nodeID);
 },
 ShowNodeLoadingPanelCore: function (button, sampleLoadingPanel, nodeID) {
  var elbowSpan = ASPx.GetParentByTagName(button, "SPAN");
  var panel = this.CloneNodeLoadingPanel(sampleLoadingPanel, nodeID, elbowSpan);
  ASPx.SetElementDisplay(panel, true);
  this.SetNodeLoadingPanelPosition(panel, button, elbowSpan);
  ASPx.SetElementDisplay(button, false);
 },
 HideNodeLoadingPanel: function (nodeID) {
  var panel = ASPx.GetElementById(this.GetNodeLoadingPanelID(nodeID));
  if(panel)
   ASPx.RemoveElement(panel);
 },
 SetNodeLoadingPanelPosition: function (panel, button, elbowSpan) {
  elbowSpan.style.position = "relative";
  var buttonStyle = ASPx.GetCurrentStyle(button);
  var marginLeft = parseInt(buttonStyle.marginLeft);
  var marginTop = parseInt(buttonStyle.marginTop);
  var leftOffset = marginLeft - Math.round((this.nodeLoadingPanelWidth - button.offsetWidth) / 2);
  var topOffset = marginTop - Math.round((this.nodeLoadingPanelHeight - button.offsetHeight) / 2);
  elbowSpan.style.position = "";
  if(this.IsRightToLeft())
   panel.style.marginRight = elbowSpan.offsetWidth - this.nodeLoadingPanelWidth - leftOffset + "px";
  else
   panel.style.marginLeft = leftOffset + "px";
  panel.style.marginTop = topOffset + "px";
 },
 CloneNodeLoadingPanel: function (sampleLoadingPanel, nodeID, elbowSpan) {
  var clonedPanel = sampleLoadingPanel.cloneNode(true);
  clonedPanel.id = this.GetNodeLoadingPanelID(nodeID);
  clonedPanel.dir = "ltr";
  elbowSpan.appendChild(clonedPanel);
  return clonedPanel;
 },
 GetSampleExpandButton: function () {
  return ASPx.GetElementById(this.name + this.SampleExpandButtonIDPostfix);
 },
 GetSampleCollapseButton: function () {
  return ASPx.GetElementById(this.name + this.SampleCollapseButtonIDPostfix);
 },
 SetExpandedToState: function (nodeID, expanded) {
  this.nodesState[0][nodeID] = this.SerializeBooleanValue(expanded);
  this.UpdateNodesStateCookies();
 },
 GetExpandedDataFromState: function () {
  return this.nodesState[0];
 },
 HandleNodeDblClick: function (e) {
  var contentElement = this.GetClickedContentElementByEventArgs(e);
  if(!contentElement)
   return;
  var listItem = ASPx.GetParentByTagName(contentElement, "LI");
  var button = this.renderHelper.GetNodeButtonElement(listItem);
  var expandedState = this.GetExpandedDataFromState();
  var nodeID = this.GetNodeIDByContentElementID(contentElement.id);
  if(!button && !ASPx.IsExists(expandedState[nodeID]))
   return;
  this.ProcessUserInitiatedExpandCollapse(button, listItem);
 },
 InsertSubnodesListMarkup: function (listItem, subnodesListMarkup) {
  var fakeDiv = document.createElement("DIV");
  ASPx.SetInnerHtml(fakeDiv, subnodesListMarkup);
  while(fakeDiv.childNodes.length != 0)
   listItem.appendChild(fakeDiv.childNodes[0]);
 },
 InsertRootSubnodesListMarkup: function(contentDiv, rootSubnodesListMarkup) {
  contentDiv.innerHTML = rootSubnodesListMarkup;
 },
 ProcessAllNodesExpandingOnCallback: function (subnodesListMarkup, nodesData, nodeNames, expandedState) {
  this.HideLoadingPanel();
  this.nodesState[0] = expandedState;
  this.UpdateNodesStateCookies();
  this.MergeRetrievedOnCallbackNodeInfo(nodesData, nodeNames);
  var contentDiv = this.GetControlContentDiv();
  this.InsertRootSubnodesListMarkup(contentDiv, subnodesListMarkup);
  var subnodesList = this.renderHelper.GetSubNodesList(contentDiv);
  this.rootNode.nodes = [];
  this.renderHelper.InitializeNodeContainerElements(subnodesList, "", null);
  this.AdjustControl();
 },
 MergeRetrievedOnCallbackNodeInfo: function (nodesData, nodeNames) {
  if(nodesData) {
   var destData = this.nodesInfo || this.nodesUrls;
   this.MergeNodesData(nodesData, destData);
  }
  if(nodeNames) {
   this.MergeNodesData(nodeNames, this.nodesState[3]);
   this.UpdateNodesStateCookies();
  }
 },
 ProcessNodeExpandingOnCallback: function (nodeID, subnodesListMarkup, nodesData, nodeNames) {
  this.MergeRetrievedOnCallbackNodeInfo(nodesData, nodeNames);
  var contentElement = this.GetContentElementByNodeID(nodeID);
  contentElement.performingExpandNodeRequest = false;
  this.HideNodeLoadingPanel(this.GetNodeIDByContentElementID(contentElement.id));
  var listItem = ASPx.GetParentByTagName(contentElement, "LI");
  this.InsertSubnodesListMarkup(listItem, subnodesListMarkup);
  var subnodesList = this.renderHelper.GetSubNodesList(listItem);
  var nodeIndexPath = this.GetNodeIndexPathByContentElementID(contentElement.id);
  var clientNode = null;
  if(this.rootNode.nodes.length > 0)
   clientNode = this.rootNode.GetNodeByContentElementID(contentElement.id);
  this.renderHelper.InitializeNodeContainerElements(subnodesList, nodeIndexPath, clientNode);
  if(listItem.requireUpdateCheckedState)
   this.UpdateDescendantsCheckedState(listItem, listItem.checkedState);
  if(this.checkNodesRecursive) {
   var listItems = this.GetListItems(subnodesList);
   if(listItems)
    this.UpdateAncestorsCheckedState(listItems[0]);
  }
  var button = this.renderHelper.GetNodeButtonElement(listItem);
  this.PerformNodeExpand(subnodesList, button);
 },
 HandleExpandButtonClick: function (e) {
  var button = this.GetExpandButton(e);
  var listItem = ASPx.GetParentByTagName(button, "LI");
  this.ProcessUserInitiatedExpandCollapse(button, listItem);
 },
 GetExpandButton: function(e) {
  return ASPx.GetParentByClassName(ASPx.Evt.GetEventSource(e), TreeViewCssClasses.Button);
 },
 HandleExpandButtonAccessibleMouseDown: function(e) {
  if(ASPx.Evt.IsLeftButtonPressed(e))
   this.requireClearExpandButtonOutline = true;
 },
 HandleExpandButtonAccessibleBlur: function(e) {
  if(this.requireClearExpandButtonOutline)
   return;
  var button = this.GetExpandButton(e);
  var listItem = ASPx.GetParentByTagName(button, "LI");
  ASPx.RemoveClassNameFromElement(listItem, TreeViewCssClasses.AccessibleNode);
 },
 ProcessUserInitiatedExpandCollapse: function (button, listItem) {
  var contentElement = this.renderHelper.GetNodeContentElement(listItem);
  if(contentElement.performingExpandNodeRequest)
   return;
  var expandedChangingResults = this.RaiseExpandedChanging(listItem);
  if(expandedChangingResults.cancel)
   return;
  this.ToggleNodeExpandCollapse(listItem, button, true, expandedChangingResults.processOnServer);
 },
 ToggleNodeExpandCollapse: function (listItem, button, requireRaiseExpandedChanged, processOnServer) {
  var subnodesList = this.renderHelper.GetSubNodesList(listItem);
  var expanding = !subnodesList || !ASPx.GetElementDisplay(subnodesList);
  var contentElement = this.renderHelper.GetNodeContentElement(listItem);
  if(processOnServer) {
   var requestArgs = this.CreatePostRequestArgs(this.RaiseExpandedChangingEventCommand,
    this.GetNodeIDByContentElementID(contentElement.id), this.SerializeBooleanValue(expanding));
   if(this.isInitialized)
    this.SendPostBack(requestArgs);
   return;
  }
  this.SetExpandedToState(this.GetNodeIDByContentElementID(contentElement.id), expanding);
  if(requireRaiseExpandedChanged)
   this.requireRaiseExpandedChangedList.push(contentElement.id);
  if(subnodesList) {
   if(expanding)
    this.PerformNodeExpand(subnodesList, button);
   else
    this.PerformNodeCollapse(subnodesList, button);
   this.ToggleNodeAriaExpanded(contentElement, expanding);
  }
  else {
   contentElement.performingExpandNodeRequest = true;
   this.SendExpandNodePostRequest(contentElement.id, button);
  }
 },
 ToggleNodeAriaExpanded: function(contentElement, expanding){
  if(this.accessibilityCompliant)
   ASPx.Attr.Aria.SetExpanded(contentElement, expanding);
 },
 SendExpandNodePostRequest: function (contentElementID, button) {
  var requestArgs = this.CreatePostRequestArgs(this.ExpandNodeCommand,
   this.GetNodeIDByContentElementID(contentElementID));
  if(this.autoPostBack || !this.callBack) {
   if(this.isInitialized)
    this.SendPostBack(requestArgs);
   return;
  }
  this.ShowNodeLoadingPanel(button, this.GetNodeIDByContentElementID(contentElementID));
  this.CreateCallback(requestArgs);
 },
 StartExpandCollapseAnimation: function (subnodesList, expanding) {
  var height = subnodesList.offsetHeight;
  if(expanding)
   ASPx.SetOffsetHeight(subnodesList, 0);
  ASPx.AnimationHelper.createAnimationTransition(subnodesList, {
   animationEngineType: ASPx.AnimationEngineType.JS, 
   property: "height", unit: "px",
   duration: height > 120 ? this.AnimationDuration : this.MinAnimationDuration,
   onComplete: function (el) {
    this.OnCompleteAnimation(el, expanding);
   }.aspxBind(this)
  }).Start(expanding ? 0 : height, expanding ? height : 0);
 },
 OnCompleteAnimation: function (element, expanding) {
  element.style.height = "";
  if(!expanding) {
   ASPx.SetElementDisplay(element, false);
   this.CorrectControlWidth();
  }
  this.RaiseExpandedChanged(element);
 },
 ReplaceExpandButtonWithSampleButton: function (button, sampleButton) {
  var newButton = this.ReplaceElementWithSampleElement(button, sampleButton, false);
  var listItem = ASPx.GetParentByTagName(newButton, "LI");
  var contentElement = this.renderHelper.GetNodeContentElement(listItem);
  if(this.renderHelper.CanAttachExpandButtonHandler(contentElement))
   this.ToggleExpandButtonHandlers(true, newButton);
  else
   newButton.style.cursor = "default";
  if(this.accessibilityCompliant) {
   if(this.requireClearExpandButtonOutline) {
    ASPx.AddClassNameToElement(listItem, TreeViewCssClasses.AccessibleNode);
    this.requireClearExpandButtonOutline = false;
   }
   newButton.focus();
  }
 },
 AccomplishExpandCollapse: function (expandButton, sampleButton, subnodesList) {
  if(expandButton)
   this.ReplaceExpandButtonWithSampleButton(expandButton, sampleButton);
  if(!this.enableAnimation)
   this.RaiseExpandedChanged(subnodesList);
 },
 PerformNodeExpand: function(subnodesList, expandButton) {
  var prevWidth = (this.enableNodeTextWrapping) ? this.GetMainElement().offsetWidth : 0;
  ASPx.SetElementDisplay(subnodesList, true);
  if(this.enableNodeTextWrapping && this.GetMainElement().offsetWidth !== prevWidth)
   this.AdjustControlCore();
  else {
   this.UpdateWordWrapNodesWidth(subnodesList);
   this.CorrectControlWidth();
  }
  if(this.enableAnimation)
   this.StartExpandCollapseAnimation(subnodesList, true);
  this.AccomplishExpandCollapse(expandButton, this.GetSampleCollapseButton(), subnodesList);
 },
 PerformNodeCollapse: function (subnodesList, expandButton) {
  if(this.enableAnimation)
   this.StartExpandCollapseAnimation(subnodesList, false);
  else {
   ASPx.SetElementDisplay(subnodesList, false);
   this.CorrectControlWidth();
  }
  this.AccomplishExpandCollapse(expandButton, this.GetSampleExpandButton(), subnodesList);
 },
 GetNodeExpanded: function (clientNode) {
  if(this.IsRootNode(clientNode))
   return true;
  var expandedState = this.GetExpandedDataFromState();
  var nodeID = this.GetNodeIDByContentElementID(clientNode.contentElementID);
  if(ASPx.IsExists(expandedState[nodeID]))
   return !!expandedState[nodeID];
  return false;
 },
 SetNodeExpanded: function (clientNode) {
  if(this.IsRootNode(clientNode))
   return;
  var contentElement = ASPx.GetElementById(clientNode.contentElementID);
  if(contentElement.performingExpandNodeRequest)
   return;
  var listItem = this.GetNodeListItem(clientNode);
  var button = this.renderHelper.GetNodeButtonElement(listItem);
  var nodeID = this.GetNodeIDByContentElementID(clientNode.contentElementID);
  var expandedState = this.GetExpandedDataFromState();
  if(!button && !ASPx.IsExists(expandedState[nodeID]))
   return;
  if(this.accessibilityCompliant)
   this.requireClearExpandButtonOutline = true;
  this.ToggleNodeExpandCollapse(listItem, button, false, false);
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ nodesState: this.nodesState });
 },
 UpdateNodesStateCookies: function() {
  if(this.cookieName) {
   ASPx.Cookie.DelCookie(this.cookieName);
   ASPx.Cookie.SetCookie(this.cookieName, this.GetClientStateString());
  }
 },
 GetClientStateString: function() {
  return ASPx.Json.ToJson(this.nodesState);
 },
 AreChildNodesLoaded: function (node) {
  var listItem = this.GetNodeListItem(node);
  var button = this.renderHelper.GetNodeButtonElement(listItem);
  return !button || !!this.renderHelper.GetSubNodesList(listItem);
 },
 CreateNodeClickEventArgs: function(processOnServer, node, htmlElement, htmlEvent) {
  return new ASPxClientTreeViewNodeClickEventArgs(processOnServer, node, htmlElement, htmlEvent);
 },
 CreateNodeEventArgs: function(node) {
  return new ASPxClientTreeViewNodeEventArgs(node);
 },
 CreateNodeCancelEventArgs: function(processOnServer, node) {
  return new ASPxClientTreeViewNodeCancelEventArgs(processOnServer, node);
 },
 CreateNodeProcessingModeEventArgs: function(processOnServer, node) {
  return new ASPxClientTreeViewNodeProcessingModeEventArgs(processOnServer, node);
 },
 RaiseNodeClick: function (contentElement, htmlEvent) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned(this.NodeClickServerEventName);
  if(!this.NodeClick.IsEmpty()) {
   var clientNode = this.rootNode.GetNodeByContentElementID(contentElement.id);
   var args = this.CreateNodeClickEventArgs(processOnServer, clientNode, contentElement, htmlEvent);
   this.NodeClick.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 RaiseExpandedChanged: function (subnodesList) {
  if(this.ExpandedChanged.IsEmpty())
   return;
  var listItem = ASPx.GetParentByTagName(subnodesList, "LI");
  var contentElement = this.renderHelper.GetNodeContentElement(listItem);
  var nodeIndex = ASPx.Data.ArrayIndexOf(this.requireRaiseExpandedChangedList, contentElement.id);
  if(nodeIndex < 0)
   return;
  this.requireRaiseExpandedChangedList.splice(nodeIndex, 1);
  var clientNode = this.rootNode.GetNodeByContentElementID(contentElement.id);
  var args = this.CreateNodeEventArgs(clientNode);
  this.ExpandedChanged.FireEvent(this, args);
 },
 RaiseExpandedChanging: function (listItem) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned(this.ExpandedChangingServerEventName);
  var contentElement = this.renderHelper.GetNodeContentElement(listItem);
  var clientNode = this.rootNode.GetNodeByContentElementID(contentElement.id);
  var args = this.CreateNodeCancelEventArgs(processOnServer, clientNode);
  if(!this.ExpandedChanging.IsEmpty())
   this.ExpandedChanging.FireEvent(this, args);
  return args;
 },
 RaiseCheckedChanged: function (contentElement) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned(this.CheckedChangedServerEventName);
  if(!this.CheckedChanged.IsEmpty()) {
   var clientNode = this.rootNode.GetNodeByContentElementID(contentElement.id);
   var args = this.CreateNodeProcessingModeEventArgs(processOnServer, clientNode);
   this.CheckedChanged.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 GetNode: function (index) {
  return this.rootNode.GetNode(index);
 },
 GetNodeByName: function (name) {
  return this.rootNode.GetNodeByName(name);
 },
 GetNodeByText: function (text) {
  return this.rootNode.GetNodeByText(text);
 },
 GetNodeCount: function () {
  return this.rootNode.GetNodeCount();
 },
 GetSelectedNode: function () {
  return this.rootNode.GetNodeByContentElementID(this.selectedNodeContentElementID);
 },
 SetSelectedNode: function (node) {
  if(node && (node.treeView != this || this.IsRootNode(node)) || !this.allowSelectNode)
   return;
  var contentElement = node ? ASPx.GetElementById(node.contentElementID) : null;
  var selectedNodeID = contentElement ? this.GetNodeIDByContentElementID(contentElement.id) : "";
  this.SetSelectedNodeIDToState(selectedNodeID);
  this.ApplySelectionToNode(contentElement);
 },
 GetRootNode: function () {
  return this.rootNode;
 },
 IsRootNode: function (clientNode) {
  return clientNode == this.rootNode;
 },
 ExpandCollapseNodesRecursive: function (clientNodes, expand) {
  for(var i = 0; i < clientNodes.length; i++) {
   clientNodes[i].SetExpanded(expand);
   if(clientNodes[i].nodes.length > 0)
    this.ExpandCollapseNodesRecursive(clientNodes[i].nodes, expand);
  }
 },
 CollapseAll: function () {
  if(this.rootNode.nodes.length == 0)
   return;
  this.ExpandCollapseNodesRecursive(this.rootNode.nodes, false);
 },
 ExpandAll: function () {
  if(this.rootNode.nodes.length == 0)
   return;
  var postRequestArgs = this.CreatePostRequestArgs(this.ExpandAllNodesCommand, "");
  if(this.autoPostBack) {
   if(this.isInitialized)
    this.SendPostBack(postRequestArgs);
   return;
  }
  if(this.callBack && !this.IsAllNodesLoadedRecursive(this.rootNode.nodes)) {
   var mainElement = this.GetMainElement();
   this.CreateLoadingDiv(mainElement);
   this.CreateLoadingPanelWithAbsolutePosition(mainElement);
   this.CreateCallback(postRequestArgs);
   return;
  }
  this.ExpandCollapseNodesRecursive(this.rootNode.nodes, true);
 },
 IsAllNodesLoadedRecursive: function(nodes) {
  for(var i = 0; i < nodes.length; i++) {
   var clientNode = nodes[i],
    listItem = this.GetNodeListItem(clientNode),
    expandedState = this.GetExpandedDataFromState(),
    nodeID = this.GetNodeIndexPathByContentElementID(clientNode.contentElementID);
    hasSubnodes = !!ASPx.IsExists(expandedState["N" + nodeID]);
   if(hasSubnodes && (!this.renderHelper.GetSubNodesList(listItem) || !this.IsAllNodesLoadedRecursive(clientNode.nodes)))
    return false;
  }
  return true;
 }
});
ASPxClientTreeView.Cast = ASPxClientControl.Cast;
var ASPxClientTreeViewNode = ASPx.CreateClass(null, {
 constructor: function (treeView, parent, index, name) {
  this.treeView = treeView;
  this.parent = parent;
  this.index = index;
  this.name = name;
  this.enabled = true;
  this.clientEnabled = true;
  this.clientVisible = true;
  this.navigateUrl = null;
  this.target = null;
  this.text = null;
  this.imageUrl = null;
  this.nodes = [];
  this.contentElementID = null;
  this.last = false;
 },
 GetNodeCount: function () {
  return this.nodes.length;
 },
 GetNode: function (index) {
  return (index >= 0 && index < this.nodes.length) ? this.nodes[index] : null;
 },
 GetNodeBySelector: function (selector) {
  for(var i = 0; i < this.nodes.length; i++) {
   if(selector(this.nodes[i]))
    return this.nodes[i];
   var foundNode = this.nodes[i].GetNodeBySelector(selector);
   if(foundNode)
    return foundNode;
  }
  return null;
 },
 GetNodeByContentElementID: function (contentElementID) {
  return this.GetNodeBySelector(function (node) { return node.contentElementID == contentElementID; });
 },
 SetCheckState: function (value) {
  this.treeView.SetNodeState(this, value);
 },
 GetNodeByName: function (name) {
  return this.GetNodeBySelector(function (node) { return node.name == name; });
 },
 GetNodeByText: function (text) {
  return this.GetNodeBySelector(function (node) { return node.GetText() == text; });
 },
 GetExpanded: function () {
  return this.treeView.GetNodeExpanded(this);
 },
 SetExpanded: function (value) {
  if(this.GetExpanded() == value)
   return;
  this.treeView.SetNodeExpanded(this);
 },
 GetChecked: function () {
  return this.GetCheckState() == ASPx.CheckBoxCheckState.Checked;
 },
 SetChecked: function (value) {
  this.SetCheckState(value ? ASPx.CheckBoxCheckState.Checked : ASPx.CheckBoxCheckState.Unchecked);
 },
 GetCheckState: function () {
  return this.treeView.GetNodeState(this);
 },
 GetEnabled: function () {
  return this.enabled && this.clientEnabled;
 },
 SetEnabled: function (value) {
  this.clientEnabled = value;
  this.treeView.SetNodeClientEnabled(this, this.clientEnabled);
 },
 GetImageUrl: function () {
  return this.imageUrl || "";
 },
 SetImageUrl: function (value) {
  this.imageUrl = value;
  this.treeView.SetNodeImageUrl(this, value);
 },
 GetNavigateUrl: function () {
  return this.treeView.GetNodeNavigateUrl(this);
 },
 SetNavigateUrl: function (value) {
  this.treeView.SetNodeNavigateUrl(this, value);
 },
 GetText: function () {
  var nbspChar = String.fromCharCode(160);
  return this.text ? this.text.replace(new RegExp(nbspChar, "g"), " ") : "";
 },
 SetText: function (value) {
  this.text = value;
  this.treeView.SetNodeText(this, value);
 },
 GetVisible: function () {
  return this.clientVisible;
 },
 SetVisible: function (value) {
  this.clientVisible = value;
  this.treeView.SetNodeClientVisible(this, this.clientVisible);
 },
 GetHtmlElement: function () {
  return ASPx.GetElementById(this.contentElementID);
 }
});
var ASPxClientTreeViewNodeProcessingModeEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function (processOnServer, node) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.node = node;
 }
});
var ASPxClientTreeViewNodeClickEventArgs = ASPx.CreateClass(ASPxClientTreeViewNodeProcessingModeEventArgs, {
 constructor: function (processOnServer, node, htmlElement, htmlEvent) {
  this.constructor.prototype.constructor.call(this, processOnServer, node);
  this.htmlElement = htmlElement;
  this.htmlEvent = htmlEvent;
 }
});
var ASPxClientTreeViewNodeEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (node) {
  this.node = node;
 }
});
var ASPxClientTreeViewNodeCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
 constructor: function (processOnServer, node) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.node = node;
 }
});
ASPx.TreeViewRenderHelper = TreeViewRenderHelper;
window.ASPxClientTreeView = ASPxClientTreeView;
window.ASPxClientTreeViewNode = ASPxClientTreeViewNode;
window.ASPxClientTreeViewNodeProcessingModeEventArgs = ASPxClientTreeViewNodeProcessingModeEventArgs;
window.ASPxClientTreeViewNodeClickEventArgs = ASPxClientTreeViewNodeClickEventArgs;
window.ASPxClientTreeViewNodeEventArgs = ASPxClientTreeViewNodeEventArgs;
window.ASPxClientTreeViewNodeCancelEventArgs = ASPxClientTreeViewNodeCancelEventArgs;
})();

(function() {
var GridDragHelperBase = ASPx.CreateClass(null, {
 maxRepeatScrollTimeout : 30,
 updateTargetPositionTimeout: 50,
 scrollingStep: 1,
 constructor: function() {
  this.isHorzDrag = false;
  this.savedPositions = { };
  this.rect = null;
 },
 GetActiveTargets: function() { return [ ]; },
 GetScrollHelper: function() { return null; },
 GetExtraCellWidth: function() { return 0; },
 GetCustomizationWindowElement: function() { return null; },
 GetScrollableControl: function() { 
  var helper = this.GetScrollHelper();
  return this.isHorzDrag ? helper.GetHorzScrollableControl() : helper.GetVertScrollableControl();
 },
 OnDragCreated: function(isHorzDrag) {
  if(this.NeedScrollOnDrag(isHorzDrag))
   this.InitializeDragScrolling(isHorzDrag);
 },
 InitializeDragScrolling: function(isHorzDrag) {
  this.isHorzDrag = isHorzDrag;
  this.SaveControlDimensions();
  this.mouseMoveHandler = function(e) { this.OnMouseMove(e); }.aspxBind(this);
  ASPx.Evt.AttachEventToDocument("mousemove", this.mouseMoveHandler);
 },
 SaveControlDimensions: function() {
  var scrollableControl = this.GetScrollableControl();
  var visibility = ASPx.GetElementDisplay(scrollableControl);
  ASPx.SetElementDisplay(scrollableControl, true);
  var scrollDivX = ASPx.GetAbsoluteX(scrollableControl);
  var scrollDivY = ASPx.GetAbsoluteY(scrollableControl);
  var width = scrollableControl.offsetWidth;
  var height = scrollableControl.offsetHeight;
  ASPx.SetElementDisplay(scrollableControl, visibility);
  this.SaveControlDimensionsCore(scrollDivX, width, scrollDivY, height);
 },
 SaveControlDimensionsCore: function(scrollDivX, width, scrollDivY, height) {
  this.rect = { 
   left: scrollDivX, 
   right: scrollDivX + width - this.GetExtraCellWidth(),
   top: scrollDivY,
   bottom: scrollDivY + height
  };
 },
 NeedScrollOnDrag: function(isHorzDrag) {
  var helper = this.GetScrollHelper();
  if(!helper || (isHorzDrag && !helper.HasHorzScroll()) || !isHorzDrag && !helper.HasVertScroll())
   return false;
  return ASPx.Browser.Firefox || helper.HasVertScroll();
 },
 OnMouseMove: function(e) {
  var pos = this.isHorzDrag ? ASPx.Evt.GetEventX(e) : ASPx.Evt.GetEventY(e);
  if(pos === this.savedPositions[this.isHorzDrag])
   return;
  var line = { 
   start:  this.isHorzDrag ? this.rect.left  : this.rect.top,
   end: this.isHorzDrag ? this.rect.right : this.rect.bottom
  };
  var isLeft = pos < line.start;
  var diff = isLeft ? line.start - pos : pos - line.end;
  if(diff <= 0) {
   this.CancelScrolling();
   return;
  }
  this.repeatScrollTimeout = diff < this.maxRepeatScrollTimeout ? this.maxRepeatScrollTimeout - diff : 1;
  this.scrollInc = this.scrollingStep * (isLeft ? -1 : 1);
  this.savedPositions[this.isHorzDrag] = pos;
  this.StartScrolling(this.isHorzDrag);
 },
 StartScrolling: function() {
  if(this.scrollingProcessing)
   return;
  this.scrollingProcessing = true;
  this.scrollHandler = this.RepeatScrolling();
 },
 CancelDrag: function() {
  if(this.mouseMoveHandler)
   ASPx.Evt.DetachEventFromDocument("mousemove", this.mouseMoveHandler);
  this.CancelScrolling();
 },
 CancelScrolling: function() {
  this.scrollingProcessing = false;
  this.scrollHandler = ASPx.Timer.ClearTimer(this.scrollHandler);
 },
 RepeatScrolling: function() {
  var scrollableControl = this.GetScrollableControl();
  if(this.isHorzDrag)
   scrollableControl.scrollLeft += this.scrollInc;
  else
   scrollableControl.scrollTop += this.scrollInc;
  return window.setTimeout(function() { this.scrollHandler = this.RepeatScrolling(); }.aspxBind(this), this.repeatScrollTimeout);
 },
 UpdateTargetPositionPostponed: function() {
  if(!this.GetActiveTargets().length)
   return;
  this.updateTargetPositionTimerID = ASPx.Timer.ClearTimer(this.updateTargetPositionTimerID);
  this.updateTargetPositionTimerID = window.setTimeout(function() { this.UpdateTargetPosition(); }.aspxBind(this), this.updateTargetPositionTimeout);
 },
 UpdateTargetPosition: function() { 
  var targets = this.GetActiveTargets();
  for(var i = 0; i < targets.length; i++)
   targets[i].UpdatePosition();
 },
 OnHeaderTargetAllowed: function(targetElement, x, y) {
  if(!this.rect)
   return true;
  var custWin = this.GetCustomizationWindowElement();
  var inRect = x >= this.rect.left && x <= this.rect.right;
  return inRect || custWin === targetElement;
 },
 UpdateScrollableControlsOnDrag: function(src) {
  this.UpdateTargetPositionPostponed();
  var helper = this.GetScrollHelper();
  var contentScrollDiv = helper.GetScrollDiv(helper.GetContentTable());
  if(contentScrollDiv === src && helper.HasVertScroll()) {
   var scrollDivs = [ helper.GetScrollDiv(helper.GetHeaderTable()), helper.GetScrollDiv(helper.GetFooterTable()) ];
   for(var i = 0; i < scrollDivs.length; i++)
    if(scrollDivs[i])
     scrollDivs[i].scrollLeft = src.scrollLeft;
  }
 }
});
var BatchEditApi = ASPx.CreateClass(null, {
 constructor: function(owner) {
  this.owner = owner;
 },
 GetHelper: function() { return this.owner.GetBatchEditHelper(); },
 GetColumnIndex: function(column) {  },
 CreateControlCellInfo: function(key, column) { },
 SetCellValueCore: function(key, column, value, displayText, cancelCellHighlighting) {
  var helper = this.GetHelper();
  var columnIndex = this.GetColumnIndex(column);
  if(!helper || columnIndex === null) 
   return;
  if(!helper.IsValidRecord(key) || !helper.IsEditableColumn(columnIndex))
   return;
  if(helper.IsEditingCell(key, columnIndex))
   return;
  if(!ASPx.IsExists(displayText))
   displayText = helper.GetColumnDisplayTextByEditor(value, columnIndex);
  if(helper.IsCheckColumn(columnIndex))
   displayText = helper.GetCheckColumnDisplayText(value, columnIndex);
  if(helper.IsColorEditColumn(columnIndex))
   displayText = helper.GetColorEditColumnDisplayText(value, columnIndex);
  helper.SetCellValue(key, columnIndex, value, displayText, cancelCellHighlighting);
  helper.ResetCellValidationState(key, columnIndex);
  helper.UpdateSyncInput(); 
  helper.UpdateItem(key, [columnIndex], false, false, true);
  helper.UpdateCommandButtonsEnabled();
  helper.RemoveRecordErrorIfHasNoChanges(key);
 },
 GetColumnDisplayText: function(column, value) {
  var helper = this.GetHelper();
  var columnIndex = this.GetColumnIndex(column);
  if(!helper || columnIndex === null) 
   return;
  return helper.GetColumnDisplayTextByEditor(value, columnIndex);
 },
 GetCellValueCore: function(key, column, initial) {
  var helper = this.GetHelper();
  var columnIndex = this.GetColumnIndex(column);
  if(!helper || columnIndex === null) return;
  return helper.GetCellValue(key, columnIndex, initial);
 },
 GetCellTextContainerCore: function(key, column) {
  var helper = this.GetHelper();
  var columnIndex = this.GetColumnIndex(column);
  if(!helper || columnIndex === null) return;
  return helper.GetCellTextContainer(key, columnIndex);
 },
 HasChangesCore: function(key, column) {
  var helper = this.GetHelper();
  if(!helper) return false;
  var columnIndex = this.GetColumnIndex(column);
  return helper.HasChanges(key, columnIndex);
 },
 ResetChangesCore: function(key, columnIndex) {
  var helper = this.GetHelper();
  if(!helper) return;
  helper.ResetChanges(key, columnIndex);
  helper.UpdateCommandButtonsEnabled();
 },
 StartEditCore: function(key, columnIndex) {
  var helper = this.GetHelper();
  if(!helper) return;
  helper.StartEdit(key, columnIndex);
 },
 EndEdit: function() {
  var helper = this.GetHelper();
  if(!helper || helper.GetFocusHelper().lockUserEndEdit) 
   return;
  helper.EndEdit();
 },
 MoveFocusBackward: function() {
  var helper = this.GetHelper();
  if(!helper) return;
  return helper.GetFocusHelper().MoveFocusPrev();
 },
 MoveFocusForward: function() {
  var helper = this.GetHelper();
  if(!helper) return;
  return helper.GetFocusHelper().MoveFocusNext();
 },
 IsColumnEdited: function(column) {
  var helper = this.GetHelper();
  if(!helper || !column) return false;
  return helper.IsColumnEdited(this.GetColumIndex(column));
 },
 ValidateItems: function(validateOnlyModified, validateOnCurrentPageOnly) {
  var helper = this.GetHelper();
  if(!helper) return false;
  return !!helper.UserValidateItems(null, validateOnlyModified, validateOnCurrentPageOnly).isValid;
 },
 ValidateRecordCore: function(key) {
  var helper = this.GetHelper();
  if(!helper) return false;
  return !!helper.UserValidateItems(key).isValid;
 }, 
 IsDeletedRecordCore: function(key) {
  var helper = this.GetHelper();
  return helper ? helper.IsDeletedRecord(key) : false;
 },
 IsNewRecordCore: function(key) {
  var helper = this.GetHelper();
  if(!helper) return false;
  return helper.IsNewRecord(key);
 },
 GetEditCellInfo: function() {
  var helper = this.GetHelper();
  if(!helper || !helper.IsEditing()) 
   return null;
  var column = helper.GetFocusedColumn();  
  if(column && !helper.IsColumnEditing(column.index))
   column = null;
  return this.CreateControlCellInfo(helper.GetEditingRecordKey(), column);
 },
 AddNewRecordCore: function(parentRecordKey) {
  var helper = this.GetHelper();
  if(helper)
   helper.AddNewRecord(parentRecordKey);
 },
 DeleteRecordCore: function(key) {
  var helper = this.GetHelper();
  if(helper)
   helper.DeleteItem(key);
 },
 RecoverRecordCore: function(key) {
  var helper = this.GetHelper();
  if(helper)
   helper.RecoverRecord(key);
 },
 GetRecordKeys: function(includeDeleted) {
  var helper = this.GetHelper();
  if(!helper) return [ ];
  return helper.GetRecordKeys(!includeDeleted);
 },
 GetInsertedRecordKeys: function() {
  var helper = this.GetHelper();
  if(!helper) return [ ];
  var indices = helper.GetInsertedRecordKeys();
  if(helper.IsNewItemOnTop())
   indices.reverse();
  return indices;
 },
 GetDeletedRecordKeys: function() {
  var helper = this.GetHelper();
  if(!helper) return [ ];
  return helper.deletedItemKeys.slice();
 },
 GetUpdatedRecordKeys: function() {
  var helper = this.GetHelper();
  if(!helper) return [ ];
  return ASPx.GetObjectKeys(helper.updatedValues);
 },
 GetUnsavedChanges: function() {
  var helper = this.GetHelper();
  if(!helper) return { };
  return helper.GetChangedValuesInfo();
 }
});
var GridStyleHelperBase = ASPx.CreateClass(null, {
 ClearItemStyleKey: "items",
 ErrorItemHtmlKey: "ei",
 BatchEditCellKey: "bec",
 BatchEditModifiedCellKey: "bemc",
 BatchEditMergedModifiedCellKey: "bemergmc",
 BatchEditDeletedItemKey: "bedi",
 FocusedCellKey: "fc",
 SelectedCellKey: "sc",
 InitCellStyleKey: "initial",
 AppliedBatchEditCellStylKey: "batchEdit",
 AppliedFocusedCellStyleKey: "focused",
 AppliedSelectedCellStyleKey: "selected",
 GetStyles: function() { return null; },
 GetStyleInfo: function(styleKey, columnIndex) {
  var info = this.GetStyleInfoCore(styleKey, columnIndex);
  if(info)
   info.styleKey = styleKey;
  return info;
 },
 GetStyleInfoCore: function(styleKey, keyPostFix) {
  var styles = this.GetStyles();
  if(!styles)
   return null;
  if(ASPx.IsExists(keyPostFix)) {
   var key = styleKey + keyPostFix;
   if(styles.hasOwnProperty(key))
    return styles[key];
  }
  return styles[styleKey];
 },
 GetCellStyleKeys: function() {
  var result = [];
  result.push(this.AppliedBatchEditCellStylKey);
  result.push(this.AppliedFocusedCellStyleKey);
  result.push(this.AppliedSelectedCellStyleKey);
  return result;
 },
 UpdateCellBatchEditStyle: function(style, cell) { this.UpdateCellStyle(this.AppliedBatchEditCellStylKey, style, cell); },
 UpdateCellFocusedStyle: function(style, cell) { this.UpdateCellStyle(this.AppliedFocusedCellStyleKey, style, cell); },
 UpdateCellSelectedStyle: function(style, cell) { this.UpdateCellStyle(this.AppliedSelectedCellStyleKey, style, cell); },
 UpdateCellStyle: function(styleKey, style, cell) {
  if(!cell) return;
  this.EnsureCellStyles(cell);
  cell.appliedStyles[styleKey] = this.GetCellStyleToApply(style);
  this.ApplyCellStyles(cell);
 },
 EnsureCellStyles: function(cell) {
  if(cell.appliedStyles)
   return;
  cell.appliedStyles = { }; 
  cell.appliedStyles[this.InitCellStyleKey] = this.CreateEmptyCellStyle(cell.className, cell.style.cssText);
  var keys = this.GetCellStyleKeys();
  for(var i = 0; i < keys.length; i++)
   cell.appliedStyles[keys[i]] = this.CreateEmptyCellStyle();
 },
 CreateEmptyCellStyle: function(className, cssText) {  
  className = className || "";
  cssText = cssText || "";
  return { className: className, cssText: cssText};
 },
 GetCellStyleToApply: function(style) {
  var result = this.CreateEmptyCellStyle();
  if(style) {
   result.className = style.className || "";
   result.cssText = style.cssText || "";
  }
  return result;
 },
 ApplyCellStyles: function(cell) {
  var className = "";
  var cssText = "";
  for(var key in cell.appliedStyles) {
   if(!cell.appliedStyles.hasOwnProperty(key)) continue;
   var style = cell.appliedStyles[key];
   if(!style) continue;
   if(style.className)
    className += " " + style.className;
   if(style.cssText)
    cssText += ";" + style.cssText;
  }
  cell.className = className;
  cell.style.cssText = cssText;
 },
 AddToBatchEditStyle: function(cell, styles, classNames) { this.AddToCellStyleCore(cell, this.AppliedBatchEditCellStylKey, styles, classNames); },
 AddToInitialStyle: function(cell, styles, classNames) { this.AddToCellStyleCore(cell, this.InitCellStyleKey, styles, classNames); },
 AddToCellStyleCore: function(cell, styleKey, styles, classNames) {
  if((!styles && !classNames) || !cell) return;
  this.EnsureCellStyles(cell);
  var style = cell.appliedStyles[styleKey];
  if(!style) return;
  if(classNames)
   style.className += " " + classNames.join(' ');
  if(styles) {
   var fakeCell = document.createElement("TD");
   fakeCell.style.cssText = style.cssText || "";
   for(var property in styles) {
    if(styles.hasOwnProperty(property)) {
     var value = styles[property];
     fakeCell.style[property] = value + (typeof (value) == "number" ? "px" : "");
    }
   }   
   style.cssText = fakeCell.style.cssText;
  }  
  this.ApplyCellStyles(cell);
 },
 ChangeCellInitialClass: function(cell, className, add, preventApply) {
  if(!cell || !cell.appliedStyles)
   return;
  var hasClass = cell.appliedStyles.initial.className.indexOf(className) > -1;
  if(hasClass && !add)
    cell.appliedStyles.initial.className =  cell.appliedStyles.initial.className.replace(className, "");
  if(!hasClass && add)
    cell.appliedStyles.initial.className += " " + className;
  if(!preventApply)
   this.ApplyCellStyles(cell);
 },
 GetEmptyCellStyle: function() { return this.CreateEmptyCellStyle(); },
 GetBatchEditCellStyle: function() { return this.GetStyleInfo(this.BatchEditCellKey); },
 GetBatchEditModifiedCellStyle: function(columnIndex) { return this.GetStyleInfo(this.BatchEditModifiedCellKey, columnIndex); },
 GetBatchEditMergedModifiedCellStyle: function() { return this.GetStyleInfo(this.BatchEditMergedModifiedCellKey); },
 GetFocusedCellStyle: function(style) { return this.GetStyleInfo(this.FocusedCellKey); },
 GetSelectedCellStyle: function(style) { return this.GetStyleInfo(this.SelectedCellKey); },
 IsBatchEditCellStyle: function(style) { return this.CheckStyleInfoByKey(style, this.BatchEditCellKey); },
 IsBatchEditModifiedCellStyle: function(style) { return this.CheckStyleInfoByKey(style, this.BatchEditModifiedCellKey); },
 IsBatchEditMergedModifiedCellStyle: function(style) { return this.CheckStyleInfoByKey(style, this.BatchEditMergedModifiedCellKey); },
 IsFocusedCellStyle: function(style) { return this.CheckStyleInfoByKey(style, this.FocusedCellKey); },
 GetClearItemStyle: function() { return this.GetStyleInfo(this.ClearItemStyleKey); },
 GetBatchEditDeletedItemStyle: function() { return this.GetStyleInfo(this.BatchEditDeletedItemKey); },
 IsClearItemStyle: function(style) { return this.CheckStyleInfoByKey(style, this.ClearItemStyleKey); },   
 IsBatchEditDeletedItemStyle: function(style) { return this.CheckStyleInfoByKey(style, this.BatchEditDeletedItemKey); },   
 CheckStyleInfoByKey: function(styleInfo, key) {
  if(!styleInfo)
   return false;
  return styleInfo.styleKey == key;
 },
 ApplyElementStyle: function(element, styleInfo, skipInitialStyle){
  if(!element) return;
  if(!skipInitialStyle) {
   if(!ASPx.IsExists(element.initialClassName))
    element.initialClassName = element.className;
   if(!ASPx.IsExists(element.initialCssText))
    element.initialCssText = element.style.cssText;
   element.className = element.initialClassName;
   element.style.cssText = element.initialCssText;
  }
  if(styleInfo) {
   element.className += " " + styleInfo.className;
   element.style.cssText += " " + styleInfo.cssText;
  }
 },
 AddClassToElement: function(element, className){
  if(!element) return;
  ASPx.AddClassNameToElement(element, className);
  this.ChangeElementInitialClass(element, className, true);
 },
 RemoveClassFromElement: function(element, className){
  if(!element) return;
  ASPx.RemoveClassNameFromElement(element, className);
  this.ChangeElementInitialClass(element, className);
 },
 ChangeElementInitialClass: function(element, className, add) {
  if(!element) return;
  if(!ASPx.IsExists(element.initialClassName))
   element.initialClassName = element.className;  
  var hasClass = element.initialClassName.indexOf(className) > -1;
  if(hasClass && !add)
    element.initialClassName =  element.initialClassName.replace(className, "");
  if(!hasClass && add)
    element.initialClassName += " " + className;
 },
 AddStyleToElementInitialCssText: function(element, style) {
  this.EnsureElementInitialCssTextFromServer(element);
  var fakeElement = document.createElement("DIV");
  for(var property in style) {
   if(!style.hasOwnProperty(property)) continue;
   var value = style[property];
   fakeElement.style[property] = value + (typeof (value) === "number" ? "px" : "");
  }  
  element.initialCssText = element.initialCssTextFromServer + ";" + fakeElement.style.cssText;
 },
 ResetElementInitialCssText: function(element) {
  if(element.initialCssTextFromServer)
   element.initialCssText = element.initialCssTextFromServer;
 },
 EnsureElementInitialCssTextFromServer: function(element) {
  if(!element.initialCssTextFromServer)
   element.initialCssTextFromServer = element.initialCssText;
 },
 GetErrorItemHtml: function() {
  var styles = this.GetStyles();
  if(!styles)
   return null;
  return styles[this.ErrorItemHtmlKey];
 }
});
var GridCommonUtils = {
 BacthEditLockFocusEventsTriggerTimeout: 50,
 NeedSaveActiveElement: function (control) { return ASPx.Browser.WindowsPhonePlatform && ASPx.Browser.Edge; },
 IsBatchEditMode: function (control) { return control.GetBatchEditHelper && !!control.GetBatchEditHelper(); },
 IsInput: function (element) {
  if (!element) return false;
  return element.tagName == "INPUT" || element.tagName == "TEXTAREA";
 },
 SaveActiveElement: function (control) {
  if (!this.NeedSaveActiveElement(control)) return;
  var activeElement = ASPx.GetActiveElement();
  var isBatchEditing = this.IsBatchEditMode(control);
  var isInput = this.IsInput(activeElement);
  if (!activeElement || !isInput && !isBatchEditing || !ASPx.GetIsParent(control.GetMainElement(), activeElement))
   return;
  control.activeElementSettings = { activeElement: activeElement };
  if (isInput)
   control.activeElementSettings.selInfo = ASPx.Selection.GetInfo(activeElement);
  if (isBatchEditing)
   this.LockBatchEditFocusEvents(control);
 },
 RestoreActiveElement: function (control) {
  var settings = control.activeElementSettings;
  if (!settings) return;
  var oldElement = settings.activeElement;
  if (ASPx.IsExistsElement(oldElement) && oldElement !== ASPx.GetActiveElement()) {
   oldElement.focus();
   if (settings.selInfo)
    ASPx.Selection.Set(oldElement, settings.selInfo.startPos, settings.selInfo.endPos);
  }
  delete control.activeElementSettings;
  this.UnLockBatchEditFocusEvents(control);
 },
 LockBatchEditFocusEvents: function (control) { control.BatchEditFocusEventsLocked = true; },
 UnLockBatchEditFocusEvents: function (control) {
  ASPx.Timer.ClearTimer(control.bacthEditLockFocusEventsTriggerID);
  if (control.BatchEditFocusEventsLocked)
   control.bacthEditLockFocusEventsTriggerID = window.setTimeout(function () { delete control.BatchEditFocusEventsLocked; }, this.BacthEditLockFocusEventsTriggerTimeout);
 },
 IsBatchEditFocusEventsLocked: function (control) { return !!control.BatchEditFocusEventsLocked; }
};
ASPx.GridDragHelperBase = GridDragHelperBase;
ASPx.BatchEditApi = BatchEditApi;
ASPx.GridStyleHelperBase = GridStyleHelperBase;
ASPx.GridCommonUtils = GridCommonUtils;
})();

(function() {
var GridKbdHelper = ASPx.CreateClass(ASPx.KbdHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.grid = grid;
 },
 CanFocus: function(e) {
  var source = ASPx.Evt.GetEventSource(e);
  if(source.tagName === "A")
   return true;
  return ASPx.KbdHelper.prototype.CanFocus.call(this, e);
 },
 HandleNoFocusAction: function(e, actionName) {
  this.HandleKbdEvent(e, actionName);
 },
 HandleKeyDown: function(e) {
  return this.HandleKbdEvent(e, "HandleKeyDown");
 },
 HandleKeyPress: function(e) {
  return this.HandleKbdEvent(e, "HandleKeyPress");
 },
 HandleKeyUp: function(e) {
  return this.HandleKbdEvent(e, "HandleKeyUp");
 },
 HandleKbdEvent: function(e, actionName) {
  var action = actionName.replace(/^Handle*/g, "Raise");
  var handled = this.grid[action](e);
  if(handled)
   ASPx.Evt.PreventEventAndBubble(e);
  return handled;
 }
});
var ASPxClientGridKeyboardEvent = ASPx.CreateClass(ASPxClientEvent, {
 constructor: function(kbdHelperOwner) {
  this.constructor.prototype.constructor.call(this);
  this.kbdHelperOwner = kbdHelperOwner;
 },
 AddHandler: function(handler, executionContext) {
  ASPxClientEvent.prototype.AddHandler.call(this, handler, executionContext);
  this.kbdHelperOwner.OnKbdEventChanged();
 },
 RemoveHandler: function(handler, executionContext) {
  ASPxClientEvent.prototype.RemoveHandler.call(this, handler, executionContext);
  this.kbdHelperOwner.OnKbdEventChanged();
 },
 ClearHandlers: function() {
  ASPxClientEvent.prototype.ClearHandlers.call(this);
  this.kbdHelperOwner.OnKbdEventChanged();
 }
});
var ASPxClientGridKeyboardEventArgsBase = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(htmlEvent) {
  this.constructor.prototype.constructor.call(this);
  this.htmlEvent = htmlEvent;
  this.handled = false;
  this.isCtrlPressed = htmlEvent.ctrlKey;
  this.isAltPressed = htmlEvent.altKey;
  this.isShiftPressed = htmlEvent.shiftKey;
  this.keyCode = ASPx.Evt.GetKeyCode(htmlEvent);
 }
});
ASPx.GridKbdHelper = GridKbdHelper;
ASPx.ASPxClientGridKeyboardEvent = ASPxClientGridKeyboardEvent;
ASPx.ASPxClientGridKeyboardEventArgsBase = ASPxClientGridKeyboardEventArgsBase;
})();

(function() {
var GridSortOrder = { None: 0, Ascending: 1, Descending: 2 };
var ASPxClientGridColumnMovingTargetPosition = {
 Right: 0,
 Left: 1,
 Top: 2,
 Bottom: 3
};
var ASPxClientGridBase = ASPx.CreateClass(ASPxClientControl, {
 MainTableID: "DXMainTable",
 CustomizationWindowSuffix: "_custwindow",
 EditingRowID: "_DXEditingRow",
 EditingErrorItemID: "DXEditingErrorItem", 
 EmptyHeaderSuffix: "_emptyheader",
 PagerBottomID: "DXPagerBottom",
 PagerTopID: "DXPagerTop",
 SearchEditorID: "DXSE",
 SelectButtonID: "DXSelBtn",
 HeaderFilterButtonClassName: "dxgv__hfb",
 CommandColumnItemClassName: "dxgv__cci",
 DetailGridSuffix: "dxdt",
 FixedColumnsDivID: "DXFixedColumnsDiv",
 FixedColumnsContentDivID: "DXFixedColumnsContentDiv",
 ProgressBarDisplayControlIDFormat: "PBc{0}i{1}",
 AccessibleFilterRowButtonID: "AFRB",
 RequireKeyFieldNameText: "Error while trying to perform a CRUD operation with an incorrect or unspecified KeyFieldName property value.",
 EtalonBatchRecordPostFix: "dxgbeEtalonRecord",
 InvalidItemIndex: -23061988,
 constructor: function(name){
  this.constructor.prototype.constructor.call(this, name);
  this.callBacksEnabled = true;
  this.custwindowLeft = null;
  this.custwindowTop = null;
  this.custwindowVisible = null;
  this.userChangedSelection = false;
  this.confirmDelete = "";
  this.editorIDList = [ ];
  this.keys = [ ];
  this.lastMultiSelectIndex = -1;
  this.mainTableClickData = {
   processing: false,
   focusChanged: false,
   selectionChanged: false
  };
  this.afterCallbackRequired = false;
  this.enableHeaderFilterCaching = true;
  this.supportGestures = true;
  this.checkBoxImageProperties = null;
  this.internalCheckBoxCollection = null;
  this.sizingConfig.adjustControl = true;
  this.lookupBehavior = false;
  this.isAccessibleRowEditing = false;
  this.batchEditApi = this.CreateBatchEditApi();
  this.CustomButtonClick = new ASPxClientEvent();
  this.SelectionChanged = new ASPxClientEvent();
  this.ColumnSorting = new ASPxClientEvent();
  this.ColumnGrouping = new ASPxClientEvent();
  this.CustomizationWindowCloseUp = new ASPxClientEvent();
  this.InternalCheckBoxClick = new ASPxClientEvent();
  this.KeyDown = new ASPx.ASPxClientGridKeyboardEvent(this);
  this.KeyPress = new ASPx.ASPxClientGridKeyboardEvent(this);
  this.KeyUp = new ASPx.ASPxClientGridKeyboardEvent(this);
  this.BatchEditStartEditing = new ASPxClientEvent();
  this.BatchEditEndEditing = new ASPxClientEvent();
  this.BatchEditConfirmShowing = new ASPxClientEvent();
  this.BatchEditTemplateCellFocused = new ASPxClientEvent();
  this.BatchEditChangesSaving = new ASPxClientEvent();
  this.BatchEditChangesCanceling = new ASPxClientEvent();
  this.BatchEditSummaryDisplayText = new ASPxClientEvent();
  this.FocusedCellChanging = new ASPxClientEvent();
  this.CellSelectionChanging = new ASPxClientEvent();
  this.ClipboardCellPasting = new ASPxClientEvent();
  this.ToolbarItemClick = new ASPxClientEvent();
  this.pendingCommands = [ ];
  this.pageRowCount = 0;
  this.pageRowSize = 0;
  this.pageIndex = 0;
  this.pageCount = 1;
  this.allowDelete = false;
  this.allowEdit = false;
  this.allowInsert = false;
  this.allowFocusedRow = false;
  this.allowFocusedCell = false;
  this.allowSelectionCell = false;
  this.allowSelectByItemClick = false;
  this.allowSelectSingleRowOnly = false;
  this.allowMultiColumnAutoFilter = false;
  this.focusedRowIndex = -1;
  this.selectedWithoutPageRowCount = 0;
  this.selectAllSettings = [ ];
  this.selectAllBtnStateWithoutPage = null;
  this.visibleStartIndex = 0;
  this.columns = [ ];
  this.columnResizeMode = ASPx.ColumnResizeMode.None;
  this.horzScroll = ASPx.ScrollBarMode.Hidden;
  this.vertScroll = ASPx.ScrollBarMode.Hidden;
  this.scrollToRowIndex = -1;
  this.useEndlessPaging = false;
  this.allowBatchEditing = false;
  this.batchEditClientState = { };
  this.resetScrollTop = false;
  this.callbackOnFocusedRowChanged = false;
  this.callbackOnSelectionChanged = false;
  this.autoFilterDelay = 1200;
  this.searchFilterDelay = 1200;
  this.allowSearchFilterTimer = true;
  this.editState = 0;
  this.kbdHelper = null;
  this.enableKeyboard = false;
  this.keyboardLock = false;
  this.accessKey = null;
  this.customKbdHelperName = null;
  this.endlessPagingHelper = null;
  this.toolbarHelper = null;
  this.icbFocusedStyle = null;
  this.pendingEvents = [ ];
  this.customSearchPanelEditorID = null;
  this.searchPanelFilter = null;
  this.isDetailGrid = null;
  this.rowHotTrackStyle = null;
  this.updateButtonName = "";
  this.cancelButtonName = "";
  this.isAccessibleFilterRowMenu = false;
  this.userHandledCallbackError = false;
 },
 HasHorzScroll: function() { return this.horzScroll != ASPx.ScrollBarMode.Hidden; },
 HasVertScroll: function() { return this.vertScroll != ASPx.ScrollBarMode.Hidden; },
 HasScrolling: function() { return this.HasHorzScroll() || this.HasVertScroll(); },
 AllowResizing: function() { return this.columnResizeMode != ASPx.ColumnResizeMode.None && this.showColumnHeaders; },
 GetGridTD: function() { 
  var table = this.GetMainElement();
  if(!table) return null;
  return table.rows[0].cells[0];
 },
 GetArrowDragDownImage: function() { return this.GetChildElement("IADD"); },
 GetArrowDragUpImage: function() { return this.GetChildElement("IADU"); },
 GetArrowDragLeftImage: function() { return this.GetChildElement("IADL"); },
 GetArrowDragRightImage: function() { return this.GetChildElement("IADR"); },
 GetArrowDragFieldImage: function() { return this.GetChildElement("IDHF"); },
 GetEndlessPagingUpdatableContainer: function() { return this.GetChildElement("DXEPUC"); },
 GetEndlessPagingLPContainer: function() { return this.GetChildElement("DXEPLPC"); },
 GetBatchEditorsContainer: function() { return this.GetChildElement("DXBEsC"); },
 GetBatchEditorContainer: function(columnIndex) { return this.GetChildElement("DXBEC" + columnIndex); }, 
 GetLoadingPanelDiv: function() {  return this.GetChildElement("LPD"); },
 GetFixedColumnsDiv: function() {  return this.GetChildElement(this.FixedColumnsDivID); },
 GettItem: function(visibleIndex) { return null; },
 GetDataItemIDPrefix: function() { },
 GetEmptyDataItemIDPostfix: function() { },
 GetEmptyDataItem: function() { return this.GetChildElement(this.GetEmptyDataItemIDPostfix()); },
 GetDataRowSelBtnIDPrefix: function() { return "_" + this.SelectButtonID; },
 GetDataRowSelBtn: function(index) { return this.FindSelectButton(this.GetItem(index), this.GetDataRowSelBtnIDPrefix(index)); },
 FindSelectButton: function(container, idPrefix) { return container && container.querySelector("input[id^='" + this.name + idPrefix + "']"); },
 GetSelectAllBtn: function(index) { return this.GetChildElement("DXSelAllBtn" + index); },
 GetMainTable: function() { return this.GetChildElement(this.MainTableID); },
 GetLoadingPanelContainer: function() { return this.GetChildElement("DXLPContainer"); },
 GetStatusBar: function() { return this.GetChildElement("DXStatus"); },
 GetGroupPanel: function() { return this.GetChildElement("grouppanel"); },
 GetHeader: function(columnIndex, inGroupPanel) { 
  var id = "col" + columnIndex;
  if(inGroupPanel)
   id = "group" + id;
  return this.GetChildElement(id); 
 },
 GetHeaderRow: function(index) {
  return ASPx.GetElementById(this.name + "_" + ASPx.GridViewConsts.HeaderRowID + index);
 },
 GetEditingRow: function(obj) { return ASPx.GetElementById((obj ? obj.name : this.name) + this.EditingRowID); },
 GetEditingErrorItem: function(obj, visibleIndex) { 
  var id = (obj ? obj.name : this.name) + "_" + this.EditingErrorItemID;
  if(ASPx.IsExists(visibleIndex))
   id = id + visibleIndex;
  return ASPx.GetElementById(id); 
 },
 GetEditFormTable: function() { return ASPx.GetElementById(this.name + "_DXEFT"); },
 GetCustomizationWindow: function() { return ASPx.GetControlCollection().Get(this.name + this.CustomizationWindowSuffix); },
 GetCustomizationWindowElement: function() {
  var win = this.GetCustomizationWindow();
  return win ? win.GetWindowElement(-1) : null;  
 },
 GetParentRowsWindow: function() { return ASPx.GetControlCollection().Get(this.name + "_DXparentrowswindow"); },
 GetEditorPrefix: function() { return "DXEditor"; },
 GetPopupEditForm: function() { return ASPx.GetControlCollection().Get(this.name  + "_DXPEForm"); },
 GetFilterRowMenu: function() { return ASPx.GetControlCollection().Get(this.name + "_DXFilterRowMenu"); },
 GetFilterRow: function() { return ASPx.GetControlCollection().Get(this.name + "_DXFilterRow"); },
 GetFilterControlPopup: function() { return ASPx.GetControlCollection().Get(this.name + "_DXPFCForm"); },
 GetFilterControl: function() { return ASPx.GetControlCollection().Get(this.name +  "_DXPFCForm_DXPFC"); }, 
 GetHeaderFilterPopup: function() { return ASPx.GetControlCollection().Get(this.name + "_DXHFP"); },
 GetToolbarByName: function(name){
  return this.GetToolbarHelper().GetToolbarByName(name);
 },
 GetToolbar: function(index){
  return ASPx.GetControlCollection().Get(this.name + "_DXCTMenu" + index);
 },
 IsBatchEditDeletedItem: function(visibleIndex) {
  var helper = this.GetBatchEditHelper();
  return helper && helper.IsDeletedRecord(this.ConvertVisibleIndexToKey(visibleIndex));
 },
 IsEmptyHeaderID: function(id) { return false; },
 IsDataItem: function(visibleIndex) { return !!this.GetItem(visibleIndex); },
 GetSearchEditor: function() { 
  var editor = this.GetCustomSearchPanelEditor() || this.GetGridSearchEditor();
  if(editor && editor.GetMainElement())
   return editor;
  return null;
 },
 GetGridSearchEditor: function() { return ASPx.GetControlCollection().Get(this.name + "_" + this.SearchEditorID); },
 GetCustomSearchPanelEditor: function() { return ASPx.GetControlCollection().Get(this.customSearchPanelEditorID); },
 SetSearchPanelCustomEditor: function(editor) { this.GetFilterHelper().SetSearchPanelCustomEditor(editor); },
 GetEditorByColumnIndex: function(colIndex) {
  var list = this._getEditors();
  for(var i = 0; i < list.length; i++) {
   if(this.tryGetNumberFromEndOfString(list[i].name).value === colIndex)
    return list[i];
  }
  return null;
 },
 GetProgressBarControlID: function(visibleIndex, columnIndex) { return ASPx.Str.ApplyReplacement(this.ProgressBarDisplayControlIDFormat, [["{0}", columnIndex], ["{1}", visibleIndex]]); },
 GetProgressBarControl: function(visibleIndex, columnIndex) { return ASPx.GetControlCollection().Get(this.name + "_" + this.GetProgressBarControlID(visibleIndex, columnIndex)); },
 CreateBatchEditApi: function() { },
 SetProperties: function(properties, obj) {
  ASPxClientControl.prototype.SetProperties.call(this, properties, obj);
  this.CreateColumns();
  this.CreateToolbars();
  this.Invalidate();
 },
 CreateColumns: function() {
  this.columns = [ ];
  for(var i = 0; i < this.columnProp.length; i++)
   this.columns.push(this.CreateColumn(this.columnProp[i]));
 },
 CreateToolbars: function(){
  this.toolbars = [ ];
  for(var i = 0; this.toolbarsProp && i < this.toolbarsProp.length; i++){
   var toolbarInfo = { index: this.toolbarsProp[i][0], name: this.toolbarsProp[i][1] };
   if(this.GetToolbar(toolbarInfo.index))
    this.toolbars.push(toolbarInfo);
  }
 },
 CreateColumn: function(prop) { },
 IsFilterLocked: function() { return this.GetFilterHelper().IsFilterLocked(); },
 LockFilter: function() { this.GetFilterHelper().LockFilter(); },
 UnlockFilter: function() { this.GetFilterHelper().UnlockFilter(); },
 InlineInitialize: function() {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  this.InitializeBubbleEvents();
 },
 InitializeBubbleEvents: function() {
  this.AttachMainTableClickEvents();
 },
 Initialize: function() {
  ASPxClientControl.prototype.Initialize.call(this);
  this.GetFilterHelper().OnInit();
  this.GetToolbarHelper().OnInit();
  if(this.enabled)
   this.SetHeadersClientEvents();
  this.EnsureRowKeys();
  this._setFocusedItemInputValue();
  this.InitializeAccessibilityEvents();
  this.InitializeCommandColumnHeaderLinkEvents();
  this.EnsureRowHotTrackItems();
  if(this.checkBoxImageProperties){
   this.CreateInternalCheckBoxCollection();
   this.UpdateSelectAllCheckboxesState();
  }
  this.CheckPendingEvents();
  this.CheckEndlessPagingLoadNextPage();
  this.PrepareCommandButtons();
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.Init();
  var cellSelectionHelper = this.GetCellSelectionHelper();
  if(cellSelectionHelper)
   cellSelectionHelper.Update();
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper)
   cellFocusHelper.Update();
  this.InitKbdHelper();
  window.setTimeout(this.scrollToElementAsignedFromServer.bind(this), 0);
 },
 scrollToElementAsignedFromServer: function () {
  if(this.shouldScrollToNewRow) {
   this.GetScrollHelper().MakeRowVisible(this.GetEditingRow());
   this.shouldScrollToNewRow = false;
  }
  if(this.scrollToRowIndex >= 0) {
   this.MakeRowVisible(this.scrollToRowIndex);
   this.scrollToRowIndex = -1;
  }
 },
 AttachEventToEditor: function(columnIndex, eventName, handler) {
  var editor = this.GetEditorByColumnIndex(columnIndex);
  if(!ASPx.Ident.IsASPxClientEdit(editor))
   return;
  var attachKeyDownToInput = eventName === "KeyDown" && this.IsCheckEditor(editor);
  if(!editor[eventName] && !attachKeyDownToInput)
   return;
  var duplicateAttachLocker = "dxgv" + eventName + "Assigned";
  if(editor[duplicateAttachLocker]) 
   return;
  if(attachKeyDownToInput)
   ASPx.Evt.AttachEventToElement(editor.GetFocusableInputElement(), "keydown", function(e) { handler(editor, { htmlEvent: e }); });
  else
   editor[eventName].AddHandler(handler);
  editor.dxgvColumnIndex = columnIndex;
  editor[duplicateAttachLocker] = true;
 },
 IsCheckEditor: function(editor) {
  return ASPx.Ident.IsASPxClientCheckEdit && ASPx.Ident.IsASPxClientCheckEdit(editor);
 },
 IsStaticBinaryImageEditor: function(editor) {
  return ASPx.Ident.IsStaticASPxClientBinaryImage && ASPx.Ident.IsStaticASPxClientBinaryImage(editor);
 },
 IsDetailGrid: function() { 
  if(this.isDetailGrid !== null)
   return this.isDetailGrid;
  var regTest = new RegExp(this.DetailGridSuffix + "[0-9]");
  this.isDetailGrid = regTest.test(this.name);
  if(this.isDetailGrid)
   return true;
  var mainElement = this.GetMainElement();
  var parent = mainElement.parentNode;
  while(parent && parent.tagName !== "BODY") {
   this.isDetailGrid = regTest.test(parent.id);
   if(this.isDetailGrid) return true;
   parent = parent.parentNode;
  }
  return false;
 },
 PrepareCommandButtons: function(){
  if(!this.cButtonIDs || this.cButtonIDs.length == 0) return;
  for(var i = 0; i < this.cButtonIDs.length; i++){
   var name = this.cButtonIDs[i];
   var element = ASPx.GetElementById(name);
   if(!element) continue;
   var button = new ASPxClientButton(name);
   var buttonMainElement = button.GetMainElement();
   element.cpGVCommandButtonInitialized = true;
   button.cpGVName = this.name;
   button.useSubmitBehavior = false;
   button.causesValidation = false;
   button.isNative = !!eval(ASPx.Attr.GetAttribute(buttonMainElement, "data-isNative"));
   button.isImage = !!eval(ASPx.Attr.GetAttribute(buttonMainElement, "data-isImage"));
   button.encodeHtml = !!eval(ASPx.Attr.GetAttribute(buttonMainElement, "data-encodeHtml"));
   button.enabled = !ASPx.ElementContainsCssClass(buttonMainElement, "dxbDisabled");
   button.clientVisible = ASPx.GetElementDisplay(buttonMainElement);
   button.accessibilityCompliant = this.accessibilityCompliant;
   button.Click.AddHandler(this.OnCommandButtonClick.aspxBind(this));
   button.InlineInitialize();
   this.PrepareCommandButton(button);
  }
  delete this.cButtonIDs;
 },
 PrepareCommandButton: function(button) {  
  if(this.allowBatchEditing && ASPx.GetIsParent(this.GetStatusBar(), button.GetMainElement())) { 
   this.EnsureCommandButtonClickArgs(button);
   var commandName = button.gvClickArgs && button.gvClickArgs[0][0];
   if(commandName === "UpdateEdit")
    this.updateButtonName = button.name;
   if(commandName === "CancelEdit")
    this.cancelButtonName = button.name;
   if(commandName === "PreviewChanges")
    this.previewChangesButtonName = button.name;
   if(commandName === "HidePreview")
    this.hidePreviewButtonName = button.name;
   if(commandName === "UpdateSummaries")
    this.updateSummariesButtonName = button.name;
  }
 },
 GetBatchEditCommandButtons: function() {
  var buttons = { };
  buttons.updateButton = ASPx.GetControlCollection().Get(this.updateButtonName);
  buttons.cancelButton = ASPx.GetControlCollection().Get(this.cancelButtonName);
  buttons.previewChangesButton = ASPx.GetControlCollection().Get(this.previewChangesButtonName);
  buttons.hidePreviewButton = ASPx.GetControlCollection().Get(this.hidePreviewButtonName);
  buttons.updateSummariesButton = ASPx.GetControlCollection().Get(this.updateSummariesButtonName);
  return buttons;
 },
 PrepareCommandButtonsIDList: function(container) {
  if(!this.cButtonIDs)
   this.cButtonIDs = [ ];
  var initButtonIndex = this.GetInitCommandButtonIndex();
  var elementList = container.getElementsByTagName("*");
  for(var i = 0; i < elementList.length; i++) {
   var element = elementList[i];
   var comandButtonIDPattern = /%DXItemIndex\d+%$/g; 
   if(element.id && comandButtonIDPattern.test(element.id)) {
    var patternID = element.id;
    var buttonID = patternID.replace(comandButtonIDPattern, initButtonIndex--);
    ASPx.SetInnerHtml(element.parentNode, element.parentNode.innerHTML.replace(new RegExp(patternID, "g"), buttonID));
    this.cButtonIDs.push(buttonID);
   }
  }
 },
 GetInitCommandButtonIndex: function() {
  var index = 0;
  var disposedControls = [];
  ASPx.GetControlCollection().ForEachControl(function(control) {
   if(control.cpGVName !== this.name)
    return;
   if(!control.GetMainElement()) { 
    disposedControls.push(control);
    return;
   }
   var matches = control.name.match(/_DXCBtn(-?\d+)/);
   if(matches && matches.length > 1) {
    var buttonIndex = parseInt(matches[1]);
    index = Math.min(index, buttonIndex);
   }
  }, this);
  for(var i = 0; i < disposedControls.length; i++)
   ASPx.GetControlCollection().Remove(disposedControls[i]);
  return index - 1;
 },
 EnsureCommandButtonClickArgs: function(button) {
  if(!button.gvClickArgs)
   button.gvClickArgs = eval(ASPx.Attr.GetAttribute(button.GetMainElement(), "data-args"));
 },
 OnCommandButtonClick: function(s, e){
  var mainElement = s.GetMainElement();
  if(!s.gvClickArgs)
   s.gvClickArgs = eval(ASPx.Attr.GetAttribute(mainElement, "data-args"));
  this.EnsureCommandButtonClickArgs(s);
  if(s.gvClickArgs && s.gvClickArgs.length > 1)
   this.ScheduleUserCommand(s.gvClickArgs[0], s.gvClickArgs[1], mainElement);
 },
 GetCommandButtonsInContainer: function(container) {
  var buttons = [];   
  ASPx.GetControlCollection().ProcessControlsInContainer(container, function(control){
   var isCommandButton = control.cpGVName === this.name && control.name.indexOf("DXCBtn") > -1;
   if(isCommandButton)
    buttons.push(control);
  }.bind(this));
  return buttons;
 },
 FindCommandButtonByChildElement: function(element) {
  if(!element) return null;
  var mainElement = ASPx.GetParentByPartialClassName(element, this.CommandColumnItemClassName);
  var buttonId = mainElement && mainElement.id;
  return buttonId ? ASPx.GetControlCollection().GetByName(buttonId) : null;
 },
 IsNewButton: function(button) { return this.CheckButtonByCommandName(button, "AddNew"); },
 IsEditButton: function(button) { return this.CheckButtonByCommandName(button, "StartEdit"); },
 IsDeleteButton: function(button) { return this.CheckButtonByCommandName(button, "Delete"); },
 IsRecoverButton: function(button) { return this.CheckButtonByCommandName(button, "Recover"); },
 IsCancelButton: function(button) { return this.CheckButtonByCommandName(button, "CancelEdit"); },
 IsSelectButton: function(button) { return this.CheckButtonByCommandName(button, "Select"); },
 IsCustomButton: function(button) { return this.CheckButtonByCommandName(button, "CustomButton"); },
 CheckButtonByCommandName: function (button, commandName) {
  if(!button) return false;
  this.EnsureCommandButtonClickArgs(button);
  return button.gvClickArgs[0] && button.gvClickArgs[0][0] === commandName ;
 },
 CheckEndlessPagingLoadNextPage: function() {
  window.setTimeout(function() {
   var scrollHelper = this.GetScrollHelper();
   if(this.useEndlessPaging && scrollHelper)
    scrollHelper.CheckEndlessPagingLoadNextPage();
  }.aspxBind(this), 0);
 },
 EnsureRowKeys: function() {
  if(ASPx.IsExists(this.stateObject.keys))
   this.keys = this.stateObject.keys;
  if(!this.keys)
   this.keys = [ ];
 }, 
 CheckPendingEvents: function() {
  if(this.pendingEvents.length < 1)
   return;
  for(var i = 0; i < this.pendingEvents.length; i++)
   this.ScheduleRaisingEvent(this.pendingEvents[i]);
  this.pendingEvents.length = 0;
 },
 ScheduleRaisingEvent: function(eventName) {
  window.setTimeout(function() { this[eventName](); }.aspxBind(this), 0);
 },
 CreateInternalCheckBoxCollection: function() {
  if(!this.internalCheckBoxCollection)
   this.internalCheckBoxCollection = new ASPx.CheckBoxInternalCollection(this.checkBoxImageProperties, true, undefined, undefined, undefined, this.accessibilityCompliant);
  else
   this.internalCheckBoxCollection.SetImageProperties(this.checkBoxImageProperties);
  this.CompleteInternalCheckBoxCollection();
 },
 CompleteInternalCheckBoxCollection: function() {
  if(!this.IsLastCallbackProcessedAsEndless()){
   this.internalCheckBoxCollection.Clear();
   for(var i = 0; i < this.selectAllSettings.length; i++){
    var selectAllSettings = this.selectAllSettings[i];
    if(selectAllSettings === null)
     continue;
    var icbSelectAllElement = this.GetSelectAllBtn(selectAllSettings.index);
    if(ASPx.IsExistsElement(icbSelectAllElement))
     this.AddInternalCheckBoxToCollection(icbSelectAllElement, -(selectAllSettings.index + 1), !this.IsCheckBoxDisabled(icbSelectAllElement));
   }
  }
  for(var i = 0; i < this.pageRowCount; i ++) {
   var index = i + this.visibleStartIndex;
   var icbInputElement = this.GetDataRowSelBtn(index);
   if(icbInputElement) {
    var enabled = !this.IsCheckBoxDisabled(icbInputElement);
    this.AddInternalCheckBoxToCollection(icbInputElement, index, enabled);
   }
  }
 },
 IsCheckBoxDisabled: function(icbInputElement) {
  var icbMainElement = ASPx.CheckableElementHelper.Instance.GetICBMainElementByInput(icbInputElement);
  return icbMainElement.className.indexOf(this.GetDisabledCheckboxClassName()) != -1;
 },
 GetCssClassNamePrefix: function() { return ""; },
 GetDisabledCheckboxClassName: function() { return this.GetCssClassNamePrefix() + "_cd"; },
 AddInternalCheckBoxToCollection: function (icbInputElement, visibleIndex, enabled) {
  var internalCheckBox = null;
  if(this.IsLastCallbackProcessedAsEndless())
   internalCheckBox = this.internalCheckBoxCollection.Get(icbInputElement.id);
  if(internalCheckBox && internalCheckBox.inputElement != icbInputElement){
   this.internalCheckBoxCollection.Remove(icbInputElement.id);
   internalCheckBox = null;
  }
  if(!internalCheckBox)
   internalCheckBox = this.internalCheckBoxCollection.Add(icbInputElement.id, icbInputElement);
  internalCheckBox.CreateFocusDecoration(this.icbFocusedStyle);
  internalCheckBox.SetEnabled(enabled && this.GetEnabled());
  internalCheckBox.readOnly = this.readOnly;
  internalCheckBox.autoSwitchEnabled = !this.allowSelectSingleRowOnly;
  var grid = this;
  function OnCheckedChanged(s, e){
   if(!s.autoSwitchEnabled && s.GetValue() == ASPx.CheckBoxInputKey.Unchecked){
    var value = s.stateController.GetNextCheckBoxValue(s.GetValue(), s.allowGrayedByClick && s.allowGrayed);
    s.SetValue(value);
   }
   var rowCheckBox = grid.GetDataRowSelBtn(visibleIndex);
   if(grid.allowSelectSingleRowOnly)
    grid._selectAllSelBtn(false, rowCheckBox.id);
   if(!grid.RaiseInternalCheckBoxClick(visibleIndex)){
    grid.ScheduleCommand(function() { grid.SelectItem(visibleIndex, s.GetChecked()); }, true);
    grid.mainTableClickCore(e, true);
   }
  }
  function OnSelectAllCheckedChanged(s, e) {
   grid.ScheduleCommand(function() { this.ProcessSelectAllCheckBoxCheckedChanged(s); }.bind(grid), true);
   grid.mainTableClickCore(e, true);
  }
  var checkedChangedHandler = visibleIndex < 0 ? OnSelectAllCheckedChanged : OnCheckedChanged;
  internalCheckBox.CheckedChanged.AddHandler(checkedChangedHandler);
 },
 ProcessSelectAllCheckBoxCheckedChanged: function(checkBox, e) {
  var index = this.tryGetNumberFromEndOfString(checkBox.inputElement.id).value;
  var columnSelectAllSettings = this.GetColumnSelectAllSettings(index);
  if(!columnSelectAllSettings)
   return;
  switch(columnSelectAllSettings.mode){
   case 1:
    if(checkBox.GetChecked())
     this.SelectAllItemsOnPage();
    else 
     this.UnselectAllItemsOnPage();
    break;
   case 2:
    if(checkBox.GetChecked())
     this.SelectItemsCore(null, true, true);
    else 
     this.UnselectFilteredItemsCore(true);
    break;
  }
  this.UpdateSelectAllCheckboxesState();
 },
 GetColumnSelectAllSettings: function(index){
  for(var i = 0; i < this.selectAllSettings.length; i++){
   if(this.selectAllSettings[i].index == index)
    return this.selectAllSettings[i];
  }
 },
 SelectItemsCore: function(visibleIndices, selected, changedBySelectAll){
  if(!ASPx.IsExists(selected)) selected = true;
  if(!ASPx.IsExists(visibleIndices)) {
   selected = selected ? "all" : "unall";
   changedBySelectAll = ASPx.IsExists(changedBySelectAll) ? changedBySelectAll : false;
   visibleIndices = [ ];
  } else {
   changedBySelectAll = false;
   if(visibleIndices.constructor != Array)
    visibleIndices = [visibleIndices];
  }
  this.gridCallBack([ASPxClientGridViewCallbackCommand.SelectRows, selected, changedBySelectAll].concat(visibleIndices));
 },
 UnselectFilteredItemsCore: function(changedBySelectAll){
  if(!ASPx.IsExists(changedBySelectAll))
   changedBySelectAll = false;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.SelectRows, "unallf", changedBySelectAll]);
 },
 AdjustControlCore: function() {
  ASPxClientControl.prototype.AdjustControlCore.call(this);
  this.UpdateScrollableControls();
  this.ApplyPostBackSyncData();
  this.AdjustPagerControls();
  this.UpdateBatchEditActiveElements();
  this.InvalidateLayout();
 },
 UpdateBatchEditActiveElements: function () {
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper)
   cellFocusHelper.LoadUnfocusableAreaElements();
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.UpdateAllRecordActiveElements();
 },
 NeedCollapseControlCore: function() {
  return this.HasScrolling();
 },
 CollapseControl: function () {
  ASPx.GridCommonUtils.SaveActiveElement(this);
  ASPxClientControl.prototype.CollapseControl.call(this);
 },
 ExpandControl: function () {
  ASPxClientControl.prototype.ExpandControl.call(this);
  ASPx.GridCommonUtils.RestoreActiveElement(this);
 },
 InRegularCallback: function() {
  return this.InCallback() && !this.GetCallbackHelper().HasWaitedFuncCallbacks();
 },
 gridCallBack: function (args, callbackHandler) {
  this.GetCallbackHelper().SendRequest(args, callbackHandler);
 },
 gridPostBack: function(args) { 
  this.GetCallbackHelper().SendPostback(args); 
 },
 gridFuncCallBack: function(args, onCallBack) {
  this.GetCallbackHelper().SendFuncCallback(args, onCallBack);
 },
 OnCallback: function (result) {
  var html = result.html;
  this.HideFilterControlPopup();
  var isFuncCallback = html.indexOf("FB|") == 0;
  this.afterCallbackRequired = !isFuncCallback; 
  if(isFuncCallback)
   this.OnFunctionalCallback(html);
  else
   this.OnGeneralCallback(result);
 },
 OnGeneralCallback: function(result) {
  var html = result.html;
  this.UpdateStateObjectWithObject(result.stateObject);
  this.GetFilterHelper().LoadSearchEditorValueOnCallback();
  if(this.RequirePartialUpdate(html))
   this.ProcessPartialCallbackResult(html);
  else
   this.ProcessFullCallbackResult(html);
 },
 RequirePartialUpdate: function(html) {
  var helper = this.GetEndlessPagingHelper();
  return html.indexOf("EP|") == 0 && helper;
 },
 ProcessPartialCallbackResult: function(result) {
  var helper = this.GetEndlessPagingHelper();
  helper.OnCallback(result);
 },
 ProcessFullCallbackResult: function(result) {
  var rootTD = this.GetGridTD();
  if(rootTD)
   ASPx.SetInnerHtml(rootTD, result);
 },
 OnFunctionalCallback: function(result){
  this.PreventCallbackAnimation();
  var result = this.ParseFuncCallbackResult(result.substr(3));
  if(!result) return;
  if(this.IsHeaderFilterFuncCallback(result.callback))
   this.OnFuncCallback(result);
  else 
   window.setTimeout(function() { this.OnFuncCallback(result); }.aspxBind(this), 0);
 },
 OnCallbackFinalized: function() {
  if(this.afterCallbackRequired)
   this.OnAfterCallback();
 },
 IsHeaderFilterFuncCallback: function(callback) {
  return callback === this.GetFilterHelper().OnHeaderFilterCallback;
 },
 ParseFuncCallbackResult: function(result) {
  var pos = result.indexOf("|");
  if(pos < 0) return;
  var index = parseInt(result.substr(0, pos), 10);
  var info = this.GetCallbackHelper().GetFuncCallBackInfo(index);
  if(info && info.callback)
   return { callback: info.callback, params: result.substr(pos + 1) };
 },
 OnFuncCallback: function(result) {
  if(result && result.callback)
   result.callback(eval("(" + result.params + ")"));
 },
 OnCallbackErrorAfterUserHandle: function(errorMessage, data) {
  this.SetCallbackErrorData(errorMessage, data, true);
 },
 OnCallbackError: function(result, data){
  this.SetCallbackErrorData(result, data, false);
  this.SetAfterCallbackRequired();
 },
 SetAfterCallbackRequired: function() {
  if(this.GetGridTD())
   this.afterCallbackRequired = true;
 },
 SetCallbackErrorData: function(errorMessage, data, userHandled) {
  this.showingError = errorMessage;
  this.errorData = data;
  this.userHandledCallbackError = userHandled;
 },
 ShowCallbackError: function(errorText, errorData) {
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper && batchEditHelper.ShowCallbackError(errorText, errorData))
   return;
  var displayIn = this;
  var popupForm = this.GetPopupEditForm();
  if(popupForm) {
   displayIn = popupForm;
   this.ShowPopupEditForm();
  }
  this.ShowCallbackErrorCore(displayIn, errorText);
 },
 ShowCallbackErrorCore: function(displayIn, errorText) {
  var errorTextContainer = this.GetErrorTextContainer(displayIn);
  if(errorTextContainer)
   errorTextContainer.innerHTML = errorText;
  else
   ASPx.ShowErrorAlert(errorText);
 },
 GetErrorTextContainer: function(displayIn) { },
 CreateEditingErrorItem: function(visibleIndex) { },
 CancelCallbackCore: function() {
  this.RestoreCallbackSettings();
  this.InitializeAccessibilityEvents();
  this.InitializeCommandColumnHeaderLinkEvents();
  this.ResetGestureElementPosition();
  this.GetFilterHelper().OnCancelCallbackCore();
  this.keyboardLock = false;
 },
 ResetGestureElementPosition: function() {  
  if(!ASPx.GesturesHelper) return;
  var handler = ASPx.GesturesHelper.handlers[this.name];
  if(handler)
   handler.ResetGestureElementPosition();
 },
 OnBeforeCallbackOrPostBack: function() {
  this.GetFilterHelper().LockFilter();
  this.HidePopupEditForm();
  ASPxClientGridBase.SaveActiveElementSettings(this);
 },
 OnBeforeCallback: function(command) {
  this.GetFilterHelper().OnBeforeCallback();
  this.GetToolbarHelper().OnBeforeCallback();
  this.keyboardLock = true;
  var endlessPagingHelper = this.GetEndlessPagingHelper();
  if(endlessPagingHelper)
   endlessPagingHelper.OnBeforeCallback(command);
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.OnBeforeCallback(command);
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper)
   cellFocusHelper.OnBeforeCallback();
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.OnBeforeCallback();
  this.ShowLoadingElements();
  this.SaveCallbackSettings();
  if(this.accessibilityCompliant)
   this.isAccessibleRowEditing = this.IsRowEditingCommand(command);
 },
 IsRowEditingCommand: function(command) {
  return command == ASPxClientGridViewCallbackCommand.AddNewRow || 
      command == ASPxClientGridViewCallbackCommand.StartEdit;
 },
 OnAfterCallback: function() {
  this.InitializeBubbleEvents();
  this.GetFilterHelper().OnAfterCallback();
  this.GetToolbarHelper().OnAfterCallback();
  var endlessPagingHelper = this.GetEndlessPagingHelper();
  if(endlessPagingHelper)
   endlessPagingHelper.OnAfterCallback();
  var checkBoxCollectionReinitializeRequired = !this.HasCallbackError(); 
  this.ProcessGridCallbackError();
  this.pendingCommands = [ ];
  try {
   this._setFocusedItemInputValue();
   this.EnsureRowKeys();
   this.SetHeadersClientEvents();
   this.RestoreCallbackSettings();
   this.InitializeAccessibilityEvents();
   this.InitializeCommandColumnHeaderLinkEvents();
   this.EnsureRowHotTrackItems();
   if(this.kbdHelper && !this.useEndlessPaging)
    this.kbdHelper.EnsureFocusedRowVisible();
  }
  finally {
   this.keyboardLock = false;
  }
  this.CheckPendingEvents();
  this.PrepareCommandButtons();
  if(this.checkBoxImageProperties && checkBoxCollectionReinitializeRequired){
   this.CreateInternalCheckBoxCollection();
   this.UpdateSelectAllCheckboxesState();
  }
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.OnAfterCallback();
  var cellSelectionHelper = this.GetCellSelectionHelper();
  if(cellSelectionHelper)
   cellSelectionHelper.OnAfterCallback();
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper)
   cellFocusHelper.OnAfterCallback();
  this.CheckEndlessPagingLoadNextPage();
  window.setTimeout(this.scrollToElementAsignedFromServer.bind(this), 0);
  if(this.isAccessibleRowEditing)
   this.HandleAccessibleFocusForEditingRow();
 },
 HasCallbackError: function() { return !!this.showingError; },
 ProcessGridCallbackError: function() {
  if(!this.HasCallbackError()) return;
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.ProcessGridCallbackError();
  if(this.userHandledCallbackError)
   this.ProcessCallbackErrorAfterUserHandle();
  else
   this.ShowCallbackError(this.showingError, this.errorData);
  this.SetCallbackErrorData(null, null, false);
 },
 ProcessCallbackErrorAfterUserHandle: function() {
  this.ShowPopupEditForm();
 },
 SaveCallbackSettings: function() {
  this.SaveCustWindowScroll();
 },
 RestoreCallbackSettings: function() {
  this.RestoreCustWindowScroll();
  this.ApplyPostBackSyncData();
  this.ResetControlAdjustment(); 
  ASPxClientGridBase.RestoreActiveElementSettings(this); 
 },
 SaveCustWindowScroll: function() {
  var custWindow = this.GetCustomizationWindow();
  var contentContainer = custWindow && custWindow.IsVisible() && custWindow.GetContentContainer(-1);
  if(contentContainer)
   this.savedCustWindowScroll = { left: contentContainer.scrollLeft, top: contentContainer.scrollTop };
 },
 RestoreCustWindowScroll: function() {   
  var custWindow = this.GetCustomizationWindow();
  var contentContainer = custWindow && custWindow.IsVisible() && custWindow.GetContentContainer(-1);
  if(contentContainer && ASPx.IsExists(this.savedCustWindowScroll)) {
   contentContainer.scrollLeft = this.savedCustWindowScroll.left;
   contentContainer.scrollTop = this.savedCustWindowScroll.top;
  }
 },
 ShowPopupEditForm: function() {
  var popupForm = this.GetPopupEditForm();
  if(popupForm && !popupForm.IsVisible())
   popupForm.Show();
 },
 HidePopupEditForm: function() {
  var popup = this.GetPopupEditForm();
  if(popup)
   popup.Hide();
 },
 OnPopupEditFormInit: function(popup) {
  if(this.HasHorzScroll() && this.GetVisibleItemsOnPage() > 0) {
   var popupHorzOffset = popup.GetPopupHorizontalOffset();
   popup.SetPopupHorizontalOffset(popupHorzOffset - this.GetPopupEditFormHorzOffsetCorrection(popup));
  }
  popup.Show();
 },
 GetPopupEditFormHorzOffsetCorrection: function(popup) {
  return 0;
 },
 HandleAccessibleFocusForEditingRow: function() {
  var editingRow = this.GetEditingRow();
  if(!editingRow || !this.accessibilityFocusTreeLine)
   return;
  var focusElement = ASPx.FindFirstChildActionElement(editingRow, function(element) {
   return !this.IsCommandColumnItem(element);
  }.aspxBind(this));
  this.accessibilityFocusTreeLine = ASPx.RestoreFocusHelper.getTreeLineCore(this.GetMainElement(), focusElement);
  this.isAccessibleRowEditing = false;
 },
 _isRowSelected: function(visibleIndex) {
  if(!ASPx.IsExists(this.stateObject.selection)) return false;
  var index = this._getItemIndexOnPage(visibleIndex);
  return this._isTrueInCheckList(this.stateObject.selection, index);
 },
 _isTrueInCheckList: function(checkList, index) {
  if(index < 0 ||  index >= checkList.length) return false;
  return checkList.charAt(index) == "T";
 },
 _getSelectedRowCount: function() {
  var count = this.selectedWithoutPageRowCount + this._getSelectedRowCountOnPage();
  if(this.allowSelectSingleRowOnly)
   count = Math.min(count, 1);
  return count;
 },
 _getSelectedRowCountOnPage: function(){
  if(!ASPx.IsExists(this.stateObject.selection))
   return 0;
  var checkList = this.stateObject.selection;
  var selCount = 0;
  for(var i = 0; i < checkList.length; i++) {
   if(checkList.charAt(i) == "T") selCount ++;
  }
  return selCount;
 },
 _selectAllRowsOnPage: function(checked) {
  if(checked && this.allowSelectSingleRowOnly) {
   this.SelectItem(0, true);
   return;
  }
  if(!ASPx.IsExists(this.stateObject.selection)) return;
  this._selectAllSelBtn(checked);
  var prevSelectedRowCount = 0;
  var isTrueInCheckList = false;
  for(var i = 0; i < this.pageRowCount; i ++) {
   isTrueInCheckList = this._isTrueInCheckList(this.stateObject.selection, i);
   if(isTrueInCheckList) prevSelectedRowCount++; 
   if(isTrueInCheckList != checked)
    this.ChangeItemStyle(i + this.visibleStartIndex, this.GetSelectedItemStyle(checked));
  }
  if (prevSelectedRowCount == 0 && !checked) return;
  var selValue = "";
  if(checked) {
   for(var i = 0; i < this.pageRowCount; i ++)
    selValue += this.IsDataItem(this.visibleStartIndex + i ) ? "T" : "F";
  }
  if(selValue != this.stateObject.selection) {
   this.userChangedSelection = true;
   if(selValue == "") selValue = "U";
   this.stateObject.selection = selValue;
  }
  this.DoSelectionChanged(-1, checked, true);
  this.UpdateSelectAllCheckboxesState();
 },
 SelectAllItemsOnPage: function(selected) {
  if(!ASPx.IsExists(selected)) selected = true;
  this._selectAllRowsOnPage(selected);
 },
 UnselectAllItemsOnPage: function() {
  this.SelectAllItemsOnPage(false);
 },
 ConfirmDeleteGridItem: function() {
  return this.confirmDelete == "" || confirm(this.confirmDelete);
 },
 DeleteGridItem: function(visibleIndex) {
  if(!this.allowDelete || !this.ConfirmDeleteGridItem())
   return;
  this.DeleteItem(visibleIndex);
 },
 _selectAllSelBtn: function(checked, exceptName) {
  if(!this.checkBoxImageProperties) return;
  this.internalCheckBoxCollection.elementsMap.forEachEntry(function(key, checkBox) {
   if(key !== exceptName && checkBox.SetValue)
    checkBox.SetValue(checked ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked);
  });
 },
 doRowMultiSelect: function(row, rowIndex, evt) {
  var ctrlKey = evt.ctrlKey || evt.metaKey,
   shiftKey = evt.shiftKey;
  if(ctrlKey || shiftKey)
   ASPx.Selection.Clear();
  if(this.allowSelectSingleRowOnly)
   shiftKey = false;
  if(!ctrlKey && !shiftKey) {
   if(this._getSelectedRowCountOnPage() === 1 && this._isRowSelected(rowIndex))
    return;
   this._selectAllRowsOnPage(false);
   this.SelectItem(rowIndex, true);
   this.lastMultiSelectIndex = rowIndex;
  } else {
   if(ctrlKey) {
    this.SelectItem(rowIndex, !this._isRowSelected(rowIndex));
    this.lastMultiSelectIndex = rowIndex;
   } else {
    var startIndex = rowIndex > this.lastMultiSelectIndex ? this.lastMultiSelectIndex + 1 : rowIndex;
    var endIndex = rowIndex > this.lastMultiSelectIndex ? rowIndex : this.lastMultiSelectIndex - 1;
    for(var i = this.visibleStartIndex; i < this.pageRowCount + this.visibleStartIndex; i ++) {
     if(i == this.lastMultiSelectIndex) 
      continue;
     this.SelectItem(i, i >= startIndex && i <= endIndex);
    }
   }
  }
  this.UpdatePostBackSyncInput();
 },
 InitializeAccessibilityEvents: function() {
  if(!this.accessibilityCompliant)
   return;
  if(this.isAccessibleFilterRowMenu)
   this.AddKeyDownFilterRowButtonHandler();
  this.PreventMouseDownHeaderCaptionLinkEvent();
 },
 AddKeyDownFilterRowButtonHandler: function() {
  var filterRow = this.GetFilterRow();
  if(!filterRow)
   return;
  var buttons = [];
  ASPx.GetNodesByPartialId(filterRow, this.AccessibleFilterRowButtonID, buttons);
  var handler = { "keydown": ASPx.Evt.InvokeMouseClickByKeyDown };
  for(var i = 0; i < buttons.length; i++)
   this.AttachEventsToElement(buttons[i], handler);
 },
 PreventMouseDownHeaderCaptionLinkEvent: function () {
  var headerCaptionLinkSelector = "a[id^='" + this.name + "'][id$='_l']";
  var headerCaptionLinks = this.GetMainElement().querySelectorAll(headerCaptionLinkSelector);
  this.PreventMouseDownHeaderLinkEvent(headerCaptionLinks);
 },
 InitializeCommandColumnHeaderLinkEvents: function () { },
 PreventMouseDownHeaderLinkEvent: function(headerLinks) {
  var handler = {
   "mousedown": function (e) {
    ASPx.Evt.GetEventSource(e).focus();
    ASPx.Evt.PreventEvent(e);
   }
  };
  for(var i = 0; i < headerLinks.length; i++)
   this.AttachEventsToElement(headerLinks[i], handler, true);
 },
 SelectItemsByKey: function(keys, selected){
  if(!ASPx.IsExists(selected)) selected = true;
  if(!ASPx.IsExists(keys)) return;
  if(keys.constructor != Array)
   keys = [keys];
  this.gridCallBack([ASPxClientGridViewCallbackCommand.SelectRowsKey, selected].concat(keys));
 },
 SelectItem: function(visibleIndex, checked, fromCheckBox) {
  if(!this.IsPossibleSelectItem(visibleIndex, checked)) return;
  if(ASPx.IsExists(fromCheckBox)) fromCheckBox = false;
  var index = this._getItemIndexOnPage(visibleIndex);
  if(index < 0) return;
  if(checked && this.allowSelectSingleRowOnly)
   this._selectAllRowsOnPage(false);
  if(ASPx.IsExists(this.stateObject.selection)) {
   this.userChangedSelection = true;
   var checkList = this.stateObject.selection;
   if(index >= checkList.length) {
    if(!checked) return;
    for(var i = checkList.length; i <= index; i ++)
     checkList += "F";
   }
   checkList = checkList.substr(0, index) + (checked ? "T" : "F") + checkList.substr(index + 1, checkList.length - index - 1);
   if(checkList.indexOf("T") < 0) checkList = "U";
   this.stateObject.selection = checkList;
  }
  this.selectItemCheckbox(visibleIndex, checked);
  this.UpdateSelectAllCheckboxesState();
  this.ChangeItemStyle(visibleIndex, this.GetSelectedItemStyle(checked));
  this.DoSelectionChanged(visibleIndex, checked, false);
 },
 selectItemCheckbox: function(visibleIndex, checked) {
  var checkBox = this.GetDataRowSelBtn(visibleIndex);
  if(checkBox) {
   var internalCheckBox = this.internalCheckBoxCollection && this.internalCheckBoxCollection.Get(checkBox.id);
   if(internalCheckBox)
    internalCheckBox.SetValue(checked ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked);
  }
 },
 IsPossibleSelectItem: function(visibleIndex, newSelectedValue){
  if(this.IsBatchEditDeletedItem(visibleIndex))
   return false;
  return visibleIndex > -1 && this._isRowSelected(visibleIndex) != newSelectedValue;
 },
 UpdateSelectAllCheckboxesState: function(){
  if(!this.selectAllSettings)
   return;
  for(var i = 0; i < this.selectAllSettings.length; i++){
   var columnSelectAllSettings = this.selectAllSettings[i];
   if(columnSelectAllSettings === null)
    continue;
   var selectAllButtonInput = this.GetSelectAllBtn(columnSelectAllSettings.index);
   if(selectAllButtonInput && !this.IsCheckBoxDisabled(selectAllButtonInput))
    this.UpdateSelectAllCheckboxStateCore(selectAllButtonInput, columnSelectAllSettings.mode);
  }
 },
 UpdateSelectAllCheckboxStateCore: function(selectAllButtonInput, selectMode){
  var value = ASPx.CheckBoxInputKey.Indeterminate;
  var selectedRowCountOnPage = this.GetSelectedKeysOnPage().length;
  var considerSelectionOnPages = selectMode == 2 && this.selectAllBtnStateWithoutPage !== null;
  if(this.GetDataItemCountOnPage() == selectedRowCountOnPage && (!considerSelectionOnPages || this.selectAllBtnStateWithoutPage == ASPx.CheckBoxInputKey.Checked))
   value = ASPx.CheckBoxInputKey.Checked;
  else if(selectedRowCountOnPage == 0 && (!considerSelectionOnPages || this.selectAllBtnStateWithoutPage == ASPx.CheckBoxInputKey.Unchecked))
   value = ASPx.CheckBoxInputKey.Unchecked;
  var selectAllCheckBoxInst = this.internalCheckBoxCollection.Get(selectAllButtonInput.id);
  selectAllCheckBoxInst.SetValue(value);
 },
 GetDataItemCountOnPage: function(){
  return this.pageRowCount;
 },
 ScheduleUserCommand: function(args, postponed, eventSource) {
  if(!args || args.length == 0) 
   return;
  var commandName = args[0];
  var rowCommands = this.GetUserCommandNamesForRow();
  if((this.useEndlessPaging || this.allowBatchEditing) && ASPx.Data.ArrayIndexOf(rowCommands, commandName) > -1)
   args[args.length - 1] = this.FindParentRowVisibleIndex(eventSource, true);
  postponed &= this.IsMainTableChildElement(eventSource);
  this.ScheduleCommand(args, postponed);
 },
 GetUserCommandNamesForRow: function() { return [ "CustomButton", "Select", "StartEdit", "Delete", "Recover", "CancelEdit" ]; },
 IsMainTableChildElement: function(src) { return true; },
 FindParentRowVisibleIndex: function(element, dataAndGroupOnly) {
  var regEx = this.GetItemVisibleIndexRegExp(dataAndGroupOnly);
  var editingRow = this.GetEditingRow();
  while(element) {
   if(element.tagName === "BODY" || element.id == this.name)
    return this.InvalidItemIndex;
   var matches = regEx.exec(element.id);
   if(matches && matches.length == 3)
    return parseInt(matches[2]);
   if(element === editingRow)
    return this.editItemVisibleIndex;
   element = element.parentNode;
  }
  return this.InvalidItemIndex;
 },
 GetItemVisibleIndexRegExp: function(dataAndGroupOnly) {
  return this.GetItemVisibleIndexRegExpByIdParts();
 },
 GetItemVisibleIndexRegExpByIdParts: function(idParts){
  if(!idParts) idParts = [ ];
  return new RegExp("^(" + this.name + "_(?:" + idParts.join("|") + "))(-?\\d+)(?:_\\d+)?$");
 },
 ScheduleCommand: function(args, postponed) {
  if(postponed)
   this.pendingCommands.push(args);
  else 
   this.PerformScheduledCommand(args);
 },
 PerformScheduledCommand: function(args) {
  if(ASPx.IsFunction(args)) {
   args(); 
   return;
  }
  if(args && args.length > 0) {
   var commandName = "UA_" + args[0];
   if(this[commandName])
    this[commandName].apply(this, args.slice(1));
  }
 },
 PerformPendingCommands: function() {
  var commandCount = this.pendingCommands.length;
  for(var i = 0; i < commandCount; i++)
   this.PerformScheduledCommand(this.pendingCommands.pop());
 },
 getItemByHtmlEvent: function(evt) { return null; },
 getItemByHtmlEventCore: function(evt, partialID) {
  var item = ASPx.GetParentByPartialId(ASPx.Evt.GetEventSource(evt), partialID);
  if(item && item.id.indexOf(this.name) > -1)
   return item;
  return null;
 },
 NeedProcessTableClick: function(evt) {
  var source = ASPx.Evt.GetEventSource(evt);
  var handlingControl = this.GetTableClickHandlingControl(source);
  return handlingControl && this === handlingControl;
 },
 GetTableClickHandlingControl: function(source) {
  var treeLine = ASPx.GetElementTreeLine(source);
  for(var i = 0; i < treeLine.length; i++) {
   var control = ASPx.GetControlCollection().GetByName(treeLine[i].id);
   if(control && control instanceof ASPxClientGridBase)
    return control;
  }
  return null;
 },
 mainTableClick: function(evt) { this.mainTableClickCore(evt); },
 mainTableDblClick: function(evt) { 
  var item = this.getItemByHtmlEvent(evt);
  if(!item) return;
  var forceItemDblClickEvent = true;
  var itemIndex = this.getItemIndex(item.id);
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper){
   batchEditHelper.ProcessTableClick(item, ASPx.Evt.GetEventSource(evt), evt, true);
   forceItemDblClickEvent = batchEditHelper.GetEditingRecordKey() !== this.ConvertVisibleIndexToKey(itemIndex);
  }
  if(forceItemDblClickEvent)
   this.RaiseItemDblClick(itemIndex, evt);
 },
 mainTableClickCore: function(evt, fromCheckBox) {
  if(this.kbdHelper) {
   this.kbdHelper.preventBrowserScrollOnFocus = fromCheckBox;
   this.kbdHelper.HandleClick(evt);
   this.kbdHelper.preventBrowserScrollOnFocus = false;
  }
  var sendNotificationCallback = true;
  this.mainTableClickData.processing = true;
  try {
   this.ProcessTableClick(evt, fromCheckBox);
   var callbackHelper = this.GetCallbackHelper();
   var savedRequestCount = callbackHelper.GetTotalRequestCount();
   this.PerformPendingCommands();
   var currentRequestCount = callbackHelper.GetTotalRequestCount();
   sendNotificationCallback = currentRequestCount === savedRequestCount;
  } finally {
   if(sendNotificationCallback)
    if(this.mainTableClickData.focusChanged && !this.mainTableClickData.selectionChanged) {
     this.gridCallBack([ASPxClientGridViewCallbackCommand.FocusedRow]);
    } else if(this.mainTableClickData.selectionChanged) {
     this.gridCallBack([ASPxClientGridViewCallbackCommand.Selection]);
    }
   this.mainTableClickData.processing = false;
   this.mainTableClickData.focusChanged = false;
   this.mainTableClickData.selectionChanged = false;
  }
 },
 ProcessTableClick: function(evt, fromCheckBox) {
  var source = ASPx.Evt.GetEventSource(evt);
  var item = this.getItemByHtmlEvent(evt);
  if(item) {
   var itemIndex = this.getItemIndex(item.id);
   var isCommandColumnItem = this.IsCommandColumnItem(source);
   if(!isCommandColumnItem && !fromCheckBox) {
    var batchEditHelper = this.GetBatchEditHelper();
    if(batchEditHelper && batchEditHelper.ProcessTableClick(item, source, evt))
     return;
    if(this.RaiseItemClick(itemIndex, evt)) 
     return;
   }
   var prevFocusedItemIndex = this._getFocusedItemIndex();
   if(this.CanTryFocusItemOnTableClick())
    this.TryFocusItem(itemIndex, evt);
   if(this.allowSelectByItemClick) {
    if(!this.testActionElement(source) && !isCommandColumnItem && !fromCheckBox) {
     if(this.lookupBehavior) {
      var checked = this.allowSelectSingleRowOnly || !this._isRowSelected(itemIndex);
      this.SelectItem(itemIndex, checked);
     } else {
      if(!fromCheckBox && !evt.shiftKey && this.RequireProcessTableClickLikeCheckBoxClick(source, itemIndex)) { 
       var newSelected = this.allowSelectSingleRowOnly || !this._isRowSelected(itemIndex);
       this.SelectItem(itemIndex, newSelected);
       return;
      }
      var indexCorrection = 0;
      if(this.lastMultiSelectIndex < 0 && prevFocusedItemIndex > -1) {
       if(evt.shiftKey && itemIndex != prevFocusedItemIndex && !this._isRowSelected(prevFocusedItemIndex))
        indexCorrection = itemIndex > prevFocusedItemIndex ? -1 : 1;
       this.lastMultiSelectIndex = prevFocusedItemIndex + indexCorrection;
      }
      this.doRowMultiSelect(item, itemIndex, evt);
      this.lastMultiSelectIndex -= indexCorrection;
     }
    }
   } else {
    this.lastMultiSelectIndex = itemIndex;
   }
  }
 },
 testActionElement: function(element) {
  return element && element.tagName.match(/input|select|textarea|^a$/i);
 },
 IsCommandColumnItem: function(element) {
  if(!element) return false;
  if(ASPx.ElementHasCssClass(element, this.CommandColumnItemClassName))
   return true;
  return ASPx.GetIsParent(this.GetMainElement(), ASPx.GetParentByPartialId(element, "DXCBtn"));
 },
 RequireProcessTableClickLikeCheckBoxClick: function(tableClickSource, visibleIndex) { return false; },
 OnBeforeFocusedCellChanging: function(cellInfo, htmlEvent) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(cellInfo.recordKey);
  if(this.allowFocusedRow && visibleIndex >= 0 && visibleIndex !== this.focusedRowIndex && !this.IsBatchEditDeletedItem(visibleIndex)) 
   return this.RaiseItemFocusing(visibleIndex, htmlEvent);
  return false;
 },
 OnFocusedCellChanged: function(cellInfo, htmlEvent) {
  this._setFocusedItemIndex(this.ConvertKeyToVisibleIndex(cellInfo.recordKey));
  var cellSelectionHelper = this.GetCellSelectionHelper();
  if(cellSelectionHelper)
   cellSelectionHelper.OnFocusedCellChanged(cellInfo, htmlEvent);
  var clipboardHelper = this.GetClipboardHelper();
  if(clipboardHelper)
   clipboardHelper.OnFocusedCellChanged(cellInfo);
  if(!this.allowFocusedRow)
   this.ChangeToolbarItemsEnabling();
 },
 CanTryFocusItemOnTableClick: function() { return !this.GetCellFocusHelper(); },
 TryFocusItem: function(visibleIndex, htmlEvent) {
  if(this.allowFocusedRow && visibleIndex >= 0 && visibleIndex !== this.focusedRowIndex && !this.IsBatchEditDeletedItem(visibleIndex)) {
   var isCanceledByUser = this.RaiseItemFocusing(visibleIndex, htmlEvent);
   if(!isCanceledByUser) {
    this._setFocusedItemIndex(visibleIndex);
    return true;
   }
  }
  return false;
 },
 _setFocusedItemIndex: function(visibleIndex) {
  if(visibleIndex < 0) 
   visibleIndex = -1;
  if(!this.IsPossibleFocusItem(visibleIndex)) 
   return;
  var oldIndex = this.focusedRowIndex;
  this.focusedRowIndex = visibleIndex;
  this.ChangeFocusedItemStyle(oldIndex, false);
  this.ChangeFocusedItemStyle(this.focusedRowIndex, true);
  this._setFocusedItemInputValue();
  if(this.callbackOnFocusedRowChanged) {
   this.UpdatePostBackSyncInput(true);
   if(!this.mainTableClickData.processing) {
    this.gridCallBack([ASPxClientGridViewCallbackCommand.FocusedRow]);
   } else {
    this.mainTableClickData.focusChanged = true;
   }
   return;
  }
  this.ChangeToolbarItemsEnabling();
  this.RaiseFocusedItemChanged();
 },
 IsPossibleFocusItem: function(visibleIndex) { return this.allowFocusedRow && visibleIndex !== this.focusedRowIndex && !this.IsBatchEditDeletedItem(visibleIndex); },
 ChangeToolbarItemsEnabling: function(){
  var helper = this.GetToolbarHelper();
  helper.RefreshItemsState();
 },
 ChangeToolbarBatchEditItemsState: function(state) {
  var helper = this.GetToolbarHelper();
  if(helper)
   helper.OnBatchEditItemsStateChanged(state);
 },
 ChangeFocusedItemStyle: function(visibleIndex, focused) {
  if(visibleIndex < 0) return;
  var itemStyle = this.GetFocusedItemStyle(visibleIndex, focused);
  this.ChangeItemStyle(visibleIndex, itemStyle);
 },
 GetFocusedItemStyle: function(visibleIndex, focused){
  if(focused)
   return this.GetStyleHelper().GetFocusedItemStyle();
  return this.GetSelectedItemStyle(this._isRowSelected(visibleIndex));
 },
 GetFocusedCell: function() {
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper && cellFocusHelper.IsCellFocused()) {
   var info = cellFocusHelper.GetFocusedCellInfo();
   if(info)
    return this.CreateUserCellInfo(this.ConvertKeyToVisibleIndex(info.recordKey), this.GetColumn(info.columnIndex), info.recordKey);
  }
  return null;
 },
 SetFocusedCell: function(itemIndex, columnIndex) { this.SetFocusedCellByKey(this.ConvertVisibleIndexToKey(itemIndex), columnIndex); },
 SetFocusedCellByKey: function(key, columnIndex) {
  var cellFocusHelper = this.GetCellFocusHelper();
  if(cellFocusHelper)
   cellFocusHelper.SetFocusedCell(key, columnIndex);
 },
 _setFocusedItemInputValue: function() {
  if(ASPx.IsExists(this.stateObject.focusedRow)) 
   this.stateObject.focusedRow = this.focusedRowIndex;
 },
 _getFocusedItemIndex: function() {
  if(!this.allowFocusedRow) return -1;
  return this.focusedRowIndex;
 },
 getItemIndex: function(rowId) {   
  return this.tryGetNumberFromEndOfString(rowId).value;
 },
 tryGetNumberFromEndOfString: function(str) {
  var value = -1;
  var success = false;
  var n = str.length - 1;
  while(n >= 0 && !isNaN(parseInt(str.substr(n), 10))) {
   value = parseInt(str.substr(n), 10);
   success = true;
   n--;
  }
  return { success: success, value: value };
 },
 GetSelectedCells: function() {
  var result = [];
  var cellSelectionHelper = this.GetCellSelectionHelper();
  if(cellSelectionHelper) {
   var cellsInfo = cellSelectionHelper.GetSelectedCells();
   if(cellsInfo && cellsInfo.length > 0) {
    result = cellsInfo.map(function(info) {
     return this.CreateUserCellInfo(this.ConvertKeyToVisibleIndex(info.recordKey), this.GetColumn(info.columnIndex), info.recordKey);
    }.bind(this));
   }
  }
  return result;
 },
 SetCellSelection: function(key, columnIndex, isSelect) {
  var cellSelectionHelper = this.GetCellSelectionHelper();
  if(cellSelectionHelper) {
   var action = isSelect ? cellSelectionHelper.SelectCell : cellSelectionHelper.UnselectCell;
   action.call(cellSelectionHelper, cellSelectionHelper.CreateCellInfo(key, columnIndex));
  }
 },
 GetSelectedState: function() {
  if(!this.userChangedSelection) return null;
  if(!ASPx.IsExists(this.stateObject.selection)) return null;
  return this.stateObject.selection;
 },
 GetKeyValues: function() {
  return ASPx.Json.ToJson(this.stateObject.keys);
 },
 UpdateItemsStyle: function() {
  var start = this.GetTopVisibleIndex();
  var end = start + this.GetVisibleItemsOnPage();
  for(var i = start; i < end; i++) 
   this.UpdateItemStyle(i, this.GetItemStyle(i));
 },
 UpdateItemStyle: function(visibleIndex) {
  this.ChangeItemStyle(visibleIndex, this.GetItemStyle(visibleIndex));
 },
 GetSelectedItemStyle: function(selected) {
  var helper = this.GetStyleHelper();
  return selected ? helper.GetSelectedItemStyle() : helper.GetClearItemStyle();
 },
 GetItemStyle: function(visibleIndex){
  var helper = this.GetStyleHelper();
  var style = helper.GetClearItemStyle();
  if(this.IsBatchEditDeletedItem(visibleIndex))
   style = helper.GetBatchEditDeletedItemStyle();
  else if(this.allowFocusedRow && this._getFocusedItemIndex() == visibleIndex)
   style = helper.GetFocusedItemStyle();
  else if(this._isRowSelected(visibleIndex))
   style = helper.GetSelectedItemStyle();
  return style;
 },
 ChangeItemStyle: function(visibleIndex, rowStyle) {
  if(!this.RequireChangeItemStyle(visibleIndex, rowStyle))
   return;
  this.ApplyItemStyle(visibleIndex, rowStyle);
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.OnItemStyleChanged(this.GetItemKey(visibleIndex), rowStyle);
 },
 ApplyItemStyle: function(visibleIndex, styleInfo) {
  var item = this.GetItem(visibleIndex);
  this.ApplyElementStyle(item, styleInfo);
 },
 ApplyElementStyle: function(element, styleInfo) {  
  this.GetStyleHelper().ApplyElementStyle(element, styleInfo);
 },
 RequireChangeItemStyle: function(visibleIndex, itemStyle){
  var focusedIndex = this._getFocusedItemIndex();
  var helper = this.GetStyleHelper();
  if(focusedIndex > -1 && focusedIndex == visibleIndex && !helper.IsFocusedItemStyle(itemStyle))
   return false;
  return !!this.GetItem(visibleIndex);
 },
 _getItemIndexOnPage: function(visibleIndex) { 
  return visibleIndex - this.visibleStartIndex; 
 },
 getColumnIndex: function(colId) {
  if(this.IsEmptyHeaderID(colId))
   return -1;
  var index = this.tryGetNumberFromEndOfString(colId).value;
  var postfix = "col" + index;
  if(colId.lastIndexOf(postfix) == colId.length - postfix.length)
   return index;
  return -1;
 },
 getColumnObject: function(colId) {
  var index = this.getColumnIndex(colId);
  return index > -1 ? this._getColumn(index) : null;
 },
 _getColumnIndexByColumnArgs: function(column) {
  column = this._getColumnObjectByArg(column);
  if(!column) return null;
  return column.index;
 },
 _getColumnObjectByArg: function(arg) {
  if(!ASPx.IsExists(arg)) return null;
  if(typeof(arg) == "number") return this._getColumn(arg);
  if(ASPx.IsExists(arg.index)) return arg;
  var column = this._getColumnById(arg);
  if(column) return column;
  return this._getColumnByField(arg);  
 },
 _getColumnCount: function() { return this.columns.length; },
 _getColumn: function(index) {
  for(var i = 0; i < this.columns.length; i++){
   if(this.columns[i].index == index) return this.columns[i];
  }
  return null;
 },
 _getColumnById: function(id) {
  if(!ASPx.IsExists(id)) return null;
  for(var i = 0; i < this.columns.length; i++) {
   if(this.columns[i].id == id) return this.columns[i];
  }
  return null;
 },
 _getColumnByField: function(fieldName) {
  if(!ASPx.IsExists(fieldName)) return null;
  for(var i = 0; i < this.columns.length; i++) {
   if(this.columns[i].fieldName == fieldName) return this.columns[i];
  }
  return null;
 },
 DoSelectionChanged: function(index, isSelected, isSelectAllOnPage){
  if(this.callbackOnSelectionChanged) {
   this.UpdatePostBackSyncInput(true);
   if(!this.mainTableClickData.processing) {
    this.gridCallBack([ASPxClientGridViewCallbackCommand.Selection]);
   } else {
    this.mainTableClickData.selectionChanged = true;
   }
   return;
  }
  this.ChangeToolbarItemsEnabling();
  this.RaiseSelectionChanged(index, isSelected, isSelectAllOnPage, false);
 },
 CommandCustomButton:function(id, index) {
  var processOnServer = true;
  if(!this.CustomButtonClick.IsEmpty()) {
   var e = this.CreateCommandCustomButtonEventArgs(index, id);
   this.CustomButtonClick.FireEvent(this, e);
   processOnServer = e.processOnServer;
  }
  if(processOnServer)
   this.gridCallBack([ASPxClientGridViewCallbackCommand.CustomButton, id, index]);
 },
 CreateCommandCustomButtonEventArgs: function(index, id){
  return null;
 },
 HeaderMouseDown: function(element, e){
  if(!ASPx.Evt.IsLeftButtonPressed(e)) 
   return;
  var source = ASPx.Evt.GetEventSource(e);
  if(this.isHeaderFilterButton(source))
   return;
  if(this.TryStartColumnResizing(e, element))
   return;
  var canDrag = this.canDragColumn(element) && source.tagName != "IMG";
  var dragHelper = this.GetDragHelper();
  var drag = dragHelper.CreateDrag(e, element, canDrag);
  if(!canDrag && (e.shiftKey || e.ctrlKey))
   drag.clearSelectionOnce = true;
  dragHelper.CreateTargets(drag, e);
 },
 isHeaderFilterButton: function(el) {
  return ASPx.ElementContainsCssClass(ASPx.getSpriteMainElement(el), this.HeaderFilterButtonClassName);
 },
 TryStartColumnResizing: function(e, headerCell) {
  return false;
 }, 
 OnParentRowMouseEnter: function(element) {
  if(this.GetParentRowsWindow() == null) return;
  if(this.GetParentRowsWindow().IsWindowVisible()) return;
  this.ParentRowsTimerId = window.setTimeout(function() {
   var gv = ASPx.GetControlCollection().Get(this.name);
   if(gv)
    gv.OnParentRowsTimer(element.id);
  }.aspxBind(this), 500);
 },
 OnParentRowsTimer: function(rowId) {
  var element = ASPx.GetElementById(rowId);
  if(element)
   this.ShowParentRows(element);
 },
 OnParentRowMouseLeave: function(evt) {
  ASPx.Timer.ClearTimer(this.ParentRowsTimerId);
  if(this.GetParentRowsWindow() == null) return;
  if(evt && evt.toElement) {
   if(ASPx.GetParentByPartialId(evt.toElement, this.GetParentRowsWindow().name) != null)
    return;
  }
  this.HideParentRows();
 },
 ShowParentRows: function(element) {
  this.ParentRowsTimerId = null;
  if(this.GetParentRowsWindow() != null) {
   this.GetParentRowsWindow().ShowAtElement(element);
  }
 },
 HideParentRows: function() {
  this.ParentRowsTimerId = null;
  if(this.GetParentRowsWindow() != null) {
   this.GetParentRowsWindow().Hide();
  }
 }, 
 canSortByColumn: function(headerElement) {
  return this.getColumnObject(headerElement.id).allowSort;
 },
 canGroupByColumn: function(column) {
  return false;
 },
 canHideColumn: function(column) {
  return false;
 },
 canDragColumn: function(headerElement) {
  return false;
 },
 doPagerOnClick: function(id) {
  if(!ASPx.IsExists(id)) return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.PagerOnClick, id]);
 },
 CanHandleGesture: function(evt) {
  var source = ASPx.Evt.GetEventSource(evt);
  var table = this.GetMainTable();
  if(!table) return false;
  if(ASPx.GetIsParent(table, source))
   return !this.NeedPreventGestures(source, table);
  if(table.parentNode.tagName == "DIV" && ASPx.GetIsParent(table.parentNode, source))
   return ASPx.Browser.TouchUI || evt.offsetX < table.parentNode.clientWidth;
  return false;
 },
 AllowStartGesture: function() {
  return ASPxClientControl.prototype.AllowStartGesture.call(this) && 
   (this.AllowExecutePagerGesture(this.pageIndex, this.pageCount, 1) || this.AllowExecutePagerGesture(this.pageIndex, this.pageCount, -1));
 },
 AllowExecuteGesture: function(value) {
  return this.AllowExecutePagerGesture(this.pageIndex, this.pageCount, value);
 },
 ExecuteGesture: function(value, count) {
  this.ExecutePagerGesture(this.pageIndex, this.pageCount, value, count, function(arg) { this.doPagerOnClick(arg); }.aspxBind(this));
 },
 ApplySearchPanelFilter: function(value, isInternalCall) {
  if(!ASPx.IsExists(value))
   value = "";
  var edit = this.GetSearchEditor();
  if(edit && !isInternalCall)
   edit.SetText(value);
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.ResetScrollTop();
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ApplySearchPanelFilter, value]);
 },
 NeedShowLoadingPanelInsideEndlessPagingContainer: function() {
  var endlessPagingHelper = this.GetEndlessPagingHelper();
  return endlessPagingHelper && endlessPagingHelper.NeedShowLoadingPanelAtBottom();
 },
 ShowLoadingPanel: function() {
  var gridMainCell = this.GetGridTD();
  if(!gridMainCell)
   return;
  if(this.NeedShowLoadingPanelInsideEndlessPagingContainer()) {
   var container = this.GetEndlessPagingLPContainer();
   ASPx.SetElementDisplay(container, true);
   this.CreateLoadingPanelWithoutBordersInsideContainer(container);
   return;
  }
  var lpContainer = this.GetLoadingPanelContainer();
  if(lpContainer)
   this.CreateLoadingPanelInline(lpContainer);
  else
   this.CreateLoadingPanelWithAbsolutePosition(gridMainCell, this.GetLoadingPanelOffsetElement(gridMainCell));
 },
 ShowLoadingDiv: function () {
  if(!this.NeedShowLoadingPanelInsideEndlessPagingContainer())
   this.CreateLoadingDiv(this.GetGridTD());
 },
 ShowLoadingPanelInsideHeaderFilterPopup: function() {
  this.CreateLoadingPanelWithoutBordersInsideContainer(this.GetHeaderFilterPopup().GetContentContainer(-1));
 },
 GetCallbackAnimationElement: function() {
  var table = this.GetMainTable();
  if(table && table.parentNode && table.parentNode.tagName == "DIV")
   return table.parentNode;
  return table;
 },
 NeedPreventTouchUIMouseScrolling: function(element) {
  return this.NeedPreventGestures(element);
 },
 NeedPreventGestures: function(element, mainElement) {
  if(!ASPx.IsExists(mainElement)) {
   mainElement = this.GetMainElement();
   if(!ASPx.IsExists(mainElement) || !ASPx.GetIsParent(mainElement, element))
    return false;
  }
  var preventElement = this.IsHeaderChild(element) || this.IsActionElement(mainElement, element);
  if(preventElement)
   return true;
  return this.pageCount <= 1 ? !ASPx.Browser.MSTouchUI : false;
 },
 IsHeaderChild: function(source) {
  return false;
 },
 IsActionElement: function(mainElement, source) {
  return false;
 },
 _updateEdit: function() {
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper && !batchEditHelper.CanUpdate())
   return;
  if(!batchEditHelper && !this._validateEditors())
   return;
  if(batchEditHelper)
   batchEditHelper.OnUpdate();
  this.gridCallBack([ASPxClientGridViewCallbackCommand.UpdateEdit]);
 },
 _validateEditors: function() {
  var editors = this._getEditors();
  var isValid = true;
  if(editors.length > 0)
   isValid &= this._validate(editors);
  if(window.ASPxClientEdit)
   isValid &= ASPxClientEdit.ValidateEditorsInContainer(this.GetEditFormTable(), this.name);
  return isValid;
 },
 _validate: function(list) {
  var isValid = true;
  var firstInvalid = null;
  var edit;
  for(var i = 0; i < list.length; i ++) {
   edit = list[i];
   edit.Validate();
   isValid = edit.GetIsValid() && isValid;
   if(firstInvalid == null && edit.setFocusOnError && !edit.GetIsValid())
    firstInvalid = edit;
  }
  if (firstInvalid != null)
   firstInvalid.Focus();
  return isValid;
 },
 _getEditors: function() {
  var list = [ ];
  for(var i = 0; i < this.editorIDList.length; i++) {
   var editor = ASPx.GetControlCollection().Get(this.editorIDList[i]);
   if(editor && editor.enabled && editor.GetMainElement && ASPx.IsExistsElement(editor.GetMainElement())) {
    if(!editor.Validate || this.IsStaticBinaryImageEditor(editor)) 
     continue; 
    list.push(editor);
   }
  }
  return list;
 },
 GetEditorValues: function() {
  if(this.allowBatchEditing) return null;
  var list = this._getEditors();
  if(list.length == 0) return null;
  var res = list.length + ";";
  for(var i = 0; i < list.length; i ++) {
   res += this.GetEditorValue(list[i]);
  }
  return res;
 },
 GetEditorValue: function(editor) {
  var value = editor.GetValueString();
  var valueLength = -1;
  if(!ASPx.IsExists(value)) {
   value = "";
  } else {
   value = value.toString();
   valueLength = value.length;
  }
  return this.GetEditorIndex(editor.name) + "," + valueLength + "," + value + ";";
 },
 GetEditorIndex: function(editorId) {
  var i = editorId.lastIndexOf(this.GetEditorPrefix());
  if(i < 0) return -1;
  var result = editorId.substr(i + this.GetEditorPrefix().length);
  i = result.indexOf('_'); 
  return i > 0
   ? result.substr(0, i)
   : result;
 },
 GetBatchEditHelper: function() {
  if(!this.allowBatchEditing) return null;
  if(!this.batchEditHelper)
   this.batchEditHelper = this.CreateBatchEditHelper(this.GetBatchEditHelperOwner());
  return this.batchEditHelper;
 },
 GetBatchEditHelperOwner: function() {
  if(!this.allowBatchEditing) return null;
  if(!this.batchEditHelperOwner)
   this.batchEditHelperOwner = this.CreateBatchEditHelperOwner();
  return this.batchEditHelperOwner;
 },
 CreateBatchEditHelper: function(owner) { return new ASPx.GridBatchEditHelper(owner); },
 CreateBatchEditHelperOwner: function() { },
 GetScrollHelper: function() { return null; },
 GetDragHelper: function() {
  if(!this.dragHelper)
   this.dragHelper = new GridViewDragHelper(this);
  return this.dragHelper;
 },
 GetEndlessPagingHelper: function() {
  if(!this.useEndlessPaging) return null;
  if(!this.endlessPagingHelper)
   this.endlessPagingHelper = this.CreateEndlessPagingHelper();
  return this.endlessPagingHelper;
 },
 CreateEndlessPagingHelper: function() { return null; },
 GetCellFocusHelper: function() {
  if(!this.allowFocusedCell) return null;
  if(!this.cellFocusHelper)
   this.cellFocusHelper = this.CreateCellFocusHelper();
  return this.cellFocusHelper;
 },
 CreateCellFocusHelper: function() { return null; },
 GetCellSelectionHelper: function() {
  if(!this.allowSelectionCell) return null;
  if(!this.cellSelectionHelper)
   this.cellSelectionHelper = this.CreateCellSelectionHelper();
  return this.cellSelectionHelper;
 },
 CreateCellSelectionHelper: function() { return null; },
 GetClipboardHelper: function() {
  if(!this.allowFocusedCell) return null;
  if(!this.clipboardHelper)
   this.clipboardHelper = this.CreateClipboardHelper();
  return this.clipboardHelper;
 },
 CreateClipboardHelper: function() { return null; },
 GetStyleHelper: function() {
  if(!this.styleHelper)
   this.styleHelper = this.CreateStyleHelper(this);
  return this.styleHelper;
 },
 CreateStyleHelper: function() { return new GridStyleHelper(this); },
 GetLayoutHelper: function() {
  if(!this.layoutHelper)
   this.layoutHelper = this.CreateLayoutHelper();
  return this.layoutHelper;
 },
 CreateLayoutHelper: function() { return new GridLayoutHelper(this); },
 GetNavigationHelper: function() {
  if(!this.navigationHelper)
   this.navigationHelper = this.CreateNavigationHelper();
  return this.navigationHelper;
 },
 CreateNavigationHelper: function() { },
 GetCallbackHelper: function() {
  if(!this.callbackHelper)
   this.callbackHelper = this.CreateCallbackHelper();
  return this.callbackHelper;
 },
 CreateCallbackHelper: function() { return new GridCallbackHelper(this); },
 GetFilterHelper: function() {
  if(!this.filterHelper)
   this.filterHelper = this.CreateFilterHelper();
  return this.filterHelper;
 },
 CreateFilterHelper: function() { return new ASPx.GridFilterHelper(this); },
 GetToolbarHelper: function() {
  if(!this.toolbarHelper)
   this.toolbarHelper = this.CreateToolbarHelper();
  return this.toolbarHelper;
 },
 CreateToolbarHelper: function() { return new ASPx.GridToolbarHelper(this); },
 CreateKbdHelper: function() {
  return new ASPx.GridKbdHelper(this);
 },
 InitKbdHelper: function() {
  if(!this.kbdHelper && this.IsKbdHelperRequired())
   this.kbdHelper = this.CreateKbdHelper();
  if(this.kbdHelper) {
   if(this.IsKbdHelperRequired()) {
    this.kbdHelper.Init();
    ASPx.KbdHelper.RegisterAccessKey(this);
   }
   else
    this.kbdHelper.Dispose();
  }
 },
 OnKbdEventChanged: function() {
  this.InitKbdHelper();
 },
 IsKbdHelperRequired: function() {
  return !this.KeyDown.IsEmpty() || !this.KeyPress.IsEmpty() || !this.KeyUp.IsEmpty();
 },
 Invalidate: function() {
  this.InvalidateLayout();
 },
 InvalidateLayout: function() {
  this.GetLayoutHelper().Invalidate();
  var navigationHelper = this.GetNavigationHelper();
  if(navigationHelper)
   navigationHelper.Invalidate();
  this.serverVisibleIndicesHash = null;
 },
 IsLastCallbackProcessedAsEndless: function() {
  var helper = this.GetEndlessPagingHelper();
  return helper && helper.endlessCallbackComplete;
 },
 UpdateScrollableControls: function() {
  var helper = this.GetScrollHelper();
  if(helper)
   helper.Update();
 },
 SetHeight: function(height) {
  var mainElemnt = this.GetMainElement();
  if(!ASPx.IsExistsElement(mainElemnt)) return;
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.SetHeight(height);
 },
 AttachTableClickEvents: function(table) {
  var handlers = {
   "click": function(e) { ASPx.GTableClick(this.name, e); }.bind(this),
   "dblclick": function(e) { ASPx.GVTableDblClick(this.name, e); }.bind(this)
  };
  this.AttachEventsToElement(table, handlers, true);
 },
 AttachEventsToElement: function(element, handlers, useCapturing) {
  for(var eventName in handlers) {
   if(!handlers.hasOwnProperty(eventName))
    continue;
   var duplicateAttachLocker = "dxg" + eventName;
   if(element[duplicateAttachLocker])
    continue;
   ASPx.Evt.AttachEventToElement(element, eventName, handlers[eventName], useCapturing);
   element[duplicateAttachLocker] = true;
  }
 },
 AttachMainTableClickEvents: function() {
  var mainTable = this.GetMainTable();
  if(mainTable)
   this.AttachTableClickEvents(mainTable);
 },
 SetHeadersClientEvents: function() {
  var grid = this;
  var attachMouseDown = function(headerCell) { 
   ASPx.Evt.AttachEventToElement(headerCell, ASPx.TouchUIHelper.touchMouseDownEventName, function(e) { 
    grid.HeaderMouseDown(headerCell, e);
   }, true);
  };
  this.AttachEventToHeaderCells(attachMouseDown, false);
  this.AttachEventToHeaderCells(attachMouseDown, true);
  this.AttachEventToCustomizationWindowHeaderCells(attachMouseDown);
 },
 AttachEventToCustomizationWindowHeaderCells: function(attachFunc) {
  var custWindow = this.GetCustomizationWindowElement();
  if(!custWindow) return;
  var headers = this.GetCustomizationWindowHeaders();
  for(var i = 0; i < headers.length; i++)
   attachFunc(headers[i]);
 },
 AttachEventToHeaderCells: function(attachFunc, inGroupPanel) {
  for(var i = 0; i < this.columns.length; i++) {
   var header = this.GetHeader(this.columns[i].index, inGroupPanel);
   if(header) 
    attachFunc(header);
  }
 },
 GetCustomizationWindowHeaders: function() {
  return ASPx.GetNodesByPartialClassName(this.GetCustomizationWindowElement(), ASPx.GridViewConsts.HeaderCellCssClass);
 },
 UpdatePostBackSyncInput: function(isChangedNotification) {
  if(!ASPx.IsExists(this.stateObject.lastMultiSelectIndex)) return;
  var selectedIndex = isChangedNotification ? -1 : this.lastMultiSelectIndex; 
  this.stateObject.lastMultiSelectIndex = selectedIndex;
 },
 ApplyPostBackSyncData: function() {
  if(!ASPx.IsExists(this.stateObject.lastMultiSelectIndex)) return;
  this.lastMultiSelectIndex = this.stateObject.lastMultiSelectIndex;
 },
 shouldPreventFocusRestoringOnCallback: function () {
  return this.scrollToRowIndex !== -1 || this.shouldScrollToNewRow;
 },
 MakeRowVisible: function(visibleIndex) { },
 IsRowHotTrackEnabled: function() {
  return this.rowHotTrackStyle !== null;
 },
 EnsureRowHotTrackItems: function() {
  if(!this.IsRowHotTrackEnabled())
   return;
  var list = [ ];
  var rowIndices = this.GetRowHotTrackItemsRowIndices();
  for(var i = rowIndices.start; i < rowIndices.start + rowIndices.end; i++)
   list.push(this.GetDataItemIDPrefix() + i);
  if(list.length > 0)
   ASPx.AddHoverItems(this.name, [ [ [this.rowHotTrackStyle[0]], [this.rowHotTrackStyle[1]],  list, this.GetHotTrackItemPostfixes() ] ]);
 },
 GetHotTrackItemPostfixes: function(){ return null; },
 GetRowHotTrackItemsRowIndices: function() {
  return {
   start: this.visibleStartIndex,
   end: this.pageRowCount
  };
 },
 GetFooterCellIndex: function(element) {
  element = this.GetFooterCellElement(element, ASPx.GridViewConsts.FooterRowID);
  if(element == null)
   return -1;
  var matrix = this.GetHeaderMatrix();
  var leafIndex = element.cellIndex - this.GetFooterIndentCount(element.parentNode);
  var index = matrix.GetLeafIndices()[leafIndex];
  return ASPx.IsExists(index) ? index : -1;
 },
 GetGroupFooterCellIndex: function(element) {
  element = this.GetFooterCellElement(element, ASPx.GridViewConsts.GroupFooterRowID);
  return element != null ? this.GetColumnIndexByDataCell(element) : -1;
 },
 GetColumnIndexByDataCell: function(element) {
  return -1;
 },
 GetFooterCellElement: function(element, footerRowID) {
  var footerRowName = this.name + "_" + footerRowID;
  while(element.parentNode.id.indexOf(footerRowName) === -1) {
   if(element.tagName == "BODY")
    return null;
   element = element.parentElement;
  }
  return element;
 },
 GetFooterIndentCount: function(footerElement) {
  return ASPx.GetChildNodesByClassName(footerElement, "dxgvIndentCell").length;
 },
 Focus: function() {
  if(this.kbdHelper)
   this.kbdHelper.Focus();
 },
 PerformCallback: function(args, onSuccess){
  if(!ASPx.IsExists(args)) args = "";
  this.gridCallBack([ASPxClientGridViewCallbackCommand.CustomCallback, args], onSuccess);
 },
 GetValuesOnCustomCallback: function(args, onCallBack) {
  this.gridFuncCallBack([ASPxClientGridViewCallbackCommand.CustomValues, args], onCallBack);
 },
 GotoPage: function(pageIndex){
  if(this.useEndlessPaging)
   return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.GotoPage, pageIndex]);
 },
 GetPageIndex: function(){
  return this.pageIndex;
 },
 GetPageCount: function(){
  return this.pageCount;
 },
 NextPage: function(){
  this.gridCallBack([ASPxClientGridViewCallbackCommand.NextPage]);
 },
 PrevPage: function(focusBottomRow){
  if(!this.useEndlessPaging)
   this.gridCallBack([ASPxClientGridViewCallbackCommand.PreviousPage, focusBottomRow ? "T" : "F"]);
 },
 IsLastPage: function() {
  return this.pageIndex === this.pageCount - 1;
 },
 GetItemKey: function(visibleIndex) {
  var arrayIndex = visibleIndex - this.visibleStartIndex;
  if(arrayIndex < 0 || arrayIndex > this.keys.length - 1) 
   return null;
  var key = this.keys[arrayIndex];
  if(key == "/^DXN")
   key = null;
  return key;
 },   
 GetDataItemVisibleIndices: function(includeDeleted, fromAPI) {
  var helper = this.GetBatchEditHelper();
  if(helper) {
   includeDeleted |= helper.GetHighlightDeletedItems() && !fromAPI;
   var keys = helper.GetRecordKeys(!includeDeleted);
   return keys.map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this));
  }
  return this.GetDataItemVisibleIndicesCore();
 },
 GetDataItemVisibleIndicesCore: function() {
  var indices = this.GetCurrentPageIndices();
  return indices.filter(function(index) { return this.GetDataItem(index); }.bind(this)); 
 },
 GetRecordKeys: function(includeDeleted) { 
  var indices = this.GetDataItemVisibleIndices(includeDeleted);
  return indices.map(this.ConvertVisibleIndexToKey.bind(this));
 },
 ConvertVisibleIndexToKey: function(visibleIndex) { 
  if(!ASPx.IsExists(visibleIndex))
   return null;
  if(visibleIndex < 0)
   return visibleIndex;
  var key = this.GetItemKey(visibleIndex);
  if(ASPx.IsExists(key))
   return key;
  var helper = this.GetBatchEditHelper();
  return helper && helper.GetSavedKeyByVisibleIndex(visibleIndex);
 },
 ConvertKeyToVisibleIndex: function(key) {
  var helper = this.GetBatchEditHelper();
  if(helper && helper.IsNewRecord(key))
   return parseInt(key);  
  this.EnsureServerVisibleIndicesHash();
  if(ASPx.IsExists(this.serverVisibleIndicesHash[key]))
   return this.serverVisibleIndicesHash[key];
  return helper ? helper.GetSavedVisibleIndexByKey(key) : null;
 },
 EnsureServerVisibleIndicesHash: function() {
  if(this.serverVisibleIndicesHash)
   return;
  this.serverVisibleIndicesHash = { };
  var indices = this.GetCurrentPageIndices();
  for(var i = 0; i < indices.length; i++) {
   var visibleIndex = indices[i];
   var key = this.GetItemKey(visibleIndex);
   this.serverVisibleIndicesHash[key] = visibleIndex;
  }
 },
 GetCurrentPageIndices: function() {
  var indices = [ ];
  var startIndex = this.GetTopVisibleIndex();
  var endIndex = startIndex + this.pageRowCount;
  for(var i = startIndex; i < endIndex; i++)
   indices.push(i);
  return indices;
 },
 StartEditItem: function(visibleIndex, columnIndex) {
  this.StartEditItemByKey(this.ConvertVisibleIndexToKey(visibleIndex), columnIndex);
 },
 StartEditItemByKey: function(key, columnIndex) {
  if(!this.HasKeyField() || key === null) 
   return;
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.StartEditCell(key, columnIndex);
  else
   this.gridCallBack([ASPxClientGridViewCallbackCommand.StartEdit, key]);
 },
 IsEditing: function() { return this.editState > 0; },
 IsNewItemEditing: function() { return this.editState > 1; },
 IsEditingItem: function(visibleIndex) { return this.editItemVisibleIndex === visibleIndex; },
 IsNewRowAtBottom: function() { return this.editState == 3; },
 UpdateEdit: function(){
  this._updateEdit();
 },
 CancelEdit: function(visibleIndex) {
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper) {
   var recordKey = ASPx.IsExists(visibleIndex) && visibleIndex !== this.InvalidItemIndex ? this.ConvertVisibleIndexToKey(visibleIndex) : null;
   batchEditHelper.CancelEdit(recordKey);
  } else
   this.gridCallBack([ASPxClientGridViewCallbackCommand.CancelEdit]);
 },
 AddNewItem: function() {
  if(this.allowBatchEditing)
   this.batchEditApi.AddNewItem();
  else 
   this.AddNewItemOnServer();
 },
 AddNewItemOnServer: function() {
  if(!this.HasKeyField()) return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.AddNewRow]);
 },
 DeleteItem: function(visibleIndex) {
  if(this.allowBatchEditing)
   this.batchEditApi.DeleteItem(visibleIndex);  
  else
   this.DeleteItemByKey(this.GetItemKey(visibleIndex));
 },
 RecoverItem: function(visibleIndex){
  if(this.allowBatchEditing)
   this.batchEditApi.RecoverItem(visibleIndex);  
 },
 DeleteItemByKey: function(key) {
  if(this.allowBatchEditing)
   this.batchEditApi.DeleteItemByKey(key);
  else
   this.DeleteItemByKeyOnServer(key);
 },
 DeleteItemByKeyOnServer: function(key) {
  if(!this.HasKeyField() || key === null) 
   return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.DeleteRow, key]);
 },
 HasKeyField: function() {
  var result = this.keys.length > 0 || this.pageRowCount === 0;
  if(!result)
   alert(this.RequireKeyFieldNameText);
  return result;
 },
 Refresh: function(){
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.CancelEdit();
  this.gridCallBack([ASPxClientGridViewCallbackCommand.Refresh]);
 },
 CopyToClipboard: function() {
  var clipboardHelper = this.GetClipboardHelper();
  if(clipboardHelper)
   clipboardHelper.CopyToClipboard();
 },
 PasteFromClipboard: function() {
  var clipboardHelper = this.GetClipboardHelper();
  if(clipboardHelper)
   clipboardHelper.PasteFromClipboard();
 },
 UpdateSummaries: function() {
  if(this.allowBatchEditing)
   this.gridFuncCallBack([ASPxClientGridViewCallbackCommand.UpdateSummaries], this.ProcessUpdateSummariesInfo.bind(this));
 },
 ProcessUpdateSummariesInfo: function(summaryInfo) {
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   batchEditHelper.UpdateSummaries(summaryInfo);
 },
 ApplyFilter: function(expression){
  expression = expression || "";
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ApplyFilter, expression]);
 },
 ClearFilter: function () {
  this.GetFilterHelper().ClearFilterEditorsState();
  this.ApplyFilter();
 },
 GetAutoFilterEditor: function(column) { 
  var index = this._getColumnIndexByColumnArgs(column);
  if(!ASPx.IsExists(index)) return null;
  return ASPx.GetControlCollection().Get(this.name + "_DXFREditorcol" + index);
 },
 AutoFilterByColumn: function(column, val){
  var index = this._getColumnIndexByColumnArgs(column);
  if(!ASPx.IsExists(index)) return;
  if(!ASPx.IsExists(val)) val = "";  
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ApplyColumnFilter, index, val]);
 },
 ApplyHeaderFilterByColumn: function() {
  var popup = this.GetHeaderFilterPopup();
  popup.Hide();
  var helper = this.GetFilterHelper();
  var column = helper.GetHeaderFilterPopupRelatedColumn();
  if(column) {
   var state = helper.GetHeaderFilterCallbackState(column.index);
   this.gridCallBack([ASPxClientGridViewCallbackCommand.ApplyHeaderColumnFilter, column.index, ASPx.Json.ToJson(state)]);
  }
 },
 SortBy: function(column, sortOrder, reset, sortIndex){
  if(this.RaiseColumnSorting(this._getColumnObjectByArg(column))) return;
  column = this._getColumnIndexByColumnArgs(column);
  if(!ASPx.IsExists(sortIndex)) sortIndex = "";
  if(!ASPx.IsExists(sortOrder)) sortOrder = "";
  if(!ASPx.IsExists(reset)) reset = true;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.Sort, column, sortIndex, sortOrder, reset]);
 },
 GroupBy: function(column, groupIndex, sortOrder){
  var columnObj = this._getColumnObjectByArg(column);
  if(!this.canGroupByColumn(columnObj)) return;
  if(this.RaiseColumnGrouping(columnObj)) return;
  column = this._getColumnIndexByColumnArgs(column);
  if(!ASPx.IsExists(groupIndex)) groupIndex = "";
  if(!ASPx.IsExists(sortOrder)) sortOrder = "ASC";
  this.gridCallBack([ASPxClientGridViewCallbackCommand.Group, column, groupIndex, sortOrder]);
 },
 Ungroup: function(column){
  column = this._getColumnIndexByColumnArgs(column);
  this.gridCallBack([ ASPxClientGridViewCallbackCommand.UnGroup, column ]);
 },
 ExpandAll: function(){
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ExpandAll]);
 },
 CollapseAll: function(){
  this.gridCallBack([ASPxClientGridViewCallbackCommand.CollapseAll]);
 },
 MoveColumn: function(column, columnMoveTo, direction, moveToGroup, moveFromGroup){
  if(!ASPx.IsExists(column)) return;
  if(!ASPx.IsExists(columnMoveTo)) columnMoveTo = -1;
  if(!ASPx.IsExists(moveToGroup)) moveToGroup = false;
  if(!ASPx.IsExists(moveFromGroup)) moveFromGroup = false;
  if(moveToGroup) {
   if(this.RaiseColumnGrouping(this._getColumnObjectByArg(column))) return;
  }
  direction = this.getColumnMoveDirection(direction);
  column = this._getColumnIndexByColumnArgs(column);
  this.MoveColumnCore(column, columnMoveTo, direction, moveToGroup, moveFromGroup);
 },
 MoveColumnCore: function(sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup) {
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ColumnMove, sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup]);
 },
 getColumnMoveDirection: function(direction){
  if(!ASPx.IsExists(direction))
   return ASPxClientGridColumnMovingTargetPosition.Left;
  if(direction === false)
   return ASPxClientGridColumnMovingTargetPosition.Left;
  if(direction === true)
   return ASPxClientGridColumnMovingTargetPosition.Right;
  if(ASPx.IsNumber(direction))
   return direction;
  return ASPxClientGridColumnMovingTargetPosition.Left;
 },
 IsCustomizationWindowVisible: function(){
  var custWindow = this.GetCustomizationWindow();
  return custWindow != null && custWindow.IsVisible();
 },
 ShowCustomizationWindow: function(showAtElement, accessibleFocusElement){
  var custWindow = this.GetCustomizationWindow();
  if(!custWindow) return;
  if(!showAtElement) showAtElement = this.GetMainElement();
  if(this.accessibilityCompliant && accessibleFocusElement)
   custWindow.accessibleFocusElement = accessibleFocusElement;
  custWindow.ShowAtElement(showAtElement);
 },
 HideCustomizationWindow: function(){
  var custWindow = this.GetCustomizationWindow();
  if(custWindow != null) custWindow.Hide();
 },
 ShowCustomizationDialog: function() { },
 ExportTo: function(format) {
  this.gridPostBack([ASPxClientGridViewCallbackCommand.Export, format]);
 },
 GetSelectedFieldValues: function(fieldNames, onCallBack) {
  this.gridFuncCallBack([ASPxClientGridViewCallbackCommand.SelFieldValues, fieldNames], onCallBack);
 },
 GetSelectedKeysOnPage: function() {
  var keys = [];
  for(var i = 0; i < this.pageRowCount; i++) {
   if(this._isRowSelected(this.visibleStartIndex + i))
    keys.push(this.keys[i]);
  }
  return keys; 
 },
 GetItemValues: function(visibleIndex, fieldNames, onCallBack) {
  this.gridFuncCallBack([ASPxClientGridViewCallbackCommand.RowValues, visibleIndex, fieldNames], onCallBack);
 },
 GetPageItemValues: function(fieldNames, onCallBack) {
  this.gridFuncCallBack([ASPxClientGridViewCallbackCommand.PageRowValues, fieldNames], onCallBack);
 },
 GetVisibleItemsOnPage: function() {
  var batchEditHelper = this.GetBatchEditHelper();
  if(batchEditHelper)
   return batchEditHelper.GetVisibleRecordsOnPageCount();
  return this.pageRowCount;
 },
 GetTopVisibleIndex: function() {
  return this.visibleStartIndex;
 },
 GetColumnsCount: function() {
  return this.GetColumnCount();
 },
 GetColumnCount: function() {
  return this._getColumnCount();
 },
 GetColumn: function(index) {
  return this._getColumn(index);
 },
 GetColumnById: function(id) {
  return this._getColumnById(id);
 },
 GetColumnByField: function(fieldName) {
  return this._getColumnByField(fieldName);
 },
 GetEditor: function(column) {
  var columnObject = this._getColumnObjectByArg(column);
  return columnObject != null ? this.GetEditorByColumnIndex(columnObject.index) : null;
 },
 FocusEditor: function(column) {
  var editor = this.GetEditor(column);
  if(editor && editor.SetFocus) {
   editor.SetFocus();  
  }
 },
 GetEditValue: function(column) {
  var editor = this.GetEditor(column);
  return editor != null && editor.enabled ? editor.GetValue() : null;
 },
 SetEditValue: function(column, value) {
  var editor = this.GetEditor(column);
  if(editor != null && editor.enabled)
   editor.SetValue(value);
 },
 ShowFilterControl: function() {
  this.PreventCallbackAnimation();
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ShowFilterControl]);
 },
 CloseFilterControl: function() {
  this.PreventCallbackAnimation();
  this.HideFilterControlPopup();
  this.gridCallBack([ASPxClientGridViewCallbackCommand.CloseFilterControl]);
 },
 HideFilterControlPopup: function() {
  var popup = this.GetFilterControlPopup();
  if(popup) {
   popup.Hide();
   if(this.accessibilityCompliant) {
    var needToStoreFocusTreeLine = !this.accessibilityFocusTreeLine && ASPx.GetIsParent(this.GetMainElement(), ASPx.GetActiveElement());
    if(needToStoreFocusTreeLine)
     this.accessibilityFocusTreeLine = ASPx.RestoreFocusHelper.getFocusTreeLine(this);
   }
  }
 },
 ApplyFilterControl: function() {
  this.PreventCallbackAnimation();
  var fc = this.GetFilterControl();
  if(fc == null) return;
  if(!this.callBacksEnabled)
   this.HideFilterControlPopup();
  if(!fc.isApplied)
   fc.Apply(this);
 },
 SetFilterEnabled: function(isFilterEnabled) {
  this.gridCallBack([ASPxClientGridViewCallbackCommand.SetFilterEnabled, isFilterEnabled]);
 },
 GetVerticalScrollPosition: function() { return 0; },
 SetVerticalScrollPosition: function(value) { },
 RaiseSelectionChangedOutOfServer: function() {
  this.RaiseSelectionChanged(-1, false, false, true);
 },
 RaiseSelectionChanged: function(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer) {
  if(!this.SelectionChanged.IsEmpty()){
   var args = this.CreateSelectionEventArgs(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer);
   this.SelectionChanged.FireEvent(this, args);
   if(args.processOnServer) {
    this.gridCallBack([ASPxClientGridViewCallbackCommand.Selection]);
   }
  }
  return false; 
 },
 CreateSelectionEventArgs: function(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer){
  return null;
 },
 RaiseFocusedItemChangedOutOfServer: function() { 
  this.RaiseFocusedItemChanged(true); 
 },
 RaiseFocusedItemChanged: function(isChangedOnServer) { return false; },
 RaiseItemFocusing: function(visibleIndex, htmlEvent) { return false; },
 RaiseColumnSorting: function(column) {
  if(!this.ColumnSorting.IsEmpty()){
   var args = this.CreateColumnCancelEventArgs(column);
   this.ColumnSorting.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 CreateColumnCancelEventArgs: function(column){
  return null;
 },
 RaiseColumnGrouping: function(column) {
  if(!this.ColumnGrouping.IsEmpty()){
   var args = this.CreateColumnCancelEventArgs(column);
   this.ColumnGrouping.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseItemClick: function(visibleIndex, htmlEvent) {
  return false; 
 },
 RaiseItemDblClick: function(visibleIndex, htmlEvent) {
  return false; 
 },
 RaiseCustomizationWindowCloseUp: function() {
  if(!this.CustomizationWindowCloseUp.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.CustomizationWindowCloseUp.FireEvent(this, args);
  }
  return false; 
 },
 RaiseColumnMoving: function(targets) {
  return false;
 },
 RaiseToolbarItemClick: function(toolbarInfo, item) {
  if(this.ToolbarItemClick.IsEmpty())
   return false;
  var args = new ASPxClientGridToolbarItemClickEventArgs(toolbarInfo.index, toolbarInfo.name, item, false);
  this.ToolbarItemClick.FireEvent(this, args);
  if(!args.handled && args.processOnServer) {
   this.GetToolbarHelper().ProcessCustomToolbarItemClickOnServer(args.usePostBack);
   return true;
  }
  return args.handled;
 },
 RaiseKeyDown: function(evt) {
  if(this.KeyDown.IsEmpty())
   return false;
  var args = new ASPxClientGridKeyboardEventArgs(evt);
  this.KeyDown.FireEvent(this, args);
  return args.handled;
 },
 RaiseKeyPress: function(evt) {
  if(this.KeyPress.IsEmpty())
   return false;
  var args = new ASPxClientGridKeyboardEventArgs(evt);
  this.KeyPress.FireEvent(this, args);
  return args.handled;
 },
 RaiseKeyUp: function(evt) {
  if(this.KeyUp.IsEmpty())
   return false;
  var args = new ASPxClientGridKeyboardEventArgs(evt);
  this.KeyUp.FireEvent(this, args);
  return args.handled;
 },
 RaiseBatchEditSummaryDisplayText: function(summaryInfo, text, groupRowVisibleIndex) {
  if(!this.BatchEditSummaryDisplayText.IsEmpty()) {
   var args = new ASPxClientGridBatchEditSummaryDisplayTextEventArgs(summaryInfo, text, groupRowVisibleIndex);
   this.BatchEditSummaryDisplayText.FireEvent(this, args);
   return args.displayText;
  }
  return text;
 },
 RaiseBatchEditStartEditing: function(visibleIndex, column, rowValues) { return null; },
 RaiseBatchEditEndEditing: function(visibleIndex, focusedColumn, rowValues) { return null; },
 RaiseBatchEditItemChangesCanceling: function(visibleIndex, rowValues) { return null; },
 RaiseBatchEditItemValidating: function(visibleIndex, validationInfo) { return null; },
 RaiseBatchEditConfirmShowing: function(requestTriggerID) { return false; },
 RaiseBatchEditTemplateCellFocused: function(columnIndex) { return false; },
 RaiseBatchEditChangesSaving: function(valuesInfo) { return false; },
 RaiseBatchEditChangesCanceling: function(valuesInfo) { return false; },
 RaiseBatchEditItemInserting: function(visibleIndex) { return false; },
 RaiseBatchEditItemDeleting: function(visibleIndex, itemValues) { return false; },
 RaiseBatchEditItemRecovering: function(visibleIndex, itemValues) { return false; },
 RaiseClipboardCellPasting: function(info, oldValueInfo, newValueInfo) {
  var cellInfo = this.CreateUserCellInfo(this.ConvertKeyToVisibleIndex(info.recordKey), this.GetColumn(info.columnIndex), info.recordKey);
  var args = this.CreateClipboardCellPastingArgs(cellInfo, oldValueInfo, newValueInfo);
  if(!this.ClipboardCellPasting.IsEmpty())
   this.ClipboardCellPasting.FireEvent(this, args);
  return args;
 },
 CreateClipboardCellPastingArgs: function(cellInfo, originalValueInfo, valueInfo) { return null; },
 RaiseCellSelectionChanging: function(info, isSelected) {
  if(!this.CellSelectionChanging.IsEmpty()) {
   var key = info.recordKey;
   var cellInfo = this.CreateUserCellInfo(this.ConvertKeyToVisibleIndex(key), this.GetColumn(info.columnIndex), key);
   var newSelectionState = isSelected ? ASPxClientGridSelectionState.Selected : ASPxClientGridSelectionState.Unselected;
   var args = this.CreateCellSelectionChangingArgs(cellInfo, newSelectionState);
   this.CellSelectionChanging.FireEvent(this, args);
   return args.cancel;
  }
 },
 CreateCellSelectionChangingArgs: function(cellInfo, newSelectionState) { return null; },
 RaiseFocusedCellChanging: function(info) {
  if(!this.FocusedCellChanging.IsEmpty()){   
   var key = info.recordKey;
   var cellInfo = this.CreateUserCellInfo(this.ConvertKeyToVisibleIndex(key), this.GetColumn(info.columnIndex), key);
   var args = this.CreateFocusedCellChangingArgs(cellInfo);
   this.FocusedCellChanging.FireEvent(this, args);
   return args.cancel;
  }
  return false;   
 },
 CreateUserCellInfo: function(visibleIndex, column, key) { return null; },
 CreateFocusedCellChangingArgs: function(cellInfo) { return null; },
 RaiseInternalCheckBoxClick: function(visibleIndex) {
  if(!this.InternalCheckBoxClick.IsEmpty()){
   var args = {"visibleIndex": visibleIndex, cancel: false};
   this.InternalCheckBoxClick.FireEvent(this, args);
   return args.cancel;
  }
  return false;
 },
 UA_AddNew: function() {
  this.AddNewItem();
 },
 UA_StartEdit: function(visibleIndex) {
  this.StartEditItem(visibleIndex);
 },
 UA_Delete: function(visibleIndex) {
  this.DeleteGridItem(visibleIndex);
 },
 UA_Recover: function(visibleIndex) {
  this.RecoverItem(visibleIndex);
 },
 UA_UpdateEdit: function() {
  this.UpdateEdit();
 },
 UA_CancelEdit: function(visibleIndex) {
  this.CancelEdit(visibleIndex);
 },
 UA_CustomButton: function(id, visibleIndex) {
  this.CommandCustomButton(id, visibleIndex);
 },
 UA_Select: function(visibleIndex) {
  if(!this.lookupBehavior || this.allowSelectByItemClick){
   var selected = this.allowSelectSingleRowOnly || !this._isRowSelected(visibleIndex);
   this.SelectItem(visibleIndex, selected);
  }
 },
 UA_ClearFilter: function() {
  this.ClearFilter();
 },
 UA_ApplySearchFilter: function() {
  this.ApplySearchFilterFromEditor();
 },
 UA_ClearSearchFilter: function() {
  var editor = this.GetSearchEditor();
  if(editor)
   editor.SetValue(null);
  this.ApplySearchFilterFromEditor();
 },
 UA_UpdateSummaries: function() {
  this.UpdateSummaries();
 },
 ApplySearchFilterFromEditor: function() {
  this.GetFilterHelper().ApplySearchFilterFromEditor(this.GetSearchEditor());
 },
 ChangeCellInitialClass: function(cell, className, add) { this.GetStyleHelper().ChangeCellInitialClass(cell, className, add); },
 OnDispose: function() { 
  if(this.filterHelper)
   this.filterHelper.OnDispose();
  ASPxClientControl.prototype.OnDispose.call(this);
 },
 GetEditFormLayout: function() {
  if(this.GetPopupEditForm())
   return ASPx.GetControlCollection().Get(this.name + "_DXPEForm" + this.GetEditFormLayoutIDPostfix());
  return ASPx.GetControlCollection().Get(this.name + this.GetEditFormLayoutIDPostfix());
 },
 GetEditFormLayoutIDPostfix: function() { return ""; },
 GetEditFormLayoutItemByColumn: function(column) {
  var editFormLayout = this.GetEditFormLayout();
  var columnObject = this._getColumnObjectByArg(column);
  if(!editFormLayout || !columnObject)
   return null;
  return this.getEditFormLayoutItemByColumnCore(editFormLayout, columnObject);
 },
 getEditFormLayoutItemByColumnCore: function(editFormLayout, columnObject) {
  var findByColumnNamePredicate = function(item) {
   if(!item.columnProperties)
    return false;
   return columnObject.name && columnObject.name == item.columnProperties.name;
  };
  var findByColumnFieldNamePredicate = function(item) {
   if(!item.columnProperties)
    return false;
   return columnObject.fieldName && columnObject.fieldName == item.columnProperties.fieldName;
  };
  return editFormLayout.getItemByPredicate(findByColumnNamePredicate) || editFormLayout.getItemByPredicate(findByColumnFieldNamePredicate);
 },
 GetEditFormLayoutItemOrGroup: function(name) {
  var editFormLayout = this.GetEditFormLayout();
  return editFormLayout ? editFormLayout.GetItemByName(name) : null;
 }
});
ASPxClientGridBase.Cast = ASPxClientControl.Cast;
var GridCallbackHelper = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
  this.funcCallbackInfoList = [ ];
  this.postbackRequestCount = 0;
 },
 GetAllowDelete: function() { return this.grid.allowDelete; },
 GetAllowEdit: function() { return this.grid.allowEdit; },
 GetAllowInsert: function() { return this.grid.allowInsert; },
 CanSendCallback: function() { return this.grid.callBack && this.grid.callBacksEnabled; },
 GetEditorValues: function() { return this.grid.GetEditorValues(); },
 GetSelectionState: function() { return this.grid.GetSelectedState(); },
 GetKeyValues: function() { return this.grid.GetKeyValues(); },
 GetFocusedRowState: function() { return this.grid.stateObject.focusedRow; },
 GetToolbarState: function() { return this.grid.GetToolbarHelper().GetCallbackState(); },
 GetRequestCount: function() { return this.grid.requestCount; },
 ResetUserChangedSelection: function() { 
  this.grid.userChangedSelection = false; 
 },
 GetTotalRequestCount: function() { return this.GetRequestCount() + this.postbackRequestCount; },
 CreateGridCallback: function(command, args, callbackHandler) {
  this.grid.CreateCallback(args, command, callbackHandler);
 },
 CreateGridPostback: function(args, preventConvertToUpdatePanelCallback) {
  this.grid.SendPostBack(args, preventConvertToUpdatePanelCallback);
 },
 OnBeforeCallbackOrPostBack: function() {
  this.grid.OnBeforeCallbackOrPostBack(); 
 },
 OnBeforeCallback: function(command) { this.grid.OnBeforeCallback(command); },
 SendRequest: function(args, callbackHandler) {
  var command = this.GetCorrectedCommand(args);
  if(!this.ValidateCommand(command))
   return;
  this.OnBeforeCallbackOrPostBack();
  if(this.CanSendCallback())
   this.SendCallback(command, args, callbackHandler);
  else
   this.SendPostback(args);
 },
 SendCallback: function(command, args, callbackHandler) {
  this.OnBeforeCallback(command);
  var callbackState = this.GetGridCallbackState();
  this.ResetUserChangedSelection();
  this.SendCallbackCore(command, args, callbackState, callbackHandler);
 },
 SendFuncCallback: function(args, onCallBack) {
  var callbackState = this.GetGridCallbackState();
  callbackState.push([ "FB", this.GetFuncCallBackIndex(onCallBack) ]);
  this.SendCallbackCore("FUNCTION", args, callbackState);
 },
 SendCallbackCore: function(command, commandArgs, callbackState, callbackHandler) {
  callbackState.push([ "GB", this.SerializeCallbackArgs(commandArgs) ]);
  this.CreateGridCallback(command, this.FormatCallbackState(callbackState), callbackHandler);
 },
 SendPostback: function(args) {
  this.postbackRequestCount++;
  this.CreateGridPostback(this.SerializeCallbackArgs(args), this.IsExportPostback(args));
 },
 ValidateCommand: function(command) {
  if(command === ASPxClientGridViewCallbackCommand.DeleteRow && !this.GetAllowDelete())
   return false;
  if(command === ASPxClientGridViewCallbackCommand.StartEdit && !this.GetAllowEdit())
   return false;
  if(command === ASPxClientGridViewCallbackCommand.AddNewRow && !this.GetAllowInsert())
   return false;
  return true;
 },
 GetCorrectedCommand: function(args) {
  if(args.length === 0) return "";
  var command = args[0];
  if(args.length > 1 && command === ASPxClientGridViewCallbackCommand.ColumnMove) {
   if(args[args.length - 1])
    command = ASPxClientGridViewCallbackCommand.UnGroup;
   if(args[args.length - 2])
    command = ASPxClientGridViewCallbackCommand.Group;
  }
  return command;
 },
 IsExportPostback: function(args) {
  if(!ASPx.Ident.IsArray(args) || args.length === 0)
   return false;
  return args[0] == ASPxClientGridViewCallbackCommand.Export || args[1] == ASPxClientGridViewCallbackCommand.Export;
 },
 GetGridCallbackState: function() {
  return [
   [ "EV", this.GetEditorValues() ],
   [ "SR", this.GetSelectionState() ],
   [ "KV", this.GetKeyValues() ],
   [ "FR", this.GetFocusedRowState() ],
   [ "CT", this.GetToolbarState() ]
  ];
 },
 GetFuncCallBackIndex: function(onCallBack) {
  var info = { date: new Date(), callback: onCallBack };
  for(var i = 0; i < this.funcCallbackInfoList.length; i ++) {
   if(this.funcCallbackInfoList[i] === null) {
    this.funcCallbackInfoList[i] = info;
    return i;
   }
  }
  this.funcCallbackInfoList.push(info);
  return this.funcCallbackInfoList.length - 1;
 },
 GetFuncCallBackInfo: function(index) {
  if(index < 0 || index >= this.funcCallbackInfoList.length) 
   return null;
  var result = this.funcCallbackInfoList[index];
  this.funcCallbackInfoList[index] = null;
  return result;
 },
 HasWaitedFuncCallbacks: function() {
  return this.funcCallbackInfoList.filter(function(i) { return i !== null; }).length > 0;
 },
 HasWaitedFuncCallbacksFromInterval: function(timeout) {
  var date = new Date();
  for(var i = 0; i < this.funcCallbackInfoList.length; i++) {
   var info = this.funcCallbackInfoList[i];
   if(info && (date - info.date) < timeout)
    return true;
  }
  return false;
 },
 FormatCallbackState: function(callbackState) {
  var result = [ ];
  for(var i = 0; i < callbackState.length; i++) {
   var stateItem = callbackState[i];
   if(!stateItem || stateItem.length !== 2)
    continue;
   var stateKey = stateItem[0];
   var stateValue = stateItem[1];
   if(ASPx.IsExists(stateValue) && stateValue !== "") {
    var stateValueString = stateValue.toString();
    result.push(stateKey);
    result.push("|");
    result.push(stateValueString.length);
    result.push(";");
    result.push(stateValueString);
    result.push(";");
   }
  }
  return result.join("");
 },
 SerializeCallbackArgs: function(args) {
  if(!ASPx.Ident.IsArray(args) || args.length === 0)
   return "";
  var result = [ ];
  for(var i = 0; i < args.length; i++) {
   var item = args[i].toString();
   result.push(item.length);
   result.push("|");
   result.push(item);
  }
  return result.join("");
 }
});
var GridStyleHelper = ASPx.CreateClass(ASPx.GridStyleHelperBase, {
 SelectedItemKey: "sel",
 FocusedItemKey: "fi",
 constructor: function(grid) {
  this.grid = grid;
 },
 GetStyles: function() { return this.grid.styleInfo; },
 GetSelectedItemStyle: function() { return this.GetStyleInfo(this.SelectedItemKey); },
 GetFocusedItemStyle: function() { return this.GetStyleInfo(this.FocusedItemKey); },
 IsSelectedItemStyle: function(style) { return this.CheckStyleInfoByKey(style, this.SelectedItemKey); },
 IsFocusedItemStyle: function(style) { return this.CheckStyleInfoByKey(style, this.FocusedItemKey); },
});
var ASPxClientGridColumnBase = ASPx.CreateClass(null, {
 constructor: function(prop) {
  this.index =   ASPx.IsExists(prop[0]) ? prop[0] : -1;
  this.visible =    ASPx.IsExists(prop[1]) ?  !!prop[1] : true;
  this.name =    ASPx.IsExists(prop[2]) ? prop[2] : "";
  this.fieldName =  ASPx.IsExists(prop[3]) ? prop[3] : "";
  this.allowSort =  ASPx.IsExists(prop[4]) ?  !!prop[4] : true;
  this.HFMode =     ASPx.IsExists(prop[5]) ? prop[5] : 1;
  this.sortIndex =  ASPx.IsExists(prop[6]) ? prop[6] : -1;
  this.sortOrder =  ASPx.IsExists(prop[7]) ? prop[7] : ASPx.GridSortOrder.None;
  this.id = this.name;
 }
});
var GridLayoutHelper = ASPx.CreateClass(null, { 
 constructor: function(grid) {
  this.grid = grid;
 },
 GetDataItemVisibleIndices: function(includeDeleted) { return this.grid.GetDataItemVisibleIndices(includeDeleted); },
 Invalidate: function() { 
 },
});
var GridViewDragHelper = ASPx.CreateClass(ASPx.GridDragHelperBase, {
 constructor: function(grid) {
  this.grid = grid;
  this.targets = null;
  this.constructor.prototype.constructor.call(this);
 },
 CreateDrag: function(e, element, canDrag) {
  var drag = new ASPx.DragHelper(e, element, true);
  drag.centerClone = true;
  drag.canDrag = canDrag;  
  drag.grid = this.grid;
  drag.ctrl = e.ctrlKey;
  drag.shift = e.shiftKey;
  drag.onDragDivCreating = this.OnDragDivCreating;
  drag.onDoClick = this.OnDoClick;
  drag.onCloneCreating = this.OnCloneCreating;
  drag.onEndDrag = this.OnEndDrag;
  drag.onCancelDrag = this.OnCancelDrag;
  this.OnDragCreated(true);
  return drag;
 },
 GetActiveTargets: function() { 
  if(this.targets && this.targets.list)
   return this.targets.list;
  return [ ];
 },
 GetScrollHelper: function() { return this.grid.GetScrollHelper(); },
 GetCustomizationWindowElement: function() { return this.grid.GetCustomizationWindowElement(); },
 GetHeaderLeaf: function(columnIndex, isLeft){ return this.grid.GetHeaderMatrix().GetLeaf(columnIndex, isLeft, false); },
 GetHeaderLevel: function(columnIndex){ return this.grid.GetHeaderMatrix().GetColumnLevel(columnIndex); },
 NeedScrollOnDrag: function(isHorzDrag) { 
  var hasFixedColumns = this.grid.GetFixedColumnsHelper && this.grid.GetFixedColumnsHelper();
  return ASPx.GridDragHelperBase.prototype.NeedScrollOnDrag.call(this, isHorzDrag) || hasFixedColumns; 
 },
 PrepareTargetHeightFunc: function() {
  GridViewDragHelper.Target_GetElementHeight = null;
  if(this.grid.allowChangeColumnHierarchy)
   return;
  var headerRowCount = this.grid.GetHeaderMatrix().GetRowCount();
  if(headerRowCount > 0) {
   var row = this.grid.GetHeaderRow(headerRowCount - 1);
   var headerBottom = ASPx.GetAbsoluteY(row) + row.offsetHeight;
   GridViewDragHelper.Target_GetElementHeight = function() {
    return headerBottom - this.absoluteY;
   };
  }
 },
 CreateTargets: function(drag, e) {
  if(!drag.canDrag) return;
  var grid = this.grid;
  this.PrepareTargetHeightFunc();
  var targets = new ASPx.CursorTargets(grid);
  targets.obj = drag.obj;
  targets.onTargetCreated = this.OnTargetCreated;
  targets.onTargetChanging = this.OnTargetChanging;
  targets.onTargetChanged = this.OnTargetChanged;
  targets.onTargetAllowed = this.OnHeaderTargetAllowed.aspxBind(this);
  this.targets = targets;
  var scrollLeft = null, scrollRight;
  var scrollHelper = grid.GetScrollHelper();
  var scrollableControl = scrollHelper && scrollHelper.GetHorzScrollableControl();
  if(scrollableControl) {
   scrollLeft = ASPx.GetAbsoluteX(scrollableControl);
   scrollRight = scrollLeft + scrollableControl.offsetWidth;
  }
  var sourceColumn = grid.getColumnObject(drag.obj.id);
  var win = grid.GetCustomizationWindow();
  if(win && !sourceColumn.inCustWindow)
   this.AddDragDropTarget(targets, win.GetWindowClientTable(-1));
  for(var i = 0; i < grid.columns.length; i++) {
   var column = grid.columns[i];
   for(var grouped = 0; grouped <= 1; grouped++) {
    var targetElement = grid.GetHeader(column.index, !!grouped);
    if(!targetElement)
     continue;
    if(this.IsValidColumnDragDropTarget(drag.obj, targetElement, sourceColumn, column))
     this.AddDragDropTarget(targets, targetElement);  
   }
  }
  this.AddAdaptivePanelTarget(targets, grid.GetAdaptiveHeaderPanel());
  this.AddAdaptivePanelTarget(targets, grid.GetAdaptiveGroupPanel());
  this.AddDragDropTarget(targets, grid.GetGroupPanel());
  this.AddDragDropTarget(targets, ASPx.GetElementById(grid.name + this.grid.EmptyHeaderSuffix));
 },
 IsValidColumnDragDropTarget: function(sourceElement, targetElement, sourceColumn, targetColumn) {
  if(sourceColumn == targetColumn)
   return false;
  if(this.grid.allowChangeColumnHierarchy)
   return true;
  if(sourceColumn.parentIndex == targetColumn.parentIndex)
   return true;
  if(sourceColumn.parentIndex == targetColumn.index) {
   return (sourceColumn.inCustWindow || this.IsGroupingTarget(sourceElement))
    && this.grid.GetHeaderMatrix().IsLeaf(targetColumn.index);
  }
  if(this.IsParentColumn(sourceColumn.index, targetColumn.index))
   return (sourceColumn.inCustWindow || this.IsGroupingTarget(sourceElement));
  if(this.IsGroupingTarget(targetElement))
   return true;
  if(this.IsValidAdaptiveTarget(sourceElement, targetElement, sourceColumn, targetColumn))
   return true;
  return false;
 },
 AddAdaptivePanelTarget: function(targets, panel) {
  if(!panel) return;
  this.AppendAdaptivePanelDragAreas(targets, panel);
  this.AddDragDropTarget(targets, panel);
 },
 AppendAdaptivePanelDragAreas: function(targets, panel) {
  panel.dragAreas = [ ];
  var headers = this.GetAdaptivePanelHeaders(panel);
  if(headers.length === 0) 
   return;
  var rows = [ ];
  var row = [ headers[0] ];
  rows.push(row);
  for(var i = 0; i < headers.length - 1; i++) {
   var currentHeader = headers[i];
   var nextHeader = headers[i + 1];
   if(ASPx.GetAbsoluteY(currentHeader) !== ASPx.GetAbsoluteY(nextHeader)) {
    row = [ ];
    rows.push(row);
   }
   row.push(nextHeader);
  }
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   this.CreateDragArea(panel, row[0], targets, true);
   this.CreateDragArea(panel, row[row.length - 1], targets,  false);
  }
 },
 GetAdaptivePanelHeaders: function(panel) {
  return ASPx.GetNodesByPartialClassName(panel, ASPx.GridViewConsts.HeaderCellCssClass);
 },
 CreateDragArea: function(panel, target, targets, isLeft) {
  if(!this.ContainsTarget(targets, target)) 
   return; 
  var targetTop = ASPx.GetAbsolutePositionY(target);
  var area = { 
   target: target,
   isLeft: isLeft,
   top: targetTop,
   bottom: targetTop + target.offsetHeight,
   left: isLeft ? ASPx.GetAbsolutePositionX(panel) : ASPx.GetAbsolutePositionX(target) + target.offsetWidth,
   right: isLeft ? ASPx.GetAbsolutePositionX(target) :  ASPx.GetAbsolutePositionX(panel) + panel.offsetWidth
  };
  panel.dragAreas.push(area);
 },
 ContainsTarget: function(targets, target) {
  for(var i = 0; i < targets.list.length; i++) {
   if(targets.list[i].element == target)
    return true;
  }
  return false;
 },
 IsValidAdaptiveTarget: function(sourceElement, targetElement, sourceColumn, targetColumn) {
  this.EnsureAdaptiveTargetInfo(sourceElement, targetElement, sourceColumn, targetColumn);
  return !!targetElement.adaptiveInfo;
 },
 EnsureAdaptiveTargetInfo: function(sourceElement, targetElement, sourceColumn, targetColumn) {
  if(!this.IsAdaptiveHeaderTarget(targetElement))
   return;
  var sourceLevel = this.GetHeaderLevel(sourceColumn.index);
  var targetLevel = this.GetHeaderLevel(targetColumn.index);
  targetElement.adaptiveInfo = null;
  if(targetLevel < 0 || sourceLevel >= targetLevel)
   return;
  var brother = this.FindColumnBrother(sourceColumn, targetColumn);
  if(!brother) 
   return;
  var leftLeaf = this.GetHeaderLeaf(brother.index, true);
  var rightLeaf = this.GetHeaderLeaf(brother.index, false);  
  if(targetColumn.index === leftLeaf || targetColumn.index === rightLeaf)
   targetElement.adaptiveInfo = { brotherIndex : brother.index, brotherHasOnlyOneLeaf: leftLeaf == rightLeaf, isLeftLeaf: targetColumn.index == leftLeaf };
 },
 FindColumnBrother: function(sourceColumn, targetColumn) {
  while(targetColumn && targetColumn.parentIndex !== sourceColumn.parentIndex)
   targetColumn = this.grid.GetColumn(targetColumn.parentIndex);
  return targetColumn;
 },
 AddDragDropTarget: function(targets, element) {
  if(element)
   targets.addElement(element);
 },
 IsAdaptiveHeaderPanelVisible: function() { return ASPx.IsElementDisplayed(this.grid.GetAdaptiveHeaderPanel()); },
 IsAdaptiveGroupPanelVisible: function() { return ASPx.IsElementDisplayed(this.grid.GetAdaptiveGroupPanel()); },
 IsDataHeaderTarget: function(element) { return element && element.id.indexOf(this.grid.name + "_col") == 0; },
 IsAdaptiveHeaderTarget: function(element) { return this.IsAdaptiveHeaderPanelVisible() && this.IsDataHeaderTarget(element) && element.adaptiveMoved; },
 IsAdaptivePanelTarget: function(element) { return element && (element == this.grid.GetAdaptiveHeaderPanel() || element == this.grid.GetAdaptiveGroupPanel()); },
 IsAdaptiveGroupHeaderTarget: function(element) { return this.IsAdaptiveGroupPanelVisible() && this.IsGroupHeaderTarget(element) && element.adaptiveMoved; },
 IsGroupHeaderTarget: function(element) {
  if(!element || !element.id)
   return false;
  return element.id.indexOf(this.grid.name + "_groupcol") == 0;
 },
 IsGroupingTarget: function(element) { 
  return element == this.grid.GetGroupPanel() || this.IsGroupHeaderTarget(element) || element ==  this.grid.GetAdaptiveGroupPanel();
 },
 IsCustWindowTarget: function(element) {
  var win = this.grid.GetCustomizationWindow();
  return win && element == win.GetWindowClientTable(-1); 
 },
 AllowVerticalTargetTags: function(element){
  return this.grid.allowChangeColumnHierarchy && !this.IsGroupingTarget(element) && !this.IsCustWindowTarget(element);
 },
 OnDragDivCreating: function(drag, dragDiv) {
  var rootTable = drag.grid.GetMainElement();
  if(!dragDiv || !rootTable) return;
  dragDiv.className = rootTable.className;
  dragDiv.style.cssText = rootTable.style.cssText;
 },
 OnDoClick: function(drag) {
  window.setTimeout(function() {
   var grid = drag.grid;
   var contextMenuHelper = grid.GetContextMenuHelper && grid.GetContextMenuHelper(); 
   if(contextMenuHelper && contextMenuHelper.contextMenuActivating) {
    contextMenuHelper.contextMenuActivating = false;
    return;
   }
   if(!grid.canSortByColumn(drag.obj) || grid.InRegularCallback()) 
    return;
   grid.SortBy(grid.getColumnIndex(drag.obj.id), drag.ctrl ? "NONE" : "", !drag.shift && !drag.ctrl);
  }, 0);
 },
 OnCancelDrag: function(drag) {
  drag.grid.dragHelper.DisplayTargetImages(false);
  drag.grid.dragHelper.CancelDrag();
 },
 OnEndDrag: function(drag) {
  if(!drag.targetElement)
   return;
  var grid = drag.grid;
  var sourceElement = drag.obj;
  var targetElement = drag.targetElement;
  var sourceIndex = grid.getColumnIndex(sourceElement.id);
  var targetIndex =  grid.getColumnIndex(targetElement.id);
  var direction = drag.targetTag;
  if(grid.IsEmptyHeaderID(targetElement.id) || targetElement == grid.GetAdaptiveHeaderPanel())
   targetIndex = 0;
  if(grid.dragHelper.IsAdaptiveHeaderTarget(targetElement) && targetElement.adaptiveInfo) {
   targetIndex = targetElement.adaptiveInfo.brotherIndex;
   var isLeft = !targetElement.adaptiveInfo.brotherHasOnlyOneLeaf ? targetElement.adaptiveInfo.isLeftLeaf : isLeft;
   direction = isLeft ? ASPx.CursorTargetTag.Left : ASPx.CursorTargetTag.Right;
  }
  if(grid.rtl && direction < 2)
   direction = direction == ASPx.CursorTargetTag.Left ? ASPx.CursorTargetTag.Right : ASPx.CursorTargetTag.Left;
  grid.MoveColumn(
   sourceIndex,
   targetIndex,
   direction,
   grid.dragHelper.IsGroupingTarget(targetElement),
   grid.dragHelper.IsGroupingTarget(sourceElement)
  );
 },
 OnCloneCreating: function(clone) {
  var table = document.createElement("table");
  table.cellSpacing = 0;
  if(this.obj.offsetWidth > 0)
   table.style.width = Math.min(200, this.obj.offsetWidth) + "px";
  if(this.obj.offsetHeight > 0)
   table.style.height = this.obj.offsetHeight + "px";
  var row = table.insertRow(-1);
  clone.style.borderLeftWidth = "";
  clone.style.borderTopWidth = "";
  clone.style.borderRightWidth = "";
  row.appendChild(clone);
  table.style.opacity = 0.80;
  table.style.filter = "alpha(opacity=80)"; 
  if(ASPx.IsElementRightToLeft(this.obj))
   table.dir = "rtl";
  return table;
 },
 OnTargetCreated: function(targets, targetObj) {
  var f = GridViewDragHelper.Target_GetElementHeight;
  var h = targets.control.dragHelper;
  var el = targetObj.element;
  if(f && !h.IsCustWindowTarget(el) && !h.IsGroupingTarget(el) && !h.IsAdaptiveHeaderTarget(el) && !h.IsAdaptivePanelTarget(el))
   targetObj.GetElementHeight = f;
 },
 OnTargetChanging: function(targets) {
  if(!targets.targetElement)
   return;
  var grid = targets.control;
  var allowVerticalTags = grid.dragHelper.AllowVerticalTargetTags(targets.targetElement);
  targets.refreshTargetTag(allowVerticalTags);
  if(allowVerticalTags)
   grid.dragHelper.CorrectTargetTagOnMovingColumnFromCustWindow(targets);
  var grouping = false;
  if(targets.targetElement == grid.GetGroupPanel() || targets.targetElement == grid.GetAdaptiveGroupPanel()) {
   targets.targetTag = ASPx.CursorTargetTag.Left;
   grouping = true;
  }  
  if(grid.dragHelper.IsGroupHeaderTarget(targets.targetElement)) {
   grouping = true;
  }
  var column = grid.getColumnObject(targets.obj.id);
  if(grouping && !grid.canGroupByColumn(column))
   targets.targetElement = null;
  if(targets.targetElement == grid.GetCustomizationWindowElement() && !grid.canHideColumn(column))
   targets.targetElement = null;
  if(grid.dragHelper.IsAdaptivePanelTarget(targets.targetElement)) {
   var info = grid.dragHelper.GetAdaptivePanelTargetInfo(targets, targets.targetElement);
   targets.targetTag = info.isLeftSide ? ASPx.CursorTargetTag.Left : ASPx.CursorTargetTag.Right;
   targets.targetElement = info.targetElement;
   targets.skipNeighbor = true;
  }
  if(targets.targetElement)
   grid.RaiseColumnMoving(targets);
 },
 CorrectTargetTagOnMovingColumnFromCustWindow: function(targets){
  if(!ASPx.currentDragHelper || !ASPx.currentDragHelper.obj || !targets.targetElement)
   return;
  var grid = targets.control;
  var sourceColumn = grid.getColumnObject(ASPx.currentDragHelper.obj.id);
  if(!sourceColumn || !sourceColumn.inCustWindow || !grid.GetColumnHelper().HasColumnChildren(sourceColumn.index))
   return;
  var sourceColumn = grid.getColumnObject(ASPx.currentDragHelper.obj.id);
  var targetColumn = grid.getColumnObject(targets.targetElement.id);
  if(targets.targetTag == ASPx.CursorTargetTag.Top || targets.targetTag == ASPx.CursorTargetTag.Bottom && grid.GetColumnHelper().HasColumnChildren(targetColumn.index))
   targets.refreshTargetTag(false);
 },
 GetAdaptivePanelTargetInfo: function(targets, panel) {
  var x = targets.x;
  var y = targets.y;
  for(var i = 0; i < panel.dragAreas.length; i++) {
   var dragArea = panel.dragAreas[i];
   if(x >= dragArea.left && x <= dragArea.right && y >= dragArea.top && y <= dragArea.bottom)
    return { targetElement: dragArea.target, isLeftSide: dragArea.isLeft };
  }
  return { targetElement: panel.children.length == 0 ? panel : null, isLeftSide: true };
 },
 OnTargetChanged: function(targets) {
  if(ASPx.currentDragHelper == null)
   return;
  var element = targets.targetElement;
  if(element == ASPx.currentDragHelper.obj)
   return;
  var grid = targets.control;
  grid.dragHelper.DisplayTargetImages(false);
  if(!element) {
   ASPx.currentDragHelper.targetElement = null;
   return;
  }
  ASPx.currentDragHelper.targetElement = element;
  ASPx.currentDragHelper.targetTag = targets.targetTag;
  var moveToCustWindow = grid.dragHelper.IsCustWindowTarget(element);
  if(moveToCustWindow) {
   ASPx.currentDragHelper.addElementToDragDiv(grid.GetArrowDragFieldImage());
   return;
  }
  var moveToGroup = grid.dragHelper.IsGroupingTarget(element);
  var info = grid.dragHelper.CreateTargetImagesInfo(targets, moveToGroup);
  if(!info) {
   ASPx.currentDragHelper.targetElement = null;
   return;
  }
  if(targets.skipNeighbor)
   info.neighbor = null;
  var position = grid.dragHelper.CreateTargetImagesPosition(element, info);
  grid.dragHelper.DisplayTargetImages(true, position);
 },
 CreateTargetImagesPosition: function(targetElement, info){
  if(info.side == ASPx.CursorTargetTag.Top || info.side == ASPx.CursorTargetTag.Bottom)
   return this.CreateVerticalTargetImagesPosition(targetElement, info);
  return this.CreateHorizontalTargetImagesPosition(targetElement, info);
 },
 CreateHorizontalTargetImagesPosition: function(targetElement, info){
  var left = ASPx.GetAbsoluteX(targetElement);
  var isRightSide = info.side == ASPx.CursorTargetTag.Right;
  if(targetElement == this.grid.GetGroupPanel() || targetElement == this.grid.GetAdaptiveHeaderPanel() || targetElement == this.grid.GetAdaptiveGroupPanel()) {
   if(this.grid.rtl)
    left += targetElement.offsetWidth;
  } else {
   if(isRightSide) {
    if(info.neighbor)
     left = ASPx.GetAbsoluteX(info.neighbor);
    else
     left += targetElement.offsetWidth;
   }
  }
  var top = ASPx.GetAbsoluteY(targetElement);
  var bottomElement = targetElement;
  var moveToGroup = this.IsGroupingTarget(targetElement);
  if(!moveToGroup && info.targetColumnIndex > -1)
   bottomElement = this.grid.GetHeader(this.GetHeaderLeaf(info.targetColumnIndex, !isRightSide));
  var bottom = ASPx.GetAbsoluteY(bottomElement) + bottomElement.offsetHeight;
  return { top: top, bottom: bottom, left: left, right: left };
 },
 CreateVerticalTargetImagesPosition: function(targetElement, info){
  var left = ASPx.GetAbsoluteX(targetElement);
  var right = left + targetElement.offsetWidth;
  var top = ASPx.GetAbsoluteY(targetElement);
  if(info.side == ASPx.CursorTargetTag.Bottom)
   top += targetElement.offsetHeight;
  return { top: top, bottom: top, left: left, right: right };
 },
 GetChildHeaderElement: function(parentIndex, childIndex, left){
  var grid = this.grid;
  var childColumnIndex = childIndex;
  var currentColumnIndex = childIndex;
  var getNextNeighborHeaderMatrixMethodName = "Get" + (left ? "Left" : "Right") + "Neighbor";
  while(ASPx.IsExists(currentColumnIndex) && this.IsParentColumn(parentIndex, currentColumnIndex)){
   childColumnIndex = currentColumnIndex; 
   currentColumnIndex = grid.GetHeaderMatrix()[getNextNeighborHeaderMatrixMethodName](childColumnIndex);
  }
  return grid.GetHeader(childColumnIndex);
 },
 IsParentColumn: function(parentIndex, columnIndex){
  var index = columnIndex;
  while(index >= 0 && index != parentIndex)
   index = this.grid.GetColumn(index).parentIndex;
  return index >= 0;
 },
 CreateTargetImagesInfo: function(targets, moveToGroup){
  if(moveToGroup)
   return this.CreateGroupPanelTargetImagesInfo(targets);
  var grid = targets.control;
  var targetElement = targets.targetElement;
  var info = {
   targetColumnIndex: grid.getColumnIndex(targetElement.id),
   side: targets.targetTag,
   neighbor: null
  };
  var isAdaptiveHeader = grid.dragHelper.IsAdaptiveHeaderTarget(targetElement);
  if(!isAdaptiveHeader && info.targetColumnIndex < 0)
   return info;
  if(isAdaptiveHeader && targetElement.adaptiveInfo) {
   info.targetColumnIndex = targetElement.adaptiveInfo.brotherIndex;
   if(!targetElement.adaptiveInfo.brotherHasOnlyOneLeaf)
    info.side = targetElement.adaptiveInfo.isLeftLeaf ? ASPx.CursorTargetTag.Left : ASPx.CursorTargetTag.Right;
  }
  var neighborIndex = this.FindHeaderNeighborIndexByHorizontal(info.side, info.targetColumnIndex, isAdaptiveHeader);
  if(neighborIndex == null)
   info = null;
  else if(neighborIndex > -1)
   info.neighbor = grid.GetHeader(neighborIndex);
  return info;
 },
 CreateGroupPanelTargetImagesInfo: function(targets){
  var grid = targets.control;
  var isRightSide = targets.targetTag == ASPx.CursorTargetTag.Right;
  var method = isRightSide ^ grid.rtl ? "nextSibling" : "previousSibling";
  var neighbor = grid.dragHelper.GetGroupNodeNeighbor(targets.targetElement, method);
  if(neighbor && neighbor.id == ASPx.currentDragHelper.obj.id)
   return null;
  return {
   targetColumnIndex: grid.getColumnIndex(targets.targetElement.id),
   side: targets.targetTag,
   neighbor: neighbor
  };
 },
 FindHeaderNeighborIndexByHorizontal: function(side, targetColumnIndex, isAdaptiveHeader){
  if(side == ASPx.CursorTargetTag.Top || side == ASPx.CursorTargetTag.Bottom)
   return targetColumnIndex;
  var grid = this.grid;
  var isRightSide = side == ASPx.CursorTargetTag.Right;
  var matrix =  grid.GetHeaderMatrix();
  var method = isRightSide ^ grid.rtl ? "GetRightNeighbor" : "GetLeftNeighbor";
  var neighborIndex = matrix[method](targetColumnIndex, !isAdaptiveHeader);
  var sourceColumn = grid.getColumnObject(ASPx.currentDragHelper.obj.id);
  if(neighborIndex == sourceColumn.index && !sourceColumn.inCustWindow && !this.IsGroupHeaderTarget(ASPx.currentDragHelper.obj))
   return sourceColumn.parentIndex != grid.GetColumn(targetColumnIndex).parentIndex ? -1 : null;
  if(!isNaN(neighborIndex)){
   if(isAdaptiveHeader && !matrix.IsLeaf(neighborIndex))
    neighborIndex = matrix.GetLeaf(neighborIndex, isRightSide);
  } else
   neighborIndex = -1;
  return neighborIndex;
 },
 GetGroupNodeNeighbor: function(element, method) {
  if(this.IsAdaptiveGroupHeaderTarget(element)) 
   return this.GetAdaptiveGroupNodeNeighbor(element, method);
  return this.GetGroupNodeNeighborCore(element, method, 2);
 },
 GetAdaptiveGroupNodeNeighbor: function(element, method) {   
  var headers = ASPx.GetNodesByPartialClassName(this.grid.GetAdaptiveGroupPanel(), ASPx.GridViewConsts.HeaderCellCssClass);
  var index = ASPx.Data.ArrayIndexOf(headers, element);
  if(index < 0) return null;   
  return method == "nextSibling" ? headers[index + 1] : headers[index - 1];
 },
 GetGroupNodeNeighborCore: function(element, method, distance) {
  var neighbor = element[method];
  if(neighbor && neighbor.nodeType == 1) {
   if(this.IsGroupingTarget(neighbor)) 
    return neighbor;
   if(distance > 1)
    return this.GetGroupNodeNeighborCore(neighbor, method, --distance);
  }
  return null;
 },
 DisplayTargetImages: function(visible, position){
  var downImage = this.grid.GetArrowDragDownImage();
  if(downImage){
   var showImage = visible && position.left == position.right;
   if(showImage) {
    ASPx.SetAbsoluteX(downImage, position.left - downImage.offsetWidth / 2);
    ASPx.SetAbsoluteY(downImage, position.top - downImage.offsetHeight);
   }
   ASPx.SetElementVisibility(downImage, showImage);
  }
  var upImage = this.grid.GetArrowDragUpImage();
  if(upImage){
   var showImage = visible && position.left == position.right;
   if(showImage) {
    ASPx.SetAbsoluteX(upImage, position.left - upImage.offsetWidth / 2);
    ASPx.SetAbsoluteY(upImage, position.bottom);
   }
   ASPx.SetElementVisibility(upImage, showImage);
  }
  var rightImage = this.grid.GetArrowDragRightImage();
  if(rightImage){
   var showImage = visible && position.left != position.right;
   if(showImage) {
    ASPx.SetAbsoluteX(rightImage, position.left - rightImage.offsetWidth);
    ASPx.SetAbsoluteY(rightImage, position.top - rightImage.offsetHeight / 2);
   }
   ASPx.SetElementVisibility(rightImage, showImage);
  }
  var leftImage = this.grid.GetArrowDragLeftImage();
  if(leftImage){
   var showImage = visible && position.left != position.right;
   if(showImage) {
    ASPx.SetAbsoluteX(leftImage, position.right);
    ASPx.SetAbsoluteY(leftImage, position.top - rightImage.offsetHeight / 2);
   }
   ASPx.SetElementVisibility(leftImage, showImage);
  }
 }
});
GridViewDragHelper.Target_GetElementHeight = null;
ASPx.GridViewDragHelper = GridViewDragHelper;
ASPxClientGridBase.SelectStartHandler = function(e) {
 if(ASPx.Evt.GetEventSource(e).tagName.match(/input|select|textarea/i))
  return;
 if(e.ctrlKey || e.shiftKey) {
  ASPx.Selection.Clear();
  ASPx.Evt.PreventEventAndBubble(e);
 }
};
ASPxClientGridBase.SaveActiveElementSettings = function(grid) {
 var element = grid.GetFilterHelper().GetActiveElement();
 grid.GetFilterHelper().ResetActiveElement();
 ASPxClientGridBase.activeElementData = null;
 if (!element || !element.id || element.tagName != "INPUT" || !(ASPx.GetIsParent(grid.GetMainElement(), element) || element.id.indexOf(grid.name + "_") == 0))
  return;  
 ASPxClientGridBase.activeElementData = [ grid.name, element.id, ASPx.Selection.GetInfo(element).endPos ];
 if(typeof(Sys) != "undefined" && typeof(Sys.Application) != "undefined") {
  if(!ASPxClientGridBase.MsAjaxActiveElementHandlerAdded) {
   Sys.Application.add_load(function() { ASPxClientGridBase.RestoreActiveElementSettings(); } );
   ASPxClientGridBase.MsAjaxActiveElementHandlerAdded = true;
  }
 } 
};
ASPxClientGridBase.RestoreActiveElementSettings = function(grid) {
 var data = ASPxClientGridBase.activeElementData;
 if(!data || grid && data[0] != grid.name) return;
 var element = ASPx.GetElementById(data[1]);
 if(element) {
  window.setTimeout(function() {
   element.focus();
   ASPx.Selection.Set(element, data[2], data[2]);
  }, 0);
 }
 ASPxClientGridBase.activeElementData = null;
};
var ASPxClientGridViewCallbackCommand = {
 NextPage: "NEXTPAGE",
 PreviousPage: "PREVPAGE",
 GotoPage: "GOTOPAGE",
 SelectRows: "SELECTROWS",
 SelectRowsKey: "SELECTROWSKEY",
 Selection: "SELECTION",
 FocusedRow: "FOCUSEDROW",
 Group: "GROUP",
 UnGroup: "UNGROUP",
 Sort: "SORT",
 ColumnMove: "COLUMNMOVE",
 CollapseAll: "COLLAPSEALL",
 ExpandAll: "EXPANDALL",
 ExpandRow: "EXPANDROW",
 CollapseRow: "COLLAPSEROW",
 HideAllDetail: "HIDEALLDETAIL",
 ShowAllDetail: "SHOWALLDETAIL",
 ShowDetailRow: "SHOWDETAILROW",
 HideDetailRow: "HIDEDETAILROW",
 PagerOnClick: "PAGERONCLICK",
 ApplyFilter: "APPLYFILTER",
 ApplyColumnFilter: "APPLYCOLUMNFILTER",
 ApplyMultiColumnFilter: "APPLYMULTICOLUMNFILTER",
 ApplyHeaderColumnFilter: "APPLYHEADERCOLUMNFILTER",
 ApplySearchPanelFilter: "APPLYSEARCHPANELFILTER",
 ApplyCustomizationDialogChanges: "APPLYCUSTOMIZATIONDIALOGCHANGES",
 FilterRowMenu: "FILTERROWMENU",
 StartEdit: "STARTEDIT",
 CancelEdit: "CANCELEDIT",
 UpdateEdit: "UPDATEEDIT",
 UpdateSummaries: "UPDATESUMMARIES",
 AddNewRow: "ADDNEWROW",
 DeleteRow: "DELETEROW",
 CustomButton: "CUSTOMBUTTON",
 CustomCallback: "CUSTOMCALLBACK",
 ShowFilterControl: "SHOWFILTERCONTROL",
 CloseFilterControl: "CLOSEFILTERCONTROL",
 SetFilterEnabled: "SETFILTERENABLED",
 Refresh: "REFRESH",
 SelFieldValues: "SELFIELDVALUES",
 RowValues: "ROWVALUES",
 PageRowValues: "PAGEROWVALUES",
 FilterPopup: "FILTERPOPUP",
 ContextMenu: "CONTEXTMENU",
 Toolbar: "TOOLBAR",
 Export: "EXPORT",
 CustomValues: "CUSTOMVALUES"
};
var ASPxClientGridExportFormat = {
 Pdf: "Pdf",
 Docx: "Docx",
 Rtf: "Rtf",
 Csv: "Csv",
 Xls: "Xls",
 Xlsx: "Xlsx"
};
var ASPxClientGridBatchEditStartEditingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex, focusedColumn, itemValues) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
  this.focusedColumn = focusedColumn;
  this.itemValues = ASPx.CloneObject(itemValues);
 }
});
var ASPxClientGridBatchEditEndEditingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex, focusedColumn, itemValues) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
  this.focusedColumn = focusedColumn;
  this.itemValues = ASPx.CloneObject(itemValues);
 }
});
var ASPxClientGridBatchEditItemChangesCancelingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex, itemValues) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
  this.itemValues = ASPx.CloneObject(itemValues);
 }
});
var ASPxClientGridBatchEditItemValidatingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(visibleIndex, validationInfo) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
  this.validationInfo = ASPx.CloneObject(validationInfo);
 }
});
var ASPxClientGridBatchEditConfirmShowingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(requestTriggerID) {
  this.constructor.prototype.constructor.call(this);
  this.requestTriggerID = requestTriggerID;
 }
});
var ASPxClientGridBatchEditTemplateCellFocusedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(column) {
  this.constructor.prototype.constructor.call(this);
  this.column = column;
  this.handled = false;
 }
});
var ASPxClientGridBatchEditClientChangesEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(insertedValues, deletedValues, updatedValues) {
  this.constructor.prototype.constructor.call(this);
  this.insertedValues = insertedValues;
  this.deletedValues = deletedValues;
  this.updatedValues = updatedValues;
 }
});
var ASPxClientGridBatchEditItemInsertingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
 }
});
var ASPxClientGridBatchEditItemDeletingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex, itemValues) {
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
  this.itemValues = itemValues;
 }
});
var ASPxClientGridClipboardCellPastingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(cellInfo, oldValueInfo, newValueInfo) {
  this.constructor.prototype.constructor.call(this);
  this.cellInfo = cellInfo;
  this.oldText = oldValueInfo.text;
  this.oldValue = oldValueInfo.value;
  this.newText = newValueInfo.text;
  this.newValue = newValueInfo.value;
 }
});
var ASPxClientGridCellSelectionChangingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(cellInfo, newSelectionState) {
  this.constructor.prototype.constructor.call(this);
  this.cellInfo = cellInfo;
  this.newSelectionState = newSelectionState;
 }
});
var ASPxClientGridSelectionState = {
 Unselected: 0,
 Selected: 1
};
var ASPxClientGridFocusedCellChangingEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(cellInfo) {
  this.constructor.prototype.constructor.call(this);
  this.cellInfo = cellInfo;
 }
});
var ASPxClientGridBatchEditApi = ASPx.CreateClass(ASPx.BatchEditApi, {
 constructor: function(owner) {
  this.constructor.prototype.constructor.call(this, owner);
  this.grid = owner;
 },
 GetColumnIndex: function(column) { return this.grid._getColumnIndexByColumnArgs(column); },
 ConvertVisibleIndexToKey: function(visibleIndex) { return this.grid.ConvertVisibleIndexToKey(visibleIndex); },
 ConvertKeyToVisibleIndex: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 CreateControlCellInfo: function(key, column) {
  var visibleIndex = this.grid.ConvertKeyToVisibleIndex(key);
  return this.grid.CreateUserCellInfo(visibleIndex, column, key);
 },
 SetCellValue: function(visibleIndex, column, value, displayText, cancelCellHighlighting) { 
  return this.SetCellValueByKey(this.ConvertVisibleIndexToKey(visibleIndex), column, value, displayText, cancelCellHighlighting);
 },
 SetCellValueByKey: function(key, column, value, displayText, cancelCellHighlighting) {
  return this.SetCellValueCore(key, column, value, displayText, cancelCellHighlighting);
 },
 GetCellValue: function(visibleIndex, column, initial) { return this.GetCellValueByKey(this.ConvertVisibleIndexToKey(visibleIndex), column, initial); },
 GetCellValueByKey: function(key, column, initial) { return this.GetCellValueCore(key, column, initial); },
 GetCellTextContainer: function(visibleIndex, column) { return this.GetCellTextContainerByKey(this.ConvertVisibleIndexToKey(visibleIndex), column); },
 GetCellTextContainerByKey: function(key, column) { return this.GetCellTextContainerCore(key, column); },
 HasChanges: function(visibleIndex, column) { return this.HasChangesByKey(this.ConvertVisibleIndexToKey(visibleIndex), column); },
 HasChangesByKey: function(key, column) { return this.HasChangesCore(key, column); },
 ResetChanges: function(visibleIndex, columnIndex) { this.ResetChangesByKey(this.ConvertVisibleIndexToKey(visibleIndex), columnIndex); },
 ResetChangesByKey: function(key, columnIndex) { this.ResetChangesCore(key, columnIndex); },
 StartEdit: function(visibleIndex, columnIndex) { this.StartEditByKey(this.ConvertVisibleIndexToKey(visibleIndex), columnIndex); },
 StartEditByKey: function(key, columnIndex) { this.StartEditCore(key, columnIndex); },
 ValidateItem: function(visibleIndex) { return this.ValidateItemByKey(this.ConvertVisibleIndexToKey(visibleIndex)); },
 ValidateItemByKey: function(key) { return this.ValidateRecordCore(key); },
 IsDeletedItem: function(visibleIndex) { return this.IsDeletedItemByKey(this.ConvertVisibleIndexToKey(visibleIndex)); },
 IsDeletedItemByKey: function(key) { return this.IsDeletedRecordCore(key); },
 IsNewItem: function(visibleIndex) { return this.IsNewRecordCore(this.ConvertVisibleIndexToKey(visibleIndex)); },
 AddNewItem: function() { this.AddNewRecordCore(); }, 
 DeleteItem: function(visibleIndex) { this.DeleteItemByKey(this.ConvertVisibleIndexToKey(visibleIndex)); },
 DeleteItemByKey: function(key) { this.DeleteRecordCore(key); },
 RecoverItem: function(visibleIndex) { this.RecoverItemByKey(this.ConvertVisibleIndexToKey(visibleIndex)); },
 RecoverItemByKey: function(key) { this.RecoverRecordCore(key); },
 GetItemVisibleIndices: function(includeDeleted) { 
  var currentPageKeys = this.FilterCurrentPageKeys(this.GetRecordKeys(includeDeleted));
  return currentPageKeys.map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this)); 
 },
 GetInsertedItemVisibleIndices: function() { return this.FilterCurrentPageKeys(this.GetInsertedRecordKeys()); },
 GetDeletedItemVisibleIndices: function() {
  var deletedIndices = [];
  var currentPageDeletedKeys = this.FilterCurrentPageKeys(this.GetDeletedRecordKeys());
  ASPx.Data.ForEach(currentPageDeletedKeys, function(key){  
   var visibleIndex = this.ConvertKeyToVisibleIndex(key);
   if(visibleIndex > -1) deletedIndices.push(visibleIndex);
  }.aspxBind(this));
  return deletedIndices;
 },
 GetUpdatedItemVisibleIndices: function() { 
  var keys = this.FilterCurrentPageKeys(this.GetUpdatedRecordKeys());
  return keys.map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this));
 },
 IsCurrentPageRecord: function(key) {
  var helper = this.GetHelper();
  return !!helper && helper.IsCurrentPageRecord(key);
 },
 FilterCurrentPageKeys: function(keys) { return keys.filter(function (key) { return this.IsCurrentPageRecord(key); }.bind(this)); },
 GetTotalSummaryValue: function(summary) {
  var helper = this.GetHelper();
  if(!helper)
   return null;
  var summaryItemIndex = summary;
  if(typeof(summary) == "string")
   summaryItemIndex = helper.GetTotalSummaryByFieldName(summary);
  return helper.GetTotalSummaryValue(summaryItemIndex);
 },
 GetGroupSummaryValue: function(groupRowVisibleIndex, summary) {
  var helper = this.GetHelper();
  if(!helper)
   return null;
  var summaryItemIndex = summary;
  if(typeof(summary) == "string")
   summaryItemIndex = helper.GetGroupSummaryByFieldName(summary);
  return helper.GetGroupSummaryValue(groupRowVisibleIndex, summaryItemIndex);
 }
});
var ASPxClientGridCellInfo = ASPx.CreateClass(null, {
 constructor: function(itemIndex, column) {
  this.itemVisibleIndex = itemIndex;
  this.column = column;
 }
});
var ASPxClientGridToolbarItemClickEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(toolbarIndex, toolbarName, item, processOnServer) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.toolbarIndex = toolbarIndex;
  this.toolbarName = toolbarName;
  this.item = item;
  this.usePostBack = false;
  this.handled = false;
 }
});
var ASPxClientGridBatchEditSummaryDisplayTextEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(summaryInfo, text, groupRowVisibleIndex) {
  this.constructor.prototype.constructor.call(this);
  this.isGroupSummary = summaryInfo.isGroupSummary;
  this.isTotalSummary = !summaryInfo.isGroupSummary;
  this.summaryItemIndex = summaryInfo.summaryIndex;
  this.summaryType = summaryInfo.summaryType;
  this.summaryFieldName = summaryInfo.summaryFieldName;
  this.serverValue = summaryInfo.serverValue;
  this.value = summaryInfo.value;
  this.summaryElement = summaryInfo.summaryElement;
  this.displayText = text;
  this.groupRowVisibleIndex = groupRowVisibleIndex;
 }
});
var ASPxClientGridKeyboardEventArgs = ASPx.CreateClass(ASPx.ASPxClientGridKeyboardEventArgsBase, { });
var ASPxClientSummaryItemType = {
 Sum: 0,
 Min: 1,
 Max: 2,
 Count: 3,
 Average: 4,
 Custom: 5,
 None: 6
};
ASPxClientGridBase.PostponeInitialize = function(name, info){
 var grid = ASPx.GetControlCollection().Get(name);
 if(grid) {
  grid.styleInfo = info.styleInfo;
  grid.cButtonIDs = info.commandButtonIDs;
  if(grid.batchEditClientState) {
   grid.batchEditClientState.extraCommandButtonsInfo = info.extraCommandButtonsInfo;
  }
  grid.EnsureRowKeys();
  grid.UpdateItemsStyle();
 }
};
ASPx.GHeaderMouseDown = function(name, element, e) {
 var grid = ASPx.GetControlCollection().Get(name);
 if(grid != null) 
  grid.HeaderMouseDown(element, e);
};
ASPx.GSort = function(name, columnIndex) {
 var grid = ASPx.GetControlCollection().Get(name);
 if(grid != null)  
  grid.SortBy(columnIndex);
};
ASPx.GVPopupEditFormOnInit = function(name, popup) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  window.setTimeout(function() { gv.OnPopupEditFormInit(popup); }, 0);
};
ASPx.GVPagerOnClick = function(name, value) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) 
  gv.doPagerOnClick(value);
};
ASPx.GVFilterKeyPress = function(name, element, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) 
  gv.GetFilterHelper().OnColumnFilterInputKeyPress(element, e);
};
ASPx.GVFilterSpecKeyPress = function(name, element, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) 
  gv.GetFilterHelper().OnColumnFilterInputSpecKeyPress(element, e);
};
ASPx.GVFilterChanged = function(name, element) {
 window.setTimeout(function() {
  var gv = ASPx.GetControlCollection().Get(name);
  var el = ASPx.GetControlCollection().Get(element.name);
  if(gv != null && el != null) 
   gv.GetFilterHelper().OnColumnFilterInputChanged(el);
 }, 0);
};
ASPx.GVFilterUserInput = function(name, element) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetFilterHelper().OnColumnFilterUserInput(element);
};
ASPx.GVShowParentRows = function(name, evt, element) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  if(element)
   gv.OnParentRowMouseEnter(element);  
  else 
   gv.OnParentRowMouseLeave(evt);
 }
};
ASPx.GTableClick = function(name, evt) {
 var g = ASPx.GetControlCollection().Get(name);
 if(g != null && g.NeedProcessTableClick(evt))
  g.mainTableClick(evt);
};
ASPx.GVTableDblClick = function(name, evt) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null && gv.NeedProcessTableClick(evt))
  gv.mainTableDblClick(evt);
};
ASPx.GVCustWindowCloseUp = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  gv.RaiseCustomizationWindowCloseUp();
 }
};
ASPx.GVApplyFilterPopup = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.ApplyHeaderFilterByColumn();
};
ASPx.GVShowFilterControl = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  gv.ShowFilterControl();
 }
};
ASPx.GVCloseFilterControl = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  gv.CloseFilterControl();
 }
};
ASPx.GVSetFilterEnabled = function(name, value) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  gv.SetFilterEnabled(value);
 }
};
ASPx.GVApplyFilterControl = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.ApplyFilterControl();
};
ASPx.GVFilterRowMenu = function(name, columnIndex, element) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetFilterHelper().FilterRowMenuButtonClick(columnIndex, element);
};
ASPx.GVFilterRowMenuClick = function(name, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetFilterHelper().FilterRowMenuItemClick(e.item);
};
ASPx.GCmdToolbarMenuItemClick = function(name, toolbar, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetToolbarHelper().OnToolbarMenuItemClick(toolbar, e);
};
ASPx.GVScheduleCommand = function(name, commandArgs, postponed, event) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.ScheduleUserCommand(commandArgs, postponed, ASPx.Evt.GetEventSource(event));
};
ASPx.GVHFCancelButtonClick = function(name) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetHeaderFilterPopup().Hide();
};
ASPx.GridStyleHelper = GridStyleHelper;
ASPx.GridLayoutHelper = GridLayoutHelper;
ASPx.GridViewDragHelper = GridViewDragHelper;
ASPx.GridCallbackHelper = GridCallbackHelper;
ASPx.GridSortOrder = GridSortOrder;
ASPx.ASPxClientGridExportFormat = ASPxClientGridExportFormat;
window.ASPxClientGridBase = ASPxClientGridBase;
window.ASPxClientGridColumnBase = ASPxClientGridColumnBase;
window.ASPxClientGridViewCallbackCommand = ASPxClientGridViewCallbackCommand;
window.ASPxClientGridKeyboardEventArgs = ASPxClientGridKeyboardEventArgs;
window.ASPxClientGridBatchEditStartEditingEventArgs = ASPxClientGridBatchEditStartEditingEventArgs;
window.ASPxClientGridBatchEditEndEditingEventArgs = ASPxClientGridBatchEditEndEditingEventArgs;
window.ASPxClientGridBatchEditItemChangesCancelingEventArgs = ASPxClientGridBatchEditItemChangesCancelingEventArgs;
window.ASPxClientGridBatchEditItemValidatingEventArgs = ASPxClientGridBatchEditItemValidatingEventArgs;
window.ASPxClientGridBatchEditConfirmShowingEventArgs = ASPxClientGridBatchEditConfirmShowingEventArgs;
window.ASPxClientGridBatchEditTemplateCellFocusedEventArgs = ASPxClientGridBatchEditTemplateCellFocusedEventArgs;
window.ASPxClientGridBatchEditClientChangesEventArgs = ASPxClientGridBatchEditClientChangesEventArgs;
window.ASPxClientGridBatchEditItemInsertingEventArgs = ASPxClientGridBatchEditItemInsertingEventArgs;
window.ASPxClientGridBatchEditItemDeletingEventArgs = ASPxClientGridBatchEditItemDeletingEventArgs;
window.ASPxClientGridClipboardCellPastingEventArgs = ASPxClientGridClipboardCellPastingEventArgs;
window.ASPxClientGridCellSelectionChangingEventArgs = ASPxClientGridCellSelectionChangingEventArgs;
window.ASPxClientGridFocusedCellChangingEventArgs = ASPxClientGridFocusedCellChangingEventArgs;
window.ASPxClientGridBatchEditApi = ASPxClientGridBatchEditApi;
window.ASPxClientGridCellInfo = ASPxClientGridCellInfo;
window.ASPxClientGridColumnMovingTargetPosition = ASPxClientGridColumnMovingTargetPosition;
window.ASPxClientGridToolbarItemClickEventArgs = ASPxClientGridToolbarItemClickEventArgs;
window.ASPxClientSummaryItemType = ASPxClientSummaryItemType;
window.ASPxClientGridSelectionState = ASPxClientGridSelectionState;
})();

(function(){
var GridViewConsts = {
 AdaptiveGroupPanelID: "DXAGroupPanel",
 AdaptiveHeaderPanelID: "DXAHeaderPanel",
 AdaptiveFooterPanelID: "DXAFooterPanel",
 AdaptiveGroupHeaderID: "DXADGroupHeader",
 AdaptiveHeaderID: "DXADHeader",
 HeaderTableID: "DXHeaderTable",
 FooterTableID: "DXFooterTable",
 FilterRowID: "DXFilterRow",
 DataRowID: "DXDataRow",
 DetailRowID: "DXDRow",
 EditingRowID: "DXEditingRow",
 EditingErrorItemID: "DXEditingErrorItem",
 EditFormTableCellID: "DXEFC",
 AdaptiveDetailRowID: "DXADRow",
 PreviewRowID: "DXPRow",
 GroupRowID: "DXGroupRow",
 GroupRowExpID: "DXGroupRowExp",
 EmptyDataRowID: "DXEmptyRow",
 FooterRowID: "DXFooterRow",
 GroupFooterRowID: "DXGFRow",
 HeaderRowID: "DXHeadersRow",
 BatchChangesPreviewGroupRowID: "DXBatchChangesPreviewGroupRow",
 BatchEditorContainerID: "DXBEC",
 CommandButtonID: "DXCBtn",
 DataRowTemplateCellID: "tcrow",
 GroupFooterRowTemplateCellID: "tcgfr",
 FooterRowTemplateCellID: "tcFooterRow",
 FilterRowTemplateCellID: "tcFR",
 CustDialogWindowID: "DXCDWindow",
 DataRowPattern: "_DXDataRow(?:-?\\d+|new)(?:_\\d+)?$",
 BandedRowPattern: "_DXDataRow(-?\\d+|new)_(\\d+)$",
 GridViewMarkerCssClass: "dxgv",
 ControlClassName: "dxgvControl",
 DataRowCssClass: "dxgvDataRow",
 GroupRowCssClass: "dxgvGroupRow",
 EmptyPagerRowCssClass: "dxgvEPDR",
 GroupFooterRowClass: "dxgvGroupFooter",
 GroupPanelCssClass: "dxgvGroupPanel",
 FooterRowClass: "dxgvFooter",
 FooterScrollDivContainerCssClass: "dxgvFSDC",
 HeaderScrollDivContainerCssClass: "dxgvHSDC",
 HeaderCellCssClass: "dxgvHeader",
 HeaderCellEllipsisContainerCssClass: "dxgvHCEC",
 CommandColumnCellCssClass: "dxgvCommandColumn",
 IndentCellCssClass: "dxgvIndentCell",
 InlineEditCellCssClass: "dxgvInlineEditCell",
 DetailCellCssClass: "dxgvDetailCell",
 DetailIndentCellCssClass: "dxgvDIC",
 DetailButtonCellCssClass: "dxgvDetailButton",
 AdaptivityDisabledCssClass: "dxgvAdD",
 AdaptivityEnabledCssClass: "dxgvAE",
 AdaptivityWithLimitEnabledCssClass: "dxgvALE",
 AdaptiveHiddenCssClass: "dxgvAH",
 AdaptiveIndentCellCssClass: "dxgvAIC",
 AdaptiveDetailShowButtonCssClass: "dxgvADSB",
 AdaptiveDetailHideButtonCssClass: "dxgvADHB",
 AdaptiveDetailTableCssClass: "dxgvADT",
 AdaptiveDetailCaptionCellCssClass: "dxgvADCC",
 AdaptiveDetailDataCellCssClass: "dxgvADDC",
 AdaptiveDetailSpacerCellCssClass: "dxgvADSC",
 AdaptiveDetailCommandCellCssClass: "dxgvADCMDC",
 AdaptiveDetailLayoutItemContentCssClass: "dxgvADLIC",
 HorizontalExtraCellClassName: "dxgvHEC",
 HiddenHorizontalExtraCellMarkerClassName: "dxgvHHEC",
 FirstVisibleRowClassName: "dxgvFVR",
 LastVisibleRowClassName: "dxgvLVR",
 AccessibilityInvisibleRowClassName: "dxAIR",
 PageBottomVisibleCellsMarkerClassName: "dxgvPBVC",
 RemoveRightBorderClassName: "dxgRRB",
 BatchEditHiddenItemClassName: "dxgvBEHI",
 BatchEditChangesPreviewClassName: "dxgvBECP",
 BatchEditChangesPreviewScrollDivClassName: "dxgvBECPSD",
 CommandButtonTemplateReplacementMarkerCssClass: "dxgvCBTR",
 UnspecifiedScrollPosition: -1
};
var GridViewRowType = { Header: 1, Filter: 2, Data: 3, Group: 4, GroupFooter: 5, Footer: 6, InlineEdit: 7, BatchEtalon: 8 };
var GridViewAdaptiveDetailButtonPosition = { None: 0, Left: 1, Right: 2 };
var ASPxClientGridView = ASPx.CreateClass(ASPxClientGridBase, {
 NewRowVisibleIndex: -2147483647,
 constructor: function(name){
  this.constructor.prototype.constructor.call(this, name);
  this.editMode = 2;
  this.enablePostponeResizing = false;
  this.FocusedRowChanged = new ASPxClientEvent();
  this.RowFocusing = new ASPxClientEvent();
  this.ColumnStartDragging  = new ASPxClientEvent();
  this.ColumnResizing  = new ASPxClientEvent();
  this.ColumnResized  = new ASPxClientEvent();
  this.ColumnMoving = new ASPxClientEvent();
  this.RowExpanding  = new ASPxClientEvent();
  this.RowCollapsing  = new ASPxClientEvent();
  this.DetailRowExpanding  = new ASPxClientEvent();
  this.DetailRowCollapsing  = new ASPxClientEvent();
  this.RowClick  = new ASPxClientEvent();
  this.RowDblClick  = new ASPxClientEvent();
  this.ContextMenu = new ASPxClientEvent();
  this.ContextMenuItemClick = new ASPxClientEvent();
  this.BatchEditRowChangesCanceling = new ASPxClientEvent();
  this.BatchEditRowValidating = new ASPxClientEvent();
  this.BatchEditRowInserting = new ASPxClientEvent();
  this.BatchEditRowDeleting = new ASPxClientEvent();
  this.BatchEditRowRecovering = new ASPxClientEvent();
  this.BatchEditChangesPreviewShowing = new ASPxClientEvent();
  this.BatchEditChangesPreviewShown = new ASPxClientEvent();
  this.allowFixedGroups = false;
  this.virtualScrollMode = 0;
  this.fixedColumnCount = 0;
  this.hasDetailRows = false;
  this.showDetailButton = true;
  this.showGroupButton = true;
  this.adaptiveButtonPos = GridViewAdaptiveDetailButtonPosition.None;
  this.showColumnHeaders = true;
  this.showGroupedColumns = false;
  this.hasMergedGroups = false;
  this.hasFilterRowTemplate = false;
  this.hasDataRowTemplate = false;
  this.hasGroupRowTemplate = false;
  this.hasFooterRowTemplate = false;
  this.hasGroupFooterRowTemplate = false;
  this.hasEditFormTemplate = false;
  this.allowChangeColumnHierarchy = false;
  this.allowColumnClientMove = false;
  this.tableHelper = null;
  this.dragHelper = null;
  this.batchEditHelper = null;
  this.custDialogHelper = null;
  this.columnAdjustor = null;
  this.virtualScrollingDelay = 500;
  this.adaptivityMode = 0;
  this.adaptiveColumnsOrder = [];
  this.adaptivityHelper = null;
  this.enableCustDialog = false;
  this.custDialogApplyButtonName = "";
  this.custDialogCloseButtonName = "";
 },
 applyAccessibilityAttributes: function() {
  this.setAriaDescription("headerLayoutElements");
 },
 GetGroupPanelContextMenu: function() { return ASPx.GetControlCollection().Get(this.name + "_DXContextMenu_GroupPanel"); },
 GetColumnContextMenu: function() { return ASPx.GetControlCollection().Get(this.name + "_DXContextMenu_Columns"); },
 GetRowContextMenu: function() { return ASPx.GetControlCollection().Get(this.name + "_DXContextMenu_Rows"); },
 GetFooterContextMenu: function() { return ASPx.GetControlCollection().Get(this.name + "_DXContextMenu_Footer"); },
 GetGroupFooterContextMenu: function() { return ASPx.GetControlCollection().Get(this.GetGroupFooterContextMenuName()); },
 GetCustDialogWindow: function() { return ASPx.GetControlCollection().Get(this.name + "_" + GridViewConsts.CustDialogWindowID); },
 GetCustDialogHelper: function() {
  if(!this.custDialogHelper && typeof(ASPx.GridViewCustDialogHelper) != "undefined" && this.GetCustDialogWindow())
   this.custDialogHelper = this.CreateCustDialogHelper();
  return this.custDialogHelper;
 },
 CreateCustDialogHelper: function() { return new ASPx.GridViewCustDialogHelper(this); },
 GetGroupFooterContextMenuName: function() { return this.name + "_DXContextMenu_GroupFooter"; },
 GetColumnCaption: function(columnIndex) {
  var result = "";
  if (this.columnCaptions && this.columnCaptions[columnIndex]) {
   result = this.columnCaptions[columnIndex];
  }
  return result;
 },
 GetItem: function(visibleIndex, level){
  var res = this.GetDataRow(visibleIndex, level);
  if(res == null) res = this.GetGroupRow(visibleIndex);
  return res;
 },
 GetDataItem: function(visibleIndex) { return this.GetDataRow(visibleIndex); },
 IsDataItem: function(visibleIndex) { return this.IsDataRow(visibleIndex); },
 GetRow: function(visibleIndex) { return this.GetItem(visibleIndex); },
 GetDataItemIDPrefix: function() { return GridViewConsts.DataRowID; },
 GetEmptyDataItemIDPostfix: function() { return GridViewConsts.EmptyDataRowID; },
 GetHotTrackItemPostfixes: function(){
  if(!this.HasBandedDataRows())
   return ASPxClientGridBase.prototype.GetHotTrackItemPostfixes.call(this);
  var postfixes = [ ];
  var layout = this.GetLayoutHelper().GetEtalonDataRowLayout();
  for(var i = 0; i < layout.length; i++)
   postfixes.push('_' + i);
  return postfixes;
 },
 GetEmptyDataItemCell: function() { 
  var row = this.GetEmptyDataItem();
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetDataRow: function(visibleIndex, level) {
  return this.GetChildElement(GridViewConsts.DataRowID + visibleIndex + this.GetBandedRowLevelPostfix(level));
 },
 GetDataRowSelBtn: function(index) { 
  var rowsToCheck = this.GetRowsToFindSelectButton(index);
  var idPostfix = this.GetDataRowSelBtnIDPrefix(index);
  for(var i = 0; i < rowsToCheck.length; i++) {
   var button = this.FindSelectButton(rowsToCheck[i], idPostfix);
   if(button) return button;
  }  
  return null; 
 },
 GetRowsToFindSelectButton: function(visibleIndex) {
  var rows = this.GetBandedDataRows(visibleIndex);
  if(this.HasAnyAdaptiveElement())
   rows.push(this.GetAdaptiveDetailRow(visibleIndex));
  return rows;
 },
 GetEditingRow: function(obj, level) {
  if(!this.HasBandedDataRows())
   return ASPxClientGridBase.prototype.GetEditingRow.call(this, obj);
  return ASPx.GetElementById((obj ? obj.name : this.name) + this.EditingRowID + this.GetBandedRowLevelPostfix(level));
 },
 GetEditingRowElements: function() {
  var rows = [];
  ASPx.GetNodesByPartialId(this.GetMainTable(), this.EditingRowID, rows);
  var adaptiveInlineEditRow = this.GetAdaptiveInlineEditRow();
  if(adaptiveInlineEditRow)
   rows.push(adaptiveInlineEditRow);
  return rows;
 },
 GetBatchEtalonRow: function(levelIndex) {
  var partialId = this.GetDataItemIDPrefix() + this.EtalonBatchRecordPostFix;
  return this.GetChildElement(partialId + this.GetBandedRowLevelPostfix(levelIndex));
 },
 GetBandedRowLevelPostfix: function(level){
  if(!this.HasBandedDataRows()) return "";
  if(!ASPx.IsExists(level))
   level = 0;
  return "_" + level;
 },
 GetBatchDataRow: function(visibleIndex) {   
  return this.GetDataRow(visibleIndex);
 },
 GetBatchBandedDataRows: function(visibleIndex) { 
  return this.GetBandedDataRows(visibleIndex);
 },
 GetBatchDataCell: function(visibleIndex, columnIndex) {
  var column = this.GetColumn(columnIndex);
  if(!column) return null;
  var adaptiveCell = column.adaptiveHidden ? this.GetAdaptiveCell(visibleIndex, columnIndex) : null;
  return adaptiveCell ? adaptiveCell : this.GetDataCell(visibleIndex, columnIndex);
 },
 GetBatchChangesPreviewGroupRow: function(groupIndex) { return this.GetChildElement(GridViewConsts.BatchChangesPreviewGroupRowID + groupIndex); },
 GetBatchEditPreviewChangesGroupCells: function() {  
  var rows = ASPx.GetNodesByPartialClassName(this.GetGridTD(), "dxgvBatchEditChangesPreviewGroupRow");  
  return rows.map(function(row) { return this.GetLastNonAdaptiveIndentCell(row);}.bind(this));
 },
 IsBatchChangesViewMode: function () {
  var helper = this.GetBatchEditHelper();
  return helper && helper.IsChangesViewVisible();
 },
 GetRecordKeysForNavigation: function(includeDeleted) {
  if(this.IsBatchChangesViewMode())
   return this.GetBatchEditHelper().GetChangedRecordKeys();
  return this.GetRecordKeys(includeDeleted);
 },
 GetBatchOtherPagesChangedRecordVisibleIndices: function () {
  return this.GetBatchEditHelper().GetOtherPagesChangedRecordKeys().map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this));
 },
 GetEditFormTableCell: function() { return ASPx.GetElementById(this.name + "_" + GridViewConsts.EditFormTableCellID); },
 HasBandedDataRows: function() { return this.GetLayoutHelper().GetEtalonDataRowLayout().length > 1; }, 
 GetBandedDataRows: function(visibleIndex) {
  var height = this.GetLayoutHelper().GetLayoutHeight();
  var rows = ASPx.Data.Range(height, 0).map(function(i) { return this.GetDataRow(visibleIndex, i); }.bind(this));
  return rows.filter(function(row) { return !!row; });
 },
 GetBandedInlineEditRows: function() {
  var height = this.GetLayoutHelper().GetLayoutHeight();
  var rows = ASPx.Data.Range(height, 0).map(function(i) { return this.GetEditingRow(this, i); }.bind(this));
  return rows.filter(function(row) { return !!row; });
 },
 GetEditingCell: function(columnIndex) { 
  var row = this.GetEditingRow();
  var cellIndex = this.GetDataCellIndex(columnIndex);
  return row ? row.cells[cellIndex] : null;
 },
 GetEditingErrorCell: function(row) { 
  var row = row || this.GetEditingErrorItem();
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetErrorTextContainer: function(displayIn) {
  var errorRow = this.GetEditingErrorItem(displayIn);
  if(!errorRow) {
   var editRow = this.GetEditingRow(displayIn);
   if(editRow) {
    errorRow = this.CreateEditingErrorItem();
    errorRow.id = editRow.id.replace("DXEditingRow", this.EditingErrorItemID);
    this.UpdateEditingErrorRowColSpan(errorRow, editRow);
    ASPx.InsertElementAfter(errorRow, editRow);
   }
  }
  return this.GetEditingErrorCell(errorRow);
 },
 CreateEditingErrorItem: function() {
  var wrapperElement = document.createElement("div");
  var helper = this.GetStyleHelper();
  wrapperElement.innerHTML = "<table><tbody>" + helper.GetErrorItemHtml() + "</tbody></table>";
  var row = wrapperElement.firstChild.rows[0];
  for(var i = 0; i < row.cells.length; i++) {
   var cell = row.cells[i];
   var colSpan = parseInt(ASPx.Attr.GetAttribute(cell, "data-colSpan"));
   if(!isNaN(colSpan)) 
    cell.colSpan = colSpan;
  }
  return row;
 },
 UpdateEditingErrorRowColSpan: function(row, previousRow) {
  if(this.HasAnyAdaptiveElement()) {
   var errorCell = this.GetLastNonAdaptiveIndentCell(row);
   var adaptiveSampleCell = this.GetSampleAdaptiveDetailCell();
   errorCell.colSpan = adaptiveSampleCell.colSpan;
   errorCell.originalColSpan = adaptiveSampleCell.originalColSpan;
  } 
  if(this.GetFixedColumnsHelper() && this.IsEditFormEditMode()) {
   var errorCell = this.GetLastNonAdaptiveIndentCell(row);
   var editRowCell = this.GetLastNonAdaptiveIndentCell(previousRow);
   errorCell.colSpan = editRowCell.colSpan;
  }
 },
 GetCustDialogApplyButton: function() { return ASPx.GetControlCollection().Get(this.custDialogApplyButtonName); },
 GetCustDialogCloseButton: function() { return ASPx.GetControlCollection().Get(this.custDialogCloseButtonName); },
 PrepareCommandButton: function(button) {
  ASPxClientGridBase.prototype.PrepareCommandButton.call(this, button);
  if(this.enableCustDialog) {
   this.EnsureCommandButtonClickArgs(button);
   var commandName = button.gvClickArgs && button.gvClickArgs[0][0];
   if(commandName === "CustDialogApply")
    this.custDialogApplyButtonName = button.name;
   if(commandName === "CustDialogClose")
    this.custDialogCloseButtonName = button.name;
  }
 },
 GetDetailRow: function(visibleIndex) { return this.GetChildElement(GridViewConsts.DetailRowID + visibleIndex); },
 GetDetailCell: function(visibleIndex) { 
  var row = this.GetDetailRow(visibleIndex);
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetPreviewRow: function(visibleIndex) { return this.GetChildElement(GridViewConsts.PreviewRowID + visibleIndex); },
 GetPreviewCell: function(visibleIndex) { 
  var row = this.GetPreviewRow(visibleIndex);
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetSampleAdaptiveDetailRow: function() { return this.GetChildElement(GridViewConsts.AdaptiveDetailRowID); },
 GetSampleAdaptiveDetailCell: function() { 
  var row = this.GetSampleAdaptiveDetailRow();
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetAdaptiveDataRow: function(visibleIndex) { 
  var getDataItem = this.GetDataRow.aspxBind(this);
  var isValidDataItem = function(item) { return !!item; };
  var getInlineEditItem = this.GetEditingRow.aspxBind(this);
  return this.GetAdaptiveItem(visibleIndex, getDataItem, isValidDataItem, getInlineEditItem);
 },
 GetBandedAdaptiveDataRows: function(visibleIndex) {
  var getDataItem = this.GetBandedDataRows.aspxBind(this);
  var isValidDataItem = function(item) { return item && item.length; };
  var getInlineEditItem = this.GetBandedInlineEditRows.aspxBind(this);
  return this.GetAdaptiveItem(visibleIndex, getDataItem, isValidDataItem, getInlineEditItem) || [ ];
 },
 GetAdaptiveItem: function(visibleIndex, getDataItem, isValidDataItem, getInlineEditItem) {
  if(this.IsGroupRow(visibleIndex))
   return null;
  var item = getDataItem(visibleIndex);
  if(isValidDataItem(item))
   return item;
  if(this.IsInlineEditMode())
   return getInlineEditItem();
  return null;
 },
 GetAdaptiveDetailRow: function(visibleIndex, forceCreate) {
  var row = this.GetChildElement(GridViewConsts.AdaptiveDetailRowID + visibleIndex);
  if(!row && forceCreate) {
   var sampleRow = this.GetSampleAdaptiveDetailRow();
   var dataRow = null;
   if(this.HasBandedDataRows()){
    var bandedRows = this.GetBandedAdaptiveDataRows(visibleIndex);
    if(bandedRows.length)
     dataRow = bandedRows[bandedRows.length - 1];
   } else {
    dataRow = this.GetAdaptiveDataRow(visibleIndex);
   }
   if(sampleRow && dataRow) {
    row = sampleRow.cloneNode(true);
    row.id = this.name + "_" + GridViewConsts.AdaptiveDetailRowID + visibleIndex;
    this.GetLastNonAdaptiveIndentCell(row).originalColSpan = this.GetLastNonAdaptiveIndentCell(sampleRow).originalColSpan;
    this.EnsureAdaptiveDetailRowStyle(row, dataRow);
    ASPx.InsertElementAfter(row, dataRow);
    for(var i = 0; i < this.indentColumnCount; i++)
     row.cells[i].style.borderBottomWidth = dataRow.cells[i].style.borderBottomWidth;
   }
  }
  return row;
 },
 GetAdaptiveInlineEditRow: function() {
  if(!this.IsInlineEditMode() || !this.HasAdaptivity())
   return null;
  return this.GetAdaptiveDetailRow(this.editItemVisibleIndex);
 },
 GetAdaptiveHeaderContainer: function(columnIndex, adaptivePanel) { 
  if(!adaptivePanel) return null;
  var isGroupHeader = adaptivePanel === this.GetAdaptiveGroupPanel();
  var headerID = this.GetAdaptiveHeaderID(columnIndex, isGroupHeader);
  var adaptiveHeader = document.getElementById(headerID);
  if(!adaptiveHeader)
   adaptiveHeader = this.CreateAdaptiveHeader(adaptivePanel, headerID, isGroupHeader);
  return adaptiveHeader.dxHeaderContainer;
 },
 GetAdaptiveHeaderID: function(columnIndex, isGroupHeader) {
  return this.name + "_" + (isGroupHeader ? GridViewConsts.AdaptiveGroupHeaderID : GridViewConsts.AdaptiveHeaderID) + columnIndex;
 },
 CreateAdaptiveHeader: function(adaptivePanel, headerID, isGroupHeader) {
  var header = this.GetSampleAdaptiveHeader(isGroupHeader).cloneNode(true);
  header.id = headerID;
  ASPx.SetElementDisplay(header, true);
  header.dxHeaderContainer = this.FindAdaptiveHeaderContainer(header);
  adaptivePanel.appendChild(header);
  return header;
 },
 FindAdaptiveHeaderContainer: function(header) {
  var table = ASPx.GetChildByTagName(header, "TABLE", 0);
  return table.rows[0];
 },
 RemoveAdaptiveHeaders: function() {
  var columnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var column = this.GetColumn(columnIndices[i]);
   var headerID = this.GetAdaptiveHeaderID(column.index, column.groupIndex > -1);
   var header = document.getElementById(headerID);
   ASPx.RemoveElement(header);
  }
 },
 GetAdaptiveGroupPanel: function() { return this.GetChildElement(GridViewConsts.AdaptiveGroupPanelID); },
 GetAdaptiveHeaderPanel: function() { return this.GetChildElement(GridViewConsts.AdaptiveHeaderPanelID); },
 GetAdaptiveFooterPanel: function() { return this.GetChildElement(GridViewConsts.AdaptiveFooterPanelID); },
 GetSampleAdaptiveHeader: function(isGroupHeader) { return this.GetChildElement(isGroupHeader ? GridViewConsts.AdaptiveGroupHeaderID : GridViewConsts.AdaptiveHeaderID); },
 IsCellAdaptiveHidden: function(cell) {
  return ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.AdaptiveHiddenCssClass);
 },
 IsAdaptiveDetailHideButton: function(button) {
  return ASPx.ElementContainsCssClass(button.GetMainElement(), ASPx.GridViewConsts.AdaptiveDetailHideButtonCssClass);
 },
 IsAdaptiveDetailShowButton: function(button) {
  return ASPx.ElementContainsCssClass(button.GetMainElement(), ASPx.GridViewConsts.AdaptiveDetailShowButtonCssClass);
 },
 GetAdaptiveCell: function(visibleIndex, columnIndex) {
  var adaptiveDetailsCell = this.GetAdaptiveDetailCell(visibleIndex, false);
  return adaptiveDetailsCell && adaptiveDetailsCell.adaptiveDetailsCells ? adaptiveDetailsCell.adaptiveDetailsCells[columnIndex] : null;
 },
 GetAdaptiveDetailCell: function(visibleIndex, forceCreate) { 
  var row = this.GetAdaptiveDetailRow(visibleIndex, forceCreate);
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetDetailButtonCell: function(visibleIndex, fromAdaptiveRow) {
  var row = fromAdaptiveRow ? this.GetAdaptiveDetailRow(visibleIndex) : this.GetAdaptiveDataRow(visibleIndex);
  return ASPx.GetChildByPartialClassName(row, GridViewConsts.DetailButtonCellCssClass);
 },
 GetGroupRow: function(visibleIndex) { 
  var element = this.GetChildElement(GridViewConsts.GroupRowID + visibleIndex);
  if(!element)
   element = this.GetExpandedGroupRow(visibleIndex);
  return element; 
 },
 GetGroupCell: function(visibleIndex) { 
  var row = this.GetGroupRow(visibleIndex);
  return row ? this.GetLastNonAdaptiveIndentCell(row) : null;
 },
 GetGroupLevel: function(visibleIndex){
  var group = this.GetGroupRow(visibleIndex);
  return group ? this.GetFooterIndentCount(group) : -1;
 },
 GetExpandedGroupRow: function(visibleIndex) { return this.GetChildElement(GridViewConsts.GroupRowID + "Exp" + visibleIndex); },
 GetGroupFooterRow: function(visibleIndex, level) { return this.GetChildElement(GridViewConsts.GroupFooterRowID + visibleIndex + this.GetBandedRowLevelPostfix(level)); },
 GetGroupFooterVisibleIndices: function() { 
  var ids = [].slice.call(this.GetMainTable().rows).map(function(row) { return row.id; });
  return this.GetGroupFooterVisibleIndicesCore(ids);
 },
 GetGroupFooterVisibleIndicesCore: function(ids) {
  var result = [ ];
  var regex = this.GetGroupFooterVisibleIndicesRegExp();
  for(var i = 0; i < ids.length; i++) {
   var matches = ids[i].match(regex);
   if(matches && matches[1]) {
    var index = parseInt(matches[1]);
    if(result.indexOf(index) === -1)
     result.push(index);
   }
  }
  return result;
 },
 GetGroupFooterVisibleIndicesRegExp: function() {
  var pattern = "^" + this.name + "_" + GridViewConsts.GroupFooterRowID + "(\\d+)(_(\\d+))?$";
  return new RegExp(pattern);
 },
 _isGroupRow: function(row) { return row.id.indexOf(GridViewConsts.GroupRowID) > -1; },
 IsHeaderRow: function(row) { return this.IsHeaderRowID(row.id); },
 IsHeaderRowID: function(id) { return id.indexOf(this.name + "_" + GridViewConsts.HeaderRowID) == 0; },
 IsEmptyHeaderID: function(id) { return id.indexOf(this.EmptyHeaderSuffix) > -1; },
 IsBandedDataRowID: function(id) {
  var pattern = new RegExp(this.name + GridViewConsts.BandedRowPattern);
  return pattern.test(id);
 },
 CreateEndlessPagingHelper: function(){
  return new ASPx.GridViewEndlessPagingHelper(this);
 },
 GetCssClassNamePrefix: function() { return "dxgv"; },
 GetFilterRow: function(level) { return this.GetChildElement(GridViewConsts.FilterRowID + this.GetBandedRowLevelPostfix(level)); },
 GetFilterCell: function(columnIndex) { return this.GetLayoutHelper().GetFilterCell(columnIndex); },
 GetDataCellIndex: function(columnIndex, visibleIndex) { 
  return this.GetLayoutHelper().GetDataCellIndex(columnIndex, visibleIndex);
 },
 GetColumnIndexByDataCell: function(dataCell) { 
  if(!dataCell) return -1;
  if(ASPx.IsExists(dataCell.columnIndex)) return dataCell.columnIndex;
  var dataRow = this.GetDataItemByChild(dataCell);
  var visibleIndex = dataRow ? this.getItemIndex(dataRow.id) : -1;
  var level = dataRow ? this.GetBandedDataRowLevelByID(dataRow.id) : -1;
  return this.GetLayoutHelper().GetColumnIndex(dataCell.cellIndex, visibleIndex, level);
 },
 GetColumnIndexByHeaderCell: function(headerCell){
  var match = headerCell.id.match(/_col(\d+)$/);
  if(match)
   return match[1];
  return -1;
 },
 GetDataItemByChild: function(element) { return ASPx.GetParent(element, this.IsDataItemElement.aspxBind(this)); },
 IsDataItemElement: function(item) {
  if(!item || !item.id) return false;
  var regex = new RegExp(GridViewConsts.DataRowPattern);
  return regex.test(item.id) || item.id.indexOf(GridViewConsts.BatchChangesViewRowID) > 0;
 },
 GetDataCell: function(visibleIndex, columnIndex) {
  return this.GetLayoutHelper().GetDataCell(visibleIndex, columnIndex);
 },
 GetDataCellByRow: function(row, columnIndex, visibleIndex){
  if(!row)
   return null;
  var cellIndex = this.GetDataCellIndex(columnIndex, visibleIndex);
  return (0 <= cellIndex && cellIndex < row.cells.length) ? row.cells[cellIndex] : null;
 },
 GetVisibleColumnIndices: function() { return this.GetColumnHelper().GetVisibleColumnIndices(); },
 GetVisibleDataColumnIndices: function() { return this.GetColumnHelper().GetVisibleDataColumnIndices(); },
 IsSingleVisibleColumnWithData: function(column) {
  var visibleDataColumnIndices = this.GetVisibleDataColumnIndices();
  if(visibleDataColumnIndices.length === 1 && visibleDataColumnIndices[0] === column.index)
   return true;
  if(column.isBand && this.GetColumnHelper().GetIsParentForAllColumns(column.index, visibleDataColumnIndices))
   return true;
  return false;
 },
 GetArmatureCells: function(columnIndex) {
  var result = [ ];
  var cellIndex = this.GetDataCellIndex(columnIndex); 
  var tableHelper = this.GetTableHelper();
  if(tableHelper) {
   if(tableHelper.GetHeaderTable()) {
    var cells = tableHelper.GetArmatureCells(tableHelper.GetHeaderTable());
    if(cells) result.push(cells[cellIndex]);
   }
   if(tableHelper.GetContentTable()) {
    var cells = tableHelper.GetArmatureCells(tableHelper.GetContentTable());
    if(cells) result.push(cells[cellIndex]);
   }
   if(tableHelper.GetFooterTable()) {
    var cells = tableHelper.GetArmatureCells(tableHelper.GetFooterTable());
    if(cells) result.push(cells[cellIndex]);
   }
  }
  else {
   var mainTable = this.GetMainTable();
   result.push(mainTable.rows[0].cells[cellIndex]);
  }
  return result;
 },
 GetDataTableAccessibilityHeaderCells: function(columnIndex) {
  var result = [ ];
  if(this.accessibilityCompliant) {
   var cellIndex = this.GetDataCellIndex(columnIndex);
   var mainTable = this.GetMainTable();
   if(ASPx.ElementHasCssClass(mainTable.rows[1], GridViewConsts.AccessibilityInvisibleRowClassName))
    result.push(mainTable.rows[1].cells[cellIndex]);
  }
  return result;
 },
 GetLastNonAdaptiveIndentCell: function(row) {
  var count = 1;
  while(count <= row.cells.length){
   var cell = row.cells[row.cells.length - count];
   if(!ASPx.ElementHasCssClass(cell, GridViewConsts.AdaptiveIndentCellCssClass) && !ASPx.ElementHasCssClass(cell, GridViewConsts.HorizontalExtraCellClassName))
    return cell;
   count++;
  }
  return null;
 },
 GetHeaderScrollContainer:function() {
  return ASPx.GetNodeByClassName(this.GetMainElement(), GridViewConsts.HeaderScrollDivContainerCssClass);
 },
 GetFooterScrollContainer:function() {
  return ASPx.GetNodeByClassName(this.GetMainElement(), GridViewConsts.FooterScrollDivContainerCssClass);
 },
 SetHeadersClientEvents: function() {
  ASPxClientGridBase.prototype.SetHeadersClientEvents.call(this);
  if(!this.AllowResizing())
   return;
  var helper = this.GetResizingHelper();
  var attachMouseMove = function(headerCell) { 
   ASPx.Evt.AttachEventToElement(headerCell, "mousemove", function(e) { helper.UpdateCursor(e, headerCell); });
  };
  this.AttachEventToHeaderCells(attachMouseMove, false);
 },
 InitializeCommandColumnHeaderLinkEvents: function () {
  var headerCommandColumnLinkSelector = [".", GridViewConsts.HeaderCellCssClass, " ", "a.dxgvCommandColumnItem"].join("");
  var headerCommandColumnLinks = this.GetMainElement().querySelectorAll(headerCommandColumnLinkSelector);
  this.PreventMouseDownHeaderLinkEvent(headerCommandColumnLinks);
 },
 GetFooterRow: function(level){
  return this.GetChildElement(GridViewConsts.FooterRowID + this.GetBandedRowLevelPostfix(level));
 },
 GetFooterCell: function(columnIndex) { return this.GetLayoutHelper().GetFooterCell(columnIndex); },
 GetUserCommandNamesForRow: function() { return ASPxClientGridBase.prototype.GetUserCommandNamesForRow().concat([ "ShowAdaptiveDetail", "HideAdaptiveDetail" ]); },
 GetItemVisibleIndexRegExp: function(dataAndGroupOnly) {
  var idParts = [ GridViewConsts.DataRowID, GridViewConsts.GroupRowID + "(?:Exp)?", GridViewConsts.AdaptiveDetailRowID ];
  if(!dataAndGroupOnly) {
   idParts.push(GridViewConsts.PreviewRowID);
   idParts.push(GridViewConsts.DetailRowID);
  }
  return this.GetItemVisibleIndexRegExpByIdParts(idParts);
 },
 IsMainTableChildElement: function(src) {
  if(!src) return true;
  var tables = [ this.GetMainTable() ];
  var tableHelper = this.GetTableHelper();
  if(tableHelper) {
   tables.push(tableHelper.GetHeaderTable());
   tables.push(tableHelper.GetFooterTable());
  }
  for(var i = 0; i < tables.length; i++) {
   if(ASPx.GetIsParent(tables[i], src))
    return true;
  }
  return false;
 },
 CreateBatchEditApi: function() { return new ASPxClientGridViewBatchEditApi(this); },
 IsVirtualScrolling: function() { return this.virtualScrollMode > 0; },
 IsVirtualSmoothScrolling: function() { return this.virtualScrollMode === 2; },
 SetData: function(data){
  if(data.adaptiveModeInfo)
   this.SetAdaptiveMode(data.adaptiveModeInfo);
 },
 CreateColumn: function(prop) { return new ASPxClientGridViewColumn(prop); },
 InitializeBubbleEvents: function() {
  ASPxClientGridBase.prototype.InitializeBubbleEvents.call(this);
  this.AttachHeaderTableClickEvents();
 },
 AttachHeaderTableClickEvents: function() {
  var tableHelper = this.GetTableHelper();
  if(!tableHelper)
   return;
  var headerTable = tableHelper.GetHeaderTable();
  if(headerTable)
   this.AttachTableClickEvents(headerTable);
 },
 InlineInitialize: function() {
  ASPxClientGridBase.prototype.InlineInitialize.call(this);
  this.UpdateAdjustmentFlags();
  this.GetColumnAdjustor().Initialize();
 },
 Initialize: function() {
  ASPxClientGridBase.prototype.Initialize.call(this);
  this.ResetStretchedColumnWidth();
  this.PrepareEditorsToKeyboardNavigation();
  this.AttachInternalContexMenuEventHandler();
  this.InitializeDropDownElementsScrolling();
  this.SetFixedColumnScrollableRows();
  this.PrepareFixedGroups();
  var resizingHelper = this.GetResizingHelper();
  if(resizingHelper)
   resizingHelper.Initialize();
  var custDialogHelper = this.GetCustDialogHelper();
  if(custDialogHelper)
   custDialogHelper.OnInit();
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.OnInitialize();
 },
 AfterInitialize: function() {
  if(this.HasAdaptivityAdjuster())
   this.GetAdaptivityAdjuster().CollapseMasterGridIfNeed(this);
  ASPxClientControl.prototype.AfterInitialize.call(this);
 },
 PrepareFixedGroups: function() {
  var helper = this.GetFixedGroupsHelper();
  if(helper)
   helper.Initialize();
 },
 InitializeDropDownElementsScrolling: function() {
  if(this.HasVertScroll()) {
   this.ScrollableContainerDropDownEditors = null;
   var vertScrollableControl = this.GetScrollHelper().GetVertScrollableControl();
   ASPx.Evt.AttachEventToElement(vertScrollableControl, "scroll", function(evt) {
    if(ASPx.Evt.GetEventSource(evt) === vertScrollableControl)
     this.AdjustDropDownElements();
   }.aspxBind(this));
  }
 },
 OnChildControlEndCallback: function(childControl) {
  this.InitializeCommandButtonsInContainer(childControl.getActualMainElement());
  var helper = this.GetBatchEditHelper();
  if(helper)
   helper.OnChildControlEndCallback(childControl);
 },
 InitializeCommandButtonsInContainer: function(container) {
  var buttons = container.querySelectorAll("*[id*=_" + GridViewConsts.CommandButtonID + "].dxbButtonSys." + GridViewConsts.CommandButtonTemplateReplacementMarkerCssClass);
  this.cButtonIDs = ASPx.NodeListToArray(buttons).filter(function(el) { return !el.cpGVCommandButtonInitialized; }).map(function(el) { return el.id; });
  this.PrepareCommandButtons();
 },
 AttachInternalContexMenuEventHandler: function() {
  if(this.IsDetailGrid()) {
   ASPx.Evt.AttachEventToElement(this.GetMainElement(), "contextmenu", function(e) {
    var showDefaultMenu = ASPx.EventStorage.getInstance().Load(e);
    if(showDefaultMenu)
     ASPx.Evt.CancelBubble(e);
    else 
     ASPx.EventStorage.getInstance().Save(e, true);
   }.aspxBind(this), true);
  }
 },
 AdjustControlCore: function() {
  this.CalculateAdaptivity();
  ASPxClientGridBase.prototype.AdjustControlCore.call(this);
  this.GetColumnAdjustor().TryAdjustColumns();
  this.UpdateIndentCellWidths();
  this.ValidateColumnWidths();
  this.UpdateFixedColumnsFrozenRowWidths();
  if(this.fixedGroupsHelper)
   this.fixedGroupsHelper.UpdateIntervalHeights();
 },
 IsAdjustmentRequired: function() {
  if(ASPxClientControl.prototype.IsAdjustmentRequired.call(this))
   return true;
  var scrollHelper = this.GetScrollHelper();
  return scrollHelper ? scrollHelper.IsRestoreScrollPosition() : false;
 },
 SaveCallbackSettings: function() {
  ASPxClientGridBase.prototype.SaveCallbackSettings.call(this);
  var helper = this.GetFixedColumnsHelper();
  if(helper != null) helper.SaveCallbackSettings();
 },
 RestoreCallbackSettings: function() {
  this.ResetStretchedColumnWidth();
  this.SetFixedColumnScrollableRows();
  var fixedColumnsHelper = this.GetFixedColumnsHelper();
  if(fixedColumnsHelper != null)
   fixedColumnsHelper.RestoreCallbackSettings();
  this.SaveAdaptiveScrollTop();
  this.UpdateScrollableControls();
  if(fixedColumnsHelper != null)
   fixedColumnsHelper.HideColumnsRelyOnScrollPosition();
  this.UpdateIndentCellWidths();
  this.ValidateColumnWidths();
  ASPxClientGridBase.prototype.RestoreCallbackSettings.call(this);
 },
 SaveAdaptiveScrollTop: function() {
  this.adaptiveScrollTop = this.stateObject.scrollState ? this.stateObject.scrollState[1] : null;
 },
 ApplyAdaptiveScrollTop: function() {
  if(ASPx.IsExists(this.adaptiveScrollTop)) {
   this.SetVerticalScrollPosition(this.adaptiveScrollTop);
   this.adaptiveScrollTop = null;
  }
 },
 GetPopupEditFormHorzOffsetCorrection: function(popup) {
  var scrollHelper = this.GetScrollHelper();
  return scrollHelper ? scrollHelper.GetPopupEditFormHorzOffsetCorrection(popup) : 0;
 },
 UpdateIndentCellWidths: function() {
  var tableHelper = this.GetTableHelper();
  if(tableHelper)
     tableHelper.UpdateIndentCellWidths();
 },
 UpdateFixedColumnsFrozenRowWidths: function() {
  var helper = this.GetFixedColumnsHelper();
  if(helper)
   helper.UpdateFrozenRowWidths();
 },
 OnBeforeCallbackOrPostBack: function() {
  ASPxClientGridBase.prototype.OnBeforeCallbackOrPostBack.call(this);
  this.SaveControlDimensions();
 },
 OnBeforeCallback: function(command) {
  ASPxClientGridBase.prototype.OnBeforeCallback.call(this, command);
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper && this.IsVirtualScrolling())
   scrollHelper.ClearVirtualScrollTimer();
 },
 OnAfterCallback: function() {
  this.ResetAdaptivityOnCallback();
  this.GetColumnAdjustor().Initialize();
  ASPxClientGridBase.prototype.OnAfterCallback.call(this);
  var isRestoreScrollRequired = false;
  if(this.HasAdaptivityAdjuster())
   isRestoreScrollRequired = this.GetAdaptivityAdjuster().TryCalculateMasterDetailGridsAdaptivity(this);
  isRestoreScrollRequired = this.GetColumnAdjustor().TryAdjustColumns() || isRestoreScrollRequired;
  if(isRestoreScrollRequired)
   GetGridViewAdjuster().RestoreDocumentScrollPosition(true);
  this.SaveControlDimensions();
  this.GetContextMenuHelper().OnAfterCallack();
  var resizingHelper = this.GetResizingHelper();
  if(resizingHelper)
   resizingHelper.OnAfterCallback();
  var fixedGroupsHelper = this.GetFixedGroupsHelper();
  if(fixedGroupsHelper)
   fixedGroupsHelper.OnAfterCallback();
  this.PrepareEditorsToKeyboardNavigation();
  this.InitializeDropDownElementsScrolling();
  if(this.accessibilityCompliant)
   this.applyAccessibilityAttributes();
  var custDialogHelper = this.GetCustDialogHelper();
  if(custDialogHelper)
   custDialogHelper.OnAfterCallback();
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.OnAfterCallback();
 },
 PrepareEditorsToKeyboardNavigation: function() {
  if(!this.RequireEditorsKeyboardNavigation()) return;
  for(var i = 0; i < this.columns.length; i++) {
   this.AttachEventToEditor(this.columns[i].index, "GotFocus", function(s, e) { this.OnEditorGotFocus(s, e); }.aspxBind(this));
   this.AttachEventToEditor(this.columns[i].index, "KeyDown", function(s, e) { this.OnEditorKeyDown(s, e); }.aspxBind(this));
  }
 },
 RequireEditorsKeyboardNavigation: function() {
  return this.GetFixedColumnsHelper() && (this.IsInlineEditMode() || this.IsEditFormEditMode());
 },
 OnEditorGotFocus: function(s, e) {
  if(!this.RequireEditorsKeyboardNavigation()) return;
  this.TryMakeNeighborEditorVisible(s);
 },
 OnEditorKeyDown: function(s, e) {
  if(!this.RequireEditorsKeyboardNavigation()) return;
  var keyCode = ASPx.Evt.GetKeyCode(e.htmlEvent);
  if(keyCode !== ASPx.Key.Tab) return;
  var neighborEditor = this.GetNeighborEditor(s, e.htmlEvent.shiftKey);
  if(neighborEditor && this.TryMakeNeighborEditorVisible(neighborEditor)) {
   ASPx.Evt.PreventEventAndBubble(e.htmlEvent);
   ASPx.Selection.SetCaretPosition(s.GetInputElement());
   neighborEditor.Focus();
  }
 },
 GetNeighborEditor: function(editor, left) {
  var neighborEditor = null;
  if(this.IsEditFormEditMode()) {
   var neighborEditorIndex = this.editorIDList.indexOf(editor.name) + (left ? -1 : 1);
   var neighborEditorName = this.editorIDList[neighborEditorIndex];
   neighborEditor = ASPx.GetControlCollection().GetByName(neighborEditorName);
  } else {
   var matrix = this.GetHeaderMatrix();
   var neighborColumnIndex = left ? matrix.GetLeftNeighbor(editor.dxgvColumnIndex, true) : matrix.GetRightNeighbor(editor.dxgvColumnIndex, true);
   neighborEditor = this.GetEditorByColumnIndex(neighborColumnIndex);
  }
  return neighborEditor;
 },
 TryMakeNeighborEditorVisible: function(editor) {
  var helper = this.GetFixedColumnsHelper();
  if(this.IsEditFormEditMode())
   return helper.TryScrollToFocusedEditor(editor);
  var columnIndex = this.tryGetNumberFromEndOfString(editor.name).value;
  return helper.TryShowColumn(columnIndex, true);
 },
 IsInlineEditMode: function() { return this.editMode === 0; },
 IsEditFormEditMode: function() { return this.editMode === 1 || this.editMode === 2; },
 IsBatchEditMode: function() { return this.editMode === 4; },
 IsEditRowHasDisplayedDataRow: function() { return this.editMode >= 2; },
 IsBatchEditDeletedItem: function (visibleIndex) {
  if(this.IsGroupRow(visibleIndex))
   return false;
  return ASPxClientGridBase.prototype.IsBatchEditDeletedItem.call(this, visibleIndex);
 },
 canSortByColumn: function(headerElement) {
  if(this.IsBatchChangesViewMode())
   return false;
  return ASPxClientGridBase.prototype.canSortByColumn.call(this,headerElement);
 },
 canGroupByColumn: function(column) {
  return !this.IsBatchChangesViewMode()
   && column.allowGroup
   && this.GetVisibleDataColumnIndices().length > 0 
   && !this.IsSingleVisibleColumnWithData(column);
 },
 canHideColumn: function(column) {
  return this.GetColumnHelper().GetGroupColumnCount() === 0 || !this.IsSingleVisibleColumnWithData(column);
 },
 canDragColumn: function(headerElement) {
  if(this.IsBatchChangesViewMode() && !this.GetColumnMovingHelper())
   return false;
  var column = this._getColumnObjectByArg(this.getColumnIndex(headerElement.id));
  return !this.RaiseColumnStartDragging(column) && this.getColumnObject(headerElement.id).allowDrag;
 },
 doPagerOnClick: function(id) {
  if(!ASPx.IsExists(id)) return;
  this.AssignSlideAnimationDirectionByPagerArgument(id, this.pageIndex);
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.ResetScrollTop();
  ASPxClientGridBase.prototype.doPagerOnClick.call(this, id);
 },
 TryStartColumnResizing: function(e, headerCell) {
  var helper = this.GetResizingHelper();
  if(!helper || !helper.CanStartResizing(e, headerCell))
   return false;
  var columnIndex = helper.GetResizingColumnIndex(e, headerCell);
  var column = this.columns.filter(function(c) { return c.index == columnIndex; })[0];
  if(this.RaiseColumnResizing(column))
   return false;
  helper.StartResizing(column.index);
  return true;
 },
 IsPossibleSelectItem: function(visibleIndex, newSelectedValue){  
  if(!this.IsDataRow(visibleIndex) || !ASPxClientGridBase.prototype.IsPossibleSelectItem.call(this, visibleIndex, newSelectedValue))
   return false;
  return !this.IsRowHiddenInBatchChangesPreviewMode(visibleIndex);
 },
 _isRowSelected: function(visibleIndex) {
  return this.IsDataRow(visibleIndex) && ASPxClientGridBase.prototype._isRowSelected.call(this, visibleIndex);
 },
 GetDataItemCountOnPage: function(){
  var dataRowCount = 0;
  for(var i = 0; i < this.pageRowCount; i++){
   var index = i + this.visibleStartIndex;
   if(!this.IsGroupRow(index))
    dataRowCount++;
  }
  return dataRowCount;
 },
 RequireProcessTableClickLikeCheckBoxClick: function(tableClickSource, visibleIndex) { 
  var dataCell = this.GetLayoutHelper().GetDataCellByChild(tableClickSource);
  if(dataCell) {
   var column = this.GetColumn(this.GetColumnIndexByDataCell(dataCell));
   if(column && column.isCommandColumn) {
    var checkBoxElement = this.GetDataRowSelBtn(visibleIndex);
    return checkBoxElement && ASPx.GetIsParent(dataCell, checkBoxElement);
   }
  }
  return false; 
 },
 IsPossibleFocusItem: function(visibleIndex) { 
  if(!ASPxClientGridBase.prototype.IsPossibleFocusItem.call(this, visibleIndex))
   return false;
  return !this.IsRowHiddenInBatchChangesPreviewMode(visibleIndex);
 },
 IsRowHiddenInBatchChangesPreviewMode: function(visibleIndex) { return this.IsBatchChangesViewMode() && !this.batchEditApi.HasChanges(visibleIndex); },
 GetFocusedItemStyle: function(visibleIndex, focused){
  var row = this.GetItem(visibleIndex);
  if(focused && row) {
   var helper = this.GetStyleHelper();
   return this._isGroupRow(row) ? helper.GetFocusedGroupItemStyle() : helper.GetFocusedItemStyle();
  }
  return ASPxClientGridBase.prototype.GetFocusedItemStyle.call(this, visibleIndex, focused);
 },
 RequireChangeItemStyle: function(visibleIndex, itemStyle){
  if(!ASPxClientGridBase.prototype.RequireChangeItemStyle.call(this, visibleIndex, itemStyle))
   return false;
  var helper = this.GetStyleHelper();
  return !helper.IsSelectedItemStyle(itemStyle) || !this.IsGroupRow(visibleIndex); 
 },
 UpdateItemsStyle: function() {
  this.UpdateFirstAndLastVisibleRowMarkers();
  ASPxClientGridBase.prototype.UpdateItemsStyle.call(this);
 },
 GetItemStyle: function(visibleIndex){
  var style = ASPxClientGridBase.prototype.GetItemStyle.call(this, visibleIndex);
  var helper = this.GetStyleHelper();
  if(helper.IsFocusedItemStyle(style) && this.IsGroupRow(visibleIndex))
   style = helper.GetFocusedGroupItemStyle();
  return style;
 },
 ApplyItemStyle: function(visibleIndex, styleInfo) {
  if(this.HasBandedDataRows() && !this.IsGroupRow(visibleIndex)){
   var rows = this.GetBandedDataRows(visibleIndex);
   for(var i = 0; i < rows.length; i++)
    this.ApplyElementStyle(rows[i], styleInfo);
  } else
   ASPxClientGridBase.prototype.ApplyItemStyle.call(this, visibleIndex, styleInfo);
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper && !adaptivityHelper.IsResponsiveMode()) {
   if(adaptivityHelper.HasAnyAdaptiveElement() && !this.IsGroupRow(visibleIndex)) {
    var dataRows = this.HasBandedDataRows() ? this.GetBandedAdaptiveDataRows(visibleIndex) : [this.GetDataRow(visibleIndex)];
    var hideRow = function(row) { if(row) ASPx.AddClassNameToElement(row, GridViewConsts.AdaptiveHiddenCssClass); };
    dataRows.forEach(hideRow);
   }
   var adaptiveItem = this.GetAdaptiveDetailRow(visibleIndex);
   if(adaptiveItem) {
    ASPx.Attr.SaveStyleAttribute(adaptiveItem, "display");
    this.ApplyElementStyle(adaptiveItem, styleInfo);
    ASPx.Attr.RestoreStyleAttribute(adaptiveItem, "display");
   }
  }
 },
 EnsureAdaptiveDetailRowStyle: function(adaptiveRow, dataRow) {
  if(this.GetAdaptivityHelper().IsResponsiveMode()) 
   return;
  var visibleIndex = this.getItemIndex(dataRow.id);
  this.ApplyItemStyle(visibleIndex, this.GetStyleHelper().GetClearItemStyle());
  var exceptions = [ GridViewConsts.DataRowCssClass, GridViewConsts.AdaptiveHiddenCssClass, GridViewConsts.FirstVisibleRowClassName, GridViewConsts.LastVisibleRowClassName ];
  var classNames = ASPx.GetClassNameList(dataRow);
  classNames = classNames.filter(function(name) { 
   for(var i = 0; i < exceptions.length; i++) {
    if(exceptions[i].indexOf(name) > -1)
     return false;
   }
   return true; 
  });
  for(var i = 0; i < classNames.length; i++)
   ASPx.AddClassNameToElement(adaptiveRow, classNames[i]);
  adaptiveRow.style.cssText = dataRow.style.cssText + " " + adaptiveRow.style.cssText;
  this.UpdateItemStyle(visibleIndex);
 },
 OnScroll: function(evt){
 },
 getItemByHtmlEvent: function(evt) {
  return this.getItemByHtmlEventCore(evt, GridViewConsts.DataRowID) || this.getItemByHtmlEventCore(evt, GridViewConsts.GroupRowID) || this.getItemByHtmlEventCore(evt, GridViewConsts.AdaptiveDetailRowID);
 },
 IsHeaderChild: function(source) {
  if(!this.showColumnHeaders) return false;
  var headerRowCount = this.GetHeaderMatrix().GetRowCount();
  for(var i = 0; i < headerRowCount; i++) {
   if(ASPx.GetIsParent(this.GetHeaderRow(i), source))
    return true;
  }
  return false;
 },
 IsActionElement: function(mainElement, source) {
  if(this.testActionElement(source))
   return true;
  var parent = source;
  var controlCollection = ASPx.GetControlCollection();
  while(parent.id !== mainElement.id) {
   var control = controlCollection.Get(parent.id);
   if(this.IsActionClientControl(control))
    return true;
   parent = parent.parentElement;
  }  
  return false;
 },
 IsActionClientControl: function(control) {
  if(!ASPx.IsExists(control)) return false;
  var isClientButton = typeof(ASPxClientButton) !== "undefined" && control instanceof ASPxClientButton;
  var isClientEditBase = typeof(ASPxClientEditBase) !== "undefined" && control instanceof ASPxClientEditBase;
  return isClientButton || isClientEditBase;
 },
 IsDetailGridFocused: function(evt) {
  var result = false;
  var mainTable = this.GetMainTable();
  var target = ASPx.Evt.GetEventSource(evt);  
  ASPx.GetControlCollection().ForEachControl(function(control) {   
   var isDetailGrid = control instanceof ASPxClientGridView && control !== this && ASPx.GetIsParent(mainTable, control.GetMainElement());
   if(isDetailGrid) {
    var helper = control.GetCellFocusHelper();
    if(helper && ASPx.GetIsParent(helper.GetCurrentFocusedCell(), target)) {
     result = true;
     return true;
    }
   }
  }, this);
  return result;
 },
 IsMasterGridFor: function(detailGrid) {
  return ASPx.GetIsParent(this.GetMainTable(), detailGrid.GetMainElement());
 },
 NeedPreventGestures: function(element, mainElement) {
  var gridElement = ASPx.GetParent(element, function(el) { return ASPx.GetControlCollection().GetByName(el.id) instanceof ASPxClientGridView; });
  if(gridElement !== this.GetMainElement())
   return true;
  return ASPxClientGridBase.prototype.NeedPreventGestures.call(this, element, mainElement);
 },
 getItemIndex: function(rowId) {
  if(this.IsHeaderRowID(rowId))
   return -1;
  if(this.IsBandedDataRowID(rowId))
   return this.GetBandedDataRowVisibleIndexByID(rowId);
  return ASPxClientGridBase.prototype.getItemIndex.call(this, rowId);
 },
 GetBandedDataRowLevelByID: function(rowId){
  if(!rowId) return -1;
  var matches = rowId.match(this.name + GridViewConsts.BandedRowPattern);
  return matches && matches.length > 2 ? parseInt(matches[2]) : -1;
 },
 GetBandedDataRowVisibleIndexByID: function(rowId){
  if(!rowId) return -1;
  var matches = rowId.match(this.name + GridViewConsts.BandedRowPattern);
  return matches && matches.length > 2 ? parseInt(matches[1]) : -1;
 },
 CreateBatchEditHelperOwner: function() { return new ASPx.GridViewBatchEditHelperOwner(this); },
 CreateCellFocusHelper: function() { return new ASPx.GridViewCellFocusHelper(this); },
 CreateCellSelectionHelper: function() { return new ASPx.GridViewCellSelectionHelper(this); },
 CreateClipboardHelper: function() { return new ASPx.GridViewClipboardHelper(this); },
 CreateStyleHelper: function() { return new GridViewStyleHelper(this); },
 GetColumnHelper: function() {
  if(!this.columnHelper)
   this.columnHelper = new ASPx.GridViewColumnHelper(this);
  return this.columnHelper;
 },
 GetColumnMovingHelper: function() {
  if(!this.allowColumnClientMove) return;
  if(!this.columnMovingHelper && typeof(ASPx.GridViewColumnMovingHelper) != "undefined")
   this.columnMovingHelper = new ASPx.GridViewColumnMovingHelper(this);
  return this.columnMovingHelper;
 },
 GetTableHelper: function() {
  if(!this.tableHelper)
   this.tableHelper = this.CreateTableHelper(this.MainTableID, GridViewConsts.HeaderTableID, GridViewConsts.FooterTableID, this.horzScroll, this.vertScroll);
  return this.tableHelper;
 },
 CreateTableHelper: function(contentTableIDSuffix, headerTableIDSuffix, footerTableIDSuffix, horzScroll, vertScroll) {
  if(typeof(ASPx.GridViewTableHelper) != "undefined")
   return new ASPx.GridViewTableHelper(this, contentTableIDSuffix, headerTableIDSuffix, footerTableIDSuffix, horzScroll, vertScroll);
 },
 GetScrollHelper: function() {
  if(!this.HasScrolling()) return null;
  if(!this.scrollableHelper)
   this.scrollableHelper = new ASPx.GridViewTableScrollHelper(this.GetTableHelper());
  return this.scrollableHelper;
 },
 GetFixedColumnsHelper: function() {
  if(!this.GetFixedColumnsDiv()) return null;
  if(!this.fixedColumnsHelper)
   this.fixedColumnsHelper = new ASPx.GridViewTableFixedColumnsHelper(this.GetTableHelper(), this.FixedColumnsDivID, this.FixedColumnsContentDivID, this.fixedColumnCount);
  return this.fixedColumnsHelper;
 },
 GetFixedGroupsHelper: function() {
  if(!this.allowFixedGroups) return null;
  if(!this.fixedGroupsHelper)
   this.fixedGroupsHelper = new ASPx.GridViewFixedGroupsHelper(this.GetTableHelper());
  return this.fixedGroupsHelper;
 },
 GetResizingHelper: function() {
  if(!this.AllowResizing()) return null;
  if(!this.resizingHelper)
   this.resizingHelper = new ASPx.GridViewTableResizingHelper(this.GetTableHelper());
  return this.resizingHelper;
 },
 GetHeaderMatrix: function() {
  if(!this.headerMatrix)
   this.headerMatrix = new GridViewHeaderMatrix(this);
  return this.headerMatrix;
 },
 GetContextMenuHelper: function() {
  if(!this.contextMenuHelper)
   this.contextMenuHelper = this.CreateContextMenuHelper();
  return this.contextMenuHelper;
 },
 CreateContextMenuHelper: function() { return new ASPx.GridViewContextMenuHelper(this); },
 CreateLayoutHelper: function() { return new ASPx.GridViewLayoutHelper(this); },
 CreateNavigationHelper: function() { return typeof(ASPx.GridViewNavigationHelper) != "undefined" ? new ASPx.GridViewNavigationHelper(this) : null; },
 CreateFilterHelper: function() { return new ASPx.GridViewFilterHelper(this); },
 CreateCallbackHelper: function() { return new GridViewCallbackHelper(this); },
 CreateToolbarHelper: function() { return new ASPx.GridViewToolbarHelper(this); },
 CreateKbdHelper: function() {
  if(this.enableKeyboard && this.customKbdHelperName)
   return new ASPx[this.customKbdHelperName](this);
  return new GridViewKbdHelper(this, this.enableKeyboard);
 },
 IsKbdHelperRequired: function() {
  return this.enableKeyboard || ASPxClientGridBase.prototype.IsKbdHelperRequired.call(this);
 },
 Invalidate: function() {
  this.GetColumnHelper().Invalidate();
  this.GetHeaderMatrix().Invalidate();
  ASPxClientGridBase.prototype.Invalidate.call(this);
 },
 ValidateColumnWidths: function() {
  var helper = this.GetResizingHelper();
  if(helper)
   helper.ValidateColumnWidths();
 },
 ResetStretchedColumnWidth: function() {
  var helper = this.GetResizingHelper();
  if(helper)
   helper.ResetStretchedColumnWidth();
 },
 SaveControlDimensions: function() {
  var helper = this.GetResizingHelper();
  if(helper)
   helper.SaveControlDimensions(true);
 },
 AdjustDropDownElements: function() {
  var vertScrollableControl = this.GetScrollHelper().GetVertScrollableControl();
  var scrollableRect = vertScrollableControl.getBoundingClientRect();
  ASPx.Data.ForEach(this.GetDropDownEditors(), function(dropDownEditor) {
   if(!ASPx.IsExists(dropDownEditor))
    return;
   var editorRect = dropDownEditor.GetMainElement().getBoundingClientRect();
   var editorBottomIsVisible = editorRect.top + editorRect.height < scrollableRect.bottom
    && editorRect.top + editorRect.height > scrollableRect.top;
   if(dropDownEditor.GetPopupControl().IsVisible())
    if(editorBottomIsVisible)
     dropDownEditor.AdjustDropDownWindow();
    else
     dropDownEditor.HideDropDown();
  });
 },
 GetDropDownEditors: function() {
  if(this.ScrollableContainerDropDownEditors === null) {
   var dropDownEditorPopupElementPostfixRegex = /_DDD_PW-\d+$/g;
   var controlCollection = ASPx.GetControlCollection();
   var vertScrollableControl = this.GetScrollHelper().GetVertScrollableControl();
   var popupElements = ASPx.GetNodesByClassName(vertScrollableControl, "dxpc-ddSys")
    .filter(function(element) { return element.id.match(dropDownEditorPopupElementPostfixRegex); });
   var editorNames = popupElements.map(function(element) { return element.id.replace(dropDownEditorPopupElementPostfixRegex, ""); });
   this.ScrollableContainerDropDownEditors = editorNames.map(controlCollection.GetByName.aspxBind(controlCollection));
  }
  return this.ScrollableContainerDropDownEditors;
 },
 BrowserWindowResizeSubscriber: function() {
  return this.IsFixedLayoutWithUnsetWidth() || this.enableCustDialog || ASPxClientGridBase.prototype.BrowserWindowResizeSubscriber.call(this);
 }, 
 IsFixedLayoutWithUnsetWidth: function() {
  var mainElement = this.GetMainElement();
  var mainTable = this.GetMainTable();
  if(mainElement && mainTable) {
   var mainElementStyle = ASPx.GetCurrentStyle(mainElement);
   var mainTableStyle = ASPx.GetCurrentStyle(mainTable);
   return mainTableStyle.tableLayout === "fixed" && mainElementStyle.width === "";
  }
 }, 
 OnBrowserWindowResize: function(e) {
  this.EndBatchEdit(e);
  if(this.AllowResizing() && !this.HasScrolling())
   this.ValidateColumnWidths();
  var custDialogHelper = this.GetCustDialogHelper();
  if(custDialogHelper)
   custDialogHelper.OnBrowserWindowResize(e);
  var fixedGroupsHelper = this.GetFixedGroupsHelper();
  if(fixedGroupsHelper)
   fixedGroupsHelper.OnBrowserWindowResize(e);
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.OnBrowserWindowResize(e);
  if(!e || !e.virtualKeyboardShownOnAndroid)
   this.AdjustControl();
 },
 ShowCustomizationDialog: function() {
  var window = this.GetCustDialogWindow();
  if(window)
   window.Show();
 },
 EndBatchEdit: function(e){ 
  var batchEditHelper = this.GetBatchEditHelper();
  if(this.HasAdaptivity() && batchEditHelper && e.prevWndWidth != e.wndWidth)
   batchEditHelper.EndEdit();
 },
 GetColumnAdjustor: function() {
  if(!this.columnAdjustor)
   this.columnAdjustor = this.CreateColumnAdjustor();
  return this.columnAdjustor;
 },
 CreateColumnAdjustor: function() {
  return new ASPx.GridViewColumnAdjustor(this);
 },
 GetAdaptivityHelper: function() {
  if(this.adaptivityMode === 0) return null;
  if(!this.adaptivityHelper)
   this.adaptivityHelper = this.CreateAdaptivityHelper();
  return this.adaptivityHelper;
 },
 HasAdaptivity: function() { return !!this.GetAdaptivityHelper(); },
 HasAnyAdaptiveElement: function() { 
  var helper = this.GetAdaptivityHelper();
  return helper && helper.HasAnyAdaptiveElement();
 },
 CreateAdaptivityHelper: function() {
  if(this.adaptivityMode === 1) {
   return this.GetLayoutHelper().IsFixedTableLayout()
    ? this.CreateFixedTableLayoutAdaptivityHelper()
    : this.CreateAutoTableLayoutAdaptivityHelper();
  }
  else if(this.adaptivityMode === 2)
   return this.CreateAdaptiveModeAdaptivityHelper();
  throw "Incorrect adaptivity mode.";
 },
 CreateFixedTableLayoutAdaptivityHelper: function() {
  return new ASPx.GridViewFixedTableLayoutAdaptivityHelper(this);
 },
 CreateAutoTableLayoutAdaptivityHelper: function() {
  return new ASPx.GridViewAutoTableLayoutAdaptivityHelper(this);
 },
 CreateAdaptiveModeAdaptivityHelper: function() {
  return new ASPx.GridViewAdaptiveModeAdaptivityHelper(this);
 },
 SetAdaptiveMode: function(data) {
  this.adaptivityMode = data.adaptivityMode;
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.ApplySettings(data);
 },
 IsResponsiveAdaptivityMode: function() {
  var adaptivityHelper = this.GetAdaptivityHelper();
  return adaptivityHelper && adaptivityHelper.IsResponsiveMode();
 },
 HasAdaptivityAdjuster: function() {
  return !!this.GetAdaptivityAdjuster();
 },
 GetAdaptivityAdjuster: function() {
  if(ASPx.GetGridViewAdaptivityAdjuster)
   return ASPx.GetGridViewAdaptivityAdjuster();
  return null;
 },
 CalculateAdaptivity: function(forceCalculate) {
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.CalculateAdaptivity(forceCalculate);
 },
 ResetAdaptivityOnCallback: function(){
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.ResetAdaptivityOnCallback();
 },
 RestoreAdaptivityState: function() {
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.RestoreAdaptivityState();
 },
 ToggleAdaptiveDetails: function(visibleIndex) {
  var adaptivityHelper = this.GetAdaptivityHelper();
  if(adaptivityHelper) {
   adaptivityHelper.ToggleAdaptiveDetails(visibleIndex, false, true);
   this.InvalidateLayout();
  }
 },
 UA_ShowAdaptiveDetail: function(visibleIndex) {
  this.ToggleAdaptiveDetails(visibleIndex);
 },
 UA_HideAdaptiveDetail: function(visibleIndex) {
  this.ToggleAdaptiveDetails(visibleIndex);
 },
 UA_ApplyMultiColumnAutoFilter: function() {
  this.ApplyOnClickRowFilter();
 },
 UA_CustDialogApply: function() {
  var helper = this.GetCustDialogHelper();
  if(helper)
   helper.ApplyChanges();
 },
 UA_CustDialogClose: function() {
  var helper = this.GetCustDialogHelper();
  if(helper)
   helper.CancelChanges();
 },
 UA_PreviewChanges: function() {
  var helper = this.GetBatchEditHelper();
  if(helper)
   helper.ShowPreviewChanges();
 },
 UA_HidePreview: function() {
  var helper = this.GetBatchEditHelper();
  if(helper)
   helper.HideChanges();
 },
 IsLastDataRow: function(visibleIndex) {
  return visibleIndex == this.visibleStartIndex + this.pageRowCount - 1 && (this.IsLastPage() || this.pageIndex < 0);
 },
 UpdateFirstAndLastVisibleRowMarkers: function() {
  if(this.HasBandedDataRows())
   return;
  if(!this.GetHeaderRow(0))
   this.UpdateExtemeVisibleRowMarker(true);
  this.UpdateExtemeVisibleRowMarker(false);
 },
 UpdateExtemeVisibleRowMarker: function(isFirstVisibleRow) {
  var tBody = ASPx.GetNodeByTagName(this.GetMainTable(), "TBODY", 0);
  var markerClassName = isFirstVisibleRow ? GridViewConsts.FirstVisibleRowClassName : GridViewConsts.LastVisibleRowClassName;
  var prevMarkedRows = ASPx.GetChildNodesByClassName(tBody, markerClassName);
  var styleHelper = this.GetStyleHelper();
  for(var i = 0; i < prevMarkedRows.length; i++) {
   styleHelper.RemoveClassFromElement(prevMarkedRows[i], markerClassName);
  }
  var exteremeRow = this.FindExtemeVisibleRow(isFirstVisibleRow);
  if(exteremeRow) {
   styleHelper.AddClassToElement(exteremeRow, markerClassName);
   if(!isFirstVisibleRow && this.GetLayoutHelper().HasCellMerging())
    this.MarkPageBottomVisibleCells(exteremeRow);
  }
 },
 MarkPageBottomVisibleCells: function(row) {
  var helper = this.GetLayoutHelper();
  var visibleIndex = this.getItemIndex(row.id);
  if(visibleIndex === -1)
   return;
  var headerLayout = helper.GetHeaderLayout()[helper.GetLayoutHeight(true) - 1];
  var headerColumnIndices = headerLayout.map(function(item) { return item.columnIndex; });
  for(var i = 0; i < headerColumnIndices.length; i++) {
   var columnIndex = headerColumnIndices[i];
   if(helper.IsHiddenMergedCell(visibleIndex, columnIndex))
    ASPx.AddClassNameToElement(this.GetDataCell(visibleIndex, columnIndex), GridViewConsts.PageBottomVisibleCellsMarkerClassName);
  }
 },
 FindExtemeVisibleRow: function(isFirstVisibleRow) {
  var rows = this.GetMainTable().rows;
  var rowCount = rows.length;
  for(var i = 0; i < rowCount; i++) {
   var row = isFirstVisibleRow ? rows[i] : rows[rowCount - 1 - i];
   if(this.IsVisibleRow(row))
    return row;
  }
  return this.GetEmptyDataItem();
 },
 IsVisibleRow: function(row) {
  var isDataRow = this.GetItemVisibleIndexRegExp(false).test(row.id);
  var isEditingRow = row.id && row.id.indexOf(this.EditingRowID) > -1;
  var isGroupFooterRow = !!row.id.match(this.GetGroupFooterVisibleIndicesRegExp());
  return ASPx.ElementContainsCssClass(row, GridViewConsts.EmptyPagerRowCssClass) || ((isDataRow || isEditingRow || isGroupFooterRow) && ASPx.GetElementDisplay(row));
 },
 OnGeneralCallback: function(result) {
  GetGridViewAdjuster().SaveDocumentScrollPosition(true);
  ASPxClientGridBase.prototype.OnGeneralCallback.call(this, result);
  if(this.hasDetailRows) {
   GetGridViewAdjuster().SetMasterGridForAdjust(this);
   if(this.HasAdaptivityAdjuster())
    this.GetAdaptivityAdjuster().SetNeedCollapseMasterGrid(this);
  }
 },
 OnCallbackFinalized: function() {
  ASPxClientGridBase.prototype.OnCallbackFinalized.call(this);
  this.AdjustPagerControls();
  GetGridViewAdjuster().ResetDocumentScrollPosition();
 },
 SetWidth: function(width) {
  if(this.IsControlCollapsed())
   this.ExpandControl();
  var mainElemnt = this.GetMainElement();
  if(!ASPx.IsExistsElement(mainElemnt) || mainElemnt.offsetWidth === width) return;
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.OnSetWidth(width);
  this.ResetControlAdjustment();
  ASPxClientControl.prototype.SetWidth.call(this, width);
 },
 NeedCollapseControlCore: function() {
  return this.IsResponsiveAdaptivityMode() || ASPxClientGridBase.prototype.NeedCollapseControlCore.call(this);
 },
 SortBy: function(column, sortOrder, reset, sortIndex){
    ASPxClientGridBase.prototype.SortBy.call(this, column, sortOrder, reset, sortIndex);
 },
 MoveColumn: function(column, columnMoveTo, moveBefore, moveToGroup, moveFromGroup){
  ASPxClientGridBase.prototype.MoveColumn.call(this, column, columnMoveTo, moveBefore, moveToGroup, moveFromGroup);
 },
 MoveColumnCore: function(sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup) {
  var helper = this.GetColumnMovingHelper();
  var requireCallback = !helper || !helper.MoveColumn(sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup);
  this.Invalidate();
  if(requireCallback)
   ASPxClientGridBase.prototype.MoveColumnCore.call(this, sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup);
  else {
   var adaptivityHelper = this.GetAdaptivityHelper();
   if(adaptivityHelper) {
    adaptivityHelper.ResetAdaptivity();
    this.RemoveAdaptiveHeaders();
    adaptivityHelper.CalculateAdaptivity(true);
   }
   var fixedHelper = this.GetFixedColumnsHelper();
   if(fixedHelper)
    fixedHelper.OnColumnClientMove();
   this.SaveClientColumnStateToCookies();
   this.stateObject.columnMoveState = helper.GetColumnMoveState();
  }
 },
 GetColumnLayout: function() {
  var helper = this.GetColumnMovingHelper();
  return helper ? helper.GetColumnLayout() : null;
 },
 SetColumnLayout: function(layout) {
  var helper = this.GetColumnMovingHelper();
  if(helper)
   helper.SetColumnLayout(layout);
 },
 SaveClientColumnStateToCookies: function() {
  if(!this.cookieName) return;
  var cookieValue = ASPx.Cookie.GetCookie(this.cookieName);
  if(!cookieValue) return;
  var prevClientStateIndex = cookieValue.indexOf("|clientvis");
  if(prevClientStateIndex > -1)
   cookieValue = cookieValue.substr(0, prevClientStateIndex);
  var columnHelper = this.GetColumnHelper();
  var visibleState = columnHelper.SerializeColumnVisibleState();
  var hierarchyState = columnHelper.SerializeColumnHierarchyState();
  cookieValue += "|" + hierarchyState + "|" + visibleState;
  ASPx.Cookie.SetCookie(this.cookieName, cookieValue);
 },
 GroupBy: function(column, groupIndex, sortOrder){
  ASPxClientGridBase.prototype.GroupBy.call(this, column, groupIndex, sortOrder);
 },
 UnGroup: function(column){
  this.Ungroup(column);
 },
 Ungroup: function(column){
  ASPxClientGridBase.prototype.Ungroup.call(this, column);
 },
 ExpandAll: function(){
  ASPxClientGridBase.prototype.ExpandAll.call(this);
 },
 CollapseAll: function(){
  ASPxClientGridBase.prototype.CollapseAll.call(this);
 },
 ExpandAllDetailRows: function(){
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ShowAllDetail]);
 },
 CollapseAllDetailRows: function(){
  this.gridCallBack([ASPxClientGridViewCallbackCommand.HideAllDetail]);
 },
 ExpandRow: function(visibleIndex, recursive){
  if(this.RaiseRowExpanding(visibleIndex)) return;
  recursive = !!recursive;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ExpandRow, visibleIndex, recursive]);
 },
 CollapseRow: function(visibleIndex, recursive){
  if(this.RaiseRowCollapsing(visibleIndex)) return;
  recursive = !!recursive;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.CollapseRow, visibleIndex, recursive]);
 },
 MakeRowVisible: function(visibleIndex) {
  if(!this.HasVertScroll()) return;
  var row = this.GetItem(visibleIndex);
  if(row == null && visibleIndex >= this.visibleStartIndex && visibleIndex < this.visibleStartIndex + this.pageRowCount) 
   row = this.GetEditingRow();
  if(row == null) return;
  this.GetScrollHelper().MakeRowVisible(row);
 },
 ExpandDetailRow: function(visibleIndex){
  var key = this.GetRowKey(visibleIndex);
  if(key == null) return;
  if(this.RaiseDetailRowExpanding(visibleIndex)) return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.ShowDetailRow, key]);
 },
 CollapseDetailRow: function(visibleIndex){
  var key = this.GetRowKey(visibleIndex);
  if(key == null) return;
  if(this.RaiseDetailRowCollapsing(visibleIndex)) return;
  this.gridCallBack([ASPxClientGridViewCallbackCommand.HideDetailRow, key]);
 },
 GetRowKey: function(visibleIndex) {
  return this.GetItemKey(visibleIndex);
 },
 StartEditRow: function(visibleIndex) {
    this.StartEditItem(visibleIndex);
 },
 StartEditRowByKey: function(key) {
  this.StartEditItemByKey(key);
 },
 IsNewRowEditing: function() {
  return this.IsNewItemEditing();
 },
 AddNewRow: function(){
    this.AddNewItem();
 },
 DeleteRow: function(visibleIndex){
  this.DeleteItem(visibleIndex);
 },
 DeleteRowByKey: function(key) {
  this.DeleteItemByKey(key);
 },
 GetFocusedRowIndex: function() {
  return this._getFocusedItemIndex();
 },
 SetFocusedRowIndex: function(visibleIndex) {
  return this._setFocusedItemIndex(visibleIndex);
 },
 SelectRows: function(visibleIndices, selected){
  this.SelectItemsCore(visibleIndices, selected, false);
 },
 SelectRowsByKey: function(keys, selected){
  this.SelectItemsByKey(keys, selected);
 },
 UnselectRowsByKey: function(keys){
  this.SelectRowsByKey(keys, false);
 },
 UnselectRows: function(visibleIndices){
  this.SelectRows(visibleIndices, false);
 },
 UnselectFilteredRows: function() {
  this.UnselectFilteredItemsCore();
 },
 SelectRowOnPage: function(visibleIndex, selected){
  if(!ASPx.IsExists(selected)) selected = true;
  this.SelectItem(visibleIndex, selected);
 },
 UnselectRowOnPage: function(visibleIndex){
  this.SelectRowOnPage(visibleIndex, false);
 },
 SelectAllRowsOnPage: function(selected){
  this.SelectAllItemsOnPage(selected);
 },
 UnselectAllRowsOnPage: function(){
  this.UnselectAllItemsOnPage();
 },
 GetSelectedRowCount: function() {
  return this._getSelectedRowCount();
 },
 IsRowSelectedOnPage: function(visibleIndex) {
  return this._isRowSelected(visibleIndex);
 },
 IsGroupRow: function(visibleIndex) {
  return this.GetGroupRow(visibleIndex) != null;
 },
 IsDataRow: function(visibleIndex) {
  return this.GetDataRow(visibleIndex) != null || this.HasBandedDataRows() && this.GetBandedDataRows(visibleIndex).length > 0;
 },
 IsGroupRowExpanded: function(visibleIndex) { 
  return this.GetExpandedGroupRow(visibleIndex) != null;
 },
 GetVertScrollPos: function() {
  return this.GetVerticalScrollPosition();
 },
 GetVerticalScrollPosition: function() {
  if(this.IsVirtualScrolling())
   return 0;
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   return scrollHelper.GetVertScrollPosition();
  return 0;
 },
 GetHorzScrollPos: function() {
  return this.GetHorizontalScrollPosition();
 },
 GetHorizontalScrollPosition: function() {
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   return scrollHelper.GetHorzScrollPosition();
  return 0;
 },
 SetVertScrollPos: function(value) {
  this.SetVerticalScrollPosition(value);
 },
 SetVerticalScrollPosition: function(value) {
  if(this.IsVirtualScrolling())
   return;
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.SetVertScrollPosition(value);
 },
 SetHorzScrollPos: function(value) {
  this.SetHorizontalScrollPosition(value);
 },
 SetHorizontalScrollPosition: function(value) {
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.SetHorzScrollPosition(value);
 },
 SetFixedColumnScrollableRows: function(scrollableRowSettings) {
  var helper = this.GetFixedColumnsHelper();
  if(helper)
   helper.SetFixedColumnScrollableRows(scrollableRowSettings);
 },
 ExportTo: function(format) {
  ASPxClientGridBase.prototype.ExportTo.call(this, format);
 },
 RaiseItemClick: function(visibleIndex, htmlEvent) {
  if(!this.RowClick.IsEmpty()){
   var args = new ASPxClientGridViewRowClickEventArgs(visibleIndex, htmlEvent);
   this.RowClick.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseItemDblClick: function(visibleIndex, htmlEvent) {
  if(!this.RowDblClick.IsEmpty()){
   ASPx.Selection.Clear(); 
   var args = new ASPxClientGridViewRowClickEventArgs(visibleIndex, htmlEvent);
   this.RowDblClick.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseContextMenu: function(objectType, index, htmlEvent, menu, showBrowserMenu) {
  var args = new ASPxClientGridViewContextMenuEventArgs(objectType, index, htmlEvent, menu, showBrowserMenu);
  if(!this.ContextMenu.IsEmpty())
   this.ContextMenu.FireEvent(this, args);
  return !!args.showBrowserMenu;
 },
 RaiseFocusedItemChanged: function(isChangedOnServer) {
  if(!this.FocusedRowChanged.IsEmpty()){
   var args = new ASPxClientGridViewFocusEventArgs(isChangedOnServer);
   this.FocusedRowChanged.FireEvent(this, args);
   if(args.processOnServer)
    this.gridCallBack([ASPxClientGridViewCallbackCommand.FocusedRow]);
  }
  return false; 
 },
 RaiseItemFocusing: function(visibleIndex, htmlEvent) { 
  if(!this.RowFocusing.IsEmpty()){
   var args = new ASPxClientGridViewRowFocusingEventArgs(visibleIndex, htmlEvent);
   this.RowFocusing.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseColumnStartDragging: function(column) {
  if(!this.ColumnStartDragging.IsEmpty()){
   var args = new ASPxClientGridViewColumnCancelEventArgs(column);
   this.ColumnStartDragging.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseColumnResizing: function(column) {
  if(!this.ColumnResizing.IsEmpty()){
   var args = new ASPxClientGridViewColumnCancelEventArgs(column);
   this.ColumnResizing.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseColumnResized: function(column) {
  if(!this.ColumnResized.IsEmpty()){
   var args = new ASPxClientGridViewColumnProcessingModeEventArgs(column);
   this.ColumnResized.FireEvent(this, args);
   if(args.processOnServer)
    this.Refresh();
  }
 },
 RaiseRowExpanding: function(visibleIndex) {
  if(!this.RowExpanding.IsEmpty()){
   var args = new ASPxClientGridViewRowCancelEventArgs(visibleIndex);
   this.RowExpanding.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseRowCollapsing: function(visibleIndex) {
  if(!this.RowCollapsing.IsEmpty()){
   var args = new ASPxClientGridViewRowCancelEventArgs(visibleIndex);
   this.RowCollapsing.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseDetailRowExpanding: function(visibleIndex) {
  if(!this.DetailRowExpanding.IsEmpty()){
   var args = new ASPxClientGridViewRowCancelEventArgs(visibleIndex);
   this.DetailRowExpanding.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseDetailRowCollapsing: function(visibleIndex) {
  if(!this.DetailRowCollapsing.IsEmpty()){
   var args = new ASPxClientGridViewRowCancelEventArgs(visibleIndex);
   this.DetailRowCollapsing.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseBatchEditConfirmShowing: function(requestTriggerID) {
  if(!this.BatchEditConfirmShowing.IsEmpty()) {
   var args = new ASPxClientGridViewBatchEditConfirmShowingEventArgs(requestTriggerID);
   this.BatchEditConfirmShowing.FireEvent(this, args);
   return args.cancel;
  }
  return false;
 },
 RaiseBatchEditStartEditing: function(visibleIndex, column, rowValues) {
  var args = new ASPxClientGridViewBatchEditStartEditingEventArgs(visibleIndex, column, rowValues, this.ConvertVisibleIndexToKey(visibleIndex));
  if(!this.BatchEditStartEditing.IsEmpty())
   this.BatchEditStartEditing.FireEvent(this, args);
  return args;
 },
 RaiseBatchEditEndEditing: function(visibleIndex, focusedColumn, rowValues) {
  var args = new ASPxClientGridViewBatchEditEndEditingEventArgs(visibleIndex, rowValues, this.ConvertVisibleIndexToKey(visibleIndex), focusedColumn);
  if(!this.BatchEditEndEditing.IsEmpty())
   this.BatchEditEndEditing.FireEvent(this, args);
  return args;
 },
 RaiseBatchEditItemChangesCanceling: function(visibleIndex, rowValues) {
  var args = new ASPxClientGridViewBatchEditRowChangesCancelingEventArgs(visibleIndex, rowValues, this.ConvertVisibleIndexToKey(visibleIndex));
  if(!this.BatchEditRowChangesCanceling.IsEmpty())
   this.BatchEditRowChangesCanceling.FireEvent(this, args);
  return args;
 },
 RaiseBatchEditItemValidating: function(visibleIndex, validationInfo) {
  var args = new ASPxClientGridViewBatchEditRowValidatingEventArgs(visibleIndex, validationInfo, this.ConvertVisibleIndexToKey(visibleIndex));
  if(!this.BatchEditRowValidating.IsEmpty())
   this.BatchEditRowValidating.FireEvent(this, args);
  return args.validationInfo;
 },
 RaiseBatchEditTemplateCellFocused: function(columnIndex) {
  var column = this._getColumn(columnIndex);
  if(!column) return false;
  var args = new ASPxClientGridViewBatchEditTemplateCellFocusedEventArgs(column);
  if(!this.BatchEditTemplateCellFocused.IsEmpty())
   this.BatchEditTemplateCellFocused.FireEvent(this, args);
  return args.handled;
 },
 RaiseBatchEditChangesSaving: function(valuesInfo) { 
  if(!this.BatchEditChangesSaving.IsEmpty()){
   var args = new ASPxClientGridViewBatchEditChangesSavingEventArgs(valuesInfo.insertedValues, valuesInfo.deletedValues, valuesInfo.updatedValues);
   this.BatchEditChangesSaving.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseBatchEditChangesCanceling: function(valuesInfo) { 
  if(!this.BatchEditChangesCanceling.IsEmpty()){
   var args = new ASPxClientGridViewBatchEditChangesCancelingEventArgs(valuesInfo.insertedValues, valuesInfo.deletedValues, valuesInfo.updatedValues);
   this.BatchEditChangesCanceling.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseBatchEditItemInserting: function(visibleIndex) { 
  if(!this.BatchEditRowInserting.IsEmpty()){
   var args = new ASPxClientGridViewBatchEditRowInsertingEventArgs(visibleIndex);
   this.BatchEditRowInserting.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseBatchEditItemDeleting: function(visibleIndex, itemValues) { 
  if(!this.BatchEditRowDeleting.IsEmpty()){
   var args = new ASPxClientGridViewBatchEditRowDeletingEventArgs(visibleIndex, itemValues, this.ConvertVisibleIndexToKey(visibleIndex));
   this.BatchEditRowDeleting.FireEvent(this, args);
   return args.cancel;
  }
  return false; 
 },
 RaiseBatchEditItemRecovering: function(visibleIndex, itemValues) { 
  if(!this.BatchEditRowRecovering.IsEmpty()){
   var args = new ASPxClientGridViewBatchEditRowRecoveringEventArgs(visibleIndex, itemValues, this.ConvertVisibleIndexToKey(visibleIndex));
   this.BatchEditRowRecovering.FireEvent(this, args);
   return args.cancel;
  }
  return false;
 },
 RaiseBatchEditChangesPreviewShowing: function() { 
  if(!this.BatchEditChangesPreviewShowing.IsEmpty()){
   var args = new ASPxClientCancelEventArgs();
   this.BatchEditChangesPreviewShowing.FireEvent(this, args);
   return args.cancel;
  }
  return false;
 },
 RaiseBatchEditChangesPreviewShown: function() { 
  if(!this.BatchEditChangesPreviewShown.IsEmpty()){
   var args = new ASPxClientEventArgs();
   this.BatchEditChangesPreviewShown.FireEvent(this, args);
  }
 },
 RaiseContextMenuItemClick: function(e, itemInfo) {
  if(this.ContextMenuItemClick.IsEmpty())
   return false;
  var args = new ASPxClientGridViewContextMenuItemClickEventArgs(e.item, itemInfo.objectType, itemInfo.index);
  this.ContextMenuItemClick.FireEvent(this, args);
  if(!args.handled && args.processOnServer) {
   this.GetContextMenuHelper().ProcessCustomContextMenuItemClick(args.usePostBack);
   return true;
  }
  return args.handled;
 },
 RaiseColumnMoving: function(targets) {
  if(this.ColumnMoving.IsEmpty()) return;
  var srcColumn = this.getColumnObject(targets.obj.id);
  var destColumn = this.getColumnObject(targets.targetElement.id);
  var isLeft = targets.isLeftPartOfElement();
  var isGroupPanel = targets.targetElement == targets.control.GetGroupPanel();
  var args = new ASPxClientGridViewColumnMovingEventArgs(srcColumn, destColumn, isLeft, isGroupPanel);
  this.ColumnMoving.FireEvent(this, args);
  if(!args.allow)
   targets.targetElement = null;
 },
 CreateCommandCustomButtonEventArgs: function(index, id){
  return new ASPxClientGridViewCustomButtonEventArgs(index, id);
 },
 CreateSelectionEventArgs: function(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer){
  return new ASPxClientGridViewSelectionEventArgs(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer);
 },
 CreateColumnCancelEventArgs: function(column){
  return new ASPxClientGridViewColumnCancelEventArgs(column);
 },
 CreateColumnMovingEventArgs: function(sourceColumn, destinationColumn, isDropBefore, isGroupPanel){
  return new ASPxClientGridViewColumnMovingEventArgs(sourceColumn, destinationColumn, isDropBefore, isGroupPanel);
 },
 CreateUserCellInfo: function(visibleIndex, column, key) { return new ASPxClientGridViewCellInfo(visibleIndex, column, key); },
 CreateFocusedCellChangingArgs: function(cellInfo) { return new ASPxClientGridViewFocusedCellChangingEventArgs(cellInfo); },
 CreateCellSelectionChangingArgs: function(cellInfo, newSelectionState) { return new ASPxClientGridViewCellSelectionChangingEventArgs(cellInfo, newSelectionState); },
 CreateClipboardCellPastingArgs: function(cellInfo, originalValueInfo, valueInfo) { return new ASPxClientGridViewClipboardCellPastingEventArgs(cellInfo, originalValueInfo, valueInfo); },
 GetRowValues: function(visibleIndex, fieldNames, onCallBack) {
  this.GetItemValues(visibleIndex, fieldNames, onCallBack);
 },
 GetPageRowValues: function(fieldNames, onCallBack) {
  this.GetPageItemValues(fieldNames, onCallBack);
 },
 GetVisibleRowsOnPage: function() {
  return this.GetVisibleItemsOnPage();
 }, 
 GetVisibleRowsIndicesForAdaptivity: function() {
  var batchEditHelper = this.GetBatchEditHelper();
  var currentPageIndices = this.GetCurrentPageIndices();
  if(batchEditHelper) {
   if(batchEditHelper.IsChangesViewVisible())
    return batchEditHelper.GetChangedRecordKeys().map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this));
   var indices = this.GetDataItemVisibleIndices(batchEditHelper.GetHighlightDeletedItems());
   var groupRowIndices = currentPageIndices.filter(function(index){ this.IsGroupRow(index); }.bind(this));
   return indices.concat(groupRowIndices);
  }
  if(this.IsInlineEditMode() && this.IsNewRowEditing()) 
   currentPageIndices.push(this.NewRowVisibleIndex);
  return currentPageIndices;
 },
 GetClientChangedVisibleIndices: function(includeDeleted, fromAPI) {
  var helper = this.GetBatchEditHelper();
  if(!helper) 
   return [ ];
  return helper.GetChangedRecordKeys().map(function(key) { return this.ConvertKeyToVisibleIndex(key); }.bind(this));
 },
 GetRowIndicesVisibleInViewPort: function(includePartiallyVisible) {
  var mainTable = this.GetMainTable();
  var treeLine = ASPx.GetElementTreeLine(mainTable).filter(function(element) {
   var style = ASPx.GetCurrentStyle(element);
   return style.overflow !== "visible" || style.overflowY !== "visible";
  });
  treeLine.push(mainTable);
  treeLine.push(document.body);
  var treeLineDimensions = treeLine.map(function(element) { 
   var y = ASPx.GetAbsoluteY(element);
   var height = element.tagName === "BODY" ? ASPx.GetDocumentClientHeight() : element.offsetHeight;
   return { element: element, top: y, bottom: y + height - 1 };
  });
  var mainTableViewPortTop = ASPx.Data.Max(treeLineDimensions, function(info) { return info.top; });
  var mainTableViewPortBottom = ASPx.Data.Min(treeLineDimensions, function(info) { return info.bottom; });
  var dataRowVisibleIndices = this.GetLayoutHelper().GetDataItemVisibleIndices();
  var groupRowVisibleIndices = ASPx.Data.Range(this.GetVisibleRowsOnPage(), this.GetTopVisibleIndex()).filter(function(i) { return this.IsGroupRow(i); }.bind(this));
  var dataRows = dataRowVisibleIndices.map(function(i) {   return { visibleIndex: i, row: this.GetDataRow(i) }; }.bind(this));
  var groupRows = groupRowVisibleIndices.map(function(i) { return { visibleIndex: i, row: this.GetGroupRow(i) }; }.bind(this));
  var result = dataRows.concat(groupRows).filter(function(rowInfo) {
   var rowTop = ASPx.GetAbsoluteY(rowInfo.row);
   var rowBottom = rowTop + rowInfo.row.offsetHeight - 1;
   if(includePartiallyVisible)
    return rowTop <= mainTableViewPortBottom && rowBottom >= mainTableViewPortTop;
   return rowTop >= mainTableViewPortTop && rowBottom <= mainTableViewPortBottom;
  }).map(function(rowInfo) { return rowInfo.visibleIndex; });
  ASPx.Data.ArrayIntegerSort(result);
  return result;
 },
 ApplyOnClickRowFilter: function() {
  this.GetFilterHelper().ApplyMultiColumnAutoFilter();
 },
 GetEditFormLayout: function() {
  if(this.hasEditFormTemplate) {
   var result = null;
   if(this.IsEditing()) {
    var popupEditForm = this.GetPopupEditForm();
    var templateContainer = popupEditForm ? popupEditForm.GetWindowContentElement(-1) : this.GetEditFormTableCell();
    var editFormLayoutIDPostfix = this.GetEditFormLayoutIDPostfix();
    ASPx.GetControlCollection().ProcessControlsInContainer(templateContainer, function(control) { result = control; },
     function(control) { return control.name && ASPx.Str.EndsWith(control.name, editFormLayoutIDPostfix); }
    );
   }
   return result;
  }
  return ASPxClientGridBase.prototype.GetEditFormLayout.call(this);
 },
 GetEditFormLayoutIDPostfix: function() {
  return "_DXEFL";
 }
});
ASPxClientGridView.Cast = ASPxClientControl.Cast;
var ASPxClientGridViewColumn = ASPx.CreateClass(ASPxClientGridColumnBase, {
 constructor: function(prop){
  this.constructor.prototype.constructor.call(this, prop);
  this.visibleIndex =    ASPx.IsExists(prop[8])  ? prop[8]  : -1;
  this.groupIndex =      ASPx.IsExists(prop[9])  ? prop[9]  : -1;
  this.columnType =      ASPx.IsExists(prop[10]) ? prop[10] : 0;
  this.filterRowTypeKind =  ASPx.IsExists(prop[11]) ? prop[11] : "";
  this.isFixed =      ASPx.IsExists(prop[12]) ?  !!prop[12] : false;
  this.allowGroup =      ASPx.IsExists(prop[13]) ?  !!prop[13] : true;
  this.allowDrag =    ASPx.IsExists(prop[14]) ?  !!prop[14] : true;
  this.parentIndex =     ASPx.IsExists(prop[15]) ? prop[15] : -1;
  this.inCustWindow =    ASPx.IsExists(prop[16]) ?  !!prop[16] : false;
  this.minWidth =     ASPx.IsExists(prop[17]) ? prop[17] : 0;
  this.maxWidth =     ASPx.IsExists(prop[18]) ? prop[18] : 0;
  this.rowSpan =      ASPx.IsExists(prop[19]) ? prop[19] : 1;
  this.showFilterMenuLikeItem =   ASPx.IsExists(prop[20]) ?  !!prop[20] : false;
  this.collectionIndex  =   ASPx.IsExists(prop[21]) ? prop[21] : -1;
  this.showInCustomizationForm =  ASPx.IsExists(prop[22]) ?  !!prop[22] : true;
  this.hasGroupRowTemplate =   ASPx.IsExists(prop[23]) ?  !!prop[23] : false;
  this.isDataColumn = this.columnType === 0;
  this.isCommandColumn = this.columnType === 1;
  this.isBand = this.columnType === 2;
 }
});
var ASPxClientGridViewColumnCancelEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(column){
  this.constructor.prototype.constructor.call(this);
  this.column = column;
 }
});
var ASPxClientGridViewColumnProcessingModeEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(column){
  this.constructor.prototype.constructor.call(this, false);
  this.column = column;
 }
});
var ASPxClientGridViewRowCancelEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
 constructor: function(visibleIndex){
  this.constructor.prototype.constructor.call(this);
  this.visibleIndex = visibleIndex;
 }
});
var ASPxClientGridViewSelectionEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(visibleIndex, isSelected, isAllRecordsOnPage, isChangedOnServer){
  this.constructor.prototype.constructor.call(this, false);
  this.visibleIndex = visibleIndex;
  this.isSelected = isSelected;
  this.isAllRecordsOnPage = isAllRecordsOnPage;
  this.isChangedOnServer = !!isChangedOnServer;
 }
});
var ASPxClientGridViewFocusEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(isChangedOnServer){
  this.constructor.prototype.constructor.call(this, false);
  this.isChangedOnServer = !!isChangedOnServer;
 }
});
var ASPxClientGridViewRowFocusingEventArgs = ASPx.CreateClass(ASPxClientGridViewRowCancelEventArgs, {
 constructor: function(visibleIndex, htmlEvent){
  this.constructor.prototype.constructor.call(this, visibleIndex);
  this.htmlEvent = htmlEvent;
 }
});
var ASPxClientGridViewRowClickEventArgs = ASPx.CreateClass(ASPxClientGridViewRowCancelEventArgs, {
 constructor: function(visibleIndex, htmlEvent){
  this.constructor.prototype.constructor.call(this, visibleIndex);
  this.htmlEvent = htmlEvent;
 }
});
var ASPxClientGridViewContextMenuEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(objectType, index, htmlEvent, menu, showBrowserMenu) {
  this.constructor.prototype.constructor.call(this);
  this.objectType = objectType;
  this.index = index;
  this.htmlEvent = htmlEvent;
  this.menu = menu;
  this.showBrowserMenu = showBrowserMenu;
 }
});
var ASPxClientGridViewContextMenuItemClickEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(item, objectType, elementIndex, processOnServer){
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.item = item;
  this.objectType = objectType;
  this.elementIndex = elementIndex;
  this.usePostBack = false;
  this.handled = false;
 }
});
var ASPxClientGridViewCustomButtonEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function(visibleIndex, buttonID) {
  this.constructor.prototype.constructor.call(this, false);
  this.visibleIndex = visibleIndex;
  this.buttonID = buttonID;
 } 
});
var ASPxClientGridViewColumnMovingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(sourceColumn, destinationColumn, isDropBefore, isGroupPanel) {
  this.constructor.prototype.constructor.call(this);
  this.allow = true;
  this.sourceColumn = sourceColumn;
  this.destinationColumn = destinationColumn;
  this.isDropBefore = isDropBefore;
  this.isGroupPanel = isGroupPanel;
 }
});
var ASPxClientGridViewBatchEditConfirmShowingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditConfirmShowingEventArgs, {
 constructor: function(requestTriggerID) {
  this.constructor.prototype.constructor.call(this, requestTriggerID);
 }
});
var ASPxClientGridViewBatchEditStartEditingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditStartEditingEventArgs, {
 constructor: function(visibleIndex, focusedColumn, itemValues, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, focusedColumn, itemValues);
  this.rowValues = this.itemValues;
  this.key = key;
 }
});
var ASPxClientGridViewBatchEditEndEditingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditEndEditingEventArgs, {
 constructor: function(visibleIndex, itemValues, key, focusedColumn) {
  this.constructor.prototype.constructor.call(this, visibleIndex, focusedColumn, itemValues);
  this.rowValues = this.itemValues;
  this.key = key;
 }
});
var ASPxClientGridViewBatchEditRowChangesCancelingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditItemChangesCancelingEventArgs, {
 constructor: function(visibleIndex, itemValues, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, itemValues);
  this.rowValues = this.itemValues;
  this.key = key;
 }
});
var ASPxClientGridViewBatchEditRowValidatingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditItemValidatingEventArgs, {
 constructor: function(visibleIndex, validationInfo, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, validationInfo);
  this.key = key;
 }
});
var ASPxClientGridViewBatchEditTemplateCellFocusedEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditTemplateCellFocusedEventArgs, {
 constructor: function(column) {
  this.constructor.prototype.constructor.call(this, column);
 }
});
var ASPxClientGridViewBatchEditChangesSavingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditClientChangesEventArgs, {
 constructor: function(insertedValues, deletedValues, updatedValues) {
  this.constructor.prototype.constructor.call(this, insertedValues, deletedValues, updatedValues);
 }
});
var ASPxClientGridViewBatchEditChangesCancelingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditClientChangesEventArgs, {
 constructor: function(insertedValues, deletedValues, updatedValues) {
  this.constructor.prototype.constructor.call(this, insertedValues, deletedValues, updatedValues);
 }
});
var ASPxClientGridViewBatchEditRowInsertingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditItemInsertingEventArgs, {
 constructor: function(visibleIndex) {
  this.constructor.prototype.constructor.call(this, visibleIndex);
 }
});
var ASPxClientGridViewBatchEditRowDeletingEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditItemDeletingEventArgs, {
 constructor: function(visibleIndex, itemValues, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, itemValues, key);  
  this.rowValues = this.itemValues;  
  this.key = key;
 }
});
var ASPxClientGridViewBatchEditRowRecoveringEventArgs = ASPx.CreateClass(ASPxClientGridBatchEditItemDeletingEventArgs, {
 constructor: function(visibleIndex, itemValues, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, itemValues, key);  
  this.rowValues = this.itemValues; 
  this.key = key;
 }
});
var ASPxClientGridViewFocusedCellChangingEventArgs = ASPx.CreateClass(ASPxClientGridFocusedCellChangingEventArgs, {
 constructor: function(cellInfo) {
  this.constructor.prototype.constructor.call(this, cellInfo);
 }
});
var ASPxClientGridViewCellSelectionChangingEventArgs = ASPx.CreateClass(ASPxClientGridCellSelectionChangingEventArgs, {
 constructor: function(cellInfo, newSelectionState) {
  this.constructor.prototype.constructor.call(this, cellInfo, newSelectionState);
 }
});
var ASPxClientGridViewClipboardCellPastingEventArgs = ASPx.CreateClass(ASPxClientGridClipboardCellPastingEventArgs, {
 constructor: function(cellInfo, oldValueInfo, newValueInfo) {
  this.constructor.prototype.constructor.call(this, cellInfo, oldValueInfo, newValueInfo);
 }
});
var ASPxClientGridViewCellInfo = ASPx.CreateClass(ASPxClientGridCellInfo, {
 constructor: function(visibleIndex, column, key) {
  this.constructor.prototype.constructor.call(this, visibleIndex, column);
  this.rowVisibleIndex = this.itemVisibleIndex;
  this.key = key;
 }
});
ASPx.GVContextMenu = function(name, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  var showDefaultMenu = gv.GetContextMenuHelper().OnContextMenuClick(e);
  if(!showDefaultMenu)
   ASPx.Evt.PreventEventAndBubble(e);
  return showDefaultMenu;
  }
 return true;
};
ASPx.GVContextMenuItemClick = function(name, e) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null)
  gv.GetContextMenuHelper().OnContextMenuItemClick(e);
};
ASPx.GVExpandRow = function(name, visibleIndex, event) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  if(gv.useEndlessPaging && event)
   visibleIndex = gv.FindParentRowVisibleIndex(ASPx.Evt.GetEventSource(event), true);
  gv.ExpandRow(visibleIndex);
 }
};
ASPx.GVCollapseRow = function(name, visibleIndex, event) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  if(gv.useEndlessPaging && event)
   visibleIndex = gv.FindParentRowVisibleIndex(ASPx.Evt.GetEventSource(event), true);
  gv.CollapseRow(visibleIndex);
 }
};
ASPx.GVShowDetailRow = function(name, visibleIndex, event) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  if(gv.useEndlessPaging && event)
   visibleIndex = gv.FindParentRowVisibleIndex(ASPx.Evt.GetEventSource(event), true);
  gv.ExpandDetailRow(visibleIndex);
 }
};
ASPx.GVHideDetailRow = function(name, visibleIndex, event) {
 var gv = ASPx.GetControlCollection().Get(name);
 if(gv != null) {
  if(gv.useEndlessPaging && event)
   visibleIndex = gv.FindParentRowVisibleIndex(ASPx.Evt.GetEventSource(event), true);
  gv.CollapseDetailRow(visibleIndex);
 }
};
ASPx.Evt.AttachEventToElement(window, "scroll", function(evt) {
 ASPx.GetControlCollection().ForEachControl(function(control){
  if(control instanceof ASPxClientGridView && ASPx.IsExists(control.GetMainElement()))
   control.OnScroll(evt);
 });
});
var GridViewCallbackHelper = ASPx.CreateClass(ASPx.GridCallbackHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
 },
 GetResizingState: function() { return this.grid.stateObject.resizingState; },
 GetContextMenuState: function() { return this.grid.GetContextMenuHelper().GetCallbackState(); },
 GetGridCallbackState: function() {
  var state = ASPx.GridCallbackHelper.prototype.GetGridCallbackState.call(this);
  return state.concat([
   [ "CR", this.GetResizingState() ],
   [ "CM", this.GetContextMenuState() ]
  ]);
 },
 ValidateCommand: function(command) {
  if(!ASPx.GridCallbackHelper.prototype.ValidateCommand.call(this, command))
   return false;
  if(this.IsBatchChangesViewMode() && command !== ASPxClientGridViewCallbackCommand.UpdateEdit)
   return false;
  return true;
 },
 IsBatchChangesViewMode: function() { return this.grid.IsBatchChangesViewMode(); }
});
var GridViewKbdHelper = ASPx.CreateClass(ASPx.GridKbdHelper, {
 constructor: function(control, enableKeyboardNavigation) {
  this.constructor.prototype.constructor.call(this, control);
  this.preventBrowserScrollOnFocus = false;
  this.enableKeyboardNavigation = enableKeyboardNavigation;
 },
 RequirePreventScrollOnFocus: function() { return this.preventBrowserScrollOnFocus; },
 CanFocus: function(e) {
  var grid = this.control;
  if(grid.IsDetailGridFocused(e))
   return false;
  var batchEditHelper = grid.GetBatchEditHelper();
  if(batchEditHelper && batchEditHelper.CanStartEditOnTableClick(grid.getItemByHtmlEvent(e), e))
   return false;
  var popupsToCheck = [grid.GetCustomizationWindow(), grid.GetCustDialogWindow(), grid.GetFilterControlPopup(), grid.GetPopupEditForm(), grid.GetHeaderFilterPopup()];
  var isPopupVisible = popupsToCheck.some(function(p) { return p && p.IsVisible(); });
  if(isPopupVisible)
   return false;
  if(!this.canFocusOnActiveDropDownEditPopup())
   return false;
  return ASPx.GridKbdHelper.prototype.CanFocus.call(this, e);
 },
 canFocusOnActiveDropDownEditPopup: function() {
  return !this.getActiveDropDownEditPopup();
 },
 getActiveDropDownEditPopup: function() {
  var result = null;
  var activePopup = ASPx.GetPopupControlCollection && ASPx.GetPopupControlCollection().GetCurrentActiveWindowElement();
  if(activePopup) {
   var activePopupControl = ASPx.GetClientControlByElementID(activePopup.id);
   var isDropDownEditPopup = ASPx.IsExists(activePopupControl) && activePopupControl.usedInDropDown;
   if(isDropDownEditPopup) 
    result = activePopupControl;
  }
  return result;
 },
 HandleKeyDown: function(e) {
  var handled = ASPx.GridKbdHelper.prototype.HandleKeyDown.call(this, e);
  if(handled || !this.enableKeyboardNavigation)
   return false;
  var grid = this.control;
  this.moveIterationCount = 0;
  var index = grid.GetFocusedRowIndex();
  var busy = grid.keyboardLock;
  var key = ASPx.Evt.GetKeyCode(e);
  if(grid.rtl) {
   if(key == ASPx.Key.Left)
    key = ASPx.Key.Right;
   else if(key == ASPx.Key.Right)
    key = ASPx.Key.Left;
  }
  switch(key) {
   case ASPx.Key.Down:
    if(!busy) 
     this.TryMoveFocusDown(index, e.shiftKey, e);
    return true;
   case ASPx.Key.Up:
    if(!busy) 
     this.TryMoveFocusUp(index, e.shiftKey, e);
    return true;
   case ASPx.Key.Right:
    if(!busy) {
     if(!this.TryExpand(index))
      this.TryMoveFocusDown(index, e.shiftKey, e);
    }
    return true;
   case ASPx.Key.Left:
    if(!busy) {
     if(!this.TryCollapse(index))
      this.TryMoveFocusUp(index, e.shiftKey, e);
    }
    return true;
   case ASPx.Key.PageDown:
    if(e.shiftKey) {
     if(!busy && grid.pageIndex < grid.pageCount - 1)
      grid.NextPage();
     return true; 
    }
    break;
   case ASPx.Key.PageUp:
    if(e.shiftKey) {
     if(!busy && grid.pageIndex > 0)
      grid.PrevPage();
     return true; 
    }
    break;     
  }
  return false;
 },
 HandleKeyPress: function(e) {
  var handled = ASPx.GridKbdHelper.prototype.HandleKeyPress.call(this, e);
  if(handled || !this.enableKeyboardNavigation)
   return false;
  var grid = this.grid;
  var index = grid.GetFocusedRowIndex();
  var busy = grid.keyboardLock;
  switch(ASPx.Evt.GetKeyCode(e)) {
   case ASPx.Key.Space:
    if(!busy && this.IsRowSelectable(index))
     if(grid.IsRowSelectedOnPage(index)) {
      grid.UnselectRowOnPage(index);
     } else {
      grid.SelectRowOnPage(index);
     }
    return true;
    case 43:
    if(!busy)
     this.TryExpand(index);
    return true;
    case 45: 
    if(!busy)   
     this.TryCollapse(index);    
    return true;
  }
  return false;
 },
 EnsureFocusedRowVisible: function() {
  var grid = this.control;
  if(!grid.HasVertScroll()) return;
  var row = grid.GetItem(grid.GetFocusedRowIndex());
  grid.GetScrollHelper().MakeRowVisible(row, true);
 },
 HasDetailButton: function(expanded) {
  var grid = this.control;
  var row = grid.GetItem(grid.GetFocusedRowIndex());
  if(!row) return;
  var needle = expanded ? "ASPx.GVHideDetailRow" : "ASPx.GVShowDetailRow";
  return row.innerHTML.indexOf(needle) > -1;
 },
 IsRowSelectable: function(index) {
  if(this.control.allowSelectByItemClick)
   return true;
  var row = this.control.GetItem(index);
  if(row && row.innerHTML.indexOf("aspxGVSelectRow") > -1)
   return true;
  var check = this.control.GetDataRowSelBtn(index); 
  if(check && this.control.internalCheckBoxCollection && !!this.control.internalCheckBoxCollection.Get(check.id))
   return true;
  return false;
 },
 UpdateShiftSelection: function(start, end) {
  var grid = this.control;
  grid.UnselectAllRowsOnPage();
  if(grid.lastMultiSelectIndex > -1)   
   start = grid.lastMultiSelectIndex;
  else   
   grid.lastMultiSelectIndex = start;
  if(grid.allowSelectSingleRowOnly)
   start = end;
  for(var i = Math.min(start, end); i <= Math.max(start, end); i++)
   grid.SelectRowOnPage(i);
 },
 TryExpand: function(index) {
  var grid = this.control;
  if(grid.IsGroupRow(index) && !grid.IsGroupRowExpanded(index)) {
   grid.ExpandRow(index);
   return true;
  }
  if(this.HasDetailButton(false)) {
   grid.ExpandDetailRow(index);
   return true;
  }
  return false;
 },
 TryCollapse: function(index) {
  var grid = this.control;
  if(grid.IsGroupRow(index) && grid.IsGroupRowExpanded(index)) {
   grid.CollapseRow(index);
   return true;
  }
  if(this.HasDetailButton(true)) {
   grid.CollapseDetailRow(index);
   return true;
  }
  return false;
 },
 TryMoveFocusDown: function(index, select, htmlEvent) {
  this.moveIterationCount++;
  var grid = this.control;
  if(index < grid.visibleStartIndex + grid.pageRowCount - 1) {
   var focusedRowIndex = index >= 0 ? index + 1 : grid.visibleStartIndex;
   var focusChanged = grid.TryFocusItem(focusedRowIndex, htmlEvent);
   this.EnsureFocusedRowVisible();
   if(this.IsRowSelectable(index)) {
    if(select) {
     this.UpdateShiftSelection(index, index + 1);
    } else {
     grid.lastMultiSelectIndex = -1;
    }
   }
   if(grid.allowFocusedRow && !grid.InCallback() && !focusChanged && this.moveIterationCount < 100)
    this.TryMoveFocusDown(++index, select, htmlEvent);
  } else {
   if(grid.pageIndex < grid.pageCount - 1 && grid.pageIndex >= 0) {       
    grid.NextPage();
   }
  }  
 },
 TryMoveFocusUp: function(index, select, htmlEvent) {
  this.moveIterationCount++;
  var grid = this.control;
  if(index > grid.visibleStartIndex || index == -1) {
   var focusedRowIndex = index >= 0 ? index - 1 : grid.visibleStartIndex + grid.pageRowCount - 1;
   var focusChanged = grid.TryFocusItem(focusedRowIndex, htmlEvent);
   this.EnsureFocusedRowVisible();
   if(this.IsRowSelectable(index)) {
    if(select) {
     this.UpdateShiftSelection(index, index - 1);
    } else {
     grid.lastMultiSelectIndex = -1;
    }
   }
   if(grid.allowFocusedRow && !grid.InCallback() && !focusChanged && this.moveIterationCount < 100)
    this.TryMoveFocusUp(--index, select, htmlEvent);
  } else {
   if(grid.pageIndex > 0) {
    grid.PrevPage(true);
   }
  }
 }
});
var GridViewHeaderMatrix = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
 },
 Invalidate: function() {
  this.matrix = null;
  this.inverseMatrix = null;
 },
 GetRowCount: function() {
  this.EnsureMatrix();
  return this.matrix.length;
 },
 IsLeftmostColumn: function(columnIndex) {
  this.EnsureMatrix();
  return this.inverseMatrix[columnIndex].left == 0;
 },
 IsRightmostColumn: function(columnIndex) {
  this.EnsureMatrix();  
  return this.inverseMatrix[columnIndex].right == this.matrix[0].length - 1;
 },
 IsLeaf: function(columnIndex) {
  this.EnsureMatrix();
  return this.inverseMatrix.hasOwnProperty(columnIndex) && this.inverseMatrix[columnIndex].bottom == this.matrix.length - 1;
 },
 GetLeaf: function(columnIndex, isLeft, isOuter) {
  this.EnsureMatrix();
  var rect = this.inverseMatrix[columnIndex];
  var row = this.matrix[this.matrix.length - 1];
  if(isLeft) {
   if(isOuter)
    return row[rect.left - 1];
   return row[rect.left];
  }
  if(isOuter)
   return row[rect.right + 1];
  return row[rect.right];
 },
 GetLeafIndex: function(columnIndex) {
  this.EnsureMatrix();
  return this.inverseMatrix[columnIndex].left;
 },
 GetLeafIndices: function() {
  return this.GetRowIndices(this.GetRowCount() - 1);
 },
 GetRowIndices: function(rowIndex) {
  this.EnsureMatrix();
  return this.matrix[rowIndex] || [];
 },
 GetRowSpan: function(columnIndex) {
  this.EnsureMatrix();
  var rect = this.inverseMatrix[columnIndex];
  return rect.bottom - rect.top + 1;
 },
 GetLeftNeighbor: function(columnIndex, skipHidden) {
  return this.GetNeighbor(columnIndex, true, skipHidden);
 },
 GetRightNeighbor: function(columnIndex, skipHidden) {
  return this.GetNeighbor(columnIndex, false, skipHidden);
 },
 GetNeighbor: function(columnIndex, isLeft, skipHidden) {
  this.EnsureMatrix();
  if(!skipHidden)
   return this.GetNeighborCore(columnIndex, isLeft);
  var boundLeafIndex = this.GetBoundLeaf(isLeft);
  while(columnIndex !== boundLeafIndex) {
   columnIndex = this.GetNeighborCore(columnIndex, isLeft);
   if(isNaN(columnIndex) || !this.GetColumn(columnIndex).adaptiveHidden)
    return columnIndex;
  }
 },
 GetNeighborCore: function(columnIndex, isLeft) {
  var rect = this.inverseMatrix[columnIndex];
  var cellIndex = isLeft ? rect.left - 1 : rect.right + 1;
  return this.matrix[rect.top][cellIndex];
 },
 GetBoundLeaf: function(isLeft) {
  var leafs = this.GetLeafIndices();
  var cellIndex = isLeft ? 0 : leafs.length - 1;
  return leafs[cellIndex];
 },
 GetColumnLevel: function(columnIndex) {
  this.EnsureMatrix();
  var rect = this.inverseMatrix[columnIndex];
  return rect ? rect.top : -1;
 },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 GetColumn: function(columnIndex) { return this.grid.GetColumn(columnIndex); },
 EnsureMatrix: function() {
  if(!this.matrix)
   this.Fill();
 },
 Fill: function() {
  var columnHelper = this.GetColumnHelper();
  var headerLayout = columnHelper.GetHeaderLayout();
  var info = columnHelper.CreateLayoutMatrixInfo(headerLayout);
  this.matrix = info.matrix;
  this.inverseMatrix = info.inverseMatrix;
 }
});
var GridViewAdjuster = ASPx.CreateClass(null, {
 constructor: function() {
  this.masterGridForAdjust = null;
  this.documentScrollTop = GridViewConsts.UnspecifiedScrollPosition;
  this.lockDocumentScrollRestoring = false;
 },
 GetMasterGridForAdjust: function() {
  return this.masterGridForAdjust;
 },
 SetMasterGridForAdjust: function(grid) {
  this.masterGridForAdjust = grid;
 },
 SaveDocumentScrollPosition: function(lockRestoring) {
  if(this.documentScrollTop === GridViewConsts.UnspecifiedScrollPosition)
   this.documentScrollTop = ASPx.GetDocumentScrollTop();
  this.lockDocumentScrollRestoring = this.lockDocumentScrollRestoring || lockRestoring;
 },
 RestoreDocumentScrollPosition: function(forceRestoring) {
  if((!this.lockDocumentScrollRestoring || forceRestoring) && this.documentScrollTop !== GridViewConsts.UnspecifiedScrollPosition) {
   if(this.documentScrollTop !== ASPx.GetDocumentScrollTop())
    ASPx.SetDocumentScrollTop(this.documentScrollTop);
   this.documentScrollTop = GridViewConsts.UnspecifiedScrollPosition;
  }
  this.lockDocumentScrollRestoring = this.lockDocumentScrollRestoring && !forceRestoring;
 },
 ResetDocumentScrollPosition: function() {
  this.documentScrollTop = GridViewConsts.UnspecifiedScrollPosition;
  this.lockDocumentScrollRestoring = false;
 }
});
var gridViewAdjuster = new GridViewAdjuster();
function GetGridViewAdjuster() {
 return gridViewAdjuster;
}
var GridViewStyleHelper = ASPx.CreateClass(ASPx.GridStyleHelper, {
 BatchEditNewItemKey: "beni",
 FocusedGroupItemKey: "fgi",
 GetFocusedGroupItemStyle: function() { return this.GetStyleInfo(this.FocusedGroupItemKey); },
 GetBatchEditNewItemStyle: function() { return this.GetStyleInfo(this.BatchEditNewItemKey); },
 IsFocusedItemStyle: function(style) { 
  return  ASPx.GridStyleHelper.prototype.IsFocusedItemStyle.call(this, style) || this.IsFocusedGroupItemStyle(style);
 },
 IsFocusedGroupItemStyle: function(style) { return this.CheckStyleInfoByKey(style, this.FocusedGroupItemKey); }
});
var ASPxClientGridViewBatchEditApi = ASPx.CreateClass(ASPxClientGridBatchEditApi, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
 },
 ValidateRows: function(validateOnlyModified, validateOnCurrentPageOnly) { 
  var res = this.ValidateItems(validateOnlyModified, validateOnCurrentPageOnly); 
  var helper = this.GetHelper();
  var needShowPreviewChanges = !res && !validateOnCurrentPageOnly && !!helper && helper.IsCallbacksEnabled();
  if(needShowPreviewChanges)
   helper.ShowPreviewChanges(true);
  return res;
 },
 ValidateRow: function(visibleIndex) { return this.ValidateItem(visibleIndex); },
 ValidateRowByKey: function(key) { return this.ValidateItemByKey(key); },
 GetRowVisibleIndices: function(includeDeleted) { return !this.IsPreviewChangesVisible() ?  this.GetItemVisibleIndices(includeDeleted) : [ ]; },
 GetDeletedRowIndices: function() { return !this.IsPreviewChangesVisible() ? this.GetDeletedItemVisibleIndices() : [ ]; },
 GetInsertedRowIndices: function() { return this.GetInsertedItemVisibleIndices(); },
 GetUpdatedRowIndices: function() { return !this.IsPreviewChangesVisible() ? this.GetUpdatedItemVisibleIndices() : [ ]; },
 IsDeletedRow: function(visibleIndex) { return this.IsDeletedItem(visibleIndex); },
 IsDeletedRowByKey: function(key) { return this.IsDeletedItemByKey(key); },
 IsNewRow: function(visibleIndex) { return this.IsNewItem(visibleIndex); },
 AddNewRow: function() { this.AddNewItem(); },
 DeleteRow: function(visibleIndex) { this.DeleteItem(visibleIndex); },
 DeleteRowByKey: function(key) { this.DeleteItemByKey(key); },
 RecoverRow: function(visibleIndex) { this.RecoverItem(visibleIndex); },
 RecoverRowByKey: function(key) { this.RecoverItemByKey(key); },
 ShowChangesPreview: function () {
  var helper = this.GetHelper();
  if(helper)
   helper.ShowPreviewChanges();
 },
 HideChangesPreview: function () {
  var helper = this.GetHelper();
  if(helper)
   helper.HideChanges();
 },
 IsCurrentPageRow: function(key) { return this.IsCurrentPageRecord(key); },
 IsPreviewChangesVisible: function() {
  var helper = this.GetHelper();
  return !!helper && helper.IsChangesViewVisible();
 },
 GetFocusedCell: function() { return this.grid.GetFocusedCell(); },
 SetFocusedCell: function(rowVisibleIndex, columnIndex) { this.grid.SetFocusedCell(rowVisibleIndex, columnIndex); },
 SetFocusedCellByKey: function(key, columnIndex) { this.grid.SetFocusedCellByKey(key, columnIndex); },
 GetSelectedCells: function() { return this.grid.GetSelectedCells(); },
 SelectCell: function(rowVisibleIndex, columnIndex) { this.SelectCellByKey(rowVisibleIndex, this.ConvertVisibleIndexToKey(columnIndex)); },
 SelectCellByKey: function(key, columnIndex) { this.grid.SetCellSelection(key, columnIndex, true); },
 UnselectCell: function(rowVisibleIndex, columnIndex) { this.UnselectCellByKey(rowVisibleIndex, this.ConvertVisibleIndexToKey(columnIndex)); },
 UnselectCellByKey: function(key, columnIndex) { this.grid.SetCellSelection(key, columnIndex, false); }
});
var ASPxClientGridViewGlobalEventsListener = ASPx.CreateClass(ASPxClientComponent, {
 OnGlobalEndCallback: function(args) {
  ASPxClientControl.prototype.OnGlobalEndCallback.call(this, args);
  var control = args.control;
  if(control instanceof ASPxClientGridView)
   return;
  var ownerGrid = control.findParentByType(ASPxClientGridView);
  if(ownerGrid && ownerGrid !== control)
   ownerGrid.OnChildControlEndCallback(control);
 }
});
var dummyGridViewGlobalEventsListener = new ASPxClientGridViewGlobalEventsListener("gvGlobalEventListener");
window.ASPxClientGridView = ASPxClientGridView;
window.ASPxClientGridViewColumn = ASPxClientGridViewColumn;
window.ASPxClientGridViewColumnCancelEventArgs = ASPxClientGridViewColumnCancelEventArgs;
window.ASPxClientGridViewColumnProcessingModeEventArgs = ASPxClientGridViewColumnProcessingModeEventArgs;
window.ASPxClientGridViewRowCancelEventArgs = ASPxClientGridViewRowCancelEventArgs;
window.ASPxClientGridViewSelectionEventArgs = ASPxClientGridViewSelectionEventArgs;
window.ASPxClientGridViewRowClickEventArgs = ASPxClientGridViewRowClickEventArgs;
window.ASPxClientGridViewContextMenuEventArgs = ASPxClientGridViewContextMenuEventArgs;
window.ASPxClientGridViewContextMenuItemClickEventArgs = ASPxClientGridViewContextMenuItemClickEventArgs;
window.ASPxClientGridViewCustomButtonEventArgs = ASPxClientGridViewCustomButtonEventArgs;
window.ASPxClientGridViewColumnMovingEventArgs = ASPxClientGridViewColumnMovingEventArgs;
window.ASPxClientGridViewBatchEditConfirmShowingEventArgs = ASPxClientGridViewBatchEditConfirmShowingEventArgs;
window.ASPxClientGridViewBatchEditStartEditingEventArgs = ASPxClientGridViewBatchEditStartEditingEventArgs;
window.ASPxClientGridViewBatchEditEndEditingEventArgs = ASPxClientGridViewBatchEditEndEditingEventArgs;
window.ASPxClientGridViewBatchEditRowChangesCancelingEventArgs = ASPxClientGridViewBatchEditRowChangesCancelingEventArgs;
window.ASPxClientGridViewBatchEditRowValidatingEventArgs = ASPxClientGridViewBatchEditRowValidatingEventArgs;
window.ASPxClientGridViewBatchEditTemplateCellFocusedEventArgs = ASPxClientGridViewBatchEditTemplateCellFocusedEventArgs;
window.ASPxClientGridViewBatchEditChangesSavingEventArgs = ASPxClientGridViewBatchEditChangesSavingEventArgs;
window.ASPxClientGridViewBatchEditChangesCancelingEventArgs = ASPxClientGridViewBatchEditChangesCancelingEventArgs;
window.ASPxClientGridViewBatchEditRowInsertingEventArgs = ASPxClientGridViewBatchEditRowInsertingEventArgs;
window.ASPxClientGridViewBatchEditRowDeletingEventArgs = ASPxClientGridViewBatchEditRowDeletingEventArgs;
window.ASPxClientGridViewBatchEditRowRecoveringEventArgs = ASPxClientGridViewBatchEditRowRecoveringEventArgs;
window.ASPxClientGridViewFocusedCellChangingEventArgs = ASPxClientGridViewFocusedCellChangingEventArgs;
window.ASPxClientGridViewCellSelectionChangingEventArgs = ASPxClientGridViewCellSelectionChangingEventArgs;
window.ASPxClientGridViewClipboardCellPastingEventArgs = ASPxClientGridViewClipboardCellPastingEventArgs;
ASPx.GridViewHeaderMatrix = GridViewHeaderMatrix;
ASPx.GridViewKbdHelper = GridViewKbdHelper;
ASPx.GridViewConsts = GridViewConsts;
ASPx.GridViewRowType = GridViewRowType;
ASPx.GridViewCallbackHelper = GridViewCallbackHelper;
ASPx.GridViewAdaptiveDetailButtonPosition = GridViewAdaptiveDetailButtonPosition;
ASPx.GetGridViewAdjuster = GetGridViewAdjuster;
ASPx.GridViewStyleHelper = GridViewStyleHelper;
window.ASPxClientGridViewBatchEditApi = ASPxClientGridViewBatchEditApi;
window.ASPxClientGridViewCellInfo = ASPxClientGridViewCellInfo;
window.ASPxClientGridViewExportFormat = ASPx.ASPxClientGridExportFormat;
})();

(function() {
 var Constants = {
  QueryParamNames: {
   PROGRESS_INFO: "DXProgressInfo",
   UPLOADING_CALLBACK: "DXUploadingCallback",
   HELPER_UPLOADING_CALLBACK: "DXHelperUploadingCallback",
   CANCEL_UPLOAD: "DXFakeQueryParam",
   PROGRESS_HANDLER: "DXProgressHandlerKey"
  },
  Delimiters: {
   STATE_ITEM: ",",
   STATE_ITEM_ARRAY: "|",
   CALLBACK_ARGUMENT: "::",
   CALLBACK_ITEM: ":"
  },
  DEFAULT_PACKET_SIZE: 200000,
  ERROR_TEXT_RESPONSE_PREFIX: "DXER:",
  SL_PLATFORM_NAME: "Sil" + "ver" + "light",
  INPUT_ZINDEX: 29999,
  FIREFOX_FOLDER_MAX_SIZE: 16384,
  MAX_HANDLING_FILE_NAME_COUNT: 5,
  INVALID_FILENAME_CHARACTERS: ['\\','/',':','*','?','"','<','>','|']
 };
 var IdSuffixes = {
  Input: {
   FileInput: "_Input",
   FileInputRow: "_FI",
   FileFakeInput: "_FakeInput",
   FakeFocusInput: "_FFI",
   UploadInputsTable: "_UploadInputs",
   TextBoxCell: "_TextBox",
   AddButtonsSeparator: "_AddUploadR",
   AddUploadButtonPanelRow: "_AddUploadPanelR",
   ButtonCell: {
    Add: "_Add",
    Upload: "_Upload",
    Browse: "_Browse",
    Remove: "_Remove",
    Cancel: "_Cancel",
    Clear: "_ClearBox",
    ClearImg: "Img"
   },
   FileList: {
    List: "_FileList",
    Row: "_FileR",
    RemoveRowButton: "_RemoveRow",
    ProgressControl: "_FL_Progress"
   }
  },
  SL: {
   UploadHelper: "_SLUploadHelper",
   UploadHost: "_SLUploadHost",
   ErrorTextResponsePrefix: "DXER:"
  },
  Progress: {
   Panel: "_ProgressPanel",
   Control: "_UCProgress"
  },
  Error: {
   Row: "_ErrR",
   RowTemplate: "_ErrRRT",
   Div: "_CErr",
   PlatformErrorTable: "_PlatformErrorPanel"
  },
  Upload: {
   IFrame: "_UploadIframe"
  }
 };
 var CSSClasses = {
  ErrorTextResponsePrefix: "DXER:",
  BrowseButtonCell: "dxBB",
  ClearButtonCell: "dxCB",
  RemoveButtonCell: "dxRB",
  BrowseButtonFocus: "dxbf",
  FITextBoxHoverDocument: "_dxFITextBoxHover",
  FIButtonHoverDocument: "_dxFIButtonHover",
  SeparatorRow: "dxucSR",
  GeneratedPrefix: "dxucgen-",
  HiddenUI: "dxucHidden",
  Textbox: "dxTB",
  TextboxInput: "dxTI",
  TextboxFakeInput: "dxTF",
  FileList: {
   List: "dxucFileList",
   NameCell: "dxucNameCell",
   RemoveButtonCell: "dxRB",
   ProgressBar: "dxucFL-Progress",
   ProgressBarCell: "dxucBarCell",
   State: {
    Pending: "dxuc-pending",
    Uploading: "dxuc-uploading",
    Complete: "dxuc-complete"
   }
  },
  DropZone: {
   Inline: "dxucInlineDropZoneSys",
   InlineHidden: "dxucIZ-hidden",
   HasExternalAnchor: "hasExternalAnchor"
  }
 };
 var ASPxEmptyRefreshArgs = {
  fileInfos: [],
  forceClear: true
 };
 var ASPxUploadErrorTypes = {
  Common: 0,
  Platform: 1,
  Validation: 2,
  InputRowError: 3
 };
 var ASPxClientUploadControl = ASPx.CreateClass(ASPxClientControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.settings = "";
   this.validationSettings = this.validationSettings || {};
   this.isInCallback = false;
   this.advancedModeEnabled = false;
   this.clientEnabled = true;
   this.fileNameHandling = false;
   this.fileInfosCache = new ASPxFileInfoCache();
   this.templateDisabledRemoveItem = null;
   this.dropZoneAnimationType = "Fade";
   aspxGetUploadControlCollection().Add(this);
   this.FileUploadComplete = new ASPxClientEvent();
   this.FilesUploadComplete = new ASPxClientEvent();
   this.FileUploadStart = new ASPxClientEvent();
   this.FilesUploadStart = new ASPxClientEvent();
   this.TextChanged = new ASPxClientEvent();
   this.UploadingProgressChanged = new ASPxClientEvent();
   this.FileInputCountChanged = new ASPxClientEvent();
   this.ValidationErrorOccurred = new ASPxClientEvent();
   this.DropZoneEnter = new ASPxClientEvent();
   this.DropZoneLeave = new ASPxClientEvent();
  },
  Initialize: function() {
   if(!this.GetMainElement())
    return;
   this.InitializeHandlers();
   this.AdjustMainElementWidth();
   this.initializeForm();
   this.viewManager.Initialize();
   this.initializeUploadManagerHandlers();
   this.SetEnabledInternal(this.clientEnabled, true);
  },
  InlineInitialize: function() {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   this.initializeDomHelper();
   this.initializeOptions();
   this.initializeDragAndDrop();
   this.initializeFileValidator();
   this.initializeUploadManager();
   this.initializeViewManager();
  },
  initializeFileValidator: function() {
   this.fileValidator = new ASPxFileValidator(this.options);
  },
  initializeForm: function () {
   var form = this.GetParentForm();
   if(form)
    form.enctype = form.encoding = "multipart/form-data";
  },
  initializeDomHelper: function() {
   var domHelper = new ASPxDOMHelper({name: this.name, stateObject: this.stateObject});
   domHelper.GetChildElement = this.GetChildElement.aspxBind(this);
   domHelper.GetMainElement = this.GetMainElement.aspxBind(this);
   domHelper.IsDisplayed = this.IsDisplayed.aspxBind(this);
   this.domHelper = domHelper;
  },
  initializeOptions: function() {
   var options = this.options = {};
   options.uploadControl = this;
   options.advancedModeEnabled = this.advancedModeEnabled;
   options.autoModeEnabled = this.autoModeEnabled || false;
   options.autoStart = this.autoStart;
   options.maxFileCount = this.validationSettings.maxFileCount || 0;
   options.enableMultiSelect = (ASPxClientUploadControl.IsFileApiAvailable() || this.IsSLPluginAvailable()) && this.enableMultiSelect;
   options.domHelper = this.domHelper;
   options.templateDisabledRemoveItem = this.templateDisabledRemoveItem;
   options.fileInputCount = this.domHelper.GetFileInputCountInternal();
   options.showAddRemoveButtons = !!this.domHelper.GetChildElement(IdSuffixes.Input.ButtonCell.Add);
   options.multiFileInputEnabled = options.fileInputCount > 1 || options.showAddRemoveButtons;
   options.enableDragAndDrop = this.enableDragAndDrop && ASPxClientUploadControl.IsDragAndDropAvailable() && !ASPx.Browser.WebKitTouchUI && !options.multiFileInputEnabled;
   options.externalDropZoneIDList = this.externalDropZoneIDList || [];
   options.inlineDropZoneAnchorElementID = this.inlineDropZoneAnchorElementID;
   options.disableInlineDropZone = this.disableInlineDropZone;
   options.dropZoneAnimationType = this.dropZoneAnimationType;
   this.enableDragAndDrop = options.enableDragAndDrop;
   options.enableFileList = options.enableMultiSelect && this.enableFileList && !options.multiFileInputEnabled;
   options.enableProgressPanel = !!this.GetProgressPanel();
   options.IsRightToLeft = this.IsRightToLeft.aspxBind(this);
   options.name = this.name;
   options.isFileApiAvailable = ASPxClientUploadControl.IsFileApiAvailable();
   options.isSLEnabled = this.IsSLPluginAvailable();
   options.isNative = this.isNative || false;
   options.selectedSeveralFilesText = this.selectedSeveralFilesText;
   options.advancedModeEnabledInternal = this.options.advancedModeEnabled && (this.options.isFileApiAvailable || this.options.isSLEnabled);
   options.fileNameHandling = this.fileNameHandling;
   options.nullText = this.getNullText();
   options.nullTextItem = this.nullTextItem;
   options.showProgressPanel = !!this.domHelper.GetChildElement(IdSuffixes.Progress.Panel);
   options.progressHandlerPage = this.progressHandlerPage;
   options.uploadingKey = this.uploadingKey;
   options.packetSize = this.packetSize || Constants.DEFAULT_PACKET_SIZE;
   options.uploadProcessingEnabled = this.uploadProcessingEnabled || false;
   options.slUploadHelperUrl = this.slUploadHelperUrl;
   options.callbackResultErrorText = this.callbackResultErrorText || "";
   options.uploadWasCanceledErrorText = this.uploadWasCanceledErrorText;
   options.generalErrorText = this.generalErrorText;
   options.dragAndDropMoreThanOneFileError = this.dragAndDropMoreThanOneFileError;
   options.customTooltip = this.domHelper.getTooltipValue() || "";
   options.validationSettings = this.validationSettings;
   options.fileInputSpacing = this.fileInputSpacing || "";
   options.dialogTriggerIDList = this.dialogTriggerIDList;
   options.accessibilityCompliant = this.accessibilityCompliant;
   options.templates = {
    DisabledTextBoxItem: this.templateDisabledTextBoxItem,
    DisabledClearBoxItem: this.templateDisabledClearBoxItem,
    HoveredBrowseItem: this.templateHoveredBrowseItem,
    PressedBrowseItem: this.templatePressedBrowseItem,
    DisabledRemoveItem: this.templateDisabledRemoveItem,
    DisabledBrowseItem: this.templateDisabledBrowseItem
   };
  },
  initializeViewManager: function() {
   this.viewManager = this.createViewManager(this.options);
   this.viewManager.UploadCancelled.AddHandler(function() {
    this.uploadManager.CancelUploading(true);
   }.aspxBind(this));
   this.viewManager.UploadStarted.AddHandler(function() {
    this.Upload();
   }.aspxBind(this));
   this.viewManager.FileInputCountChangedInternal.AddHandler(this.raiseFileInputCountChanged.aspxBind(this));
   this.viewManager.DropZoneEnter.AddHandler(this.raiseDropZoneEnter.aspxBind(this));
   this.viewManager.DropZoneLeave.AddHandler(this.raiseDropZoneLeave.aspxBind(this));
   this.fileValidator.ValidationErrorInternal.AddHandler(this.OnErrorInternal.aspxBind(this));
   this.fileValidator.ValidationErrorOccurredInternal.AddHandler(this.raiseErrorOccurred.aspxBind(this));
   this.viewManager.InlineInitialize();
  },
  createViewManager: function(options) {
   return new ASPxViewManager(this.options);
  },
  initializeUploadManager: function() {
   if(this.options.advancedModeEnabled) {
    if(this.options.isFileApiAvailable)
     this.options.uploadHelper = new ASPxUploadHelperHTML5(this.options);
    else
     this.options.uploadHelper = new ASPxUploadHelperSL(this.options);
   }
   else
    this.options.uploadHelper = new ASPxUploadHelperStandardStrategy(this.options);
   var stateHelper = this.options.advancedModeEnabledInternal
    ? new AdvancedStateHelper(this)
    : new EmptyStateHelper(this);
   this.uploadManager = this.createUploadManager(stateHelper);
   this.uploadManager.GetParentForm = this.GetParentForm.aspxBind(this);
  },
  initializeDragAndDrop: function() {
   if(this.options.enableDragAndDrop)
    aspxGetUploadControlCollection().initializeEvents();
  },
  createUploadManager: function(stateHelper) {
   return new ASPxLegacyUploadManager(this.options, stateHelper);
  },
  initializeUploadManagerHandlers: function() {
   this.uploadManager.FileUploadCompleteInternal.AddHandler(this.OnFileUploadComplete.aspxBind(this));
   this.uploadManager.FilesUploadCompleteInternal.AddHandler(this.OnFilesUploadComplete.aspxBind(this));
   this.uploadManager.FileUploadStartInternal.AddHandler(this.OnFileUploadStart.aspxBind(this));
   this.uploadManager.UploadInitiatedInternal.AddHandler(this.viewManager.OnUploadInitiated.aspxBind(this.viewManager));
   this.uploadManager.BeginProcessUploadingInternal.AddHandler(this.viewManager.OnBeginProcessUploading.aspxBind(this.viewManager));
   this.uploadManager.UploadingProgressChangedInternal.AddHandler(this.OnUploadingProgressChangedInternal.aspxBind(this));
   this.uploadManager.InCallbackChangedInternal.AddHandler(this.OnInCallbackChanged.aspxBind(this));
   this.uploadManager.NeedSetJSProperties.AddHandler(this.setJSProperties.aspxBind(this));
   this.uploadManager.InternalError.AddHandler(this.OnErrorInternal.aspxBind(this));
   this.uploadManager.FileUploadErrorInternal.AddHandler(this.OnErrorInternal.aspxBind(this));
  },
  applyAccessibilityAttributes: function() {
   this.setAriaDescription("buttons");
   this.setAriaDescription("presentationElements");
   this.setAriaDescription("clearButtonLabels");
  },
  getNullText: function() {
   var result = null;
   if(this.nullText)
    result = this.nullText;
   else if(this.enableDragAndDrop)
    result = this.dropZoneText;
   return result;
  },
  OnInCallbackChanged: function(isInCallback) {
   this.isInCallback = isInCallback;
   this.viewManager.InCallbackChanged(isInCallback);
  },
  OnFilesUploadComplete: function(args) {
   if(!args.uploadCancelled || this.options.autoStart)
    this.viewManager.Clear();
   this.viewManager.OnUploadFilesComplete(args);
   var fileUploadCompleteArgs = this.CreateFilesUploadCompleteEventArgs(args);
   this.FilesUploadComplete.FireEvent(this, fileUploadCompleteArgs);
  },
  CreateFilesUploadCompleteEventArgs: function(args) {
   return new ASPxClientUploadControlFilesUploadCompleteEventArgs(args.commonErrorText, args.commonCallbackData);
  },
  OnFileUploadComplete: function(args) {
   this.FileUploadComplete.FireEvent(this, args);
  },
  OnFileUploadStart: function(args) {
   if(!this.FilesUploadStart.IsEmpty())
    this.FilesUploadStart.FireEvent(this, args);
   else if(!this.FileUploadStart.IsEmpty())
    this.FileUploadStart.FireEvent(this, args);
  },
  OnUploadingProgressChangedInternal: function(args) {
   this.RaiseUploadingProgressChanged(args);
   this.viewManager.UpdateProgress(args);
  },
  RaiseUploadingProgressChanged: function(args) {
   this.UploadingProgressChanged.FireEvent(this, args);
  },
  raiseDropZoneEnter: function(args) {
   this.DropZoneEnter.FireEvent(this, args);
  },
  raiseDropZoneLeave: function(args) {
   this.DropZoneLeave.FireEvent(this, args);
  },
  GetProgressPanel: function () {
   return this.domHelper.GetChildElement(IdSuffixes.Progress.Panel);
  },
  GetProgressControl: function() {
   return this.viewManager.GetProgressControl();
  },
  InitializeHandlers: function() {
   this.viewManager.StateChanged.AddHandler(function(args) {
    this.OnViewManagerStateChange(args);
   }.aspxBind(this));
   this.fileInfosCache.FileListChanged.AddHandler(function(args) {
    this.OnFileListChanged(args);
   }.aspxBind(this));
  },
  AdjustMainElementWidth: function() {
   var element = this.GetMainElement();
   if(this.IsDisplayed() && element.style.width == "") {
    element.style.width = ASPx.GetCurrentStyle(element).width;
   }
  },
  OnViewManagerStateChange: function(args) {
   args.fileInfos = this.Validate(args.fileInfos);
   this.fileInfosCache.Update(args);
  },
  Validate: function(fileInfos) {
   return this.fileValidator.validate(fileInfos);
  },
  UpdateErrorMessageCell: function(index, errorText, isValid) {
   this.viewManager.UpdateErrorMessageCell(index, errorText, isValid);
  },
  OnFileListChanged: function(args) {
   args.isStateChanged = true;
   this.viewManager.RefreshViews(args);
   if(args.fileCountChanged || !this.options.enableMultiSelect)
    this.RaiseTextChanged(args.inputIndex);
   if(this.options.autoStart)
    this.Upload();
  },
  OnPluginLoaded: function(index) {
   this.viewManager.SetFileInputRowEnabled(true, index);
  },
  OnDocumentMouseUp: function() {
   this.viewManager.OnDocumentMouseUp();
  },
  OnDocumentKeyDown: function(e) {
   this.viewManager.OnDocumentKeyUpDown(e, true);
  },
  OnDocumentKeyUp: function(e) {
   this.viewManager.OnDocumentKeyUpDown(e);
  },
  InvokeTextChangedInternal: function(index) {
   this.viewManager.InvokeTextChangedInternal(index);
  },
  OnErrorInternal: function(args) {
   this.viewManager.HandleError(args);
  },
  raiseErrorOccurred: function(args) {
   args.validationSettings = this.getErrorOccurredValidationSettings();
   if(this.IsAdvancedModeEnabled())
    this.ValidationErrorOccurred.FireEvent(this, args);
  },
  getErrorOccurredValidationSettings: function() {
   var validationSettings = this.validationSettings;
   var invalidFileNameCharacters = Constants.INVALID_FILENAME_CHARACTERS.slice(0);
   return new ASPxClientUploadControlValidationSettings(validationSettings.maxFileSize, validationSettings.maxFileCount || 0, validationSettings.allowedFileExtensions || [], invalidFileNameCharacters);
  },
  setJSProperties: function(JSProperties) {
   for(var property in JSProperties) {
    if(!JSProperties.hasOwnProperty(property)) continue;
    this[property] = JSProperties[property];
   }
  },
  GetFileInputCountInternal: function() {
   return this.domHelper.GetFileInputCountInternal();
  },
  RaiseTextChanged: function(inputIndex) {
   if(!this.TextChanged.IsEmpty()) {
    var args = new ASPxClientUploadControlTextChangedEventArgs(inputIndex);
    this.TextChanged.FireEvent(this, args);
   }
  },
  raiseFileInputCountChanged: function() {
   if(!this.FileInputCountChanged.IsEmpty()) {
    var args = new ASPxClientEventArgs();
    this.FileInputCountChanged.FireEvent(this, args);
   }
  },
  isControlInitialized: function() {
   return this.isInitialized && this.IsDOMInitialized();
  },
  IsRightToLeft: function() {
   return ASPx.IsElementRightToLeft(this.GetMainElement());
  },
  IsSLPluginInstalled: function () {
   if(!this.isSlInstalled) {
    var pluginName = Constants.SL_PLATFORM_NAME + " Plug-In";
    try {
     if(typeof (ActiveXObject) != 'undefined') {
      var slControl = new ActiveXObject('AgControl.AgControl');
      if(slControl != null)
       this.isSlInstalled = true;
     }
     else if(navigator.plugins[pluginName])
      this.isSlInstalled = true;
    } catch (e) { }
   }
   return this.isSlInstalled;
  },
  IsSLPluginSupported: function () {
   return !(ASPx.Browser.Safari && ASPx.Browser.MajorVersion == 5);
  },
  IsSLPluginAvailable: function () {
   return this.IsSLPluginInstalled() && this.IsSLPluginSupported();
  },
  IsShowPlatformErrorElement: function () {
   return this.advancedModeEnabled && !ASPxClientUploadControl.IsFileApiAvailable() && !this.IsSLPluginAvailable() && !this.autoModeEnabled;
  },
  IsHelperElementReady: function(index) {
   return this.options.uploadHelper.IsHelperElementReady(index);
  },
  IsAdvancedModeEnabled: function() {
   return this.options.advancedModeEnabled;
  },
  UploadFileFromUser: function() {
   this.Upload();
  },
  UploadFile: function() {
   this.Upload();
  },
  AddFileInput: function() {
   this.viewManager.AddFileInput();
  },
  RemoveFileInput: function(index) {
   this.viewManager.RemoveFileInput(index);
  },
  RemoveFileFromSelection: function(param) {
   if(this.advancedModeEnabled && !this.isInCallback)
    this.fileInfosCache.RemoveFile(param);
  },
  GetSelectedFiles: function(inputIndex) {
   if(!ASPx.IsExists(inputIndex)) inputIndex = 0;
   return this.fileInfosCache.getSelectedFiles(inputIndex);
  },
  GetText: function(index) {
   return this.viewManager.GetText(index);
  },
  GetFileNames: function(index) {
   return this.viewManager.getFileNames(index);
  },
  GetFileInputElement: function() {
   return this.viewManager.GetFileInputElement();
  },
  SetCustomText: function(text, index) {
   this.viewManager.setText(text, index || 0);
  },
  SetCustomTooltip: function(tooltip, index) {
   this.viewManager.setTooltip(tooltip, index || 0);
  },
  GetFileInputCount: function () {
   return this.GetFileInputCountInternal();
  },
  SetFileInputCount: function(count) {
   this.viewManager.SetFileInputCount(count);
  },
  SetEnabled: function(enabled) {
   this.SetEnabledInternal(enabled);
  },
  GetEnabled: function() {
   return this.clientEnabled;
  },
  SetEnabledInternal: function(enabled, initialization) {
   if(this.clientEnabled !== enabled || initialization) {
    this.clientEnabled = enabled;
    this.viewManager.SetEnabled(enabled);
   }
  },
  Upload: function() {
   var fileInfos = this.fileInfosCache.Get(),
    filesCount = fileInfos.length;
   if(filesCount) {
    var uploadStarted = this.uploadManager.UploadFileFromUser(fileInfos);
    if(uploadStarted)
     this.viewManager.SetViewsEnabled(false);
   }
  },
  Cancel: function () {
   this.uploadManager.CancelUploading(true);
  },
  ClearText: function() {
   this.fileInfosCache.clear();
  },
  SetAddButtonText: function (text) {
   this.viewManager.SetAddButtonText(text);
  },
  SetUploadButtonText: function (text) {
   this.viewManager.SetUploadButtonText(text);
  },
  GetAddButtonText: function () {
   return this.viewManager.GetAddButtonText();
  },
  GetUploadButtonText: function () {
   return this.viewManager.GetUploadButtonText();
  },
  SetExternalDropZoneID: function(ids) {
   this.viewManager.SetExternalDropZoneID(ids);
  },
  SetDialogTriggerID: function(ids) {
   this.viewManager.SetDialogTrigger({ idsString: ids });
  },
  SetDialogTriggerSelector: function(selector) {
   this.viewManager.SetDialogTrigger({ selector: selector });
  },
  OnDragEnter: function(args) {
   this.viewManager.OnDragEnter(args);
  },
  OnDragLeave: function(args) {
   this.viewManager.OnDragLeave(args);
  },
  OnDrop: function(args) {
   this.viewManager.OnDrop(args);
  },
  AdjustControlCore: function() {
   ASPxClientControl.prototype.AdjustControlCore.call(this);
   this.viewManager.AdjustSize();
  },
  OnCallback: function(result) {
   this.uploadManager.onFileNameHandlingCallback(result);
  },
  OnCallbackError: function (result, data) {
   this.uploadManager.onFileNameHandlingCallbackError(result);
  },
  ShowTooManyFilesError: function () {
   ASPx.ShowErrorAlert(this.tooManyFilesErrorText);
  },
  IsInputsVisible: function() {
   return this.viewManager.isInputsVisible();
  },
  SuppressFileDialog: function(suppress) {
   this.viewManager.suppressFileDialog(suppress);
  }
 });
 ASPxClientUploadControl.Cast = ASPxClientControl.Cast;
 var ASPxFileValidator = ASPx.CreateClass(null, {
  constructor: function(options) {
   this.validationSettings = options.validationSettings;
   this.options = options;
   this.validators = this.CreateFileValidators();
   this.ValidationErrorInternal = new ASPxClientEvent();
   this.ValidationErrorOccurredInternal = new ASPxClientEvent();
  },
  clearValidationResult: function() {
   this.result = {
    validFileInfos: [],
    invalidFileInfos: [],
    isValid: true,
    exceedCount: 0,
    initialFilesCount: 0,
    errorText: ""
   };
  },
  getFileExtension: function (fileName) {
   return fileName.replace(/.*?(\.[^.\\\/:*?\"<>|]+$)/, "$1");
  },
  CreateFileValidators: function () {
   var that = this;
   var validators = {
    fileName: {
     value: true,
     errorText: that.validationSettings.invalidWindowsFileNameErrorText,
     errorType: ASPxClientUploadControlValidationErrorTypeConsts.FileNameContainsInvalidCharacter,
     isValid: function(fileInfo) {
      var fileName = ASPx.Str.Trim(fileInfo.fileName),
       forbiddenCharsRegExp = /^[^\\/:\*\?"<>\|]+$/,
       forbiddenNamesRegExp = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i;
      return forbiddenCharsRegExp.test(fileName) && !forbiddenNamesRegExp.test(fileName);
     },
     getErrorText: function() {
      return this.errorText;
     }
    },
    fileSize: {
     value: this.validationSettings.maxFileSize,
     errorText: this.validationSettings.maxFileSizeErrorText,
     errorType: ASPxClientUploadControlValidationErrorTypeConsts.MaxFileSizeExceeded,
     isValid: function (fileInfo) {
      return fileInfo.fileSize <= this.value;
     },
     getErrorText: function () {
      return this.errorText.replace("{0}", this.value);
     }
    },
    fileExtensions: {
     value: this.validationSettings.allowedFileExtensions,
     errorText: this.validationSettings.notAllowedFileExtensionErrorText,
     errorType: ASPxClientUploadControlValidationErrorTypeConsts.NotAllowedFileExtension,
     isValid: function (fileInfo) {
      var fileExtension = that.getFileExtension(fileInfo.fileName).toLowerCase();
      return ASPx.Data.ArrayIndexOf(this.value, fileExtension) != -1;
     },
     getErrorText: function () {
      return this.errorText;
     }
    }
   };
   return this.options.advancedModeEnabled ? validators : { fileName: validators["fileName"] };
  },
  validateFileCore: function(fileInfo) {
   for(var validatorName in this.validators) {
    if(!this.validators.hasOwnProperty(validatorName))
     continue;
    var validator = this.validators[validatorName];
    if(validator != null && validator.value) {
     if(!validator.isValid(fileInfo)) {
      this.result.commonErrorText = validator.getErrorText();
      this.result.invalidFileInfos.push(new ASPxClientUploadControlInvalidFileInfo(fileInfo.fileName, fileInfo.fileSize, validator.errorType));
      return false;
     }
    }
   }
   return true;
  },
  validate: function(fileInfos) {
   this.clearValidationResult();
   this.validateFiles(fileInfos);
   if(!this.result.isValid) {
    var errorOccurredArgs = this.raiseValidationErrorOccurred(this.result.errorText, this.result.invalidFileInfos);
    this.raiseValidationError(errorOccurredArgs);
   }
   return this.result.validFileInfos;
  },
  validateFiles: function(fileInfos) {
   this.result.initialFilesCount = ASPxFileInfoCache.getPlainArray(fileInfos).length;
   this.result.validFileInfos = fileInfos;
   if(this.validationSettings.maxFileCount > 0 && this.options.enableMultiSelect)
    this.validateFilesCount(fileInfos);
   this.validateFilesProperties();
  },
  validateFilesProperties: function() {
   var fileInfos = this.result.validFileInfos;
   for(var i = 0; i < fileInfos.length; i++) {
    var validFileInfos = [];
    this.validateFilesInternal(fileInfos[i].reverse(), validFileInfos);
    fileInfos[i] = validFileInfos.slice();
    fileInfos[i].reverse();
   }
   var isValid = !this.result.invalidFileInfos.length;
   if(!isValid)
    this.result.errorText = this.prepareResultErrorText();
   this.result.isValid = this.result.isValid && isValid;
   this.result.validFileInfos = fileInfos;
  },
  validateFilesInternal: function(fileInfos, validFileInfos) {
   ASPx.Data.ForEach(fileInfos, function(fileInfo) {
    var isValid = this.validateFileCore(fileInfo);
    if(isValid)
     validFileInfos.push(fileInfo);
    else
     fileInfo.dispose();
   }.aspxBind(this));
  },
  validateFilesCount: function() {
   var fileInfosArray = ASPxFileInfoCache.getPlainArray(this.result.validFileInfos),
    invalidFilesCount,
    validFileInfos;
   invalidFilesCount = fileInfosArray.length - this.validationSettings.maxFileCount;
   validFileInfos = fileInfosArray.splice(0, this.validationSettings.maxFileCount);
   if(invalidFilesCount < 0)
    invalidFilesCount = 0;
   ASPx.Data.ForEach(fileInfosArray.reverse(), function(fileInfo) {
    this.result.invalidFileInfos.push(new ASPxClientUploadControlInvalidFileInfo(fileInfo.fileName, fileInfo.fileSize, ASPxClientUploadControlValidationErrorTypeConsts.MaxFileCountExceeded));
    if(fileInfo.fileName)
     fileInfo.dispose();
   }.aspxBind(this));
   this.result.exceedCount = invalidFilesCount;
   this.result.validFileInfos = [validFileInfos];
   this.result.errorText = this.prepareMaxFileCountErrorText();
   this.result.isValid = invalidFilesCount === 0;
  },
  prepareMaxFileCountErrorText: function() {
   var errorText = "";
   if(this.result.exceedCount > 0) {
    errorText = this.validationSettings.maxFileCountErrorText
     .replace("{0}", this.result.exceedCount)
     .replace("{1}", this.validationSettings.maxFileCount);
   }
   return errorText;
  },
  prepareResultErrorText: function() {
   var errorText,
    multipleFilesSelected = this.result.initialFilesCount > 1 && this.options.enableMultiSelect;
   if(multipleFilesSelected) {
    errorText = this.validationSettings.multiSelectionErrorText
     .replace("{0}", this.result.invalidFileInfos.length)
     .replace("{1}", this.validators.fileSize.value)
     .replace("{2}", this.getInvalidFileNames(this.result.invalidFileInfos).join(', '));
   } else
    errorText = this.result.commonErrorText;
   if(this.result.errorText.length)
    errorText += "\n\n" + this.result.errorText;
   return errorText;
  },
  getInvalidFileNames: function(invalidFileInfos) {
   var result = [];
   ASPx.Data.ForEach(invalidFileInfos, function(fileInfo) {
    result.push(fileInfo.fileName);
   });
   return result;
  },
  raiseValidationErrorOccurred: function(errorText, invalidFiles) {
   var args = new ASPxClientUploadControlValidationErrorOccurredEventArgs(errorText, invalidFiles);
   this.ValidationErrorOccurredInternal.FireEvent(args);
   return args;
  },
  raiseValidationError: function(errorOccurredArgs) {
   var args = {
    text: errorOccurredArgs.errorText,
    showAlert: errorOccurredArgs.showAlert,
    type: ASPxUploadErrorTypes.Validation
   };
   this.ValidationErrorInternal.FireEvent(args);
  }
 });
 var ASPxFileInfo = ASPx.CreateClass(null, {
  constructor: function(file, publicFileObject, inputIndex, input) {
   this.file = file;
   this.publicFileObject = publicFileObject;
   this.fileName = file.name || file.fileName;
   this.fileSize = file.size || file.fileSize || 0;
   this.fileType = file.type || file.fileType || "";
   this.fullName = "C:\\fakepath\\" + this.fileName;
   this.inputIndex = inputIndex;
   this.OnDispose = new ASPxClientEvent();
   this.OnUploadStart = new ASPxClientEvent();
   this.OnUploadComplete = new ASPxClientEvent();
  },
  dispose: function() {
   this.OnDispose.FireEvent(this);
  }
 });
 var ASPxViewManager = ASPx.CreateClass(null, {
  constructor: function(options) {
   this.options = options;
   this.domHelper = options.domHelper;
   this.options.parentNode = this.GetUploadInputsTable();
   this.progressPanelView = null;
   this.InternalError = new ASPxClientEvent();
   this.StateChanged = new ASPxClientEvent();
   this.UploadCancelled = new ASPxClientEvent();
   this.UploadStarted = new ASPxClientEvent();
   this.FileInputCountChangedInternal = new ASPxClientEvent();
   this.DropZoneEnter = new ASPxClientEvent();
   this.DropZoneLeave = new ASPxClientEvent();
   this.DropZoneDropInternal = new ASPxClientEvent();
   this.InternalError.AddHandler(this.HandleError.aspxBind(this));
  },
  InlineInitialize: function() {
   this.initializeViewCollection(this.options);
   this.applyToViewCollection("InlineInitialize");
   this.errorView.InlineInitialize();
  },
  Initialize: function() {
   this.initializeViews();
   this.isInCallback = false;
   this.initializeHandlers();
  },
  initializeViewCollection: function(options) {
   this.viewCollection = [];
   var inputView = this.CreateFileInputView(options);
   if(inputView)
    this.viewCollection.push(inputView);
   if(options.enableFileList)
    this.viewCollection.push(this.createFileListView(options));
   if(options.enableDragAndDrop) {
    var dropZoneView = this.createDropZoneView(options);
    dropZoneView.DropZoneEnterInternal.AddHandler(this.raiseDropZoneEnter.aspxBind(this));
    dropZoneView.DropZoneLeaveInternal.AddHandler(this.raiseDropZoneLeave.aspxBind(this));
    dropZoneView.DropZoneDropInternal.AddHandler(this.raiseDropZoneDrop.aspxBind(this));
    this.viewCollection.push(dropZoneView);
   }
   if(options.enableProgressPanel) {
    this.progressPanelView = this.createProgressPanelView(options);
    this.viewCollection.push(this.progressPanelView);
   }
   this.uploadButton = this.createButtonView(options, IdSuffixes.Input.ButtonCell.Upload, this.uploadButtonHandler.aspxBind(this));
   this.cancelButton = this.createButtonView(options, IdSuffixes.Input.ButtonCell.Cancel, this.cancelButtonHandler.aspxBind(this));
   this.errorView = this.createErrorView(options);
   ASPx.Data.ForEach(this.viewCollection, function(view) {
    view.ErrorOccurred.AddHandler(this.HandleError.aspxBind(this));
   }.aspxBind(this));
  },
  createProgressPanelView: function(options) {
   return new ASPxProgressPanelView(options);
  },
  createButtonView: function(options, idSuffix, handler) {
   return new ASPxButtonView(options, idSuffix, handler);
  },
  createDropZoneView: function(options) {
   return new ASPxDropZoneView(options);
  },
  createFileListView: function(options) {
   return new ASPxFileListView(options);
  },
  createErrorView: function(options) {
   return new ASPxErrorView(options);
  },
  initializeViews: function() {
   this.applyToViewCollection("Initialize");
  },
  uploadButtonHandler: function() {
   this.UploadStarted.FireEvent();
  },
  cancelButtonHandler: function() {
   this.UploadCancelled.FireEvent();
  },
  GetUploadInputsTable: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Input.UploadInputsTable);
  },
  initializeHandlers: function() {
   for(var i = 0; i < this.viewCollection.length; i++) {
    var view = this.viewCollection[i];
    view.StateChangedInternal.AddHandler(
     function(view, args) {
      this.OnViewStateChanged(view, args);
     }.aspxBind(this));
   }
  },
  CreateFileInputView: function(options) {
   var fileInputStrategy;
   var fileInputView = this.createFileInputViewCore(options);
   if(fileInputView) {
    if (this.isInputsVisible()) {
     fileInputStrategy = new ASPxMultiFileInputView(options, fileInputView);
     fileInputStrategy.FileInputCountChangedInternal.AddHandler(this.raiseFileInputCountChanged.aspxBind(this));
     this.addButton = new ASPxButtonView(options, IdSuffixes.Input.ButtonCell.Add, function() {
      fileInputStrategy.addFileInput();
     }.aspxBind(fileInputStrategy));
     this.addButton.SetEnabled(true);
     this.domHelper.isMultiFileInput = true;
     if (fileInputStrategy)
      fileInputStrategy.FocusNeedResetInternal.AddHandler(this.resetFocus.aspxBind(this));
    }
    else
     fileInputStrategy = this.createInvisibleFileInputDecorator(options, fileInputView);
   }
   return fileInputStrategy;
  },
  createFileInputViewCore: function(options) {
   var fileInputView;
   if (options.isNative)
    fileInputView = ASPxNativeInputView;
   else if (options.advancedModeEnabled || options.autoModeEnabled) {
    if (options.isFileApiAvailable)
     fileInputView = ASPxHTML5InputView;
    else if (options.isSLEnabled)
     fileInputView = ASPxSLInputView;
   } else
    fileInputView = ASPxStandardInputView;
   if (!fileInputView) {
    if (options.autoModeEnabled)
     fileInputView = ASPxStandardInputView;
    else if (options.advancedModeEnabled)
     this.InternalError.FireEvent({ type: ASPxUploadErrorTypes.Platform });
   }
   return fileInputView;
  },
  createInvisibleFileInputDecorator: function(options, fileInputView) {
   return new ASPxInvisibleFileInputDecorator(options, fileInputView);
  },
  applyToViewCollection: function(method, args) {
   args = args || [];
   var result;
   ASPx.Data.ForEach(this.viewCollection, function(view) {
    if(view[method])
     result = view[method].apply(view, args);
   });
   return result;
  },
  resetFocus: function(view, args) {
   var element = view.GetNextFocusElement(args);
   if(!args.backward) {
    if(!element)
     element = this.addButton && this.addButton.GetLink();
    if(!element)
     element = this.uploadButton && this.uploadButton.GetLink();
   }
   if(element) {
    element.focus();
    ASPx.Evt.PreventEvent(args.event);
   }
  },
  showFileInputError: function(error) {
   this.applyToViewCollection("showError", [error]);
  },
  showPlatformError: function() {
   ASPx.SetElementDisplay(this.GetUploadInputsTable(), false);
   ASPx.SetElementDisplay(this.getPlatformErrorPanel(), true);
  },
  getPlatformErrorPanel: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Error.PlatformErrorTable);
  },
  showValidationError: function(error) {
   if(error.showAlert)
    ASPx.ShowErrorAlert(error.text);
  },
  raiseFileInputCountChanged: function() {
   var args = new ASPxClientEventArgs();
   this.FileInputCountChangedInternal.FireEvent(this, args);
  },
  raiseDropZoneEnter: function(args) {
   this.DropZoneEnter.FireEvent(args);
  },
  raiseDropZoneLeave: function(args) {
   this.DropZoneLeave.FireEvent(args);
  },
  raiseDropZoneDrop: function(args) {
   this.DropZoneDropInternal.FireEvent(args);
  },
  OnViewStateChanged: function(view, args) {
   if(args.uploadCancelled)
    this.UploadCancelled.FireEvent();
   else
    this.StateChanged.FireEvent(args);
  },
  OnUploadInitiated: function() {
   this.errorView.Clear();
   this.applyToViewCollection("clearErrors");
   this.applyToViewCollection("OnUploadInitiated");
  },
  OnBeginProcessUploading: function() {
   this.applyToViewCollection("OnBeginProcessUploading");
   this.SetViewsEnabled(false);
  },
  OnUploadFilesComplete: function(args) {
   if(!this.lock) {
    this.lock = true;
    this.ShowCommonError(args);
    this.SetViewsEnabled(true);
    if(args.uploadCancelled)
     this.uploadButton.SetEnabled(true);
    this.applyToViewCollection("OnUploadFilesComplete", [args]);
    this.lock = false;
   }
  },
  OnDocumentMouseUp: function() {
   this.applyToViewCollection("OnDocumentMouseUp");
  },
  OnDocumentKeyUpDown: function(e, isKeydownEvent) {
   this.applyToViewCollection("OnDocumentKeyUpDown", [e, isKeydownEvent]);
  },
  OnDragEnter: function(args) {
   this.applyToViewCollection("OnDragEnter", args);
  },
  OnDragLeave: function(args) {
   this.applyToViewCollection("OnDragLeave", args);
  },
  OnDrop: function(args) {
   this.applyToViewCollection("OnDrop", args);
  },
  HandleError: function(error) {
   switch (error.type) {
    case ASPxUploadErrorTypes.Common:
     this.errorView.UpdateCommonErrorDiv(error.text);
     break;
    case ASPxUploadErrorTypes.InputRowError:
     this.showFileInputError(error);
     break;
    case ASPxUploadErrorTypes.Platform:
     this.showPlatformError();
     break;
    case ASPxUploadErrorTypes.Validation:
     this.showValidationError(error);
     break;
   }
  },
  SetFileInputRowEnabled: function(enabled, index) {
   this.applyToViewCollection("SetFileInputRowEnabled", [enabled, index]);
  },
  RefreshViews: function(args) {
   if(!this.lock) {
    this.lock = true;
    this.errorView.Clear();
    args.skipRefreshInput = this.options.enableFileList && this.options.enableDragAndDrop;
    ASPx.Data.ForEach(this.viewCollection, function(view) {
     view.Refresh(args);
    });
    this.lock = false;
   }
   this.uploadButton.SetEnabled(!!args.fileInfosCount);
  },
  GetText: function(index) {
   index = index || 0;
   var args = [index];
   var text = this.applyToViewCollection("GetText", args);
   return text || "";
  },
  getFileNames: function(index) {
   index = index || 0;
   var args = [index];
   return this.applyToViewCollection("getFileNames", args);
  },
  setText: function(text, index) {
   this.applyToViewCollection("setText", [text, index]);
  },
  setTooltip: function(text, index) {
   this.applyToViewCollection("setTooltip", [text, index]);
  },
  AddFileInput: function() {
   if(!this.options.enableDragAndDrop && !this.options.enableFileList)
    this.applyToViewCollection("addFileInput");
  },
  RemoveFileInput: function(index) {
   this.applyToViewCollection("removeFileInput", [index]);
  },
  SetFileInputCount: function(count) {
   this.applyToViewCollection("setFileInputCount", [count]);
  },
  GetFileInputElement: function(index) {
   var args = [index];
   return this.applyToViewCollection("GetFileInputElement", args);
  },
  Clear: function(args) {
   if(!this.lock) {
    this.lock = true;
    this.applyToViewCollection("Refresh", [ASPxEmptyRefreshArgs]);
    this.lock = false;
   }
  },
  ShowCommonError: function(args) {
   this.errorView.Refresh(args);
  },
  UpdateProgress: function(args) {
   this.applyToViewCollection("UpdateProgress", [args]);
  },
  InCallbackChanged: function(isInCallback) {
   this.applyToViewCollection("setInCallback", [isInCallback]);
  },
  SetViewsEnabled: function(enabled) {
   this.applyToViewCollection("SetEnabled", [enabled]);
   if(!enabled)
    this.uploadButton.SetEnabled(false);
   if(this.addButton)
    this.addButton.SetEnabled(enabled);
  },
  InvokeTextChangedInternal: function(index) {
   if(!this.lock)
    this.applyToViewCollection("InvokeTextChangedInternal", [index]);
  },
  getButtonLinkById: function(idPrefix) {
   var button = this.domHelper.GetChildElement(idPrefix),
    link = ASPx.GetNodeByTagName(button, "A", 0);
   return link || {};
  },
  SetAddButtonText: function(text) {
   this.getButtonLinkById(IdSuffixes.Input.ButtonCell.Add).innerHTML = text;
  },
  SetUploadButtonText: function(text) {
   this.getButtonLinkById(IdSuffixes.Input.ButtonCell.Upload).innerHTML = text;
  },
  GetAddButtonText: function() {
   return this.getButtonLinkById(IdSuffixes.Input.ButtonCell.Add).innerHTML || null;
  },
  GetUploadButtonText: function() {
   return this.getButtonLinkById(IdSuffixes.Input.ButtonCell.Upload).innerHTML || null;
  },
  SetEnabled: function(enabled) {
   this.SetViewsEnabled(enabled);
  },
  SetExternalDropZoneID: function(ids) {
   this.applyToViewCollection("SetExternalDropZoneID", [ids.split(";")]);
  },
  SetDialogTrigger: function(triggerElementSelectors) {
   this.applyToViewCollection("setDialogTrigger", [triggerElementSelectors]);
  },
  setInlineDropZoneAnchorElementID: function(id) {
   this.applyToViewCollection("SetInlineDropZoneAnchorElementID", [id]);
  },
  GetProgressControl: function() {
   if(this.options.enableProgressPanel)
    return this.progressPanelView.GetProgressControl();
   return null;
  },
  UpdateErrorMessageCell: function(index, errorText, isValid) {
   var args = {
    index: index,
    errorText: errorText,
    isValid: isValid
   };
   this.errorView.UpdateErrorMessageCell(args);
  },
  AdjustSize: function() {
   this.adjustMainElementWidth();
   this.applyToViewCollection("AdjustSize");
  },
  adjustMainElementWidth: function () {
   var element = this.domHelper.GetMainElement();
   if(this.domHelper.IsDisplayed() && element.style.width == "") {
    element.style.width = ASPx.GetCurrentStyle(element).width;
   }
  },
  isInputsVisible: function() {
   return !ASPx.ElementHasCssClass(this.domHelper.GetMainElement(), CSSClasses.HiddenUI);
  },
  suppressFileDialog: function(suppress) {
   this.applyToViewCollection("suppressFileDialog", [suppress]);
  }
 });
 var ASPxBaseView = ASPx.CreateClass(null, {
  constructor: function(options) {
   options = options || [];
   this.baseName = options.name;
   this.IsRightToLeft = options.IsRightToLeft;
   this.options = options;
   this.domHelper = options.domHelper;
   this.id = options.id || 0;
   this.containerNode = options.containerNode;
   this.supressEvents = false;
   this.cache = {};
   this.buttonEventHandlers = {};
   this.StateChangedInternal = new ASPxClientEvent();
   this.ErrorOccurred = new ASPxClientEvent();
  },
  Initialize: function() { },
  InlineInitialize: function() { },
  GetContainerNode: function() {
   return this.containerNode || this.domHelper.GetChildElement(IdSuffixes.Input.UploadInputsTable);
  },
  SetButtonEnabled: function(element, enabled) {
   this.ChangeButtonEnabledState(element, enabled);
   this.ChangeButtonEnabledAttributes(element, ASPx.Attr.ChangeAttributesMethod(enabled), enabled);
  },
  ChangeButtonEnabledState: function(element, enabled) {
   if(element)
    ASPx.GetStateController().SetElementEnabled(element, enabled);
  },
  ChangeButtonEnabledAttributes: function(element, method, enabled) {
   if(element) {
    var link = ASPx.GetNodeByTagName(element, "A", 0);
    if(link) {
     var isBrowseButton = element.className.indexOf(CSSClasses.BrowseButtonCell) != -1;
     if(!isBrowseButton)
      ASPx.Attr.SetOrRemoveAttribute(link, "tabindex", !enabled ? "-1" : "0");
     ASPx.Attr.SetOrRemoveAttribute(link, "unselectable", !enabled ? "on" : null);
     if(ASPx.Browser.NetscapeFamily || ASPx.Browser.WebKitFamily) {
      method = this.ChangeEventsMethod(!enabled);
      method(link, "mousedown", function(e) {
       ASPx.Evt.PreventEvent(e);
       return false;
      }, true);
     }
    }
   }
  },
  attachButtonHandler: function(element, eventName, enabled) {
   var method = this.ChangeEventsMethod(enabled);
   method(element, eventName, this.buttonEventHandlers[element.id + "_" + eventName]);
  },
  GetElementFromCacheByClassName: function(className) {
   if(!this.cache[className])
    this.cache[className] = ASPx.GetNodesByPartialClassName(this.GetRenderResult(), className)[0];
   return this.cache[className];
  },
  GetID: function() {
   return this.id;
  },
  GetFullID: function() {
   return this.GetName() + this.GetInputRowPrefix() + this.GetID();
  },
  GetName: function() {
   return this.baseName;
  },
  GetUploadInputsTable: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Input.UploadInputsTable);
  },
  GetInputRow: function(id) {
   return this.domHelper.GetChildElement(this.GetInputRowId(id));
  },
  GetInputRowPrefix: function() {
   return IdSuffixes.Input.FileInputRow;
  },
  GetInputRowId: function(id) {
   return this.GetInputRowPrefix() + (id || this.GetID());
  },
  GetRowTemplate: function() {
   return this.GetInputRow("T");
  },
  GetFileInfos: function() {
   return this.fileInfos;
  },
  getFileInfos: function() {
   return this.fileInfos;
  },
  GetFileNames: function(isShortName) {
   var fileInfos = this.getFileInfos(),
    files = [];
   for(var i in fileInfos) {
    if(fileInfos[i])
     files.push(isShortName ? fileInfos[i].fileName : fileInfos[i].fullName);
   }
   return files;
  },
  OnUploadFilesComplete: function() { },
  OnBeginProcessUploading: function() { },
  setInCallback: function(isInCallback) {
   this.isInCallback = isInCallback;
  },
  IsSlModeEnabled: function() {
   return this.options.isSLEnabled && !this.options.isFileApiAvailable && (this.options.advancedModeEnabled || this.options.autoModeEnabled);
  },
  RaiseStateChangedInternal: function(view) {
   var args = view.prepareInternalStateChangedArgs(view);
   if(!this.supressEvents && this.StateChangedInternal)
    this.StateChangedInternal.FireEvent(this, args);
  },
  raiseError: function(errorText) {
   var args = {
    type: ASPxUploadErrorTypes.Validation,
    text: errorText,
    showAlert: true
   };
   this.ErrorOccurred.FireEvent(args);
  },
  prepareInternalStateChangedArgs: function(view) {
   var fileInfos = view.GetFileInfos.call(view),
    inputIndex = view.GetID.call(view);
   return new ASPxViewStateChangedInternalArgs(fileInfos, inputIndex);
  },
  AttachEventForElement: function(element, eventName, func, detachOldEvent) {
   if(detachOldEvent && element["dx" + eventName])
    ASPx.Evt.DetachEventFromElement(element, eventName, element["dx" + eventName]);
   element["dx" + eventName] = func;
   ASPx.Evt.AttachEventToElement(element, eventName, element["dx" + eventName]);
  },
  DetachEventForElement: function(element, eventName) {
   if(element["dx" + eventName]) {
    ASPx.Evt.DetachEventFromElement(element, eventName, element["dx" + eventName]);
    element["dx" + eventName] = null;
   }
  },
  ChangeEventsMethod: function(attach) {
   return attach ? this.AttachEventForElement : this.DetachEventForElement;
  },
  UpdateIndex: function() {},
  Clear: function() {
   this.refreshBase(ASPxEmptyRefreshArgs);
   this.RaiseStateChangedInternal(this);
  },
  Dispose: function() {
   this.dropElementCache();
   ASPx.RemoveElement(this.GetRenderResult());
  },
  SetEnabled: function(enabled) { },
  EnsureRender: function() {
   if(!this.GetRenderResult()) {
    this.Render();
    this.AfterRender();
   }
  },
  Render: function() { },
  AfterRender: function() { },
  Refresh: function(args) {
   this.supressEvents = true;
   this.refreshBase(args);
   this.supressEvents = false;
  },
  refreshBase: function(args) {
   this.updateFileInfos(args);
  },
  updateFileInfos: function(args) {
   this.fileInfos = args.fileInfos;
  },
  GetRenderResult: function() {
   if(!this.renderResult)
    this.renderResult = this.domHelper.GetChildElement(this.GetInputRowId());
   return this.renderResult;
  },
  getOwnerControl: function () {
   return aspxGetUploadControlCollection().Get(this.baseName);
  },
  dropElementCache: function(id) {
   ASPx.CacheHelper.DropCachedValue(this.getOwnerControl(), id || this.GetFullID());
  }
 });
 var ASPxButtonView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options, idSuffix, handler, disabledTemplate) {
   this.constructor.prototype.constructor.call(this, options);
   this.disabledItemTemplate = disabledTemplate;
   this.SetId(idSuffix);
   this.SetHandler(handler);
   this.CreateDisabledState();
   this.SetEnabled(false);
  },
  CreateDisabledState: function() {
   if(this.disabledItemTemplate) {
    ASPx.GetStateController().AddDisabledItem(this.GetName() + this.GetID(),
     this.disabledItemTemplate.className, this.disabledItemTemplate.cssText,
     this.disabledItemTemplate.postfixes, this.disabledItemTemplate.imageObjs,
     this.disabledItemTemplate.imagePostfixes);
   }
  },
  GetRenderResult: function() {
   return this.domHelper.GetChildElement(this.GetID());
  },
  GetLink: function() {
   return ASPx.GetNodeByTagName(this.GetRenderResult(), "A", 0);
  },
  SetId: function(id) {
   this.dropElementCache(this.GetName() + this.GetID());
   this.id = id;
  },
  SetHandler: function(handler) {
   this.handler = handler;
  },
  SetEnabled: function(enabled) {
   var method = this.ChangeEventsMethod(enabled),
    markup = this.GetRenderResult();
   if(markup) {
    method(this.GetRenderResult(), "click", this.handler, true);
    this.SetButtonEnabled(markup, enabled);
   }
  }
 });
 var ASPxCompositeView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.initialized = false;
   this.views = [];
   this.removeButtons = [];
   this.options.containerNode = this.GetContainerNode();
   this.internalCount = this.internalCount || 0;
   this.internalIndex = this.internalIndex || 0;
   this.viewPrototype = options.viewPrototype || this.viewPrototype || undefined;
   this.templates = options.templates;
   this.createViews();
  },
  createViews: function() {
   for(var i = 0; i < this.internalCount; i++)
    this.addView();
  },
  Initialize: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    view.Initialize();
    view.Refresh(ASPxEmptyRefreshArgs);
   });
   this.initialized = true;
  },
  InlineInitialize: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    view.InlineInitialize();
   });
  },
  addView: function(fileInfo) {
   var index = this.internalIndex;
   this.options.id = index;
   var view = new this.viewPrototype(this.options),
    removeButton = this.createButtonView(this.options, this.getRemoveButtonPostfix(index), function() {
     this.onRemoveButtonClick(index);
    }.aspxBind(this), this.templates.DisabledRemoveItem);
   view.EnsureRender(fileInfo);
   if(this.initialized) {
    view.Initialize();
    view.Refresh(ASPxEmptyRefreshArgs);
   }
   removeButton.SetEnabled(true);
   this.views[index] = view;
   this.removeButtons[index] = removeButton;
   view.StateChangedInternal.AddHandler(this.onInternalStateChanged, this);
   this.internalIndex++;
  },
  removeView: function(index) {
   if(this.views[index]) {
    this.removeButtons[index].SetEnabled(false);
    this.views[index].Dispose();
    this.views[index] = undefined;
    for(var viewIndex = index + 1; viewIndex < this.internalCount; viewIndex++) {
     var newIndex = viewIndex - 1;
     this.changeRemoveHandler(viewIndex, newIndex);
     this.views[viewIndex].UpdateIndex.call(this.views[viewIndex], newIndex);
     this.views[newIndex] = this.views[viewIndex];
     this.removeButtons[newIndex].SetEnabled(true);
    }
    this.internalCount--;
    this.internalIndex = this.internalCount;
    this.views.splice(this.internalCount, 1);
    this.RaiseStateChangedInternal(this);
   }
  },
  getRemoveButtonPostfix: function(index) {
   return  IdSuffixes.Input.ButtonCell.Remove + index;
  },
  onRemoveButtonClick: function(index) {
   this.disposeFileInfo(index);
   this.removeView(index);
  },
  changeRemoveHandler: function(oldIndex, newIndex) {
   this.removeButtons[oldIndex].SetEnabled(false);
   this.removeButtons[newIndex] = this.removeButtons[oldIndex];
   this.removeButtons[newIndex].SetId(this.getRemoveButtonPostfix(newIndex));
   this.removeButtons[newIndex].SetHandler(function() {
    this.onRemoveButtonClick(newIndex);
   }.aspxBind(this));
  },
  refreshView: function(view, commonArgs) {
   var args = this.getViewRefreshArgs(view, commonArgs);
   view.Refresh(args);
  },
  getViewRefreshArgs: function(view, commonArgs) {
   return {
    fileInfos: this.fileInfos[view.GetID()],
    isStateChanged: commonArgs.isStateChanged
   };
  },
  GetView: function(index) {
   return this.views[index];
  },
  clearViews: function() {
   ASPx.Data.ForEach(this.views, this.clearView.aspxBind(this));
  },
  clearView: function(view, index) {
   view.Clear();
  },
  FilterViews: function() {
  },
  GetContainerNode: function() {
   var inputsTable = this.domHelper.GetChildElement(IdSuffixes.Input.UploadInputsTable);
   return ASPx.GetChildByTagName(inputsTable, "TBODY");
  },
  onInternalStateChanged: function() {
   this.RaiseStateChangedInternal();
  },
  RaiseStateChangedInternal: function() {
   this.FilterViews();
   ASPxBaseView.prototype.RaiseStateChangedInternal.call(this, this);
  },
  SetFileInputRowEnabled: function(enabled, index) {
   if(this.views[index]) {
    this.views[index].SetFileInputRowEnabled(enabled);
    this.removeButtons[index].SetEnabled(enabled);
   }
  },
  GetRemoveButtonCell: function(index) {
   var renderResult = this.views[index].GetRenderResult();
   return ASPx.GetNodesByPartialClassName(renderResult, CSSClasses.RemoveButtonCell)[0];
  },
  OnUploadFilesComplete: function(args) {
   ASPx.Data.ForEach(this.views, function(view) {
    view.OnUploadFilesComplete.call(view, args);
   });
  },
  SetEnabled: function(enabled) {
   ASPx.Data.ForEach(this.views, function(view, index) {
    view.SetEnabled(enabled);
    this.removeButtons[index].SetEnabled(enabled);
   }.aspxBind(this));
  },
  ResetState: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    view.ResetState();
   });
  },
  GetFileInfos: function() {
   var fileInfos = [];
   ASPx.Data.ForEach(this.views, function(view) {
    fileInfos.push(view.GetFileInfos());
   });
   return fileInfos;
  },
  refreshBase: function(args) {
   ASPxBaseView.prototype.refreshBase.call(this, args);
   ASPx.Data.ForEach(this.views, function(view) {
    this.refreshView(view, args);
   }.aspxBind(this));
  },
  Clear: function() {
   this.supressEvents = true;
   this.clearViews();
   this.supressEvents = false;
  },
  createButtonView: function(options, idSuffix, handler) {
   return new ASPxButtonView(options, idSuffix, handler);
  }
 });
 var ASPxFileListItem = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.templateDisabledRemoveItem = this.options.templateDisabledRemoveItem;
  },
  Render: function() {
   var template = this.GetRowTemplate().cloneNode(true);
   template.id = this.GetFullID();
   this.GetContainerNode().appendChild(template);
   this.progressControl = this.cloneProgressControl(template);
   ASPx.SetElementDisplay(template, true);
   this.correctNameSpanWidth();
   this.RedefineAttributes();
   this.SetState(CSSClasses.FileList.State.Pending);
  },
  cloneProgressControl: function(template) {
   var progressBarTemplateName = this.baseName + IdSuffixes.Input.FileList.ProgressControl,
    templateProgressControl = ASPx.GetControlCollection().Get(progressBarTemplateName),
    clonedBarMarkup = this.getBarElement(template),
    indicatorDiv = templateProgressControl.GetIndicatorDiv(),
    indicatorClassName = ASPx.GetClassNameList(indicatorDiv)[0],
    clonedIndicatorDiv = ASPx.GetNodeByClassName(template, indicatorClassName),
    progressControl;
   this.progressBarBaseId = templateProgressControl.name;
   clonedIndicatorDiv.id = this.progressBarBaseId + this.GetID() + "_DI";
   clonedBarMarkup.id = this.progressBarBaseId + this.GetID();
   progressControl = this.createProgressBar();
   progressControl.mainElement = clonedBarMarkup;
   progressControl.displayMode = templateProgressControl.displayMode;
   progressControl.customDisplayFormat = templateProgressControl.customDisplayFormat;
   progressControl.position = templateProgressControl.position;
   progressControl.minimum = templateProgressControl.minimum;
   progressControl.maximum = templateProgressControl.maximum;
   progressControl.onePercentValue = templateProgressControl.onePercentValue;
   progressControl.AfterCreate();
   return progressControl;
  },
  getBarElement: function(template){
   return ASPx.GetNodesByPartialClassName(template, CSSClasses.FileList.ProgressBar)[0];
  },
  createProgressBar: function() {
   return new ASPxClientProgressBarBase(this.progressBarBaseId + this.GetID());
  },
  correctNameSpanWidth: function() {
   var progressBarShare = 0.283,
    fileNameShare = 1 - progressBarShare;
   var controlWidth = this.domHelper.GetMainElement().offsetWidth,
    fileRow = this.GetRenderResult(),
    fileNameCell = this.GetNameCell(fileRow),
    progressBarCell = this.getProgressBarCell(),
    stateDiv = ASPx.GetChildNodesByTagName(fileNameCell, "DIV");
   var fileNameWidth = fileNameShare * controlWidth - 1;
   var progressBarWidth = progressBarShare * controlWidth - 1;
   for(var i = 0; i < stateDiv.length; i++) {
    var fileNameLabel = ASPx.GetChildByTagName(stateDiv[i], "SPAN");
    fileNameLabel.style.maxWidth = (fileNameWidth - ASPx.GetLeftRightPaddings(fileNameLabel)) + "px";
    progressBarCell.style.width = progressBarWidth + "px";
   }
  },
  Dispose: function() {
   this.dropElementCache();
   this.GetRenderResult().parentNode.removeChild(this.GetRenderResult());
  },
  refreshBase: function(args) {
   ASPxBaseView.prototype.refreshBase.call(this, args);
   var fileRow = this.GetRenderResult(),
    fileNameCell = this.GetNameCell(fileRow),
    fileInfo = args.fileInfos;
   var stateDiv = ASPx.GetChildNodesByTagName(fileNameCell, "DIV");
   for(var i = 0; i < stateDiv.length; i++) {
    var fileNameLabel = ASPx.GetChildByTagName(stateDiv[i], "SPAN");
    fileNameLabel.innerHTML = fileInfo.fileName || "";
    fileNameLabel.title = fileInfo.fileName || "";
   }
   fileRow.aspxFileInfos = fileInfo;
  },
  GetFileInfos: function() {
   return ASPxBaseView.prototype.GetFileInfos.call(this);
  },
  RedefineAttributes: function(oldIndex) {
   this.dropElementCache();
   this.dropElementCache(this.GetRemoveButtonCell().id);
   this.GetRenderResult().id = this.GetFullID();
   this.GetRemoveButtonCell().id = this.GetRemoveRowButtonId();
   this.redefineProgressBarAttributes();
  },
  redefineProgressBarAttributes: function() {
   var progressbarMarkup = this.progressControl.GetMainElement(),
    progressBarIndicatorMarkup = this.progressControl.GetIndicatorDiv();
   this.dropElementCache(progressbarMarkup.id);
   this.dropElementCache(progressBarIndicatorMarkup.id);
   progressbarMarkup.id = this.progressBarBaseId + this.GetID();
   progressBarIndicatorMarkup.id = this.progressBarBaseId + this.GetID() + "_DI";
  },
  setId: function(newId) {
   this.id = newId;
  },
  SetState: function(newState) {
   var stateDiv = ASPx.GetChildNodesByTagName(this.GetNameCell(), "DIV")[0];
   if(!ASPx.ElementHasCssClass(stateDiv, newState)) {
    var stateClasses = CSSClasses.FileList.State;
    for(var state in stateClasses) {
     if(!stateClasses.hasOwnProperty(state)) continue;
     ASPx.RemoveClassNameFromElement(stateDiv, stateClasses[state]);
    }
    ASPx.AddClassNameToElement(stateDiv, newState);
   }
  },
  ResetState: function() {
   this.SetState(CSSClasses.FileList.State.Pending);
  },
  SetEnabled: function(enabled) {
  },
  GetRemoveRowButtonId: function() {
   return this.GetName() + IdSuffixes.Input.FileList.RemoveRowButton + this.GetID();
  },
  GetInputRowPrefix: function() {
   return IdSuffixes.Input.FileList.Row;
  },
  UpdateIndex: function(newIndex) {
   var oldIndex = this.GetID();
   this.setId(newIndex);
   this.RedefineAttributes(oldIndex);
  },
  GetNameCell: function() {
   return ASPx.GetChildByClassName(this.GetRenderResult(), CSSClasses.FileList.NameCell);
  },
  GetRemoveButtonCell: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.FileList.RemoveButtonCell);
  },
  RaiseStateChangedInternal: function(args) {
   ASPxBaseView.prototype.RaiseStateChangedInternal.call(this, args);
  },
  OnFileItemUploadStart: function() {
   this.UpdateProgress({ currentFileProgress: 0 });
   this.SetState(CSSClasses.FileList.State.Uploading);
   this.progressControl.AdjustControl();
  },
  OnFileItemUploadComplete: function() {
   this.UpdateProgress({ currentFileProgress: 100 });
   this.SetState(CSSClasses.FileList.State.Complete);
  },
  OnUploadInitiated: function() {
   ASPx.SetElementDisplay(this.progressControl.GetMainElement(), true);
   ASPx.SetElementDisplay(this.getProgressBarCell(), true);
   ASPx.SetElementDisplay(this.GetRemoveButtonCell(), false);
   this.progressControl.AdjustControl(true);
  },
  OnUploadFilesComplete: function() {
   this.SetState(CSSClasses.FileList.State.Pending);
   ASPx.SetElementDisplay(this.getProgressBarCell(), false);
   this.UpdateProgress({ currentFileProgress: 0 });
  },
  UpdateProgress: function(args) {
   this.progressControl.SetPosition(parseInt(args.currentFileProgress));
  },
  getProgressBarCell: function() {
   return ASPx.GetNodesByPartialClassName(this.GetRenderResult(), CSSClasses.FileList.ProgressBarCell)[0];
  }
 });
 var ASPxFileListView = ASPx.CreateClass(ASPxCompositeView, {
  viewPrototype: ASPxFileListItem,
  constructor: function(options, id) {
   this.constructor.prototype.constructor.call(this, options);
   this.name = options.name + IdSuffixes.Input.FileList.List;
   this.progressControl = undefined;
   this.currentView = null;
   this.showList(false);
  },
  UpdateProgress: function(args) {
   if(this.currentView)
    this.currentView.UpdateProgress(args);
  },
  addView: function(fileInfo) {
   ASPxCompositeView.prototype.addView.call(this, fileInfo);
   var index = this.internalIndex - 1,
    view = this.views[index];
   fileInfo.OnUploadStart.ClearHandlers();
   fileInfo.OnUploadComplete.ClearHandlers();
   fileInfo.OnUploadStart.AddHandler(function() {
    view.OnFileItemUploadStart();
    this.currentView = view;
   }.aspxBind(this));
   fileInfo.OnUploadComplete.AddHandler(function() { view.OnFileItemUploadComplete(); }.aspxBind(this));
  },
  removeView: function(index) {
   ASPxCompositeView.prototype.removeView.call(this, index);
   if(this.internalCount === 0)
    this.showList(false);
  },
  disposeFileInfo: function(index) {
   if(this.fileInfos[index])
    this.fileInfos[index].dispose();
  },
  getRemoveButtonPostfix: function(index) {
   return IdSuffixes.Input.FileList.RemoveRowButton + index;
  },
  showList: function(show) {
   ASPx.SetElementDisplay(this.GetRenderResult(), show);
  },
  GetContainerNode: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Input.FileList.List);
  },
  ResetState: function() {
   ASPxBaseInputView.prototype.ResetState.call(this);
   ASPx.Data.ForEach(this.views, function(view) {
    view.ResetState();
   });
  },
  OnUploadFilesComplete: function(args) {
   ASPx.Data.ForEach(this.views, function(view, index) {
    view.OnUploadFilesComplete();
    ASPx.SetElementDisplay(this.GetRemoveButtonCell(index), true);
   }.aspxBind(this));
   this.currentView = null;
  },
  refreshBase: function(args) {
   this.fileInfos = args.fileInfos[0] || [];
   if(args.forceClear || this.fileInfos.length < this.internalCount)
    this.Clear();
   if(args.forceClear)
    return;
   if(this.fileInfos.length)
    this.showList(true);
   var currentCount = this.internalCount,
    endIndex = this.fileInfos.length;
   for(var i = currentCount; i < endIndex; i++) {
    this.addView(this.fileInfos[i]);
    this.internalCount++;
   }
   ASPxCompositeView.prototype.refreshBase.call(this, args);
  },
  SetEnabled: function(enabled) {
   ASPxCompositeView.prototype.SetEnabled.call(this, enabled);
  },
  clearViews: function() {
   for(var i = this.views.length; i >= 0; --i)
    this.clearView(null, i);
  },
  clearView: function(view, index) {
   this.removeView(index);
  },
  OnUploadInitiated: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    view.OnUploadInitiated();
   });
  },
  GetRenderResult: function() {
   if(!this.renderResult)
    this.renderResult = ASPx.GetNodesByPartialClassName(this.domHelper.GetMainElement(), CSSClasses.FileList.List)[0];
   return this.renderResult;
  },
  GetFileInfos: function() {
   return [ASPxCompositeView.prototype.GetFileInfos.call(this)];
  },
  updateFileInfos: function(args) {
   this.fileInfos = args.fileInfos[0];
  }
 });
 var ASPxBaseInputView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.nullText = options.nullText;
   this.templates = options.templates;
   this.enabled = true;
   this.isEventsAttachedToFileInput = false;
   this.triggerCursorsList = {};
   this.FocusNeedResetInternal = new ASPxClientEvent();
  },
  Initialize: function() {
   this.prepareFileInputRowTemplate();
   this.InitializeFakeFocusInputElement();
   this.InitializeTemplates();
   this.ChangeEventsToFileInput(true);
  },
  InitializeFakeFocusInputElement: function() {
   if(this.IsFocusNeedReset()) {
    var mainCell = this.GetUploadInputsTable().parentNode;
    var div = ASPx.CreateHtmlElementFromString("<div class='dxucFFIHolder'></div>");
    mainCell.appendChild(div);
    var fakeFocusInput = ASPx.CreateHtmlElementFromString("<input readonly='readonly' class='dxucFFI'></input>");
    fakeFocusInput.id = this.GetFakeFocusInputElementID();
    div.appendChild(fakeFocusInput);
   }
  },
  prepareFileInputRowTemplate: function() {
   this.fileInputRowTemplate = this.GetFileInputRowTemplate();
   this.fileInputRowTemplateNode = this.fileInputRowTemplate.cloneNode(true);
   ASPx.SetElementDisplay(this.fileInputRowTemplateNode, true);
  },
  Render: function() {
   var errorRowTemplate = this.GetErrorRowTemplate(),
    separatorRow = this.GetFileInputSeparatorRowTemplate().cloneNode(true),
    addButtonSeparator = this.domHelper.GetChildElement(IdSuffixes.Input.AddButtonsSeparator),
    errorRow;
   if(errorRowTemplate) {
    errorRow = errorRowTemplate.cloneNode(true);
    this.errorRow = errorRow;
   }
   var inputRow = this.CreateInputRow();
   this.GetContainerNode().insertBefore(separatorRow, addButtonSeparator);
   this.GetContainerNode().insertBefore(inputRow, addButtonSeparator);
   if(errorRow) {
    this.GetContainerNode().insertBefore(errorRow, addButtonSeparator);
    ASPx.SetElementDisplay(errorRow, false);
   }
   ASPx.SetElementDisplay(separatorRow, true);
   ASPx.SetElementDisplay(inputRow, true);
   this.registerStates();
  },
  AfterRender: function() {
   this.ChangeEventsToFileInput(true);
  },
  Dispose: function() {
   ASPx.RemoveElement(this.GetErrorRow());
   ASPxBaseView.prototype.Dispose.call(this);
  },
  UpdateIndex: function(newIndex) {
   var oldIndex = this.GetID();
   this.dropElementCache();
   this.ChangeEventsToFileInput(false);
   this.setId(newIndex);
   this.RedefineAttributes(oldIndex);
   this.ChangeEventsToFileInput(true);
  },
  replaceFileInputElement: function() {
   var inputElement = this.getFileInputTemplate().cloneNode(),
    aspxFileInfos = this.GetFileInputElement().aspxFileInfos;
   this.GetFileInputElement().parentNode.replaceChild(inputElement, this.GetFileInputElement());
   this.resetCache();
   this.RedefineInputAttributes();
   this.ChangeEventsToFileInput(false);
   this.ChangeEventsToFileInput(true);
   this.GetFileInputElement().aspxFileInfos = aspxFileInfos;
  },
  resetCache: function() {
   this.cache[CSSClasses.TextboxInput] = null;
  },
  setId: function(newId) {
   this.id = newId;
  },
  CreateInputRow: function() {
   var inputRow = this.GetRowTemplate().cloneNode(true);
   this.renderResult = inputRow;
   this.RedefineAttributes("T");
   return inputRow;
  },
  refreshBase: function(args) {
   ASPxBaseView.prototype.refreshBase.call(this, args);
   if(args.isStateChanged)
    this.clearErrors();
   if(this.fileInfos && !this.fileInfos.length)
    this.Clear();
  },
  updateFileInfos: function(args) {
   this.fileInfos = args.fileInfos[this.GetID()];
  },
  Clear: function() {
   this.clearFileInputValue();
   this.fileInfos = [];
   this.replaceFileInputElementIfNeeded();
   ASPxBaseView.prototype.Clear.call(this);
  },
  clearFileInputValue: function() {
   this.supressInputEvent = true;
   this.GetFileInputElement().value = "";
   this.supressInputEvent = false;
  },
  replaceFileInputElementIfNeeded: function() {
   if(this.GetFileInputElement().value) {
    this.replaceFileInputElement();
    this.Refresh(ASPxEmptyRefreshArgs);
   }
  },
  clearErrors: function() {
   var errorCell = this.GetErrorCell();
   if(errorCell) {
    errorCell.innerHTML = "";
    ASPx.SetElementDisplay(this.GetErrorRow(), false);
   }
  },
  showError: function(error) {
   var errorCell = this.GetErrorCell();
   if(errorCell) {
    var currentErrors = errorCell.innerHTML;
    errorCell.innerHTML = currentErrors + error.text + "<br />";
    ASPx.SetElementDisplay(this.GetErrorRow(), true);
   }
  },
  Validate: function() { },
  GetRemoveRowButtonId: function() {
   return this.GetName() + IdSuffixes.Input.ButtonCell.Remove + this.GetID();
  },
  RedefineAttributes: function(oldIndex) {
   this.RedefineInputRowAttributes(this.GetRenderResult());
   if(this.errorRow)
    this.RedefineErrorRowAttributes(oldIndex);
   this.RedefineRemoveAttributes();
  },
  RedefineRemoveAttributes: function() {
   var removeButtonCell = ASPx.GetNodesByPartialClassName(this.GetRenderResult(), CSSClasses.RemoveButtonCell)[0];
   if(removeButtonCell)
    removeButtonCell.id = this.GetRemoveButtonId();
  },
  GetRemoveButtonId: function() {
   return this.GetName() + IdSuffixes.Input.ButtonCell.Remove + this.GetID();
  },
  RedefineErrorRowAttributes: function(oldIndex) {
   this.GetErrorRow(oldIndex).id = this.GetName() + this.GetErrorRowId();
  },
  RedefineInputRowAttributes: function() {
   this.GetRenderResult().id = this.GetFullID();
   this.RedefineTextBoxAttributes();
  },
  RedefineTextBoxAttributes: function() {
   var textBoxCell = this.GetTextBoxCell();
   if(textBoxCell) {
    textBoxCell.id = this.GetTextBoxCellID();
    this.RedefineInputAttributes();
   }
  },
  RedefineInputAttributes: function() {
   var input = this.GetFileInputElement();
   var newInputID = this.GetFileInputElementId();    
   input.id = newInputID;
   input.name = newInputID;
  },
  GetFileInputElementId: function() {
   return this.GetTextBoxCellID() + IdSuffixes.Input.FileInput;
  },
  ChangeTextBoxEnabledAttributes: function(element, method, enabled) {
   this.enabled = enabled;
   if(element) {
    var inputs = ASPx.GetNodesByTagName(element, "INPUT");
    for(var i = 0; i < inputs.length; i++)
     inputs[i].disabled = !enabled;
   }
  },
  ChangeClearBoxEnabledAttributes: function(element, method, enabled) {
   if(element) {
    var link = ASPx.GetNodeByTagName(element, "A", 0);
    this.ChangeButtonEnabledAttributes(link, method, enabled);
   }
  },
  SetFileInputRowEnabled: function(enabled) {
   this.SetTextBoxEnabled(this.GetTextBoxCell(), enabled);
  },
  SetTextBoxEnabled: function(element, enabled) {
   this.ChangeTextBoxEnabledState(element, enabled);
   this.ChangeTextBoxEnabledAttributes(element, ASPx.Attr.ChangeAttributesMethod(enabled), enabled);
  },
  ChangeTextBoxEnabledState: function(element, enabled) {
   if(element) {
    ASPx.GetStateController().SetElementEnabled(element, enabled);
    var editArea = ASPx.GetNodeByTagName(element, "INPUT", 1);
    if(editArea)
     ASPx.GetStateController().SetElementEnabled(editArea, enabled);
   }
  },
  SetClearBoxEnabled: function(element, enabled) {
   this.ChangeClearBoxEnabledState(element, enabled);
   this.ChangeClearBoxEnabledAttributes(element, ASPx.Attr.ChangeAttributesMethod(enabled), enabled);
  },
  ChangeClearBoxEnabledState: function(element, enabled) {
   if(element)
    ASPx.GetStateController().SetElementEnabled(element, enabled);
  },
  SetEnabled: function(enabled) {
   this.SetFileInputRowEnabled(enabled);
  },
  registerStates: function() {
   this.CreateTextBoxDisabledState();
   this.CreateClearBoxDisabledState();
   this.CreateBrowseHoveredState();
   this.CreateBrowsePressedState();
   this.CreateBrowseDisabledState();
  },
  CreateTextBoxDisabledState: function () {
   if(this.templates.DisabledTextBoxItem) {
    ASPx.GetStateController().AddDisabledItem(this.GetTextBoxCellID(),
     this.templates.DisabledTextBoxItem.className, this.templates.DisabledTextBoxItem.cssText,
     this.templates.DisabledTextBoxItem.postfixes, this.templates.DisabledTextBoxItem.imageUrls,
     this.templates.DisabledTextBoxItem.imagePostfixes);
   }
  },
  CreateClearBoxDisabledState: function () {
   if(this.templates.DisabledClearBoxItem) {
    ASPx.GetStateController().AddDisabledItem(this.GetClearBoxCellId(),
     this.templates.DisabledClearBoxItem.className, this.templates.DisabledClearBoxItem.cssText,
     this.templates.DisabledClearBoxItem.postfixes, this.templates.DisabledClearBoxItem.imageObjs,
     this.templates.DisabledClearBoxItem.imagePostfixes);
   }
  },
  CreateBrowseHoveredState: function () {
   if(this.templates.HoveredBrowseItem) {
    ASPx.GetStateController().AddHoverItem(this.GetBrowseButtonCellId(),
     this.templates.HoveredBrowseItem.className, this.templates.HoveredBrowseItem.cssText,
     this.templates.HoveredBrowseItem.postfixes, this.templates.HoveredBrowseItem.imageObjs,
     this.templates.HoveredBrowseItem.imagePostfixes);
   }
  },
  CreateBrowsePressedState: function () {
   if(this.templates.PressedBrowseItem) {
    ASPx.GetStateController().AddPressedItem(this.GetBrowseButtonCellId(),
     this.templates.PressedBrowseItem.className, this.templates.PressedBrowseItem.cssText,
     this.templates.PressedBrowseItem.postfixes, this.templates.PressedBrowseItem.imageObjs,
     this.templates.PressedBrowseItem.imagePostfixes);
   }
  },
  CreateBrowseDisabledState: function () {
   if(this.templates.DisabledBrowseItem) {
    ASPx.GetStateController().AddDisabledItem(this.GetBrowseButtonCellId(),
     this.templates.DisabledBrowseItem.className, this.templates.DisabledBrowseItem.cssText,
     this.templates.DisabledBrowseItem.postfixes, this.templates.DisabledBrowseItem.imageObjs,
     this.templates.DisabledBrowseItem.imagePostfixes);
   }
  },
  getBaseFileName: function(filePath) {
   if(!ASPxClientUploadControl.IsValidWindowsFileName(filePath))
    return filePath;
   var windowsFileNameRegExp = new RegExp(windowsFileNameRegExpTemplate, "gi");
   return filePath.replace(windowsFileNameRegExp, '$2').replace('\\', '');
  },
  GetFileInfos: function() {
   var fileInfos = this.getFilesFromCache(),
    fileList = this.getFileList(),
    index = this.GetID(),
    fileCount;
   fileCount = fileList && fileList.length;
   if(fileCount && !this.options.enableMultiSelect)
    fileInfos = [];
   ASPx.Data.ForEach(fileList, function(fileInfo) {
    var publicFileObject = this.GetPublicFileObject(fileInfo);
    fileInfos.push(new ASPxFileInfo(fileInfo, publicFileObject, index));
   }.aspxBind(this));
   fileInfos = this.ensureFileInputIndex(fileInfos);
   this.subsribeFileInfos(fileInfos);
   return fileInfos;
  },
  GetPublicFileObject: function(file) {
   return new ASPxClientUploadControlFile(file.name, file.size, file.fakeFileObject ? null : file);
  },
  getFilesFromCache: function() {
   return this.fileInfos && this.fileInfos.length && this.fileInfos.slice() || [];
  },
  getFileList: function() {
   var fileInputElement = this.GetFileInputElement(),
    fileList = [];
   if(fileInputElement.files && fileInputElement.files.length)
    return fileInputElement.files;
   if(fileInputElement.value) {
    var fileName = this.getBaseFileName(fileInputElement.value);
    var fileObject = {
     name: fileName,
     size: -1,
     fakeFileObject: true
    };
    fileList.push(fileObject);
   }
   return fileList;
  },
  ensureFileInputIndex: function(fileInfos) {
   if(fileInfos) {
    ASPx.Data.ForEach(fileInfos, function(fileInfo) {
     fileInfo.inputIndex = this.GetID();
    }.aspxBind(this));
   }
   return fileInfos;
  },
  subsribeFileInfos: function(fileInfos) {
   ASPx.Data.ForEach(fileInfos, function(fileInfo) {
    fileInfo.OnDispose.ClearHandlers();
    fileInfo.OnDispose.AddHandler(function() {
     this.Refresh(ASPxEmptyRefreshArgs);
    }.aspxBind(this));
   }.aspxBind(this));
  },
  GetText: function(index) {
   return this.GetValue(index);
  },
  getFileNames: function(index) {
   return this.GetFileNames(true);
  },
  setText: function() { },
  setTooltip: function() { },
  GetValue: function(isShortName) {
   var value = this.GetFileNames(isShortName).join(', ');
   return value != '' ? value : null;
  },
  IsInputEmpty: function(index) {
   var value = this.GetFileNames(index || 0);
   return !value.length;
  },
  GetFileSelectorElement: function() {
   return this.GetFileInputElement();
  },
  GetErrorRow: function(id) {
   if(!this.errorRow)
    this.errorRow = this.domHelper.GetChildElement(this.GetErrorRowId(id));
   return this.errorRow;
  },
  GetErrorCell: function(row) {
   var row = this.GetErrorRow(),
    errorCell = null;
   if(row) {
    errorCell = ASPx.GetNodesByTagName(row, "TD")[0];
   }
   return errorCell;
  },
  GetErrorRowPrefix: function() {
   return IdSuffixes.Error.Row;
  },
  GetErrorRowId: function(id) {
   return this.GetErrorRowPrefix() + (id || this.GetID());
  },
  GetFileInputElement: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.TextboxInput);
  },
  getFileInputTemplate: function() {
   return ASPx.GetNodesByPartialClassName(this.GetFileInputRowTemplate(), CSSClasses.TextboxInput)[0];
  },
  GetErrorRowTemplate: function() {
   return this.GetErrorRow("RT");
  },
  GetTextBoxCell: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.Textbox);
  },
  GetTextBoxCellID: function(id) {
   var id = ASPx.IsExists(id) ? id : this.GetID();
   return this.GetName() + IdSuffixes.Input.TextBoxCell + id;
  },
  GetFileFakeInputElement: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.TextboxFakeInput);
  },
  GetFileInputRowTemplate: function() {
   if(!this.fileInputRowTemplate) {
    var inputTemplate = this.GetInputRow("T");
    this.fileInputRowTemplate = ASPx.GetParentByTagName(inputTemplate, "TR");
   }
   return this.fileInputRowTemplate;
  },
  GetFileInputSeparatorRowTemplate: function() {
   if(this.options.fileInputSpacing === "")
    return null;
   return ASPx.GetNodesByPartialClassName(this.GetUploadInputsTable(), CSSClasses.SeparatorRow)[0];
  },
  GetBrowseButtonCell: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.BrowseButtonCell);
  },
  GetFakeFocusInputElementID: function () {
   return this.GetName() + IdSuffixes.Input.FakeFocusInput;
  },
  GetFakeFocusInputElement: function () {
   return ASPx.GetElementById(this.GetFakeFocusInputElementID());
  },
  setDialogTrigger: function(triggerElementSelectors) {
   this.triggerElements = this.triggerElements || [];
   var ids = [];
   if(this.triggerElements.length)
    aspxGetUploadControlCollection().SubscribeDialogTriggers(this, this.GetName(), this.triggerElements, this.getDialogTriggerHandlers(), false);
   if(triggerElementSelectors.idsString)
    ids = triggerElementSelectors.idsString.split(";");
   ids = ids.concat(this.options.dialogTriggerIDList);
   this.ensureTriggerElementsCache(ids, triggerElementSelectors.selector);
   if(this.triggerElements.length)
    aspxGetUploadControlCollection().SubscribeDialogTriggers(this, this.GetName(), this.triggerElements, this.getDialogTriggerHandlers(), true);
   this.ensureTriggerCursors();
  },
  ensureTriggerCursors: function() {
   ASPx.Data.ForEach(this.triggerElements, function(trigger) {
    this.triggerCursorsList[trigger.id] = this.getElementCursor(trigger);
   }.aspxBind(this));
  },
  ensureTriggerElementsCache: function(triggerIdList, selector) {
   this.triggerElements = [];
   if(this.GetID() !== 0)
    return;
   if(triggerIdList && triggerIdList.length) {
    ASPx.Data.ForEach(triggerIdList, function(triggerId) {
     var triggerElement = document.getElementById(triggerId);
     if(triggerElement && ASPx.Data.ArrayIndexOf(this.triggerElements, triggerElement) === -1)
      this.triggerElements.push(triggerElement);
    }.aspxBind(this));
   }
   if(selector) {
    var triggerElements = document.querySelectorAll(selector);
    ASPx.Data.ForEach(triggerElements, function(triggerElement) {
     if(ASPx.Data.ArrayIndexOf(this.triggerElements, triggerElement) === -1)
      this.triggerElements.push(triggerElement);
    }.aspxBind(this));
   }
  },
  getTriggerElements: function() {
   this.triggerElements = this.triggerElements || [];
   if(!this.triggerElements.length)
    this.ensureTriggerElementsCache(this.options.dialogTriggerIDList);
   return this.triggerElements;
  },
  InitializeTemplates: function() {
   if(this.options.fileInputSpacing != "") {
    this.fileInputSeparatorTemplateNode = this.GetFileInputSeparatorRowTemplate().cloneNode(true);
    ASPx.SetElementDisplay(this.fileInputSeparatorTemplateNode, true);
   }
  },
  IsFocusNeedReset: function() {
   return this.IsSlModeEnabled() || ASPx.Browser.Opera;
  },
  ChangeEventsToFileInput: function(attach) {
   if(attach == this.isEventsAttachedToFileInput)
    return;
   var method = this.ChangeEventsMethod(attach),
    fileInput = this.GetRenderResult();
   this.AttachOnChangeHandler(fileInput, method, attach);
   this.isEventsAttachedToFileInput = attach;
  },
  AttachOnChangeHandlerCore: function(fileInput, method, attach) {
   this.attachOnChangeHandlerForInput(method);
   aspxGetUploadControlCollection().SubscribeDialogTriggers(this, this.GetName(), this.getTriggerElements(), this.getDialogTriggerHandlers(), attach);
   this.ensureTriggerCursors();
  },
  attachOnChangeHandlerForInput: function(method) {
   method(this.GetFileInputElement(), "change", function(evt) {
    this.onFileInputChange(evt);
   }.aspxBind(this));
  },
  onFileInputChange: function(evt) {
   if(!this.supressInputEvent)
    this.RaiseStateChangedInternal(this);
  },
  getDialogTriggerHandlers: function() {
   var triggerHandlers = {};
   triggerHandlers.click = [this.createTriggerHandler(this.onTriggerClick)];
   if(!this.isSupportsInputClick()) {
    triggerHandlers.mousemove = [
     this.createTriggerHandler(this.onTriggerMouseMove),
     this.createTriggerHandler(this.onFileSelectorMouseMove, this.GetFileSelectorElement())
    ];
    triggerHandlers.mouseout = [
     this.createTriggerHandler(this.OnFileInputMouseOut),
     this.createTriggerHandler(this.onFileSelectorMouseOut, this.GetFileSelectorElement())
    ];
    triggerHandlers.mousedown = [this.createTriggerHandler(this.onFileSelectorMouseDown, this.GetFileSelectorElement())];
   }
   return triggerHandlers;
  },
  createTriggerHandler: function(handler, target) {
   return {
    handler: handler,
    target: target
   };
  },
  setFileInputPosition: function(e) {
   this.setFileInputPositionCore(e);
  },
  setFileInputPositionCore: function(e) {
   var space = 10,
    xPos = ASPx.Evt.GetEventX(e),
    yPos = ASPx.Evt.GetEventY(e),
    fileSelector = this.GetFileSelectorElement(),
    width = fileSelector.offsetWidth,
    height = fileSelector.offsetHeight;
   xPos -= this.IsRightToLeft() ? space : (width - space);
   yPos -= height / 2;
   ASPx.SetAbsoluteY(fileSelector, yPos);
   ASPx.SetAbsoluteX(fileSelector, xPos);
  },
  onFileSelectorMouseMove: function(e, trigger) {
   if(this.domHelper.IsMouseOverElement(e, trigger)) {
    ASPx.Evt.CancelBubble(e);
    this.reraiseEvent(e, "onmousemove", trigger);
    ASPx.RemoveClassNameFromElement(this.GetFileSelectorElement(), this.GetFileInputOnTextBoxHoverClassName());
    this.ensureCursorStyle(this.triggerCursorsList[trigger.id]);
   }
  },
  onFileSelectorMouseDown: function(e, trigger) {
   if(this.domHelper.IsMouseOverElement(e, trigger)) {
    ASPx.Evt.CancelBubble(e);
    this.reraiseEvent(e, "onmousedown", trigger);
   }
  },
  onFileSelectorMouseOut: function(e) {
   this.ensureCursorStyle("");
  },
  getElementCursor: function(element) {
   return ASPx.GetCurrentStyle(element).cursor;
  },
  ensureCursorStyle: function(cursor) {
   if(this.getElementCursor(this.GetFileSelectorElement()) !== cursor) {
    ASPx.SetStyles(this.GetFileSelectorElement(), {
     cursor: cursor
    });
   }
  },
  onTriggerMouseMove: function(e) {
   if(this.enabled)
    this.setFileInputPosition(e, false, true);
  },
  isSupportsInputClick: function() {
   return true;
  },
  onTriggerClick: function(e) {
   var left = ASPx.GetDocumentScrollLeft();
   var top = ASPx.GetDocumentScrollTop();
   this.GetFileSelectorElement().focus();
   ASPx.SetDocumentScrollLeft(left);
   ASPx.SetDocumentScrollTop(top);
   this.showFileChooserDialog();
  },
  showFileChooserDialog: function() {
   var fileInput = this.GetFileSelectorElement();
   if(fileInput.click)
    fileInput.click();
  },
  OnUploadFilesComplete: function(args) {
   if(!args.uploadCancelled || this.options.autoStart)
    this.Clear();
  },
  OnDocumentMouseUp: function() {
   this.browseButtonPressed = false;
  },
  OnDocumentKeyUpDown: function(e, isKeydown) {
  },
  reraiseEvent: function(e, eventType, newTarget) {
   var evt;
   if(document.createEvent) {
    evt = document.createEvent("MouseEvents");
    evt.initMouseEvent(e.type, e.bubbles, e.cancelable, window, e.detail, e.screenX, e.screenY,
     e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    evt.target = newTarget;
    newTarget.dispatchEvent(evt);
   } else if(document.createEventObject) {
    evt = document.createEventObject(window.event);
    evt.type = e.type;
    evt.bubbles = e.bubbles;
    evt.cancelable = e.cancelable;
    evt.view = window;
    evt.detail = e.detail;
    evt.screenX = e.screenX;
    evt.screenY = e.screenY;
    evt.clientX = e.clientX;
    evt.clientY = e.clientY;
    evt.ctrlKey = e.ctrlKey;
    evt.altKey = e.altKey;
    evt.shiftKey = e.shiftKey;
    evt.metaKey = e.metaKey;
    evt.button = e.button;
    evt.relatedTarget = e.relatedTarget;
    newTarget.fireEvent(eventType, evt);
   }
  },
  suppressFileDialog: function(suppress) {
   this.ChangeEventsToFileInput(!suppress);
  }
 });
 var ASPxInvisibleFileInputDecorator = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options, view) {
   this.view = new view(options);
   this.options = options;
   this.initializeEvents();
   this.replaceFunctions();
  },
  initializeEvents: function() {
   this.StateChangedInternal = new ASPxClientEvent();
   this.ErrorOccurred = new ASPxClientEvent();
   this.view.StateChangedInternal.AddHandler(function(view, args) {
    this.StateChangedInternal.FireEvent(this.view, args);
   }.aspxBind(this));
   this.view.ErrorOccurred.AddHandler(function(args) {
    this.ErrorOccurred.FireEvent(args);
   }.aspxBind(this));
  },
  replaceFunctions: function() {
   this.view.getFileInputTemplate = this.getFileInputTemplate;
   this.view.GetFileInputElement = this.GetFileInputElement;
   this.view.baseGetFileInfos = this.view.GetFileInfos.aspxBind(this.view);
   this.view.GetFileInfos = this.GetFileInfos.aspxBind(this.view);
   this.view.SetFileInputTooltip = this.SetFileInputTooltip.aspxBind(this.view);
   this.view.SetFileInputRowEnabled = this.SetFileInputRowEnabled.aspxBind(this);
   this.view.GetRenderResult = this.GetRenderResult.aspxBind(this);
   this.view.GetUploadInputsTable = this.GetUploadInputsTable.aspxBind(this);
   this.view.FileInputGotFocus = this.FileInputGotFocus.aspxBind(this);
   this.view.FileInputLostFocus = this.FileInputLostFocus.aspxBind(this);
   this.view.prepareFileInputRowTemplate = this.noop;
   this.view.UpdateNullText = this.noop;
   this.view.InitializeFakeFocusInputElement = this.noop;
   this.view.InitializeTemplates = this.noop;
   this.view.InitializeFileInputStyles = this.noop;
   this.view.changeTooltip = this.noop;
   this.view.GetBrowseButtonCell = this.returnNull;
   this.view.GetTextBoxCell = this.returnNull;
  },
  SetFileInputRowEnabled: function() {
   this.view.enabled = true;
  },
  InvokeTextChangedInternal: function() {
   this.view.InvokeTextChangedInternal();
  },
  GetRenderResult: function() {
   return this.options.domHelper.GetMainElement();
  },
  Initialize: function() {
   this.view.Initialize.call(this.view);
  },
  InlineInitialize: function() {
   this.view.InlineInitialize.call(this.view);
  },
  Clear: function() {
   this.view.Clear.call(this.view);
  },
  GetText: function() {
   return this.view.GetText.call(this.view);
  },
  getFileNames: function(index) {
   return this.view.getFileNames.call(this.view, index);
  },
  OnBeginProcessUploading: function() {
   this.view.OnBeginProcessUploading.call(this.view);
  },
  OnUploadFilesComplete: function(args) {
   this.view.OnUploadFilesComplete.call(this.view, args);
  },
  Refresh: function(args) {
   this.view.Refresh.call(this.view, args);
  },
  setDialogTrigger: function(triggerElementSelectors) {
   this.view.setDialogTrigger.call(this.view, triggerElementSelectors);
  },
  SetEnabled: function(enabled) {
   this.view.SetEnabled.call(this.view, enabled);
  },
  setInCallback: function(isInCallback) {
   this.view.setInCallback.call(this.view, isInCallback);
  },
  GetNextFocusElement: function() {
   return null;
  },
  FileInputGotFocus: function() {
   this.view.FileInputGotFocusInternal.call(this.view);
  },
  FileInputLostFocus: function() {
   this.view.FileInputLostFocusInternal.call(this.view);
  },
  noop: function() { },
  returnNull: function() {
   return null;
  },
  getFileInputTemplate: function() {
   return ASPx.GetNodesByPartialClassName(this.GetRenderResult(), CSSClasses.TextboxInput)[0];
  },
  GetFileInputElement: function() {
   return ASPx.GetNodesByPartialClassName(this.GetRenderResult(), CSSClasses.TextboxInput)[1];
  },
  GetFileInfos: function() {
   return [this.baseGetFileInfos()];
  },
  SetFileInputTooltip: function(text) {
   var handler = (text != '') ? ASPx.Attr.SetAttribute : ASPx.Attr.RemoveAttribute;
   ASPx.Data.ForEach(this.getTriggerElements(), function(trigger) {
    handler(trigger, "title", text);
   });
   handler(this.GetFileSelectorElement(), "title", text);
  },
  GetUploadInputsTable: function() {
   return this.GetRenderResult();
  },
  suppressFileDialog: function(suppress) {
   this.view.suppressFileDialog.call(this.view,  suppress);
  }
 });
 var ASPxStandardInputView = ASPx.CreateClass(ASPxBaseInputView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.fileInputIsHidden = true;
   this.selectedSeveralFilesText = options.selectedSeveralFilesText;
   this.nullTextItem = options.nullTextItem;
   this.accessibilityCompliant = options.accessibilityCompliant;
   this.isTouchClick = false;
  },
  InlineInitialize: function(options) {
   ASPxBaseView.prototype.InlineInitialize.call(this, options);
   this.UpdateNullText();
  },
  Initialize: function() {
   ASPxBaseInputView.prototype.Initialize.call(this, this.options);
   this.InitializeFileInputStyles();
  },
  OnDocumentKeyUpDown: function(e, isKeydown) {
   if(ASPx.Evt.GetKeyCode(e) === ASPx.Key.Tab)
    this.PrepareFileInputHiddenFocusing(isKeydown);
  },
  PrepareFileInputHiddenFocusing: function(isKeydown) {
   if(this.fileInputIsHidden) {
    if(isKeydown)
     this.GetFileSelectorElement().style.top = "";
    else
     this.ResetFileInputPosition();
   }
  },
  InitializeFileInputStyles: function() {
   var styleSheet = ASPx.GetCurrentStyleSheet();
   ASPx.AddStyleSheetRule(styleSheet,
         " ." + this.GetFileInputOnTextBoxHoverClassName(),
         "cursor: " + ASPx.GetCurrentStyle(this.GetTextBoxCell())["cursor"] + ";");
   ASPx.AddStyleSheetRule(styleSheet,
         " ." + this.GetFileInputOnBrowseButtonHoverClassName(),
         "cursor: " + ASPx.GetCurrentStyle(this.GetBrowseButtonCell())["cursor"] + ";");
  },
  GetFileInputOnTextBoxHoverClassName: function() {
   return this.getGeneratedCssClassPrefix() + CSSClasses.FITextBoxHoverDocument;
  },
  GetFileInputOnBrowseButtonHoverClassName: function() {
   return this.getGeneratedCssClassPrefix() + CSSClasses.FIButtonHoverDocument;
  },
  getGeneratedCssClassPrefix: function() {
   var id = aspxGetUploadControlCollection().getIdForControlName(this.GetName());
   return CSSClasses.GeneratedPrefix + id;
  },
  GetClearBoxCell: function() {
   return this.GetElementFromCacheByClassName(CSSClasses.ClearButtonCell);
  },
  RedefineInputRowAttributes: function() {
   ASPxBaseInputView.prototype.RedefineInputRowAttributes.call(this);
   this.redefineClearBoxAttributes();
   this.GetBrowseButtonCell().id = this.GetBrowseButtonCellId();
  },
  redefineClearBoxAttributes: function() {
   var clearBox = this.GetClearBoxCell(),
    clearBoxImg = ASPx.GetNodeByTagName(clearBox, "IMG", 0),
    clearBoxId = this.GetClearBoxCellId(),
    clearBoxImgId = clearBoxId + IdSuffixes.Input.ButtonCell.ClearImg;
   if(clearBox) {
    clearBox.id = clearBoxId;
    if(clearBoxImg)
     clearBoxImg.id = clearBoxImgId;
   }
  },
  RedefineInputAttributes: function() {
   ASPxBaseInputView.prototype.RedefineInputAttributes.call(this);
   var fakeInputElement = this.GetFileFakeInputElement();
   if(fakeInputElement)
    fakeInputElement.id = this.GetFileFakeInputElementId();
  },
  GetClearBoxCellId: function() {
   return this.GetName() + IdSuffixes.Input.ButtonCell.Clear + this.GetID();
  },
  GetBrowseButtonCellId: function() {
   return this.GetName() + IdSuffixes.Input.ButtonCell.Browse + this.GetID();
  },
  SetFileInputRowEnabled: function(enabled) {
   ASPxBaseInputView.prototype.SetFileInputRowEnabled.call(this, enabled);
   this.SetClearBoxEnabled(this.GetClearBoxCell(), enabled);
   this.SetButtonEnabled(this.GetBrowseButtonCell(), enabled);
  },
  GetFileFakeInputElementId: function() {
   return this.GetTextBoxCellID() + IdSuffixes.Input.FileFakeInput;
  },
  SetFileInputTooltip: function(text) {
   var handler = (text != '') ? ASPx.Attr.SetAttribute : ASPx.Attr.RemoveAttribute,
    isTextBoxHidden = this.isTextBoxHidden(),
    setTitleForSelector = ASPx.Browser.Firefox && !this.IsSlModeEnabled() || ASPx.Browser.WebKitFamily && isTextBoxHidden,
    element = isTextBoxHidden ? this.GetBrowseButtonCell() : this.GetTextBoxCell();
   handler(element, "title", text);
   if(setTitleForSelector && !this.accessibilityCompliant)
    handler(this.GetFileSelectorElement(), "title", text);
  },
  getFileInputTooltipText: function(files) {
   var value = '';
   if((typeof files == "object") && (files instanceof Array)) {
    var isNewlineSupported = ASPx.Browser.WebKitFamily || (ASPx.Browser.Firefox && !this.IsSlModeEnabled());
    if(isNewlineSupported && files.length > 1) {
     var i = 0;
     while(i < files.length) {
      if(i > 0)
       value += '\n';
      value += ASPx.Str.Trim(files[i++] || "");
     }
    }
    else
     value = files.join(', ');
   }
   return value;
  },
  ShowClearButton: function(show) {
   var clearBoxCell = this.GetClearBoxCell();
   if(clearBoxCell) {
    var link = ASPx.GetNodeByTagName(clearBoxCell, "A", 0);
    var func = show ? ASPx.Attr.RemoveAttribute : ASPx.Attr.SetAttribute;
    func(link.style, "visibility", "hidden");
   }
  },
  SetNullTextEnabled: function (enabled) {
   if(this.nullText != null) {
    if(enabled)
     this.SetFileFakeInputElementValue(this.nullText);
    this.ChangeTextBoxNullTextState(this.GetTextBoxCell(), enabled);
    this.ChangeClearBoxNullTextState(this.GetClearBoxCell(), enabled);
   }
  },
  ChangeTextBoxNullTextState: function (element, enabled) {
   if(element && (this.nullText || this.customText) && this.nullTextItem) {
    var restore = !enabled,
     styleAttrName = 'style';
    ASPx.Attr.ChangeAttributesMethod(restore)(element, 'class');
    ASPx.Attr.ChangeAttributesMethod(restore)(element, styleAttrName);
    var inputRow = null;
    if(this.nullTextItem.inputRow) {
     inputRow = this.GetInputRow();
     ASPx.Attr.ChangeAttributesMethod(restore)(inputRow, styleAttrName);
    }
    var editArea = this.GetFileFakeInputElement();
    if(editArea)
     ASPx.Attr.ChangeAttributesMethod(restore)(editArea, styleAttrName);
    if(enabled) {
     element.className = this.nullTextItem.textBox.className;
     element.style.cssText = this.nullTextItem.textBox.cssText;
     if(editArea)
      editArea.style.cssText = this.nullTextItem.editArea.cssText;
     if(this.nullTextItem.inputRow)
      inputRow.style.cssText = this.nullTextItem.inputRow.cssText;
    }
   }
  },
  ChangeClearBoxNullTextState: function (element, enabled) {
   if(element && this.nullText != null && this.nullTextItem) {
    var restore = !enabled;
    ASPx.Attr.ChangeAttributesMethod(restore)(element, 'style');
    ASPx.Attr.ChangeAttributesMethod(restore)(element, 'class');
    if(enabled) {
     element.className = this.nullTextItem.clearBox.className;
     element.style.cssText = this.nullTextItem.clearBox.cssText;
    }
   }
  },
  CreateSelectedSeveralFilesText: function(files) {
   var text = "",
    filteredFiles = [];
   if(files.length) {
    ASPx.Data.ForEach(files, function(file) {
     if(file !== undefined) {
      filteredFiles.push(file);
     }
    });
    files = filteredFiles;
    if(files.length > 1)
     text = this.selectedSeveralFilesText.replace("{0}", files.length);
    else if(files.length === 1)
     text = files[0];
   }
   return text;
  },
  SetFileFakeInputElementValue: function(value) {
   var element = this.GetFileFakeInputElement();
   if(element)
    element.value = value;
  },
  refreshBase: function(args) {
   ASPxBaseInputView.prototype.refreshBase.call(this, args);
   this.RefreshInput(args.skipRefreshInput);
  },
  RefreshInput: function(skipRefreshInput) {
   var files = this.GetFileNames(true),
    fakeInputValue = this.CreateSelectedSeveralFilesText(files),
    inputTooltip = skipRefreshInput ? fakeInputValue : this.getFileInputTooltipText(files);
   if(!inputTooltip && ASPx.Browser.Firefox && this.options.customTooltip)
    inputTooltip = this.options.customTooltip;
   this.SetFileInputTooltip(inputTooltip);
   if(!skipRefreshInput) {
    this.SetFileFakeInputElementValue(fakeInputValue);
    this.UpdateNullText();
    this.ShowClearButton(fakeInputValue && fakeInputValue !== "");
   }
  },
  getFilesFromCache: function() {
   return [];
  },
  UpdateNullText: function() {
   var isEmpty = this.IsInputEmpty();
   if(this.nullText != null)
    this.SetNullTextEnabled(isEmpty);
   else if(isEmpty)
    this.SetFileFakeInputElementValue("");
  },
  isUseTouchEvents: function() {
   return ASPx.Browser.MacOSMobilePlatform || ASPx.Browser.WebKitTouchUI;
  },
  isUseMovingFileInput: function() {
   return !this.isUseTouchEvents();
  },
  AttachOnChangeHandler: function(fileInput, method, attach) {
   if(this.IsFocusNeedReset())
    method(this.GetFileSelectorElement(), "keydown", this.raiseFocusNeedResetInternal.aspxBind(this));
   if(this.isUseMovingFileInput())
    this.attachFileInputMoveEventsOnChangeHandler(fileInput, method, attach);
   if(this.isUseTouchEvents())
    this.attachTouchEventsOnChangeHandler(attach);
   else
    this.attachClickEventsOnChangeHandler(attach);
   this.AttachOnChangeHandlerCore(fileInput, method, attach);
  },
  attachFileInputMoveEventsOnChangeHandler: function(fileInput, method) {
   var textBoxCell = this.GetTextBoxCell(),
    fileSelectorElement = this.GetFileSelectorElement();
   if(textBoxCell) {
    method(textBoxCell, "mousemove", this.OnFileInputMouseMove.aspxBind(this));
    method(textBoxCell, "mouseout", this.OnFileInputMouseOut.aspxBind(this));
   }
   method(fileInput, "mouseout", this.OnBrowseButtonMouseOut.aspxBind(this));
   method(fileInput, "mousemove", this.OnFileInputMouseMove.aspxBind(this));
   method(fileInput, "mouseout", this.OnFileInputMouseOut.aspxBind(this));
   method(fileInput, "mousedown", this.OnFileInputMouseDown.aspxBind(this));
   method(fileSelectorElement, "focus", this.FileInputGotFocus.aspxBind(this));
   method(fileSelectorElement, "blur", this.FileInputLostFocus.aspxBind(this));
   method(fileSelectorElement, "mousemove", this.OnFileInputMouseMove.aspxBind(this));
  },
  attachClickEventsOnChangeHandler: function(attach) {
   var attachMethod = function(element, eventHandler) {
     this.buttonEventHandlers[element.id + "_click"] = eventHandler.aspxBind(this);
     this.attachButtonHandler(element, "click", attach);
    }.aspxBind(this);
   this.attachEventsOnChangeHandler(attachMethod, this.OnBrowseButtonClick, this.onClearButtonClick);
  },
  attachTouchEventsOnChangeHandler: function(attach) {
   var touchStartHandler = function() { this.isTouchClick = true; },
    touchMoveHandler = function() { this.isTouchClick = false; },
    attachMethod = function(element, eventHandler) {
     this.buttonEventHandlers[element.id + "_touchstart"] = touchStartHandler.aspxBind(this);
     this.attachButtonHandler(element, "touchstart", attach);
     this.buttonEventHandlers[element.id + "_touchmove"] = touchMoveHandler.aspxBind(this);
     this.attachButtonHandler(element, "touchmove", attach);
     this.buttonEventHandlers[element.id + "_touchend"] = eventHandler.aspxBind(this);
     this.attachButtonHandler(element, "touchend", attach);
    }.aspxBind(this);
   this.attachEventsOnChangeHandler(attachMethod, this.OnBrowseButtonTouchEnd, this.onClearButtonTouchEnd);
  },
  attachEventsOnChangeHandler: function(attachMethod, clickHandler, clearHandler) {
   var textBoxCell = this.GetTextBoxCell(),
    browseButton = this.GetBrowseButtonCell(),
    clearBoxCell = this.GetClearBoxCell();
   if(textBoxCell)
    attachMethod(textBoxCell, clickHandler);
   if(browseButton)
    attachMethod(browseButton, clickHandler);
   if(clearBoxCell)
    attachMethod(clearBoxCell, clearHandler);
  },
  onClearButtonClick: function() {
   if(this.isInCallback || !this.enabled) return;
   this.Clear();
   this.clearErrors();
  },
  onClearButtonTouchEnd: function() {
   if(this.isTouchClick)
    this.onClearButtonClick();
  },
  raiseFocusNeedResetInternal: function(e) {
   if(ASPx.Evt.GetKeyCode(e) === ASPx.Key.Tab) {
    var args = {
     backward: e.shiftKey,
     index: this.GetID(),
     event: e
    };
    this.FocusNeedResetInternal.FireEvent(this, args);
   }
  },
  GetNextFocusElement: function(args) {
   var element = null;
   if(this.GetText() && !args.backward)
    element = this.GetClearBoxCell() && this.GetClearBoxCell().childNodes[0];
   return element;
  },
  IsMouseOverTextBox: function(evt) {
   return this.domHelper.IsMouseOverElement(evt, this.GetTextBoxCell());
  },
  IsMouseOverBrowseButton: function(evt) {
   return this.domHelper.IsMouseOverElement(evt, this.GetBrowseButtonCell());
  },
  isOverTriggerElement: function(evt) {
   var triggerElements = this.getTriggerElements();
   for(var i = 0; i < triggerElements.length; i++)
    if(this.domHelper.IsMouseOverElement(evt, triggerElements[i]))
     return true;
   return false;
  },
  isTextBoxHidden: function() {
   return this.GetFileFakeInputElement() == null;
  },
  FileInputGotFocus: function(evt) {
   var button = this.GetBrowseButtonCell();
   var focusedClassName = " " + CSSClasses.BrowseButtonFocus;
   button.className += focusedClassName;
   if(ASPx.Browser.Opera) {
    if(this._operaFocusedFlag)
     this._operaFocusedFlag = false;
    else {
     this._operaFocusedFlag = true;
     this.GetFakeFocusInputElement().focus();
     var _this = this;
     window.setTimeout(function() {
      _this.GetFileInputElement().focus();
     }, 100);
    }
   }
  },
  FileInputGotFocusInternal: function(){
   if(this.options.enableDragAndDrop)
    aspxGetUploadControlCollection().onFileInputGotFocus();
  },
  NeedMouseClickCorrection: function() {
   return !ASPx.Browser.TouchUI && this.fileInputIsHidden;
  },
  FileInputLostFocus: function(evt) {
   this.OnFileInputMouseOut(evt);
   this.FileInputLostFocusInternal();
   var button = this.GetBrowseButtonCell();
   var focusedClassName = " " + CSSClasses.BrowseButtonFocus;
   var className = button.className;
   while(className.indexOf(focusedClassName) != -1)
    className = className.replace(focusedClassName, "");
   button.className = className;
  },
  FileInputLostFocusInternal: function() {
   if(this.options.enableDragAndDrop)
    aspxGetUploadControlCollection().onFileInputLostFocus();
  },
  OnBrowseButtonTouchEnd: function(evt) {
   if(this.isTouchClick)
    this.showFileChooserDialog();
  },
  OnBrowseButtonClick: function(evt) {
   if(this.isUseMovingFileInput())
    this.OnClickInFakeElement(evt);
   else
    this.showFileChooserDialog();
  },
  OnBrowseButtonMouseOut: function(e) {
   this.OnFileInputMouseOut(e);
   this.ChangeButtonHoveredState(this.GetBrowseButtonCell(), false);
  },
  OnFileInputMouseMove: function(evt) {
   this.OnMouseMoveInFileInputElement(evt);
  },
  OnFileInputMouseOut: function(e) {
   if(!(this.IsMouseOverBrowseButton(e) || this.IsMouseOverTextBox(e) || this.isOverTriggerElement(e)))
    this.ResetFileInputPosition();
  },
  OnFileInputMouseDown: function(evt) {
   var isOverBrowseButton = this.IsMouseOverBrowseButton(evt);
   this.browseButtonPressed = true;
   this.ChangeButtonPressedState(this.GetBrowseButtonCell(), isOverBrowseButton);
  },
  OnMouseMoveInFakeElement: function(evt) {
   if(this.enabled) {
    var isOverBrowseButton = this.IsMouseOverBrowseButton(evt);
    this.setFileInputPosition(evt, isOverBrowseButton);
    var browseButtonCell = this.GetBrowseButtonCell();
    if(this.browseButtonPressed)
     this.ChangeButtonPressedState(browseButtonCell, isOverBrowseButton);
    else
     this.ChangeButtonHoveredState(browseButtonCell, isOverBrowseButton);
   }
  },
  OnMouseMoveInFileInputElement: function(evt) {
   if(this.enabled) {
    var isOverBrowseButton = this.IsMouseOverBrowseButton(evt),
     isOverTextBox = this.IsMouseOverTextBox(evt),
     isOverTriggerElement = this.isOverTriggerElement(evt),
     browseButtonCell = this.GetBrowseButtonCell();
    if(isOverTextBox || isOverBrowseButton || isOverTriggerElement) {
     this.setFileInputPosition(evt, isOverBrowseButton, isOverTriggerElement);
     if(this.browseButtonPressed)
      this.ChangeButtonPressedState(browseButtonCell, isOverBrowseButton);
     else if(!isOverTriggerElement)
      this.ChangeButtonHoveredState(browseButtonCell, isOverBrowseButton);
     this.changeTooltip(isOverTextBox);
    }
    else
     this.ResetFileInputPosition();
   }
  },
  OnClickInFakeElement: function(evt) {
   if(!this.NeedMouseClickCorrection()) return;
   this.OnMouseMoveInFakeElement(evt);
   this.showFileChooserDialog();
  },
  ChangeButtonHoveredState: function(element, enabled) {
   if(element && !this.browseButtonPressed) {
    element = enabled ? ASPx.GetStateController().GetHoverElement(element) : null;
    ASPx.GetStateController().SetCurrentHoverElement(element);
   }
  },
  ChangeButtonPressedState: function(element, enabled) {
   if(element) {
    var controller = ASPx.GetStateController();
    var pressedElement = controller.GetPressedElement(element);
    controller.SetPressedElement(enabled ? pressedElement : null);
   }
  },
  changeTooltip: function() { },
  setFileInputPosition: function(e, isChooseButton, isOverTrigger) {
   this.setFileInputPositionCore(e);
   this.SetFileInputCursor(isChooseButton, isOverTrigger);
   this.fileInputIsHidden = false;
  },
  SetFileInputCursor: function(isChooseButton, isOverTrigger) {
   var fileSelectorElement = this.GetFileSelectorElement(),
    initialClassName = fileSelectorElement.className,
    textboxHoverClass = this.GetFileInputOnTextBoxHoverClassName(),
    browseHoverClass = this.GetFileInputOnBrowseButtonHoverClassName(),
    hoverClassName = isChooseButton ? browseHoverClass : textboxHoverClass;
   if(isOverTrigger)
    hoverClassName = "";
   var newClassName = initialClassName
    .replace(textboxHoverClass, "")
    .replace(browseHoverClass, "")
    .replace(/^\s+|\s+$/g, '')  
    .concat(" ", hoverClassName);
   if(initialClassName !== newClassName)
    fileSelectorElement.className = newClassName;
  },
  ResetFileInputPosition: function() {
   this.GetFileSelectorElement().style.top = '-5000px';
   this.fileInputIsHidden = true;
  },
  setText: function(text) {
   this.customText = text;
   this.SetFileFakeInputElementValue(text);
   this.ChangeTextBoxNullTextState(this.GetTextBoxCell(), false);
  },
  setTooltip: function(text) {
   this.SetFileInputTooltip(text);
  }
 });
 var ASPxMultiFileInputView = ASPx.CreateClass(ASPxCompositeView, {
  constructor: function(options, viewPrototype) {
   this.internalCount = options.fileInputCount;
   this.viewPrototype = viewPrototype;
   this.activeInputIndex = -1;
   this.constructor.prototype.constructor.call(this, options);
   this.FileInputCountChangedInternal = new ASPxClientEvent();
   this.FocusNeedResetInternal = new ASPxClientEvent();
  },
  GetRenderResult: function() {
   return this.GetUploadInputsTable();
  },
  raiseFileInputCountChanged: function() {
   var args = new ASPxClientEventArgs();
   this.FileInputCountChangedInternal.FireEvent(this, args);
  },
  Clear: function(index) {
   ASPx.Data.ForEach(this.views, function(view) {
    if(index === view.GetID() || index === undefined)
     view.Clear();
   });
  },
  AdjustSize: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    if(view.AdjustSize)
     view.AdjustSize();
   });
  },
  getViewRefreshArgs: function(view, commonArgs) {
   var args = ASPxEmptyRefreshArgs,
    fileInfos = [],
    viewIndex = view.GetID(),
    isStateChanged = commonArgs.isStateChanged && commonArgs.inputIndex === viewIndex;
   fileInfos[viewIndex] = this.fileInfos[viewIndex] || [];
   if(fileInfos.length) {
    args = {
     fileInfos: fileInfos,
     isStateChanged: isStateChanged,
     skipRefreshInput: commonArgs.skipRefreshInput
    };
   }
   return args;
  },
  addView: function(fileInfo) {
   ASPxCompositeView.prototype.addView.call(this, fileInfo);
   this.views[this.internalIndex - 1].FocusNeedResetInternal.AddHandler(this.raiseFocusNeedResetInternal, this);
  },
  onInternalStateChanged: function(_, args) {
   this.activeInputIndex = args.inputIndex;
   ASPxCompositeView.prototype.onInternalStateChanged.call(this);
  },
  prepareInternalStateChangedArgs: function(view) {
   var args = ASPxCompositeView.prototype.prepareInternalStateChangedArgs.call(this, view);
   args.inputIndex = this.activeInputIndex;
   this.activeInputIndex = -1;
   return args;
  },
  addFileInput: function(supressCountChanged) {
   if(this.options.maxFileCount && this.internalCount >= this.options.maxFileCount)
    return;
   this.addView();
   this.internalCount++;
   this.updateInternalInputCountField(this.internalCount);
   if(this.internalCount === 1)
    this.showSeparatorRow(true);
   if(!supressCountChanged)
    this.raiseFileInputCountChanged();
  },
  raiseFocusNeedResetInternal: function(view, args) {
   this.FocusNeedResetInternal.FireEvent(this, args);
  },
  GetNextFocusElement: function(args) {
   var element = this.views[args.index].GetNextFocusElement(args),
    inputIndex = args.index + (args.backward ? -1 : 1),
    removeButtonIndex = args.backward ? inputIndex : args.index;
   if(this.IsSlModeEnabled()) {
    element = this.views[inputIndex] && this.views[inputIndex].GetFileSelectorElement();
    if(!element && inputIndex > this.internalCount - 1)
     element = this.views[args.index].GetFakeFocusInputElement();
   }
   if(!element) {
    element = this.removeButtons[removeButtonIndex] && this.removeButtons[removeButtonIndex].GetLink();
    if(!element)
     element = this.views[inputIndex] && this.views[inputIndex].GetFileSelectorElement();
   }
   return element;
  },
  updateInternalInputCountField: function(count) {
   this.domHelper.stateObject.inputCount = count;
  },
  removeFileInput: function(index) {
   this.removeView(index);
  },
  removeView: function(index) {
   if(this.views[index]) {
    var separatorsCount = ASPx.GetNodesByPartialClassName(this.domHelper.GetMainElement(), CSSClasses.SeparatorRow).length;
    if(separatorsCount > 1)
     ASPx.RemoveElement(ASPx.GetPreviousSibling(this.views[index].GetRenderResult())); 
    ASPxCompositeView.prototype.removeView.call(this, index);
    this.updateInternalInputCountField(this.internalCount);
    this.raiseFileInputCountChanged();
   }
   if(this.internalCount === 0)
    this.showSeparatorRow(false);
  },
  disposeFileInfo: function(index) {
   if(this.fileInfos && this.fileInfos[index] && this.fileInfos[index].length) {
    ASPx.Data.ForEach(this.fileInfos[index], function(fileInfo) {
     fileInfo.dispose();
    });
   }
  },
  showSeparatorRow: function(show) {
   var separatorRow = this.domHelper.GetAddUploadButtonsSeparatorRow();
   if(separatorRow)
    ASPx.SetElementDisplay(separatorRow, show);
  },
  setFileInputCount: function(count) {
   var currentCount = this.internalCount;
   if(count > currentCount) {
    for(var i = currentCount; i < count; i++)
     this.addFileInput(true);
   } else {
    for(var i = currentCount; i >= count; i--)
     this.removeFileInput(i);
   }
  },
  setDialogTrigger: function(triggerElementSelectors) {
   if(this.views && this.views[0])
    this.views[0].setDialogTrigger(triggerElementSelectors);
  },
  setInCallback: function(isInCallback) {
   ASPxCompositeView.prototype.setInCallback.call(this, isInCallback);
   ASPx.Data.ForEach(this.views, function(view) {
    view.setInCallback(isInCallback);
   });
  },
  showError: function(error) {
   for(var i = 0; i < this.internalCount; i++) {
    if(i === error.inputIndex)
     this.views[i].showError(error);
   }
  },
  GetText: function(index) {
   return this.views[index].GetText();
  },
  getFileNames: function(index) {
   return this.views[index].getFileNames(index);
  },
  setText: function(text, index) {
   if(this.views && this.views[index])
    this.views[index].setText(text);
  },
  setTooltip: function(text, index) {
   if(this.views && this.views[index])
    this.views[index].setTooltip(text);
  },
  GetFileInputElement: function(index) {
   var view = this.views[index || 0] || {};
   return view.GetFileInputElement.call(view);
  },
  GetFileInputRowTemplate: function(index) {
   var view = this.views[index || 0] || {};
   return view.GetFileInputRowTemplate.call(view);
  },
  GetErrorRow: function(index) {
   var view = this.views[index || 0] || {};
   return view.GetErrorRow.call(view, index);
  },
  GetErrorRowTemplate: function() {
   var view = this.views[0] || {};
   return view.GetErrorRowTemplate.call(view);
  },
  GetInputRow: function(index) {
   var view = this.views[index || 0] || {};
   return view.GetInputRow.call(view);
  },
  GetErrorCell: function(index) {
   var view = this.views[index || 0] || {};
   return view.GetErrorCell.call(view);
  },
  GetAddUploadButtonsSeparatorRow: function() {
   return this.GetChildElement(IdSuffixes.Input.AddButtonsSeparator);
  },
  GetAddUploadButtonsPanelRow: function() {
   return this.GetChildElement(IdSuffixes.Input.AddUploadButtonPanelRow);
  },
  InvokeTextChangedInternal: function(index) {
   if(this.views[index]) {
    this.views[index].InvokeTextChangedInternal();
   }
  },
  OnDocumentMouseUp: function() {
   ASPx.Data.ForEach(this.views, function(view) {
    view.OnDocumentMouseUp();
   });
  },
  OnDocumentKeyUpDown: function(e, isKeydown) {
   ASPx.Data.ForEach(this.views, function(view) {
    view.OnDocumentKeyUpDown(e, isKeydown);
   });
  },
  suppressFileDialog: function(suppress) {
   ASPx.Data.ForEach(this.views, function(view) {
    view.suppressFileDialog(suppress);
   });
  }
 });
 var ASPxAdvancedInputView = ASPx.CreateClass(ASPxStandardInputView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  Initialize: function() {
   ASPxStandardInputView.prototype.Initialize.call(this, this.options);
  },
  AttachOnChangeHandler: function(fileInput, method, attach) {
   ASPxStandardInputView.prototype.AttachOnChangeHandler.call(this, fileInput, method, attach);
   if(this.options.enableDragAndDrop) {
    var fileSelectorElement = this.GetFileSelectorElement();
    method(fileSelectorElement, "click", this.FileInputClick.aspxBind(this));
   }
  },
  FileInputClick: function(evt) {
   aspxGetUploadControlCollection().onFileInputClick();
  },
  FileInputGotFocus: function(evt) {
   this.FileInputGotFocusInternal();
   ASPxStandardInputView.prototype.FileInputGotFocus.call(this, evt);
  },
  onFileInputChange: function(evt) {
   if(this.options.enableDragAndDrop)
    aspxGetUploadControlCollection().onFileInputChange();
   ASPxStandardInputView.prototype.onFileInputChange.call(this, evt);
  },
  RaiseStateChangedInternal: function(view) {
   ASPxStandardInputView.prototype.RaiseStateChangedInternal.call(this, view);
   this.clearInputValue();
  },
  refreshBase: function(args) {
   ASPxStandardInputView.prototype.refreshBase.call(this, args);
   this.clearInputValue();
  },
  clearInputValue: function() {
   this.supressInputEvent = true;
   this.GetFileInputElement(0).value = "";
   this.supressInputEvent = false;
  },
  GetPublicFileObject: function(file) {
   return new ASPxClientUploadControlFile(file.name || file.fileName, file.size || file.fileSize || 0, file);
  },
  getFilesFromCache: function() {
   var files = [];
   if(this.options.enableMultiSelect || !this.GetFileInputElement().files.length)
    files = ASPxBaseInputView.prototype.getFilesFromCache.call(this);
   return files;
  },
  getFileList: function() {
   return this.GetFileInputElement().files || [];
  },
  subsribeFileInfos: function() {}
 });
 var ASPxSLInputView = ASPx.CreateClass(ASPxAdvancedInputView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.slUploadHelperUrl = options.slUploadHelperUrl;
   this.domHelper.GetSlUploadHelperElement = this.GetSlUploadHelperElement.aspxBind(this);
  },
  Initialize: function(options) {
   this.initSlObject();
   ASPxAdvancedInputView.prototype.Initialize.call(this, options);
   this.SetEnabled(false);
  },
  initSlObject: function() {
   if(!this.SlInitialized && (!this.domHelper.IsSlObjectLoaded() || !this.GetRenderResult())) {
    this.createSlHost();
    this.initInput();
    this.SlInitialized = true;
   }
  },
  Render: function() {
   ASPxAdvancedInputView.prototype.Render.call(this);
   this.initSlObject();
   this.SetEnabled(false);
  },
  Dispose: function() {
   ASPx.RemoveElement(this.GetFileSelectorElement());
   ASPxAdvancedInputView.prototype.Dispose.call(this);
  },
  UpdateIndex: function(newIndex) {
   this.cachedSlHelperElement = this.GetSlUploadHelperElement();
   ASPxAdvancedInputView.prototype.UpdateIndex.call(this, newIndex);
  },
  SetEnabled: function(enabled) {
   this.SetFileInputRowEnabled(enabled);
  },
  initInput: function() {
   var slHelper = this.CreateSlObject(this.slUploadHelperUrl);
   if(this.GetUploadHostElement())
    this.GetUploadHostElement().appendChild(slHelper);
   else
    this.GetFileInputElement().parentNode.insertBefore(slHelper, this.GetFileInputElement());
   this.GetFileInputElement().parentNode.removeChild(this.GetFileInputElement());
   ASPx.SetStyles(slHelper, {
    "zIndex": Constants.INPUT_ZINDEX
   });
  },
  createSlHost: function() {
   if(!this.GetUploadHostElement()) {
    var slHost = document.createElement("DIV");
    var mainCell = this.GetUploadInputsTable().parentNode;
    ASPx.Attr.SetAttribute(slHost, "id", this.GetHostElementId());
    ASPx.Attr.SetAttribute(slHost.style, "position", "absolute");
    ASPx.Attr.SetAttribute(slHost.style, "width", "0px");
    ASPx.Attr.SetAttribute(slHost.style, "height", "0px");
    ASPx.Attr.SetAttribute(slHost.style, "border-width", "0px");
    mainCell.appendChild(slHost);
   }
  },
  RedefineInputAttributes: function() {
   ASPxAdvancedInputView.prototype.RedefineInputAttributes.call(this);
   this.redefineSlObjectAttributes(this.cachedSlHelperElement);
  },
  redefineSlObjectAttributes: function(slElement) {
   if(this.GetUploadHostElement())
    this.RedefineSlObjectAttributesInHostElement(slElement);
   else
    this.RedefineSlObjectAttributes(slElement);
  },
  RedefineSlObjectAttributesInHostElement: function (slElement) {
   var slElement = slElement || this.GetSlUploadHelperElement();
   if(slElement) {
    slElement.id = this.GetSlUploadHelperElementID();
    if(this.domHelper.IsSlObjectLoaded(this.GetID()))
     slElement.content.sl.RedefineAttributes(this.baseName, this.GetID());
   }
  },
  clearInputValue: function() { },
  changeTooltip: function(isOverTextBox) {
   var tooltipElement = isOverTextBox ? this.GetTextBoxCell() : this.GetBrowseButtonCell();
   var tooltip = ASPx.Attr.GetAttribute(tooltipElement, "title");
   ASPx.Attr.SetAttribute(this.GetFileSelectorElement(), "title", tooltip ? tooltip : "");
  },
  renewFileInfosSubscribtion: function(fileInfos) {
   if(this.domHelper.IsSlObjectLoaded(this.GetID())) {
    var slElement = this.GetSlUploadHelperElement(),
     fileInfosArray = fileInfos || this.fileInfos || [];
    ASPx.Data.ForEach(fileInfosArray, function(fileInfo, index) {
     fileInfo.OnDispose.ClearHandlers();
     fileInfo.OnDispose.AddHandler(function() {
      slElement.content.sl.DisposeFileInfo(index);
     });
    }.aspxBind(this));
   }
  },
  GetNextFocusElement: function() {
   return null;
  },
  RedefineSlObjectAttributes: function (slElement) {
   var slElement = slElement || ASPx.GetNodeByTagName(this.GetTextBoxCell(), "OBJECT", 0),
    inputIndex = this.GetID();
   if(slElement) {
    var slObjectId = this.GetSlUploadHelperElementID(inputIndex);
    var controlName = this.baseName;
    slElement.id = slObjectId;
    if(this.domHelper.IsSlObjectLoaded(inputIndex))
     slElement.content.sl.RedefineAttributes(controlName, inputIndex);
   }
  },
  GetUploadHostElement: function() {
   if(!this.slUploadHostElement)
    this.slUploadHostElement = document.getElementById(this.GetSlUploadHostElementID());
   return this.slUploadHostElement;
  },
  GetSlUploadHostElementID: function () {
   return this.GetName() + IdSuffixes.SL.UploadHost;
  },
  InlineInitialize: function(options) {
   ASPxAdvancedInputView.prototype.InlineInitialize.call(this, options);
   if(!ASPx.Browser.Opera)
    this.SetFileInputRowEnabled(false);
  },
  CreateSlObject: function(source) {
   var inputIndex = this.GetID();
   var slObjectId = this.GetUploadHelperElementID(inputIndex);
   var controlName = this.GetName();
   var properties = { width: '70px', height: '22px' };
   var events = {};
   events.onLoad = 'slOnLoad_' + slObjectId;
   window[events.onLoad] = function() {
    ASPx.SLOnLoad(this.GetName(), inputIndex);
   }.aspxBind(this);
   events.onError = 'slOnError_' + slObjectId;
   window[events.onError] = function() {
    ASPx.SLOnError(this.GetName(), inputIndex);
   }.aspxBind(this);
   var parentElement = document.createElement("DIV");
   parentElement.innerHTML = this.BuildHTML(source, slObjectId, controlName, inputIndex, properties, events);
   return parentElement.firstChild;
  },
  BuildHTML: function (source, id, controlName, inputIndex, properties, events) {
   var sb = [];
   var appType = "application/x-" + Constants.SL_PLATFORM_NAME.toLowerCase() + "-2";
   sb.push('<object type="' + appType + '" data="data:' + appType + ',"');
   sb.push(' id="' + id + '"');
   if(properties.width != null) sb.push(' width="' + properties.width + '"');
   if(properties.height != null) sb.push(' height="' + properties.height + '"');
   var opacityStyle = "";
   opacityStyle = "opacity: 0.01;";
   sb.push(' style="position: absolute; background-color: transparent; top: -5000px; ' + opacityStyle + '"');
   sb.push('>');
   sb.push('<param name="source" value="' + source + '" />');
   sb.push('<param name="background" value="Transparent" />');
   sb.push('<param name="windowless" value="true" />');
   sb.push('<param name="minRuntimeVersion" value="3.0.40818.0" />');
   var init = '<param name="initParams" value="';
   init += 'controlName=' + controlName + ', ';
   init += 'inputIndex=' + inputIndex + ', ';
   init += 'multiselect=' + this.options.enableMultiSelect + ', ';
   init += 'allowedMaxFileSize=' + this.options.validationSettings.maxFileSize;
   var allowedFileExtensions = this.options.validationSettings.allowedFileExtensions;
   if(allowedFileExtensions != null) {
    init += ', allowedFileExtensions=' + allowedFileExtensions.join(';') + ', ';
    var fileMasks = [];
    for(var i = 0; i < allowedFileExtensions.length; i++)
     fileMasks.push("*" + allowedFileExtensions[i]);
    init += 'filter=' + fileMasks.join(';');
   }
   init += '" />';
   sb.push(init);
   if(events.onLoad)
    sb.push('<param name="onLoad" value="' + events.onLoad + '" />');
   if(events.onError)
    sb.push('<param name="onError" value="' + events.onError + '" />');
   sb.push("</object>");
   return sb.join("");
  },
  InvokeTextChangedInternal: function() {
   this.changed = true;
   this.RaiseStateChangedInternal(this);
   this.changed = false;
  },
  GetFileInfos: function() {
   var slElement,
    slFileInfos,
    inputIndex = this.GetID(),
    currentFilesLength = this.fileInfos && this.fileInfos.length || 0;
   var fileInfos;
   if(this.domHelper.IsSlObjectLoaded(inputIndex)) {
    slElement = this.GetSlUploadHelperElement();
    if(!this.options.enableMultiSelect && currentFilesLength && this.changed) {
     this.fileInfos[0].dispose();
     this.fileInfos.splice(0, 1);
    }
    fileInfos = this.fileInfos && this.fileInfos.slice() || [];
    currentFilesLength = fileInfos.length;
    slFileInfos = eval(slElement.content.sl.FileInfos);
    ASPx.Data.ForEach(slFileInfos, function(file, index) {
     if(index >= currentFilesLength) {
      file.fileType = "";
      var publicFileObject = this.GetPublicFileObject(file);
      fileInfos.push(new ASPxFileInfo(file, publicFileObject, this.GetID()));
     }
    }.aspxBind(this));
   }
   this.renewFileInfosSubscribtion(fileInfos);
   fileInfos = this.ensureFileInputIndex(fileInfos);
   return fileInfos || [];
  },
  GetUploadHelperElementID: function() {
   return this.GetTextBoxCellID() + IdSuffixes.SL.UploadHelper;
  },
  GetFileSelectorElement: function() {
   return this.GetSlUploadHelperElement();
  },
  GetSlUploadHelperElement: function(id) {
   return document.getElementById(this.GetSlUploadHelperElementID(id));
  },
  GetSlUploadHelperElementID: function(id) {
   return this.GetTextBoxCellID(id) + IdSuffixes.SL.UploadHelper;
  },
  SetFileInputCursor: function(isChooseButton, isOverTrigger) {
   ASPxStandardInputView.prototype.SetFileInputCursor.call(this, isChooseButton, isOverTrigger);
   var fileSelectorElement = this.GetFileSelectorElement();
   this.SetCursorStyle(ASPx.GetCurrentStyle(fileSelectorElement)["cursor"]);
  },
  GetHostElementId: function() {
   return this.baseName + IdSuffixes.SL.UploadHost;
  },
  SetCursorStyle: function (cursorStyle) {
   var inputIndex = this.GetID();
   if(this.domHelper.IsSlObjectLoaded(inputIndex)) {
    var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
    slElement.content.sl.SetCursorStyle(cursorStyle);
   }
  },
  Clear: function() {
   this.options.uploadHelper.ClearFileInfos(this.GetID());
   ASPxAdvancedInputView.prototype.Clear.call(this);
  },
  clearFileInputValue: function() { },
  replaceFileInputElementIfNeeded: function() { },
  refreshBase: function(args) {
   ASPxAdvancedInputView.prototype.refreshBase.call(this, args);
   this.renewFileInfosSubscribtion();
  },
  attachOnChangeHandlerForInput: function() { },
  getDialogTriggerHandlers: function() {
   var triggerHandlers = ASPxAdvancedInputView.prototype.getDialogTriggerHandlers.call(this);
   triggerHandlers.mousemove = triggerHandlers.mousemove || [];
   triggerHandlers.mousemove.push(this.createTriggerHandler(this.OnFileInputMouseMove));
   return triggerHandlers;
  }
 });
 var ASPxHTML5InputView = ASPx.CreateClass(ASPxAdvancedInputView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  Initialize: function() {
   ASPxAdvancedInputView.prototype.Initialize.call(this, this.options);
   if(this.options.enableMultiSelect) {
    this.GetFileSelectorElement().multiple = true;
    this.initializeTemplateInput();
   }
  },
  initializeTemplateInput: function() {
   this.getFileInputTemplate().multiple = true;
  }
 });
 var ASPxNativeInputView = ASPx.CreateClass(ASPxBaseInputView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  Initialize: function() {
   ASPxBaseInputView.prototype.Initialize.call(this);
   if(ASPx.Browser.Firefox)
    this.correctFileInputSize();
  },
  EnsureRender: function() {
   ASPxBaseInputView.prototype.EnsureRender.call(this);
   if(ASPx.Browser.Firefox)
    this.correctFileInputSize();
  },
  AdjustSize: function() {
   this.correctFileInputSize();
  },
  correctFileInputSize: function() {
   if(!this.domHelper.GetMainElement())
    return;
   var width = this.GetFileInputElement().clientWidth,
    fontSize = ASPx.GetCurrentStyle(this.GetFileInputElement()).fontSize,
    size = this.findInputSize(width, fontSize);
   this.GetFileInputElement().size = size;
  },
  findInputSize: function (width, fontSize) {
   var spanInput = document.createElement("SPAN");
   document.body.appendChild(spanInput);
   var fakeInput = document.createElement("INPUT");
   fakeInput.type = "file";
   fakeInput.size = 1;
   fakeInput.style.fontSize = fontSize;
   spanInput.appendChild(fakeInput);
   var stepSize = 1;
   while(true) {
    var previousInputWidth = spanInput.offsetWidth;
    fakeInput.size += stepSize;
    if(previousInputWidth == spanInput.offsetWidth) {
     fakeInput.size = 1;
     break;
    }
    if(spanInput.offsetWidth == width)
     break;
    else if(spanInput.offsetWidth > width) {
     if(stepSize > 1) {
      fakeInput.size -= stepSize;
      stepSize = 1;
     } else {
      fakeInput.size -= 1;
      break;
     }
    }
    else
     stepSize *= 2;
   }
   var inputSize = fakeInput.size;
   ASPx.RemoveElement(fakeInput);
   ASPx.RemoveElement(spanInput);
   return inputSize;
  },
  AttachOnChangeHandler: function(fileInput, method) {
   this.AttachOnChangeHandlerCore(fileInput, method);
  },
  Clear: function() {
   ASPxBaseInputView.prototype.Clear.call(this);
   this.supressInputEvent = true;
   this.GetFileInputElement().value = "";
   this.supressInputEvent = false;
  }
 });
 var ASPxErrorView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  InlineInitialize: function(options) {
   ASPxBaseView.prototype.InlineInitialize.call(this, options);
   this.decodeErrorTexts();
  },
  Initialize: function() {
   if(this.options.advancedModeEnabled && !this.options.isFileApiAvailable && !this.options.isSLEnabled && !this.options.autoModeEnabled)
    this.SetVisiblePlatformErrorElement(true);
   var errorRowTemplate = this.GetErrorRowTemplate();
   if(errorRowTemplate)
    this.errorRowTemplateNode = errorRowTemplate.cloneNode(true);
  },
  GetErrorRowTemplate: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Error.RowTemplate);
  },
  GetErrorRow: function(index) {
   return this.domHelper.GetChildElement(IdSuffixes.Error.Row + index);
  },
  GetErrorCell: function(index) {
   var errorRow = this.GetErrorRow(index);
   return errorRow ? ASPx.GetNodesByTagName(errorRow, "td")[0] : null;
  },
  Refresh: function(args) {
  },
  Clear: function() {
   this.UpdateCommonErrorDiv("");
  },
  UpdateErrorMessageCell: function(args) {
   var index = args.index,
    errorText = args.errorText,
    isValid = args.isValid;
   if(this.GetErrorRow(index)) {
    var errorCell = this.GetErrorCell(index);
    if(errorText instanceof Array) {
     var errorTexts = [];
     for(var i = 0; i < errorText.length; i++)
      if(!isValid[i] && errorText[i] != "")
       errorTexts.push(errorText[i]);
     errorText = errorTexts.join("<br />");
     ASPx.SetElementDisplay(this.GetErrorRow(index), true);
    }
    else
     ASPx.SetElementDisplay(this.GetErrorRow(index), !isValid);
    if(errorText != "")
     errorCell.innerHTML = errorText;
   }
  },
  UpdateCommonErrorDiv: function(text) {
   var commonErrorDiv = this.getCommonErrorDivElement();
   if(commonErrorDiv) 
    commonErrorDiv.innerHTML = text;
   ASPx.SetElementDisplay(commonErrorDiv, !!text.length);
  },
  getCommonErrorDivElement: function () {
   return this.domHelper.GetChildElement(IdSuffixes.Error.Div);
  },
  decodeErrorTexts: function() {
   var inputCount = this.options.fileInputCount;
   for(var i = 0; i < inputCount; i++) {
    var errorCell = this.GetErrorCell(i);
    if(errorCell) {
     var text = errorCell.innerHTML;
     if(text) {
      var decodedText = ASPx.Str.DecodeHtmlViaTextArea(text);
      ASPx.SetInnerHtml(errorCell, decodedText);
     }
    }
   }
  }
 });
 var ASPxProgressPanelView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.isInCallback = false;
  },
  Initialize: function(options) {
   ASPxBaseView.prototype.Initialize.call(this, options);
   var cancelButton = this.getCancelButton();
   if(cancelButton) {
    this.AttachEventForElement(this.getCancelButton(), "click", function() {
     this.RaiseStateChangedInternal(this);
    }.aspxBind(this));
   }
  },
  prepareInternalStateChangedArgs: function() {
   return {
    uploadCancelled: true
   };
  },
  OnBeginProcessUploading: function() {
   this.ShowProgressPanel(true);
  },
  ShowProgressPanel: function() {
   window.setTimeout(function() {
    if(this.isInCallback)
     this.ShowProgressInfoPanel(true);
   }.aspxBind(this), 600);
   this.CleanUploadingInfoPanel();
  },
  ShowProgressInfoPanel: function (show) {
   var inputsTable = this.GetUploadInputsTable();
   ASPx.SetStyles(this.GetProgressPanel(), {
    width: inputsTable.clientWidth,
    height: inputsTable.clientHeight
   });
   ASPx.SetElementDisplay(inputsTable, !show);
   ASPx.SetElementDisplay(this.GetProgressPanel(), show);
   if(!show && ASPx.Browser.Chrome) { 
    var _inputsTable = inputsTable;
    window.setTimeout(function () {
     ASPx.SetElementVisibility(_inputsTable, true);
    }, 100);
   }
   if(show) {
    var progressControl = this.GetProgressControl();
    if(progressControl != null)
     progressControl.AdjustControl();
   }
   this.SetButtonEnabled(this.getCancelButton(), true);
  },
  CleanUploadingInfoPanel: function () {
   this.UpdateProgress(0);
  },
  getCancelButton: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Input.ButtonCell.Cancel);
  },
  OnUploadFilesComplete: function() {
   this.UpdateProgress(100);
   this.ShowProgressInfoPanel(false);
  },
  UpdateProgress: function (args) {
   var percent = args.progress;
   if(!(percent > 0 && percent <= 100))
    percent = percent > 0 ? 100 : 0;
   var element = this.GetProgressControl();
   if(element != null)
    element.SetPosition(percent);
  },
  GetProgressControl: function () {
   if(!this.progressControl) {
    var name = this.GetName() + IdSuffixes.Progress.Control;
    this.progressControl = ASPx.GetControlCollection().Get(name);
   }
   return this.progressControl;
  },
  GetProgressPanel: function () {
   return this.domHelper.GetChildElement(IdSuffixes.Progress.Panel);
  }
 });
 var ASPxDropZoneView = ASPx.CreateClass(ASPxBaseView, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
   this.enabled = true;
   this.externalDropZoneIDList = [];
   this.savedExternalDropZoneIDList = null;
   this.inlineDropZone = null;
   this.inlineDropZoneAnchorElementID = options.inlineDropZoneAnchorElementID;
   this.animationStrategy = this.animationStrategies[options.dropZoneAnimationType];
   this.DropZoneEnterInternal = new ASPxClientEvent();
   this.DropZoneLeaveInternal = new ASPxClientEvent();
   this.DropZoneDropInternal = new ASPxClientEvent();
   this.fileSystemHelper = new DragAndDropFileSystemHelper();
   this.fileSystemHelper.ProcessingComplete.ClearHandlers();
   this.fileSystemHelper.ProcessingComplete.AddHandler(this.onDropEventProcessed.aspxBind(this));
  },
  InlineInitialize: function() {
   if(!this.options.disableInlineDropZone) {
    this.InitializeInlineDropZone();
    if(this.inlineDropZone)
     aspxGetUploadControlCollection().RegisterDropZone(this.GetName(), this.inlineDropZone.id, true);
    this.AdjustInlineDropZone();
   }
  },
  Initialize: function() {
   this.SetExternalDropZoneID(this.options.externalDropZoneIDList);
   aspxGetUploadControlCollection().RegisterAnchorElement(this.GetName(), this.getAnchorElement());
  },
  SetEnabled: function(enabled) {
   if(this.enabled === enabled)
    return;
   this.setInlineDropZoneEnabled(enabled);
   this.setExternalDropZonesEnabled(enabled);
   this.enabled = enabled;
  },
  setInlineDropZoneEnabled: function(enabled) {
   if(!this.inlineDropZone)
    return;
   if(enabled) {
    aspxGetUploadControlCollection().RegisterAnchorElement(this.GetName(), this.getAnchorElement());
    aspxGetUploadControlCollection().RegisterDropZone(this.GetName(), this.inlineDropZone.id, true);
   }
   else {
    aspxGetUploadControlCollection().DeregisterAnchorElement(this.getAnchorElement());
    aspxGetUploadControlCollection().DeregisterDropZones(this.GetName(), [this.inlineDropZone.id], true);
   }
  },
  setExternalDropZonesEnabled: function(enabled) {
   if(enabled) {
    this.SetExternalDropZoneID(this.savedExternalDropZoneIDList || this.externalDropZoneIDList);
    this.savedExternalDropZoneIDList = null;
   }
   else {
    this.savedExternalDropZoneIDList = this.externalDropZoneIDList;
    this.SetExternalDropZoneID();
   }
  },
  SetExternalDropZoneID: function(externalZoneIDList) {
   aspxGetUploadControlCollection().DeregisterDropZones(this.GetName(), this.externalDropZoneIDList);
   this.externalDropZoneIDList = [];
   if(externalZoneIDList && externalZoneIDList.length) {
    ASPx.Data.ForEach(externalZoneIDList, function(zoneId) {
     aspxGetUploadControlCollection().RegisterDropZone(this.GetName(), zoneId, false);
     this.externalDropZoneIDList.push(zoneId);
    }.aspxBind(this));
   }
  },
  AdjustInlineDropZone: function() {
   if(this.options.disableInlineDropZone || !this.inlineDropZone)
    return;
   var dropZone = this.inlineDropZone,
    anchorElement = this.getAnchorElement(),
    anchorStyle = ASPx.GetCurrentStyle(anchorElement),
    anchorRect = anchorElement.getBoundingClientRect();
   ASPx.Attr.SetAttribute(dropZone.style, "height", anchorElement.offsetHeight + "px");
   ASPx.Attr.SetAttribute(dropZone.style, "width", anchorElement.offsetWidth + "px");
   ASPx.Attr.SetAttribute(dropZone.style, "top", anchorRect.top + "px");
   ASPx.Attr.SetAttribute(dropZone.style, "left", anchorRect.left + "px");
   ASPx.Attr.SetAttribute(dropZone.style, "padding", anchorStyle.padding);
  },
  AdjustSize: function() {
   this.AdjustInlineDropZone();
  },
  InitializeInlineDropZone: function() {
   this.inlineDropZone = this.domHelper.GetMainElement().previousElementSibling;
   if(this.inlineDropZone) {
    this.removeOutdatedInlineDropZone();
    this.moveInlineDropZoneToBody();
   }
  },
  removeOutdatedInlineDropZone: function() {
   var id = this.inlineDropZone.id;
   this.inlineDropZone.id = "";
   var oldZone = document.getElementById(id);
   if(oldZone)
    ASPx.RemoveElement(oldZone);
   this.inlineDropZone.id = id;
  },
  moveInlineDropZoneToBody: function() {
   document.body.appendChild(this.inlineDropZone);
  },
  getAnchorElement: function() {
   if(!this.anchorElement) {
    if(this.inlineDropZoneAnchorElementID)
     this.anchorElement = document.getElementById(this.inlineDropZoneAnchorElementID);
    else
     this.anchorElement = this.domHelper.GetMainElement();
   }
   return this.anchorElement;
  },
  SetInlineDropZoneAnchorElementID: function(id) {
   aspxGetUploadControlCollection().DeregisterAnchorElement(this.getAnchorElement());
   this.anchorElement = null;
   this.inlineDropZoneAnchorElementID = id;
   aspxGetUploadControlCollection().RegisterAnchorElement(this.GetName(), this.getAnchorElement());
   ASPx.AddClassNameToElement(this.inlineDropZone, CSSClasses.DropZone.HasExternalAnchor);
  },
  refreshBase: function(args) {
   ASPxBaseView.prototype.refreshBase.call(this, args);
   this.AdjustInlineDropZone();
  },
  updateFileInfos: function(args) {
   this.fileInfos = args.fileInfos[0];
  },
  onDropEventProcessed: function(files) {
   this.rawFiles = files;
   if(!this.options.enableMultiSelect && this.rawFiles.length > 1)
    this.raiseError(this.options.dragAndDropMoreThanOneFileError);
   else
    this.RaiseStateChangedInternal(this);
  },
  OnDrop: function(e, zoneId) {
   this.rawFiles = [];
   this.RaiseDropZoneDropInternal(e, zoneId);
   this.RaiseDropZoneLeave(e, zoneId);
   this.fileSystemHelper.processDataTransfer(e.dataTransfer);
   if(zoneId === this.inlineDropZone.id)
    this.animationStrategy.hide(this.inlineDropZone);
  },
  OnDragLeave: function(e, zoneId) {
   if(this.inlineDropZone && zoneId === this.inlineDropZone.id)
    this.animationStrategy.hide(this.inlineDropZone);
   this.RaiseDropZoneLeave(e, zoneId);
  },
  OnDragEnter: function(e, zoneId) {
   if(zoneId === this.inlineDropZone.id)
    this.onDragEnterInlineZone();
   this.RaiseDropZoneEnter(e, zoneId);
  },
  onDragEnterInlineZone: function() {
   this.AdjustInlineDropZone();
   this.animationStrategy.show(this.inlineDropZone);
  },
  RaiseDropZoneEnter: function(e, dropZoneId) {
   if(!this.DropZoneEnterInternal.IsEmpty()) {
    var dropZone = document.getElementById(dropZoneId),
     args = new ASPxClientUploadControlDropZoneEnterEventArgs(dropZone);
    this.DropZoneEnterInternal.FireEvent(args);
   }
  },
  RaiseDropZoneLeave: function(e, dropZoneId) {
   if(!this.DropZoneLeaveInternal.IsEmpty()) {
    var dropZone = document.getElementById(dropZoneId),
     args = new ASPxClientUploadControlDropZoneLeaveEventArgs(dropZone);
    this.DropZoneLeaveInternal.FireEvent(args);
   }
  },
  RaiseDropZoneDropInternal: function(e, dropZoneId) {
   if(!this.DropZoneEnterInternal.IsEmpty()) {
    var dropZone = document.getElementById(dropZoneId),
     args = new ASPxClientUploadControlDropZoneDropEventArgs(dropZone);
    this.DropZoneDropInternal.FireEvent(args);
   }
  },
  GetFileInfos: function() {
   var fileInfos = [];
   if(this.fileInfos && this.options.enableMultiSelect)
    fileInfos = this.fileInfos.slice(0);
   ASPx.Data.ForEach(this.rawFiles, function(file) {
    var publicFileObject = ASPxAdvancedInputView.prototype.GetPublicFileObject(file);
    fileInfos.push(new ASPxFileInfo(file, publicFileObject, 0));
   }.aspxBind(this));
   return [fileInfos];
  },
  animationStrategies: {
   None: {
    show: function(dropZone) {
     ASPx.SetElementDisplay(dropZone, true);
    },
    hide: function(dropZone) {
     ASPx.SetElementDisplay(dropZone, false);
    }
   },
   Fade: {
    animationDuration: 250,
    show: function(dropZone) {
     ASPx.AnimationHelper.setOpacity(dropZone, 0);
     ASPx.SetElementDisplay(dropZone, true);
     ASPx.AnimationHelper.fadeIn(dropZone, null, this.animationDuration);
    },
    hide: function(dropZone) {
     ASPx.AnimationHelper.setOpacity(dropZone, 1);
     ASPx.AnimationHelper.fadeOut(dropZone, function() {
      ASPx.SetElementDisplay(dropZone, false);
     }, this.animationDuration);
    }
   }
  }
 });
  var DragAndDropFileSystemHelper = ASPx.CreateClass(null, {
   constructor: function() {
    this.ProcessingComplete = new ASPxClientEvent();
    this.ValidationComplete = new ASPxClientEvent();
   },
   processDataTransfer: function(dataTransfer) {
    this.files = [];
    if(dataTransfer.items && !ASPx.Browser.Edge)
     this.processWebkitItems(dataTransfer.items);
    else if(dataTransfer.files)
     this.finalizeProcessing(dataTransfer.files);
   },
   processWebkitItems: function(items) {
    this.callbackCount = 0;
    ASPx.Data.ForEach(items, function(item) {
     this.processWebkitItem(item);
    }.aspxBind(this));
   },
   processWebkitItem: function(item) {
    if(item.kind == "string")
     return;
    var entry = item.webkitGetAsEntry();
    if(!entry)
     return;
    var entries = [entry];
    this.processEntries(entries);
   },
   processEntries: function(entries) {
    ASPx.Data.ForEach(entries, function(entry) {
     if (entry.isDirectory)
      this.processDirectory(entry.createReader(), this.processEntries);
     else {
      this.callbackCount++;
      entry.file(this.appendFile.aspxBind(this));
     }
    }.aspxBind(this));
   },
   appendFile: function(file) {
    this.callbackCount--;
    this.files.push(file);
    if(this.callbackCount === 0)
     this.finalizeProcessing(this.files);
   },
   processDirectory: function(directoryReader, callback) {
    var entries = [],
     that = this;
    var readEntries = function() {
     that.callbackCount++;
     directoryReader.readEntries(function(results) {
      that.callbackCount--;
      if(results.length) {
       entries = entries.concat(results.slice(0));
       readEntries();
      } else
       callback.call(that, entries);
     });
    };
    readEntries();
   },
   finalizeProcessing: function(files) {
    if(this.ValidationComplete.IsEmpty()) {
     this.ValidationComplete.AddHandler(function() {
      this.ProcessingComplete.FireEvent(this.validFiles);
     }.aspxBind(this));
    }
    this.validateFiles(files);
   },
   validateFiles: function(files) {
    this.validFiles = files;
    this.callbackCount = 0;
    for(var i = 0; i < files.length; i++)
     this.validateFile(files[i]);
    if(this.callbackCount === 0)
     this.ValidationComplete.FireEvent();
   },
   validateFile: function(file) {
    if(ASPx.Browser.Firefox && !file.type && file.size <= Constants.FIREFOX_FOLDER_MAX_SIZE)
     this.examineFile(file);
   },
   examineFile: function(file) {
    var that = this;
    try {
     var reader = new FileReader();
     reader.onerror = that.onReaderError.aspxBind(that);
     reader.onload = that.onReaderLoad.aspxBind(that);
     this.callbackCount++;
     reader.readAsDataURL(file);
    }
    catch(e) {
     this.onReaderError();
    }
   },
   onReaderLoad: function() {
    if(--this.callbackCount === 0)
     this.ValidationComplete.FireEvent();
   },
   onReaderError: function() {
    this.validFiles = [];
    this.ValidationComplete.FireEvent();
   }
  });
 ASPxClientUploadControl.isValidDragAndDropEvent = function(e) {
  if(ASPx.Browser.Safari)
   return isAllowedDragAndDropObjectTypes_Safari(e.dataTransfer.types);
  var hasFiles = false;
  var typeCount = e.dataTransfer.types.length;
  for(var i = 0; i < typeCount; i++) {
   var type = e.dataTransfer.types[i];
   if(type == "Files")
    hasFiles = true;
   else if(!isAllowedDragAndDropObjectType(type))
    return false;
  }
  return hasFiles;
 };
 var isAllowedDragAndDropObjectTypes_Safari = function(types) {
  var hasFiles = false,
   hasFileUrls = false,
   hasProhibitedTypes = false;
  var typeCount = types.length;
  for(var i = 0; i < typeCount; i++) {
   var type = types[i];
   switch(type) {
    case "Files":
     hasFiles = true;
     break;
    case "public.file-url":
     hasFileUrls = true;
     break;
    case "text/html":
     hasProhibitedTypes = true;
     break;
   }
  }
  return hasFiles && (hasFileUrls || !hasProhibitedTypes);
 };
 var isAllowedDragAndDropObjectType = function(type) {
  var typeIsAllowed = type == "text/plain" || type == "Text";
  if(!typeIsAllowed && ASPx.Browser.Firefox)
   typeIsAllowed = type == "application/x-moz-file" || type == "text/x-moz-url";
  if(!typeIsAllowed && ASPx.Browser.WebKitFamily)
   typeIsAllowed = type == "text/uri-list";
  return typeIsAllowed;
 };
 var ASPxFileInfoCache = ASPx.CreateClass(null, {
  constructor: function() {
   this.fileInfos = [];
   this.FileListChanged = new ASPxClientEvent();
   ASPxFileInfoCache.getPlainArray = this.getPlainArray;
  },
  Update: function(args) {
   this.UpdateFileInfos(args);
   var listChangedArgs = new ASPxFileListChangedInternalArgs(this.fileInfos, args.inputIndex, args.fileCountChanged);
   this.RaiseFileListChanged(listChangedArgs);
  },
  UpdateFileInfos: function(args) {
   var currentLength = this.getPlainArray(this.fileInfos).length,
    newLength = this.getPlainArray(args.fileInfos).length;
   args.fileCountChanged = currentLength !== newLength;
   this.fileInfos = args.fileInfos;
  },
  Get: function() {
   return this.getPlainArray(this.fileInfos);
  },
  clear: function() {
   ASPx.Data.ForEach(this.fileInfos, function(fileInfosArr) {
    if(fileInfosArr)
     fileInfosArr.reverse();
    ASPx.Data.ForEach(fileInfosArr, function(fileInfo) {
     fileInfo.dispose();
    }.aspxBind(this));
   }.aspxBind(this));
   this.Update(ASPxEmptyRefreshArgs);
  },
  getPlainArray: function(complexArray) {
   var result = [];
   ASPx.Data.ForEach(complexArray, function(inputFileInfos) {
    ASPx.Data.ForEach(inputFileInfos, function(fileInfo, fileIndex) {
     fileInfo.fileIndex = fileIndex;
     result.push(fileInfo);
    });
   });
   return result;
  },
  getFileInfosCount: function() {
   var count = 0;
   ASPx.Data.ForEach(this.fileInfos, function(fileInfos) {
    count += fileInfos.length;
   }.aspxBind(this));
   return count;
  },
  getSelectedFiles: function(inputIndex) {
   if(inputIndex >= this.fileInfos.length)
    return null;
   var fileInfos = this.fileInfos[inputIndex],
    result = [];
   ASPx.Data.ForEach(fileInfos, function(fileInfo) {
    result.push(fileInfo.publicFileObject);
   });
   return result;
  },
  RemoveFile: function(param) {
   var absoluteIndex = 0,
    fileIndex = -1,
    fileObject = null;
   if(param instanceof ASPxClientUploadControlFile)
    fileObject = param;
   else
    fileIndex = param;
   for(var i = 0; i < this.fileInfos.length; i++) {
    var info = this.tryRemoveFile(this.fileInfos[i], absoluteIndex, fileObject, fileIndex);
    this.fileInfos[i] = info.fileInfos;
    absoluteIndex = info.absoluteIndex;
   }
   var args = {
    fileInfos: this.fileInfos,
    inputIndex: undefined
   };
   this.Update(args);
  },
  tryRemoveFile: function(fileInfos, absoluteIndex, fileObject, fileIndex) {
   var remained = [];
   ASPx.Data.ForEach(fileInfos, function(fileInfo) {
    if(fileObject != null && fileInfo.publicFileObject === fileObject || absoluteIndex === fileIndex)
     fileInfo.dispose();
    else
     remained.push(fileInfo);
    absoluteIndex++;
   });
   return {
    fileInfos: remained.slice(),
    absoluteIndex: absoluteIndex
   };
  },
  GetFileIndexesCount: function(fileInputCount) {
   var count = 0;
   for(var inputIndex = 0; inputIndex < fileInputCount; inputIndex++) {
    var fileInfos = this.GetFileInfos(inputIndex);
    count += fileInfos.length > 0 ? fileInfos.length : 1;
   }
   return count;
  },
  RaiseFileListChanged: function(args) {
   args.fileInfosCount = this.getFileInfosCount();
   this.FileListChanged.FireEvent(args);
  }
 });
 var EmptyStateHelper = ASPx.CreateClass(null, {
  constructor: function(uploadControl) {
   this.control = uploadControl;
  },
  resetCurrentState: function() {
  },
  updateControlState: function() {
  },
  dropControlState: function() {
  },
  updateState: function(uploadingInfo) {
  },
  isFileNameHandlingRequired: function() {
   return false;
  }
 });
 var AdvancedStateHelper = ASPx.CreateClass(EmptyStateHelper, {
  constructor: function(uploadControl) {
   this.constructor.prototype.constructor.call(this, uploadControl);
   this.settings = uploadControl.settings;
   this.state = "";
   this.allState = "";
   this.publicStateArray = [];
   this.currentStateIndex = 0;
   this.isStateSaved = false;
  },
  resetCurrentState: function() {
   this.state = "";
   this.allState = "";
   if(this.publicStateArray.length > 0)
    this.publicStateArray = [];
   this.currentStateIndex = 0;
   this.isStateSaved = false;
  },
  updateControlState: function() {
   var finState = {};
   finState.settings = this.getSettings();
   finState.state = this.getAllState();
   if(this.publicStateArray.length != 0)
    finState.publicState = this.getAllPublicState();
   this.getControlStateObject().finState = finState;
  },
  dropControlState: function() {
   delete this.getControlStateObject().finState;
  },
  updateState: function(uploadingInfo) {
   this.isStateSaved = false;
   this.state = uploadingInfo.state;
   if(uploadingInfo.publicState)
    this.addPublicState(uploadingInfo.publicState);
  },
  saveCurrentUploadState: function() {
   if(this.isStateSaved)
    return;
   this.isStateSaved = true;
   this.currentStateIndex++;
   if(this.allState)
    this.allState += Constants.Delimiters.STATE_ITEM;
   this.allState += this.state;
  },
  getCurrentUploadState: function() {
   return this.state;
  },
  getAllPublicState: function() {
   return this.publicStateArray.join(Constants.Delimiters.STATE_ITEM_ARRAY);
  },
  getAllState: function() {
   return this.allState;
  },
  getSettings: function() {
   return this.settings;
  },
  isFileNameHandlingRequired: function() {
   return this.currentStateIndex % Constants.MAX_HANDLING_FILE_NAME_COUNT == 0;
  },
  addPublicState: function(publicState) {
   if(this.publicStateArray.length == this.currentStateIndex)
    this.publicStateArray.push(publicState);
   else
    this.publicStateArray[this.currentStateIndex] += Constants.Delimiters.STATE_ITEM + publicState;
  },
  getControlStateObject: function() {
   return this.control.stateObject;
  }
 });
 var ASPxLegacyUploadManager = ASPx.CreateClass(null, {
  constructor: function(options, stateHelper) {
   this.options = options;
   this.uploadControl = options.uploadControl;
   this.stateHelper = stateHelper;
   this.isInCallback = false;
   this.isNative = false;
   this.requestUrlPath = "";
   this.fileNameHandling = options.fileNameHandling;
   this.domHelper = options.domHelper;
   this.uploadHelper = options.uploadHelper;
   this.progressHandlerPage = options.progressHandlerPage;
   this.uploadingKey = options.uploadingKey;
   this.name = options.name;
   this.packetSize = options.packetSize;
   this.callbackResultErrorText = options.callbackResultErrorText;
   this.validationSettings = options.validationSettings;
   this.InitializeIframe();
   this.FileUploadErrorInternal = new ASPxClientEvent();
   this.UploadInitiatedInternal = new ASPxClientEvent();
   this.InternalError = new ASPxClientEvent();
   this.FileUploadCompleteInternal = new ASPxClientEvent();
   this.FilesUploadCompleteInternal = new ASPxClientEvent();
   this.FileUploadStartInternal = new ASPxClientEvent();
   this.UploadingProgressChangedInternal = new ASPxClientEvent();
   this.InCallbackChangedInternal = new ASPxClientEvent();
   this.NeedSetJSProperties = new ASPxClientEvent();
   this.BeginProcessUploadingInternal = new ASPxClientEvent();
  },
  UploadFileFromUser: function(fileInfos) {
   if(!this.IsAdvancedModeEnabled() && this.IsUploadProcessingEnabled())
    this.uploadingKey = this.GenerateNewUploadingKey();
   this.stateHelper.resetCurrentState();
   this.fileInfos = fileInfos;
   this.currentFileIndex = 0;
   this.UploadInitiatedInternal.FireEvent();
   this.isComplete = false;
   this.isAborted = false;
   this.isCancel = false;
   this.uploadProcessingErrorText = "";
   var validateObj = {
    commonErrorText: "",
    commonCallbackData: ""
   };
   if(!this.isInCallback) {
    if(this.IsFileUploadCanceled(validateObj)) {
     this.isCancel = true;
     this.RaiseFilesUploadCompleteInternal(validateObj);
     return false;
    }
    var isSuccessful = true;
    if(this.IsAdvancedModeEnabled())
     this.BeginProcessUploading();
    else {
     isSuccessful = this.UploadForm();
     if(this.IsUploadProcessingEnabled())
      this.BeginProcessUploading();
    }
    return true;
   }
  },
  GenerateNewUploadingKey: function() {
   return this.options.uploadingKey + new Date().getTime().toString();
  },
  GetUploadInputsTable: function() {
   return this.domHelper.GetChildElement(IdSuffixes.Input.UploadInputsTable);
  },
  IsAdvancedModeEnabled: function() {
   return this.options.advancedModeEnabledInternal;
  },
  isFileNameHandlingEnabled: function() {
   return this.fileNameHandling && this.IsAdvancedModeEnabled();
  },
  CancelUploading: function(isUI) {
   this.cancelUploadingProcess(isUI);
   window.setTimeout(this.UploadAsyncCancelProcessing.aspxBind(this), 100);
  },
  cancelUploadingProcess: function (isUI) {
   if(this.isInCallback) {
    if(isUI)
     this.isCancel = true;
    else
     this.isAborted = true;
    var iframeUrl = ASPx.SSLSecureBlankUrl;
    if(ASPx.Browser.Opera)
     this.SetIFrameUrl(iframeUrl + "&" + Constants.QueryParamNames.CANCEL_UPLOAD + "=" + (new Date()).valueOf());
    this.SetIFrameUrl(iframeUrl);
    this.EndProcessUploading();
   }
  },
  CancelUploadingFileFromHelper: function () {
   this.cancelUploadingProcess();
  },
  IsRightToLeft: function () {
   return ASPx.IsElementRightToLeft(this.GetMainElement());
  },
  IsUploadProcessingEnabled: function () {
   return this.options.uploadProcessingEnabled;
  },
  CreateXmlHttpRequestObject: function () {
   if(!this.xmlHttpRequest) {
    if(typeof (XMLHttpRequest) != 'undefined')
     this.xmlHttpRequest = new XMLHttpRequest();
    else if(typeof (ActiveXObject) != 'undefined')
     this.xmlHttpRequest = new ActiveXObject('Microsoft.XMLHTTP');
    this.xmlHttpRequest.onreadystatechange = function() { this.UploadAsyncXmlHttpResponse(this.xmlHttpRequest); }.aspxBind(this);
   }
   return this.xmlHttpRequest;
  },
  BeginProcessUploading: function() {
   this.TotalFilesLength = this.GetTotalLength();
   this.BeginProcessUploadingInternal.FireEvent();
   this.uploadingTimerID = window.setInterval(function() { this.UploadProcessing(); }.aspxBind(this), 1000);
  },
  EndProcessUploading: function () {
   this.uploadingInfo = null;
   if(this.uploadingTimerID != null)
    this.uploadingTimerID = ASPx.Timer.ClearInterval(this.uploadingTimerID);
   if(this.IsAdvancedModeEnabled() && !this.isCancel && !this.isAborted) {
    this.stateHelper.saveCurrentUploadState();
    this.UploadForm();
   }
  },
  GetFileIndexesCount: function() {
   return this.fileInfos.length;
  },
  GetHelperRequestData: function () {
   this.currentFileIndex = this.currentFileIndex || 0;
   this.isLastChunk = false;
   var fileInfo = this.fileInfos[this.currentFileIndex] || {},
    currentIndex = this.currentFileIndex,
    startPos = 0,
    requestData = { data: "", isNewFile: !fileInfo.uploadedLength },
    isNewUploading = !(currentIndex || !fileInfo || fileInfo.uploadedLength),
    chunkLength;
   if(fileInfo) {
    fileInfo.uploadedLength = fileInfo.uploadedLength || 0;
    startPos = fileInfo.uploadedLength;
    chunkLength = fileInfo.fileSize - fileInfo.uploadedLength;
    if(chunkLength > this.packetSize) {
     chunkLength = this.packetSize;
    } else {
     this.currentFileIndex++;
     if(this.currentFileIndex === this.fileInfos.length) {
      this.isLastChunk = true;
     }
    }
    fileInfo.uploadedLength += chunkLength;
   }
   var fileData = this.uploadHelper.ReadFileData(fileInfo.file, startPos, chunkLength, fileInfo.inputIndex, fileInfo.fileIndex);
   if(fileData.errorText)
    requestData.errorText = fileData.errorText;
   else {
    requestData.data = this.uploadHelper.BuildChunkRequest(
     isNewUploading,
     this.stateHelper.getSettings(),
     this.stateHelper.getCurrentUploadState(),
     this.TotalFilesLength,
     fileInfo.inputIndex,
     currentIndex,
     fileInfo.fileSize,
     fileInfo.fileType,
     chunkLength,
     fileInfo.fileName,
     fileData.data);
   }
   return requestData;
  },
  GetUploadingInfo: function () {
   if(!this.uploadingInfo) {
    this.uploadingInfo = {
     isUploadingStart: false,
     isComplete: false,
     currentFileName: "",
     currentFileContentLength: 0,
     currentFileUploadedContentLength: 0,
     currentFileProgress: 0,
     currentContentType: "",
     totalUploadedSize: 0,
     totalLength: 0,
     progress: 0,
     settings: "",
     state: "",
     publicState: "",
     errorText: ""
    };
   }
   return this.uploadingInfo;
  },
  GetTotalLength: function() {
   var totalFileLength = 0;
   ASPx.Data.ForEach(this.fileInfos, function(file) {
    totalFileLength += parseInt(file.fileSize);
   });
   return totalFileLength;
  },
  SetCompleteUploadingInfo: function(info) {
   info.isUploadingStart = false;
   info.isComplete = true;
   info.progress = 100;
   info.totalUploadedSize = info.totalLength;
  },
  UpdateUploadingInfo: function (responseXML) {
   var info = this.GetUploadingInfo();
   if(responseXML == null || this.GetXmlAttribute(responseXML, 'empty') == 'true') {
    if(info.isUploadingStart && (this.IsAdvancedModeEnabled() || this.isComplete))
     this.SetCompleteUploadingInfo(info);
    return;
   }
   if(this.isComplete && !this.IsAdvancedModeEnabled()) {
    this.SetCompleteUploadingInfo(info);
    return;
   }
   info.isUploadingStart = true;
   info.errorText = this.GetXmlAttribute(responseXML, 'errorText');
   info.currentFileName = this.GetXmlAttribute(responseXML, 'fileName');
   info.currentFileContentLength = this.GetXmlAttribute(responseXML, 'fileSize');
   info.currentFileUploadedContentLength = this.GetXmlAttribute(responseXML, 'fileUploadedSize');
   info.currentFileProgress = this.GetXmlAttribute(responseXML, 'fileProgress');
   info.currentContentType = this.GetXmlAttribute(responseXML, 'contentType');
   info.totalUploadedSize = parseInt(this.GetXmlAttribute(responseXML, 'totalUploadedSize'));
   info.totalLength = parseInt(this.GetXmlAttribute(responseXML, 'totalSize'));
   info.progress = parseInt(this.GetXmlAttribute(responseXML, 'progress'));
   info.settings = this.GetXmlAttribute(responseXML, 'settings');
   info.state = this.GetXmlAttribute(responseXML, 'state');
   info.publicState = this.GetXmlAttribute(responseXML, 'publicState');
  },
  UploadProcessing: function(forceUploadRequest) {
   if(this.isProgressWaiting || this.isResponseWaiting) return;
   this.isProgressWaiting = true;
   if(!(this.GetUploadingInfo().isComplete || this.isCancel)) {
    var fileNamesToHandle = null;
    if(!forceUploadRequest && this.IsAdvancedModeEnabled())
     fileNamesToHandle = this.processUploadState();
    if(fileNamesToHandle)
     this.sendFileNameHandlingCallback(fileNamesToHandle);
    else
     this.sendUploadRequest();
   }
   else {
    this.fileInfos[this.currentFileIndex].OnUploadComplete.FireEvent();
    this.EndProcessUploading();
   }
   this.isProgressWaiting = false;
  },
  processUploadState: function() {
   var fileNamesToHandle = null;
   var fileInfo = this.fileInfos[this.currentFileIndex];
   var isNewFile = !fileInfo.uploadedLength;
   if(isNewFile) {
    if(this.currentFileIndex > 0)
     this.stateHelper.saveCurrentUploadState();
    if(this.isFileNameHandlingEnabled() && this.stateHelper.isFileNameHandlingRequired())
     fileNamesToHandle = this.getNextFileNamesToHandle();
   }
   return fileNamesToHandle;
  },
  getNextFileNamesToHandle: function() {
   var result = [];
   var fileEndIndex = this.currentFileIndex + Constants.MAX_HANDLING_FILE_NAME_COUNT;
   if(fileEndIndex > this.fileInfos.length)
    fileEndIndex = this.fileInfos.length;
   for(var i = this.currentFileIndex; i < fileEndIndex; i++) {
    var fileInfo = this.fileInfos[i];
    result.push(fileInfo.fileName);
   }
   return result;
  },
  sendFileNameHandlingCallback: function(fileNames) {
   var callbackArg = this.getCallbackArgumentString(
    this.GetProgressInfoKey(), this.stateHelper.getSettings(), 
    this.stateHelper.getCurrentUploadState(), fileNames);
   this.uploadControl.CreateCallback(callbackArg);
   this.isResponseWaiting = true;
  },
  getCallbackArgumentString: function(uploadKey, settings, state, fileNames) {
   var fileNamesStr = fileNames.join(Constants.Delimiters.CALLBACK_ITEM);
   var argStr = [settings, state, fileNamesStr].join(Constants.Delimiters.STATE_ITEM_ARRAY);
   return [uploadKey, argStr].join(Constants.Delimiters.CALLBACK_ARGUMENT);
  },
  onFileNameHandlingCallback: function(result) {
   var info = { state: result };
   this.stateHelper.updateState(info);
   this.isResponseWaiting = false;
   window.setTimeout(function() { this.UploadProcessing(true); }.aspxBind(this), 0);
  },
  onFileNameHandlingCallbackError: function(result) {
   this.isResponseWaiting = false;
   this.cancelUploadingFromHelperOnError(result);
  },
  sendUploadRequest: function() {
   var xmlHttp = this.CreateXmlHttpRequestObject();
   if(xmlHttp == null) {
    this.isProgressWaiting = false;
    this.EndProcessUploading();
    return;
   }
   var url = this.progressHandlerPage + '?' + Constants.QueryParamNames.PROGRESS_HANDLER + '=' + this.GetProgressInfoKey();
   var httpMethod = "GET";
   var requestData = { data: "" };
   if(this.IsAdvancedModeEnabled()) {
    url += "&" + Constants.QueryParamNames.HELPER_UPLOADING_CALLBACK + "=" + this.name;
    httpMethod = "POST";
    var previousFileIndex = this.currentFileIndex;
    requestData = this.GetHelperRequestData();
    if(requestData.isNewFile)
     this.fileInfos[previousFileIndex].OnUploadStart.FireEvent();
    if(requestData.errorText) {
     this.isProgressWaiting = false;
     this.uploadProcessingErrorText = requestData.errorText;
     this.CancelUploadingFileFromHelper();
     return;
    }
   }
   this.requestUrlPath = url;
   xmlHttp.open(httpMethod, url, true);
   xmlHttp.send(requestData.data);
   this.isResponseWaiting = true;
  },
  UploadAsyncXmlHttpResponse: function (xmlHttp) {
   if(xmlHttp && xmlHttp.readyState == 4) {
    var successful = false;
    var errorText = "";
    var info = null;
    if(xmlHttp.status == 200) {
     var errorObj = this.tryGetResponseErrorObject(xmlHttp.responseText);
     if(errorObj)
      errorText = this.processResponseErrorObject(errorObj);
     else {
      var xmlDoc = this.GetResponseXml(xmlHttp);
      this.UpdateUploadingInfo(xmlDoc);
      info = this.GetUploadingInfo();
      successful = !info.errorText;
      this.stateHelper.updateState(info);
     }
    }
    if(successful) {
     if(info.isUploadingStart || info.isComplete) {
      this.OnUploadingProgressChanged(this.fileInfos.length, info);
     }
    } else {
     if(this.IsAdvancedModeEnabled()) {
      if(!errorText)
       errorText = (info && info.errorText != "") ? info.errorText : xmlHttp.statusText;
      this.cancelUploadingFromHelperOnError(errorText);
     }
    }
    var isEndProcessUploading = !(this.GetUploadingInfo().isUploadingStart || this.isInCallback) ||
     this.IsAdvancedModeEnabled() && this.isLastChunk || this.uploadingTimerID == -1 || this.isComplete;
    if(isEndProcessUploading)
     this.EndProcessUploading();
    else if(this.IsAdvancedModeEnabled())
     window.setTimeout(function() { this.UploadProcessing(); }.aspxBind(this), 0);
    this.isResponseWaiting = false;
   }
  },
  UploadAsyncCancelProcessing: function () {
   if(this.isResponseWaiting)
    window.setTimeout(this.UploadAsyncCancelProcessing.aspxBind(this), 100);
   else {
    var xmlHttp = this.CreateXmlHttpRequestObject();
    if(xmlHttp && this.IsAdvancedModeEnabled()) {
     this.stateHelper.saveCurrentUploadState();
     var url = this.progressHandlerPage + '?' + Constants.QueryParamNames.PROGRESS_HANDLER + '=' + this.GetProgressInfoKey();
     url += "&" + Constants.QueryParamNames.HELPER_UPLOADING_CALLBACK + "=" + this.name;
     var cancelRequest = this.uploadHelper.BuildCancelRequest(
      this.stateHelper.getSettings(), this.stateHelper.getCurrentUploadState(), this.stateHelper.getAllState());
     xmlHttp.open("POST", url, false);
     xmlHttp.send(cancelRequest);
     this.stateHelper.resetCurrentState();
    }
   }
  },
  cancelUploadingFromHelperOnError: function(errorText) {
   this.uploadProcessingErrorText = errorText;
   this.isLastChunk = true;
   this.CancelUploadingFileFromHelper();
  },
  GetResponseXml: function(xmlHttp) {
   var xmlDoc = xmlHttp.responseXML;
   if(this.IsInvalidXmlDocument(xmlDoc)) {
    var responseContent = this.GetContentFromString(xmlHttp.responseText, "<", ">");
    try {
     xmlDoc = ASPx.Xml.Parse(responseContent);
    }
    catch(ex) {
     xmlDoc = null;
    }
   }
   return xmlDoc;
  },
  IsInvalidXmlDocument: function(xmlDoc) {
   var ret = xmlDoc == null || xmlDoc.documentElement == null;
   if(!ret) {
    var xmlStr = xmlDoc.documentElement.outerHTML;
    ret = xmlStr && xmlStr.toLowerCase().indexOf("parsererror") > -1;
   }
   return ret;
  },
  GetContentFromString: function(str, startSubstr, endSubstr) {
   var startIndex = str.indexOf(startSubstr),
    endIndex = str.lastIndexOf(endSubstr);
   return str.substring(startIndex, endIndex + 1);
  },
  GetXmlAttribute: function (xmlDoc, attrName) {
   return xmlDoc.documentElement.getAttribute(attrName);
  },
  WriteResponseString: function (responseString) {
   try {
    this.GetFakeIframeDocument().body.innerHTML = responseString;
   }
   catch (e) { }
  },
  restoreProtectedWhitespaceSeries: function (text) {
   return text.replace(/&nbsp;/g, ' ').replace(/&nbspx;/g, '&nbsp;');
  },
  raiseFileUploadErrorInternal: function(errorText, errorType, index) {
   this.FileUploadErrorInternal.FireEvent({
    text: errorText,
    type: errorType,
    inputIndex: index
   });
  },
  OnCompleteFileUpload: function () {
   this.isComplete = true;
   var commonErrorText = '';
   var responseObj = this.GetResponseObject();
   if(responseObj) {
    if(responseObj.isResponseErrorObject)
     commonErrorText = this.processResponseErrorObject(responseObj);
    else
     this.processResponseObject(responseObj);
   }
   if(!this.isCancel) {
    this.stateHelper.resetCurrentState();
    if(!commonErrorText)
     commonErrorText = this.getCommonErrorText(responseObj);
   }
   else {
    var currentFileInfo = this.fileInfos[this.currentFileIndex] || this.fileInfos[this.currentFileIndex - 1];
    currentFileInfo.OnUploadComplete.FireEvent();
   }
   if(commonErrorText)
    this.raiseFileUploadErrorInternal(commonErrorText, ASPxUploadErrorTypes.Common);
   this.RaiseInCallbackChange(false);
   if(responseObj && !responseObj.isResponseErrorObject)
    this.RaiseFilesUploadCompleteInternal(responseObj);
   else
    this.RaiseFilesUploadCompleteInternal({
     commonErrorText: commonErrorText,
     commonCallbackData: ""
    });
  },
  processResponseObject: function(responseObj) {
   if(responseObj.customJSProperties)
    this.NeedSetJSProperties.FireEvent(responseObj.customJSProperties);
   var indexTable = [];
   ASPx.Data.ForEach(this.fileInfos, function(fileInfo) {
    var index = fileInfo.inputIndex;
    if(!indexTable[index])
     indexTable[index] = 1;
    else
     indexTable[index]++;
   });
   var fileInputCount = this.domHelper.GetFileInputCountInternal();
   for(var inputIndex = 0, responseFileIndex = -1; inputIndex < fileInputCount; inputIndex++) {
    var fileCount = indexTable[inputIndex] || 0;
    if(this.options.enableMultiSelect) {
     var errorTexts = [];
     for(var j = 0; j < fileCount; j++) {
      var eventInputIndex = fileInputCount > 1 ? inputIndex : j;
      responseFileIndex++;
      this.raiseFileUploadCompleteInternal(responseFileIndex, eventInputIndex, responseObj);
      if(!responseObj.isValidArray[responseFileIndex] && responseObj.errorTexts[responseFileIndex])
       errorTexts.push(responseObj.errorTexts[responseFileIndex]);
     }
     if(errorTexts.length)
      this.raiseFileUploadErrorInternal(errorTexts.join("<br />"), ASPxUploadErrorTypes.InputRowError, inputIndex);
    }
    else {
     responseFileIndex++;
     if(fileCount == 1) {
      if(!responseObj.isValidArray[responseFileIndex] && responseObj.errorTexts[responseFileIndex])
       this.raiseFileUploadErrorInternal(responseObj.errorTexts[responseFileIndex], ASPxUploadErrorTypes.InputRowError, inputIndex);
      this.raiseFileUploadCompleteInternal(responseFileIndex, inputIndex, responseObj);
     }
    }
   }
  },
  processResponseErrorObject: function(responseObj) {
   var errorText = responseObj.generalError;
   if(responseObj.redirect) {
    if(this.detectAuthorizationRedirect(responseObj.redirect, this.requestUrlPath))
     errorText = responseObj.message;
    else if(!errorText)
     errorText = this.callbackResultErrorText;
   }
   this.requestUrlPath = "";
   return errorText;
  },
  detectAuthorizationRedirect: function(url, originUrlPath) {
   var token = encodeURIComponent(originUrlPath).toLowerCase();
   token = "?returnurl=" + token;
   return url.toLowerCase().indexOf(token) >= 0;
  },
  getCommonErrorText: function(responseObj) {
   if(responseObj && !responseObj.isResponseErrorObject)
    return responseObj.commonErrorText;
   else if(this.uploadProcessingErrorText != '')
    return this.uploadProcessingErrorText;
   else
    return this.callbackResultErrorText;
  },
  InitializeIframe: function() {
   if(ASPx.Browser.Opera && !frames[this.GetFakeIframeName()])
    this.ReinitializeIFrame(this.GetFakeIframe());
   this.GetIFrameUrl();
   ASPx.Evt.AttachEventToElement(this.GetFakeIframeElement(), "load", function(){
    if(this.isInCallback)
     this.OnCompleteFileUpload();
   }.aspxBind(this));
  },
  ReinitializeIFrame: function(iframe) {
   var divElem = document.createElement("DIV");
   ASPx.SetElementDisplay(divElem, false);
   var parentIframe = iframe.parentNode;
   parentIframe.appendChild(divElem);
   divElem.appendChild(iframe);
  },
  GetFakeIframe: function() {
   var name = this.GetFakeIframeName();
   return document.getElementById(name);
  },
  GetFakeIframeElement: function () {
   return this.GetFakeIframe();
  },
  GetInnerHTML: function (element) {
   var html = element.innerHTML;
   if(/&nbsp;/g.test(html)) {
    html = html.replace(/&nbsp;/g, "%C2%A0");
    html = decodeURIComponent(html);
   }
   return html;
  },
  GetFakeIframeResponseString: function(asText) {
   var container = this.GetFakeIframeDocument().body;
   var html = asText ? ASPx.GetInnerText(container) : this.GetInnerHTML(container);
   return ASPx.Str.DecodeHtml(html);
  },
  GetFakeIframeDocument: function () {
   return this.GetFakeIframe().contentDocument;
  },
  GetIFrameUrl: function() {
   if(!this.iframeUrl) {
    var iframe = this.GetFakeIframeElement();
    var iframeSrc = ASPx.Attr.GetAttribute(iframe, "src");
    this.iframeUrl = (iframeSrc) ? iframeSrc : "";
   }
   return this.iframeUrl;
  },
  SetIFrameUrl: function (url) {
   var iframe = this.GetFakeIframeElement();
   ASPx.Attr.SetAttribute(iframe, "src", url);
  },
  GetFakeIframeName: function() {
   return this.name + IdSuffixes.Upload.IFrame;
  },
  OnUploadingProgressChanged: function (fileCount, info) {
   this.RaiseUploadingProgressChanged(fileCount, info.currentFileName, info.currentFileContentLength,
    info.currentFileUploadedContentLength, info.currentFileProgress, info.totalLength, info.totalUploadedSize, info.progress);
   if(info.currentFileProgress === "100" && !(this.isCancel || this.isAborted) && this.currentFileIndex)
    this.fileInfos[this.currentFileIndex - 1].OnUploadComplete.FireEvent();
  },
  GetProgressInfoKey: function () {
   return this.uploadingKey;
  },
  GetResponseObject: function () {
   var ret = null,
    responseString = "";
   try {
    responseString = this.GetFakeIframeResponseString(true);
    ret = this.tryGetResponseErrorObject(responseString);
    if(!ret) {
     responseString = this.GetFakeIframeResponseString();
     ret = window.eval(responseString);
    }
   }
   catch(ex) { }
   return this.GetCorrectedResponseObject(ret, responseString);
  },
  GetCorrectedResponseObject: function(responseObj, responseString) {
   if(responseObj != null && !responseObj.isResponseErrorObject && !responseObj.hasOwnProperty("commonCallbackData")) {
    var responseContent = this.GetContentFromString(responseString, "(", ")");
    try {
     responseObj = window.eval(responseContent);
    }
    catch(ex) { }
   }
   return responseObj;
  },
  tryGetResponseErrorObject: function(responseString) {
   var prefixIndex = responseString.indexOf(ASPx.CallbackResultPrefix);
   if(prefixIndex == -1)
    return null;
   responseString = responseString.substr(prefixIndex + ASPx.CallbackResultPrefix.length);
   var resultObj = null;
   try {
    resultObj = this.uploadControl.EvalCallbackResult(responseString);
   } 
   catch(e) { }
   if(resultObj)
    resultObj.isResponseErrorObject = true;
   return resultObj;
  },
  getUrlPathAndQuery: function(url) {
   if(!url) return "";
   var index = url.indexOf("//");
   if(index == -1)
    return url;
   url = url.substr(index + 2);
   index = url.indexOf("/");
   if(index > -1)
    url = url.substr(index);
   return url;
  },
  GetUploadFormAction: function (form) {
   var action = form.action;
   if(this.IsAdvancedModeEnabled())
    action = this.AddQueryParamToUrl(action, Constants.QueryParamNames.PROGRESS_HANDLER, this.GetProgressInfoKey());
   else if(this.IsUploadProcessingEnabled())
    action = this.AddQueryParamToUrl(action, Constants.QueryParamNames.PROGRESS_INFO, this.GetProgressInfoKey());
   if(this.IsAdvancedModeEnabled())
    action = this.AddQueryParamToUrl(action, Constants.QueryParamNames.HELPER_UPLOADING_CALLBACK, this.name);
   else
    action = this.AddQueryParamToUrl(action, Constants.QueryParamNames.UPLOADING_CALLBACK, this.name);
   return action;
  },
  AddQueryParamToUrl: function (url, paramName, paramValue) {
   var prefix = url.indexOf("?") >= 0 ? "&" : "?";
   var paramQueryString = prefix + paramName + "=" + paramValue;
   var anchorStart = url.indexOf("#");
   return anchorStart >= 0
    ? url.substring(0, anchorStart) + paramQueryString + url.substring(anchorStart)
    : url + paramQueryString;
  },
  GetUploadFormTarget: function (form) {
   return this.GetFakeIframe().name;
  },
  UploadForm: function () {
   var form = this.GetParentForm();
   if(!form) return;
   var sourceTarget = form.target;
   var soureActionString = form.action;
   var sourceMethod = form.method;
   form.action = this.GetUploadFormAction(form);
   form.target = this.GetUploadFormTarget(form);
   form.method = "post";
   this.requestUrlPath = this.getUrlPathAndQuery(form.action);
   this.stateHelper.updateControlState();
   var isInternalErrorOccurred = false;
   try {
    form.submit();
   }
   catch (e) {
    isInternalErrorOccurred = true;
    this.WriteResponseString(Constants.ERROR_TEXT_RESPONSE_PREFIX + this.options.generalErrorText);
    this.OnCompleteFileUpload();
   }
   this.stateHelper.dropControlState();
   form.target = sourceTarget;
   form.action = soureActionString;
   form.method = sourceMethod;
   return !isInternalErrorOccurred;
  },
  IsFileUploadCanceled: function (validateObj) {
   var isCancel = this.RaiseFileUploadStartInternal();
   if(!isCancel)
    this.RaiseInCallbackChange(true);
   else
    validateObj.commonErrorText = this.options.uploadWasCanceledErrorText;
   return isCancel;
  },
  RaiseInCallbackChange: function(isInCallback) {
   this.isInCallback = isInCallback;
   this.InCallbackChangedInternal.FireEvent(isInCallback);
  },
  RaiseUploadingProgressChanged: function (fileCount, currentFileName, currentFileContentLength,
             currentFileUploadedContentLength, currentFileProgress, totalContentLength, uploadedContentLength, progress) {
   if(!this.UploadingProgressChangedInternal.IsEmpty()) {
    var args = new ASPxClientUploadControlUploadingProgressChangedEventArgs(fileCount, currentFileName, currentFileContentLength,
     currentFileUploadedContentLength, currentFileProgress, totalContentLength, uploadedContentLength, progress);
    this.UploadingProgressChangedInternal.FireEvent(args);
   }
  },
  raiseFileUploadCompleteInternal: function(index, inputIndex, responseObj) {
   if(!this.FileUploadCompleteInternal.IsEmpty()) {
    var args = this.CreateFileUploadCompleteEventArgs(index, inputIndex, responseObj);
    this.FileUploadCompleteInternal.FireEvent(args);
   }
  },
  CreateFileUploadCompleteEventArgs: function(index, inputIndex, responseObj) {
   return new ASPxClientUploadControlFileUploadCompleteEventArgs(inputIndex, responseObj.isValidArray[index],
    responseObj.errorTexts[index], responseObj.callbackDataArray[index]);
  },
  RaiseFilesUploadCompleteInternal: function (responseObj) {
   ASPx.Data.ForEach(this.fileInfos, function(fileInfo) {
    fileInfo.uploadedLength = 0;
   });
   var args = {
    commonErrorText: responseObj.commonErrorText,
    commonCallbackData: responseObj.commonCallbackData,
    uploadCancelled: this.isCancel || this.isAborted
   };
   this.FilesUploadCompleteInternal.FireEvent(args);
  },
  RaiseFileUploadStartInternal: function () {
   var ret = false;
   var args = new ASPxClientUploadControlFilesUploadStartEventArgs(false);
   this.FileUploadStartInternal.FireEvent(args);
   ret = args.cancel;
   return ret;
  }
 });
 var ASPxUploadHelperStandardStrategy = ASPx.CreateClass(null, {
  constructor: function(options) {
   this.domHelper = options.domHelper;
  },
  IsHelperElementReady: function() {
   return true;
  }
 });
 var ASPxUploadHelperHTML5 = ASPx.CreateClass(ASPxUploadHelperStandardStrategy, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  FileSlice: function(file, startPos, endPos) {
   if(file.slice)
    return file.slice(startPos, endPos);
   if(ASPx.Browser.WebKitFamily && file.webkitSlice)
    return file.webkitSlice(startPos, endPos);
   if(ASPx.Browser.NetscapeFamily && file.mozSlice)
    return file.mozSlice(startPos, endPos);
   throw "'File.slice()' method is not implemented";
  },
  ReadFileData: function(file, startPos, chunkLength) {
   var fileData = {};
   if(!chunkLength)
    return fileData;
   try {
    fileData.data = this.FileSlice(file, startPos, startPos + chunkLength);
   }
   catch(ex) {
    fileData.errorText = "" + ex;
   }
   return fileData;
  },
  RemoveFileInfo: function(inputIndex, fileIndex) {
   var fileInfos = this.GetFileInfos(inputIndex);
   ASPx.Data.ArrayRemoveAt(fileInfos, fileIndex);
  },
  BuildChunkRequest: function (isNewUploading, settings, state, totalSize, inputIndex, fileIndex, fileSize, fileType, chunkSize, fileName, fileData) {
   var index = fileIndex;
   var formData = new FormData();
   formData.append("IsNewUploading", isNewUploading ? "true" : "false");
   formData.append("Settings", settings);
   formData.append("State", state);
   formData.append("TotalSize", totalSize);
   formData.append("FileIndex", index);
   formData.append("FileSize", fileSize);
   formData.append("FileType", fileType);
   formData.append("ChunkSize", chunkSize);
   formData.append("FileName", fileName);
   if(chunkSize)
    formData.append("Data", fileData);
   return formData;
  },
  BuildCancelRequest: function(settings, state, allStatesString) {
   var formData = new FormData();
   formData.append("IsCancel", "true");
   formData.append("Settings", settings);
   formData.append("State", state);
   formData.append("AllStatesString", allStatesString);
   return formData;
  }
 });
 var ASPxUploadHelperSL = ASPx.CreateClass(ASPxUploadHelperStandardStrategy, {
  constructor: function(options) {
   this.constructor.prototype.constructor.call(this, options);
  },
  SetCursorStyle: function(inputIndex, cursorStyle) {
   if(this.IsHelperElementReady(inputIndex)) {
    var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
    slElement.content.sl.SetCursorStyle(cursorStyle);
   }
  },
  ClearFileInfos: function(inputIndex) {
   if(this.IsHelperElementReady(inputIndex)) {
    var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
    return slElement.content.sl.ClearFileInfos();
   }
  },
  GetErrorText: function(stringData) {
   var index = stringData.indexOf(Constants.ERROR_TEXT_RESPONSE_PREFIX) + Constants.ERROR_TEXT_RESPONSE_PREFIX.length;
   return stringData.substr(index);
  },
  GetFileInfos: function(inputIndex) {
   if(this.IsHelperElementReady(inputIndex)) {
    var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
    var fileInfos = eval(slElement.content.sl.FileInfos);
    for(var i = 0, count = fileInfos.length; i < count; i++)
     fileInfos[i].fileType = "";
    return fileInfos;
   }
   return [];
  },
  ReadBase64StringData: function(fileIndex, startPos, length, inputIndex) {
   if(this.IsHelperElementReady(inputIndex)) {
    var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
    return slElement.content.sl.ReadBase64StringData(fileIndex, startPos, length);
   }
   return null;
  },
  ReadFileData: function(file, startPos, chunkLength, inputIndex, fileIndex) {
   var fileData = {};
   var encodedData = this.ReadBase64StringData(fileIndex, startPos, chunkLength, inputIndex);
   if(this.IsErrorOccurred(encodedData))
    fileData.errorText = this.GetErrorText(encodedData);
   else
    fileData.data = encodedData;
   return fileData;
  },
  IsErrorOccurred: function (stringData) {
   return stringData !== null ? stringData.indexOf(IdSuffixes.SL.ErrorTextResponsePrefix) != -1 : true;
  },
  RemoveFileInfo: function(inputIndex, fileIndex) {
   var slElement = this.domHelper.GetSlUploadHelperElement(inputIndex);
   return slElement.content.sl.RemoveFileInfo(fileIndex);
  },
  BuildChunkRequest: function(isNewUploading, settings, state, totalSize, inputIndex, fileIndex, fileSize, fileType, chunkSize, fileName, fileData) {
   var index = fileIndex; 
   var request = "";
   request += "IsNewUploading:" + (isNewUploading ? "true" : "false") + "\r\n";
   request += "TotalSize:" + totalSize + "\r\n";
   request += "FileIndex:" + index + "\r\n";
   request += "FileSize:" + fileSize + "\r\n";
   request += "FileType:" + fileType + "\r\n";
   request += "ChunkSize:" + chunkSize + "\r\n";
   request += "FileName:" + fileName + "\r\n";
   request += "Settings:" + settings + "\r\n";
   request += "State:" + state + "\r\n";
   request += "EncodingData:" + fileData;
   return request;
  },
  BuildCancelRequest: function(settings, state, allStatesString) {
   var request = "";
   request += "IsCancel:true" + "\r\n";
   request += "State:" + state + "\r\n";
   request += "AllStatesString:" + allStatesString;
   return request;
  },
  IsHelperElementReady: function(index) {
   return this.domHelper.IsSlObjectLoaded(index);
  }
 });
 var ASPxDOMHelper = ASPx.CreateClass(null, {
  constructor: function(options) {
   this.name = options.name;
   this.stateObject = options.stateObject;
   this.options = options;
   this.isMultiFileInput = false;
  },
  IsMouseOverElement: function(mouseEvt, element) {
   if(!element) return false;
   var x = ASPx.GetAbsoluteX(element);
   var y = ASPx.GetAbsoluteY(element);
   var w = element.offsetWidth;
   var h = element.offsetHeight;
   var eventX = ASPx.Evt.GetEventX(mouseEvt);
   var eventY = ASPx.Evt.GetEventY(mouseEvt);
   return (eventX >= x && eventX < (x + w) && eventY >= y && eventY < (y + h));
  },
  GetFileInputCountInternal: function() {
   return this.stateObject.inputCount;
  },
  IsSlObjectLoaded: function (inputIndex) {
   var slElement = this.GetSlUploadHelperElement(inputIndex);
   try {
    if(slElement) {
     if(slElement.content) {
      return !!slElement.content.sl;
     }
     else if(slElement.Content) {
      return slElement.Content.sl;
     }
    }
   }
   catch(e) { }
   return false;
  },
  GetFileInputSeparatorRow: function (index) {
   if(this.options.fileInputSpacing == "" || this.GetFileInputCountInternal() == 1)
    return null;
   return ASPx.GetNodesByPartialClassName(this.GetMainElement(), CSSClasses.SeparatorRow)[index || 0];
  },
  GetAddUploadButtonsSeparatorRow: function() {
   return this.GetChildElement(IdSuffixes.Input.AddButtonsSeparator);
  },
  GetAddUploadButtonsPanelRow: function() {
   return this.GetChildElement(IdSuffixes.Input.AddUploadButtonPanelRow);
  },
  getTooltipValue: function() {
   return ASPx.Attr.GetAttribute(this.GetMainElement(), "title");
  }
 });
 var ASPxClientUploadControlFilesUploadStartEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(cancel) {
   this.constructor.prototype.constructor.call(this);
   this.cancel = cancel;
  }
 });
 var ASPxClientUploadControlFileUploadCompleteEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(inputIndex, isValid, errorText, callbackData) {
   this.constructor.prototype.constructor.call(this);
   this.inputIndex = inputIndex;
   this.isValid = isValid;
   this.errorText = errorText;
   this.callbackData = callbackData;
  }
 });
 var ASPxClientUploadControlFilesUploadCompleteEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(errorText, callbackData) {
   this.constructor.prototype.constructor.call(this);
   this.errorText = errorText;
   this.callbackData = callbackData;
  }
 });
 var ASPxClientUploadControlTextChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(inputIndex) {
   this.constructor.prototype.constructor.call(this);
   this.inputIndex = inputIndex;
  }
 });
 var ASPxClientUploadControlUploadingProgressChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(fileCount, currentFileName, currentFileContentLength,
   currentFileUploadedContentLength, currentFileProgress, totalContentLength, uploadedContentLength, progress) {
   this.constructor.prototype.constructor.call(this);
   this.fileCount = fileCount;
   this.currentFileName = currentFileName;
   this.currentFileContentLength = currentFileContentLength;
   this.currentFileUploadedContentLength = currentFileUploadedContentLength;
   this.currentFileProgress = currentFileProgress;
   this.totalContentLength = totalContentLength;
   this.uploadedContentLength = uploadedContentLength;
   this.progress = progress;
  }
 });
 var ASPxClientUploadControlValidationErrorOccurredEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(errorText, invalidFiles) {
   this.constructor.prototype.constructor.call(this);
   this.errorText = errorText;
   this.showAlert = true;
   this.validationSettings = null;
   this.invalidFiles = invalidFiles;
  }
 });
 var ASPxClientUploadControlValidationSettings = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(maxFileSize, maxFileCount, allowedFileExtensions, invalidFileNameCharacters) {
   this.constructor.prototype.constructor.call(this);
   this.maxFileSize = maxFileSize;
   this.maxFileCount = maxFileCount;
   this.allowedFileExtensions = allowedFileExtensions;
   this.invalidFileNameCharacters = invalidFileNameCharacters;
  }
 });
 var ASPxClientUploadControlInvalidFileInfo = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(fileName, fileSize, errorType) {
   this.constructor.prototype.constructor.call(this);
   this.fileName = fileName;
   this.fileSize = fileSize;
   this.errorType = errorType;
  }
 });
 var ASPxClientUploadControlValidationErrorTypeConsts = {
  MaxFileSizeExceeded: 1,
  NotAllowedFileExtension: 2,
  MaxFileCountExceeded: 3,
  FileNameContainsInvalidCharacter: 4
 };
 var ASPxClientUploadControlFile = ASPx.CreateClass(null, {
  constructor: function(name, size, sourceFileObject) {
   this.name = name;
   this.size = size;
   this.sourceFileObject = sourceFileObject;
  }
 });
 var ASPxClientUploadControlDropZoneEnterEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(dropZone) {
   this.constructor.prototype.constructor.call(this);
   this.dropZone = dropZone;
  }
 });
 var ASPxClientUploadControlDropZoneLeaveEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(dropZone) {
   this.constructor.prototype.constructor.call(this);
   this.dropZone = dropZone;
  }
 });
 var ASPxClientUploadControlDropZoneDropEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(dropZone) {
   this.constructor.prototype.constructor.call(this);
   this.dropZone = dropZone;
  }
 });
 var windowsFileNameRegExpTemplate = "^([a-zA-Z]\\:|\\\\\\\\[^\\/\\\\:*?\\\"<>|]+\\\\[^\\/\\\\:*?\\\"<>|]+)(\\\\[^\\/\\\\:*?\\\"<>|]+)+(\\.[^\\/\\\\:*?\\\"<>|]+)?$";
 var windowsRootDirectoryNameRegExpTemplate = "[a-zA-Z]\\:";
 ASPxClientUploadControl.IsValidWindowsFileName = function (fileName) {
  var windowsRootDirectoryNameRegExp = new RegExp(windowsRootDirectoryNameRegExpTemplate, "gi");
  var windowsFileNameRegExp = new RegExp(windowsFileNameRegExpTemplate, "gi");
  return (fileName == "" || windowsFileNameRegExp.test(fileName)) || (fileName.length == 3 && windowsRootDirectoryNameRegExp.test(fileName));
 };
 ASPxClientUploadControl.UploadManagerClass = ASPxLegacyUploadManager;
 ASPxClientUploadControl.IsDragAndDropAvailable = function() {
  return 'draggable' in document.createElement('span') && ASPxClientUploadControl.IsFileApiAvailable();
 };
 ASPxClientUploadControl.IsFileApiAvailable = function() {
  if(ASPxClientUploadControl.fileApiAvailable === undefined) {
   var input = document.createElement("input"),
    isBuggyAndroid = ASPx.Browser.AndroidDefaultBrowser && "webkitSlice" in window.File.prototype;
   ASPxClientUploadControl.fileApiAvailable = "multiple" in input && "File" in window && "FormData" in window;
   ASPxClientUploadControl.fileApiAvailable = ASPxClientUploadControl.fileApiAvailable && !isBuggyAndroid && ("slice" in window.File.prototype || 
    ASPx.Browser.WebKitFamily && "webkitSlice" in window.File.prototype ||   
    ASPx.Browser.NetscapeFamily && "mozSlice" in window.File.prototype);
  }
  return ASPxClientUploadControl.fileApiAvailable;
 };
 ASPxClientUploadControl.OnTooManyFilesError = function(name) {
  var uploader = ASPx.GetControlCollection().Get(name);
  if(uploader != null)
   uploader.ShowTooManyFilesError(); 
 };
 ASPx.SLOnLoad = function(name, index) {
  var uploader = ASPx.GetControlCollection().Get(name);
  if(uploader != null)
   uploader.OnPluginLoaded(index);
 };
 ASPx.SLOnError = function(name, index) {
  var uploader = ASPx.GetControlCollection().Get(name);
  if(uploader != null)
   uploader.OnPluginError(index);
 };
 ASPx.SLOnFileSelectionChanged = function(name, index) {
  var uploader = ASPx.GetControlCollection().Get(name);
  if(uploader != null)
   uploader.InvokeTextChangedInternal(index);
 };
 var ASPxClientUploadControlCollection = ASPx.CreateClass(ASPxClientControlCollection, {
  constructor: function () {
   this.constructor.prototype.constructor.call(this);
   this.dropZoneList = [];
   this.dropZoneRegistry = {};
   this.controlDropZonesRegistry = {};
   this.inlineZoneRegistry = {};
   this.anchorElements = [];
   this.anchorElementRegistry = {};
   this.zoneHandlersList = {};
   this.triggersSubscriptions = {};
   this.controlNameIdMap = {};
   this.controlNameLastId = 0;
   this.activeZoneId = null;
   this.dropEffect = "none";
   this.domHelper = new ASPxDOMHelper({ name: this.name });
   this.lastEventTimeStamp = 0;
   this.lastEventName = null;
   this.eventsInitialized = false;
   this.hasActiveDragFiles = false;
   this.disableDragAndDrop = false;
   this.dialogObservationActivated = false;
   this.dialogObservationHandler = null;
   this.preventDefaultDrag = false;
   this.wasIntermediateFocusEvents = false;
  },
  GetCollectionType: function(){
   return "Upload";
  },
  Remove: function(element) {
   this.unsubscribeControl(element.name);
   ASPxClientControlCollection.prototype.Remove.call(this, element);
  },
  RegisterDropZone: function(controlName, zoneId, isInline) {
   if(zoneId) {
    if(this.isRegistered(zoneId))
     this.unsubscribeDropZone(zoneId, controlName);
    this.dropZoneList.push(zoneId);
    this.dropZoneRegistry[zoneId] = controlName;
    this.ensureDropZoneRegistered(controlName, zoneId);
    if(isInline)
     this.inlineZoneRegistry[controlName] = zoneId;
    this.subscribeDropZone(zoneId, controlName);
   }
  },
  DeregisterDropZones: function(controlName, zoneIDs) {
   if(!(zoneIDs && zoneIDs.length)) return;
   ASPx.Data.ForEach(zoneIDs, function(zoneId) {
    this.unsubscribeDropZone(zoneId, controlName);
    var pos = this.controlDropZonesRegistry[controlName].indexOf(zoneId);
    if(pos > -1)
     this.controlDropZonesRegistry[controlName].splice(pos, 1);
   }.aspxBind(this));
  },
  ensureDropZoneRegistered: function(controlName, zoneId) {
   if(!this.controlDropZonesRegistry[controlName])
    this.controlDropZonesRegistry[controlName] = [];
   if(this.controlDropZonesRegistry[controlName].indexOf(zoneId) === -1)
    this.controlDropZonesRegistry[controlName].push(zoneId);
  },
  isRegistered: function(zoneId) {
   return this.dropZoneList.indexOf(zoneId) !== -1;
  },
  RegisterAnchorElement: function(controlName, anchor) {
   this.anchorElements.push(anchor.id);
   var entry = { controlName: controlName, handler: null };
   this.anchorElementRegistry[anchor.id] = entry;
   this.subscribeAnchorElement(anchor);
  },
  DeregisterAnchorElement: function(anchor) {
   if(anchor && anchor.id) {
    this.anchorElements.splice(this.anchorElements.indexOf(anchor.id), 1);
    var entry = this.anchorElementRegistry[anchor.id];
    delete this.anchorElementRegistry[anchor.id];
    ASPx.Evt.DetachEventFromElement(anchor, "dragleave", entry.handler);
   }
  },
  subscribeAnchorElement: function(anchor) {
   var entry = this.anchorElementRegistry[anchor.id],
    inlineZoneId = this.inlineZoneRegistry[entry.controlName];
   var handler = function(e) { 
    this.onDropZoneLeave(e, inlineZoneId);
   }.aspxBind(this);
   ASPx.Evt.AttachEventToElement(anchor, "dragleave", handler);
   entry.handler = handler;
  },
  subscribeDropZone: function(zoneId) {
   var dropZone = document.getElementById(zoneId),
    handlerIndex = zoneId,
    that = this;
   if(dropZone) {
    var dropHandler = function(e) {
     that.onDrop(e, zoneId);
    };
    var dragEnterHandler = function(e) {
     that.onDropZoneEnter(e, zoneId);
    };
    var dragLeaveHandler = function(e) {
     that.onDropZoneLeave(e, zoneId);
    };
    this.zoneHandlersList[handlerIndex] = {
     drop: dropHandler,
     dragenter: dragEnterHandler,
     dragleave: dragLeaveHandler
    };
    ASPx.Evt.AttachEventToElement(dropZone, "drop", this.zoneHandlersList[handlerIndex].drop);
    ASPx.Evt.AttachEventToElement(dropZone, "dragenter", this.zoneHandlersList[handlerIndex].dragenter);
    ASPx.Evt.AttachEventToElement(dropZone, "dragleave", this.zoneHandlersList[handlerIndex].dragleave);
   }
  },
  unsubscribeDropZone: function(zoneId) {
   var dropZone = document.getElementById(zoneId),
    handlerIndex = zoneId;
   if(dropZone) {
    ASPx.Evt.DetachEventFromElement(dropZone, "drop", this.zoneHandlersList[handlerIndex].drop);
    ASPx.Evt.DetachEventFromElement(dropZone, "dragleave", this.zoneHandlersList[handlerIndex].dragleave);
    this.dropZoneList.splice(this.dropZoneList.indexOf(zoneId), 1);
    delete this.zoneHandlersList[handlerIndex];
   }
  },
  setDropEffect: function(e, effect) {
   e.dataTransfer.dropEffect = effect;
  },
  isMouseOverElement: function(e, element) {
   if(!element)
    return false;
   var x = this.getElementAbsoluteX(element),
    w = element.offsetWidth,
    eventX = ASPx.Evt.GetEventX(e);
   if(eventX < x || eventX >= (x + w))
    return false;
   var y = this.getElementAbsoluteY(element),
    h = element.offsetHeight,
    eventY = ASPx.Evt.GetEventY(e);
   return (eventY >= y && eventY < (y + h));
  },
  getElementAbsoluteX: function(element) {
   if(ASPx.Browser.WebKitFamily)
    return Math.round(element.getBoundingClientRect().left + ASPx.GetDocumentScrollLeft());
   else
    return ASPx.GetAbsoluteX(element);
  },
  getElementAbsoluteY: function(element) {
   if(ASPx.Browser.WebKitFamily)
    return Math.round(element.getBoundingClientRect().top + ASPx.GetDocumentScrollTop());
   else
    return ASPx.GetAbsoluteY(element);
  },
  isActiveZoneChanged: function(e, zoneId) {
   var zoneChanged = this.activeZoneId === null || this.activeZoneId !== zoneId;
   if(this.activeZoneId !== null) {
    zoneChanged = this.isMouseLeftActiveZone(e);
   }
   return zoneChanged;
  },
  isMouseLeftActiveZone: function(e) {
   var activeZone = document.getElementById(this.activeZoneId);
   return !this.isMouseOverElement(e, activeZone);
  },
  isInstanceAlive: function(controlName) {
   var control = this.Get(controlName);
   return control && control.GetMainElement();
  },
  getElementUnderPointerFromList: function(e, list) {
   var ret = null;
   list = list.filter(function (id) {
    return document.getElementById(id) !== null;
   });
   for(var i = 0; i < list.length; i++) {
    var element = document.getElementById(list[i]);
    if(this.isMouseOverElement(e, element)) {
     ret = element;
     break;
    }
   }
   return ret;
  },
  OnDocumentMouseUp: function (e) {
   this.ForEachControl(function (control) {
    if(control.isControlInitialized())
     control.OnDocumentMouseUp();
   });
  },
  OnDocumentKeyDown: function(e) {
   this.ForEachControl(function(control) {
    if(control.isControlInitialized())
     control.OnDocumentKeyDown(e);
   });
  },
  OnDocumentKeyUp: function(e) {
   this.ForEachControl(function(control) {
    if(control.isControlInitialized())
     control.OnDocumentKeyUp(e);
   });
  },
  unsubscribeControl: function(controlName) {
   this.DeregisterDropZones(controlName, this.controlDropZonesRegistry[controlName]);
   delete this.controlDropZonesRegistry[controlName];
   this.detachTriggersFromControl(controlName);
  },
  proxyEvent: function(controlName, handler) {
   if(this.isInstanceAlive(controlName))
    handler.call(this);
   else
    this.unsubscribeControl(controlName);
  },
  proxyTriggerEvent: function(controlName, handler) {
   if(!this.hasActiveDragFiles)
    this.proxyEvent(controlName, handler);
  },
  OnDocumentDragEnter: function(e) {
   this.dropEffect = "";
   this.preventDefaultDrag = false;
   if(this.disableDragAndDrop) {
    this.preventDefaultDrag = true;
    this.dropEffect = "none";
   }
   else if(ASPxClientUploadControl.isValidDragAndDropEvent(e)) {
    var anchorElement = this.getElementUnderPointerFromList(e, this.anchorElements),
     zone,
     zoneId,
     controlName;
    if(anchorElement) {
     var entry = this.anchorElementRegistry[anchorElement.id];
     controlName = entry.controlName;
     zoneId = this.inlineZoneRegistry[controlName];
    }
    else {
     zone = this.getElementUnderPointerFromList(e, this.dropZoneList);
     if(zone) {
      zoneId = zone.id;
      controlName = this.dropZoneRegistry[zoneId];
     }
    }
    this.preventDefaultDrag = true;
    this.dropEffect = "copy";
    if(controlName && zoneId)
     this.onDragEnter(e, controlName, zoneId);
    else
     this.dropEffect = "none";
   }
  },
  onDragEnter: function(e, controlName, zoneId) {
   this.lastEventName = "dragenter";
   if(this.isActiveZoneChanged(e, zoneId)) {
    if(this.activeZoneId)
     this.onDropZoneLeave(e, this.activeZoneId);
    if(this.activeZoneId !== zoneId) {
     this.proxyEvent(controlName, function() {
      this.passDragEnterToControl(e, controlName, zoneId);
     });
    }
   }
  },
  passDragEnterToControl: function(e, controlName, zoneId) {
   var control = this.Get(controlName);
   if(!control.isInCallback) {
    control.OnDragEnter([e, zoneId]);
    this.activeZoneId = zoneId;
    this.dropEffect = "copy";
   }
   else
    this.dropEffect = "none";
  },
  onDropZoneEnter: function(e, zoneId) {
   this.hasActiveDragFiles = true;
  },
  onDropZoneLeave: function(e, zoneId) {
   var zone = document.getElementById(zoneId),
    controlName = this.dropZoneRegistry[zoneId];
   this.hasActiveDragFiles = false;
   if(this.shouldRaiseDragLeave(e, zoneId, zone)) {
    this.proxyEvent(controlName, function() {
     var control = this.Get(controlName);
     control.OnDragLeave([e, zoneId]);
    });
    this.activeZoneId = null;
    this.dropEffect = "none";
   }
   ASPx.Evt.PreventEvent(e);
  },
  shouldRaiseDragLeave: function(e, zoneId, zone) {
   return this.activeZoneId === zoneId && (this.isActiveZoneLeft(e, zone) || this.dragCancelledByEscKey());
  },
  isActiveZoneLeft: function(e, zone) {
   return !this.isMouseOverElement(e, zone);
  },
  dragCancelledByEscKey: function() {
   return this.lastEventName !== "dragenter";
  },
  onDrop: function(e, zoneId) {
   var controlName = this.dropZoneRegistry[zoneId];
   this.hasActiveDragFiles = false;
   ASPx.Evt.PreventEvent(e);
   if(ASPxClientUploadControl.isValidDragAndDropEvent(e) && this.lastEventTimeStamp !== e.timeStamp) {
    this.proxyEvent(controlName, function() {
     var control = this.Get(controlName);
     control.OnDrop([e, zoneId]);
    });
    this.activeZoneId = null;
    this.lastEventTimeStamp = e.timeStamp;
   }
  },
  OnDocumentDragOver: function(e) {
   this.lastEventName = "dragover";
   if(this.dropEffect)
    this.setDropEffect(e, this.dropEffect);
   if(this.preventDefaultDrag)
    ASPx.Evt.PreventEvent(e);
  },
  initializeEvents: function() {
   var that = this;
   if(!this.eventsInitialized) {
    ASPx.Evt.AttachEventToDocument("dragenter", function(e) {
     that.OnDocumentDragEnter(e);
    });
    ASPx.Evt.AttachEventToDocument("dragover", function(e) {
     that.OnDocumentDragOver(e);
    });
    this.eventsInitialized = true;
   }
  },
  SubscribeDialogTriggers: function(context, controlName, dialogTriggersList, triggerHandlers, attach) {
   var config = {
    controlName: controlName,
    dialogTriggersList: dialogTriggersList,
    triggerHandlers: triggerHandlers,
    context: context
   };
   this.detachTriggersFromControl(config.controlName);
   if(attach)
    this.attachTriggersToControl(config);
  },
  attachTriggersToControl: function(config) {
   this.triggersSubscriptions[config.controlName] = {};
   ASPx.Data.ForEach(config.dialogTriggersList, function(trigger) {
    this.subscribeTrigger(config.controlName, trigger, config.triggerHandlers, config.context);
   }.aspxBind(this));
  },
  detachTriggersFromControl: function(controlName) {
   var controlSubscriptions = this.triggersSubscriptions[controlName],
    triggerIDs = ASPx.GetObjectKeys(controlSubscriptions);
   ASPx.Data.ForEach(triggerIDs, function(triggerID) {
    var triggerSubscriptions = controlSubscriptions[triggerID];
    if(triggerSubscriptions) {
     var eventNames = ASPx.GetObjectKeys(triggerSubscriptions);
     ASPx.Data.ForEach(eventNames, function(eventName) {
      ASPx.Data.ForEach(triggerSubscriptions[eventName], function(subscription) {
       ASPx.Evt.DetachEventFromElement(subscription.target, eventName, subscription.handler);
      });
      triggerSubscriptions[eventName] = {};
     });
    }
   });
   delete this.triggersSubscriptions[controlName];
  },
  subscribeTrigger: function(controlName, trigger, triggerHandlers, context) {
   var triggerSubscriptions =  this.triggersSubscriptions[controlName][trigger.id] = {},
    eventNames = ASPx.GetObjectKeys(triggerHandlers),
    that = this;
   ASPx.Data.ForEach(eventNames, function(eventName) {
    triggerSubscriptions[eventName] = triggerSubscriptions[eventName] || [];
    ASPx.Data.ForEach(triggerHandlers[eventName], function(config) {
     var handler = function(e) {
      that.proxyTriggerEvent(controlName, function() {
       config.handler.call(context, e, trigger);
      });
     };
     triggerSubscriptions[eventName].push({
      handler: handler,
      target: config.target || trigger
     });
    });
    ASPx.Data.ForEach(triggerSubscriptions[eventName], function(subscription) {
     ASPx.Evt.AttachEventToElement(subscription.target, eventName, subscription.handler);
    });
   }.aspxBind(this));
  },
  onFileInputClick: function() {
   this.disableDragAndDrop = true;
   this.wasIntermediateFocusEvents = false;
   this.startDialogObservation();
  },
  onFileInputGotFocus: function() {
   this.disableDragAndDrop = false;
   this.wasIntermediateFocusEvents = true;
  },
  onFileInputChange: function() {
   this.disableDragAndDrop = false;
   this.stopDialogObservation();
   this.wasIntermediateFocusEvents = true;
  },
  onFileInputLostFocus: function() {
   this.enableDragAndDropAfterDialogClosed();
   this.wasIntermediateFocusEvents = true;
  },
  onDocumentMouseMove: function(evt) {
   this.wasIntermediateFocusEvents = true;
   this.enableDragAndDropAfterDialogClosed();
  },
  enableDragAndDropAfterDialogClosed: function() {
   if(this.dialogObservationActivated && this.wasIntermediateFocusEvents) {
    this.disableDragAndDrop = false;
    this.stopDialogObservation();
   }
  },
  startDialogObservation: function() {
   if(this.dialogObservationActivated) return;
   this.dialogObservationHandler = this.onDocumentMouseMove.aspxBind(this);
   ASPx.Evt.AttachEventToDocument("mousemove", this.dialogObservationHandler);
   this.dialogObservationActivated = true;
  },
  stopDialogObservation: function() {
   if(!this.dialogObservationActivated) return;
   ASPx.Evt.DetachEventFromDocument("mousemove", this.dialogObservationHandler);
   this.dialogObservationHandler = null;
   this.dialogObservationActivated = false;
  },
  getIdForControlName: function(controlName) {
   var id = this.controlNameIdMap[controlName];
   if(!id)
    id = this.controlNameIdMap[controlName] = ++this.controlNameLastId;
   return id;
  }
 });
 var uploadControlCollection = null;
 function aspxGetUploadControlCollection() {
  if(uploadControlCollection == null)
   uploadControlCollection = new ASPxClientUploadControlCollection();
  return uploadControlCollection;
 }
 ASPx.Evt.AttachEventToDocument("mouseup", function(e) {
  aspxGetUploadControlCollection().OnDocumentMouseUp(e);
 });
 ASPx.Evt.AttachEventToDocument("keydown", function(e) {
  aspxGetUploadControlCollection().OnDocumentKeyDown(e);
 });
 ASPx.Evt.AttachEventToDocument("keyup", function(e) {
  aspxGetUploadControlCollection().OnDocumentKeyUp(e);
 });
 var ASPxFileListChangedInternalArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(fileInfos, inputIndex, fileCountChanged) {
   this.fileInfos = fileInfos;
   this.inputIndex = inputIndex;
   this.fileCountChanged = fileCountChanged;
  }
 });
 var ASPxViewStateChangedInternalArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(fileInfos, inputIndex) {
   this.constructor.prototype.constructor.call(this);
   this.fileInfos = fileInfos;
   this.inputIndex = inputIndex;
  }
 });
 ASPx.IsUploadSubmitRequest = function(form) {
  if(!form || typeof form.action !== "string")
   return false;
  var parameters = [Constants.QueryParamNames.UPLOADING_CALLBACK, Constants.QueryParamNames.HELPER_UPLOADING_CALLBACK];
  for(var i = 0; i < parameters.length; i++)
   if(form.action.indexOf(parameters[i]) > -1) 
    return true;     
  return false;
 };
 ASPx.ASPxViewManager = ASPxViewManager;
 ASPx.ASPxHTML5InputView = ASPxHTML5InputView;
 ASPx.ASPxStandardInputView = ASPxStandardInputView;
 ASPx.ASPxButtonView = ASPxButtonView;
 ASPx.ASPxDropZoneView = ASPxDropZoneView;
 ASPx.ASPxFileListView = ASPxFileListView;
 ASPx.ASPxFileListItem = ASPxFileListItem;
 ASPx.ASPxInvisibleFileInputDecorator = ASPxInvisibleFileInputDecorator;
 ASPx.ASPxErrorView = ASPxErrorView;
 ASPx.ASPxProgressPanelView = ASPxProgressPanelView;
 ASPx.GetUploadControlCollection = aspxGetUploadControlCollection;
 window.ASPxClientUploadControl = ASPxClientUploadControl;
 window.ASPxClientUploadControlCollection = ASPxClientUploadControlCollection;
 window.ASPxClientUploadControlFilesUploadStartEventArgs = ASPxClientUploadControlFilesUploadStartEventArgs;
 window.ASPxClientUploadControlFileUploadCompleteEventArgs = ASPxClientUploadControlFileUploadCompleteEventArgs;
 window.ASPxClientUploadControlFilesUploadCompleteEventArgs = ASPxClientUploadControlFilesUploadCompleteEventArgs;
 window.ASPxClientUploadControlTextChangedEventArgs = ASPxClientUploadControlTextChangedEventArgs;
 window.ASPxClientUploadControlUploadingProgressChangedEventArgs = ASPxClientUploadControlUploadingProgressChangedEventArgs;
 window.ASPxClientUploadControlValidationErrorOccurredEventArgs = ASPxClientUploadControlValidationErrorOccurredEventArgs;
 window.ASPxClientUploadControlValidationSettings = ASPxClientUploadControlValidationSettings;
 window.ASPxClientUploadControlInvalidFileInfo = ASPxClientUploadControlInvalidFileInfo;
 window.ASPxClientUploadControlValidationErrorTypeConsts = ASPxClientUploadControlValidationErrorTypeConsts;
 window.ASPxClientUploadControlFile = ASPxClientUploadControlFile;
})();

(function() {
var FileManagerConsts = {};
FileManagerConsts.SplitterPostfix = "_Splitter";
FileManagerConsts.ItemsPostfix = "_Items";
FileManagerConsts.ToolbarPostfix = "_Toolbar";
FileManagerConsts.ContextMenuPostfix = "_ContextMenu";
FileManagerConsts.FoldersPostfix = "_Folders";
FileManagerConsts.BreadCrumbsPostfix = "_BreadCrumbs";
FileManagerConsts.GridPostfix = "_FilesGridView";
FileManagerConsts.UploadPostfix = "_Upload";
FileManagerConsts.UploadButtonPostfix = "_UploadButton";
FileManagerConsts.RenameFileInputPostfix = "_RFI";
FileManagerConsts.FolderBrowserPopupPostfix = "_FolderBrowserPopup";
FileManagerConsts.UploadProgressPopupPostfix = "_UploadProgressPopup";
FileManagerConsts.BreadCrumbsPopupPostfix = "_BreadCrumbsPopup";
FileManagerConsts.BreadCrumbsFolderUpButtonPostfix = "_FUB";
FileManagerConsts.BreadCrumbsHiddenItemsButtonPostfix = "_HIB";
FileManagerConsts.BreadCrumbsCustomFilterElementPostfix = "_CFE"; 
FileManagerConsts.ItemPostfix = "_I";
FileManagerConsts.SeparatorPostfix = "S";
FileManagerConsts.ImagePostfix = "I";
FileManagerConsts.CheckboxPostfix = "_CHK";
FileManagerConsts.FolderBrowserFoldersContainerPostfix = "_FC";
FileManagerConsts.FolderBrowserFolders = "_FolderBrowserFolders";
FileManagerConsts.FolderBrowserDialogOkButtonPostfix = "_OkB";
FileManagerConsts.FolderBrowserDialogCancelButtonPostfix = "_CaB";
FileManagerConsts.UploadProgressBarPostfix = "_PB";
FileManagerConsts.UploadPopupCancelButtonPostfix = "_CB";
FileManagerConsts.ItemsPaneSplitterName = "ContentPane2";
FileManagerConsts.CreateHelperFolderPostfix = "CHF";
FileManagerConsts.VirtualScrollingEmptyPageElementPostifx = "_EP";
FileManagerConsts.ToolbarStandardButtonPrefix = "fmtsi-";
FileManagerConsts.ToolbarPathBoxClassName = "dxfm-path";
FileManagerConsts.ToolbarFilterBoxClassName = "dxfm-filter";
FileManagerConsts.ToolbarExpandFolderContainerHiddenClassName = "dxfm-efcHidden";
FileManagerConsts.FileClassName = "dxfm-file";
FileManagerConsts.FileContainerClassName = "dxfm-fileContainer";
FileManagerConsts.TouchContextMenuClassName = "dxfm-touchCtxMenu";
FileManagerConsts.FolderContentContainerClassName = "dxtv-nd";
FileManagerConsts.UploadControlDisableClassName = "dxfm-uploadDisable";
FileManagerConsts.MultiSelectClassName = "dxfm-multiSelect";
FileManagerConsts.ItemMaskClassName = "dxfm-itemMask";
FileManagerConsts.BreadCrumbsContainerClassName = "dxfm-bcContainer";
FileManagerConsts.BreadCrumbsLineSeparatorClassName = "dxfm-bcLineSeparator";
FileManagerConsts.BreadCrumbsButtonClassName = "dxfm-bcButton";
FileManagerConsts.BreadCrumbsLastItemClassName = "dxfm-bcLastItem";
FileManagerConsts.BreadCrumbsRootStateClassName = "dxfm-bcRoot";
FileManagerConsts.ThumbnailCellClassName = "dxfm-fileThumb";
FileManagerConsts.GridColumnTitleCellClassName = "dxfm-fileNameCell";
FileManagerConsts.GridColumnTitleClassName = "dxfm-fileName";
FileManagerConsts.GridAdaptiveHiddenClassName = "dxgvAH";
FileManagerConsts.ShowAllFileAreaCheckBoxesClassName = "dxfm-faShowCheckBoxes";
FileManagerConsts.CreateHelperElementClassName = "dxfm-createHelper";
FileManagerConsts.CreateHelperGridCommandCellClassName = "dxfm-createHelperGridCommandCell";
FileManagerConsts.ToolbarWrapperClassName = "dxfm-tbwrp";
FileManagerConsts.TextBoxClassName = "dxeTextBoxSys";
FileManagerConsts.FilterViewClassName = "dxfm-filterView";
FileManagerConsts.FilterViewRowClassName = "dxfm-filterViewRow";
FileManagerConsts.FilterViewImageCellClassName = "dxfm-filterViewImageCell";
FileManagerConsts.FilterViewFileNameCellClassName = "dxfm-filterViewFileNameCell";
FileManagerConsts.FilterViewDateCellClassName = "dxfm-filterViewDateCell";
FileManagerConsts.FilterViewSizeCellClassName = "dxfm-filterViewSizeCell";
FileManagerConsts.FilterViewCheckBoxCellClassName = "dxfm-filterViewCheckBoxCell";
FileManagerConsts.FilterViewTransparentTextClassName = "dxfm-fvtt";
FileManagerConsts.FilterViewHiddenColumnClassName = "dxfm-fvhc";
FileManagerConsts.CallbackArgumentSeparator = "|";
FileManagerConsts.CallbackLinkedArgumentSeparator = "||ls||";
FileManagerConsts.PathSeparator = "\\";
FileManagerConsts.ItemPropertyValueSeparator = "::";
FileManagerConsts.ClientStatePrefix = "DXFORMAT^^";
FileManagerConsts.ParentFolderItemName = "..";
FileManagerConsts.CreateHelperItemName = "aspxFMCreateHelperFolder";
FileManagerConsts.BreadCrumbsHiddenItemsButtonText = "...";
FileManagerConsts.RenameInputAdditionalWidth = 20;
FileManagerConsts.DefaultRenameInputWidth = 150;
FileManagerConsts.DefaultFilterViewThumbnailSize = 48;
FileManagerConsts.UpperBoundaryAdditionalOffset = 1;
FileManagerConsts.StateField = {
 CurrentPath: "currentPath",
 CurrentIdPath: "currentIdPath",
 ItemFilter: "filter",
 CustomFilter: "filter.custFilter",
 CustomFilterBreadcrumbs: "filter.custFilterBreadcrumbs",   
 FilterBoxText: "filter.filterBoxText",
 FilterTextCnagedOnServer: "filter.textCnangedOnServer",
 FilterView: "filterView",
 ItemSelected: "item.selected",
 ItemFocused: "item.focused",
 SplitterState: "splitter",
 IsFolderNodeExpanded: "isFolderNodeExpanded",
 UploadState: "upload",
 VirtScrollItemIndexFieldName: "virtScrollItemIndex",
 VirtScrollPageItemsCountFieldName: "virtScrollPageItemsCount"
};
FileManagerConsts.ToolbarName = {
 Delete: "Delete",
 Move: "Move",
 Refresh: "Refresh",
 Rename: "Rename",
 Create: "Create",
 Download: "Download",
 Upload: "Upload",
 Copy: "Copy",
 Path: "Path",
 Filter: "Filter",
 ExpandFolderContainer: "ExpandFolderContainer"
};
FileManagerConsts.SelectedArea = {
 Folders: 0,
 Files: 1,
 None: 2
};
FileManagerConsts.SelectedAreaNames = {
 0: "Folders",
 1: "Files",
 2: "None"
};
FileManagerConsts.FileAreaItemTypes = {
 File: "File",
 Folder: "Folder",
 ParentFolder: "ParentFolder",
 CreateHelperFolder: "aspxFMCreateHelperFolder"
};
FileManagerConsts.Rights = {
 Default: 0,
 Allow: 1,
 Deny: 2
};
FileManagerConsts.ViewMode = {
 Thumbnail: 0,
 Grid: 1
};
FileManagerConsts.FilterBoxMode = {
 CurrentFolder: 0,
 Subfolders: 1
};
FileManagerConsts.FilterFileListViewMode = {
 Auto: 0,
 FilterView: 1,
 Standard: 2
};
FileManagerConsts.ModifierKey = {
 None: 0,
 Shift: 1,
 Ctrl: 2,
 Meta: 3
};
FileManagerConsts.IdValuePrefix = {
 AutoId: "a:",
 OriginalId: "o:"
};
FileManagerConsts.Templates = {};
FileManagerConsts.Templates.Item =
 "<div id=\"{{itemId}}\">" +
  "<div>" +
   "{{fileImage}}" +
   "<br/>" +
   "<div class=\"dxfm-itemNameContainer\">{{fileName}}</div>" +
  "</div>" +
 "</div>";
FileManagerConsts.Templates.FilterViewItem =
 "<div id=\"{{itemId}}\" class=\"" + FileManagerConsts.FilterViewRowClassName + "\">" +
  "<div class=\"" + FileManagerConsts.FilterViewImageCellClassName + "\">" +
   "{{fileImage}}" +
  "</div>" +
  "<div class=\"" + FileManagerConsts.FilterViewFileNameCellClassName +"\">"+
   "<div>{{fileName}}</div>" +
   "<div class=\"" + FileManagerConsts.FilterViewTransparentTextClassName +"\">{{fileLocation}}</div>" +
  "</div>" +  
  "<div class=\"" + FileManagerConsts.FilterViewDateCellClassName + "\"> " +
   "<span class=\"" + FileManagerConsts.FilterViewTransparentTextClassName +"\">{{fileDateCaption}}: </span> {{fileDate}}" +
  "</div>" +
  "<div class=\"" + FileManagerConsts.FilterViewSizeCellClassName + "\"> " +
   "<span class=\"" + FileManagerConsts.FilterViewTransparentTextClassName +"\">{{fileSizeCaption}}: </span>{{fileSize}}" +
  "</div>" +
 "</div>";
FileManagerConsts.Templates.PageIndent = "<div style='height: 0px; padding: 0; margin: 0; border: 0px none; clear: both;'></div>";
FileManagerConsts.Templates.FilterViewPageIndent = 
 "<div class=\"" + FileManagerConsts.FilterViewRowClassName + "\" style='height: 0px; padding: 0; margin: 0; border: 0px none; clear: both;'>" +
  "<div class=\"" + FileManagerConsts.FilterViewImageCellClassName + "\"></div>" + 
  "<div class=\"" + FileManagerConsts.FilterViewFileNameCellClassName +"\"></div>" +  
  "<div class=\"" + FileManagerConsts.FilterViewDateCellClassName + "\"></div>" +
  "<div class=\"" + FileManagerConsts.FilterViewSizeCellClassName + "\"></div>" +
 "</div>";
FileManagerConsts.Templates.EmptyPageElement = "<div id='{{id}}' class='dxfm-epe' style='height: {{height}}'></div>";
FileManagerConsts.Templates.HighlightedText = "{{textStart}}<span class=\"{{highlightCssClass}}\">{{textMiddle}}</span>{{textEnd}}";
var ASPxClientFileManager = ASPx.CreateClass(ASPxClientControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.styleSheet = ASPx.GetCurrentStyleSheet();
  this.elements = this.CreateElementsHelper();
  this.filterBox = new ASPxClientFileManager.FilterBoxHelper(this);
  this.tree = this.CreateTreeViewHelper();
  this.filterView = new FilterViewHelper(this);
  this.items = {};
  this.itemElementsIds = {};
  this.itemThumbnailHeight = 0;
  this.itemThumbnailWidth = 0;
  this.itemThumbnailMarginTop = 0;
  this.gridScrollHeight = 0;
  this.noThumbnailImage = "";
  this.customThumbnails = [];
  this.hasInitialState = undefined;
  this.allowUpload = true;
  this.uploadText = "";
  this.cancelUploadText = "";
  this.allowUploadToCurrentFolder = false;
  this.uploadErrorText = "";
  this.uploadSessionInfo = null;
  this.showPath = true;
  this.showAppRelativePath = false;
  this.allowMultiSelect = false;
  this.focusedItem = null;
  this.allowRename = false;
  this.allowMove = false;
  this.allowDelete = false;
  this.allowCreate = false;
  this.renameMode = false;
  this.createMode = false;
  this.deleteConfirmText = "";
  this.downloadError = null;
  this.folderDialogCommand = null;
  this.lockLoadingDiv = false;
  this.filterDelay = 1200;
  this.filterBoxMode = FileManagerConsts.FilterBoxMode.TopFolderOnly;
  this.filterFileListViewMode = FileManagerConsts.FilterFileListViewMode.Auto;
  this.folderRights = {};
  this.filesRules = [];
  this.processOpenedEventOnServer = false;
  this.viewMode = FileManagerConsts.ViewMode.Thumbnail;
  this.folderExpandingNode = null;
  this.hideFoldersWindowLimit = 0;
  this.toolbarInitialized = false;
  this.toolbarLastWidth = 0;
  this.contextMenuEvt = null;
  this.virtScroll = {
   itemIndex: 0,
   itemsCount: 0,
   pageSize: 0,
   pageCount: 0,
   pageItemsCount: 0,
   startPageScrollPos: null,
   lastPageScrollPos: null,
   lastPageIndexOffset: 0,
   timerId: -1,
   timeout: 10,
   jumpTimerId: -1,
   nearJumpTimeout: 100,
   farJumpTimeout: 500,
   selectedItems: null,
   inCallback: false
  };
  this.apiCommandCallback = null;
  this.apiCommandItems = null;
  this.SelectedFileChanged = new ASPxClientEvent();
  this.SelectedFileOpened = new ASPxClientEvent();
  this.FocusedItemChanged = new ASPxClientEvent();
  this.SelectionChanged = new ASPxClientEvent();
  this.CurrentFolderChanged = new ASPxClientEvent();
  this.FolderCreating = new ASPxClientEvent();
  this.FolderCreated = new ASPxClientEvent();
  this.ItemRenaming = new ASPxClientEvent();
  this.ItemRenamed = new ASPxClientEvent();
  this.ItemDeleting = new ASPxClientEvent();
  this.ItemDeleted = new ASPxClientEvent();
  this.ItemsDeleted = new ASPxClientEvent();
  this.ItemMoving = new ASPxClientEvent();
  this.ItemMoved = new ASPxClientEvent();
  this.ItemsMoved = new ASPxClientEvent();
  this.ItemCopying = new ASPxClientEvent();
  this.ItemCopied = new ASPxClientEvent();
  this.ItemsCopied = new ASPxClientEvent();
  this.ErrorOccurred = new ASPxClientEvent();
  this.ErrorAlertDisplaying = new ASPxClientEvent();
  this.CustomCommand = new ASPxClientEvent();
  this.ToolbarUpdating = new ASPxClientEvent();
  this.HighlightItemTemplate = new ASPxClientEvent();
  this.FileUploading = new ASPxClientEvent();
  this.FilesUploading = new ASPxClientEvent();
  this.FileUploaded = new ASPxClientEvent();
  this.FilesUploaded = new ASPxClientEvent();
  this.FileUploadValidationErrorOccurred = new ASPxClientEvent();
  this.FileDownloading = new ASPxClientEvent();
 },
 CreateElementsHelper: function() {
  return new ASPxClientFileManager.ElementsHelper(this);
 },
 CreateTreeViewHelper: function() {
  return new TreeViewHelper(this);
 },
 SetData: function(data){
  if(data.customThumbnails)
   this.customThumbnails = data.customThumbnails;
  if(data.selectedItems)
   this.selectedItems = data.selectedItems;
  if(data.styles)
   this.SetStyles(data.styles);
  if(data.virtScrollConfig)
   this.SetProperties(data.virtScrollConfig, this.virtScroll);
  if(data.itemsInfo) {
   if(data.itemsInfo.clearItemsBeforeCreate)
    this.ClearItems(true);
   this.CreateItems(data.itemsInfo.items);
  }
  if(data.fileRules)
   this.UpdateFilesRules(data.fileRules);
  if(data.createBreadCrumbs)
   this.createBreadCrumbs();
  if(data.folderRights)
   this.UpdateFolderRights(data.folderRights);
  if(data.commandResult)
   this.ProcessCommandResult(data.commandResult);
 },
 Initialize: function() {
  ASPxClientControl.prototype.Initialize.call(this);
  this.selectedArea = this.foldersHidden ? FileManagerConsts.SelectedArea.Files : FileManagerConsts.SelectedArea.Folders;
  var splitter = this.GetSplitter();
  if(splitter)
   splitter.controlOwner = this;
  this.InitializeKbdHelper();
  if(this.allowUpload && this.enabled)
   this.InitializeUploadControl();
  this.InitializeFoldersTreeView();
  if(this.showPath && !this.showAppRelativePath)
   this.UpdatePath();
  if(!this.foldersHidden)
   this.tree.saveSelectedNodeFromView();
  if(this.enabled) {
   this.initializeContextMenu();
   this.InitializeEventHandlers();
   this.SetActiveArea(FileManagerConsts.SelectedArea.None);
  }
  if(this.breadCrumbsEnabled)
   this.breadCrumbs.refresh();
  this.filterBox.Initialize();
 },
 AfterInitialize: function() {
  ASPxClientControl.prototype.AfterInitialize.call(this);
  this.SetSplitterUploadPaneSize();
  var isPostBack = this.autoPostBack && this.checkHasInitialState();
  if(!isPostBack)
   this.setSplitterFolderContainerPaneScroll();
  if(this.isDetailsViewMode())
   this.InitializeFilesGridView();
  else
   this.ensureDelayedApplyState();
  if(this.allowMove)
   this.UpdateTollbarStandardItem(FileManagerConsts.ToolbarName.Move, this.IsMoveAvailable());
  if(this.allowCopy)
   this.UpdateTollbarStandardItem(FileManagerConsts.ToolbarName.Copy, this.IsCopyAvailable());
  if(this.inCommandProcessing)
   this.EndCommandProcessing();
  if(this.selectedItems) {
   this.selectItems(this.selectedItems, !isPostBack);
   this.selectedItems = null;
  }
  this.KeepClientState();
  if(this.downloadError)
   this.showError(ASPxClientFileManagerCommandConsts.Download, this.downloadError.editErrorText, this.downloadError.editErrorCode.toString());
 },
 SetSplitterUploadPaneSize: function() {
  if(!this.allowUpload) return;
  this.SetSplitterPaneSizeByContentControl("UploadPanelPane", this.GetUploadControl());
 },
 SetSplitterPaneSizeByContentControl: function(name, control) {
  if(!control)
   return;
  var pane = this.GetSplitter().GetPaneByName(name),
   paneElement = pane.GetElement(),
   mainElement = control.GetMainElement();
  pane.SetSize(mainElement.offsetHeight + ASPx.GetTopBottomMargins(mainElement) + ASPx.GetTopBottomBordersAndPaddingsSummaryValue(paneElement.firstChild));
 },
 setSplitterFolderContainerPaneScroll: function() {
  if(!this.foldersHidden)
   this.tree.scrollToSelectedNode();
 },
 InitializeFoldersTreeView: function() {
  var treeView = this.GetTreeView();
  if(treeView)
   treeView.InitFileManagerCallbacks(this, false);
  this.foldersHidden = !treeView;
 },
 InitializeFilesGridView: function() {
  var gridView = this.GetFilesGridView();
  gridView.fileManager = this;
  this.AdjustGridViewSize();
  this.ensureGridViewItems();
  gridView.mainElement.className += " " + this.styles.rowSelectionActiveCssClass;
  if(this.accessibilityCompliant && !this.allowMultiSelect) {
   ASPx.Evt.AttachEventToElement(gridView.GetMainElement(), "focus", function() {
    window.setTimeout(this.onItemsAreaFocus.bind(this), 100);
   }.bind(this));
  }
 },
 InitializeUploadControl: function() {
  var uc = this.GetUploadControl(),
   filesPaneSplitter = this.GetSplitter().GetPaneByName(FileManagerConsts.ItemsPaneSplitterName),
   filesPaneElement = filesPaneSplitter && filesPaneSplitter.GetElement();
  uc.fileManager = this;
  this.UpdateUploadPanelVisibility();
  if(this.uploadErrorText)
   this.showError(ASPxClientFileManagerCommandConsts.Upload, this.uploadErrorText);
  if(filesPaneElement)
   uc.viewManager.setInlineDropZoneAnchorElementID(filesPaneElement.id);
 },
 InitializeKbdHelper: function() {
  this.kbdHelper = new FileManagerKbdHelper(this);
  this.kbdHelper.Init();
  ASPx.KbdHelper.RegisterAccessKey(this);
  this.updateFocusInputVisibility();
 },
 InitializeEventHandlers: function() {
  var _this = this;
  this.initializeFilesAreaEventHandlers();
  if(this.enableContextMenu) {
   var container = this.elements.GetItemsPaneContainer();
   ASPx.Evt.AttachContextMenuToElement(container, this.OnFilesAreaRMBClick.bind(this));
  }
  if(!this.foldersHidden) {
   var foldersContainer = this.elements.GetFoldersContainer();
   ASPx.Evt.AttachEventToElement(foldersContainer, "mousedown", function(evt) { _this.OnFoldersContainerClick(evt); });
   if(this.enableContextMenu)
    ASPx.Evt.AttachEventToElement(foldersContainer, "contextmenu", function(evt) { _this.OnFoldersContainerRMBClick(evt); });
   ASPx.Evt.AttachEventToElement(foldersContainer, "keydown", function(evt) {
    if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Enter && !_this.IsEditMode())
     _this.SetActiveArea(FileManagerConsts.SelectedArea.Folders);
   });
  }
  ASPx.Evt.AttachEventToDocument("click", function(evt) { _this.OnDocumentClick(evt); });
  if(this.allowRename || this.GetCreateHelperItem())
   this.PrepareRenameInput();
  if(this.allowMove || this.allowCopy)
   this.PrepareFolderBrowserDialog();
  if(this.allowUpload) {
   if(this.hideUploadPanel)
    ASPx.Evt.AttachEventToElement(this.elements.GetProgressPopupCancelButtonElement(), "click", function() { _this.GetUploadControl().Cancel(); });
   else
    ASPx.Evt.AttachEventToElement(this.elements.GetUploadButtonElement(), "click", function() { _this.GetUploadControl().OnButtonClick(); });
  }
  if(this.accessibilityCompliant) {
   ASPx.Evt.AttachEventToElement(this.elements.GetFocusInput(), "focus", this.onItemsAreaFocus.bind(this));
  }
 },
 initializeFilesAreaEventHandlers: function() {
  var itemsContainer = this.elements.GetItemsPaneContainer();
  if(itemsContainer["dxmousedown"])
   ASPxClientUtils.DetachEventFromElement(itemsContainer, "mousedown", itemsContainer["dxmousedown"]);
  if(itemsContainer["dxscroll"])
   ASPxClientUtils.DetachEventFromElement(itemsContainer, "scroll", itemsContainer["dxscroll"]);
  itemsContainer["dxmousedown"] = null;
  itemsContainer["dxscroll"] = null;
  if(this.isDetailsViewMode()) {
   this.InitializeGridViewEventHandlers();
  } else {
   var _this = this;
   itemsContainer["dxmousedown"] = function(evt) { _this.OnFilesContainerClick(evt); };
   ASPxClientUtils.AttachEventToElement(itemsContainer, "mousedown", itemsContainer["dxmousedown"]);
   if(this.isThumbnailModeVirtScrollEnabled()) {
    itemsContainer["dxscroll"] = function(evt) { _this.onItemsContainerScroll(evt); };
    ASPxClientUtils.AttachEventToElement(itemsContainer, "scroll", itemsContainer["dxscroll"]);
   }
  }
 },
 InitializeGridViewEventHandlers: function() {
  if(!this.isDetailsViewMode())
   return;
  var grid = this.GetFilesGridView();
  grid.FocusedRowChanged.AddHandler(this.onFilesGridViewFocusedRowChanged.bind(this));
  grid.SelectionChanged.AddHandler(this.onFilesGridViewSelectionChanged.bind(this));
  grid.RowDblClick.AddHandler(this.onFilesGridViewRowDblClick.bind(this));
  grid.ColumnResized.AddHandler(this.onFilesGridViewColumnResized.bind(this));
  ASPx.Evt.AttachEventToElement(grid.GetMainElement(), "click", function(evt) {
   this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
  }.aspxBind(this));
 },
 PrepareRenameInput: function() {
  var _this = this;
  var input = this.elements.GetRenameInputElement();
  ASPx.Evt.AttachEventToElement(input, "keydown", function(evt) {
   _this.OnRenameInputKeyDown(evt);
   if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Enter)
    return ASPx.Evt.PreventEventAndBubble(evt);
  });
  ASPx.Evt.AttachEventToElement(input, "blur", function() { _this.DoRename(); });
  ASPx.Evt.AttachEventToElement(input, "keypress", function(evt) { 
   if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Enter)
    return ASPx.Evt.PreventEventAndBubble(evt);
  });
 },
 PrepareFolderBrowserDialog: function() {
  var _this = this;
  ASPx.Evt.AttachEventToElement(this.elements.GetFolderBrowserDialogOkButton(), "click", function() { _this.FolderBrowserOkButtonClick(); });
  ASPx.Evt.AttachEventToElement(this.elements.GetFolderBrowserDialogCancelButton(), "click", function() { _this.FolderBrowserCancelButtonClick(); });
 },
 initializeContextMenu: function() {
  if(this.enableContextMenu && ASPx.Browser.WebKitTouchUI)
   ASPx.AddClassNameToElement(this.elements.GetItemsPaneContainer(), FileManagerConsts.TouchContextMenuClassName);
 },
 UpdateFolderRights: function(str) {
  this.folderRights = {
   allowMove: str.indexOf("m") > -1,
   allowRename: str.indexOf("r") > -1,
   allowDelete: str.indexOf("d") > -1,
   allowCreate: str.indexOf("c") > -1,
   allowUpload: str.indexOf("u") > -1,
   allowCopy: str.indexOf("o") > -1
  };
 },
 updateFocusInputVisibility: function() {
  var visible = !this.accessibilityCompliant || !this.isDetailsViewMode();
  ASPx.SetElementDisplay(this.elements.GetFocusInput(), visible);
 },
 NeedCollapseControlCore: function() {
  return this.GetSplitter().NeedCollapseControlCore();
 },
 CollapseControl: function() {
  this.isControlCollapsed = true;
  this.GetSplitter().CollapseControl();
 },
 ExpandControl: function() {
  this.isControlCollapsed = false;
  this.GetSplitter().ExpandControl();
 },
 AdjustControlCore: function() {
  this.calculateFolderContainerAdaptivity();
  window.setTimeout(function() {
   this.updateToolbarExpandFoldersButtonVisibility();
  }.bind(this), 0);
  ASPx.GetControlCollection().AdjustControls(this.GetMainElement());
  this.SetSplitterUploadPaneSize();
  this.ensureToolbarInitialized();
  var instance = this;
  window.setTimeout(function() {
   instance.updateFolderContainerExpandedState();
   if(instance.isInitialized)
    instance.UpdateUploadPanelVisibility();
   instance.SetSplitterPaneSizeByContentControl("ToolbarPane", instance.GetToolbar());
   instance.SetSplitterUploadPaneSize();
   instance.SetSplitterPaneSizeByContentControl("BreadCrumbsPane", instance.breadCrumbs);
   instance.CorrectScroll(instance.focusedItem);
   if(!ASPxClientUtils.touchUI && window.devicePixelRatio !== 1 && !!instance.GetSplitter().GetPaneByName("FoldersPane")) 
    instance.GetSplitter().GetPaneByName("FoldersPane").inResizing = true;
  }, 0);
  if(this.prepareCreateNode) {
   window.setTimeout(function() {
    instance.PrepareCreateNode();
   }, 0);
   this.prepareCreateNode = false;
  }
  setTimeout(function() {
   this.AdjustGridViewSize();
   this.adjustBreadCrumbsItems();
   this.updateToolbarLastWidth();
   this.updateVirtScroll();
  }.aspxBind(this), 0);
  this.itemsPaneContainerScrollHeight = this.elements.GetItemsPaneContainer().scrollTop;
  if(this.GetIsFilterViewActive())
   this.filterView.UpdateFilterViewOnResize();
 },
 AdjustGridViewSize: function(windowResize) {
  if(!this.isDetailsViewMode())
   return;
  var grid = this.GetFilesGridView();
  var itemsPaneContainerElement = this.elements.GetItemsPaneContainer();
  var containerFullHeight = itemsPaneContainerElement.offsetHeight;
  if(containerFullHeight === 0) return;
  var containerHeight = containerFullHeight - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(itemsPaneContainerElement);
  grid.SetHeight(containerHeight);
  if(grid.GetAdaptivityHelper()) {
   if(windowResize)
    grid.OnBrowserWindowResize();
   else
    grid.AdjustControl();
  }
 },
 isFolderContainerAdaptivityEnabled: function() {
  return this.hideFoldersWindowLimit > 0;
 },
 updateFolderContainerAdaptivity: function() {
  this.calculateFolderContainerAdaptivity();
  this.updateToolbarExpandFoldersButtonVisibility();
  this.updateFolderContainerExpandedState();
 },
 calculateFolderContainerAdaptivity: function() {
  this.foldersShouldBeCollapsed = this.isFolderContainerAdaptivityEnabled() && ASPx.GetDocumentClientWidth() <= this.hideFoldersWindowLimit;
 },
 updateToolbarExpandFoldersButtonVisibility: function() {
  var toolbar = this.GetToolbar();
  if(!toolbar || !this.isFolderContainerAdaptivityEnabled())
   return;
  var itemName = this.GetMenuStandardItemFullName(FileManagerConsts.ToolbarName.ExpandFolderContainer);
  var item = toolbar.GetItemByName(itemName);
  var itemVisibility = item.GetVisible();
  var itemNewVisibility = this.foldersShouldBeCollapsed;
  if(itemNewVisibility != itemVisibility) {
   this.updateToolbarExpandFoldersButtonCssClass(item, itemNewVisibility);
   item.SetVisible(itemNewVisibility);
  }
 },
 updateToolbarExpandFoldersButtonCssClass: function(item, visible) {
  var itemElement = this.GetToolbar().GetItemElement(item.GetIndexPath());
  ASPx.ToggleClassNameToElement(itemElement, FileManagerConsts.ToolbarExpandFolderContainerHiddenClassName, !visible);
 },
 updateFolderContainerExpandedState: function() {
  if(this.isFolderContainerAdaptivityEnabled())
   this.setFoldersPaneExpanded(!this.foldersShouldBeCollapsed);
 },
 changeFoldersPaneExpandedState: function() {
  var pane = this.elements.GetFolderContainerPane();
  this.setFoldersPaneExpanded(pane.IsCollapsed());
 },
 setFoldersPaneExpanded: function(expand) {
  var pane = this.elements.GetFolderContainerPane();
  var expanded = !pane.IsCollapsed();
  if(expand == expanded)
   return;
  var contentPaneHelper = pane.GetNextPane().helper;
  var separator = contentPaneHelper.GetSeparatorElement();
  ASPx.CacheHelper.DropCachedValue(contentPaneHelper, "SeparatorSize");
  ASPx.CacheHelper.DropCachedValue(pane.GetParentPane().helper, "hTotalSeparatorsSize");
  if(expand) {
   ASPx.SetElementDisplay(separator, true);
   pane.Expand();
  }
  else {
   ASPx.SetElementDisplay(separator, false);
   pane.CollapseBackward();
  }
 },
 updateToolbarLastWidth: function() {
  if(this.GetToolbar())
   this.saveToolbarLastWidth(this.getToolbarWidth());
 },
 getToolbarWidth: function() {
  return this.elements.GetToolbarPane().GetClientWidth();
 },
 saveToolbarLastWidth: function(width) {
  this.toolbarLastWidth = width;
 },
 OnBrowserWindowResize: function(e) {
  setTimeout(function() { this.adjustControlOnResize(); }.aspxBind(this), 0);
  var splitter = this.GetSplitter();
  if(splitter)
   splitter.OnBrowserWindowResize();
 },
 adjustControlOnResize: function() {
  this.updateFolderContainerAdaptivity();
  this.updateVirtScroll();
  this.adjustBreadCrumbsItems();
  if(this.widthValueSetInPercentage)
   this.AdjustGridViewSize(true);
  this.adjustToolbarOnWindowResize();
  if(this.GetIsFilterViewActive())
   this.filterView.UpdateFilterViewOnResize();
 },
 adjustToolbarOnWindowResize: function() {
  var toolbar = this.GetToolbar();
  if(!toolbar)
   return;
  var width = this.getToolbarWidth();
  if(width !== this.toolbarLastWidth)
   toolbar.OnBrowserWindowResize();
  this.saveToolbarLastWidth(width);
 },
 focusMainElement: function() {
  ASPxClientFileManager.FocusElement(this.GetMainElement());
 },
 UpdateFilesRules: function(rules) {
  this.filesRules = [];
  var ruleCount = rules.length;
  for(var i = 0; i < ruleCount; i++) {
   var ruleParts = rules[i];
   var rule = {
    pattern: ruleParts[0],
    edit: this.GetPermissionValue(ruleParts[1].charAt(0)),
    browse: this.GetPermissionValue(ruleParts[1].charAt(1))
   };
   this.filesRules.push(rule);
  }
 },
 GetPermissionValue: function(str) {
  return str == "-"
   ? FileManagerConsts.Rights.Default
   : str == "a" ? FileManagerConsts.Rights.Allow : FileManagerConsts.Rights.Deny;
 },
 EscapeRegExp: function(str) {
  return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
 },
 IsAppliedRule: function(rule, fileName) {
  var filePath = this.GetCurrentPath(true) + FileManagerConsts.PathSeparator + fileName;
  var regexpPattern = "^" + this.EscapeRegExp(rule.pattern).replace(/\\\*/g, ".*").replace(/\\\?/g, ".") + "$";
  var regExp = new RegExp(regexpPattern, "i");
  return regExp.test(filePath);
 },
 CheckEditAccessByFileName: function(fileName) {
  var result = true;
  var ruleCount = this.filesRules.length;
  for(var i = 0; i < ruleCount; i++) {
   var rule = this.filesRules[i];
   if(this.IsAppliedRule(rule, fileName)) {
    if(rule.edit != FileManagerConsts.Rights.Default)
     result = rule.edit == FileManagerConsts.Rights.Allow;
    if(rule.browse != FileManagerConsts.Rights.Default)
     result = rule.browse == FileManagerConsts.Rights.Allow;
   }
  }
  return result;
 },
 ValidateName: function(fileName, commandName) {
  if(fileName.length == 0)
   return false;
  var forbiddenCharsRegExp = /^[^\\/:\*\?"<>\|]+$/,
   forbiddenNamesRegExp = /^(nul|aux|prn|con|lpt[0-9]|com[0-9])(\.|$)/i,
   isValid = forbiddenCharsRegExp.test(fileName) && !forbiddenNamesRegExp.test(fileName);
  if(!isValid) {
   this.showError(commandName, this.invalidSymbolErrorText, ASPxClientFileManagerErrorConsts.InvalidSymbols.toString());
   return false;
  }
  return true;
 },
 GetCustomFilter: function() {
  return this.GetStateField(FileManagerConsts.StateField.CustomFilter);
 },
 GetCustomFilterBreadcrumbsText: function() {
  if(this.GetCustomFilter())
   return this.GetStateField(FileManagerConsts.StateField.CustomFilterBreadcrumbs);
  return "";
 },
 GetIsFilterApplied: function() {  
  var filter = this.GetCustomFilter() || this.filterBox.GetText();
  return !!filter;
 },
 GetIsRecursiveFilterByNameEnabled: function() {
  return this.filterBoxMode === FileManagerConsts.FilterBoxMode.Subfolders;
 },
 GetIsRecursiveFilterApplied: function() {
  return (this.GetIsRecursiveFilterByNameEnabled() && this.filterBox.GetText()) || this.GetCustomFilter();  
 },
 GetIsFilterViewActive: function() {
  return this.GetStateField(FileManagerConsts.StateField.FilterView);
 },
 RequireApplyFilterBoxTextOnServer: function() {
  if(this.filterBox.GetIsFilterTextChangedOnServer())
   return true;
  if(this.isDetailsViewMode() || this.isVirtScrollEnabled())
   return true;
  if(this.GetIsFilterViewActive() || this.filterFileListViewMode === FileManagerConsts.FilterFileListViewMode.FilterView)
   return true;
  return this.GetIsRecursiveFilterByNameEnabled() || this.GetIsRecursiveFilterApplied();
 },
 SetStyles: function(styles) {
  var stylesInfo = ASPxClientFileManager.StylesHelper.GetStylesInfo(
   styles.iw,
   styles.ih,
   this.elements.GetItemsContainer() || this.elements.GetItemsPaneContainer(),
   [
    [styles.fc, styles.fs],
    [styles.fsac, styles.fsas],
    [styles.fsic, styles.fsis],
    [styles.fhc, styles.fhs],
    [styles.ffc, styles.ffs],
    [styles.fafc, styles.fafs],
    [styles.fafsac, styles.fafsas],
    [styles.fafsic, styles.fafsis],
    [styles.fafhc, styles.fafhs],
    [styles.faffc, styles.faffs]
   ]
  );
  var contentWidth = "", contentHeight = "", containerPosition ="";
  if(stylesInfo.contentWidth > 0)
   contentWidth = "width:" + (this.isThumbnailsViewFileAreaItemTemplate ? stylesInfo.contentWidth : Math.max(stylesInfo.contentWidth, styles.tw)) + "px;";
  if(stylesInfo.contentHeight > 0)
   contentHeight = "height:" + (this.isThumbnailsViewFileAreaItemTemplate ?  stylesInfo.contentHeight : Math.max(stylesInfo.contentHeight, styles.th)) + "px;";
  if(this.allowMultiSelect || this.isThumbnailsViewFileAreaItemTemplate)
   containerPosition = "position: relative;";
  this.styles = {};
  this.styles.thumbnailWidth = styles.tw;
  this.styles.thumbnailHeight = styles.th;
  this.styles.fileCssClass = this.MergeCssClassWithStyleString(styles.fc, stylesInfo.styleStrings[0] + containerPosition);
  this.styles.fileContentCssClass = this.MergeCssClassWithStyleString(styles.fcc, styles.fcs + contentWidth + contentHeight);
  if(this.isThumbnailOrFilterViewMode())
   this.styles.fileSelectionActiveCssClass = this.MergeCssClassWithStyleString(styles.fsac, stylesInfo.styleStrings[1]);
  else
   this.styles.fileSelectionActiveCssClass = styles.fsac;
  this.styles.fileSelectionInactiveCssClass = this.MergeCssClassWithStyleString(styles.fsic, stylesInfo.styleStrings[2]);
  this.styles.fileHoverCssClass = this.MergeCssClassWithStyleString(styles.fhc, stylesInfo.styleStrings[3]); 
  this.styles.fileFocusCssClass = this.isDetailsViewMode() ? styles.ffc : this.MergeCssClassWithStyleString(styles.ffc, stylesInfo.styleStrings[4]);
  this.styles.fileAreaFolderCssClass = this.MergeCssClassWithStyleString(styles.fafc, stylesInfo.styleStrings[5] + containerPosition);
  this.styles.fileAreaFolderContentCssClass = this.MergeCssClassWithStyleString(styles.fafcc, styles.fafcs + contentWidth + contentHeight);
  if(!this.isDetailsViewMode())
   this.styles.fileAreaFolderSelectionActiveCssClass = this.MergeCssClassWithStyleString(styles.fafsac, stylesInfo.styleStrings[6]);
  else
   this.styles.fileAreaFolderSelectionActiveCssClass = styles.fafsac;
  this.styles.fileAreaFolderSelectionInactiveCssClass = this.MergeCssClassWithStyleString(styles.fafsic, stylesInfo.styleStrings[7]);
  this.styles.fileAreaFolderHoverCssClass = this.MergeCssClassWithStyleString(styles.fafhc, stylesInfo.styleStrings[8]); 
  this.styles.fileAreaFolderFocusCssClass = this.isDetailsViewMode() ? styles.faffc : this.MergeCssClassWithStyleString(styles.faffc, stylesInfo.styleStrings[9]);
  this.styles.folderSelectionActiveCssClass = styles.fosac;
  this.styles.folderSelectionInactiveCssClass = this.MergeCssClassWithStyleString(styles.fosic, styles.fosis);
  this.styles.highlightCssClass = this.MergeCssClassWithStyleString(styles.hc, styles.hs);
  this.styles.breadCrumbsItemCssClass = this.MergeCssClassWithStyleString(styles.bc, styles.bs);
  this.styles.breadCrumbsItemHoverCssClass = this.MergeCssClassWithStyleString(styles.bhc, styles.bhs);
  this.styles.breadCrumbsUpButtonImageDisabledScriptObjects = styles.bids;
  this.styles.breadCrumbsUpButtonImageHoveredScriptObjects = styles.bihs;
  this.styles.rowSelectionActiveCssClass = "selectActive";
  this.styles.rowSelectionInactiveCssClass = "selectInactive";
  this.styles.filesGridViewDataRowCssClass = this.MergeCssClassWithStyleString(styles.gvrc, styles.gvrs);
 },
 MergeCssClassWithStyleString: function(cssClass, styleString) {
  if(!styleString)
   return cssClass;
  var styleStringCssClass = ASPx.CreateImportantStyleRule(this.styleSheet, styleString);
  return cssClass
   ? cssClass + " " + styleStringCssClass
   : styleStringCssClass;
 },
 SetHeight: function(height) {
  this.GetMainElement().style.height = height + "px";
  this.GetSplitter().SetHeight(height);
  this.AdjustGridViewSize();
 },
 SetWidth: function(width) {
  this.GetSplitter().SetWidth(width);
  this.adjustBreadCrumbsItems();
 },
 forEachItem: function(action) {
  for(var item in this.items) {
   if(this.items.hasOwnProperty(item) && action(this.items[item]))
    return;
  }
 },
 isEmptyItemsList: function() {
  for(var item in this.items) {
   if(this.items.hasOwnProperty(item))
    return false;
  }
  return true;
 },
 getSelectedItems: function(onlyVisible) {
  var items = [];
  this.forEachItem(function(item) {
   if(item.IsSelected() && (!onlyVisible || item.GetVisible()))
    items.push(item);
  });
  items.sort(function(item1, item2) { return item1.index - item2.index; });
  return items;
 },
 GetItemThumbnailSize: function(isHeight) {
  if(this.GetIsFilterViewActive())
   return FileManagerConsts.DefaultFilterViewThumbnailSize;
  return isHeight ? this.styles.thumbnailHeight : this.styles.thumbnailWidth;
 },
 isVirtScrollEnabled: function() {
  return this.virtScroll.pageSize > 0;
 },
 getItemSizes: function() {
  var sampleItem = this.virtScroll.firstItem;
  if(sampleItem) {
   var sampleElement = sampleItem.getElement();
   var cssText = sampleElement.style.cssText;
   if(cssText)
    sampleElement.style.cssText = "";
   var sampleStyle = this.getCurrentStyle(sampleElement);
   var sampleElementSizes = this.getElementSizes(sampleElement, sampleStyle);
   var itemWidth = sampleElementSizes.width,
    itemHeight = sampleElementSizes.height;
   itemWidth += ASPx.GetLeftRightMargins(sampleElement, sampleStyle);
   itemHeight += ASPx.GetTopBottomMargins(sampleElement, sampleStyle);
   if(cssText)
    sampleElement.style.cssText = cssText;
   return { 
    width: itemWidth,
    height: itemHeight,
    marginTop: ASPx.PxToInt(sampleStyle.marginTop)
   };
  }
  return null;
 },
 getElementSizes: function(element, currentStyle) {
  var elementWidth = 0,
   elementHeight = 0;
  elementWidth = ASPx.PxToFloat(currentStyle.width) + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element, currentStyle);
  elementHeight = ASPx.PxToFloat(currentStyle.height) + ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element, currentStyle);
  return { width: elementWidth, height: elementHeight };
 },
 getItemAreaSizes: function() {
  var itemsContainer = this.elements.GetItemsContainer();
  var itemsPaneContainer = this.elements.GetItemsPaneContainer();
  return {
   width: itemsContainer.clientWidth,
   height: itemsPaneContainer.clientHeight - ASPx.GetTopBottomPaddings(itemsPaneContainer)
  };
 },
 getCurrentStyle: function(element) {
  if(window.getComputedStyle)
   return window.getComputedStyle(element, null);
  if(element.currentStyle)
   return element.currentStyle;
  return null;
 },
 createVirtScrollState: function() {
  var state = {};
  var itemAreaSizes = this.getItemAreaSizes();
  state.itemsAreaWidth = itemAreaSizes.width;
  state.itemsViewAreaHeight = itemAreaSizes.height;
  var itemSizes = this.getItemSizes();
  if(this.virtScroll.itemsCount == 0 || itemSizes.itemWidth == 0 || itemSizes.itemHeight == 0) {
   state.itemWidth = state.itemHeight = state.itemsInRowCount = 0;
   state.isEmpty = true;
   return state;
  }
  state.itemWidth = itemSizes.width;
  state.itemHeight = itemSizes.height;
  var itemsInRowCount = Math.floor(state.itemsAreaWidth / state.itemWidth);
  state.itemsInRowCount = itemsInRowCount > 0 ? itemsInRowCount : 1;
  return state;
 },
 createVirtScrollExtendedState: function(itemIndex, pageItemsCount, itemsCount) {
  var state = this.createVirtScrollState();
  if(state.isEmpty) {
   state.pageHeight = 0;
   state.topIndentHeight = 0;
   state.bottomIndentHeight = 0;
   state.pageItemLeftOffset = 0;
   state.pageLastRowIsFull = true;
  }
  else {
   var itemLeftOffsetIndex = itemIndex % state.itemsInRowCount;
   var pageLayoutItemsCount = pageItemsCount + itemLeftOffsetIndex;
   state.pageHeight = Math.ceil((pageLayoutItemsCount) / state.itemsInRowCount) * state.itemHeight;
   var pageLastRowIsFull = (pageLayoutItemsCount % state.itemsInRowCount) == 0;
   state.pageLastRowIsFull = pageLastRowIsFull || (itemIndex + pageItemsCount >= itemsCount);
   var pageItemRowIndex = Math.floor(itemIndex / state.itemsInRowCount);
   state.topIndentHeight = pageItemRowIndex * state.itemHeight;
   var itemRowsCount = Math.ceil(itemsCount / state.itemsInRowCount);
   var itemAreaHeight = itemRowsCount * state.itemHeight;
   state.bottomIndentHeight = itemAreaHeight - state.topIndentHeight - state.pageHeight;
   state.pageItemLeftOffset = itemLeftOffsetIndex * state.itemWidth;
  }
  return state;
 },
 calculateVirtScrollState: function() {
  this.virtScroll.state = this.createVirtScrollExtendedState(this.virtScroll.itemIndex, this.virtScroll.pageItemsCount, this.virtScroll.itemsCount);
 },
 updatePageIndents: function() {
  this.elements.pageTopIndentElement.style.height = this.virtScroll.state.topIndentHeight + "px";
  this.elements.pageBottomIndentElement.style.height = this.virtScroll.state.bottomIndentHeight + "px";
 },
 updateVirtScroll: function() {
  if(!this.isThumbnailModeVirtScrollEnabled()) return;
  this.saveItemsScrollPosition();
  this.resetFirstItemIndent();
  this.updateVirtScrollCore();
  this.restoreItemsScrollPosition();
 },
 updateVirtScrollCore: function() {
  this.calculateVirtScrollState();
  this.updatePageIndents();
  this.updateFirstItemIndent();
 },
 saveNewItemsScrollPosition: function(itemIndex, pageItemsCount, scrollTop) {
  var state = this.createVirtScrollExtendedState(itemIndex, pageItemsCount, 0);
  this.virtScroll.lastPageScrollPos = this.getItemsScrollPosition(state, scrollTop);
 },
 saveItemsScrollPosition: function() {
  var scrollTop = this.elements.GetItemsPaneContainer().scrollTop;
  this.virtScroll.lastPageScrollPos = this.getItemsScrollPosition(this.virtScroll.state, scrollTop);
 },
 getItemsScrollPosition: function(state, scrollTop) {
  var pageScrollPos = null;
  if(state && !state.isEmpty) {
   var rowIndex = scrollTop / state.itemHeight;
   var itemIndex = Math.floor(rowIndex) * state.itemsInRowCount;
   var itemHeightOffset = rowIndex % 1;
   pageScrollPos = { itemIndex: itemIndex, itemHeightOffset: itemHeightOffset };
  }
  else
   pageScrollPos = this.getStartItemsScrollPos();
  return pageScrollPos;
 },
 getStartItemsScrollPos: function() {
  if(this.virtScroll.startPageScrollPos == null)
   this.virtScroll.startPageScrollPos = { itemIndex: 0, itemHeightOffset: 0 };
  return this.virtScroll.startPageScrollPos;
 },
 restoreItemsScrollPosition: function() {
  var scrollPos = this.virtScroll.lastPageScrollPos || this.getStartItemsScrollPos();
  var rowIndex = Math.floor(scrollPos.itemIndex / this.virtScroll.state.itemsInRowCount);
  var scrollTop = (rowIndex + scrollPos.itemHeightOffset) * this.virtScroll.state.itemHeight;
  this.elements.GetItemsPaneContainer().scrollTop = scrollTop;
 },
 resetFirstItemIndent: function() {
  if(this.virtScroll.firstItem != null)
   this.virtScroll.firstItem.getElement().style.marginLeft = "";
 },
 updateFirstItemIndent: function() {
  if(this.virtScroll.firstItem != null) {
   var element = this.virtScroll.firstItem.getElement();
   element.style.cssText = "";
   var style = ASPx.GetCurrentStyle(element);
   var margin = style.marginLeft ? ASPx.PxToFloat(style.marginLeft) : 0;
   margin += this.virtScroll.state.pageItemLeftOffset;
   var cssText = "margin-left: " + margin + "px";
   element.style.cssText = ASPx.CreateImportantCssText(cssText);
  }
 },
 CreateItems: function(itemsList, skipState, isNewFileList) {
  if(this.isThumbnailModeVirtScrollEnabled())
   this.elements.ensurePageIndentsCreated();
  this.items = {};
  this.itemElementsIds = {};
  this.virtScroll.firstItem = null;
  for(var item, i = 0; item = itemsList[i]; i++) {
   var itemIndex = this.isVirtScrollEnabled() ? this.virtScroll.itemIndex + i : i;
   var item = this.createItem(item, itemIndex);
   if(!item.isCreateHelperFolder) {
    if(this.virtScroll.firstItem == null && !item.isVirtual())
     this.virtScroll.firstItem = item;
    this.items[item.id] = item;
    this.itemElementsIds[item.elementID] = item;
    this.PrepareItemState(item);
   }
  }
  if(this.enabled) {
   if(isNewFileList && !this.filterBox.GetText())
    this.filterBox.UpdateEnabled(!this.isEmptyItemsList() || this.GetIsRecursiveFilterByNameEnabled());
   this.delayedApplyState = !this.isInitialized;
   if(!skipState && !this.delayedApplyState)
    this.ApplyControlState(false);
   if(!isNewFileList && this.isVirtScrollEnabled())
    this.restoreSelectedItems();
  }
  if(this.isThumbnailOrFilterViewMode()) {
   if(this.isThumbnailsViewFileAreaItemTemplate)
    this.elements.disableImagesDraggable(this.elements.GetItemsContainer());
   var itemSizes = this.getItemSizes();
   if(itemSizes) {
    this.itemThumbnailHeight = itemSizes.height;
    this.itemThumbnailWidth = itemSizes.width;
    this.itemThumbnailMarginTop = itemSizes.marginTop;
   }
  }
  var filterViewActive = this.GetIsFilterViewActive();
  if(filterViewActive) {   
   this.filterView.UpdateFilterViewOnResize();
  }
 },
 ClearItems: function(isNewFileList, skipUnselect) {
  if(this.internalCheckBoxCollection)
   this.internalCheckBoxCollection.Clear();
  if(isNewFileList) {
   if(!skipUnselect)
    this.unselectAllItems();
   this.DropStateField("item");
  }
  else if(this.isVirtScrollEnabled())
   this.saveSelectedItems();
  this.ClearStateControllerHoverItems();
  this.items = {};
  this.itemElementsIds = {};
  this.focusedItem = null;
  if(this.isThumbnailOrFilterViewMode()) {
   if(this.isVirtScrollEnabled()) {
    this.elements.dropPageIndents();
    if(isNewFileList) {
     this.virtScroll.itemIndex = 0;
     this.virtScroll.pageItemsCount = 0;
    }
   }
   this.elements.DropItemsContainer();
  }
 },
 forEachSelectedItemID: function(action) {
  var selectItemProperties = this.GetStateField(FileManagerConsts.StateField.ItemSelected);
  if(!selectItemProperties)
   return;
  for(var itemProperties, i = 0; itemProperties = selectItemProperties[i]; i++) {
   var itemID = this.GetItemName(itemProperties);
   action.call(this, itemID);
  }
 },
 saveSelectedItems: function() {
  var selectedItems = [];
  this.forEachSelectedItemID(function(itemID) {
   var item = this.items[itemID];
   if(item)
    selectedItems.push(item);
  }.aspxBind(this));
  this.virtScroll.selectedItems = selectedItems;
 },
 restoreSelectedItems: function() {
  var selectedItems = this.virtScroll.selectedItems;
  if(!selectedItems)
   return;
  for(var i = 0, item; item = selectedItems[i]; i++) {
   var existingItem = this.items[item.id];
   if(existingItem)
    item.outdated = true;
   else {
    item.makeClientInvisible();
    this.items[item.id] = item;
   }
  }
  this.virtScroll.selectedItems = null;
 },
 createApiCommandItems: function(itemsDataList) {
  this.apiCommandItems = [];
  for(var itemData, i = 0; itemData = itemsDataList[i]; i++) {
   var item = this.createItem(itemData, i);
   if(!item.isCreateHelperFolder)
    this.apiCommandItems.push(item);
  }
 },
 createItem: function(itemData, index) {
  return itemData.it == FileManagerConsts.FileAreaItemTypes.File
   ? new ASPxClientFileManagerFile(this, index, itemData)
   : new ASPxClientFileManagerFolder(this, index, itemData);
 },
 getVisibleItemsInfo: function(skipIndexMap, skipParentFolder) {
  var list = [];
  var indexMap = skipIndexMap ? null : {};
  this.forEachItem(function(item) {
   if(item.GetVisible() && !item.isCreateHelperFolder && (!skipParentFolder || !item.isParentFolderItem)) {
    list.push(item);
    if(!skipIndexMap)
     indexMap[item.index] = item;
   }
  });
  list.sort(function(a, b) { return a.index - b.index; });
  return { list: list, indexMap: indexMap };
 },
 GetVisibleItems: function(skipParentFolder) {
  var itemsInfo = this.getVisibleItemsInfo(true, skipParentFolder);
  return itemsInfo.list;
 },
 UpdateFileList: function(callbackCommand, needSelectItem) {
  this.DropStateField("item");
  this.SendCallback(callbackCommand, { name: needSelectItem });
 },
 TryOpen: function() {
  return this.TryOpenItem(this.allowMultiSelect ? this.focusedItem : this.getSelectedItems()[0]);
 },
 TryOpenItem: function(item) {
  if(!item)
   return false;
  if(item.isFolder) {
   var path = "",
    idPath = null;
   if(item.parentInfo) {
    path = item.parentInfo.relativeName;
    idPath = item.parentInfo.idPath.slice();
   } else {
    path = this.GetCurrentPath(true);
    idPath = this.currentIdPath.slice();
   }
   if(!item.isParentFolderItem) {
    path += (path ? FileManagerConsts.PathSeparator : "") + item.name;
    idPath.push(item.formattedId);
   }
   else {
    path = path.substr(0, path.lastIndexOf(FileManagerConsts.PathSeparator));
    idPath.pop();
   }
   this.SetCurrentFolderPathInternal(path, undefined, idPath, item.isParentFolderItem);
   this.needSetActiveItemsArea = true;
  } else
   this.raiseSelectedFileOpenedEvent(item);
  return true;
 },
 ensureGridViewItems: function() {
  if(this.isDetailsViewMode()) {
   var grid = this.GetFilesGridView();
   this.forEachItem(function(item) {
    item.index = grid.GetRowIndexByKey(item.id);
    var row = grid.GetItem(item.index);
    if(row) {
     row.title = item.tooltip;
     this.elements.disableDraggable(row);
     if(ASPx.Browser.WebKitTouchUI)
      ASPx.TouchUIHelper.AttachDoubleTapEventToElement(row, function(evt) { this.onFilesGridViewRowDblClickInternal(item); }.bind(this));
    }
   }.aspxBind(this));
   if(this.detailsCreateHelperItem) {
    this.detailsCreateHelperItem.index = grid.getVisibleEndIndex();
    this.elements.createDetailsCreateHelperItemElement(this.detailsCreateHelperItem);
   }
  }
  this.ensureDelayedApplyState();
 },
 createBreadCrumbs: function() {
  this.breadCrumbs = this.createBreadCrumbsCore();
  this.breadCrumbs.render();
 },
 createBreadCrumbsCore: function() {
  return new ClientFileManagerBreadCrumbs(this);
 },
 adjustBreadCrumbsItems: function() {
  if(!this.breadCrumbsEnabled)
   return;
  this.breadCrumbs.hidePopup();
  this.breadCrumbs.adjustItems();
 },
 ApplyControlState: function(skipEvents) {
  if(!this.enabled) return;
  var focusFileName = this.GetItemName(this.GetStateField(FileManagerConsts.StateField.ItemFocused));
  var selectItemProperties = this.GetStateField(FileManagerConsts.StateField.ItemSelected);
  var selectItemNames = [];
  var outdatedItems = { };
  if(selectItemProperties) {
   for(var itemProperties, i = 0; itemProperties = selectItemProperties[i]; i++) {
    var itemName = this.GetItemName(itemProperties);
    selectItemNames.push(itemName);
    if(!this.items[itemName])
     outdatedItems[itemName] = this.createOutdatedItem(itemProperties);
   }
  }
  if(this.isDetailsViewMode()) {
   this.GetFilesGridView().UnselectAllRowsOnPage();
   this.GetFilesGridView().SetFocusedRowIndex(-1);
  }
  if(selectItemNames.length > 0) {
   var focused = focusFileName && ASPx.Data.ArrayIndexOf(selectItemNames, focusFileName) > -1 ? this.focusItem(focusFileName, skipEvents) : true;
   var selectedItems = this.selectItems(selectItemNames, skipEvents, !focused);
   if(selectedItems.length != selectItemNames.length) {
    for(var fileName, i = 0; fileName = selectItemNames[i]; i++) {
     if(ASPx.Data.ArrayIndexOf(selectedItems, fileName) < 0) {
      var item = this.items[fileName] || outdatedItems[fileName];
      this.raiseSelectionChanged(item, false);
     }
    }
   }
   this.saveSelectedItemsToState();
  }
 },
 ensureDelayedApplyState: function() {
  if(this.delayedApplyState) {
   this.delayedApplyState = null;
   this.ApplyControlState(false);
  }
 },
 PrepareItemState: function(item) {
  if(!this.enabled || this.isDetailsViewMode())
   return;
  ASPx.GetStateController().AddSelectedItem(
   item.elementID,
   [item.selectionActiveCssClass],
   [""],
   null,
   null,
   null
  );
  ASPx.GetStateController().AddHoverItem(
   item.elementID,
   [item.hoverCssClass],
   [""],
   null,
   null,
   null
  );
 },
 ClearStateControllerHoverItems: function() {
  if(this.isDetailsViewMode())
   return;
  this.forEachItem(function(file) {
   var fileId = file.elementID;
   ASPx.GetStateController().RemoveSelectedItem(fileId);
   ASPx.GetStateController().RemoveHoverItem(fileId);
  });
 },
 GetItemName: function(itemProperties) {
  return itemProperties ? this.getIdFromFormattedId(itemProperties.id) : "";
 },
 createOutdatedItem: function(itemInfo) {
  return this.createOutdatedItemCore(itemInfo.id, itemInfo.name, itemInfo.isFolder);
 },
 createOutdatedItemCore: function(id, name, isFolder) {
  var itemInfo = {
   id: id,
   n: name,
   outdated: true
  };
  var item = null;
  if(!isFolder) {
   itemInfo.it = FileManagerConsts.FileAreaItemTypes.File;
   item = new ASPxClientFileManagerFile(this, 0, itemInfo);
  }
  else {
   itemInfo.it = FileManagerConsts.FileAreaItemTypes.Folder;
   item = new ASPxClientFileManagerFolder(this, 0, itemInfo);
  }
  return item;
 },
 UpdateClientStateCookie: function() {
  if(this.cookieName && this.cookieName != "") {
   var cookieValue = ASPx.Cookie.GetCookie(this.cookieName);
   ASPx.Cookie.DelCookie(this.cookieName);
   ASPx.Cookie.SetCookie(this.cookieName, this.GetClientStateString(cookieValue));
  }
 },
 GetClientStateString: function(prevStateString) {
  var prevState = null;
  if(prevStateString && prevStateString.indexOf(FileManagerConsts.ClientStatePrefix) === 0) {
   prevStateString = prevStateString.substr(FileManagerConsts.ClientStatePrefix.length);
   prevState = JSON.parse(prevStateString) || {};
  } else
   prevState = {};
  var splitterState = this.GetSplitter().GetClientStateString();
  var folders = this.GetTreeView();
  var foldersState = folders ? folders.GetClientStateString() : "";
  var state = {
   "dxformatver": "1.0",
   "version": prevState["version"],
   "spl": splitterState,
   "ftv": foldersState,
   "fgv": prevState["fgv"],
   "fgv-cw": this.GetFilesGridViewColumnsWidthState(),
   "fm": {
    "filterbox": this.filterBox.GetText()
   }
  };
  return FileManagerConsts.ClientStatePrefix + ASPx.Json.ToJson(state);
 },
 GetFilesGridViewColumnsWidthState: function() {
  var grid = this.GetFilesGridView();
  if(!grid) return "";
  return grid.GetCallbackHelper().GetResizingState() || "";
 },
 OnFolderClick: function(node) {
  this.SetActiveArea(FileManagerConsts.SelectedArea.Folders);
  this.UpdateTollbarStandardItem(FileManagerConsts.ToolbarName.Move, this.IsMoveAvailable());
  if(this.tree.getSelectedNode() == node)
   return;
  this.tree.setSelectedNode(node);
  this.tree.scrollToNode(node);
  this.DoRename();
  this.needCurrentFolderChangedRaise = true;
  this.lockLoadingDiv = true;
  this.UpdateFileList(ASPxClientFileManagerCallbackCommand.GetFileList);
  setTimeout(function() {
   this.lockLoadingDiv = false;
   if(this.inCallback)
    this.ShowLoadingDiv();
  }.aspxBind(this), 150);
 },
 OnFolderExpanding: function(treeView, e) {
  if(treeView.callBack) {
   if(!e.node.GetExpanded() && e.node.GetNodeCount() == 0)
    this.folderExpandingNode = e.node;
   if(!treeView.isFolderBrowserFolders && this.inCallback) {
    e.cancel = true;
    this.delayedExpandNode = e.node;
   }
  }
 },
 OnFolderExpanded: function(treeView, e) {
  this.UpdateClientStateCookie();
 },
 OnItemClick: function(item, modifierKey) {
  if(this.allowRename && !item.IsSelected())
   this.DoRename();
  if(this.allowMultiSelect)
   this.onItemClickInMultipleMode(item, modifierKey);
  else
   item.Select();
  this.CorrectScroll(item);
 },
 onItemClickInMultipleMode: function(item, modifierKey) {
  var itemsInfo = this.getVisibleItemsInfo();
  var focusFile = itemsInfo.list[0];
  if(this.focusedItem && !this.focusedItem.isVirtual())
   focusFile = this.focusedItem;
  item.focus();
  if(modifierKey == FileManagerConsts.ModifierKey.None) {
   item.Select();
   this.unselectAllItems([item], true);
  }
  else if(modifierKey == FileManagerConsts.ModifierKey.Ctrl) {
   if(!(this.getSelectedItems().length == 1 && item.IsSelected()))
    item.invertSelection();
  }
  else if(modifierKey == FileManagerConsts.ModifierKey.Shift) {
   var direction = item.index - focusFile.index;
   this.changeRangeSelection(focusFile, item, itemsInfo.indexMap, direction);
  }
 },
 Focus: function() {
  if(this.kbdHelper)
   this.kbdHelper.Focus();
 },
 KeepClientUploadState: function(uploadedFileCount) {
  var path = this.GetCurrentPath(true);
  var idPath = this.currentIdPath;
  if(!this.uploadSessionInfo) {
   var stateItem = {
    path: path,
    idPath: idPath,
    startFileIndex: 0
   };
   this.uploadSessionInfo = {
    state: [ stateItem ]
   };
  }
  else {
   var lastStateItem = this.uploadSessionInfo.state[this.uploadSessionInfo.state.length - 1];
   if(lastStateItem.path !== path || !ASPx.Data.ArrayEqual(lastStateItem.idPath, idPath)) {
    var stateItem = {
     path: path,
     idPath: idPath,
     startFileIndex: this.uploadSessionInfo.fileCount
    };
    this.uploadSessionInfo.state.push(stateItem);
   }
  }
  this.uploadSessionInfo.fileCount = uploadedFileCount;
  this.UpdateStateField(FileManagerConsts.StateField.UploadState, this.uploadSessionInfo.state);
 },
 findUploadFolderPath: function(fileIndex) {
  var result = this.uploadSessionInfo.state[0].path;
  for(var i = 1; i < this.uploadSessionInfo.state.length; i++) {
   var stateItem = this.uploadSessionInfo.state[i];
   if(fileIndex >= stateItem.startFileIndex)
    result = stateItem.path;
   else
    return result;
  }
  return result;
 },
 OnFileUploadStart: function() {
  if(!this.hideUploadPanel)
   return;
  this.GetUploadProgressPopup().Show();
  this.correctItemsAreaPopupPosition(this.GetUploadProgressPopup());
 },
 OnFilesUploadComplete: function(evt) {
  var uc = this.GetUploadControl();
  uc.OnCompleteFileUpload();
  if(!this.hideUploadPanel) {
   uc.UpdateButtonValue(false);
   this.OnUploadTextChanged("");
  }
  var result = {
   uploadErrorText: evt.errorText
  };
  if(evt.callbackData != '')
   result = eval(evt.callbackData);
  uc.ClearText();
  if(result.uploadErrorText || !result.uploadSuccess) {
   if(result.errorCode === undefined)
    result.errorCode = "" + ASPxClientFileManagerErrorConsts.Unspecified;
   this.showError(ASPxClientFileManagerCommandConsts.Upload, result.uploadErrorText, result.errorCode);
  }
  if(result.uploadSuccess) {
   this.needSelectItems = [];
   for(var fileInfo, i = 0; fileInfo = result.uploadedFileInfos[i]; i++) {
    var fileFullName = ASPxClientFileManager.GetItemFullName(fileInfo.name, this, null, true);
    this.needSelectItems.push(fileFullName);
   }
   var needSelectItem = this.needSelectItems.length > 0 ? this.needSelectItems[0] : undefined;
   this.UpdateFileList(ASPxClientFileManagerCallbackCommand.GetFileList, needSelectItem);
   this.raiseFileUploaded(result.uploadedFileInfos);
  }
  if(this.hideUploadPanel) {
   this.GetUploadProgressBar().SetPosition(0);
   this.GetUploadProgressPopup().Hide();
  }
  this.HideLoadingElements();
  this.uploadSessionInfo = null;
  this.DropStateField(FileManagerConsts.StateField.UploadState);
 },
 OnUploadControlValidationErrorOccurred: function(evt) {
  this.raiseEventWithArgsInternal("FileUploadValidationErrorOccurred", evt);
 },
 OnUploadingProgressChanged: function(evt) {
  if(this.hideUploadPanel)
   this.GetUploadProgressBar().SetPosition(evt.progress);
 },
 OnUploadTextChanged: function(text) {
  if(!this.hideUploadPanel)
   this.GetUploadControl().SetButtonEnable(text != "");
 },
 OnToolbarItemClick: function(itemName) {
  if(this.renameMode)
   this.DoRename();
  if(itemName.indexOf(FileManagerConsts.ToolbarStandardButtonPrefix) != 0) {
   this.raiseCustomCommand(itemName);
   return;
  }
  switch(itemName.replace(FileManagerConsts.ToolbarStandardButtonPrefix, "")) {
   case FileManagerConsts.ToolbarName.Refresh:
    this.Refresh();
    break;
   case FileManagerConsts.ToolbarName.Delete:
    this.TryDelete();
    break;
   case FileManagerConsts.ToolbarName.Rename:
    this.TryRename();
    break;
   case FileManagerConsts.ToolbarName.Move:
    this.TryMove();
    break;
   case FileManagerConsts.ToolbarName.Create:
    this.TryCreate();
    break;
   case FileManagerConsts.ToolbarName.Download:
    this.TryDownload();
    break;
   case FileManagerConsts.ToolbarName.Copy:
    this.TryCopy();
    break;
   case FileManagerConsts.ToolbarName.ExpandFolderContainer:
    this.changeFoldersPaneExpandedState();
    break;
  }
 },
 OnContextMenuItemClick: function(itemName) {
  this.OnToolbarItemClick(itemName);
 },
 OnFolderBrowserDialogClosing: function() {
  this.folderDialogCommand = null;
  this.UpdateToolbars();
 },
 OnFolderBrowserDialogShown: function() {
  this.UpdateToolbars();
 },
 OnDocumentClick: function(evt) {
  if(!this.GetMainElement() || !this.isExists())
   return;
  var element = ASPx.Evt.GetEventSource(evt);
  if(element.parentNode && !ASPx.GetIsParent(this.GetMainElement(), element)) {
   if(this.createMode)
    this.DoCreate();
   this.SetActiveArea(FileManagerConsts.SelectedArea.None);
  }
 },
 OnFilesContainerClick: function(evt) {
  if(!ASPx.Evt.IsLeftButtonPressed(evt))
   return;
  if(this.createMode)
   this.DoCreate();
  else {
   var item = this.getClickedItem(evt);
   if(item && !this.elements.getCheckBoxByEvt(evt))
    this.OnItemClick(item, this.getKeyModifier(evt));
   this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
  }
 },
 onItemsContainerScroll: function(evt) {
  if(this.inCallback || this.createInFileAreaMode)
   return;
  if(this.virtScroll.timerId == -1)
   this.virtScroll.timerId = window.setTimeout(this.onVirtualScrollingTimeout.aspxBind(this), this.virtScroll.timeout);
 },
 onVirtualScrollingTimeout: function() {
  this.virtScroll.timerId = -1;
  this.tryPerformVirtulScrolling();
 },
 onVirtScrollJumpTimeout: function() {
  this.virtScroll.jumpTimerId = -1;
  this.tryPerformVirtulScrolling(true);
 },
 tryPerformVirtulScrolling: function(doScroll) {
  if(this.inCallback) {
   this.virtScroll.lastPageIndexOffset = 0;
   return;
  }
  var scrollTop = this.elements.GetItemsPaneContainer().scrollTop;
  var lowerBoundary = this.virtScroll.state.topIndentHeight;
  var upperBoundary = lowerBoundary + this.getBaseUpperBoundary();
  var upperBoundaryOffset = this.virtScroll.state.pageLastRowIsFull ? 0 : this.virtScroll.state.itemHeight;
  upperBoundary -= upperBoundaryOffset;
  if(upperBoundary < 0)
   upperBoundary = 0;
  var lowerBoundaryOverflow = scrollTop < lowerBoundary;
  var upperBoundaryOverflow = scrollTop > upperBoundary;
  var boundaryOverflow = lowerBoundaryOverflow || upperBoundaryOverflow;
  if(boundaryOverflow) {
   if(doScroll) {
    this.virtScroll.lastPageIndexOffset = 0;
    this.performVirtualScrolling(scrollTop, upperBoundaryOverflow);
    return;
   }
   var pageBottomIndexOffset = Math.floor((scrollTop - lowerBoundary) / this.virtScroll.state.pageHeight);
   var pageTopIndexOffset = Math.floor((scrollTop + this.virtScroll.state.itemsViewAreaHeight + upperBoundaryOffset - lowerBoundary) / this.virtScroll.state.pageHeight);
   var pageIndexOffset = 0;
   if(pageBottomIndexOffset !== 0)
    pageIndexOffset = pageBottomIndexOffset;
   else if(pageTopIndexOffset !== 0)
    pageIndexOffset = pageTopIndexOffset;
   if(pageIndexOffset !== this.virtScroll.lastPageIndexOffset) {
    var farJump = Math.abs(pageIndexOffset) > 1;
    var jumpTimeout = farJump ? this.virtScroll.farJumpTimeout : this.virtScroll.nearJumpTimeout;
    if(this.virtScroll.jumpTimerId > -1)
     window.clearTimeout(this.virtScroll.jumpTimerId);
    this.virtScroll.jumpTimerId = window.setTimeout(this.onVirtScrollJumpTimeout.aspxBind(this), jumpTimeout);
    this.virtScroll.lastPageIndexOffset = pageIndexOffset;
   }
  }
  else {
   this.virtScroll.lastPageIndexOffset = 0;
   if(this.virtScroll.jumpTimerId > -1) {
    window.clearTimeout(this.virtScroll.jumpTimerId);
    this.virtScroll.jumpTimerId = -1;
   }
  }
 },
 performVirtualScrolling: function(scrollTop, forwardScroll) {
  var params = this.getNewVirtScrollParams(scrollTop, forwardScroll);
  this.saveNewItemsScrollPosition(params.newItemIndex, params.newPageItemsCount, scrollTop);
  this.virtScroll.inCallback = true;
  this.performVirtualScrollingCallback(params.newItemIndex, params.newPageItemsCount);
 },
 getBaseUpperBoundary: function() {
  return this.virtScroll.state.pageHeight - this.virtScroll.state.itemsViewAreaHeight + FileManagerConsts.UpperBoundaryAdditionalOffset;
 },
 getNewVirtScrollParams: function(scrollTop, forwardScroll) {
  var state = this.createVirtScrollState();
  if(state.isEmpty)
   return { newItemIndex: 0, newPageItemsCount: this.virtScroll.pageSize };
  var prevItemsRate = 0.2,
   nextItemsRate = 1 - prevItemsRate;
  var viewAreaMaxRowCount = Math.ceil(state.itemsViewAreaHeight / state.itemHeight) + 1;
  var minPageItemsCount = Math.ceil((viewAreaMaxRowCount * state.itemsInRowCount) / nextItemsRate);
  var newPageItemsCount = this.virtScroll.pageSize >= minPageItemsCount ? this.virtScroll.pageSize : minPageItemsCount;
  var viewAreaScrollTop = forwardScroll ? scrollTop : scrollTop + state.itemsViewAreaHeight;
  var viewAreaStartItemIndex = Math.floor(viewAreaScrollTop / state.itemHeight) * state.itemsInRowCount;
  var backItemsOffset = Math.floor((forwardScroll ? prevItemsRate : nextItemsRate) * newPageItemsCount);
  var newItemIndex = viewAreaStartItemIndex - backItemsOffset;
  if(newItemIndex < 0)
   newItemIndex = 0;
  return { 
   newItemIndex: newItemIndex,
   newPageItemsCount: newPageItemsCount
  };
 },
 isThumbnailOrFilterViewMode: function() {
  return this.viewMode == FileManagerConsts.ViewMode.Thumbnail || this.GetIsFilterViewActive();
 },
 isDetailsViewMode: function() {
  return this.viewMode == FileManagerConsts.ViewMode.Grid && !this.GetIsFilterViewActive();
 },
 isThumbnailModeVirtScrollEnabled: function() {
  return this.isThumbnailOrFilterViewMode() && this.isVirtScrollEnabled();
 },
 isDetailsModeVirtScrollEnabled: function() {
  return !this.isThumbnailOrFilterViewMode() && this.isVirtScrollEnabled();
 },
 OnFilesAreaRMBClick: function(evt) {
  if(ASPxClientUtils.safari && this.getKeyModifier(evt) == FileManagerConsts.ModifierKey.Ctrl) {
   ASPxClientUtils.PreventEventAndBubble(evt);
   return;
  }
  this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
  var file = this.getClickedItem(evt);
  if(file) {
   if(ASPxClientUtils.ArrayIndexOf(this.getSelectedItems(), file) == -1)
    this.OnItemClick(file, this.getKeyModifier(evt));
  } else
   this.SetActiveArea(FileManagerConsts.SelectedArea.None);
  this.ShowContextMenu(evt);
 },
 onItemsAreaFocus: function() {
  if(this.getSelectedItems().length === 0) {
   this.forEachItem(function(item) {
    item.Select();
    return true;
   });
  }
  this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
 },
 onThumbnailViewFilesAreaItemDblClick: function(item, evt) {
  if(this.elements.getCheckBoxByEvt(evt))
   return;
  this.TryOpenItem(item);
 },
 onFilesGridViewRowDblClick: function(s, e) {
  this.onFilesGridViewRowDblClickInternal(null, e.visibleIndex);
 },
 onFilesGridViewRowDblClickInternal: function(item, visibleIndex) {
  if(this.createMode)
   this.DoCreate();
  else {
   if(!item)
    item = this.items[this.GetFilesGridView().GetRowKey(visibleIndex)];
   this.TryOpenItem(item);
  }
 },
 onFilesGridViewFocusedRowChanged: function(s, e) {
  if(this.inCallback)
   return;
  var rowIndex = s.GetFocusedRowIndex();
  if(rowIndex == -1)
   return;
  var item = this.items[s.GetRowKey(rowIndex)];
  if(this.allowMultiSelect)
   item.focus();
  else {
   var selectedKeys = s.GetSelectedKeysOnPage();
   for(var selKey, i = 0; selKey = selectedKeys[i]; i++) {
    if(selKey != item.id)
     s.UnselectRowOnPage(this.items[selKey].index);
   }
   item.Select();
  }
 },
 onFilesGridViewSelectionChanged: function(s, e) {
  if(!this.allowMultiSelect || this.inCallback)
   return;
  if(this.createMode)
   this.DoCreate();
  if(e.visibleIndex == -1 && e.isAllRecordsOnPage) {
   this.forEachItem(function(item) {
    if(item.GetVisible())
     item.SetSelected(e.isSelected);
   });
  }
  else {
   var itemId = s.GetRowKey(e.visibleIndex);
   var item = this.items[itemId];
   if(item && item.GetVisible())
    item.SetSelected(e.isSelected);
  }
  if(this.showSelectAllCheckbox)
   s.UpdateFileManagerSelectAllCheckboxesState();
  this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
 },
 onFilesGridViewColumnResized: function(s, e) {
  this.UpdateClientStateCookie();
 },
 OnFoldersContainerClick: function(evt) {
  this.SetActiveArea(FileManagerConsts.SelectedArea.Folders);
 },
 OnFoldersContainerRMBClick: function(evt) {
  var sourceElement = ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(evt), this.elements.GetFoldersNodeContentElementTagName());
  if(sourceElement) {
   while(!sourceElement.id)
    sourceElement = sourceElement.parentNode;
   var treeView = this.GetTreeView();
   var node = treeView.rootNode.GetNodeByContentElementID(sourceElement.id);
   if(!node)
    return;
   if(node !== this.tree.getSelectedNode()) {
    this.tree.setSelectedNodeInView(node);
    this.OnFolderClick(node);
    this.contextMenuEvt = evt;
    ASPx.Evt.PreventEventAndBubble(evt);
   } else
    this.ShowContextMenu(evt);
  }
 },
 OnSplitterPaneResizeCompleted: function() {
  this.UpdateClientStateCookie();
 },
 OnRenameInputKeyDown: function(evt) {
  switch (ASPx.Evt.GetKeyCode(evt)) {
   case ASPx.Key.Enter:
    if(this.renameMode || this.createInFileAreaMode)
     this.DoRename();
    this.SetActiveArea(FileManagerConsts.SelectedArea.None);
    break;
   case ASPx.Key.Esc:
    this.HideRenameInput();
    this.HideCreateHelperElement();
    if(this.isDetailsModeVirtScrollEnabled())
     this.GetFilesGridView().scrollToPageEnd();
    ASPx.Evt.PreventEvent(evt);
    this.Focus();
    break;
   case ASPx.Key.Tab:
    this.DoRename();
    this.SetActiveArea(FileManagerConsts.SelectedArea.None);
    break;
  }
 },
 getKeyModifier: function(evt) {
  if(evt.shiftKey)
   return FileManagerConsts.ModifierKey.Shift;
  if(evt.ctrlKey)
   return FileManagerConsts.ModifierKey.Ctrl;
  if(ASPx.Browser.MacOSPlatform && evt.metaKey)
   return FileManagerConsts.ModifierKey.Meta;
  return FileManagerConsts.ModifierKey.None;
 },
 getClickedItem: function(evt) {
  if(this.isDetailsViewMode()) {
   var grid = this.GetFilesGridView();
   var row = grid.getItemByHtmlEvent(evt);
   if(!row)
    return null;
   return this.items[grid.GetRowKey(grid.getItemIndex(row.id))];
  } else {
   var sourceElement = ASPx.GetParentByPartialClassName(ASPx.Evt.GetEventSource(evt), this.elements.GetFileClassName());
   while(sourceElement && !sourceElement.id)
    sourceElement = sourceElement.parentNode;
   return sourceElement ? this.itemElementsIds[sourceElement.id] : null;
  }
 },
 raiseEventWithArgsInternal: function(eventName, args) {
  var evt = this[eventName];
  if(!evt.IsEmpty())
   evt.FireEvent(this, args);
  return args;
 },
 raiseSelectedFileOpenedEvent: function(file) {
  var args = new ASPxClientFileManagerFileOpenedEventArgs(file);
  args.processOnServer = this.processOpenedEventOnServer;
  this.raiseEventWithArgsInternal("SelectedFileOpened", args);
  if(args.processOnServer)
   this.SendPostBack(ASPxClientFileManagerCallbackCommand.SelectedFileOpened);
 },
 raiseFocusedItemChangedEvent: function(item) {
  if(!this.allowMultiSelect)
   return;
  var args = new ASPxClientFileManagerFocusedItemChangedEventArgs(item, item.name, item.GetFullName());
  this.raiseEventWithArgsInternal("FocusedItemChanged", args);
 },
 raiseSelectedFileChangedEvent: function(file) {
  if(!this.allowMultiSelect)
   this.raiseEventWithArgsInternal("SelectedFileChanged", new ASPxClientFileManagerFileEventArgs(file));
 },
 raiseSelectionChanged: function(item, isSelected) {
  var args = new ASPxClientFileManagerSelectionChangedEventArgs(item, item.id, item.GetFullName(), isSelected);
  this.raiseEventWithArgsInternal("SelectionChanged", args);
 },
 raiseCurrentFolderChangedEvent: function() {
  var args = new ASPxClientFileManagerCurrentFolderChangedEventArgs(this.getFolderName(), this.GetCurrentPath());
  this.raiseEventWithArgsInternal("CurrentFolderChanged", args);
 },
 raiseFileEditingEvent: function(eventName, item) {
  var arg = new ASPxClientFileManagerItemEditingEventArgs(item.GetFullName(), item.name, item.isFolder);
  arg = this.raiseEventWithArgsInternal(eventName, arg);
  return !arg.cancel;
 },
 raiseFolderEditingEvent: function(eventName) {
  var arg = new ASPxClientFileManagerItemEditingEventArgs(this.GetCurrentPath(), this.getFolderName(), true);
  arg = this.raiseEventWithArgsInternal(eventName, arg);
  return !arg.cancel;
 },
 raiseItemDeleting: function(item) {
  return this.raiseFileEditingEvent("ItemDeleting", item);
 },
 raiseFolderDeleting: function() {
  return this.raiseFolderEditingEvent("ItemDeleting");
 },
 raiseItemMoving: function(file) {
  return this.raiseFileEditingEvent("ItemMoving", file);
 },
 raiseFolderMoving: function() {
  return this.raiseFolderEditingEvent("ItemMoving");
 },
 raiseItemCopying: function(item) {
  return this.raiseFileEditingEvent("ItemCopying", item);
 },
 raiseFolderCopying: function() {
  return this.raiseFolderEditingEvent("ItemCopying");
 },
 raiseFolderCreating: function() {
  return this.raiseFolderEditingEvent("FolderCreating");
 },
 raiseFileRenaming: function(file) {
  return this.raiseFileEditingEvent("ItemRenaming", file);
 },
 raiseFolderRenaming: function(file) {
  return this.raiseFolderEditingEvent("ItemRenaming");
 },
 raiseFolderCreated: function() {
  var fullName = "",
   name = "";
  if(this.GetActiveArea() == FileManagerConsts.SelectedArea.Files) {
   var item = this.GetSelectedItem(FileManagerConsts.FileAreaItemTypes.Folder);
   if(item) {
    fullName = item.GetFullName();
    name = item.name;
   }
  }
  else {
   fullName = this.GetCurrentPath();
   name = this.getFolderName();
  }
  var arg = new ASPxClientFileManagerItemCreatedEventArgs(fullName, name, true);
  this.raiseEventWithArgsInternal("FolderCreated", arg);
 },
 raiseItemMoved: function() {
  var itemEventArgCreator = function(fullName, itemName, oldFolderFullName, itemIsFolder) {
   return new ASPxClientFileManagerItemMovedEventArgs(fullName, itemName, oldFolderFullName, itemIsFolder);
  };
  var itemsEventArgCreator = function(items, oldFolderFullName) {
   return new ASPxClientFileManagerItemsMovedEventArgs(items, oldFolderFullName);
  };
  this.raiseItemPositionChangedEvents("ItemMoved", "ItemsMoved", itemEventArgCreator, itemsEventArgCreator);
 },
 raiseItemCopied: function() {
  var itemEventArgCreator = function(fullName, itemName, oldFolderFullName, itemIsFolder) {
   return new ASPxClientFileManagerItemCopiedEventArgs(fullName, itemName, oldFolderFullName, itemIsFolder);
  };
  var itemsEventArgCreator = function(items, oldFolderFullName) {
   return new ASPxClientFileManagerItemsCopiedEventArgs(items, oldFolderFullName);
  };
  this.raiseItemPositionChangedEvents("ItemCopied", "ItemsCopied", itemEventArgCreator, itemsEventArgCreator);
 },
 raiseItemPositionChangedEvents: function(itemEventName, itemsEventName, itemEventArgCreator, itemsEventArgCreator) {
  var folderPath = this.GetCurrentPath();
  var items = [];
  var arg = null;
  for(var itemName, i = 0; itemName = this.changeItemPositionOldInfo.name[i]; i++) {
   var itemId = this.changeItemPositionOldInfo.id[i];
   var itemIsFolder = this.changeItemPositionOldInfo.isFolder[i];
   var item = this.items[itemId];
   if(!item)
    item = this.createOutdatedItemCore(itemId, itemName, itemIsFolder);
   items.push(item);
   var fullName = folderPath + FileManagerConsts.PathSeparator + itemName;
   arg = itemEventArgCreator(fullName, itemName, this.changeItemPositionOldInfo.oldFolderFullName, itemIsFolder);
   this.raiseEventWithArgsInternal(itemEventName, arg);
  }
  arg = itemsEventArgCreator(items, this.changeItemPositionOldInfo.oldFolderFullName);
  this.raiseEventWithArgsInternal(itemsEventName, arg);
 },
 raiseItemDeleted: function() {
  var doi = this.deleteOldInfo;
  var items = [];
  var arg = null;
  for(var i = 0, itemName; itemName = doi.name[i]; i++) {
   var itemIsFolder = this.deleteOldInfo.isFolder[i];
   var item = this.createOutdatedItemCore(this.deleteOldInfo.id[i], itemName, itemIsFolder);
   items.push(item);
   var arg = new ASPxClientFileManagerItemDeletedEventArgs(doi.oldFolderFullName + FileManagerConsts.PathSeparator + itemName, itemName, itemIsFolder);
   this.raiseEventWithArgsInternal("ItemDeleted", arg);
  }
  arg = new ASPxClientFileManagerItemsDeletedEventArgs(items);
  this.raiseEventWithArgsInternal("ItemsDeleted", arg);
 },
 raiseItemRenamed: function(oldName, item) {
  var args = new ASPxClientFileManagerItemRenamedEventArgs(item.GetFullName(), item.name, oldName, item.isFolder);
  this.raiseEventWithArgsInternal("ItemRenamed", args);
 },
 raiseFolderRenamed: function(oldName) {
  var args = new ASPxClientFileManagerItemRenamedEventArgs(this.GetCurrentPath(), this.getFolderName(), oldName, true);
  this.raiseEventWithArgsInternal("ItemRenamed", args);
 },
 raiseFileDownloading: function(file) {
  var arg = this.raiseEventWithArgsInternal("FileDownloading", new ASPxClientFileManagerFileDownloadingEventArgs(file));
  return !arg.cancel;
 },
 raiseErrorOccurred: function(commandName, errorText, errorCode) {
  return this.raiseEventWithArgsInternal("ErrorOccurred", new ASPxClientFileManagerErrorEventArgs(commandName, errorText, errorCode));
 },
 raiseErrorAlertDisplaying: function(commandName, errorText) {
  return this.raiseEventWithArgsInternal("ErrorAlertDisplaying", new ASPxClientFileManagerErrorAlertDisplayingEventArgs(commandName, errorText));
 },
 raiseFileUploading: function() {
  var folder = this.GetCurrentPath();
  var uploadControl = this.GetUploadControl();
  var arg = new ASPxClientFileManagerFilesUploadingEventArgs(folder, uploadControl.GetFileNames());
  if(!this.FilesUploading.IsEmpty())
   this.FilesUploading.FireEvent(this, arg);
  else {
   arg = new ASPxClientFileManagerFileUploadingEventArgs(folder, uploadControl.GetFileName());
   if(!this.FileUploading.IsEmpty())
    this.FileUploading.FireEvent(this, arg);
  }
  return !arg.cancel;
 },
 raiseFileUploaded: function(fileInfos) {
  var arg = null;
  for(var fileInfo, i = 0; fileInfo = fileInfos[i]; i++) {
   var folder = this.findUploadFolderPath(fileInfo.index);
   arg = new ASPxClientFileManagerFileUploadedEventArgs(folder, fileInfo.name);
   this.raiseEventWithArgsInternal("FileUploaded", arg);
  }
  for(var stateItem, i = 0; stateItem = this.uploadSessionInfo.state[i]; i++) {
   var nextStateItem = this.uploadSessionInfo.state[i + 1];
   var folder = stateItem.path;
   var fileNames = [];
   for(var fileInfo, j = 0; fileInfo = fileInfos[j]; j++) {
    if(fileInfo.index >= stateItem.startFileIndex && (!nextStateItem || fileInfo.index < nextStateItem.startFileIndex))
     fileNames.push(fileInfo.name);
   }
   arg = new ASPxClientFileManagerFilesUploadedEventArgs(folder, fileNames);
   this.raiseEventWithArgsInternal("FilesUploaded", arg);
  }
 },
 raiseCustomCommand: function(commandName) {
  this.raiseEventWithArgsInternal("CustomCommand", new ASPxClientFileManagerCustomCommandEventArgs(commandName));
 },
 raiseToolbarUpdating: function(activeAreaName) {
  this.raiseEventWithArgsInternal("ToolbarUpdating", new ASPxClientFileManagerToolbarUpdatingEventArgs(activeAreaName));
 },
 raiseHighlightItemTemplate: function(filterValue, itemName, templateElement, highlightCssClassName) {
  this.raiseEventWithArgsInternal("HighlightItemTemplate", new ASPxClientFileManagerHighlightItemTemplateEventArgs(filterValue, itemName, templateElement, highlightCssClassName));
 },
 SetVisible: function(visible) {
  ASPxClientControl.prototype.SetVisible.call(this, visible);
  if(visible) {
   setTimeout(function() {
    this.AdjustControl();
   }.aspxBind(this), 0);
  }
 },
 GetLastKeyPart: function(key) {
  var parts = key.split(".");
  return parts[parts.length - 1];
 },
 GetStateItem: function(key) {
  var parts = key.split(".");
  var currentItem = this.getStateObject();
  for(var i = 0; i < parts.length - 1; i++) {
   var _key = parts[i];
   if(!currentItem[_key])
    currentItem[_key] = {};
   currentItem = currentItem[_key];
  }
  return currentItem;
 },
 checkHasInitialState: function() {
  if(this.hasInitialState === undefined)
   this.hasInitialState = !!this.stateObject;
  return this.hasInitialState;
 },
 getStateObject: function() {
  this.checkHasInitialState();
  if(!this.stateObject) 
   this.stateObject = { };
  return this.stateObject;
 },
 GetStateField: function(key) {
  var stateItem = this.GetStateItem(key);
  return stateItem[this.GetLastKeyPart(key)];
 },
 UpdateStateField: function(key, value) {
  if(!this.enabled) return;
  var stateItem = this.GetStateItem(key);
  stateItem[this.GetLastKeyPart(key)] = value;
 },
 DropStateField: function(key) {
  if(!this.enabled) return;
  var stateItem = this.GetStateItem(key);
  delete stateItem[this.GetLastKeyPart(key)];
 },
 SendCallback: function(commandId, args, skipScrollSaving, onSuccess) {
  this.inCallback = true;
  this.callbackOwner = null;
  this.KeepClientState();
  if(this.isThumbnailModeVirtScrollEnabled() && !skipScrollSaving)
   this.saveItemsScrollPosition();
  var callbackArg = this.GetArgumentsString(commandId, args);
  if(!this.autoPostBack) {
   if(commandId != ASPxClientFileManagerCallbackCommand.GetAllItems)
    this.ShowLoadingElements();
   if(this.isDetailsViewMode() && this.IsCommandNeedFilesRefresh(commandId)) {   
    this.savedCallbackArg = callbackArg;
    this.GetFilesGridView().Refresh();
   }
   else
    this.CreateCallback(callbackArg, commandId, onSuccess);
  }
  else
   this.SendPostBack(callbackArg);
 },
 IsCommandNeedFilesRefresh: function(commandId) {
  return commandId != ASPxClientFileManagerCallbackCommand.ShowFolderBrowserDialog && commandId != ASPxClientFileManagerCallbackCommand.CustomCallback &&
      commandId != ASPxClientFileManagerCallbackCommand.GetAllItems;
 },
 GetArgumentsString: function(commandId, args) {
  var callbackString = commandId;
  if(args)
   callbackString += FileManagerConsts.CallbackArgumentSeparator + ASPx.Json.ToJson(args);
  return callbackString;
 },
 GetItemsCallbackInfo: function(items) {
  return items.map(function(i) { return this.GetClientItemInfo(i); }.bind(this));
 },
 GetClientItemInfo: function(item) {
  var info = { name: item.name, id: item.formattedId, isFolder: item.isFolder };
  if(item.parentInfo)
   info.parent = item.parentInfo;
  return info;
 },
 SendTreeViewCallback: function(treeView, callbackString) {
  this.ShowLoadingDiv();
  this.KeepClientState();
  var folderPath = "";
  var folderIdPath = null;
  var commandId = null;
  if(this.folderExpandingNode) {
   folderPath = this.GetFoldersPath(this.folderExpandingNode, true);
   folderIdPath = this.GetFoldersPathArray(this.folderExpandingNode, false, true);
   this.folderExpandingNode = null;
  }
  var args = {
   parentPath: folderPath,
   parentIdPath: folderIdPath,
   callbackString: callbackString
  };
  if(this.delayedSetCurrentFolderPath !== undefined) {
   commandId = ASPxClientFileManagerCallbackCommand.ChangeFolderInTreeView;
   args.path = this.delayedSetCurrentFolderPath;
   args.idPath = this.delayedSetCurrentFolderIdPath;
  }
  else {
   this.callbackOwner = treeView;
   commandId = treeView.isFolderBrowserFolders
    ? ASPxClientFileManagerCallbackCommand.FolderBrowserTreeView    
    : ASPxClientFileManagerCallbackCommand.FoldersTreeView;
  }
  var callbackArg = this.GetArgumentsString(commandId, args);
  this.CreateCallback(callbackArg, commandId);
 },
 SendGridViewCallback: function(gridView, callbackString, command) {
  this.KeepClientState();
  if(command == ASPxClientGridViewCallbackCommand.ApplyHeaderColumnFilter || command == ASPxClientGridViewCallbackCommand.ApplyFilter)
   this.needResetSelection = true;
  if(command == "FUNCTION")
   this.skipClearItems = true;
  this.ShowLoadingElements();
  if(this.savedCallbackArg != null) {
   var argPrefix = this.savedCallbackArg + FileManagerConsts.CallbackLinkedArgumentSeparator;
   this.savedCallbackArg = null;
   this.CreateCallback(argPrefix + ASPxClientFileManagerCallbackCommand.GridView + FileManagerConsts.CallbackArgumentSeparator + callbackString, ASPxClientFileManagerCallbackCommand.GridView);
  }
  else {
   var commandId = command == ASPxClientGridViewCallbackCommand.GotoPage ? ASPxClientFileManagerCallbackCommand.GridViewVirtualScrolling : ASPxClientFileManagerCallbackCommand.GridView;
   this.virtScroll.inCallback = commandId == ASPxClientFileManagerCallbackCommand.GridViewVirtualScrolling;
   this.CreateCallback(commandId + FileManagerConsts.CallbackArgumentSeparator + callbackString, commandId);
  }
 },
 ClearCallbackOwner: function() {
  if(this.callbackOwner)
   this.callbackOwner.HideLoadingElements();
  this.callbackOwner = null;
 },
 OnCallback: function(result) {
  if(this.callbackOwner)
   this.callbackOwner.OnCallback(result);
  else
   this.ProcessCommandResult(result);
 },
 ProcessCommandResult: function(result) {
  this.inCommandProcessing = true;
  if(result.apiCommandResult)
   this.createApiCommandItems(result.apiCommandResult);
  var hasChangeFileListModeData = ASPx.IsExists(result.changeFileListModeData);
  if(hasChangeFileListModeData) {
   this.ChangeFileListModeOnCallback(result.changeFileListModeData);
   this.needInitializeAfterCallback = true;
  }
  this.UpdateFilterState(result.filterData);
  if(result.styles)
   this.SetStyles(result.styles);
  if(result.selectedArea != undefined && !result.apiCommandResult)
   this.SetActiveArea(result.selectedArea ? FileManagerConsts.SelectedArea.Files : FileManagerConsts.SelectedArea.Folders);
  if(result.items && !this.skipClearItems) {
   this.needApplyState = this.getSelectedItems().length > 0 && result.isNewFileList ? 2 : 1;
   this.ClearItems(result.isNewFileList, hasChangeFileListModeData);
   this.needResetSelection = this.needResetSelection || result.isNewFileList;
   if(this.isVirtScrollEnabled()) {
    if(ASPx.IsExists(result.virtScrollItemIndex)) {
     if(result.selectedItems && this.isThumbnailOrFilterViewMode())
      this.scrollToFirstSelectedItem = true;
     this.virtScroll.itemIndex = result.virtScrollItemIndex;
     this.virtScroll.itemsCount = result.itemsCount;
     this.virtScroll.pageItemsCount = result.virtScrollPageItemsCount;
     if(ASPx.IsExists(result.virtScrollResetState))
      this.virtScroll.lastPageScrollPos = this.getStartItemsScrollPos();
    }
   }
   this.customThumbnails = result.thumbnails;
   if(result.itemsRender)
    this.elements.GetItemsContainer().innerHTML = result.itemsRender;
   this.CreateItems(result.items, true, result.isNewFileList);
   if(this.isThumbnailModeVirtScrollEnabled()) {
    this.updateVirtScrollCore();
    this.restoreItemsScrollPosition();
   }
   if(typeof (result.folderRights) == "string")
    this.UpdateFolderRights(result.folderRights);
   if(result.filesRules)
    this.UpdateFilesRules(result.filesRules);
   this.allowUploadToCurrentFolder = result.allowUpload && this.folderRights.allowUpload && !this.GetIsRecursiveFilterApplied();
   this.UpdateUploadPanelVisibility();
   this.SetSplitterUploadPaneSize();
   this.UpdateToolbars();
   if(this.contextMenuEvt) {
    this.ShowContextMenu(this.contextMenuEvt);
    this.contextMenuEvt = null;
   }
  }
  if(result.gridViewResult) {
   this.gridLayoutChangeCallbackProcess = !(result.isNewFileList || this.skipClearItems);
   this.GetFilesGridView().OnCallback(result.gridViewResult);
   if(!this.isVirtScrollEnabled())
    this.updateGridFilterView();
   this.needGridViewEndCallback = true;
   this.filterView.DropFilterView();
  }
  if(result.foldersRender)
   this.RefreshFoldersOnCallback(result.foldersRender);
  if(result.selectedItems)
   this.needSelectItems = result.selectedItems;
  if(result.treeViewResult) {
   this.GetTreeView().OnCallback(result.treeViewResult);
   this.needTreeViewEndCallback = true;
  }
  if(ASPx.IsExists(result.changeCurrentFolder)) {
   this.currentPath = result.changeCurrentFolder;
   this.currentIdPath = result.changeCurrentFolderIdPath;
   this.KeepClientState();
  }
  this.StartCommandProcessing(result);
  if(this.showPath && !result.apiCommandResult && (!this.showAppRelativePath || result.path))
   this.UpdatePath(result.path);
  if(result.currentFolderId !== undefined)
   this.currentFolderId = result.currentFolderId;
  this.skipClearItems = null;
 },
 UpdateFilterState: function(data) {
  if(!data) return;
  if(ASPx.IsExists(data.filterView))
   this.UpdateStateField(FileManagerConsts.StateField.FilterView, data.filterView);
  this.UpdateStateField(FileManagerConsts.StateField.ItemFilter, data.filter);   
  this.filterBox.Update();
 },
 ChangeFileListModeOnCallback: function(data) {
  if(!data) return;
  this.viewMode = data.viewMode;
  this.UpdateFileListRenderOnCallback(data);
  if(ASPx.IsExists(data.noThumbnailImage))
   this.noThumbnailImage = data.noThumbnailImage;
  if(ASPx.IsExists(data.isThumbnailsViewFileAreaItemTemplate))
   this.isThumbnailsViewFileAreaItemTemplate = data.isThumbnailsViewFileAreaItemTemplate;
  if(ASPx.IsExists(data.filterBoxMode))
   this.filterBoxMode = data.filterBoxMode;
  if(ASPx.IsExists(data.filterFileListViewMode))
   this.filterFileListViewMode = data.filterFileListViewMode;
  this.updateFocusInputVisibility();
 },
 UpdateFileListRenderOnCallback: function(data) {
  var detailsView = !!data.gridViewRender;
  this.elements.GetItemsPaneContainer().innerHTML = detailsView ? data.gridViewRender : "";
  if(!detailsView) {
   var grid = this.GetFilesGridView();
   if(grid)
    ASPx.GetControlCollection().Remove(grid);
  }
 },
 updateGridFilterView: function() {
  if(this.filterBox && this.gridLayoutChangeCallbackProcess) {
   this.GetFilesGridView().EnsureRowKeys();
   this.gridLayoutChangeCallbackProcess = false;
  }
 },
 StartCommandProcessing: function(result) {
  var commandName;
  switch (result.command) {
   case ASPxClientFileManagerCallbackCommand.ShowCreateFolderEditorInTreeView:
    if(result.isSuccess) {
     this.createMode = true;
     this.prepareCreateNode = true;
     this.UpdateToolbars();
    }
    break;
   case ASPxClientFileManagerCallbackCommand.CreateFolder:
    commandName = ASPxClientFileManagerCommandConsts.Create;
    if(result.isSuccess) {
     this.needFolderCreatedRaise = true;
     this.needFoldersScroll = this.GetActiveArea() == FileManagerConsts.SelectedArea.Folders;
    }
    break;
   case ASPxClientFileManagerCallbackCommand.Refresh:
    this.selectedArea = this.foldersHidden ? FileManagerConsts.SelectedArea.Files : FileManagerConsts.SelectedArea.Folders;
    this.UpdateToolbars();
    break;
   case ASPxClientFileManagerCallbackCommand.RenameItem:
    commandName = ASPxClientFileManagerCommandConsts.Rename;
    if(result.isSuccess) {
     this.needItemRenamedRaise = true;
     this.needFoldersScroll = this.GetActiveArea() == FileManagerConsts.SelectedArea.Folders;
    }
    break;
   case ASPxClientFileManagerCallbackCommand.ShowFolderBrowserDialog:
    if(result.isSuccess) {
     this.ShowFolderBrowserPopup(result.folderBrowserFoldersRender);
     this.needInitFolderBrowserFolders = true;
    }
    break;
   case ASPxClientFileManagerCallbackCommand.MoveItems:
    commandName = ASPxClientFileManagerCommandConsts.Move;
    if(result.isSuccess) {
     this.needItemMovedRaise = true;
     this.needFoldersScroll = true;
    }
    break;
   case ASPxClientFileManagerCallbackCommand.CopyItems:
    commandName = ASPxClientFileManagerCommandConsts.Copy;
    if(result.isSuccess) {
     this.needItemCopiedRaise = true;
     this.needFoldersScroll = true;
    }
    break;
   case ASPxClientFileManagerCallbackCommand.DeleteItems:
    commandName = ASPxClientFileManagerCommandConsts.Delete;
    if(result.isSuccess)
     this.raiseItemDeleted();
    break;
   case ASPxClientFileManagerCallbackCommand.ChangeFolderInTreeView:
    if(!result.isSuccess) {
     this.delayedSetCurrentFolderPath = undefined;
     this.delayedSetCurrentFolderIdPath = undefined;
     this.delayedCallbackFunction = undefined;
    }
    else {
     this.needCurrentFolderChangedRaise = true;
     this.needFoldersScroll = true;
    }
    break;
  }
  if(result && !result.isSuccess) {
   this.folderDialogCommand = null;
   this.showError(commandName, result.editErrorText, result.editErrorCode);
  }
 },
 OnCallbackFinalized: function() {
  if(this.callbackOwner)
   this.callbackOwner.OnCallbackFinalized();
  else
   this.OnCallbackFinalizedCore();
  this.inCallback = false;
  this.virtScroll.inCallback = false;
  if(this.delayedExpandNode) {
   this.delayedExpandNode.SetExpanded(!this.delayedExpandNode.GetExpanded());
   this.delayedExpandNode = null;
  }
 },
 OnCallbackFinalizedCore: function() {
  if(this.needInitializeAfterCallback)
   this.InitializeAfterCallback();
  if(this.isVirtScrollEnabled())
   this.updateGridFilterView();
  if(this.needGridViewEndCallback) {
   this.GetFilesGridView().OnCallbackFinalized();
   this.needGridViewEndCallback = false;
  }
  if(this.needTreeViewEndCallback) {
   this.GetTreeView().OnCallbackFinalized();
   this.needTreeViewEndCallback = false;
  }
  if(this.delayedSetCurrentFolderPath !== undefined) {
   var node = this.GetTreeView().GetNodeByName(this.currentFolderId);
   if(node) {
    this.tree.setSelectedNodeInView(node);
    this.tree.setSelectedNode(node);
    this.expandNodeRecursive(node);
   }
   this.delayedSetCurrentFolderPath = undefined;
   this.delayedSetCurrentFolderIdPath = undefined;
  }
  if(this.createMode)
   this.PrepareCreateNode();
  this.EndCommandProcessing();
  if(this.showPath && !this.showAppRelativePath)
   this.UpdatePath();
  if(this.filterBox)
   this.filterBox.OnCallbackFinalized();
  if(this.isDetailsViewMode() && this.showSelectAllCheckbox)
   this.GetFilesGridView().UpdateFileManagerSelectAllCheckboxesState();
 },
 EndCommandProcessing: function() {
  if(!this.foldersHidden)
   this.tree.saveSelectedNodeFromView();
  if(this.needFoldersScroll) {
   this.setSplitterFolderContainerPaneScroll();
   this.needFoldersScroll = false;
  }
  if(this.needInitFolderBrowserFolders) {
   this.GetFolderBrowserTreeView().InitFileManagerCallbacks(this, true);
   this.needInitFolderBrowserFolders = false;
  }
  if(this.needApplyState) {
   if(this.needApplyState == 2)
    this.raiseSelectedFileChangedEvent(null);
   this.ApplyControlState(true);
   this.needApplyState = null;
  }
  if(!this.needResetSelection && this.needSelectItems) {
   var selectedItems = this.selectItems(this.needSelectItems);
   if(this.scrollToFirstSelectedItem) {
    setTimeout((function() { this.scrollToItem(this.items[selectedItems[0]]); }).aspxBind(this), 0);
    this.scrollToFirstSelectedItem = false;
   }
  }
  if(this.needResetSelection) {
   this.resetSelection(this.needSelectItems);
   if(this.isThumbnailModeVirtScrollEnabled() && !this.allowMultiSelect)
    this.scrollToSelection(this.needSelectItems);
   this.needResetSelection = false;
   this.needSelectItems = null;
  }
  if(this.needFocusItemName) {
   var item = this.items[this.needFocusItemName];
   if(item) {
    if(this.allowMultiSelect)
     item.focus(true, true);
    else
     item.Select(true);
   }
   this.needFocusItemName = "";
  }
  if(this.needSetActiveItemsArea) {
   this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
   this.needSetActiveItemsArea = false;
  }
  if(this.needInitFolders) {
   this.InitializeFoldersTreeView();
   this.needInitFolders = false;
  }
  if(this.needItemRenamedRaise) {
   var item = this.GetSelectedItem();
   if(item == null)
    this.raiseFolderRenamed(this.renameOldName);
   else
    this.raiseItemRenamed(this.renameOldName, item);
   this.needItemRenamedRaise = false;
  }
  if(this.needItemMovedRaise) {
   this.raiseItemMoved();
   this.needItemMovedRaise = false;
  }
  if(this.needItemCopiedRaise) {
   this.raiseItemCopied();
   this.needItemCopiedRaise = false;
  }
  if(this.needFolderCreatedRaise) {
   this.raiseFolderCreated();
   this.needFolderCreatedRaise = false;
  }
  if(this.needCurrentFolderChangedRaise) {
   this.raiseCurrentFolderChangedEvent();
   this.needCurrentFolderChangedRaise = false;
  }
  if(this.delayedCallbackFunction !== undefined) {
   this.delayedCallbackFunction.call();
   this.delayedCallbackFunction = undefined;
  }
  if(this.apiCommandItems)
   window.setTimeout(this.onApiCommandCallback.aspxBind(this), 0);
  else {
   this.UpdateToolbars();
   this.KeepClientState();
   if(this.breadCrumbsEnabled)
    this.breadCrumbs.refresh();
  }
  this.inCommandProcessing = false;
 },
 onApiCommandCallback: function() {
  var callback = this.apiCommandCallback,
   items = this.apiCommandItems;
  this.apiCommandCallback = null;
  this.apiCommandItems = null;
  callback(items);
 },
 UpdatePath: function(path) {
  var textBox = this.GetToolbarPathTextBox();
  if(textBox) {
   var path = this.showAppRelativePath ? path : this.GetCurrentPath();
   if(this.createMode)
    path += this.newFolderName;
   textBox.SetText(path);
  }
 },
 RefreshFoldersOnCallback: function(render) {
  this.elements.GetFoldersContainer().innerHTML = render;
  if(this.allowMove)
   this.UpdateTollbarStandardItem(FileManagerConsts.ToolbarName.Move, this.IsMoveAvailable());
  this.needInitFolders = true;
 },
 InitializeAfterCallback: function() {
  if(this.isDetailsViewMode())
   this.InitializeFilesGridView();
  if(this.enabled)
   this.initializeFilesAreaEventHandlers();
  this.needInitializeAfterCallback = false;
 },
 GetSplitter: function() {
  return this.getInnerControl(FileManagerConsts.SplitterPostfix);
 },
 GetUploadControl: function() {
  var splitterPostfix = this.hideUploadPanel ? "" : FileManagerConsts.SplitterPostfix;
  return this.getInnerControl(splitterPostfix + FileManagerConsts.UploadPostfix);
 },
 GetToolbar: function() {
  return this.getInnerControl(FileManagerConsts.SplitterPostfix + FileManagerConsts.ToolbarPostfix);
 },
 GetToolbarPathTextBox: function() {
  var name = this.elements.getToolbarPathElementId();
  return name ? ASPx.GetControlCollection().Get(name) : null;
 },
 GetToolbarFilterTextBox: function() {
  var name = this.elements.getToolbarFilterElementId();
  return name ? ASPx.GetControlCollection().Get(name) : null;
 },
 GetContextMenu: function() { 
  return this.getInnerControl(FileManagerConsts.ContextMenuPostfix);
 },
 GetTreeView: function() {
  return this.getInnerControl(FileManagerConsts.SplitterPostfix + FileManagerConsts.FoldersPostfix);
 },
 GetFilesGridView: function() {
  return this.getInnerControl(FileManagerConsts.SplitterPostfix + FileManagerConsts.GridPostfix);
 },
 GetFolderBrowserPopup: function() {
  return this.getInnerControl(FileManagerConsts.FolderBrowserPopupPostfix);
 },
 GetFolderBrowserTreeView: function() {
  return this.getInnerControl(FileManagerConsts.FolderBrowserPopupPostfix + FileManagerConsts.FolderBrowserFolders);
 },
 GetUploadProgressPopup: function() {
  return this.getInnerControl(FileManagerConsts.UploadProgressPopupPostfix);
 },
 GetUploadProgressBar: function() {
  return this.getChildControl(FileManagerConsts.UploadProgressPopupPostfix + FileManagerConsts.UploadProgressBarPostfix);
 },
 GetBreadCrumbsPopup: function() {
  return this.getInnerControl(FileManagerConsts.BreadCrumbsPopupPostfix);
 },
 getFolderName: function() {
  return this.GetCurrentPath().substr(this.GetCurrentPath().lastIndexOf(FileManagerConsts.PathSeparator) + 1);
 },
 getFolderNameByNode: function(node) {
  return this.isNewFolderNode(node) ? "" : node.GetText();
 },
 getFolderIdByNode: function(node) {
  return node.name;
 },
 isNewFolderNode: function(node) {
  return node.name.indexOf("[fmNewFolderNode]") > -1;
 },
 GetCurrentPath: function(skipRootFolder, separator) {
  return this.getFullPath(this.currentPath, separator, skipRootFolder);
 },
 getFullPath: function(partialPath, separator, skipRootFolder) {
  var path = "";
  if(skipRootFolder)
   path = partialPath;
  else {
   var escapedPartialPath = partialPath ? FileManagerConsts.PathSeparator + partialPath : "";
   path = this.rootFolderName + escapedPartialPath;
  }
  if(separator && separator != FileManagerConsts.PathSeparator) {
   var regExp = new RegExp("\\" + FileManagerConsts.PathSeparator, "g");
   path = path.replace(regExp, separator);
  }
  return path;
 },
 getCurrentFolderParentPath: function() {
  var path = this.GetCurrentPath();
  path = path.slice(0, path.lastIndexOf(this.getFolderName()));
  return path == "" ? path : path.slice(0, path.length - 1);
 },
 GetFoldersPath: function(currentFolder, skipRootFolder, separator, useId) {
  var pathParts = this.GetFoldersPathArray(currentFolder, skipRootFolder, useId);
  if(!separator)
   separator = FileManagerConsts.PathSeparator;
  return pathParts.join(separator);
 },
 GetFoldersPathArray: function(currentFolder, skipRootFolder, useId) {
  var pathParts = [];
  while(currentFolder) {
   var pathPart = useId ? this.getFolderIdByNode(currentFolder) : this.getFolderNameByNode(currentFolder);
   pathParts.push(pathPart);
   currentFolder = currentFolder.parent;
  }
  pathParts = pathParts.reverse();
  if(skipRootFolder)
   pathParts = pathParts.slice(1);
  return pathParts;
 },
 getIdFromFormattedId: function(formattedId) {
  return formattedId.substr(FileManagerConsts.IdValuePrefix.AutoId.length);
 },
 isFormattedAutoIdValue: function(formattedId) {
  return formattedId.indexOf(FileManagerConsts.IdValuePrefix.AutoId) === 0;
 },
 getPathParts: function(path) {
  var result = [""];
  if(path) {
   var parts = this.splitPath(path);
   for(var i = 0; i < parts.length; i++) {
    var pathPart = this.pathCombine(result[i], parts[i]);
    result.push(pathPart);
   }
  }
  return result;
 },
 pathCombine: function(path1, path2) {
  return path1 ? path1 + FileManagerConsts.PathSeparator + path2 : path2;
 },
 KeepClientState: function() {
  this.UpdateStateField(FileManagerConsts.StateField.CurrentPath, this.getCurrentPathStateValue());
  this.UpdateStateField(FileManagerConsts.StateField.CurrentIdPath, this.currentIdPath);
  if(this.isVirtScrollEnabled()) {
   this.UpdateStateField(FileManagerConsts.StateField.VirtScrollItemIndexFieldName, this.virtScroll.itemIndex);
   this.UpdateStateField(FileManagerConsts.StateField.VirtScrollPageItemsCountFieldName, this.virtScroll.pageItemsCount);
  }
 },
 getCurrentPathStateValue: function() {
  var expandedParam = "";
  var treeView = this.GetTreeView();
  if(treeView && treeView.enabled)
   expandedParam = this.tree.getSelectedNode().GetExpanded().toString();
  var result = this.GetCurrentPath(true);
  if(expandedParam)
   result += FileManagerConsts.CallbackArgumentSeparator + expandedParam;
  return result;
 },
 GetActiveArea: function() {
  return this.selectedArea;
 },
 GetActiveAreaName: function() {
  return FileManagerConsts.SelectedAreaNames[this.GetActiveArea()];
 },
 SetActiveArea: function(selectedArea) {
  if(this.folderDialogCommand != null)
   return;
  if(selectedArea != FileManagerConsts.SelectedArea.None)
   this.lastActiveItemsArea = selectedArea;
  if(this.GetActiveArea() == selectedArea) {
   this.UpdateToolbars();
   return;
  }
  this.selectedArea = selectedArea;
  this.UpdateToolbars();
  this.DoRename();
  if(selectedArea == FileManagerConsts.SelectedArea.Folders) {
   this.UpdateFileSelectState(true);
   this.UpdateFolderSelectState(false);
  }
  if(selectedArea == FileManagerConsts.SelectedArea.Files) {
   this.UpdateFileSelectState(false);
   this.UpdateFolderSelectState(true);
  }
  if(selectedArea == FileManagerConsts.SelectedArea.None) {
   this.UpdateFileSelectState(true);
   this.UpdateFolderSelectState(true);
  }
 },
 UpdateFileSelectState: function(toInactive) {
  this.forEachItem(function(file) {
   file.UpdateSelectState(toInactive);
  }.aspxBind(this));
 },
 updateFocusedRowStyle: function(row, toInactive) {
  var grid = this.GetFilesGridView();
  if(grid)
   grid.updateFocusedRowStyle(row, toInactive);
 },
 UpdateFolderSelectState: function(toInactive) {
  var selectedNode = this.tree.getSelectedNode();
  if(selectedNode) {
   var selectedNodeEl = selectedNode.GetHtmlElement();
   if(!selectedNodeEl)
    return;
   this.UpdateFolderSelectStateCore(selectedNodeEl, toInactive);
  }
 },
 UpdateFolderSelectStateCore: function(selectedFolderElement, toInactive) {
  selectedFolderElement.className = toInactive
   ? selectedFolderElement.className.replace(this.styles.folderSelectionActiveCssClass, this.styles.folderSelectionInactiveCssClass)
   : selectedFolderElement.className.replace(this.styles.folderSelectionInactiveCssClass, this.styles.folderSelectionActiveCssClass);
 },
 ShowLoadingPanel: function() {
  var parentElement = this.virtScroll.inCallback ? this.elements.GetItemsPaneContainer() : this.GetMainElement();
  this.CreateLoadingPanelWithAbsolutePosition(parentElement, this.GetLoadingPanelOffsetElement(parentElement));
 },
 ShowLoadingDiv: function() {
  if(this.lockLoadingDiv) {
   this.lockLoadingDiv = false;
   return;
  }
  this.CreateLoadingDiv(this.GetMainElement());
 },
 GetLoadingPanelCallbackAnimationOffsetElement: function() {
  return this.elements.GetItemsPaneContainer();
 },
 GetCallbackAnimationElement: function() {
  return this.elements.GetItemsContainer() || this.elements.GetItemsPaneContainer();
 },
 UpdateToolbars: function(disableAll) {
  disableAll = disableAll ? disableAll : this.IsEditMode();
  var toolbar = this.GetToolbar();
  this.UpdateMenuStandardItems(toolbar, disableAll);
  this.raiseToolbarUpdating(FileManagerConsts.SelectedAreaNames[this.GetActiveArea()]);
 },
 UpdateTollbarStandardItem: function(name, enable) {
  this.UpdateToolbarItem(this.GetMenuStandardItemFullName(name), enable);
 },
 UpdateToolbarItem: function(name, enable) {
  this.UpdateMenuItem(this.GetToolbar(), name, enable);
 },
 UpdateMenuStandardItems: function(menu, disableAll) {
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Create, !disableAll && this.IsCreateAvailable());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Move, !disableAll && this.IsMoveAvailable());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Delete, !disableAll && this.IsDeleteAvailable());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Rename, !disableAll && this.IsRenameAvailable());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Download, !disableAll && this.IsDownloadButtonActive());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Copy, !disableAll && this.IsCopyAvailable());
  this.UpdateMenuStandardItem(menu, FileManagerConsts.ToolbarName.Upload, !disableAll && this.allowUploadToCurrentFolder);
 },
 UpdateMenuStandardItem: function(owner, name, enable) {
  this.UpdateMenuItem(owner, this.GetMenuStandardItemFullName(name), enable);
 },
 UpdateMenuItem: function(owner, name, enable) {
  if(!owner)
   return;
  var items = owner.items || owner.rootItem.items;
  for(var item, i = 0; item = items[i] ; i++) {
   if(item.name == name)
    item.SetEnabled(enable);
   if(item.items.length > 0)
    this.UpdateMenuItem(item, name, enable);
  }
 },
 GetMenuStandardItemFullName: function(name) {
  return FileManagerConsts.ToolbarStandardButtonPrefix + name;
 },
 ensureToolbarInitialized: function() {
  if(this.toolbarInitialized) return;
  var toolbar = this.GetToolbar();
  if(toolbar)
   this.elements.GetToolbarWrapper().style.width = "auto";
  this.toolbarInitialized = true;
 },
 ShowContextMenu: function(e) {
  var menu = this.GetContextMenu();
  if(menu) {
   this.UpdateMenuStandardItems(menu);
   menu.ShowInternal(e);
   if(!ASPx.TouchUIHelper.useLongTapHelper())
    ASPx.Evt.PreventEventAndBubble(e);
  }
 },
 UpdateUploadPanelVisibility: function() {
  if(!this.allowUpload) return;
  if(!this.enabled) return;
  var pane = this.elements.GetUploadPanelPane();
  var visible = this.allowUploadToCurrentFolder;
  this.GetUploadControl().SuppressFileDialog(!visible);
  if(this.hideUploadPanel)
   return;
  if(visible)
   pane.Expand();
  else
   pane.CollapseForward();
  ASPx.SetElementDisplay(this.elements.GetUploadPanelElement(), visible);
  this.GetUploadControl().SetVisible(visible);
 },
 IsEditOperationAvailable: function(rule, multiselect) {
  switch (this.GetActiveArea()) {
   case FileManagerConsts.SelectedArea.Folders:
    var selectedNode = this.tree.getSelectedNode();
    return selectedNode && selectedNode.parent && this.folderRights[rule];
   case FileManagerConsts.SelectedArea.Files:
    var items = this.getSelectedItems();
    if(items.length == 0 || (!multiselect && items.length > 1))
     return false;
    for(var item, i = 0; item = items[i]; i++) {
     if(!item.rights[rule])
      return false;
    }
    return true;
  }
  return false;
 },
 IsDeleteAvailable: function() {
  if(!this.allowDelete)
   return false;
  return this.IsEditOperationAvailable("allowDelete", true);
 },
 TryDelete: function() {
  this.UpdateToolbars(true);
  var successCommand = false;
  switch (this.GetActiveArea()) {
   case FileManagerConsts.SelectedArea.Files:
    var selectedItems = this.getSelectedItems();
    var deleteItems = [];
    if(selectedItems.length > 0) {
     for(var item, i = 0; item = selectedItems[i]; i++) {
      if(this.raiseItemDeleting(item))
       deleteItems.push(item);
     }
    }
    if(deleteItems.length > 0) {
     if(confirm(this.deleteConfirmText.replace('{0}', this.joinItemNames(deleteItems, ", ")))) {
      this.DoDelete(deleteItems);
      successCommand = true;
     }
    }
    break;
   case FileManagerConsts.SelectedArea.Folders:
    var folder = this.GetCurrentPath();
    if(this.raiseFolderDeleting() && confirm(this.deleteConfirmText.replace('{0}', folder))) {
     this.DoDelete();
     successCommand = true;
    }
    break;
  }
  this.UpdateToolbars();
  return successCommand;
 },
 DoDelete: function(items) {
  var isFolderAreaCommand = this.GetActiveArea() == FileManagerConsts.SelectedArea.Folders;
  this.deleteOldInfo = {
   id: [],
   name: [],
   oldFolderFullName: isFolderAreaCommand ? this.getCurrentFolderParentPath() : this.GetCurrentPath(),
   isFolder: []
  };
  this.fillEditOperationOldInfo(items, isFolderAreaCommand, this.deleteOldInfo);
  var args = { isFolderArea: isFolderAreaCommand };  
  if(!isFolderAreaCommand)
   args.items = this.GetItemsCallbackInfo(items);  
  this.SendCallback(ASPxClientFileManagerCallbackCommand.DeleteItems, args);
 },
 IsRenameAvailable: function() {
  if(!this.allowRename)
   return false;
  return this.IsEditOperationAvailable("allowRename", false);
 },
 TryRename: function() {
  this.HideRenameInput();
  switch (this.GetActiveArea()) {
   case FileManagerConsts.SelectedArea.Files:
    var files = this.getSelectedItems();
    if(files.length == 1 && this.raiseFileRenaming(files[0])) {
     this.SetVisibleRenameInputInFileArea(files[0], true);
     return true;
    }
    break;
   case FileManagerConsts.SelectedArea.Folders:
    var folderNode = this.tree.getSelectedNode();
    if(folderNode && this.raiseFolderRenaming())
     return this.TrySetVisibleRenameInputInFoldersArea(folderNode, true);
    break;
  }
  return false;
 },
 HideRenameInput: function() {
  if(!this.allowRename)
   return;
  var input = this.elements.GetRenameInputElement();
  this.renameMode = false;
  this.UpdateToolbars();
  switch (this.elements.GetRenameElementArea()) {
   case FileManagerConsts.SelectedArea.Files:
    var item = this.items[input["data-fileName"]];
    if(item)
     this.SetVisibleRenameInputInFileArea(item, false);
    break;
   case FileManagerConsts.SelectedArea.Folders:
    var node = this.GetTreeView().GetRootNode().GetNodeByContentElementID(input.parentNode.id);
    if(node)
     this.TrySetVisibleRenameInputInFoldersArea(node, false);
    break;
  }
 },
 DoRename: function() {
  if(!this.renameMode && !this.createInFileAreaMode)
   return;
  var newName = this.elements.GetRenameInputElement().value;
  this.elements.GetRenameInputElement().value = "";
  if(this.ValidateName(newName, ASPxClientFileManagerCommandConsts.Rename)) {
   if(this.createInFileAreaMode) {
    this.DoCreateCore(newName, false);
    this.createInFileAreaMode = false;
   } else if(this.renameMode) {
    switch (this.elements.GetRenameElementArea()) {
     case FileManagerConsts.SelectedArea.Files:
      var items = this.getSelectedItems();
      var item = items[0];
      if(items.length == 1 && item.name != newName) {
       this.renameOldName = item.name;
       var args = { isFolderArea: false, name: newName, id: item.formattedId, isFolder: item.isFolder };
       if(item.parentInfo)
        args.parent = item.parentInfo;
       this.SendCallback(ASPxClientFileManagerCallbackCommand.RenameItem, args);
      }
      break;
     case FileManagerConsts.SelectedArea.Folders:
      if(this.getFolderName() != newName) {
       this.renameOldName = this.getFolderName();
       this.SendCallback(ASPxClientFileManagerCallbackCommand.RenameItem, { isFolderArea: true, name: newName });
      }
      break;
    }
    this.renameMode = false;
   }
  }
  this.HideCreateHelperElement();
  this.HideRenameInput();
 },
 SetVisibleRenameInputInFileArea: function(item, enable) {
  var input = this.elements.GetRenameInputElement();
  var itemElement = item.getElement();
  ASPx.SetElementDisplay(input, enable);
  if(this.isDetailsViewMode()) {
   var titleCellElement = ASPx.GetChildByClassName(itemElement, FileManagerConsts.GridColumnTitleCellClassName);
   if(!titleCellElement) {
    for(var cell, i = 0; cell = ASPx.GetChildElementNodes(itemElement)[i]; i++) {
     if(ASPx.ElementContainsCssClass(cell, "dxgvCommandColumn") || ASPx.ElementContainsCssClass(cell, FileManagerConsts.CreateHelperGridCommandCellClassName))
      continue;
     titleCellElement = cell;
     if(!ASPx.ElementContainsCssClass(cell, FileManagerConsts.ThumbnailCellClassName))
      break;
    }
   }
   var titleElement = ASPx.GetChildByClassName(titleCellElement, FileManagerConsts.GridColumnTitleClassName);
   if(enable) {
    if(titleElement && !this.nameColumnHasTemplate) {
     titleCellElement.appendChild(input);
     this.elements.PrepareRenameInputElement(titleElement);
     ASPx.SetElementDisplay(titleElement, false);     
    } else {
     ASPx.AdjustHeight(titleCellElement);
     this.hiddenOnRenameHtml = titleCellElement.innerHTML;
     titleCellElement.innerHTML = "";
     titleCellElement.appendChild(input);
     var size = this.elements.CalculateTextSize(item.name, titleCellElement);
     if(item.isCreateHelperFolder)
      size.width = FileManagerConsts.DefaultRenameInputWidth;
     this.elements.PrepareRenameInputElement(null, size);
    }
   } else {
    if(titleElement)
     ASPx.SetElementDisplay(titleElement, true);
    else
     titleCellElement.innerHTML = this.hiddenOnRenameHtml;
   }
  }
  if(this.isThumbnailOrFilterViewMode()) {
   var mask = this.elements.GetRenameMask();
   var titleElement = this.elements.GetItemTitleElement(item);
   if(enable) {
    if(this.isThumbnailsViewFileAreaItemTemplate) {
     if(!item.isCreateHelperFolder) {
      ASPx.SetElementDisplay(mask, true);
      itemElement.appendChild(mask);
     }
     itemElement.appendChild(input);
     this.elements.PrepareRenameInputElement(item.itemContentElement, this.elements.CalculateTextSize(item.name, itemElement), true);
    } else {
     ASPx.InsertElementAfter(input, titleElement);
     this.elements.PrepareRenameInputElement(titleElement);
     ASPx.SetElementDisplay(titleElement, false);
    }
   } else {
    if(this.isThumbnailsViewFileAreaItemTemplate)
     ASPx.SetElementDisplay(mask, false);
    else
     ASPx.SetElementDisplay(titleElement, true);
   }
  }
  ASPx.GetStateController().ClearElementCache(input);
  if(enable) {
   if(this.createInFileAreaMode)
    input.value = "";
   else {
    input.value = item.name;
    this.renameMode = true;
   }
   ASPx.SetFocus(input);
   this.UpdateToolbars();
  }
  input["data-fileName"] = item.id;
 },
 TrySetVisibleRenameInputInFoldersArea: function(node, enable) {
  var treeView = this.GetTreeView();
  if(node == treeView.GetNode(0))
   return false;
  var input = this.elements.GetRenameInputElement();
  var element = node.GetHtmlElement();
  var titleElement = treeView.renderHelper.GetNodeTextElement(element);
  ASPx.InsertElementAfter(input, titleElement);
  ASPx.SetElementDisplay(input, enable);
  ASPx.ClearHeight(input);
  this.elements.PrepareRenameInputElement(titleElement, { width: FileManagerConsts.DefaultRenameInputWidth });
  ASPx.GetStateController().ClearElementCache(input);
  if(enable) {
   input.value = node.GetText();
   ASPx.SetFocus(input);
   this.renameMode = true;
   this.UpdateToolbars();
  }
  var vamClassName = this.elements.GetVerticalCenteringClassName();
  if(vamClassName) {
   var action = enable ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
   action(titleElement, vamClassName);
  }
  ASPx.SetElementDisplay(titleElement, !enable);
  treeView.AdjustControl();
 },
 IsMoveAvailable: function() {
  if(!this.allowMove)
   return false;
  return this.IsEditOperationAvailable("allowMove", true);
 },
 TryMove: function() {
  this.folderDialogCommand = ASPxClientFileManagerCallbackCommand.MoveItems;
  return this.TryShowFolderBrowserDialog();
 },
 IsCopyAvailable: function() {
  if(!this.allowCopy)
   return false;
  return this.IsEditOperationAvailable("allowCopy", true);
 },
 TryCopy: function() {
  this.folderDialogCommand = ASPxClientFileManagerCallbackCommand.CopyItems;
  return this.TryShowFolderBrowserDialog();
 },
 TryShowFolderBrowserDialog: function() {
  var area = this.GetActiveArea();
  switch (area) {
   case FileManagerConsts.SelectedArea.Files:
    var approvedItems = [];
    this.forEachItem(function(item) {
     if(item.IsSelected() && !item.isParentFolderItem && this.GetFolderBrowserEventResult(item))
      approvedItems.push(item);
    }.aspxBind(this));
    if(approvedItems.length > 0) {
     this.SendCallback(ASPxClientFileManagerCallbackCommand.ShowFolderBrowserDialog, { isFolderArea: false });
     this.movedItems = approvedItems;
     return true;
    }
    else
     this.folderDialogCommand = null;
    break;
   case FileManagerConsts.SelectedArea.Folders:
    if(this.GetFolderBrowserEventResult()) {
     this.SendCallback(ASPxClientFileManagerCallbackCommand.ShowFolderBrowserDialog, { isFolderArea: true, isCopyFolder: this.folderDialogCommand == ASPxClientFileManagerCallbackCommand.CopyItems });
     return true;
    } else
     this.folderDialogCommand = null;
    break;
  }
  return false;
 },
 GetFolderBrowserEventResult: function(item) {
  switch(this.folderDialogCommand) {
   case ASPxClientFileManagerCallbackCommand.CopyItems:
    return item ? this.raiseItemCopying(item) : this.raiseFolderCopying();
   case ASPxClientFileManagerCallbackCommand.MoveItems:
    return item ? this.raiseItemMoving(item) : this.raiseFolderMoving();
  }
 },
 ChangeItemsPosition: function() {
  var node = this.GetFolderBrowserTreeView().GetSelectedNode();
  var isFolderAreaCommand = this.GetActiveArea() == FileManagerConsts.SelectedArea.Folders;
  if(this.GetActiveArea() == FileManagerConsts.SelectedArea.None || !node.enabled || (!isFolderAreaCommand && this.movedItems.length == 0))
   return;
  this.changeItemPositionOldInfo = {
   id: [],
   name: [],
   oldFolderFullName: isFolderAreaCommand ? this.getCurrentFolderParentPath() : this.GetCurrentPath(),
   isFolder: []
  };
  this.fillEditOperationOldInfo(this.movedItems, isFolderAreaCommand, this.changeItemPositionOldInfo);
  var targetPath = this.GetFoldersPath(node, true);
  var targetIdPath = this.GetFoldersPath(node, false, "\\\\", true);
  var args = { isFolderArea: isFolderAreaCommand, path: targetPath, targetIdPath: targetIdPath };
  if(!isFolderAreaCommand)
   args.items = this.GetItemsCallbackInfo(this.movedItems);
  this.SendCallback(this.folderDialogCommand, args);
 },
 ShowFolderBrowserPopup: function(renderFolders) {
  var popup = this.GetFolderBrowserPopup();
  var container = this.elements.GetFolderBrowserPopupFoldersContainer();
  var popupHeight = this.GetHeight() / 2;
  if(popup.GetHeight() < popupHeight)
   ASPx.SetOffsetHeight(container, popupHeight);
  popup.ShowAtElement(this.GetMainElement());
  if(renderFolders)
   container.innerHTML = renderFolders;
  popup.UpdatePosition();
 },
 HideFolderBrowserPopup: function() {
  var popup = this.GetFolderBrowserPopup();
  popup.Hide();
 },
 FolderBrowserOkButtonClick: function() {
  this.ChangeItemsPosition();
  this.HideFolderBrowserPopup();
 },
 FolderBrowserCancelButtonClick: function() {
  this.HideFolderBrowserPopup();
 },
 IsCreateAvailable: function() {
  if(!this.allowCreate ||  this.GetIsRecursiveFilterApplied())
   return false;
  return this.folderRights.allowCreate &&
   (this.GetActiveArea() == FileManagerConsts.SelectedArea.Folders || this.showFoldersInFileArea);
 },
 TryCreate: function() {
  if(this.raiseFolderCreating()) {
   if(this.showFoldersInFileArea && this.GetActiveArea() != FileManagerConsts.SelectedArea.Folders) {
    if(this.GetActiveArea() == FileManagerConsts.SelectedArea.None)
     this.SetActiveArea(FileManagerConsts.SelectedArea.Files);
    this.ShowCreateHelperElement();
   }
   else
    this.SendCallback(ASPxClientFileManagerCallbackCommand.ShowCreateFolderEditorInTreeView, { currentPath: this.GetCurrentPath(true) });
   return true;
  }
  return false;
 },
 HideCreateTextbox: function() {
  if(!this.createMode)
   return;
  this.createMode = false;
  this.UpdateToolbars();
  this.elements.createNodeTextBox = null;
  var createNode = this.tree.getSelectedNodeInView();
  var newSelectedNode = createNode.parent;
  this.tree.setSelectedNodeInView(newSelectedNode);
  this.tree.setSelectedNode(newSelectedNode);
  this.Refresh();
 },
 PrepareCreateNode: function() {
  var tb = ASPx.GetNodeByTagName(this.tree.getSelectedNodeInView().GetHtmlElement(), "INPUT", 0);
  this.elements.createNodeTextbox = tb;
  var _this = this;
  ASPx.Evt.AttachEventToElement(tb, "keydown", function(evt) {
   switch (ASPx.Evt.GetKeyCode(evt)) {
    case ASPx.Key.Enter:
     ASPx.Evt.PreventEvent(evt);
     _this.DoCreate();
     break;
    case ASPx.Key.Esc:
     _this.HideCreateTextbox();
     ASPx.Evt.PreventEvent(evt);
     break;
   }
  });
  ASPx.Evt.AttachEventToElement(tb, "keypress", function(evt) { 
   if(ASPx.Evt.GetKeyCode(evt) == ASPx.Key.Enter)
    return ASPx.Evt.PreventEventAndBubble(evt);
  });
  ASPx.Evt.AttachEventToElement(tb, "blur", function(evt) {
   _this.DoCreate();
  });
  if(!ASPxClientUtils.iOSPlatform)
   ASPx.SetFocus(tb);
 },
 ShowCreateHelperElement: function() {
  var grid = this.GetFilesGridView();
  if(this.isDetailsModeVirtScrollEnabled())
   grid.lockVirtualScrolling(true);
  var item = this.GetCreateHelperItem();
  var element = item.getElement();
  item.SetVisible(true);
  ASPx.AddClassNameToElement(element, item.selectionActiveCssClass);
  this.createInFileAreaMode = true;
  if(this.isDetailsViewMode()) {
   var emptyDataItem = grid.GetEmptyDataItem();
   if(emptyDataItem)
    ASPx.SetElementDisplay(emptyDataItem, false);
   grid.syncAdaptivityInCreateHelperElement(element);
  }
  this.SetVisibleRenameInputInFileArea(item, true);
 },
 HideCreateHelperElement: function() {
  var item = this.GetCreateHelperItem();
  if(!item)
   return;
  item.unfocus();
  item.SetVisible(false);
  this.createInFileAreaMode = false;
  if(this.isDetailsViewMode() && this.GetFilesGridView().GetEmptyDataItem())
   ASPx.SetElementDisplay(this.GetFilesGridView().GetEmptyDataItem(), true);
 },
 GetCreateHelperItem: function() {
  if(this.isDetailsViewMode())
   return this.detailsCreateHelperItem;
  else
   return this.thumbCreateHelperItem;
 },
 DoCreate: function() {
  if(!this.createMode)
   return;
  var newName = this.elements.createNodeTextbox.value;
  if(this.ValidateName(newName, ASPxClientFileManagerCommandConsts.Create)) {
   this.UpdateToolbars();
   this.elements.createNodeTextbox.value = "";
   this.DoCreateCore(newName, true);
  }
  else
   this.HideCreateTextbox();
  this.createMode = false;
 },
 DoCreateCore: function(newName, selectNewFolder) {
  this.SendCallback(ASPxClientFileManagerCallbackCommand.CreateFolder, { name: newName, selectNewFolder: selectNewFolder });
 },
 GetDownloadFiles: function(isNeedRaiseFileDownloading) {
  var files = this.getSelectedItems();
  var downloadFiles = [];
  for(var file, i = 0; file = files[i]; i++) {
   if(!file.rights.allowDownload)
    return [];
   if(!isNeedRaiseFileDownloading || this.raiseFileDownloading(file))
    downloadFiles.push(file);
  }
  return downloadFiles;
 },
 TryDownload: function() {
  var downloadFiles = this.GetDownloadFiles(true);
  if(downloadFiles.length == 0)
   return false;
  var arg = this.GetArgumentsString(ASPxClientFileManagerCallbackCommand.Download, {items : this.GetItemsCallbackInfo(downloadFiles)});
  this.SendPostBack(arg, true);
  return true;
 },
 IsDownloadButtonActive: function() {
  return (this.GetActiveArea() == FileManagerConsts.SelectedArea.Files) && this.GetDownloadFiles(false).length > 0;
 },
 joinItemNames: function(items, separator) {
  return this.joinItemPropertyValues(items, "name", separator);
 },
 joinItemsIDs: function(items, separator) {
  return this.joinItemPropertyValues(items, "id", separator);
 },
 joinItemPropertyValues: function(items, propertyName, separator) {
  separator = separator ? separator : FileManagerConsts.ItemPropertyValueSeparator;
  var propertyValues = "";
  for(var item, i = 0; item = items[i]; i++) {
   if(propertyValues.length > 0)
    propertyValues += separator;
   propertyValues += item[propertyName];
  }
  return propertyValues;
 },
 IsEditMode: function() {
  return this.renameMode || this.createMode || this.folderDialogCommand != null;
 },
 showError: function(commandName, errorText, errorCode) {
  if(errorCode == undefined || errorText == undefined)
   return;
  var errorCodes = errorCode.split('|');
  var errorTexts = errorText.split('|');
  var resultErrorText = "";
  for(var i = 0; i < errorCodes.length; i++) {
   var errorCodeNumber = parseInt(errorCodes[i]);
   var args = this.raiseErrorOccurred(commandName, errorTexts[i], errorCodeNumber);
   if(args.showAlert) {
    if(resultErrorText.length > 0)
     resultErrorText += "\r\n";
    resultErrorText += args.errorText;
   }
  }
  if(resultErrorText.length > 0) {
   var args = this.raiseErrorAlertDisplaying(commandName, resultErrorText);
   if(args.showAlert && args.errorText)
    ASPx.ShowErrorAlert(args.errorText);
  }
 },
 CorrectScroll: function(item) {
  if(this.isDetailsViewMode() || !item || !item.GetVisible())
   return;
  var element = item.getElement(),
   scrollContainer = this.elements.GetItemsPaneContainer(),
   containerHeight = scrollContainer.offsetHeight,
   itemHeight = this.itemThumbnailHeight,
   selectItemOffsetTop = ASPx.GetAbsolutePositionY(element) - this.itemThumbnailMarginTop,
   scrollContainerOffsetTop = ASPx.GetAbsolutePositionY(scrollContainer);
  if(scrollContainerOffsetTop > selectItemOffsetTop) {
   scrollContainer.scrollTop -= scrollContainerOffsetTop - selectItemOffsetTop;
   if(this.isThumbnailModeVirtScrollEnabled() && this.virtScroll.state) {
    var isVirtualScrollTopEdge = this.virtScroll.state.topIndentHeight == scrollContainer.scrollTop;
    if(isVirtualScrollTopEdge)
     scrollContainer.scrollTop--;
   }
  }
  else if(selectItemOffsetTop + itemHeight > scrollContainerOffsetTop + containerHeight) {
   scrollContainer.scrollTop += selectItemOffsetTop + itemHeight - scrollContainerOffsetTop - containerHeight;
   if(this.isThumbnailModeVirtScrollEnabled() && this.virtScroll.state) {
    var isVirtualScrollBottomEdge = this.virtScroll.state.topIndentHeight + this.virtScroll.state.pageHeight - this.virtScroll.state.itemsViewAreaHeight == scrollContainer.scrollTop;
    if(isVirtualScrollBottomEdge)
     scrollContainer.scrollTop += FileManagerConsts.UpperBoundaryAdditionalOffset + 1;
   }
  }
 },
 scrollToItem: function(item) {
  var element = item.getElement(),
   scrollContainer = this.elements.GetItemsPaneContainer();
  this.elements.GetItemsPaneContainer().scrollTop += ASPx.GetAbsoluteY(element) - ASPx.GetAbsoluteY(scrollContainer);
 },
 fillEditOperationOldInfo: function(items, isFolderAreaCommand, oldInfoObject) {
  if(!isFolderAreaCommand) {
   for(var item, i = 0; item = items[i]; i++) {
    oldInfoObject.id.push(item.id);
    oldInfoObject.name.push(item.name);
    oldInfoObject.isFolder.push(item.isFolder);
   }
  }
  else {
   oldInfoObject.id.push(this.GetCurrentFolderId());
   oldInfoObject.name.push(this.getFolderName());
   oldInfoObject.isFolder.push(true);
  }
 },
 scrollToSelection: function(selectItemNames) {
  if(selectItemNames && selectItemNames.length > 0) {
   for(var itemName, i = 0; itemName = selectItemNames[i]; i++) {
    var item = this.items[itemName];
    if(item && !item.isVirtual() && item.GetVisible()) {
     this.scrollToItem(item);
     return;
    }
   }
  }
 },
 resetSelection: function(needSelectItemNames) {
  var selectedItems = [];
  if(needSelectItemNames && needSelectItemNames.length > 0) {
   for(var itemName, i = 0; itemName = needSelectItemNames[i]; i++) {
    var item = this.items[itemName];
    if(item && item.isAvailable()) {
     if(selectedItems.length == 0)
      item.focus();
     item.Select();
     selectedItems.push(item);
    }
   }
  }
  this.unselectAllItems(selectedItems);
 },
 unselectAllItems: function(excludes, onlyVisible) {
  var items = this.getSelectedItems();
  for(var item, i = 0; item = items[i]; i++) {
   var needUnselect = (!onlyVisible || item.GetVisible()) &&
    (!excludes || ASPx.Data.ArrayIndexOf(excludes, item) < 0);
   if(needUnselect)
    item.Unselect();
  }
 },
 selectAllItems: function() {
  if(!this.allowMultiSelect)
   return;
  var items = this.GetVisibleItems();
  for(var item, i = 0; item = items[i]; i++) {
   if(!item.IsSelected())
    item.Select();
  }
 },
 getSelectAllCheckboxState: function() {
  var value = ASPx.CheckBoxInputKey.Indeterminate;
  var selectedItemsCount = this.getSelectedItems(true).length;
  if(selectedItemsCount == 0)
   value = ASPx.CheckBoxInputKey.Unchecked;
  else {
   var itemsCount = this.GetVisibleItems(true).length;
   if(itemsCount == selectedItemsCount)
    value = ASPx.CheckBoxInputKey.Checked;
  }
  return value;
 },
 selectItem: function(itemName) {
  this.selectItems([itemName]);
 },
 focusItem: function(fileName, skipEvent) {
  var file = this.items[fileName];
  if(file)
   return file.focus(skipEvent);
 },
 selectItems: function(itemIDs, skipEvent, skipFocus) {
  var selected = [];
  for(var id, i = 0; id = itemIDs[i]; i++) {
   var item = this.items[id];
   if(item && item.Select(skipEvent, skipFocus))
    selected.push(id);
  }
  return selected;
 },
 changeRangeSelection: function(startItem, endItem, itemsMap, direction) {
  if(endItem == startItem)
   return;
  var select = !(endItem.IsSelected() && startItem.IsSelected());
  for(var i = startItem.index; direction > 0 ? i <= endItem.index : i >= endItem.index; direction > 0 ? i++ : i--) {
   var nextItem = itemsMap[i];
   if(!nextItem)
    continue;
   if(select)
    nextItem.Select();
   else if(nextItem != endItem)
    nextItem.Unselect();
  }
 },
 saveSelectedItemsToState: function() {
  var selectedItemsInfo = [];
  this.forEachItem(function(item) {
   if(item.IsSelected()) {
    selectedItemsInfo.push(this.GetClientItemInfo(item));
   }
  }.aspxBind(this));
  this.UpdateStateField(FileManagerConsts.StateField.ItemSelected, selectedItemsInfo);
 },
 saveFocusedItemToState: function() {
  if(!this.focusedItem)
   return;
  this.UpdateStateField(FileManagerConsts.StateField.ItemFocused, this.GetClientItemInfo(this.focusedItem));
 }, 
 correctItemsAreaPopupPosition: function(popup) {
  var popupElement = this.isDetailsViewMode() ? this.GetFilesGridView().GetMainElement() : this.elements.GetItemsPaneContainer();
  var scrollbarWidth = ASPx.PxToInt(ASPx.GetCurrentStyle(popupElement.parentNode).width) - ASPx.PxToInt(ASPx.GetCurrentStyle(popupElement).width);
  popup.ShowAtPos(ASPx.GetAbsolutePositionX(popupElement) + popupElement.offsetWidth - scrollbarWidth - popup.GetWidth(),
      ASPx.GetAbsolutePositionY(popupElement) + popupElement.offsetHeight - popup.GetHeight());
 },
 Refresh: function() {
  if(!this.enabled)
   return;
  this.UpdateFileList(ASPxClientFileManagerCallbackCommand.Refresh);
 },
 ExecuteCommand: function(commandName) {
  if(this.GetActiveArea() == FileManagerConsts.SelectedArea.None)
   this.SetActiveArea(this.lastActiveItemsArea);
  switch(commandName) {
   case ASPxClientFileManagerCommandConsts.Delete:
    return this.TryDelete();
   case ASPxClientFileManagerCommandConsts.Rename:
    return this.TryRename();
   case ASPxClientFileManagerCommandConsts.Create:
    return this.TryCreate();
   case ASPxClientFileManagerCommandConsts.Download:
    return this.TryDownload();
   case ASPxClientFileManagerCommandConsts.Move:
    return this.TryMove();
   case ASPxClientFileManagerCommandConsts.Copy:
    return this.TryCopy();
   case ASPxClientFileManagerCommandConsts.Open:
    return this.TryOpen();
  }
 },
 GetSelectedFile: function() {
  return this.GetSelectedItem(FileManagerConsts.FileAreaItemTypes.File);
 },
 GetSelectedItem: function(type) {
  if(!this.enabled)
   return null;
  var items = this.getSelectedItems();
  if(items.length > 0 && (!type || items[0].type == type))
   return items[0];
  return null;
 },
 GetSelectedItems: function() {
  return this.getSelectedItems();
 },
 GetItems: function() {
  var files = [];
  this.forEachItem(function(file) {
   files.push(file);
  });
  return files;
 },
 GetAllItems: function(onCallback) {
  this.apiCommandCallback = onCallback;
  this.SendCallback(ASPxClientFileManagerCallbackCommand.GetAllItems);
 },
 GetToolbarItemByCommandName: function(commandName) {
  return this.GetToolbar().GetItemByName(commandName);
 },
 GetContextMenuItemByCommandName: function(commandName) {
  return this.GetContextMenu().GetItemByName(commandName);
 },
 GetCurrentFolderPath: function(separator, skipRootFolder) {
  if(!this.enabled)
   return null;
  if(this.currentPath != null)
   return this.GetCurrentPath(skipRootFolder, separator);
  return "";
 },
 SetCurrentFolderPath: function(path, onCallback) {
  var parts = this.getPathParts(path);
  for(var i = 0; i < parts.length; i++) {
   parts[i] = FileManagerConsts.IdValuePrefix.AutoId + parts[i];
  }
  this.SetCurrentFolderPathInternal(path, onCallback, parts, false);
 },
 GetCurrentFolderId: function () {
  return this.getIdFromFormattedId(this.currentFolderId);
 },
 SetCurrentFolderPathInternal: function(path, onCallback, idPath, selectPreviousFolder) {
  this.cancelActiveActions();
  var currentPath = this.GetCurrentPath(true);
  if(selectPreviousFolder)
   this.needFocusItemName = currentPath;
  if(this.foldersHidden) {
   this.needCurrentFolderChangedRaise = true;
   this.SendCallback(ASPxClientFileManagerCallbackCommand.ChangeFolder, { path: path, idPath: idPath });
   return;
  }
  this.SetActiveArea(FileManagerConsts.SelectedArea.Folders);
  var splittedPath = this.splitPath(path);
  var treeView = this.GetTreeView();
  var node = this.tree.getFilesRootNode();
  if(splittedPath.length > 0) {
   for(var i = 0, folder; folder = splittedPath[i]; i++) {
    if(treeView.AreChildNodesLoaded(node)) {
     node = this.findTreeViewNodeChild(node, folder, idPath[i + 1]);
     if(!node)
      return false;
    }
    else { 
     this.delayedSetCurrentFolderPath = path.replace("/", "\\");
     this.delayedSetCurrentFolderIdPath = idPath;
     this.delayedCallbackFunction = onCallback;
     this.folderExpandingNode = node;
     node.SetExpanded(true);
     return true;
    }
   }
  }
  if(this.tree.getSelectedNode() != node) {
   this.tree.setSelectedNodeInView(node);
   this.tree.setSelectedNode(node);
   this.needCurrentFolderChangedRaise = true;
   this.delayedCallbackFunction = onCallback;
   this.expandNodeRecursive(node);
   this.tree.scrollToNode(node);
   this.UpdateFileList(ASPxClientFileManagerCallbackCommand.GetFileList);
   return true;
  }
  return false;
 },
 PerformCallback: function(args, onSuccess) {
  if(!ASPx.IsExists(args)) args = "";
  this.SendCallback(ASPxClientFileManagerCallbackCommand.CustomCallback, { custCallbackParam: args }, null, onSuccess);
 },
 performVirtualScrollingCallback: function(itemIndex, pageItemsCount) {
  if(this.isThumbnailOrFilterViewMode())
   this.SendCallback(ASPxClientFileManagerCallbackCommand.VirtualScrolling, { itemIndex: itemIndex, pageItemsCount: pageItemsCount }, true);
  else
   this.GetFilesGridView().NextPage();
 },
 expandNodeRecursive: function(node) {
  var treeView = this.GetTreeView();
  var nodeParent = node.parent;
  while(nodeParent) {
   if(!treeView.GetNodeExpandedInternal(nodeParent))
    nodeParent.SetExpanded(true);
   nodeParent = nodeParent.parent;
  }
 },
 findTreeViewNodeChild: function(parentNode, text, id) {
  for(var childNode, j = 0; childNode = parentNode.nodes[j]; j++) {
   var isAutoId = this.isFormattedAutoIdValue(id);
   if(isAutoId && this.getFolderNameByNode(childNode) === text || !isAutoId && this.getFolderIdByNode(childNode) === id)
    return childNode;
  }
 },
 splitPath: function(path) {
  if(!path) return [];
  var separator = "/";
  if(path.indexOf(separator) == -1)
   separator = "\\";
  return path.split(separator);
 },
 setFocusToFilterBox: function() {
  var filterBox = this.GetToolbarFilterTextBox();
  if(filterBox)
   filterBox.Focus();
 },
 KeyProcessEnter: function() {
  if(this.GetActiveArea() != FileManagerConsts.SelectedArea.Files)
   return;
  if(!this.renameMode && !this.createMode) {
   if(this.allowMultiSelect) {
    if(this.focusedItem)
     this.TryOpenItem(this.focusedItem);
   }
   else {
    var selectedFiles = this.getSelectedItems();
    if(selectedFiles.length == 1)
     this.TryOpenItem(selectedFiles[0]);
   }
  }
 },
 KeyProcessEsc: function() {
  this.cancelActiveActions();
 },
 KeyProcessF2: function() {
  if(this.allowRename && this.IsRenameAvailable() && !this.IsEditMode())
   this.TryRename();
 },
 KeyProcessF6: function() {
  if(this.allowMove && this.IsMoveAvailable() && !this.IsEditMode())
   this.TryMove();
 },
 KeyProcessDelete: function() {
  if(this.allowDelete && this.IsDeleteAvailable() && !this.IsEditMode())
   this.TryDelete();
 },
 KeyProcessTab: function() {
  if(this.folderDialogCommand != null) {
   if(this.GetActiveArea() == FileManagerConsts.SelectedArea.Files)
    this.elements.GetAccessibilityInput().focus();
   this.SetActiveArea(FileManagerConsts.SelectedArea.None);
  }
 },
 KeyProcessF7: function() {
  if(this.allowCreate && this.IsCreateAvailable() && !this.IsEditMode())
   this.TryCreate();
 },
 KeyProcessSpace: function() {
  var focusFile = this.focusedItem;
  if(this.allowMultiSelect && focusFile)
   focusFile.invertSelection();
 },
 KeyProcessCtrlA: function() {
  if(this.GetActiveArea() == FileManagerConsts.SelectedArea.Files)
   this.selectAllItems();
 },
 KeyProcessPageUp: function(modifier) {
  this.keyProcessNavigateToPageEdge(-1, modifier);
 },
 KeyProcessPageDown: function(modifier) {
  this.keyProcessNavigateToPageEdge(1, modifier);
 },
 keyProcessNavigateToPageEdge: function(direction, modifier) {
  var grid = this.GetFilesGridView(),
   focusItemIndex = grid.focusedRowIndex,
   scrollHelper = grid.GetScrollHelper();
  if(!this.gridScrollHeight)
   this.gridScrollHeight = scrollHelper.GetScrollDiv(scrollHelper.GetContentTable()).clientHeight;
  var rowHeight = scrollHelper.GetVirtualScrollRowHeight(),
   rowsOnPage = Math.round(this.gridScrollHeight / rowHeight),
   pageStartIndex = Math.round(scrollHelper.GetVertScrollPosition() / rowHeight),
   pageEndIndex = pageStartIndex + rowsOnPage - 1,
   newItemPosition = direction > 0 ? pageEndIndex : pageStartIndex;
  if(pageStartIndex > focusItemIndex || focusItemIndex > pageEndIndex || newItemPosition == focusItemIndex)
   newItemPosition = focusItemIndex + (rowsOnPage - 1) * direction;
  var itemsInfo = this.getVisibleItemsInfo(),
   files = itemsInfo.list,
   visibleItemPosition = newItemPosition - this.virtScroll.itemIndex;
  if(visibleItemPosition < 0)
   visibleItemPosition = 0;
  var file = files[visibleItemPosition >= files.length ? files.length - 1 : visibleItemPosition];
  if(this.allowMultiSelect) {
   if(modifier == FileManagerConsts.ModifierKey.Shift)
    this.changeRangeSelection(this.focusedItem, file, itemsInfo.indexMap, direction);
   file.focus();
  }
  else {
   file.Select();
   file.correctScroll();
  }
 },
 KeyProcessHome: function(modifier) {
  this.keyProcessNavigateToEdge(0, modifier);
 },
 KeyProcessEnd: function(modifier) {
  this.keyProcessNavigateToEdge(1, modifier);
 },
 keyProcessNavigateToEdge: function(position, modifier) {
  if(this.GetActiveArea() == FileManagerConsts.SelectedArea.Files) {
   var itemsInfo = this.getVisibleItemsInfo(),
    files = itemsInfo.list;
   if(files.length == 0)
    return;
   var file = files[position > 0 ? files.length - 1 : 0];
   if(this.allowMultiSelect) {
    if(modifier == FileManagerConsts.ModifierKey.Shift)
     this.changeRangeSelection(this.focusedItem, file, itemsInfo.indexMap, position > 0 ? 1 : -1);
    file.focus();
   }
   else {
    file.Select();
    file.correctScroll();
   }
  }
 },
 preProcessGridArrowKey: function(direction, modifier) {
  if(modifier != FileManagerConsts.ModifierKey.Ctrl || !this.allowMultiSelect || this.isThumbnailOrFilterViewMode())
   return;
  var grid = this.GetFilesGridView(),
   index = grid.GetFocusedRowIndex(),
   nextIndex = index + direction,
   isIndexSelected = grid.IsRowSelectedOnPage(index),
   isNextIndexSelected = grid.IsRowSelectedOnPage(nextIndex);
  if(isIndexSelected && !isNextIndexSelected)
   grid.SelectRowOnPage(nextIndex);
  else if(!isIndexSelected)
   grid.SelectRowOnPage(index);
  else if(!(isIndexSelected && this.getSelectedItems().length == 1))
   grid.UnselectRowOnPage(index);
 },
 cancelActiveActions: function() {
  if(this.renameMode)
   this.HideRenameInput();
  else if(this.folderDialogCommand != null)
   this.HideFolderBrowserPopup();
  else if(this.createMode)
   this.HideCreateTextbox();
  else
   this.SetActiveArea(FileManagerConsts.SelectedArea.None);
 },
 isExists: function() {
  return ASPx.GetControlCollection().Get(this.name) == this;
 }
});
ASPxClientFileManager.Cast = ASPxClientControl.Cast;
var ASPxClientFileManagerItem = ASPx.CreateClass(null, {
 constructor: function(fileManager, index, itemInfo) {
  this.fileManager = fileManager;
  this.index = index;
  this.name = itemInfo.n;
  this.encodedName = itemInfo.en || itemInfo.n;
  this.formattedId = itemInfo.id;
  this.id = this.fileManager.getIdFromFormattedId(this.formattedId);
  this.type = itemInfo.it;
  this.isFolder = this.type != FileManagerConsts.FileAreaItemTypes.File;
  this.filterViewInfo = itemInfo.fvi ? itemInfo.fvi : undefined;
  this.outdated = itemInfo.outdated;
  if(this.outdated)
   return;
  this.clientVisible = !itemInfo.cn;
  this.SetRights(itemInfo.r);
  this.imageSrc = itemInfo.i;
  this.imageIndex = itemInfo.ci;
  this.metadata = itemInfo.md;
  if(itemInfo.pi) {
   this.parentInfo = { };
   this.parentInfo.relativeName = itemInfo.pi.rn;
   this.parentInfo.idPath = itemInfo.pi.ip;
  }
  this.elementID = this.fileManager.elements.itemsContainerId + FileManagerConsts.ItemPostfix + this.index.toString();
  this.isParentFolderItem = this.type == FileManagerConsts.FileAreaItemTypes.ParentFolder;
  this.isCreateHelperFolder = this.type == FileManagerConsts.FileAreaItemTypes.CreateHelperFolder;
  var idPostfix = this.isCreateHelperFolder ? FileManagerConsts.CreateHelperFolderPostfix : this.index.toString();
  this.elementID = this.fileManager.elements.itemsContainerId + FileManagerConsts.ItemPostfix + idPostfix;
  this.cssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderCssClass : this.fileManager.styles.fileCssClass;
  if(!this.fileManager.GetIsFilterViewActive())
   this.contentCssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderContentCssClass : this.fileManager.styles.fileContentCssClass;
  this.selectionActiveCssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderSelectionActiveCssClass : this.fileManager.styles.fileSelectionActiveCssClass;
  this.selectionInactiveCssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderSelectionInactiveCssClass: this.fileManager.styles.fileSelectionInactiveCssClass;
  this.hoverCssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderHoverCssClass : this.fileManager.styles.fileHoverCssClass;
  this.focusCssClass = this.isFolder ? this.fileManager.styles.fileAreaFolderFocusCssClass : this.fileManager.styles.fileFocusCssClass;
  var tooltip = this.isCreateHelperFolder ? "" : (itemInfo.t ? itemInfo.t.replace(/\|\|/g, "\r\n") : "");
  if(this.fileManager.isThumbnailOrFilterViewMode()) {
   this.element = document.getElementById(this.elementID);
   if(!this.element && !this.isVirtual())
    this.element = this.fileManager.elements.createItemElement(this);
   if(this.element) {
    if(this.fileManager.allowMultiSelect && !this.isParentFolderItem && !this.isCreateHelperFolder) {
     var checkBox = ASPx.CreateHtmlElementFromString(ASPxClientFileManager.PrepareTemplate( this.fileManager.thumbnailCheckBox, { itemId: this.elementID } ));
     var container = this.GetCheckBoxContainer();
     container.appendChild(checkBox);
     this.fileManager.elements.createItemCheckBoxInstance(this);
    }
    if(ASPxClientUtils.touchUI && !ASPxClientUtils.windowsPlatform)
     ASPx.TouchUIHelper.AttachDoubleTapEventToElement(this.element, function(evt) {  this.fileManager.onThumbnailViewFilesAreaItemDblClick(this, evt); }.aspxBind(this));    
    else
     ASPx.Evt.AttachEventToElement(this.element, "dblclick", function(evt) { this.fileManager.onThumbnailViewFilesAreaItemDblClick(this, evt); }.aspxBind(this));
    this.itemContentElement = ASPx.GetNodeByTagName(this.element, "div", 0);
    this.fileManager.elements.PrepareItemElement(this, tooltip);
   }
   if(this.isCreateHelperFolder) {
    this.fileManager.thumbCreateHelperItem = this;
    this.fileManager.HideCreateHelperElement();
   }
  }
  else {
   this.tooltip = tooltip;
   if(this.isCreateHelperFolder)
    this.fileManager.detailsCreateHelperItem = this;
  }
  this.visible = true;
  this.isSelected = false;
 },
 GetCheckBoxContainer: function() {
  if(!this.fileManager.GetIsFilterViewActive())
   return this.element;
  var checkBoxCell = ASPx.GetChildByPartialClassName(this.element, FileManagerConsts.FilterViewCheckBoxCellClassName);
  if(!checkBoxCell) {
   checkBoxCell = document.createElement("div");
   checkBoxCell.className = FileManagerConsts.FilterViewCheckBoxCellClassName;
   this.element.insertBefore(checkBoxCell, this.element.firstChild);
  }
  return checkBoxCell;
 },
 SetRights: function(obj) {
  var checkPermission = function(literal) {
   return typeof (obj) == "undefined" || obj.indexOf(literal) > -1;
  };
  this.rights = {
   allowMove: checkPermission("m"),
   allowRename: checkPermission("r"),
   allowDelete: checkPermission("d"),
   allowDownload: checkPermission("l"),
   allowCopy: checkPermission("o")
  };
 },
 SetVisible: function(visible) {
  if(this.index < 0)
   return;
  if(!visible && this.IsSelected())
   this.Unselect();
  ASPx.SetElementDisplay(this.getElement(), visible);
  this.visible = visible;
 },
 GetVisible: function() {
  return this.clientVisible && this.getVisibleInternal();
 },
 getVisibleInternal: function() {
  return this.index > -1 && this.visible && !!this.getElement();
 },
 isAvailable: function() {
  return !this.clientVisible || this.getVisibleInternal();
 },
 focus: function(skipEvent, skipSelect) {
  if(!this.fileManager.allowMultiSelect)
   return;
  if(!(this.isExists() && this.GetVisible()))
   return;
  if(this.isFocused())
   return;
  this.fileManager.forEachItem(function(file) {
   file.unfocus();
  });
  this.fileManager.focusedItem = this;
  this.applyFocusView();
  if(!skipEvent)
   this.fileManager.raiseFocusedItemChangedEvent(this);
  var gridWithMultiSelect = this.fileManager.allowMultiSelect && this.fileManager.isDetailsViewMode();
  if(!skipSelect && this.fileManager.getSelectedItems().length == 0 && !gridWithMultiSelect)
   this.Select(skipEvent);
  this.fileManager.saveFocusedItemToState();
  this.fileManager.UpdateToolbars();
  return true;
 },
 applyFocusView: function() {
  if(this.fileManager.isThumbnailOrFilterViewMode())
   this.getElement().className += " " + this.focusCssClass;
  else {
   var grid = this.fileManager.GetFilesGridView();
   if(grid.GetFocusedRowIndex() == this.index)
    return;
   grid.SetFocusedRowIndex(this.index);
  }
  this.correctScroll();
 },
 unfocus: function() {
  if(!this.isAvailable())
   return;
  if(this.clientVisible)
   this.removeFocusView();
  if(this.fileManager.focusedItem == this)
   this.fileManager.focusedItem = null;
  this.fileManager.UpdateToolbars();
 },
 removeFocusView: function() {
  var element = this.getElement();
  if(this.fileManager.isThumbnailOrFilterViewMode()) {
   var focusClass = this.focusCssClass;
   if(element.className.indexOf(focusClass) > -1)
    element.className = ASPx.Str.Trim(element.className.replace(focusClass, ""));
  }
  else
   this.fileManager.GetFilesGridView().SetFocusedRowIndex(-1);
 },
 isFocused: function() {
  return this.fileManager.focusedItem == this;
 },
 SetSelected: function(selected) {
  if(selected)
   this.Select();
  else
   this.Unselect();
 },
 Select: function(skipEvent, skipFocus) {
  if(!this.isExists() || (this.isParentFolderItem && this.fileManager.allowMultiSelect))
   return;
  if(!this.fileManager.allowMultiSelect)
   this.fileManager.unselectAllItems([this]);
  if(!this.isAvailable())
   return;
  return this.SelectCore(skipEvent, skipFocus);
 },
 SelectCore: function(skipEvent, skipFocus) {
  if(this.IsSelected()) {
   this.UpdateSelectState(false);
   return true;
  }
  this.isSelected = true;
  if(this.clientVisible)
   this.applySelectView();
  this.fileManager.saveSelectedItemsToState();
  if(!skipEvent) {
   if(!this.isFolder)
    this.fileManager.raiseSelectedFileChangedEvent(this);
   this.fileManager.raiseSelectionChanged(this, true);
  }
  if(this.fileManager.allowMultiSelect && !this.fileManager.focusedItem && !skipFocus)
   this.focus(skipEvent);
  this.fileManager.SetActiveArea(FileManagerConsts.SelectedArea.Files);
  return true;
 },
 applySelectView: function() {
  if(this.fileManager.isThumbnailOrFilterViewMode())
   ASPx.GetStateController().SelectElementBySrcElement(this.getElement());
  else {
   var grid = this.fileManager.GetFilesGridView();
   if(this.fileManager.allowMultiSelect) {
    if(!grid.IsRowSelectedOnPage(this.index))
     grid.SelectRowOnPage(this.index);
   }
   else {
    if(grid.GetFocusedRowIndex() != this.index)
     grid.SetFocusedRowIndex(this.index);
   }
  }
  this.updateCheckBoxState(true);
 },
 Unselect: function(skipEvent) {
  if(!this.isExists())
   return;
  if(!this.isAvailable())
   return;
  if(!this.IsSelected())
   return;
  this.UpdateSelectState(false);
  this.isSelected = false;
  if(this.clientVisible)
   this.removeSelectView();
  this.fileManager.saveSelectedItemsToState();
  this.fileManager.UpdateToolbars();
  if(!skipEvent)
   this.fileManager.raiseSelectionChanged(this, false);
 },
 removeSelectView: function() {
  if(this.fileManager.isThumbnailOrFilterViewMode())
   ASPx.GetStateController().DeselectElementBySrcElement(this.getElement());
  else {
   var grid = this.fileManager.GetFilesGridView();
   if(this.fileManager.allowMultiSelect) {
    if(grid.IsRowSelectedOnPage(this.index))
     grid.UnselectRowOnPage(this.index);
   }
   else {
    if(grid.GetFocusedRowIndex() != this.index)
     grid.SetFocusedRowIndex(-1);
   }
  }
  this.updateCheckBoxState(false);
 },
 correctScroll: function() {
  if(this.fileManager.isThumbnailOrFilterViewMode())
   this.fileManager.CorrectScroll(this);
  else {
   var grid = this.fileManager.GetFilesGridView(),
    focusItemIndex = this.index,
    scrollHelper = grid.GetScrollHelper();
   if(!this.gridScrollHeight)
    this.gridScrollHeight = scrollHelper.GetScrollDiv(scrollHelper.GetContentTable()).clientHeight;
   var rowHeight = scrollHelper.GetVirtualScrollRowHeight(),
    rowsOnPage = Math.round(this.gridScrollHeight / rowHeight),
    pageStartIndex = Math.round(scrollHelper.GetVertScrollPosition() / rowHeight),
    pageEndIndex = pageStartIndex + rowsOnPage - 1;
   if(pageStartIndex > focusItemIndex)
    scrollHelper.SetVertScrollPosition(focusItemIndex > 0 ? focusItemIndex * rowHeight : 0);
   else if(focusItemIndex > pageEndIndex)
    scrollHelper.SetVertScrollPosition((focusItemIndex + 1) * rowHeight - this.gridScrollHeight);
  }
 },
 updateCheckBoxState: function(checked) {
  if(!this.fileManager.allowMultiSelect || !this.checkBox)
   return;
  this.checkBox.SetChecked(checked);
  this.fileManager.focusMainElement();
  var container = this.fileManager.elements.GetItemsContainer();
  var changeClassNameFunc = this.fileManager.getSelectedItems().length > 0
   ? ASPx.AddClassNameToElement
   : ASPx.RemoveClassNameFromElement;
  changeClassNameFunc(container, FileManagerConsts.ShowAllFileAreaCheckBoxesClassName);
 },
 invertSelection: function() {
  if(this.IsSelected())
   this.Unselect();
  else
   this.Select();
 },
 IsSelected: function() {
  return this.isExists() && this.isSelected;
 },
 UpdateSelectState: function(toInactive) {
  if(!this.GetVisible())
   return;
  var element = this.fileManager.elements.GetItemElement(this);
  if(!ASPx.IsExists(element))
   return;
  this.fileManager.updateFocusedRowStyle(element, toInactive);
  var className = element.className;
  if(this.IsSelected()) {
   className = toInactive
    ? className.replace(this.selectionActiveCssClass, this.selectionInactiveCssClass)
    : className.replace(this.selectionInactiveCssClass, this.selectionActiveCssClass);
   if(toInactive && className.indexOf(this.selectionInactiveCssClass) == -1)
    className += " " + this.selectionInactiveCssClass;
   else if(!toInactive && (this.isFocused() && this.fileManager.isDetailsViewMode()))
    className = className.replace(this.selectionActiveCssClass, "");
  }
  if(this.isFocused()) {
   if(toInactive)
    className = className.replace(this.focusCssClass, "");
   else if(className.indexOf(this.focusCssClass) < 0)
    className += " " + this.focusCssClass;
  }
  element.className = ASPx.Str.Trim(className);
 },
 getElement: function() {
  if(this.isVirtual())
   return null;
  if(this.element)
   return this.element;
  return this.fileManager.elements.GetItemElement(this);
 },
 GetFullName: function(separator, skipRootFolder) {
  if(this.parentInfo) {
   var partialName = this.fileManager.pathCombine(this.parentInfo.relativeName, this.name);
   return this.fileManager.getFullPath(partialName, separator, skipRootFolder);
  }
  return ASPxClientFileManager.GetItemFullName(this.name, this.fileManager, separator, skipRootFolder);
 },
 GetMetadata: function() { 
  return ASPx.CloneObject(this.metadata); 
 },
 toString: function() {
  return this.name;
 },
 isExists: function() {
  return !this.outdated && this.fileManager && this.fileManager.items[this.id] == this && this.fileManager.isExists();
 },
 isVirtual: function() {
  return this.outdated || !this.clientVisible;
 },
 makeClientInvisible: function() {
  this.clientVisible = false;
  this.element = null;
  this.checkBox = null;
 }
});
var ASPxClientFileManagerFile = ASPx.CreateClass(ASPxClientFileManagerItem, {
 constructor: function(fileManager, index, fileInfo) {
  this.constructor.prototype.constructor.call(this, fileManager, index, fileInfo);
 },
 Download: function() {
  if(!this.isExists())
   return;
  this.Select();
  if(this.IsSelected())
   this.fileManager.TryDownload();
 }
});
var ASPxClientFileManagerFolder = ASPx.CreateClass(ASPxClientFileManagerItem, {
 constructor: function(fileManager, index, fileInfo) {
  this.constructor.prototype.constructor.call(this, fileManager, index, fileInfo);
  this.isParentFolder = this.isParentFolderItem;
 }
});
ASPxClientFileManager.GetItemFullName = function(partialName, fileManager, separator, skipRootFolder) {
 if(!separator)
  separator = FileManagerConsts.PathSeparator;
 var folderPath = fileManager.GetCurrentFolderPath(separator, skipRootFolder);
 return folderPath ? (folderPath + separator + partialName) : partialName;
};
ASPxClientFileManager.OnFoldersTreeViewNodeClick = function(s, e) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.FoldersPostfix, !s.IsSplitterNestedControl()).OnFolderClick(e.node);
};
ASPxClientFileManager.OnFoldersTreeViewNodeExpanding = function(s, e) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.FoldersPostfix, !s.IsSplitterNestedControl()).OnFolderExpanding(s, e);
};
ASPxClientFileManager.OnUploadControlFileUploadStartEventHandler = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.UploadPostfix, !s.IsSplitterNestedControl()).OnFileUploadStart(evt);
};
ASPxClientFileManager.OnUploadControlUploadingProgressChanged = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.UploadPostfix, !s.IsSplitterNestedControl()).OnUploadingProgressChanged(evt);
};
ASPxClientFileManager.OnUploadControlFilesUploadComplete = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.UploadPostfix, !s.IsSplitterNestedControl()).OnFilesUploadComplete(evt);
};
ASPxClientFileManager.OnUploadControlValidationErrorOccurred = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.UploadPostfix, !s.IsSplitterNestedControl()).OnUploadControlValidationErrorOccurred(evt);
};
ASPxClientFileManager.OnUploadControlTextChanged = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.UploadPostfix, !s.IsSplitterNestedControl()).OnUploadTextChanged(s.GetText());
};
ASPxClientFileManager.OnToolbarMenuItemClick = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.ToolbarPostfix, !s.IsSplitterNestedControl()).OnToolbarItemClick(evt.item.name);
};
ASPxClientFileManager.OnContextMenuItemClick = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.ContextMenuPostfix, true).OnContextMenuItemClick(evt.item.name);
};
ASPxClientFileManager.OnFolderBrowserPopupShown = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.FolderBrowserPopupPostfix, true).OnFolderBrowserDialogShown();
};
ASPxClientFileManager.OnFolderBrowserPopupClosing = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.FolderBrowserPopupPostfix, true).OnFolderBrowserDialogClosing();
};
ASPxClientFileManager.OnPaneResizeCompleted = function(s, evt) {
 ASPxClientFileManager.GetFileManagerByInnerControl(s.name, FileManagerConsts.SplitterPostfix, true).OnSplitterPaneResizeCompleted();
};
ASPxClientFileManager.GetFileManagerByInnerControl = function(controlName, controlPostfix, ignoreSplitter) {
 var controlIdPostfix = ignoreSplitter ? controlPostfix : FileManagerConsts.SplitterPostfix + controlPostfix;
 var fileManagerId = controlName.substr(0, controlName.length - controlIdPostfix.length);
 return ASPx.GetControlCollection().Get(fileManagerId);
};
ASPxClientFileManager.PrepareTemplate = function(template, values) {
 var result = template;
 for(var key in values) {
  if(!values.hasOwnProperty(key))
   continue;
  result = result.replace(new RegExp("{{" + key + "}}", 'g'), values[key]);
 }
 return result;
};
ASPxClientFileManager.FocusElement = function(element) {
 if(ASPx.Browser.Chrome)
  focusElementChrome(element);
 else
  element.focus();
};
var focusElementChrome = function(element) {
 var left = ASPx.GetDocumentScrollLeft(),
  top = ASPx.GetDocumentScrollTop();
 element.focus();
 ASPx.SetDocumentScrollLeft(left);
 ASPx.SetDocumentScrollTop(top);
};
var ASPxClientFileManagerFileEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(file) {
  this.constructor.prototype.constructor.call(this);
  this.file = file;
 }
});
var ASPxClientFileManagerFileOpenedEventArgs = ASPx.CreateClass(ASPxClientFileManagerFileEventArgs, {
 constructor: function(file) {
  this.constructor.prototype.constructor.call(this, file);
  this.processOnServer = false;
 }
});
var ASPxClientFileManagerActionEventArgsBase = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(fullName, name, isFolder) {
  this.constructor.prototype.constructor.call(this);
  this.fullName = fullName;
  this.name = name;
  this.isFolder = !!isFolder;
 }
});
var ASPxClientFileManagerItemEditingEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
  this.cancel = false;
 }
});
var ASPxClientFileManagerItemRenamedEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, oldName, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
  this.oldName = oldName;
 }
});
var ASPxClientFileManagerItemDeletedEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
 }
});
var ASPxClientFileManagerItemsDeletedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(items) {
  this.constructor.prototype.constructor.call(this);
  this.items = items;
 }
});
var ASPxClientFileManagerItemMovedEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, oldFolderFullName, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
  this.oldFolderFullName = oldFolderFullName;
 }
});
var ASPxClientFileManagerItemsMovedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(items, oldFolderFullName) {
  this.constructor.prototype.constructor.call(this);
  this.items = items;
  this.oldFolderFullName = oldFolderFullName;
 }
});
var ASPxClientFileManagerItemCopiedEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, oldFolderFullName, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
  this.oldFolderFullName = oldFolderFullName;
 }
});
var ASPxClientFileManagerItemsCopiedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(items, oldFolderFullName) {
  this.constructor.prototype.constructor.call(this);
  this.items = items;
  this.oldFolderFullName = oldFolderFullName;
 }
});
var ASPxClientFileManagerItemCreatedEventArgs = ASPx.CreateClass(ASPxClientFileManagerActionEventArgsBase, {
 constructor: function(fullName, name, isFolder) {
  this.constructor.prototype.constructor.call(this, fullName, name, isFolder);
 }
});
var ASPxClientFileManagerErrorEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(commandName, errorText, errorCode) {
  this.constructor.prototype.constructor.call(this);
  this.commandName = commandName;
  this.errorText = errorText;
  this.showAlert = true;
  this.errorCode = errorCode;
 }
});
var ASPxClientFileManagerErrorAlertDisplayingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(commandName, errorText, errorCode) {
  this.constructor.prototype.constructor.call(this);
  this.commandName = commandName;
  this.errorText = errorText;
  this.showAlert = true;
 }
});
var ASPxClientFileManagerFileUploadingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(folder, fileName) {
  this.constructor.prototype.constructor.call(this);
  this.folder = folder;
  this.fileName = fileName;
  this.cancel = false;
 }
});
var ASPxClientFileManagerFilesUploadingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(folder, fileNames) {
  this.constructor.prototype.constructor.call(this);
  this.folder = folder;
  this.fileNames = fileNames;
  this.cancel = false;
 }
});
var ASPxClientFileManagerFileUploadedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(folder, fileName) {
  this.constructor.prototype.constructor.call(this);
  this.folder = folder;
  this.fileName = fileName;
 }
});
var ASPxClientFileManagerFilesUploadedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(folder, fileNames) {
  this.constructor.prototype.constructor.call(this);
  this.folder = folder;
  this.fileNames = fileNames;
 }
});
var ASPxClientFileManagerFileDownloadingEventArgs = ASPx.CreateClass(ASPxClientFileManagerFileEventArgs, {
 constructor: function(file) {
  this.constructor.prototype.constructor.call(this, file);
  this.cancel = false;
 }
});
var ASPxClientFileManagerFocusedItemChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(item, name, fullName) {
  this.constructor.prototype.constructor.call(this);
  this.item = item;
  this.name = name;
  this.fullName = fullName;
 }
});
var ASPxClientFileManagerCurrentFolderChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(name, fullName) {
  this.constructor.prototype.constructor.call(this);
  this.name = name;
  this.fullName = fullName;
 }
});
var ASPxClientFileManagerSelectionChangedEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(item, name, fullName, isSelected) {
  this.constructor.prototype.constructor.call(this);
  this.item = item;
  this.name = name;
  this.fullName = fullName;
  this.isSelected = isSelected;
 }
});
var ASPxClientFileManagerCustomCommandEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(commandName) {
  this.constructor.prototype.constructor.call(this);
  this.commandName = commandName;
 }
});
var ASPxClientFileManagerToolbarUpdatingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(activeAreaName) {
  this.constructor.prototype.constructor.call(this);
  this.activeAreaName = activeAreaName;
 }
});
var ASPxClientFileManagerHighlightItemTemplateEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(filterValue, itemName, templateElement, highlightCssClassName) {
  this.constructor.prototype.constructor.call(this);
  this.filterValue = filterValue;
  this.itemName = itemName;
  this.templateElement = templateElement;
  this.highlightCssClassName = highlightCssClassName;
 }
});
ASPxClientFileManager.StylesHelper = {};
ASPxClientFileManager.StylesHelper.Styles = ["Border", "Padding", "Margin"];
ASPxClientFileManager.StylesHelper.Kinds = ["Left", "Right", "Top", "Bottom"];
ASPxClientFileManager.StylesHelper.GetStylesInfo = function(width, height, elementsContainer, elementsStyles) {
 this.elements = [];
 var currentStyles = [];
 for(var i = 0; i < elementsStyles.length; i++)
  currentStyles.push(this.GetCurrentStyle(elementsContainer, elementsStyles[i]));
 var result = this.GetStylesInfoCore(width, height, currentStyles);
 this.DropCurrentStyles(elementsContainer);
 for(var i = 0; i < elementsStyles.length; i++)
  result.styleStrings[i] += this.GetUnprocessedStylesString(elementsStyles[i][1]);
 return result;
};
ASPxClientFileManager.StylesHelper.GetCurrentStyle = function(elementsContainer, styles) {
 var element = ASPx.CreateHtmlElementFromString("<div class=\"" + styles[0] + "\" style=\"visibility:hidden;" + styles[1] + "\"></div>");
 elementsContainer.appendChild(element);
 this.elements.push(element);
 return ASPx.GetCurrentStyle(element);
};
ASPxClientFileManager.StylesHelper.DropCurrentStyles = function(elementsContainer) {
 for(var i = 0; i < this.elements.length; i++)
  elementsContainer.removeChild(this.elements[i]);
};
ASPxClientFileManager.StylesHelper.GetUnprocessedStylesString = function(stylesString) {
 var processingStyles = [];
 for(var i = 0; i < this.Styles.length; i++)
  processingStyles.push(this.Styles[i].toLowerCase());
 var result = [];
 var stylesToSkip = ["margin", "padding", "border-width"];
 var styleParts = stylesString.split(';');
 for(var i = 0; i < styleParts.length; i++) {
  var stylePart = styleParts[i];
  var skippFlag = false;
  for(var j = 0; j < stylesToSkip.length; j++) {
   if(stylePart.toLowerCase().indexOf(stylesToSkip[j]) == 0) {
    skippFlag = true;
    break;
   }
  }
  if(!skippFlag)
   result.push(stylePart);
 }
 return result.join(';');
};
ASPxClientFileManager.StylesHelper.GetStylesInfoCore = function(width, height, currentStyles) {
 var stylesTables = this.GetStylesTables(currentStyles);
 var styleStrings = [];
 for(var i = 0; i < stylesTables.length; i++)
  styleStrings.push(this.StylesTableToString(stylesTables[i]));
 var itemStylesTable = stylesTables[0];
 return {
  contentWidth: width - (itemStylesTable.Border.Left + itemStylesTable.Border.Right + itemStylesTable.Padding.Left + itemStylesTable.Padding.Right),
  contentHeight: height - (itemStylesTable.Border.Top + itemStylesTable.Border.Bottom + itemStylesTable.Padding.Top + itemStylesTable.Padding.Bottom),
  styleStrings: styleStrings
 };
};
ASPxClientFileManager.StylesHelper.GetStylesTables = function(currentStyles) {
 var itemStylesTable = this.GetStylesTable(currentStyles[0]);
 var result = [itemStylesTable];
 for(var i = 1; i < currentStyles.length; i++) {
  result.push(this.GetStylesTable(currentStyles[i]));
  for(var j = 0; j < this.Kinds.length; j++)
   this.UpdateItemStylesTable(itemStylesTable, result[i], this.Kinds[j]);
 }
 for(var i = 1; i < result.length; i++) {
  for(var j = 0; j < this.Kinds.length; j++)
   this.UpdateStateStylesTable(itemStylesTable, result[i], this.Kinds[j]);
 }
 return result;
};
ASPxClientFileManager.StylesHelper.UpdateItemStylesTable = function(baseStylesTable, stylesTable, kind) {
 baseStylesTable.Margin[kind] += Math.max(               
  stylesTable.Border[kind] + stylesTable.Padding[kind] - baseStylesTable[kind + "Sum"],   
  0
 );
};
ASPxClientFileManager.StylesHelper.UpdateStateStylesTable = function(baseStylesTable, stylesTable, kind) {
 var borderChange = stylesTable.Border[kind] - baseStylesTable.Border[kind];
 var paddingChange = stylesTable.Padding[kind] - baseStylesTable.Padding[kind];
 if(stylesTable.Padding[kind] != 0)
  stylesTable.Margin[kind] = baseStylesTable.Margin[kind] - (paddingChange + borderChange);
 else {
  stylesTable.Padding[kind] = baseStylesTable.Padding[kind] - borderChange;
  stylesTable.Margin[kind] = baseStylesTable.Margin[kind];
  if(stylesTable.Padding[kind] < 0) {
   stylesTable.Margin[kind] += stylesTable.Padding[kind];
   stylesTable.Padding[kind] = 0;
  }
 }
};
ASPxClientFileManager.StylesHelper.GetBorder = function(currentStyle, borderKind) {
 var borderStyleName = "border" + borderKind + "Style";
 var borderWidthName = "border" + borderKind + "Width";
 if(currentStyle[borderStyleName] != "none")
  return ASPx.PxToInt(currentStyle[borderWidthName]);
 return 0;
};
ASPxClientFileManager.StylesHelper.GetPadding = function(currentStyle, paddingKind) {
 return ASPx.PxToInt(currentStyle["padding" + paddingKind]);
};
ASPxClientFileManager.StylesHelper.GetMargin = function(currentStyle, marginKind) {
 return ASPx.PxToInt(currentStyle["margin" + marginKind]);
};
ASPxClientFileManager.StylesHelper.BorderToString = function(kind, border) {
 return "border-" + kind.toLowerCase() + "-width:" + border + "px;";
};
ASPxClientFileManager.StylesHelper.PaddingToString = function(kind, padding) {
 return "padding-" + kind.toLowerCase() + ":" + padding + "px;";
};
ASPxClientFileManager.StylesHelper.MarginToString = function(kind, margin) {
 return "margin-" + kind.toLowerCase() + ":" + margin + "px;";
};
ASPxClientFileManager.StylesHelper.GetStylesTable = function(currentStyle) {
 var result = {};
 for(var i = 0; i < this.Styles.length; i++)
  result[this.Styles[i]] = {};
 for(var i = 0; i < this.Kinds.length; i++)
  result[this.Kinds[i] + "Sum"] = 0;
 for(var i = 0; i < this.Styles.length; i++) {
  var style = this.Styles[i];
  var getStyle = this["Get" + style];
  for(var j = 0; j < this.Kinds.length; j++) {
   var kind = this.Kinds[j];
   result[style][kind] = getStyle(currentStyle, kind);
   result[kind + "Sum"] += result[style][kind];
  }
 }
 return result;
};
ASPxClientFileManager.StylesHelper.StylesTableToString = function(stylesTable) {
 var styleString = "";
 for(var i = 0; i < this.Styles.length; i++) {
  var style = this.Styles[i];
  var toStringFunc = this[style + "ToString"];
  for(var j = 0; j < this.Kinds.length; j++) {
   var kind = this.Kinds[j];
   styleString += toStringFunc(kind, stylesTable[style][kind]);
  }
 }
 return styleString;
};
ASPxClientFileManager.FilterBoxHelper = ASPx.CreateClass(null, {
 constructor: function(fileManager) {
  this.fileManager = fileManager;
  this.delayedFilter = null;
  this.InitFilterBoxEditor();
 },
 InitFilterBoxEditor: function() {
  this.editor = this.fileManager.GetToolbarFilterTextBox();
  if(this.editor)
   this.editor.KeyUp.AddHandler(function() { this.OnInputValueChanged(); }.bind(this));
 },
 OnInputValueChanged: function() {
  var _this = this;
  var value = this.editor.GetText();
  if(this.filterTimerID > -1)
   ASPx.Timer.ClearTimer(this.filterTimerID);
  if(this.delayedFilter !== null)
   this.delayedFilter = value;
  this.filterTimerID = window.setTimeout(function() {
   _this.Filter(value);
  }, this.fileManager.filterDelay);
 },
 Filter: function(value) {
  if(this.HasRequestOnServer())
   return;
  if(this.filterTimerID)
   ASPx.Timer.ClearTimer(this.filterTimerID);
  if(this.GetText() != value) {
   this.UpdateText(value);
   if(this.fileManager.RequireApplyFilterBoxTextOnServer())
    this.applyFilterOnServer(value);
   else
    this.applyFilterOnClient(value);
  }
 },
 applyFilterOnServer: function(value) {
  this.delayedFilter = value;
  this.fileManager.SendCallback(ASPxClientFileManagerCallbackCommand.GetFileList, { keepFilter: true});
 },
 applyFilterOnClient: function(value) {
  this.fileManager.forEachItem(function(item) {
   if(item.isParentFolderItem|| item.isCreateHelperFolder)
    return;
   var isSatisfy = item.name.toLowerCase().indexOf(value.toLowerCase()) != -1;
   item.SetVisible(isSatisfy);
   this.HighlightItem(item, value);
  }.aspxBind(this));
  this.fileManager.resetSelection();
 },
 applyDelayedFilter: function() {
  var delayedFilter = this.delayedFilter;
  this.delayedFilter = null;
  if(this.GetText() !== delayedFilter && !this.GetIsFilterTextChangedOnServer())
   this.Filter(delayedFilter);
 },
 HighlightItems: function() {
  var value = this.GetText();
  if(!value) return;
  this.fileManager.forEachItem(function(item) {
   this.HighlightItem(item, value);
  }.aspxBind(this));
 },
 HighlightItem: function(item, value) {
  if(!item.GetVisible() || item.isParentFolderItem)
   return;
  if(!this.fileManager.GetIsFilterViewActive()) {
   if(this.fileManager.isThumbnailOrFilterViewMode() && this.fileManager.isThumbnailsViewFileAreaItemTemplate) {
    this.fileManager.raiseHighlightItemTemplate(value, item.name, item.itemContentElement, this.fileManager.styles.highlightCssClass);
    return;
   }
   if(this.fileManager.isDetailsViewMode() && this.fileManager.nameColumnHasTemplate) {
    var templateContainer = ASPx.GetChildByClassName(item.getElement(), FileManagerConsts.GridColumnTitleCellClassName);
    if(!templateContainer)
     return;
    this.fileManager.raiseHighlightItemTemplate(value, item.name, templateContainer, this.fileManager.styles.highlightCssClass);
    return;
   }
  }
  var titleElement = this.fileManager.elements.GetItemTitleElement(item);
  if(!titleElement)
   return;
  var name = item.name;
  var highlightedText = name;
  if(value && value.length > 0) {
   var startIndex = name.toLowerCase().indexOf(value.toLowerCase());
   if(startIndex > -1) {
    highlightedText = ASPxClientFileManager.PrepareTemplate(
     FileManagerConsts.Templates.HighlightedText,
     {
      textStart: name.substr(0, startIndex),
      textMiddle: name.substr(startIndex, value.length),
      textEnd: name.substr(startIndex + value.length),
      highlightCssClass: this.fileManager.styles.highlightCssClass
     }
    );
   }
  }
  titleElement.innerHTML = highlightedText;
 },
 setEditorValue: function(value) {
  if(this.editor)
   this.editor.SetText(value);
 },
 UpdateEnabled: function(enabled) {
  if(this.editor)
   this.editor.SetEnabled(enabled);
 },
 Initialize: function() {
  if(this.GetText()) {
   this.Update();
   this.HighlightItems();
  }
 },
 Update: function() {
  this.setEditorValue(this.GetText());
 },
 UpdateText: function(value) {
  this.fileManager.UpdateStateField(FileManagerConsts.StateField.FilterBoxText, value);
  this.fileManager.DropStateField(FileManagerConsts.StateField.FilterTextCnagedOnServer);
  this.fileManager.UpdateClientStateCookie();
 },
 GetText: function() { return this.fileManager.GetStateField(FileManagerConsts.StateField.FilterBoxText) || "";  }, 
 GetIsFilterTextChangedOnServer: function() { return !!this.fileManager.GetStateField(FileManagerConsts.StateField.FilterTextCnagedOnServer); },
 HasRequestOnServer: function() { return this.delayedFilter !== null; },
 OnCallbackFinalized: function() {
  this.HighlightItems();
  if(this.HasRequestOnServer())
   this.applyDelayedFilter();
 }
});
ASPxClientFileManager.ElementsHelper = ASPx.CreateClass(null, {
 constructor: function(fileManager) {
  this.fileManager = fileManager;
  this.itemsContainerId = this.fileManager.name + FileManagerConsts.SplitterPostfix + FileManagerConsts.ItemsPostfix;
  this.focusId = this.fileManager.name + "_Focus";
  this._sbPane = this.GetSplitterPane("UploadPanelPane");
  if(this._sbPane)
   this._sbPaneElement = this._sbPane.helper.GetContentContainerElement();
  this._bcPane = this.GetSplitterPane("BreadCrumbsPane");
  if(this._bcPane)
   this._bcPaneElement = this._bcPane.helper.GetContentContainerElement();
  var itemsPane = this.GetSplitterPane("ItemsPane");
  if(itemsPane)
   this._itemsPaneElement = itemsPane.helper.GetContentContainerElement();
  this._tbPane = this.GetSplitterPane("ToolbarPane");
  if(this._tbPane)
   this._tbPaneElement = this._tbPane.helper.GetContentContainerElement();
  this._itemsContainer = null;
  this._fcPane = this.GetSplitterPane("FoldersPane");
  if(this._fcPane)
   this._foldersContainer = this._fcPane.helper.GetContentContainerElement();
  this._renameInput = document.getElementById(this.fileManager.name + FileManagerConsts.RenameFileInputPostfix);
  this.emptyPageElementsInfo = [];
 },
 GetSplitterPane: function(name) {
  return this.fileManager.GetSplitter().GetPaneByName(name);
 },
 GetItemsContainer: function() {
  if(this.fileManager.isDetailsViewMode())
   return null;
  if(!ASPx.IsValidElement(this._itemsContainer))
   this._itemsContainer = document.getElementById(this.itemsContainerId);
  if(!this._itemsContainer) {
   this._itemsContainer = ASPx.CreateHtmlElementFromString("<div id=\"" + this.itemsContainerId + "\"></div>");
   this._itemsPaneElement.appendChild(this._itemsContainer);
  }
  if(!this.itemsContainerPrepared)
   this.PrepareItemsContainer();
  return this._itemsContainer;
 },
 PrepareItemsContainer: function() {
  this._itemsContainer.className = this.GetFileContainerClassName();
  if(this.fileManager.allowMultiSelect)
   ASPx.AddClassNameToElement(this._itemsContainer, this.GetMultiSelectClassName());
  if(this.fileManager.GetIsFilterViewActive())
   ASPx.AddClassNameToElement(this._itemsContainer, this.GetFilterViewClassName());
  this.itemsContainerPrepared = true;
 },
 GetFoldersNodeContentElementTagName: function() {
  return this.fileManager.accessibilityCompliant ? "A" : "DIV";
 },
 GetFolderContentContainerClassName: function() {
  return FileManagerConsts.FolderContentContainerClassName;
 },
 GetFileContainerClassName: function() {
  return FileManagerConsts.FileContainerClassName;
 },
 GetFileClassName: function() {
  return FileManagerConsts.FileClassName;
 },
 GetMultiSelectClassName: function() {
  return FileManagerConsts.MultiSelectClassName;
 },
 GetFilterViewClassName: function() {
  return FileManagerConsts.FilterViewClassName;
 },
 GetVerticalCenteringClassName: function() {
  return "dx-vam";
 },
 GetItemsPaneContainer: function() {
  return this._itemsPaneElement;
 },
 DropItemsContainer: function() {
  var filesContainer = this.GetItemsContainer();
  if(filesContainer)
   filesContainer.parentNode.removeChild(this._itemsContainer);
  this._itemsContainer = null;
  this.itemsContainerPrepared = false;
  this.emptyPageElementsInfo = [];
 },
 GetUploadPanelContainer: function() {
  return this._sbPaneElement;
 },
 GetUploadPanelPane: function() {
  return this._sbPane;
 },
 GetBreadCrumbsPaneContainer: function() {
  return this._bcPaneElement;
 },
 GetToolbarPane: function() {
  return this._tbPane;
 },
 GetToolBarContainer: function() {
  return this._tbPaneElement;
 },
 GetToolbarWrapper: function() {
  return ASPx.GetChildByClassName(this.GetToolBarContainer(), FileManagerConsts.ToolbarWrapperClassName);
 },
 GetFolderContainerPane: function() {
  return this._fcPane;
 },
 GetFoldersContainer: function() {
  return this._foldersContainer;
 },
 GetFocusInput: function() {
  if(!this._focusInput)
   this._focusInput = this.PrepareFocusInput(this.GetItemsPaneContainer(), this.focusId);
  return this._focusInput;
 },
 GetAccessibilityInput: function() {
  if(!this._accessibilityInput)
   this._accessibilityInput = this.PrepareFocusInput(this.GetItemsPaneContainer(), "");
  return this._accessibilityInput;
 },
 PrepareFocusInput: function(parent, id) {
  var input = ASPx.CreateHtmlElementFromString("<input type=\"text\" id=\"" + id + "\"></div>");
  ASPx.SetStyles(input, {
   left: ASPx.AbsoluteLeftPosition,
   top: ASPx.InvalidPosition,
   position: "absolute"
  });
  parent.appendChild(input);
  return input;
 },
 ensurePageIndentsCreated: function() {
  if(this.pageIndentsCreated) return;
  this.pageTopIndentElement = this.creagePageIndent();
  this.pageBottomIndentElement = this.pageTopIndentElement.cloneNode(true);
  var itemsContainer = this.GetItemsContainer();
  if(this.fileManager.isThumbnailsViewFileAreaItemTemplate)
   itemsContainer.insertBefore(this.pageTopIndentElement, itemsContainer.firstChild);
  else
   itemsContainer.appendChild(this.pageTopIndentElement);
  itemsContainer.appendChild(this.pageBottomIndentElement);
  this.pageIndentsCreated = true;
 },
 creagePageIndent: function() {
  if(!this.fileManager.GetIsFilterViewActive())
   return ASPx.CreateHtmlElementFromString(this.GetPageIndentTemplate());
  var dummy = ASPx.CreateHtmlElement();
  dummy.innerHTML = FileManagerConsts.Templates.FilterViewPageIndent;
  var row = dummy.firstChild;
  if(this.fileManager.allowMultiSelect) {   
   checkBoxCell = ASPx.CreateHtmlElementFromString("<div class=\"" + FileManagerConsts.FilterViewCheckBoxCellClassName + "\"></div>");
   row.insertBefore(checkBoxCell, row.firstChild);
  }
  return row;
 },
 GetPageIndentTemplate: function() {
  return FileManagerConsts.Templates.PageIndent;
 },
 dropPageIndents: function() {
  this.pageTopIndentElement = null;
  this.pageBottomIndentElement = null;
  this.pageIndentsCreated = false;
 },
 addItemElementToItemsArea: function(element) {
  var itemsContainer = this.GetItemsContainer();
  if(this.fileManager.isVirtScrollEnabled())
   itemsContainer.insertBefore(element, this.pageBottomIndentElement);
  else
   itemsContainer.appendChild(element);
 },
 createItemElement: function(item) {
  var wrap = ASPx.CreateHtmlElementFromString("<div></div>");
  var fm = this.fileManager;
  var thumbnailWidth = fm.GetItemThumbnailSize();
  var thumbnailHeight = fm.GetItemThumbnailSize(true);
  var fileImage = item.type == "File" ? fm.noThumbnailImage : fm.folderThumbnailImageRender;
  if(item.imageIndex > -1 && fm.customThumbnails[item.imageIndex]) {
   wrap.innerHTML = fm.customThumbnails[item.imageIndex];
   this.prepareItemCustomThumbnailImage(wrap, thumbnailWidth, thumbnailHeight);
   fileImage = wrap.innerHTML;
  }
  else if(item.imageSrc) {
   var img = this.createItemThumbnailImage(item.imageSrc, thumbnailWidth, thumbnailHeight);
   this.disableDraggable(img);
   wrap.appendChild(img);
   fileImage = wrap.innerHTML;
  }
  var element = this.CreateItemHtmlElement(item, fileImage);
  if(item.isCreateHelperFolder)
   ASPx.AddClassNameToElement(element, FileManagerConsts.CreateHelperElementClassName);
  this.addItemElementToItemsArea(element);
  return element;
 },
 createItemThumbnailImage: function(thumbnailUrl, thumbnailWidth, thumbnailHeight) {
  var imageElement = document.createElement("img");
  ASPx.ImageUtils.SetImageSrc(imageElement, thumbnailUrl);
  ASPx.ImageUtils.SetSize(imageElement, thumbnailWidth, thumbnailHeight);
  return imageElement;
 },
 prepareItemCustomThumbnailImage: function(parentElement, thumbnailWidth, thumbnailHeight) {
  var img = ASPx.GetNodeByTagName(parentElement, "IMG", 0);
  if(img) {
   ASPx.ImageUtils.SetImageSrc(img, ASPx.ImageUtils.GetImageSrc(img));
   ASPx.ImageUtils.SetSize(img, thumbnailWidth, thumbnailHeight);
  }
 },
 CreateItemHtmlElement: function(item, fileImage) {
  var elementHtml = ASPxClientFileManager.PrepareTemplate(this.GetItemTemplate(), this.GetItemTemplateInfo(item, fileImage));
  return ASPx.CreateHtmlElementFromString(elementHtml);
 },
 GetItemTemplate: function() {
  if(this.fileManager.GetIsFilterViewActive())
   return this.GetFilterViewItemTemplate();
  return this.GetItemTemplateCore();
 },
 GetItemTemplateCore: function() {
  return FileManagerConsts.Templates.Item;
 },
 GetFilterViewItemTemplate: function() {
  return FileManagerConsts.Templates.FilterViewItem;
 },
 GetItemTemplateInfo: function(item, fileImage) {
  var fileName = this.fileManager.isThumbnailsViewFileAreaItemTemplate ? "" : item.encodedName;
  var info = { itemId: item.elementID, fileImage: fileImage, fileName: fileName };
  if(item.filterViewInfo) {
   info.fileLocation = item.filterViewInfo[0];
   info.fileDateCaption = item.filterViewInfo[3];
   info.fileDate = item.filterViewInfo[4];
   info.fileSizeCaption = item.filterViewInfo[1];
   info.fileSize = item.filterViewInfo[2];
  }
  return info;
 },
 createItemCheckBoxInstance: function(item) {
  var checkboxInput = document.getElementById(item.elementID + FileManagerConsts.CheckboxPostfix);
  if(!checkboxInput)
   return;
  if(!this.fileManager.internalCheckBoxCollection)
   this.fileManager.internalCheckBoxCollection = new ASPx.CheckBoxInternalCollection(this.fileManager.checkBoxImageProperties);
  var internalCheckBox = this.fileManager.internalCheckBoxCollection.Add(checkboxInput.id, checkboxInput);
  internalCheckBox.CreateFocusDecoration(this.fileManager.icbFocusedStyle);
  internalCheckBox.CheckedChanged.AddHandler(function(s, e) {
   item.SetSelected(s.GetChecked());
   if(this.fileManager.allowMultiSelect)
    item.focus(false, true);
  }.aspxBind(item));
  item.checkBox = internalCheckBox;
 },
 getCheckBoxByEvt: function(evt) {
  return ASPx.GetParentByPartialClassName(ASPx.Evt.GetEventSource(evt), "dxichSys");
 },
 PrepareItemElement: function(item, tooltip) {
  ASPx.Attr.SetAttribute(item.element, "title", tooltip.replace(/&/g, "&amp;"));
  ASPx.AddClassNameToElement(item.element, item.cssClass);
  ASPx.AddClassNameToElement(item.itemContentElement, item.contentCssClass);
 },
 disableImagesDraggable: function(element) {
  var images = ASPx.GetNodesByTagName(element, "img");
  if(images && images.length) {
   for(var i = 0; i < images.length; i++)
    this.disableDraggable(images[i]);
  }
 },
 disableDraggable: function(element) {
  if(("draggable" in element) && !ASPx.Attr.IsExistsAttribute(element, "ondragstart"))
   ASPx.Attr.SetAttribute(element, "ondragstart", "return false;");
 },
 createDetailsCreateHelperItemElement: function(item) {
  if(ASPx.IsExists(item.element))
   ASPx.RemoveElement(item.element);
  var grid = this.fileManager.GetFilesGridView();
  var element = grid.getHeaderFirstRow().cloneNode(true);
  ASPx.GetChildByTagName(grid.GetMainTable(), "TBODY").appendChild(element);
  item.element = element;
  this.fileManager.HideCreateHelperElement();
  setTimeout(function() { this.prepareDetailsCreateHelperElement(element); }.aspxBind(this), 0);
 },
 prepareDetailsCreateHelperElement: function(element) {
  var grid = this.fileManager.GetFilesGridView();
  if(!grid || !this.fileManager.isDetailsViewMode())
   return;
  ASPx.AddClassNameToElement(element, this.fileManager.styles.filesGridViewDataRowCssClass);
  ASPx.AddClassNameToElement(element, FileManagerConsts.CreateHelperElementClassName);
  var cells = ASPx.GetChildElementNodes(element);
  var hMatrix = grid.GetHeaderMatrix();
  hMatrix.EnsureMatrix();
  for(var i = 0, cell; cell = cells[i]; i++) {
   ASPx.AddClassNameToElement(cell, "dxgv");
   var columnIndex = hMatrix.matrix[0][i];
   if(grid.GetColumn(columnIndex).isCommandColumn)
    ASPx.AddClassNameToElement(cell, FileManagerConsts.CreateHelperGridCommandCellClassName);
   if(grid.GetColumnByField("Name") && columnIndex == grid.GetColumnByField("Name").index)
    ASPx.AddClassNameToElement(cell, FileManagerConsts.GridColumnTitleCellClassName);
   if(grid.GetColumnByField("ThumbnailUrl") && columnIndex == grid.GetColumnByField("ThumbnailUrl").index) {
    var thumbnail = ASPx.CreateHtmlElementFromString(this.fileManager.folderThumbnailImageRender);
    cell.appendChild(thumbnail);
    ASPx.AddClassNameToElement(cell, FileManagerConsts.ThumbnailCellClassName);
   }
  }
 },
 GetItemElement: function(item) {
  if(this.fileManager.isThumbnailOrFilterViewMode())
   return document.getElementById(item.elementID);
  else {
   var grid = this.fileManager.GetFilesGridView();
   var index = grid.GetRowIndexByKey(item.id);
   return grid.GetItem(index);
  }
 },
 GetItemTitleElement: function(item) {
  var fileElement = item.getElement();
  if(this.fileManager.GetIsFilterViewActive()) {
   var node = ASPx.GetNodesByPartialClassName(fileElement, FileManagerConsts.FilterViewFileNameCellClassName)[0];
   return node != null ? node.firstElementChild : null;
  }
  if(this.fileManager.isThumbnailOrFilterViewMode())
   return this.GetThumbnailItemTitleElement(fileElement);
  var fileNameCell = ASPx.GetNodeByClassName(fileElement, FileManagerConsts.GridColumnTitleCellClassName);
  return fileNameCell != null ? fileNameCell.firstChild : null;
 },
 GetThumbnailItemTitleElement: function(itemElement) {
  return ASPx.GetNodeByTagName(itemElement.childNodes[0], "DIV", 0);
 },
 PrepareRenameInputElement: function(neighborElement, size, absolutePosition) {
  var input = this.GetRenameInputElement();
  var width = size ? size.width : null;
  input.style.width = "";
  if(neighborElement) {
   if(absolutePosition) {
    var parent = input.parentNode;
    input.style.position = "absolute";
    input.style.bottom = ASPx.GetAbsolutePositionY(neighborElement) - ASPx.GetAbsolutePositionY(parent) + "px";
    if(input.offsetWidth > ASPx.GetClearClientWidth(parent))
     this.SetElementOffsetWidth(input, ASPx.GetClearClientWidth(parent));
    input.style.left = (parent.offsetWidth - ASPx.GetHorizontalBordersWidth(parent) - width) / 2 + "px";
   } else {
    input.style.position = "";
    this.SetElementOffsetHeight(input, neighborElement.offsetHeight);
    width = width ? width : neighborElement.offsetWidth;
   }
  }
  if(size && size.height)
   this.SetElementOffsetHeight(input, size.height);
  this.SetElementOffsetWidth(input, width);
 },
 GetRenameInputElement: function() {
  return this._renameInput;
 },
 GetRenameElementArea: function() {
  var input = this.GetRenameInputElement(this);
  if(!ASPx.GetElementDisplay(input) || !input.parentNode)
   return FileManagerConsts.SelectedArea.None;
  var parent = input.parentNode;
  if(ASPx.GetParentByPartialClassName(input, this.GetFileClassName()))
   return FileManagerConsts.SelectedArea.Files;
  if(ASPx.GetParentByPartialClassName(parent, this.GetFolderContentContainerClassName()))
   return FileManagerConsts.SelectedArea.Folders;
 },
 GetRenameMask: function() {
  if(!this._renameMask)
   this._renameMask = ASPx.CreateHtmlElementFromString("<div class='" + FileManagerConsts.ItemMaskClassName + "'></div>");
  return this._renameMask;
 },
 CalculateTextSize: function(text, parentNode) {
  var parentNodeSizes = { width: ASPx.GetClearClientWidth(parentNode), height: ASPx.GetClearClientHeight(parentNode) };
  var calculateSizeHelper = document.createElement("span");  
  calculateSizeHelper.innerHTML = text;
  parentNode.appendChild(calculateSizeHelper);
  var width = calculateSizeHelper.offsetWidth + FileManagerConsts.RenameInputAdditionalWidth;
  if(width < FileManagerConsts.DefaultRenameInputWidth)
   width = FileManagerConsts.DefaultRenameInputWidth;
  else if(width > parentNodeSizes.width)
   width = parentNodeSizes.width;
  var height = calculateSizeHelper.offsetHeight + 4;
  if(height > parentNodeSizes.height)
   height = parentNodeSizes.height;
  calculateSizeHelper.parentNode.removeChild(calculateSizeHelper);
  return { width: width, height: height };  
 },
 GetFolderBrowserPopupFoldersContainer: function() {
  return document.getElementById(this.fileManager.name + FileManagerConsts.FolderBrowserPopupPostfix + FileManagerConsts.FolderBrowserFoldersContainerPostfix);
 },
 GetFolderBrowserDialogOkButton: function() {
  return document.getElementById(this.fileManager.name + FileManagerConsts.FolderBrowserPopupPostfix + FileManagerConsts.FolderBrowserDialogOkButtonPostfix);
 },
 GetFolderBrowserDialogCancelButton: function() {
  return document.getElementById(this.fileManager.name + FileManagerConsts.FolderBrowserPopupPostfix + FileManagerConsts.FolderBrowserDialogCancelButtonPostfix);
 },
 GetUploadPanelElement: function() {
  return ASPx.GetChildByTagName(this.GetUploadPanelContainer(), "TABLE");
 },
 GetUploadButtonElement: function() {
  return document.getElementById(this.fileManager.name + FileManagerConsts.SplitterPostfix + FileManagerConsts.UploadButtonPostfix);
 },
 GetProgressPopupCancelButtonElement: function() {
  return document.getElementById(this.fileManager.name + FileManagerConsts.UploadProgressPopupPostfix + FileManagerConsts.UploadPopupCancelButtonPostfix);
 },
 getToolbarPathElementId: function() {
  return this.getToolbarElementId(FileManagerConsts.ToolbarName.Path, this.getToolbarTextBoxClassName());
 },
 getToolbarFilterElementId: function() {
  return this.getToolbarElementId(FileManagerConsts.ToolbarName.Filter, this.getToolbarTextBoxClassName());
 },
 getToolbarTextBoxClassName: function() {
  return FileManagerConsts.TextBoxClassName;
 },
 getToolbarElementId: function(itemName, className) {
  var key = "_toolbar" + itemName + "Id";
  if(this[key] === undefined)
   this[key] = this.getToolbarElementIdInternal(itemName, className);
  return this[key];
 },
 getToolbarElementIdInternal: function(itemName, className) {
  var toolbar = this.fileManager.GetToolbar();
  if(!toolbar)
   return null;
  var itemName = this.fileManager.GetMenuStandardItemFullName(itemName);
  var pathItem = toolbar.GetItemByName(itemName);
  if(!pathItem)
   return null;
  var indexPath = pathItem.indexPath;
  var templateElement = toolbar.GetItemTemplateContainer(indexPath);
  var element = ASPx.GetNodeByClassName(templateElement, className);
  return element.id;
 },
 SetElementOffsetHeight: function(element, height) {
  ASPx.SetOffsetHeight(element, height);
 },
 SetElementOffsetWidth: function(element, width) {
  ASPx.SetOffsetWidth(element, width);
 }
});
var FilterViewHelper = ASPx.CreateClass(null, {
 constructor: function(fileManager) {
  this.fileManager = fileManager;  
 },
 GetItemsContainer: function() {
  return this.fileManager.elements.GetItemsContainer();
 },
 GetItemsPaneContainer: function() {
  return this.fileManager.elements.GetItemsPaneContainer();
 },
 UpdateFilterViewOnResize: function() {
  this.ResetFilterViewAdaptivity();
  this.CalculateFilterViewAdaptivity();
 },
 ResetFilterViewAdaptivity: function() {
  var row = ASPx.GetChildByPartialClassName(this.GetItemsContainer(), FileManagerConsts.FilterViewRowClassName);
  if(!row) return;
  this.MoveFilterViewSizeContentToSizeColumn();
  this.ChangeFilterViewColumnVisibilty(FileManagerConsts.FilterViewSizeCellClassName, true);
  this.ChangeFilterViewColumnVisibilty(FileManagerConsts.FilterViewDateCellClassName, true);
  this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewImageCellClassName, this.fileManager.GetItemThumbnailSize() + "px");
  this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewFileNameCellClassName, "");
  this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewDateCellClassName, "");
  this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewSizeCellClassName, "100%");
  this.EnsureFilterViewDateColumnWidthLimit(row);
 },
 CalculateFilterViewAdaptivity: function() {
  var row = ASPx.GetChildByPartialClassName(this.GetItemsContainer(), FileManagerConsts.FilterViewRowClassName);
  if(!row) return;
  if(!this.IsFilterViewSizeColumnCutted())
   return;
  this.MoveFilterViewSizeContentToDateColumn();
  this.ChangeFilterViewColumnVisibilty(FileManagerConsts.FilterViewSizeCellClassName, false);
  this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewDateCellClassName, "100%");
  if(this.IsFilterViewDateColumnCutted()) {
   this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewDateCellClassName, "");
   this.UpdateFilterViewCellWidth(row, FileManagerConsts.FilterViewFileNameCellClassName, "100%");
  }
  if(this.IsFilterViewNameColumnCutted())
   this.ChangeFilterViewColumnVisibilty(FileManagerConsts.FilterViewDateCellClassName, false);
 },
 GetFilterFiewCell: function(row, cellClassName) {
  return ASPx.GetChildByPartialClassName(row, cellClassName);
 },
 UpdateFilterViewCellWidth: function(row, cellClassName, width) {
  var cell = this.GetFilterFiewCell(row, cellClassName);
  if(cell)
   cell.style.width = width;
 },
 EnsureFilterViewDateColumnWidthLimit: function(row) {
  var dateCell = this.GetFilterFiewCell(row, FileManagerConsts.FilterViewDateCellClassName);
  if(dateCell)
   this.filterViewDateColumnMinWidth = ASPx.PxToInt(ASPx.GetCurrentStyle(dateCell).width);
 },
 ChangeFilterViewColumnVisibilty: function(columnClassName, visible) {
  ASPx.Data.ForEach(ASPx.GetNodesByPartialClassName(this.GetItemsContainer(), columnClassName), function(element) { 
   if(visible)
    ASPx.RemoveClassNameFromElement(element, FileManagerConsts.FilterViewHiddenColumnClassName);
   else
    ASPx.AddClassNameToElement(element, FileManagerConsts.FilterViewHiddenColumnClassName);
  });
 },
 IsFilterViewColumnCuttedCore: function(columnClassName, predicate) {
  var cells = ASPx.GetNodesByPartialClassName(this.GetItemsContainer(), columnClassName);
  return cells.some(predicate);
 },
 IsFilterViewNameColumnCutted: function() {
  return this.IsFilterViewColumnCuttedCore(FileManagerConsts.FilterViewFileNameCellClassName, function(cell){
   var div = cell.children[1];
   return div && div.offsetWidth < div.scrollWidth * 0.75;
  });
 },
 IsFilterViewSizeColumnCutted: function() {
  return this.IsFilterViewColumnCuttedCore(FileManagerConsts.FilterViewSizeCellClassName, function(cell){ return cell.offsetWidth < cell.scrollWidth; });
 },
 IsFilterViewDateColumnCutted: function() {
  var minWidth = this.filterViewDateColumnMinWidth;
  return this.IsFilterViewColumnCuttedCore(FileManagerConsts.FilterViewDateCellClassName, function(cell){ return cell.offsetWidth < minWidth; });  
 },
 MoveFilterViewSizeContentToDateColumn: function() {
  ASPx.Data.ForEach(ASPx.GetNodesByPartialClassName(this.GetItemsContainer(), FileManagerConsts.FilterViewRowClassName), function(row) { 
   var sourceCell = ASPx.GetChildByPartialClassName(row, FileManagerConsts.FilterViewSizeCellClassName);
   var destinationCell = ASPx.GetChildByPartialClassName(row, FileManagerConsts.FilterViewDateCellClassName);
   var contentContainer = ASPx.GetChildByPartialClassName(destinationCell, "dxfm-fvcc");
   if(!contentContainer) {
    contentContainer = ASPx.CreateHtmlElementFromString("<div class=\"dxfm-fvcc\"></div>");
    destinationCell.appendChild(contentContainer);
   }
   ASPx.MoveChildrenToElement(sourceCell, contentContainer);
  });  
 },
 MoveFilterViewSizeContentToSizeColumn: function() {
  ASPx.Data.ForEach(ASPx.GetNodesByPartialClassName(this.GetItemsContainer(), FileManagerConsts.FilterViewRowClassName), function(row) { 
   var destinationCell = ASPx.GetChildByPartialClassName(row, FileManagerConsts.FilterViewSizeCellClassName);
   var sourceCell = ASPx.GetChildByPartialClassName(row, FileManagerConsts.FilterViewDateCellClassName);
   var contentContainer = ASPx.GetChildByPartialClassName(sourceCell, "dxfm-fvcc");
   if(contentContainer)
    ASPx.MoveChildrenToElement(contentContainer, destinationCell);
  });  
 },
 DropFilterView: function() {
  var vilterView = ASPx.GetChildByPartialClassName(this.GetItemsPaneContainer(), FileManagerConsts.FilterViewClassName);
  if(vilterView)
   vilterView.parentNode.removeChild(vilterView);
 },
});
var TreeViewHelper = ASPx.CreateClass(null, {
 constructor: function(fileManager) {
  this.fileManager = fileManager;
  this.selectedNode = null;
 },
 saveSelectedNodeFromView: function() {
  this.setSelectedNode(this.getSelectedNodeInView());
 },
 setSelectedNode: function(node) {
  this.fileManager.currentPath = this.fileManager.GetFoldersPath(node, true);
  this.fileManager.currentIdPath = this.fileManager.GetFoldersPathArray(node, false, true);
  this.selectedNode = node;
 },
 setSelectedNodeInView: function(node) {
  this.getTreeView().SetSelectedNode(node);
 },
 getSelectedNodeInView: function() {
  return this.getTreeView().GetSelectedNode();
 },
 getSelectedNode: function() {
  return this.selectedNode;
 },
 getFilesRootNode: function() {
  return this.getTreeView().GetRootNode().GetNode(0);
 },
 scrollToSelectedNode: function() {
  var selectedNode = this.getSelectedNode();
  if(selectedNode)
   this.scrollToNode(selectedNode);
 },
 scrollToNode: function(node) {
  var nodeEl = node.GetHtmlElement();
  var pane = this.fileManager.elements.GetFolderContainerPane();
  var scrollValue = ASPx.GetAbsoluteY(nodeEl) - ASPx.GetAbsoluteY(pane.GetElement());
  if(scrollValue < 0)
   pane.SetScrollTop(pane.GetScrollTop() + scrollValue);
  else {
   scrollValue += nodeEl.clientHeight;
   if(scrollValue > pane.GetClientHeight())
    pane.SetScrollTop(pane.GetScrollTop() - pane.GetClientHeight() + scrollValue);
  }
 },
 getTreeView: function() {
  return this.fileManager.GetTreeView();
 }
});
ASPx.FileManagerTreeViewHelper = TreeViewHelper;
var FileManagerKbdHelper = ASPx.CreateClass(ASPx.KbdHelper, {
 CanFocus: function(e) {
  var src = ASPx.Evt.GetEventSource(e);
  if(src === this.control.elements.GetFocusInput())
   return true;
  if(this.control.isDetailsViewMode() && ASPx.GetIsParent(this.control.GetFilesGridView().GetMainElement(), src))
   return false;
  return ASPx.KbdHelper.prototype.CanFocus.call(this, e);
 },
 getFocusableElements: function() {
  return [this.GetFocusableElement(), this.control.elements.GetFocusInput()]; 
 },
 HandleKeyDown: function(e) {
  var modifier = this.control.getKeyModifier(e);
  var fm = this.control;
  var keyCode_A = 65;
  switch (ASPx.Evt.GetKeyCode(e)) {
   case ASPx.Key.Left:
    this.TryMoveFocusLeft(modifier);
    return true;
   case ASPx.Key.Right:
    this.TryMoveFocusRight(modifier);
    return true;
   case ASPx.Key.Up:
    this.TryMoveFocusUp(modifier);
    return true;
   case ASPx.Key.Down:
    this.TryMoveFocusDown(modifier);
    return true;
   case ASPx.Key.PageUp:
    this.TryMoveFocusPageUp(modifier);
    return true;
   case ASPx.Key.PageDown:
    this.TryMoveFocusPageDown(modifier);
    return true;
   case ASPx.Key.Enter:
    fm.KeyProcessEnter();
    return true;
   case ASPx.Key.Esc:
    fm.KeyProcessEsc();
    return true;
   case ASPx.Key.F2:
    fm.KeyProcessF2();
    return true;
   case ASPx.Key.F6:
    fm.KeyProcessF6();
    return true;
   case ASPx.Key.Delete:
    fm.KeyProcessDelete();
    return true;
   case ASPx.Key.Tab:
    fm.KeyProcessTab();
    return false;
   case ASPx.Key.F7:
    fm.KeyProcessF7();
    return true;
   case ASPx.Key.Space:
    fm.KeyProcessSpace();
    return true;
   case ASPx.Key.Home:
    fm.KeyProcessHome(modifier);
    return true;
   case ASPx.Key.End:
    fm.KeyProcessEnd(modifier);
    return true;
   case keyCode_A:
    if(modifier == FileManagerConsts.ModifierKey.Ctrl || modifier == FileManagerConsts.ModifierKey.Meta)
     fm.KeyProcessCtrlA();
    return true;
  }
  return false;
 },
 TryMoveFocusLeft: function(modifier) {
  this.TryMoveCore(-1, this.GetLeftRightIndex, modifier);
 },
 TryMoveFocusRight: function(modifier) {
  this.TryMoveCore(1, this.GetLeftRightIndex, modifier);
 },
 TryMoveFocusUp: function(modifier) {
  this.TryMoveCore(-1, this.GetTopLeftIndex, modifier);
 },
 TryMoveFocusDown: function(modifier) {
  this.TryMoveCore(1, this.GetTopLeftIndex, modifier);
 },
 TryMoveFocusPageUp: function(modifier) {
  this.TryMoveCore(-1, this.GetPageTopIndex, modifier);
 },
 TryMoveFocusPageDown: function(modifier) {
  this.TryMoveCore(1, this.GetPageTopIndex, modifier);
 },
 TryMoveCore: function(direction, getNewIndex, modifier) {
  var fm = this.control;
  if(fm.GetActiveArea() != FileManagerConsts.SelectedArea.Files || this.folderDialogCommand != null)
   return;
  if(fm.isDetailsViewMode())
   return;
  var itemsInfo = fm.getVisibleItemsInfo();
  var visibleItems = itemsInfo.list;
  if(visibleItems.length == 0)
   return;
  var focusFile = visibleItems[0];
  var lastFocusFile = fm.allowMultiSelect ? fm.focusedItem : fm.GetSelectedItem();
  if(lastFocusFile && !lastFocusFile.isVirtual())
   focusFile = lastFocusFile;
  var focusVisibleIndex = ASPx.Data.ArrayIndexOf(visibleItems, focusFile);
  var newIndex = getNewIndex.call(this, focusFile, focusVisibleIndex, direction);
  newIndex = this.Bound(newIndex, 0, visibleItems.length - 1);
  var file = visibleItems[newIndex];
  if(!file)
   file = direction == -1 ? visibleItems[0] : visibleItems[visibleItems.length - 1];
  if(fm.allowMultiSelect) {
   file.focus(false, true);
   if(modifier == FileManagerConsts.ModifierKey.Ctrl) {
    if(focusFile.IsSelected() && !file.IsSelected())
     file.Select();
    else if(!focusFile.IsSelected())
     focusFile.Select();
    else if(!(focusFile.IsSelected() && fm.getSelectedItems().length == 1))
     focusFile.Unselect();
   }
   else if(modifier == FileManagerConsts.ModifierKey.Shift)
    fm.changeRangeSelection(focusFile, file, itemsInfo.indexMap, direction);
  }
  else {
   file.Select();
   fm.CorrectScroll(file);
  }
 },
 GetItemsPerLine: function() {
  var fm = this.control,
   fileContainerWidth = fm.elements.GetItemsContainer().offsetWidth;
  return Math.floor(fileContainerWidth / fm.itemThumbnailWidth);
 },
 GetLeftRightIndex: function(selectedFile, visibleIndex, direction) {
  return visibleIndex + direction;
 },
 GetTopLeftIndex: function(selectedFile, visibleIndex, direction) {
  return visibleIndex + this.GetItemsPerLine() * direction;
 },
 GetPageTopIndex: function(selectedFile, visibleIndex, direction) {
  var fm = this.control,
   scrollContainer = fm.elements.GetItemsPaneContainer(),
   containerHeight = scrollContainer.offsetHeight,
   itemHeight = fm.itemThumbnailHeight,
   selectItemOffsetTop = ASPx.GetAbsolutePositionY(selectedFile.getElement()) - fm.itemThumbnailMarginTop,
   scrollContainerOffsetTop = ASPx.GetAbsolutePositionY(scrollContainer),
   itemsPerColumn = Math.round(containerHeight / itemHeight);
   itemsPerLine = this.GetItemsPerLine();
  if(scrollContainerOffsetTop <= selectItemOffsetTop && selectItemOffsetTop + itemHeight <= scrollContainerOffsetTop + containerHeight) {
   var newLine = Math.round(scrollContainer.scrollTop / itemHeight);
   if(direction > 0)
    newLine += itemsPerColumn - 1;
   var selectedColumn = selectedFile.index - itemsPerLine * Math.floor(selectedFile.index / itemsPerLine),
    newIndex = itemsPerLine * newLine + selectedColumn - selectedFile.index + visibleIndex;
   if(newIndex != visibleIndex)
    return newIndex;
  }
  return visibleIndex + itemsPerLine * (itemsPerColumn - 1) * direction;
 },
 Bound: function(value, min, max) {
  return Math.min(Math.max(value, min), max);
 },
 Focus: function() {
  this.control.focusMainElement();
 }
});
var FileManagerGridKbdHelper = ASPx.CreateClass(ASPx.GridViewKbdHelper, {
 constructor: function(control) {
  this.constructor.prototype.constructor.call(this, control, true);
 },
 HandleKeyDown: function(e) {
  var fm = this.control.fileManager;
  if(!fm)
   return false;
  var modifier = fm.getKeyModifier(e);
  var keyCode_A = 65;
  switch (ASPx.Evt.GetKeyCode(e)) {
   case ASPx.Key.PageUp:
    fm.KeyProcessPageUp(modifier);
    return true;
   case ASPx.Key.PageDown:
    fm.KeyProcessPageDown(modifier);
    return true;
   case ASPx.Key.Enter:
    fm.KeyProcessEnter();
    return true;
   case ASPx.Key.Esc:
    fm.KeyProcessEsc();
    return true;
   case ASPx.Key.F2:
    fm.KeyProcessF2();
    return true;
   case ASPx.Key.F6:
    fm.KeyProcessF6();
    return true;
   case ASPx.Key.Delete:
    fm.KeyProcessDelete();
    return true;
   case ASPx.Key.Tab:
    fm.KeyProcessTab();
    return false;
   case ASPx.Key.F7:
    fm.KeyProcessF7();
    return true;
   case ASPx.Key.Space:
    fm.KeyProcessSpace();
    return true;
   case keyCode_A:
    if(modifier == FileManagerConsts.ModifierKey.Ctrl || modifier == FileManagerConsts.ModifierKey.Meta)
     fm.KeyProcessCtrlA();
    return true;
   case ASPx.Key.Home:
    fm.KeyProcessHome(modifier);
    return true;
   case ASPx.Key.End:
    fm.KeyProcessEnd(modifier);
    return true;
   case ASPx.Key.Up:
   case ASPx.Key.Left:
    fm.preProcessGridArrowKey(-1, modifier);
    break;
   case ASPx.Key.Down:
   case ASPx.Key.Right:
    fm.preProcessGridArrowKey(1, modifier);
    break;
  }
  if(ASPx.GridViewKbdHelper.prototype.HandleKeyDown.call(this, e))
   return true;
  return false;
 },
 Focus: function() {
  ASPxClientFileManager.FocusElement(this.GetFocusableElement());
 }
});
var FileManagerUploadControl = ASPx.CreateClass(ASPxClientUploadControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.fileManager = null;
  this.inProgress = false;
  this.TextChanged.AddHandler(this.onTextChanged.aspxBind(this));
  this.FilesUploadStart.AddHandler(this.onFileUploadStart.aspxBind(this));
 },
 initializeViewManager: function() {
  ASPxClientUploadControl.prototype.initializeViewManager.call(this);
  this.viewManager.DropZoneDropInternal.AddHandler(function() {
   this.forceUpload = true;
  }.aspxBind(this));
 },
 initializeUploadManagerHandlers: function() {
  ASPxClientUploadControl.prototype.initializeUploadManagerHandlers.call(this);
  this.uploadManager.UploadInitiatedInternal.AddHandler(this.onFileUploadInitiated.bind(this));
 },
 onFileUploadInitiated: function(s, e) {
  var uploadedFileCount = this.fileInfosCache.getFileInfosCount();
  this.fileManager.KeepClientUploadState(uploadedFileCount);
 },
 onFileUploadStart: function(s, e) {
  if(!this.autoStart) return;
  e.cancel = !this.fileManager.raiseFileUploading();
  if(!e.cancel)
   this.changeUploadState(true);
 },
 onTextChanged: function(s, e) {
  if(this.autoStart) return;
  if(this.forceUpload && this.fileManager.raiseFileUploading()) {
   this.changeUploadState(true);
   this.Upload();
  }
  this.forceUpload = false;
 },
 changeUploadState: function(start) {
  this.fileManager.KeepClientState();
  this.inProgress = start;
  if(!this.fileManager.hideUploadPanel)
   this.UpdateButtonValue();
 },
 OnCompleteFileUpload: function() {
  this.inProgress = false;
  if(!this.fileManager.hideUploadPanel) {
   this.UpdateButtonValue();
   this.SetButtonEnable(true);
  }
  this.fileManager.HideLoadingElements();
 },
 SetVisible: function(visible) {
  ASPxClientUploadControl.prototype.SetVisible.call(this, visible);
  if(this.IsShowPlatformErrorElement()) {
   var pane = this.fileManager.elements.GetUploadPanelPane().helper.GetContentContainerElement();
   var uploadButton = this.fileManager.elements.GetUploadButtonElement();
   ASPx.Attr.SetAttribute(pane.style, "text-align", "center");
   ASPx.SetElementDisplay(uploadButton, false);
  }
 },
 CreateFileValidators: function() {
  var validators = ASPxClientUploadControl.prototype.CreateFileValidators.apply(this);
  validators.filePermissions = {
   value: this.fileManager.filesRules,
   errorText: this.validationSettings.notAllowedFileExtensionErrorText,
   isValid: function(fileInfo) {
    return this.fileManager.CheckEditAccessByFileName(fileInfo.fileName);
   }.aspxBind(this),
   getErrorText: function() {
    return this.errorText;
   }
  };
  return validators;
 },
 ShowMultiselectionErrorText: function(errorText) {
  this.fileManager.showError(ASPxClientFileManagerCommandConsts.Upload, errorText, "" + ASPxClientFileManagerErrorConsts.WrongExtension);
 },
 OnButtonClick: function() {
  if(!this.GetButtonEnabled())
   return;
  if(!this.inProgress && !this.fileManager.raiseFileUploading())
   return;
  this.changeUploadState(!this.inProgress);
  if(!this.inProgress)
   this.Cancel();
  else if(this.UploadFileFromUser())
   this.fileManager.ShowLoadingDivAndPanel();
 },
 UpdateButtonValue: function(inProgress) {
  if(typeof (inProgress) != 'undefined')
   this.inProgress = inProgress;
  var button = this.fileManager.elements.GetUploadButtonElement();
  button.innerHTML = this.inProgress ? this.fileManager.cancelUploadText : this.fileManager.uploadText;
 },
 SetButtonEnable: function(enable) {
  var button = this.fileManager.elements.GetUploadButtonElement();
  if(!enable && button.className.indexOf(FileManagerConsts.UploadControlDisableClassName) == -1)
   button.className += " " + FileManagerConsts.UploadControlDisableClassName;
  else if(enable && button.className.indexOf(FileManagerConsts.UploadControlDisableClassName) > -1)
   button.className = button.className.replace(FileManagerConsts.UploadControlDisableClassName, "");
 },
 GetButtonEnabled: function() {
  var button = this.fileManager.elements.GetUploadButtonElement();
  return button.className.indexOf(FileManagerConsts.UploadControlDisableClassName) == -1;
 },
 GetFileName: function() {
  return this.GetFileNames().join(", ");
 },
 IsSplitterNestedControl: function() {
  return this.IsInputsVisible();
 }
});
var FileManagerTreeViewRenderHelper = ASPx.CreateClass(ASPx.TreeViewRenderHelper, {
 CanAttachExpandButtonHandler: function(contentElement) {
  return true;
 }
});
var FileManagerTreeView = ASPx.CreateClass(ASPxClientTreeView, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.fileManager = null;
  this.callbackCount = 0;
  this.isFolderBrowserFolders = false;
 },
 CreateRenderHelper: function() {
  return new FileManagerTreeViewRenderHelper(this);
 },
 CreateCallback: function(callbackString) {
  this.fileManager.SendTreeViewCallback(this, callbackString);
  this.callbackCount++;
 },
 OnCallbackFinalized: function() {
  if(this.callbackCount > 0)
   this.callbackCount--;
  if(this.callbackCount <= 0)
   this.fileManager.ClearCallbackOwner();
  ASPxClientTreeView.prototype.OnCallbackFinalized.apply(this, arguments);
 },
 InitFileManagerCallbacks: function(fm, isFolderBrowserFolders) {
  this.fileManager = fm;
  this.isFolderBrowserFolders = isFolderBrowserFolders;
  if(isFolderBrowserFolders)
   this.ExpandedChanging.AddHandler(fm.OnFolderExpanding.aspxBind(fm));
  else
   this.ExpandedChanged.AddHandler(fm.OnFolderExpanded.aspxBind(fm));
 },
 IsSplitterNestedControl: function() {
  return true;
 },
 GetNodeExpandedInternal: function(node) {
  var expanded = node.GetExpanded();
  if(!this.virtualMode || expanded) return expanded;
  var listItem = this.GetNodeListItem(node);
  var subnodesList = this.renderHelper.GetSubNodesList(listItem);
  return subnodesList && ASPx.GetElementDisplay(subnodesList);
 }
});
var FileManagerGridView = ASPx.CreateClass(ASPxClientGridView, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.fileManager = null;
 },
 CreateCallback: function(callbackString, command) {
  this.fileManager.SendGridViewCallback(this, callbackString, command);
 },
 OnCallback: function(resultObj) {
  ASPxClientGridView.prototype.OnCallback.apply(this, arguments);
 },
 OnCallbackFinalized: function() {
  this.fileManager.AdjustGridViewSize();
  ASPxClientGridView.prototype.OnCallbackFinalized.apply(this);
 },
 GetRowIndexByKey: function(key) {
  for(i = 0; i < this.keys.length; i++) {
   if(this.keys[i] == key)
    return this.visibleStartIndex + i;
  }
  return -1;
 },
 SelectAllItemsOnPage: function(selected) {
  if(!ASPx.IsExists(selected)) selected = true;
  if(selected)
   this.fileManager.selectAllItems();
  else
   ASPxClientGridView.prototype.SelectAllItemsOnPage.call(this, selected);
 },
 UpdateFileManagerSelectAllCheckboxesState: function() {
  ASPxClientGridView.prototype.UpdateSelectAllCheckboxesState.apply(this);
 },
 UpdateSelectAllCheckboxesState: function() { },
 UpdateSelectAllCheckboxStateCore: function(selectAllButtonInput, selectMode) {
  var selectAllCheckBoxInst = this.internalCheckBoxCollection.Get(selectAllButtonInput.id);
  selectAllCheckBoxInst.SetValue(this.fileManager.getSelectAllCheckboxState());
 },
 getVisibleEndIndex: function() {
  return this.visibleStartIndex + this.GetDataItemCountOnPage();
 },
 getHeaderFirstRow: function() {
  var table = this.GetTableHelper().GetHeaderTable();
  var tbody = ASPx.GetChildByTagName(table, "TBODY");
  return ASPx.GetChildByTagName(tbody, "TR");
 },
 syncAdaptivityInCreateHelperElement: function(element) {
  if(!this.HasAdaptivity())
   return;
  var sourceRow = this.getHeaderFirstRow();
  for(var i = 0; i < sourceRow.cells.length; i++) {
   var sourceCell = sourceRow.cells[i];
   var cell = element.cells[i];
   var isHiddenNew = ASPx.ElementHasCssClass(sourceCell, FileManagerConsts.GridAdaptiveHiddenClassName);
   var isHiddenOld = ASPx.ElementHasCssClass(cell, FileManagerConsts.GridAdaptiveHiddenClassName);
   if(isHiddenNew !== isHiddenOld) {
    var action = isHiddenNew ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
    action(cell, FileManagerConsts.GridAdaptiveHiddenClassName);
   }
  }
 },
 EnsureRowKeys: function() {
  ASPxClientGridView.prototype.EnsureRowKeys.apply(this);
  if(this.fileManager)
   this.fileManager.ensureGridViewItems();
 },
 ProcessTableClick: function(evt, fromCheckBox) {
  var row = this.getItemByHtmlEvent(evt);
  if(!row)
   return;
  var rowIndex = this.getItemIndex(row.id);
  if(this.fileManager.items[this.GetRowKey(rowIndex)].isParentFolderItem)
   this.SetFocusedRowIndex(rowIndex);
  else {
   if(fromCheckBox)
    this.lastMultiSelectIndex = rowIndex;
   ASPxClientGridView.prototype.ProcessTableClick.call(this, evt, fromCheckBox);
  }
 },
 updateFocusedRowStyle: function(row, toInactive) {
  var index = this.GetFocusedRowIndex();
  if(index === -1)
   return;
  if(this.GetItem(index) !== row)
   return;
  var style = this.GetFocusedItemStyle(index, !toInactive);
  this.ApplyItemStyle(index, style);
 },
 lockVirtualScrolling: function(lock) {
  this.GetScrollHelper().lockVirtualScrolling = lock;
 },
 scrollToPageEnd: function() {
  var scrollHelper = this.GetScrollHelper(),
   mainTable = this.GetMainTable(),
   scrollableElement = scrollHelper.GetVertScrollableControl();
  var childElements = ASPx.GetChildElementNodes(scrollableElement);
  var startHeight = childElements[0].tagName == "DIV" ? childElements[0].offsetHeight : 0;
  scrollableElement.scrollTop = startHeight + mainTable.offsetHeight - scrollableElement.offsetHeight - 1;
  this.lockVirtualScrolling(false);
 }
});
var FileManagerToolbarMenu = ASPx.CreateClass(ASPxClientMenu, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.fileManager = null;
 },
 CreateRenderHelper: function(){
  return new FileManagerToolbarRenderHelper(this);
 },
 IsSplitterNestedControl: function() {
  return true;
 }
});
var FileManagerToolbarRenderHelper = ASPx.CreateClass(ASPx.MenuRenderHelper, {
 constructor: function(menu) {
  this.constructor.prototype.constructor.call(this, menu);
  this.denyShowAdaptiveItemForElementClassNames = ["dxm-spacing", "dxm-separator", FileManagerConsts.ToolbarPathBoxClassName, FileManagerConsts.ToolbarFilterBoxClassName];
 },
 NeedShowAdaptiveItemForHiddenElements: function(elementsToHide) {
  var elements = elementsToHide.map(function(el) { return el.itemElement; });
  return this.allowShowAdaptiveItemForHiddenElementsCore(elements);
 },
 SetAdaptiveItemElementVisibility: function(adaptiveItemElement, adaptiveItemSpacing, visible) {
  if(visible && !this.allowShowAdaptiveItemForHiddenElements())
   visible = false;
  ASPx.MenuRenderHelper.prototype.SetAdaptiveItemElementVisibility.call(this, adaptiveItemElement, adaptiveItemSpacing, visible);
 },
 allowShowAdaptiveItemForHiddenElements: function() {
  var menuElement = this.menu.GetMainElement();
  var contentElement = this.GetAdaptiveMenuContentElement(menuElement);
  var elements = ASPx.GetChildElementNodes(contentElement);
  return this.allowShowAdaptiveItemForHiddenElementsCore(elements);
 },
 allowShowAdaptiveItemForHiddenElementsCore: function(elementsToHide) {
  for(var i = 0; i < elementsToHide.length; i++) {
   var element = elementsToHide[i];
   if(!element) continue;
   if(this.allowShowAdaptiveItemForHiddenElement(element))
    return true;
  }
  return false;
 },
 allowShowAdaptiveItemForHiddenElement: function(element) {
  for(var i = 0, className; className = this.denyShowAdaptiveItemForElementClassNames[i]; i++) {
   if(ASPx.ElementHasCssClass(element, className))
    return false;
  }
  return true;
 }
});
var ClientFileManagerBreadCrumbs = ASPx.CreateClass(null, {
 constructor: function(fileManager) {
  this.fileManager = fileManager;
  this.showFolderUpButton = this.fileManager.showBreadCrumbsFolderUpButton;
  this.mainElementID = this.fileManager.name + FileManagerConsts.BreadCrumbsPostfix;
  this.hasSeparatorElements = true;
  this.items = [];
 },
 render: function() {
  this.fileManager.elements.GetBreadCrumbsPaneContainer().innerHTML = "";
  this.mainElement = this.createMainElement();
  this.mainElement.id = this.mainElementID;
  this.mainElement.className = this.getMainElementClassName();
  if(this.showFolderUpButton) {
   this.folderUpElement = this.createFolderUpElement();
   this.mainElement.appendChild(this.folderUpElement);
   if(this.hasSeparatorElements)
    this.mainElement.appendChild(this.createLineSeparatorElement());
  }
  this.hiddenItemsButton = this.createHiddenItemsButtonElement();
  this.mainElement.appendChild(this.hiddenItemsButton);
  if(this.hasSeparatorElements)
   this.mainElement.appendChild(this.createItemSeparatorElement());
  this.fileManager.elements.GetBreadCrumbsPaneContainer().appendChild(this.mainElement);
  this.calculateItemsSizes();
 },
 getMainElementClassName: function() {
  return FileManagerConsts.BreadCrumbsContainerClassName;
 },
 getBreadCrumbsButtonClassName: function() {
  return FileManagerConsts.BreadCrumbsButtonClassName;
 },
 getBreadCrumbsLastItemClassName: function() {
  return FileManagerConsts.BreadCrumbsLastItemClassName;
 },
 getItemElementTagName: function() {
  return "span";
 },
 getItemElementImage: function(element) {
  return ASPxClientUtils.GetChildByTagName(element, "IMG", 0);
 },
 getItemElementInnerHTML: function(item) {
  return item.text;
 },
 createMainElement: function() {
  return document.createElement("div");
 },
 createElementBase: function(className, innerHtml) {
  var element = document.createElement(this.getItemElementTagName());
  if(className)
   element.className = className;
  element.innerHTML = innerHtml;
  return element;
 },
 createElement: function(innerHtml, id, hasImage, disableHover) {
  var element = this.createElementBase(this.fileManager.styles.breadCrumbsItemCssClass, innerHtml);
  element.id = id;
  if(hasImage)
   this.getItemElementImage(element).id = element.id + FileManagerConsts.ImagePostfix;
  if(disableHover)
   return element;
  ASPx.GetStateController().AddHoverItem(
   element.id,
   [this.fileManager.styles.breadCrumbsItemHoverCssClass],
   [""],
   null,
   hasImage ? [this.fileManager.styles.breadCrumbsUpButtonImageHoveredScriptObjects] : null,
   hasImage ? [FileManagerConsts.ImagePostfix] : null,
   null
  );
  return element;
 },
 createFolderUpElement: function() {
  var element = this.createElement(this.fileManager.breadCrumbsUpButtonImage, this.mainElementID + FileManagerConsts.BreadCrumbsFolderUpButtonPostfix, true);
  ASPx.Evt.AttachEventToElement(element, "mouseup", function() { this.onFolderUpElementClick(); }.aspxBind(this));
  ASPx.AddClassNameToElement(element, this.getBreadCrumbsButtonClassName());
  ASPx.GetStateController().AddDisabledItem(
   element.id,
   [""],
   [""],
   null,
   [this.fileManager.styles.breadCrumbsUpButtonImageDisabledScriptObjects],
   [FileManagerConsts.ImagePostfix],
   null
  );
  return element;
 },
 createHiddenItemsButtonElement: function() {
  var element = this.createElement(FileManagerConsts.BreadCrumbsHiddenItemsButtonText, this.mainElementID + FileManagerConsts.BreadCrumbsHiddenItemsButtonPostfix, false);
  ASPx.AddClassNameToElement(element, this.getBreadCrumbsButtonClassName());
  ASPx.Evt.AttachEventToElement(element, "mouseup", function() { this.onHiddenItemsButtonClick(); }.aspxBind(this));
  return element;
 },
 createItemElement: function(item) {
  var element = this.createItemElementCore(item);
  if(item.isLastItem)
   ASPx.AddClassNameToElement(element, this.getBreadCrumbsLastItemClassName());
  else
   ASPx.Evt.AttachEventToElement(element, "mouseup", function() { this.onItemClick(item); }.aspxBind(this));
  return element;
 },
 createItemElementCore: function(item) {
  return this.createElement(this.getItemElementInnerHTML(item), item.getElementID(), false, item.isLastItem);
 },
 createItemSeparatorElement: function() {
  return this.createElementBase("", this.fileManager.breadCrumbsSeparatorImage);
 },
 createLineSeparatorElement: function() {
  return this.createElementBase(FileManagerConsts.BreadCrumbsLineSeparatorClassName, "");
 },
 clearItems: function() {
  for(var item, i = 0; item = this.items[i]; i++)
   item.removeElement();
  this.items = [];
  this.getPopupContentContainer().innerHTML = "";
 },
 createItems: function() {
  var path = "";
  var currentPath = this.fileManager.GetCurrentPath();
  if(currentPath[currentPath.length - 1] == FileManagerConsts.PathSeparator)
   currentPath = currentPath.substring(0, currentPath.length - 1);
  var pathParts = currentPath.split(FileManagerConsts.PathSeparator);
  for(var part, i = 0; part = pathParts[i]; i++) {
   if(i > 0)
    path += (path ? FileManagerConsts.PathSeparator : "") + part;
   var isLastItem = i == pathParts.length - 1;
   var item = new ASPxClientFileManagerBreadCrumbsItem(this, i, path, part, isLastItem);
   this.items.push(item);
   if(!isLastItem)
    this.placeItemElementToPopup(item);
   else
    this.mainElement.appendChild(item.getElement());
  }
  var isRootState = this.items.length == 1;
  if(isRootState)
   this.hideHiddenItemsButton();
  this.updateRootStateMarker(isRootState);
  this.adjustItems();
 },
 onFolderUpElementClick: function() {
  if(this.upFolderPath != null)
   this.fileManager.SetCurrentFolderPath(this.upFolderPath);
 },
 onHiddenItemsButtonClick: function() {
  this.showPopup();
 },
 onItemClick: function(item) {
  this.hidePopup();
  this.fileManager.SetCurrentFolderPath(item.targetPath);   
 },
 refresh: function() {
  if(this.showFolderUpButton)
   this.updateFolderUpElementState();
  this.clearItems();
  this.updateCustomFilterBreadCrumbsElement();
  if(!this.hasCustomFilterBreadCrumbsText())
   this.createItems();
 },
 updateFolderUpElementState: function() {
  var path = this.fileManager.GetCurrentPath(true);
  this.upFolderPath = path ? path.substr(0, path.lastIndexOf(FileManagerConsts.PathSeparator)) : null;
  this.setFolderUpElementEnabled(!!path);
  var visible = !this.hasCustomFilterBreadCrumbsText();
  this.setElementVisible(this.folderUpElement, visible);
  if(this.hasSeparatorElements)
   this.setElementVisible(this.folderUpElement.nextSibling, visible);
 },
 updateCustomFilterBreadCrumbsElement: function() {
  var visible = this.hasCustomFilterBreadCrumbsText();
  if(visible) {
   if(!this.customFilterBreadCrumbsElement)
    this.createCustomFilterBreadCrumbsElement();
   this.customFilterBreadCrumbsElement.innerHTML = this.getCustomFilterBreadcrumbsText();
  }
  this.setElementVisible(this.customFilterBreadCrumbsElement, visible);
 },
 createCustomFilterBreadCrumbsElement: function() {
  this.customFilterBreadCrumbsElement = this.createElement(this.getCustomFilterBreadcrumbsText(), this.mainElementID + FileManagerConsts.BreadCrumbsCustomFilterElementPostfix, false, true);
  this.mainElement.appendChild(this.customFilterBreadCrumbsElement);
 },
 hasCustomFilterBreadCrumbsText: function() {
  return !!this.getCustomFilterBreadcrumbsText();
 },
 getCustomFilterBreadcrumbsText: function() {  
  return this.fileManager.GetCustomFilterBreadcrumbsText();
 },
 calculateItemsSizes: function() {
  var itemSeparator = this.createItemSeparatorElement();
  if(itemSeparator)
   this.mainElement.appendChild(itemSeparator);
  var simpleItem = new ASPxClientFileManagerBreadCrumbsItem(this, 0, "_", "_");
  var element = simpleItem.getElement();
  this.mainElement.appendChild(element);
  this.itemSeparatorWidth = itemSeparator ? itemSeparator.offsetWidth : 0;
  this.itemElementSymbolWidth = ASPx.GetClearClientWidth(element);
  this.itemElementOuterWidth = element.offsetWidth + ASPx.GetLeftRightMargins(element) - this.itemElementSymbolWidth;
  if(itemSeparator)
   ASPx.RemoveElement(itemSeparator);
  ASPx.RemoveElement(element);
 },
 getItemWithSeparatorWidth: function(item) {
  return this.itemSeparatorWidth + this.itemElementOuterWidth + item.text.length * this.itemElementSymbolWidth;
 },
 adjustItems: function() {
  if(this.items.length == 0)
   return;
  var modificationRange = this.getModificationRange();
  if(!modificationRange)
   return;
  if(modificationRange < 0) {
   for(var i = 0; i < this.items.length - 1; i++) {
    var item = this.items[i];
    if(!item.inPopup) {
     this.placeItemElementToPopup(item);
     modificationRange += this.getItemWithSeparatorWidth(item);
     if(modificationRange >= 0)
      break;
    }
   }
   return;
  }
  for(var item, i = this.items.length - 2; item = this.items[i]; i--) {
   if(item.inPopup) {
    var itemWidth = this.getItemWithSeparatorWidth(item);
    if(itemWidth <= modificationRange) {
     this.placeItemToMainElement(item);
     modificationRange -= itemWidth;
    } else
     break;
   }
  }
 },
 getModificationRange: function() {
  var lastElement = this.items[this.items.length - 1].getElement();
  return ASPx.GetAbsoluteX(this.GetMainElement()) + this.GetMainElement().offsetWidth - ASPx.GetAbsoluteX(lastElement) - lastElement.offsetWidth;
 },
 placeItemElementToPopup: function(item) {
  var itemElement = item.getElement();
  var popupContainer = this.getPopupContentContainer();
  if(this.hasSeparatorElements)
   ASPx.RemoveElement(itemElement.nextSibling);
  popupContainer.insertBefore(itemElement, popupContainer.firstChild);
  item.inPopup = true;
  this.resetPopupSize();
  if(item.index == 0)
   this.showHiddenItemsButton();
 },
 placeItemToMainElement: function(item) {
  var lastItem = this.items[this.items.length - 1];
  for(var curItem, i = lastItem.index - 1; curItem = this.items[i]; i--) {
   if(!curItem.inPopup)
    lastItem = curItem;
   else
    break;
  }
  this.placeItemToMainElementCore(item, lastItem.getElement());
  item.inPopup = false;
  if(item.index == 0)
   this.hideHiddenItemsButton();
 },
 placeItemToMainElementCore: function(item, nextSibling) {
  var separator = this.createItemSeparatorElement();
  this.GetMainElement().insertBefore(separator, nextSibling);
  this.GetMainElement().insertBefore(item.getElement(), separator);
 },
 setFolderUpElementEnabled: function(enabled) {
  ASPx.GetStateController().SetElementEnabled(this.folderUpElement, enabled);
 },
 setElementVisible: function(element, visible) {
  ASPx.SetElementDisplay(element, visible);
 },
 GetMainElement: function() {
  return this.mainElement;
 },
 getPopup: function() {
  return this.fileManager.GetBreadCrumbsPopup();
 },
 getPopupContentContainer: function() {
  return this.getPopup().GetContentContainer(-1);
 },
 resetPopupSize: function() {
  this.getPopup().SetSize(0, 0);
 },
 showPopup: function() {
  this.getPopup().ShowAtElement(this.hiddenItemsButton);
 },
 hidePopup: function() {
  this.getPopup().Hide();
 },
 hideHiddenItemsButton: function() {
  if(this.hasSeparatorElements)
   this.setElementVisible(this.hiddenItemsButton.nextSibling, false);
  this.setElementVisible(this.hiddenItemsButton, false);
 },
 showHiddenItemsButton: function() {
  this.setElementVisible(this.hiddenItemsButton, true);
  if(this.hasSeparatorElements)
   this.setElementVisible(this.hiddenItemsButton.nextSibling, true);
 },
 updateRootStateMarker: function(isRoot) {
  var func = isRoot ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
  func(this.mainElement, FileManagerConsts.BreadCrumbsRootStateClassName);
 }
});
ASPx.FileManagerBreadCrumbs = ClientFileManagerBreadCrumbs;
var ASPxClientFileManagerBreadCrumbsItem = ASPx.CreateClass(null, {
 constructor: function(breadCrumbs, index, targetPath, text, isLastItem) {
  this.breadCrumbs = breadCrumbs;
  this.index = index;
  this.targetPath = targetPath;
  this.text = text;
  this.isLastItem = isLastItem;
 },
 getElement: function() {
  if(!this.element)
   this.element = this.breadCrumbs.createItemElement(this);
  return this.element;
 },
 removeElement: function() {
  if(!this.element)
   return;
  ASPx.GetStateController().RemoveHoverItem(this.element.id, null);
  if(this.breadCrumbs.hasSeparatorElements)
   ASPx.RemoveElement(this.element.nextSibling);
  ASPx.RemoveElement(this.element);
 },
 getElementID: function() {
  return this.breadCrumbs.mainElementID + FileManagerConsts.ItemPostfix + this.index;
 }
});
var ASPxClientFileManagerCommandConsts = {
 Rename: "rename",
 Move: "move",
 Delete: "delete",
 Create: "create",
 Upload: "upload",
 Download: "download",
 Copy: "copy",
 Open: "open"
};
var ASPxClientFileManagerErrorConsts = {
 FileNotFound: 0,
 FolderNotFound: 1,
 AccessDenied: 2,
 UnspecifiedIO: 3,
 Unspecified: 4,
 EmptyName: 5,
 CanceledOperation: 6,
 InvalidSymbols: 7,
 WrongExtension: 8,
 UsedByAnotherProcess: 9,
 AlreadyExists: 10
};
var ASPxClientFileManagerCallbackCommand = {
 GetAllItems: "GETALLITEMS",
 GetFileList: "GETFILELIST",
 Refresh: "REFRESH",
 DeleteItems: "DELETEITEMS",
 MoveItems: "MOVEITEMS",
 CopyItems: "COPYITEMS",
 RenameItem: "RENAMEITEM",
 Download: "DOWNLOAD",
 ShowFolderBrowserDialog: "SHOWFOLDERBROWSERDIALOG",
 ShowCreateFolderEditorInTreeView: "SHOWCREATEFOLDEREDITORINTREEVIEW",
 CreateFolder: "CREATEFOLDER",
 SelectedFileOpened: "SELECTEDFILEOPENED",
 FoldersTreeView: "FOLDERSTREEVIEW",
 FolderBrowserTreeView: "FOLDERBROWSERTREEVIEW",
 GridView: "GRIDVIEW",
 ChangeFolder: "CHANGEFOLDER",
 ChangeFolderInTreeView: "CHANGEFOLDERINTREEVIEW",
 CustomCallback: "CUSTOMCALLBACK",
 VirtualScrolling: "VIRTUALSCROLLING",
 GridViewVirtualScrolling: "GRIDVIEWVIRTUALSCROLLING"
};
ASPx.FileManagerConsts = FileManagerConsts;
ASPx.FileManagerGridKbdHelper = FileManagerGridKbdHelper;
ASPx.FileManagerKbdHelper = FileManagerKbdHelper;
ASPx.FileManagerTreeView = FileManagerTreeView;
ASPx.FileManagerGridView = FileManagerGridView;
ASPx.FileManagerUploadControl = FileManagerUploadControl;
ASPx.FileManagerToolbarMenu = FileManagerToolbarMenu;
window.ASPxClientFileManager = ASPxClientFileManager;
window.ASPxClientFileManagerFile = ASPxClientFileManagerFile;
window.ASPxClientFileManagerFolder = ASPxClientFileManagerFolder;
window.ASPxClientFileManagerSelectionChangedEventArgs = ASPxClientFileManagerSelectionChangedEventArgs;
window.ASPxClientFileManagerCurrentFolderChangedEventArgs = ASPxClientFileManagerCurrentFolderChangedEventArgs;
window.ASPxClientFileManagerFocusedItemChangedEventArgs = ASPxClientFileManagerFocusedItemChangedEventArgs;
window.ASPxClientFileManagerFileDownloadingEventArgs = ASPxClientFileManagerFileDownloadingEventArgs;
window.ASPxClientFileManagerFileUploadedEventArgs = ASPxClientFileManagerFileUploadedEventArgs;
window.ASPxClientFileManagerFileUploadingEventArgs = ASPxClientFileManagerFileUploadingEventArgs;
window.ASPxClientFileManagerFilesUploadingEventArgs = ASPxClientFileManagerFilesUploadingEventArgs;
window.ASPxClientFileManagerErrorAlertDisplayingEventArgs = ASPxClientFileManagerErrorAlertDisplayingEventArgs;
window.ASPxClientFileManagerErrorEventArgs = ASPxClientFileManagerErrorEventArgs;
window.ASPxClientFileManagerItemCreatedEventArgs = ASPxClientFileManagerItemCreatedEventArgs;
window.ASPxClientFileManagerItemCopiedEventArgs = ASPxClientFileManagerItemCopiedEventArgs;
window.ASPxClientFileManagerItemMovedEventArgs = ASPxClientFileManagerItemMovedEventArgs;
window.ASPxClientFileManagerItemDeletedEventArgs = ASPxClientFileManagerItemDeletedEventArgs;
window.ASPxClientFileManagerItemRenamedEventArgs = ASPxClientFileManagerItemRenamedEventArgs;
window.ASPxClientFileManagerItemEditingEventArgs = ASPxClientFileManagerItemEditingEventArgs;
window.ASPxClientFileManagerActionEventArgsBase = ASPxClientFileManagerActionEventArgsBase;
window.ASPxClientFileManagerFileOpenedEventArgs = ASPxClientFileManagerFileOpenedEventArgs;
window.ASPxClientFileManagerFileEventArgs = ASPxClientFileManagerFileEventArgs;
window.ASPxClientFileManagerCommandConsts = ASPxClientFileManagerCommandConsts;
window.ASPxClientFileManagerErrorConsts = ASPxClientFileManagerErrorConsts;
})();

(function() {
 var downloadCommandArgument = "DXMVCFileManagerDownloadArgument";
 var MVCxClientFileManager = ASPx.CreateClass(ASPxClientFileManager, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.callbackUrl = "";
   this.downloadUrl = "";
   this.customActionUrl = "";
   this.callbackCustomArgs = {};
  },
  PerformCallback: function(data, onSuccess){
   ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
   ASPxClientFileManager.prototype.PerformCallback.call(this, data, onSuccess);
  },
  InlineInitialize: function() {
   if(this.callbackUrl != "")
    this.callBack = function(arg) { MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs); };
   if (this.customActionUrl != "")
    this.customActionCallBack = function(arg){ MVCx.PerformControlCallback(this.name, this.customActionUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs); };
   ASPxClientFileManager.prototype.InlineInitialize.call(this);
  },
  RaiseBeginCallbackInternal: function(command) {
   var args = new MVCxClientBeginCallbackEventArgs(command);
   if(!this.BeginCallback.IsEmpty())
    this.BeginCallback.FireEvent(this, args);
   ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
  },
  GetCallbackParams: function(arg) {
   var params = {};
   MVCx.AddCallbackParam(params, this.GetStateHiddenField());
   MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
   var treeView = this.GetTreeView();
   if(treeView)
    MVCx.AddCallbackParam(params, treeView.GetStateHiddenField());
   var folderBrowser = this.GetFolderBrowserTreeView();
   if(folderBrowser && folderBrowser.GetStateHiddenField()) 
    MVCx.AddCallbackParam(params, folderBrowser.GetStateHiddenField());
   if(this.isDetailsViewMode()) 
    MVCx.AddCallbackParam(params, this.GetFilesGridView().GetStateHiddenField());
   return params;
  },
  CreateCallbackByInfo: function(arg, command, callbackInfo) {
   this.CreateCallbackInternal(arg, command, true, callbackInfo);
  },
  Download: function() {
   if(!this.downloadUrl)
    return;
   ASPxClientFileManager.prototype.Download.call(this);
  },
  SendPostBack: function(postBackArg) {
   this.OnPost();
   var form = ASPx.GetParentByTagName(this.GetMainElement(), "form");
   if(form) {
    var sourceFormAction = form.action,
     commandArgument = ASPx.CreateHiddenField(downloadCommandArgument);
    commandArgument.value = postBackArg;
    form.appendChild(commandArgument);
    form.action = this.downloadUrl;
    form.submit();
    form.action = sourceFormAction;
    form.removeChild(commandArgument);
   }
  },
  EvalCallbackResult: function (resultString) {
   var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
   if(resultStringParts.length == 2) {
    var resultObj = ASPxClientFileManager.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
    resultObj.result.itemsRender = resultStringParts[1];
    return resultObj;
   }
   return ASPxClientFileManager.prototype.EvalCallbackResult.call(this, resultString);
  },
  CreateCallbackCore: function(arg, command, callbackID){
   if(this.callbackCustomArgs != {})
    window.setTimeout(function(){ this.callbackCustomArgs = {}; }.aspxBind(this), 0);
   ASPxClientFileManager.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
  },
  GetCallbackMethod: function(command){
   return MVCx.IsCustomCallback(command) ? MVCx.GetCustomActionCallBackMethod(this) : this.callBack;
  }
 });
 MVCxClientFileManager.Cast = ASPxClientControl.Cast;
 var MVCxLegacyUploadManager = ASPx.CreateClass(ASPxClientUploadControl.UploadManagerClass, {
  GetUploadFormAction: function(form) {
   if(this.options.callbackUrl != "")
    form.action = this.options.callbackUrl;
   return ASPxClientUploadControl.UploadManagerClass.prototype.GetUploadFormAction.call(this, form);
  }
 });
 var FileManagerUploadControl = ASPx.CreateClass(ASPx.FileManagerUploadControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.callbackUrl = "";
  },
  createUploadManager: function(stateHelper) {
   this.options.callbackUrl = this.callbackUrl;
   return new MVCxLegacyUploadManager(this.options, stateHelper);
  }
 });
 window.MVCxClientFileManager = MVCxClientFileManager;
 MVCx.FileManagerUploadControl = FileManagerUploadControl;
})();

(function () {
var SplitterHelper = ASPx.CreateClass(null, {
 constructor: function (splitter) {
  this.splitter = splitter;
 },
 GetMoveMaxDeltaSize: function (deltaSize) {
  if(deltaSize == 0)
   return 0;
  var splitter = this.splitter,
   leftPane = splitter.moveLeftPane,
   rightPane = splitter.moveRightPane;
  if(splitter.isHeavyUpdate) {
   var parent = leftPane.parent;
   var totalSize = 0, minSize = 0;
   for(var i = 0; i < parent.panes.length; i++) {
    var pane = parent.panes[i];
    if(pane.isSizePx)
     continue;
    if(pane.collapsed) {
     var collapsedSize = pane.GetSizeDiff(pane.isVertical);
     totalSize += collapsedSize;
     minSize += collapsedSize;
    }
    else {
     totalSize += pane.GetOffsetSize();
     minSize += pane.GetMinSize();
    }
   }
   var rightPanePx = rightPane.isSizePx;
   if(rightPanePx)
    deltaSize = this.GetPaneMaxDeltaSize(rightPane, -deltaSize);
   deltaSize = this.GetMaxDeltaSize(totalSize, minSize, Number.MAX_VALUE, -deltaSize);
   if(!rightPanePx)
    deltaSize = this.GetPaneMaxDeltaSize(leftPane, -deltaSize);
  }
  else {
   var parent = leftPane.parent,
    rightPaneAutoSize = rightPane.IsAutoSize(parent.isVertical),
    leftPaneAutoSize = leftPane.IsAutoSize(parent.isVertical);
   if(!rightPaneAutoSize)
    deltaSize = -this.GetPaneMaxDeltaSize(rightPane, -1 * deltaSize);
   if(!leftPaneAutoSize)
    deltaSize = this.GetPaneMaxDeltaSize(leftPane, deltaSize);
  }
  return deltaSize;
 },
 GetPaneMaxDeltaSize: function (pane, deltaSize) {
  return this.GetMaxDeltaSize(pane.GetOffsetSize(), pane.GetMinSize(), pane.maxSize, deltaSize);
 },
 GetMaxDeltaSize: function (size, min, max, deltaSize) {
  var minDeltaSize = Math.floor(min - size);
  var maxDeltaSize = Math.floor(max - size);
  if(deltaSize < minDeltaSize)
   return (size < min) ? 0 : minDeltaSize;
  else if(deltaSize > maxDeltaSize)
   return (size > max) ? 0 : maxDeltaSize;
  return deltaSize;
 },
 GetCurrentPos: function () {
  return this.splitter.moveIsVertical
   ? ASPxClientSplitter.CurrentYPos
   : ASPxClientSplitter.CurrentXPos;
 },
 SetResizingPanelVisibility: function (visible, cursor) {
  var resizingPanel = ASPx.CacheHelper.GetCachedValue(this, "resizingPanel", function () {
   var resizingPanel = document.createElement("DIV");
   resizingPanel.style.overflow = "hidden";
   resizingPanel.style.position = "absolute";
   resizingPanel.isVisible = false;
   return resizingPanel;
  });
  if(resizingPanel.isVisible != visible) {
   if(visible) {
    var mainElement = this.splitter.GetMainElement();
    ASPx.SetStyles(resizingPanel, {
     width: mainElement.offsetWidth,
     height: mainElement.offsetHeight
    });
    if(cursor)
     resizingPanel.style.cursor = cursor;
    mainElement.parentNode.appendChild(resizingPanel);
    ASPx.SetAbsoluteX(resizingPanel, ASPx.GetAbsoluteX(mainElement));
    ASPx.SetAbsoluteY(resizingPanel, ASPx.GetAbsoluteY(mainElement));
   }
   else
    resizingPanel.parentNode.removeChild(resizingPanel);
   resizingPanel.isVisible = visible;
  }
 },
 OnDispose: function() {
  this.splitter = null;
 }
});
SplitterHelper.Resize = function (pane1, pane2, deltaSize) {
 if(pane1.isSizePx || pane2.isSizePx) {
  var parent = pane1.parent;
  if(pane1.isSizePx && !pane1.IsAutoSize(parent.isVertical))
   pane1.size += deltaSize;
  if(pane2.isSizePx && !pane2.IsAutoSize(parent.isVertical))
   pane2.size -= deltaSize;
 }
 else {
  var c = (pane1.size + pane2.size) / (pane1.GetOffsetSize() + pane2.GetOffsetSize());
  pane1.size = c * (pane1.GetOffsetSize() + deltaSize);
  pane2.size = c * (pane2.GetOffsetSize() - deltaSize);
 }
};
SplitterHelper.IsAllowResize = function (pane1, pane2) {
 if(!pane1 || !pane2)
  return false;
 if(!pane1.splitter.enabled)
  return false;
 var bothAutoSizeOrPercent = pane1.isVertical
  ? pane1.autoHeight && pane2.autoHeight || pane1.autoHeight && !pane2.isSizePx || !pane1.isSizePx && pane2.autoHeight
  : pane1.autoWidth && pane2.autoWidth || pane1.autoWidth && !pane2.isSizePx || !pane1.isSizePx && pane2.autoWidth;
 if(bothAutoSizeOrPercent)
  return false;
 return pane1.splitter.allowResize && pane1.allowResize && pane2.allowResize;
};
var ASPxSplitterPaneHelper = ASPx.CreateClass(null, {
 constructor: function(pane) {
  this.pane = pane;
  this.indexPath = this.GetIndexPath();
  var paneIdPostfix = this.pane.isRootPane ? "" : "_" + this.indexPath;
  var separatorIdPostfix = paneIdPostfix + "_S";
  this.postfixes = {
   pane: paneIdPostfix,
   separator: separatorIdPostfix,
   table: paneIdPostfix + "_T",
   contentContainer: paneIdPostfix + "_CC",
   collapseForwardButton: separatorIdPostfix + "_CF",
   collapseBackwardButton: separatorIdPostfix + "_CB",
   collapseButtonsSeparator: separatorIdPostfix + "_CS"
  };
  this.buttonsTableExists = !!this.GetCollapseBackwardButton();
  this.separatorImageExists = !!this.GetCollapseButtonsSeparatorImage();
  this.buttonsExists = this.buttonsTableExists || this.separatorImageExists;
 },
 GetCachedValue: function (name, func) {
  return ASPx.CacheHelper.GetCachedValue(this, name, func);
 },
 DropCachedValue: function (name) {
  ASPx.CacheHelper.DropCachedValue(this, name);
 },
 DropCache: function() {
  ASPx.CacheHelper.DropCache(this);
 },
 GetIndexPath: function () {
  if(this.pane.isRootPane)
   return "";
  var parentPane = this.pane.parent;
  if(parentPane.isRootPane)
   return "" + this.pane.index;
  return parentPane.helper.indexPath + ASPx.ItemIndexSeparator + this.pane.index;
 },
 GetChildElement: function (idPostfix) {
  return this.pane.splitter.GetChildElement(idPostfix);
 },
 GetPaneElement: function () {
  return this.GetChildElement(this.postfixes.pane);
 },
 GetTableElement: function () {
  return this.GetChildElement(this.postfixes.table);
 },
 GetContentContainerElement: function () {
  return this.GetCachedValue(this.postfixes.contentContainer, 
   function () { return ASPx.GetElementById(this.pane.splitter.name + this.postfixes.contentContainer); });
 },
 DropContentContainerElementFromCache: function () {
  this.DropCachedValue(this.postfixes.contentContainer);
 },
 GetSeparatorElementId: function () {
  return this.pane.splitter.name + this.postfixes.separator;
 },
 GetSeparatorElement: function () {
  return this.GetChildElement(this.postfixes.separator);
 },
 GetSeparatorDivElement: function () {
  return this.GetCachedValue("separatorDivElement", function () {
   var separatorElement = this.GetSeparatorElement();
   return separatorElement ? separatorElement.childNodes[0] : null;
  });
 },
 GetCollapseBackwardButton: function () {
  return this.GetChildElement(this.postfixes.collapseBackwardButton);
 },
 GetCollapseForwardButton: function () {
  return this.GetChildElement(this.postfixes.collapseForwardButton);
 },
 GetCollapseButtonsSeparator: function () {
  return this.GetChildElement(this.postfixes.collapseButtonsSeparator);
 },
 GetCollapseButtonsTable: function () {
  return this.GetCachedValue("collapseButtonsTable", function () {
   return this.buttonsTableExists ? ASPx.GetParentByTagName(this.GetCollapseForwardButton(), "TABLE") : null;
  });
 },
 GetCollapseButtonsSeparatorImage: function () {
  return this.GetCachedValue("collapseButtonsSeparatorImage", function () {
   var separator = this.GetCollapseButtonsSeparator();
   if(!separator) {
    if(!this.buttonsTableExists)
     separator = this.GetSeparatorElement();
    else
     return null;
   }
   return ASPx.GetNodeByTagName(separator, "IMG", 0);
  });
 },
 GetButtonUpdateElement: function (buttonElement) {
  return !this.pane.isVertical ? buttonElement.parentNode : buttonElement;
 },
 ClearElementSizeProperty: function (property) {
  var element = this.GetPaneElement(),
   isVertical = property === "width";
  this.pane.savedSizeProperty = element.style[property];
  element.style[property] = "";
  if(!this.pane.IsAutoSize(isVertical)) {
   var contentContainerElement = this.GetContentContainerElement();
   this.pane.savedContentSizeProperty = contentContainerElement.style[property];
   contentContainerElement.style[property] = (this.pane.GetMinSize() - (isVertical ? this.pane.contentContainerWidthDiff : this.pane.contentContainerHeightDiff)) + "px";
  }
 },
 RestoreElementSizeProperty: function (property) {
  if(this.pane.savedSizeProperty) {
   this.GetPaneElement().style[property] = this.pane.savedSizeProperty;
   this.pane.savedSizeProperty = null;
  }
  if(!this.pane.IsAutoSize(property === "width")) {
   this.GetContentContainerElement().style[property] = this.pane.savedContentSizeProperty;
   this.pane.savedContentSizeProperty = null;
  }
 },
 SetEmptyDivVisible: function (visible) {
  var emptyDiv = this.GetCachedValue("emptyDiv", function () {
   var emptyDiv = document.createElement("DIV");
   emptyDiv.style.cssText = "overflow: hidden; width: 0px; height: 0px";
   emptyDiv.isVisible = false;
   return emptyDiv;
  });
  if(visible != emptyDiv.isVisible) {
   if(visible)
    this.GetPaneElement().appendChild(emptyDiv);
   else
    this.GetPaneElement().removeChild(emptyDiv);
   emptyDiv.isVisible = visible;
  }
 },
 HasCollapsedParent: function () {
  var parent = this.pane.parent;
  if(parent)
   return parent.collapsed || parent.helper.HasCollapsedParent();
  return false;
 },
 HasVisibleAutoSizeChildren: function (isVertical) {
  var result = false;
  if(!ASPx.IsExists(isVertical))
   isVertical = this.pane.isVertical;
  for(var i = 0; i < this.pane.panes.length; i++) {
   var pane = this.pane.panes[i];
   result = result || !pane.collapsed && pane.IsAutoSize(isVertical) && (!pane.panes.length || pane.helper.HasVisibleAutoSizeChildren(isVertical));
  }
  return result;
 },
 OnDispose: function() {
  this.pane = null;
  this.DropCache();
 }
});
var ASPxSplitterResizingPointer = ASPx.CreateClass(null, {
 constructor: function (elementId) {
  this.elementId = elementId;
  this.element = ASPx.GetElementById(this.elementId);
  this.x = 0;
  this.y = 0;
 },
 SetCursor: function (cursor) {
  this.element.style.cursor = cursor;
 },
 SetPosition: function (x, y) {
  this.x = x;
  this.y = y;
  ASPx.SetAbsoluteY(this.element, this.y);
  ASPx.SetAbsoluteX(this.element, this.x);
 },
 SetVisibility: function (isVisible) {
  ASPx.SetElementDisplay(this.element, isVisible);
 },
 Move: function (delta, isX) {
  if(isX)
   this.x += delta;
  else
   this.y += delta;
  this.SetPosition(this.x, this.y);
 },
 AttachToElement: function (element, isShow) {
  ASPx.SetStyles(this.element, {
   width: element.offsetWidth, height: element.offsetHeight
  });
  this.SetVisibility(true);
  this.SetPosition(ASPx.GetAbsoluteX(element), ASPx.GetAbsoluteY(element));
 }
});
var ASPxClientSplitter = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.leadingAfterInitCall = ASPxClientControl.LeadingAfterInitCallConsts.Reverse;
  this.emptyUrls = [
   "javascript:false",
   "about:blank",
   "#"
  ];
  this.width = "100%";
  this.height = "200px";
  this.helper = new SplitterHelper(this);
  this.resizingPointer = new ASPxSplitterResizingPointer(this.name + "_RP");
  this.rootPane = new ASPxClientSplitterPane(this, null, 0, 0, {});
  this.liveResizing = false;
  this.allowResize = true;
  this.defaultMinSize = 5;
  this.showSeparatorImage = true;
  this.showCollapseBackwardButton = false;
  this.showCollapseForwardButton = false;
  this.fullScreen = false;
  this.prepared = false;
  this.PaneResizing = new ASPxClientEvent();
  this.PaneResized = new ASPxClientEvent();
  this.PaneCollapsing = new ASPxClientEvent();
  this.PaneCollapsed = new ASPxClientEvent();
  this.PaneExpanding = new ASPxClientEvent();
  this.PaneExpanded = new ASPxClientEvent();
  this.PaneResizeCompleted = new ASPxClientEvent();
  this.PaneContentUrlLoaded = new ASPxClientEvent();
  this.autoHeightPanes = [];
  this.autoWidthPanes = [];
  this.documentScrollTop = 0;
  this.documentScrollLeft = 0;
  this.inFullscreen = false;
 },
 SetData: function(data){
  if(data.isVertical)
   this.rootPane.isVertical = data.isVertical;
  if(data.panes)
   this.CreatePanes(data.panes);
 },
 CreatePanes: function (panesInfo) {
  this.CreatePanesInternal(this.rootPane, panesInfo);
  this.rootPane.ForEach("UpdateSize");
  this.rootPane.ForEach("UpdateAutoSize");
  this.state = this.GetStateObj(panesInfo);
 },
 CreatePanesInternal: function (parent, panesInfo) {
  var prevPane = null,
   visibleIndex = 0;
  for(var i = 0; i < panesInfo.length; i++) {
   var paneInfo = panesInfo[i];
   if(!paneInfo.v) continue; 
   var pane = new ASPxClientSplitterPane(this, parent, visibleIndex++, i, paneInfo);
   updatePrevNext(pane);
   updateAutoSize(parent, pane.autoWidth, pane.autoHeight);
   parent.panes.push(pane);
   if(ASPx.IsExists(paneInfo["i"]))
    this.CreatePanesInternal(pane, paneInfo["i"]);
  }
  function updatePrevNext(pane) {
   pane.prevPane = prevPane;
   if(prevPane != null)
    prevPane.nextPane = pane;
   prevPane = pane;
  }
  function updateAutoSize(pane, autoWidth, autoHeight) {
   if(pane && (autoWidth || autoHeight)) {
    if(autoWidth)
     pane.autoWidth = true;
    if(autoHeight)
     pane.autoHeight = true;
    if(!pane.splitter.hasAutoSizePane)
     pane.splitter.hasAutoSizePane = true;
    updateAutoSize(pane.parent, autoWidth, autoHeight);
   }
  }
 },
 GetStateObj: function (panesInfo) {
  var result = [];
  for(var i = 0; i < panesInfo.length; i++) {
   var paneState = {};
   if(panesInfo[i].st) {
    paneState.st = panesInfo[i].st;
    paneState.s = panesInfo[i].s;
   }
   if(panesInfo[i].c)
    paneState.c = panesInfo[i].c;
   if(panesInfo[i]["i"])
    paneState["i"] = this.GetStateObj(panesInfo[i]["i"]);
   result.push(paneState);
  }
  return result;
 },
 GetClientStateString: function () {
  return ASPx.Json.ToJson(this.GetClientStateObject());
 },
 GetClientStateObject: function () {
  return this.RefreshState(this.state, this.rootPane.panes);
 },
 RefreshState: function (state, panes) {
  for(var i = 0; i < panes.length; i++) {
   var pane = panes[i];
   var paneState = state[pane._index];
   paneState.s = Math.round(pane.size * 1000) / 1000;
   paneState.st = pane.sizeType;
   paneState.c = pane.collapsed ? 1 : 0;
   paneState.mp = !!pane.maximizedPane ? pane.maximizedPane.index : -1;
   if(pane.panes.length == 0) {
    paneState.spt = Math.round(pane.scrollTop);
    paneState.spl = Math.round(pane.scrollLeft);
   }
   if(pane.panes.length > 0)
    this.RefreshState(paneState["i"], pane.panes);
  }
  return state;
 },
 InlineInitialize: function () {
  this.EnsureFullscreenMode();
  this.rootPane.ForEach("Initialize");
  ASPxClientControl.prototype.InlineInitialize.call(this);
 },
 EnsureFullscreenMode: function () {
  if(this.fullScreen) {
   var overflowProperty = "overflow",
    autoWidth = this.rootPane.autoWidth,
    autoHeight = this.rootPane.autoHeight;
   if(autoWidth && autoHeight)
    overflowProperty = null;
   else if(autoWidth)
    overflowProperty = "overflowY";
   else if(autoHeight)
    overflowProperty = "overflowX";
   var element = this.GetMainElement().parentNode;
   while(element && element.tagName) {
    var tagName = element.tagName.toLowerCase();
    if(tagName != "tbody") {
     element.style.height = "100%";
     if(tagName == "form" || tagName == "body" || tagName == "html") {
      element.style.margin = "0px";
      element.style.padding = "0px";
      if(overflowProperty)
       element.style[overflowProperty] = "hidden";
      if(autoHeight != autoWidth && (tagName == "body" || tagName == "html"))
       element.style.overflow = "hidden";
     }
     if(tagName == "html")
      break;
    }
    element = element.parentNode;
   }
  }
 },
 Initialize: function () {
  ASPxClientControl.prototype.Initialize.call(this);
  this.rootPane.ForEach("CreateContentUrlIFrame", true);
  if(ASPx.Browser.TouchUI) 
   this.UpdateAutoSizePanes();
 },
 AfterInitialize: function () {
  ASPxClientControl.prototype.AfterInitialize.call(this);
  this.SubscribeBrowserFullScreenChangeEvent();
  this.rootPane.ForEach("RaiseResizedEvent", true);
 },
 OnWebkitFullScreenChange: function(e) {
  this.inFullscreen = true;
  this.rootPane.ForEach('SetVisibleOverflow');
 },
 SubscribeBrowserFullScreenChangeEvent: function() {
  if(ASPx.Browser.Chrome) {
   this.webKitFullScreenChangeHandler = this.OnWebkitFullScreenChange.bind(this);
   ASPx.Evt.AttachEventToDocument('webkitfullscreenchange', this.webKitFullScreenChangeHandler);
  }
 },
 UnsubscribeFromBrowserFullScreenChangeEvent: function() {
  if(this.webKitFullScreenChangeHandler)
   ASPx.Evt.DetachEventFromDocument('webkitfullscreenchange', this.webKitFullScreenChangeHandler);
 },
 IsPrepared: function () {
  return this.prepared;
 },
 Prepare: function () {
  if(this.IsPrepared() || !this.IsDisplayed())
   return;
  this.rootPane.ForEach("Prepare", true);
  ASPxClientSplitter.Instances.Add(this);
  this.prepared = true;
 },
 UpdateAdjustmentFlags: function () {
  var mainElement = this.GetMainElement();
  if(mainElement) {
   var mainElementStyle = ASPx.GetCurrentStyle(mainElement);
   this.UpdatePercentSizeConfig([mainElementStyle.width, this.width], [mainElementStyle.height, this.height]);
  }
 },
 AdjustControlCore: function () {
  this.Prepare();
  this.UpdateControlSizes(false, this.isInsideHierarchyAdjustment);
 },
 NeedCollapseControlCore: function () {
  return true;
 },
 NeedUpdateControlSizes: function () {
  return ASPx.IsPercentageSize(this.width) || ASPx.IsPercentageSize(this.height) || !this.sizeUpdatedOnce;
 },
 UpdateControlSizes: function (forceUpdate, disableControlsAdjustment) {
  if(!(forceUpdate || this.NeedUpdateControlSizes()) || !this.IsDisplayed())
   return;
  var element = this.GetMainElement();
  element.style.width = this.width;
  element.style.height = this.height;
  var focusedElement = ASPx.GetFocusedElement(); 
  var isFocusedElementVisible = ASPx.IsElementVisible(focusedElement, true);
  var savedSelectionStart = null,
   savedSelectionEnd = null,
   editor = null;
  var innerEditorIsFocused = false;
  if(window.ASPxClientEdit && !!focusedElement && isFocusedElementVisible) {
   editor = ASPx.GetFocusedEditor();
   if(!!editor) {
    innerEditorIsFocused = true;
    editor.BeginFocusUpdate(); 
    savedSelectionStart = focusedElement.selectionStart;
    savedSelectionEnd = focusedElement.selectionEnd;
   }
  }
  this.saveDocumentScrollPositon();
  this.UpdatePanesVisible(ASPx.Attr.ChangeStyleAttribute);
  if(ASPx.Browser.WebKitFamily)
   this.CreateWebkitSpecialElement();
  var newWidth = ASPx.GetClearClientWidth(element);
  var newHeight = ASPx.GetClearClientHeight(element);
  this.UpdatePanesVisible(ASPx.Attr.RestoreStyleAttribute);
  this.restoreDocumentScrollPoisiton();
   this.rootPane.offsetWidth = Math.max(newWidth, this.defaultMinSize);
   this.rootPane.offsetHeight = Math.max(newHeight, this.defaultMinSize);
   this.rootPane.UpdatePanes(true);
  try { 
   if(focusedElement &&  
    isFocusedElementVisible && 
    !ASPx.Browser.AndroidMobilePlatform && 
    !(ASPx.Browser.MacOSMobilePlatform && ASPx.Browser.Version >= 6) && 
    ASPx.GetIsParent(element, focusedElement) && 
    !(focusedElement.tagName && focusedElement.tagName == "IFRAME")) { 
    focusedElement.blur();
    focusedElement.focus(); 
    if(innerEditorIsFocused) {
     focusedElement.selectionStart = savedSelectionStart;
     focusedElement.selectionEnd = savedSelectionEnd;
    }
   }
  }
  catch (e) { }
  this.rootPane.ForEach("ApplyScrollPosition", true);
  if(this.isInitialized && !disableControlsAdjustment)
   this.rootPane.ForEach("AdjustControls", true);
  if(innerEditorIsFocused)
   window.setTimeout(editor.EndFocusUpdate.bind(editor), 0);
  if(this.IsPrepared())
   this.sizeUpdatedOnce = true;
  this.UpdateCookie();
 },
 saveDocumentScrollPositon: function() {
  if(this.isInitialized) {
   this.documentScrollTop = ASPx.GetDocumentScrollTop();
   this.documentScrollLeft = ASPx.GetDocumentScrollLeft();
  }
 },
 restoreDocumentScrollPoisiton: function() {
  if(this.documentScrollTop > 0 && ASPx.GetDocumentScrollTop() !== this.documentScrollTop)
   ASPx.SetDocumentScrollTop(this.documentScrollTop);
  if(this.documentScrollLeft > 0 && ASPx.GetDocumentScrollLeft() !== this.documentScrollLeft)
   ASPx.SetDocumentScrollLeft(this.documentScrollLeft);
  this.documentScrollTop = 0;
  this.documentScrollLeft = 0;
 },
 UpdateAutoSizePanes: function (forced) {
  if(this.hasAutoSizePane) {
   var heightChanged = this.UpdateAutoHeightPanes(forced),
    widthChanged = this.UpdateAutoWidthPanes(forced);
   if(forced || heightChanged || widthChanged)
    this.rootPane.ForEach("UpdateChildrenSize");
  }
 },
 UpdateAutoHeightPanes: function (forced) {
  var changed = false;
  for(var i = 0; i < this.autoHeightPanes.length; i++)
   changed = this.autoHeightPanes[i].IsContentHeightChanged() || changed;
  if(forced || changed)
   this.UpdateAutoSizePanesSizes(false);
  return changed;
 },
 UpdateAutoWidthPanes: function (forced) {
  var changed = false;
  for(var i = 0; i < this.autoWidthPanes.length; i++)
   changed = this.autoWidthPanes[i].IsContentWidthChanged() || changed;
  if(forced || changed)
   this.UpdateAutoSizePanesSizes(true);
  return changed;
 },
 UpdateAutoSizePanesSizes: function (isVertical) {
  var autoSizePanes = isVertical
   ? this.autoWidthPanes
   : this.autoHeightPanes,
   property = isVertical ? "width" : "height",
   percentPanes = [];
  for(var i = 0; i < autoSizePanes.length; i++) {
   var pane = autoSizePanes[i];
   if(!pane.helper.HasCollapsedParent()) {
    pane.helper.ClearElementSizeProperty(property);
    for(var child = pane.panes[0]; child; child = child.nextPane)
     if(!child.isSizePx) {
      percentPanes.push(child);
      child.helper.ClearElementSizeProperty(property);
     }
   }
  }
  for(var i = 0; i < autoSizePanes.length; i++)
   autoSizePanes[i].UpdateOffsetSize(isVertical);
  for(var i = 0; i < autoSizePanes.length; i++) {
   var pane = autoSizePanes[i];
   if(!pane.helper.HasCollapsedParent())
    pane.helper.RestoreElementSizeProperty(property);
  }
  for(var i = 0; i < percentPanes.length; i++)
   percentPanes[i].helper.RestoreElementSizeProperty(property);
 },
 UpdatePanesVisible: function (func) {
  var firstTD = this.rootPane.panes[0].helper.GetPaneElement();
  func(firstTD, "width", "1px");
  func(firstTD, "height", "1px");
  func(this.rootPane.panes[0].helper.GetContentContainerElement(), "display", "none");
  for(var i = 1; i < this.rootPane.panes.length; i++) {
   var pane = this.rootPane.panes[i];
   func(pane.helper.GetPaneElement(), "display", "none");
   var separator = pane.helper.GetSeparatorElement();
   if(separator)
    func(separator, "display", "none");
  }
 },
 UpdateCookie: function () {
  if(this.cookieName && this.cookieName != "") {
   ASPx.Cookie.DelCookie(this.cookieName);
   ASPx.Cookie.SetCookie(this.cookieName, this.GetClientStateString());
  }
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ state: this.GetClientStateObject() });
 },
 GetPaneByPath: function (panePath, parentPane) {
  var pane = parentPane || this.rootPane;
  for(var i = 0; i < panePath.length; i++)
   pane = pane.panes[panePath[i]];
  return pane;
 },
 GetPaneByStringPath: function (paneStringPath, paneIndexSeparator) {
  if(!paneIndexSeparator)
   paneIndexSeparator = ASPx.ItemIndexSeparator;
  return this.GetPaneByPath(paneStringPath.split(paneIndexSeparator));
 },
 IsDocumentWidthChanged: function () {
  var documentWidth = this.GetDocumentWidth();
  if(!ASPx.IsExists(this.lastDocumentWidth) || documentWidth != this.lastDocumentWidth) {
   this.lastDocumentWidth = documentWidth;
   return true;
  }
  return false;
 },
 GetDocumentWidth: function () {
  if(this.fullScreen && (this.rootPane.autoHeight || this.rootPane.autoWidth))
   return this.GetDocumentWidthFullscreen();
  return ASPx.GetDocumentWidth();
 },
 GetDocumentWidthFullscreen: function () {
  var sizeElement = ASPx.CacheHelper.GetCachedValue(this, "fullscreenWidthElement", function () {
   var element = ASPx.CreateHtmlElementFromString("<div style='width: 100%; height: 0px'></div>");
   this.GetMainElement().parentNode.insertBefore(element, this.GetMainElement());
   return element;
  });
  return sizeElement.offsetWidth;
 },
 CreateWebkitSpecialElement: function () {
  var webkitSpecialElement = document.createElement("DIV"),
    element = this.GetMainElement();
  element.parentNode.appendChild(webkitSpecialElement);
  var dummy = element.offsetHeight;
  element.parentNode.removeChild(webkitSpecialElement);
 },
 OnBrowserWindowResize: function() {
  if(this.inFullscreen)
   window.setTimeout(function() {
    this.inFullscreen = false;
    this.rootPane.ForEach('ResetOverflow');
   }.aspxBind(this), 0);
  this.UpdateControlSizes(false, true);
  this.lastDocumentWidth = this.GetDocumentWidth();
 },
 BrowserWindowResizeSubscriber: function() {
  return this.widthValueSetInPercentage;
 },
 OnSeparatorMouseDown: function (moveRightPanePath) {
  var pane = this.GetPaneByStringPath(moveRightPanePath);
  var invert = this.rtl && !pane.isVertical;
  this.moveRightPane = invert ? pane.prevPane : pane;
  this.moveLeftPane = invert ? pane : pane.prevPane;
  this.moveIsVertical = pane.isVertical;
  this.moveStartPos = this.helper.GetCurrentPos();
  this.moveLastPos = this.moveStartPos;
  this.isHeavyUpdate = this.moveLeftPane.isSizePx != this.moveRightPane.isSizePx
   && !this.moveLeftPane.parent.IsAutoSize();
  if(!SplitterHelper.IsAllowResize(this.moveLeftPane, this.moveRightPane))
   return false;
  if(this.moveLeftPane.collapsed || this.moveRightPane.collapsed)
   return false;
  if(this.RaiseCancelEvent("PaneResizing", this.moveRightPane) || this.RaiseCancelEvent("PaneResizing", this.moveLeftPane))
   return false;
  var cursor = this.moveIsVertical ? "n-resize" : "w-resize";
  if(!this.liveResizing) {
   this.resizingPointer.SetCursor(cursor);
   this.resizingPointer.AttachToElement(pane.helper.GetSeparatorElement(), true);
  }
  else
   this.isInLiveResizing = true;
  this.setIframesMouseMoveEnabled(this.moveRightPane, false);
  this.setIframesMouseMoveEnabled(this.moveLeftPane, false);
  this.helper.SetResizingPanelVisibility(true, cursor);
  return true;
 },
 OnSeparatorMouseUp: function () {
  this.helper.SetResizingPanelVisibility(false);
  if(!this.liveResizing || !this.isHeavyUpdate) {
   var deltaSize = this.moveLastPos - this.moveStartPos;
   if(!this.moveLeftPane.IsAutoSize(!this.moveLeftPane.isVertical)) {
    this.moveLeftPane.SetOffsetSize(this.moveLeftPane.GetOffsetSize() - deltaSize);
    this.moveLeftPane.inResizing = true;
   }
   if(!this.moveRightPane.IsAutoSize(!this.moveRightPane.isVertical)) {
    this.moveRightPane.SetOffsetSize(this.moveRightPane.GetOffsetSize() + deltaSize);
    this.moveRightPane.inResizing = true;
   }
   if(!this.liveResizing || !this.hasAutoSizePane)
    SplitterHelper.Resize(this.moveLeftPane, this.moveRightPane, deltaSize);
   this.moveLeftPane.parent.ForEach("UpdateChildrenSize");
  }
  if(!this.liveResizing)
   this.resizingPointer.SetVisibility(false);
  else
   this.isInLiveResizing = null;
  this.UpdateAutoSizePanes(true);
  this.moveLeftPane.parent.ForEach("AdjustControls");
  if(!this.liveResizing && (this.rootPane.autoHeight || this.rootPane.autoWidth) && this.IsDocumentWidthChanged())
   this.UpdateControlSizes();
  this.moveLeftPane.inResizing = null;
  this.moveRightPane.inResizing = null;
  this.UpdateCookie();
  this.setIframesMouseMoveEnabled(this.moveRightPane, true);
  this.setIframesMouseMoveEnabled(this.moveLeftPane, true);
  this.RaiseEvent("PaneResizeCompleted", this.moveLeftPane);
  this.RaiseEvent("PaneResizeCompleted", this.moveRightPane);
 },
 OnMouseMove: function () {
  var deltaSize = this.helper.GetMoveMaxDeltaSize(this.helper.GetCurrentPos() - this.moveLastPos);
  if(deltaSize == 0) return;
  if(!this.moveLeftPane.IsAutoSize(!this.moveLeftPane.isVertical) || this.liveResizing)
   this.moveLeftPane.SetOffsetSize(this.moveLeftPane.GetOffsetSize() + deltaSize);
  if(!this.moveRightPane.IsAutoSize(!this.moveRightPane.isVertical) || this.liveResizing)
   this.moveRightPane.SetOffsetSize(this.moveRightPane.GetOffsetSize() - deltaSize);
  if(this.liveResizing) {
   var changePaneSize = function (pane, deltaSize) {
    pane.SetContentVisible(false);
    if(pane.ApplyElementSize()) {
     pane.ForEach("UpdateChildrenSize");
     pane.SetContentVisible(true);
     pane.RaiseResizedEvent();
    }
   };
   if(this.isHeavyUpdate || this.moveLeftPane.parent.autoHeight || this.moveLeftPane.parent.autoWidth) {
    SplitterHelper.Resize(this.moveLeftPane, this.moveRightPane, this.moveLeftPane.isSizePx || this.moveRightPane.isSizePx ? deltaSize : 0);
    this.moveLeftPane.parent.ForEach("UpdateChildrenSize");
   }
   else {
    changePaneSize(this.moveLeftPane, deltaSize, this.helper);
    changePaneSize(this.moveRightPane, -deltaSize, this.helper);
   }
   this.UpdateAutoSizePanes(this.liveResizing);
  }
  else
   this.resizingPointer.Move(deltaSize, !this.moveIsVertical);
  this.moveLastPos += deltaSize;
 },
 setIframesMouseMoveEnabled: function(pane, enabled) {
  if(pane) {
   var iframe = pane.GetContentIFrame();
   if(iframe)
    iframe.style.pointerEvents = enabled ? "" : "none";
  }
 },
 CreateFakeDivForIframe: function(iframe) {
  var fakeDiv = document.createElement("div");
  ASPx.SetStyles(fakeDiv, { width: iframe.offsetWidth, height: iframe.offsetHeight });
  return fakeDiv;
 },
 CreateIframeCoverDiv: function(iframe, index) {
  if(!this.iframeCoverDiv)
   this.iframeCoverDiv = [];
  if(!this.iframeCoverDiv[index])
   this.iframeCoverDiv[index] = this.CreateFakeDivForIframe(iframe);
  this.iframeCoverDiv[index].style.position = "absolute";
  this.iframeCoverDiv[index].className = "dxspl-cover";
  iframe.parentElement.appendChild(this.iframeCoverDiv[index]);
  ASPx.SetAbsoluteX(this.iframeCoverDiv[index], ASPx.GetAbsoluteX(iframe));
  ASPx.SetAbsoluteY(this.iframeCoverDiv[index], ASPx.GetAbsoluteY(iframe));
 },
 RemoveIframeCoverDiv: function(iframe, index) {
  iframe.parentElement.removeChild(this.iframeCoverDiv[index]);
  this.iframeCoverDiv[index] = null;
 },
 OnCollapseButtonClick: function (panePath, forwardDirection) {
  var rightPane = this.GetPaneByStringPath(panePath);
  var pane1 = forwardDirection ? rightPane.prevPane : rightPane;
  var pane2 = forwardDirection ? rightPane : rightPane.prevPane;
  if(pane1.collapsed && pane1.maximizedPane == pane2) {
   if(!this.RaiseCancelEvent("PaneExpanding", pane1)) {
    pane1.Expand();
    if(this.savedSize) {
     var rootPaneChildren = this.rootPane.panes;
     for(var i = 0; i < rootPaneChildren.length; i++) {
      if(rootPaneChildren[i].IsCollapsed())
       return;
     }
     for(var sizeProperty in this.savedSize)
      if(this.savedSize.hasOwnProperty(sizeProperty))
       this.GetMainElement().style[sizeProperty] = this.savedSize[sizeProperty];
     this.savedSize = null;
    }
   }
  }
  else {
   if(!this.RaiseCancelEvent("PaneCollapsing", pane2)) {
    if(pane2.NeedResetSplitterSizeOnCollapsing(pane1)) {
     if(!this.savedSize)
      this.savedSize = {};
     var sizeProperty = pane1.isVertical ? "height" : "width";
     if(!this.savedSize[sizeProperty]) {
      this.savedSize[sizeProperty] = this.GetMainElement().style[sizeProperty];
      this.GetMainElement().style[sizeProperty] = "";
     }
    }
    pane2.Collapse(pane1);
   }
  }
 },
 IsEmptyUrl: function (url) {
  for(var i = 0; i < this.emptyUrls.length; i++)
   if(url == this.emptyUrls[i])
    return true;
  return false;
 },
 RaiseEvent: function (eventName, pane) {
  if(this.isInitialized)
   this[eventName].FireEvent(this, new ASPxClientSplitterPaneEventArgs(pane));
 },
 RaiseCancelEvent: function (eventName, pane) {
  var args = new ASPxClientSplitterPaneCancelEventArgs(pane);
  this[eventName].FireEvent(this, args);
  return args.cancel;
 },
 GetPaneCount: function () {
  return this.rootPane.GetPaneCount();
 },
 GetPane: function (index) {
  return this.rootPane.GetPane(index);
 },
 GetPaneByName: function (name) {
  return this.rootPane.GetPaneByName(name);
 },
 SetAllowResize: function (allowResize) {
  if(this.allowResize == allowResize)
   return;
  this.allowResize = allowResize;
  this.rootPane.ForEach("UpdateSeparatorStyle", true);
 },
 GetLayoutData: function() {
  return this.GetClientStateString();
 },
 SetWidth: function (width) {
  this.width = width + "px";
  if(this.IsPrepared())
   this.UpdateControlSizes(true);
 },
 SetHeight: function (height) {
  this.height = height + "px";
  if(this.IsPrepared())
   this.UpdateControlSizes(true);
 },
 OnDispose: function() {
  this.RemoveGlobalLinksToObject();
  this.rootPane.ForEach("OnDispose");
  if(this.helper)
   this.helper.OnDispose();
  ASPxClientControl.prototype.OnDispose.call(this);
 },
 RemoveGlobalLinksToObject: function() {
  this.UnsubscribeFromBrowserFullScreenChangeEvent();
  ASPxClientSplitter.Instances.Remove(this.name);
  if(ASPxClientSplitter.current === this)
   ASPxClientSplitter.current = null;
 }
});
ASPxClientSplitter.Cast = ASPxClientControl.Cast;
var ASPxClientSplitterPane = ASPx.CreateClass(null, {
 constructor: function (splitter, parent, visibleIndex, index, paneInfo) {
  this.splitter = splitter;
  this.parent = parent;
  this.index = visibleIndex;
  this._index = index;
  this.name = paneInfo.n || "";
  this.isRootPane = (this.parent == null);
  this.helper = new ASPxSplitterPaneHelper(this);
  this.prevPane = null;
  this.nextPane = null;
  this.panes = [];
  this.isVertical = this.isRootPane ? false : !parent.isVertical;
  this.hasSeparator = (this.index > 0);
  this.collapsed = ASPx.IsExists(paneInfo.c);
  this.size = ASPx.IsExists(paneInfo.s) ? paneInfo.s : 0;
  this.sizeType = ASPx.IsExists(paneInfo.st) ? paneInfo.st : null;
  this.autoWidth = ASPx.IsExists(paneInfo.aw);
  this.autoHeight = ASPx.IsExists(paneInfo.ah);
  this.maxSize = ASPx.IsExists(paneInfo.smax) ? paneInfo.smax : Number.MAX_VALUE;
  this.minSize = ASPx.IsExists(paneInfo.smin) ? paneInfo.smin : this.splitter.defaultMinSize;
  this.allowResize = !ASPx.IsExists(paneInfo.nar);
  this.showCollapseBackwardButton = ASPx.IsExists(paneInfo.scbb);
  this.showCollapseForwardButton = ASPx.IsExists(paneInfo.scfb);
  this.maximizedPaneIndex = ASPx.IsExists(paneInfo.mp) ? paneInfo.mp : -1;
  this.iframe = {};
  if(paneInfo.iframe) {
   this.iframe = {
    src: paneInfo.iframe[0],
    scrolling: paneInfo.iframe[1]
   };
   if(paneInfo.iframe[2] != "")
    this.iframe.name = paneInfo.iframe[2];
   if(paneInfo.iframe[3] != "")
    this.iframe.title = paneInfo.iframe[3];
   this.isContentUrl = true;
  }
  this.scrollTop = paneInfo.spt || 0;
  this.scrollLeft = paneInfo.spl || 0;
  this.isSizePx = (this.sizeType == "px");
  this.maximizedPane = null;
  this.dragPrevented = false;
  this.offsetWidth = 0;
  this.offsetHeight = 0;
  this.widthDiff = 0;
  this.heightDiff = 0;
  this.contentContainerWidthDiff = 0;
  this.contentContainerHeightDiff = 0;
  this.collapsedWidthDiff = 0;
  this.collapsedHeightDiff = 0;
  this.isASPxClientSplitterPane = true;
 },
 SetVisibleOverflow: function() {
  var element = this.helper.GetContentContainerElement();
  if(element)
   element.style.overflow = 'visible';
 },
 ResetOverflow: function() {
  var element = this.helper.GetContentContainerElement();
  if(element)
   element.style.overflow = '';
 },
 UpdateSize: function () {
  if(!this.panes.length) return;
  var prcSum = 0,
   emptyPanesCount = 0;
  for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
   if(!pane.sizeType)
    emptyPanesCount++;
   else if(pane.sizeType == "%")
    prcSum += pane.size;
  }
  if(emptyPanesCount) {
   var emptyPaneSize = Math.max(100 - prcSum, 0) / emptyPanesCount;
   for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
    if(!pane.sizeType) {
     pane.sizeType = "%";
     pane.size = emptyPaneSize;
    }
   }
  }
  if(prcSum && (!emptyPanesCount && prcSum != 100 || prcSum > 100)) {
   for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
    if(pane.sizeType == "%")
     pane.size = 100 * pane.size / prcSum;
   }
  }
 },
 UpdateAutoSize: function () {
  if(this.panes.length) {
   var propertyAll = this.isVertical ? "autoHeight" : "autoWidth",
    propertyOne = this.isVertical ? "autoWidth" : "autoHeight";
   if(this[propertyAll]) {
    for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
     pane[propertyAll] = true;
    }
   }
   if(this[propertyOne]) {
    var selected;
    for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
     if(pane[propertyOne] || !pane.isSizePx || pane.isSizePx && !selected && !pane.nextPane)
      selected = pane;
     if(pane[propertyOne])
      break;
    }
    selected[propertyOne] = true;
   }
   for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
    if(pane.isSizePx)
     continue;
    if(pane[propertyOne]) {
     pane.size = pane.GetMinSize();
     pane.sizeType = "px";
     pane.isSizePx = true;
    }
   }
  }
  if(!this.isRootPane) {
   if(this.autoHeight)
    this.splitter.autoHeightPanes.push(this);
   if(this.autoWidth)
    this.splitter.autoWidthPanes.push(this);
  }
 },
 IsAutoSize: function (isVertical) {
  if(isVertical == null)
   isVertical = this.isVertical;
  return isVertical ? this.autoWidth : this.autoHeight;
 },
 IsContentHeightChanged: function () {
  var contentHeight = this.helper.GetContentContainerElement().getBoundingClientRect().height;
  if(!ASPx.IsExists(this.lastContentHeight) || Math.abs(contentHeight - this.lastContentHeight) > 1) {
   this.lastContentHeight = contentHeight;
   return true;
  }
  return false;
 },
 IsContentWidthChanged: function () {
  var contentWidth = this.helper.GetContentContainerElement().getBoundingClientRect().width;
  if(!ASPx.IsExists(this.lastContentWidth) || Math.abs(contentWidth - this.lastContentWidth) > 1) {
   this.lastContentWidth = contentWidth;
   return true;
  }
  return false;
 },
 UpdateOffsetSize: function (isVertical) {
  var hasPanes = !!this.panes.length,
   contentContainerSizeDiff = hasPanes
    ? 0
    : isVertical
     ? this.widthDiff
     : this.heightDiff,
    contentSize = 0;
  if(this.isContentUrl && !hasPanes) {
   var element = this.helper.GetContentContainerElement();
   element.style.display = "none";
  }
  var contentSize = this.GetContentMinSize(isVertical);
  this.SetOffsetSize(Math.max(this.GetMinSize(!isVertical), contentSize), !isVertical);
  if(this.isContentUrl && !hasPanes) {
   var element = this.helper.GetContentContainerElement();
   element.style[isVertical ? "width" : "height"] = this.isVertical || isVertical
    ? "100%"
    : this.helper.GetPaneElement().offsetHeight - contentContainerSizeDiff + "px";
   element.style.display = "";
  }
 },
 GetContentMinSize: function (isVertical) {
  if(!this.panes.length) {
   var contentContainerElement = this.helper.GetContentContainerElement(),
    contentContainerSizeDiff = isVertical
     ? this.widthDiff
     : this.heightDiff;
   return (isVertical ? contentContainerElement.offsetWidth : contentContainerElement.offsetHeight) + contentContainerSizeDiff;
  }
  var contentSize = 0;
  if(this.isVertical != isVertical)
   for(var pane = this.panes[0]; pane; pane = pane.nextPane)
    contentSize = Math.max(contentSize, pane.GetContentMinSize(isVertical));
  else {
   for(var pane = this.panes[0]; pane; pane = pane.nextPane)
    contentSize += pane.GetContentMinSize(isVertical);
   contentSize += this.GetTotalSeparatorsSize(!this.isVertical);
  }
  return contentSize;
 },
 Initialize: function() {
  this.InitializePreventDragging();
  if(this.isRootPane)
   return;
  if(this.collapsed) {
   if(this.maximizedPaneIndex !== -1)
    this.maximizedPane = this.GetParentPane().GetPane(this.maximizedPaneIndex);
   else if(this.IsFirstPane())
    this.maximizedPane = this.GetNextPane();
   else if(this.IsLastPane())
    this.maximizedPane = this.GetPrevPane();
   else if(this.prevPane.maximizedPane !== this)
    this.maximizedPane = this.prevPane;
   else
    this.maximizedPane = this.nextPane;
   if(this.maximizedPane == null)
    this.collapsed = false;
  }
 },
 PrepareInternal: function(needToResetContentSize) {
  var EvaluateWidthDiff = function(element) {
   return element.getBoundingClientRect().width - element.clientWidth;
  };
  var EvaluateHeightDiff = function(element) {
   var elementClientHeight = ((ASPx.Browser.Safari && (ASPx.Browser.Version < 4)) || (ASPx.Browser.Chrome && (ASPx.Browser.Version < 2))) ? (element.offsetHeight - element.clientTop * 2) : element.clientHeight;
   return element.getBoundingClientRect().height - elementClientHeight;
  };
  this.GetSeparatorSize();
  var element = this.helper.GetPaneElement();
  this.widthDiff = EvaluateWidthDiff(element);
  this.heightDiff = EvaluateHeightDiff(element); 
  if(needToResetContentSize && this.panes.length == 0) {
   var contentContainerElement = this.helper.GetContentContainerElement();
   ASPx.SetScrollBarVisibility(contentContainerElement, false);
   ASPx.SetStyles(contentContainerElement, { width: 1, height: 1 });
   var overflow = contentContainerElement.style.overflowY;
   if(ASPx.Browser.Edge) 
    contentContainerElement.style.overflowY = '';
   this.contentContainerWidthDiff = contentContainerElement.offsetWidth - 1;
   this.contentContainerHeightDiff = contentContainerElement.offsetHeight - 1;
   if(ASPx.Browser.Edge) 
    contentContainerElement.style.overflowY = overflow;
   if(this.autoWidth) {
    contentContainerElement.style.width = "";
    var minWidthValue = this.splitter.defaultMinSize - this.contentContainerWidthDiff;
    if(minWidthValue > -1)
     contentContainerElement.style.minWidth = minWidthValue + "px";
   }
   if(this.autoHeight) {
    contentContainerElement.style.height = "";
    var minHeightValue = this.splitter.defaultMinSize - this.contentContainerWidthDiff;
    if(minHeightValue > -1)
     contentContainerElement.style.minHeight = minHeightValue + "px";
   }
   ASPx.SetScrollBarVisibility(contentContainerElement, true);
   if(!this.scrollEventAttached) {
    var _this = this;
    ASPx.Evt.AttachEventToElement(contentContainerElement, "scroll", function () {
     if(!_this.splitter) return;
     if(contentContainerElement.scrollTop >= 0)
      _this.scrollTop = contentContainerElement.scrollTop;
     if(contentContainerElement.scrollLeft >= 0)
      _this.scrollLeft = contentContainerElement.scrollLeft;
     _this.splitter.UpdateCookie();
    });
    this.scrollEventAttached = true;
   }
  }
  this.UpdateStyle(element, true);
  this.collapsedWidthDiff = EvaluateWidthDiff(element);
  this.collapsedHeightDiff = EvaluateHeightDiff(element);
  this.UpdateStyle(element, false);
  var separator = this.helper.GetSeparatorElement();
  if(separator) {
   ASPx.SetElementDisplay(this.helper.GetSeparatorDivElement(), false);
   if(!this.isVertical)
    this.separatorSizeDiff = separator.offsetWidth - separator.clientWidth;
   else
    this.separatorSizeDiff = separator.offsetHeight - separator.clientHeight;
   ASPx.SetElementDisplay(this.helper.GetSeparatorDivElement(), true);
  }
  else
   this.separatorSizeDiff = 0;
  this.PrepareSeparatorButtons();
  if(ASPx.Browser.WebKitTouchUI) {
   var contentContainer = this.helper.GetContentContainerElement();
   var scrollbarVisible = contentContainer.style.overflow == "auto" || contentContainer.style.overflow == "scroll";
   var hScrollbarVisible = scrollbarVisible || contentContainer.style.overflowX == "scroll";
   var vScrollbarVisible = scrollbarVisible || contentContainer.style.overflowY == "scroll";
   if(hScrollbarVisible || vScrollbarVisible) {
    ASPx.TouchUIHelper.MakeScrollable(contentContainer, { showHorizontalScrollbar: hScrollbarVisible, showVerticalScrollbar: vScrollbarVisible });
   }
  }
  if(needToResetContentSize && !this.isRootPane) {
   if(this.autoHeight)
    this.offsetHeight = this.GetMinSize(true);
   if(this.autoWidth)
    this.offsetWidth = this.GetMinSize(false);
  }
 },
 Prepare: function() {
  this.PrepareInternal(true);
 },
 PrepareSeparatorButtons: function () {
  if(!(this.hasSeparator && this.helper.buttonsExists))
   return;
  var sizeProperty = this.isVertical ? "offsetWidth" : "offsetHeight";
  if(this.helper.buttonsTableExists) {
   this.collapseBackwardButtonSize = this.helper.GetButtonUpdateElement(this.helper.GetCollapseBackwardButton())[sizeProperty];
   this.collapseForwardButtonSize = this.helper.GetButtonUpdateElement(this.helper.GetCollapseForwardButton())[sizeProperty];
   this.buttonsTableDiffSize = this.helper.GetCollapseButtonsTable()[sizeProperty] - this.collapseBackwardButtonSize - this.collapseForwardButtonSize;
   if(this.helper.separatorImageExists) {
    this.collapseButtonsSeparatorSize = this.helper.GetButtonUpdateElement(this.helper.GetCollapseButtonsSeparator())[sizeProperty];
    this.buttonsTableDiffSize -= this.collapseButtonsSeparatorSize;
   }
  }
  else
   this.collapseButtonsSeparatorSize = this.helper.GetCollapseButtonsSeparatorImage()[sizeProperty];
 },
 InitializePreventDragging: function () {
  if(!this.dragPrevented && this.helper.separatorImageExists) {
   ASPx.Evt.PreventElementDrag(this.helper.GetCollapseButtonsSeparatorImage());
   this.dragPrevented = true;
  }
 },
 ApplyScrollPosition: function () {
  if(this.panes.length == 0) {
   this.SetScrollTop(this.scrollTop);
   this.SetScrollLeft(this.scrollLeft);
  }
 },
 ForEach: function (funcName, skippSelf) {
  if(!skippSelf)
   this[funcName]();
  for(var i = 0; i < this.panes.length; i++)
   this.panes[i].ForEach(funcName);
 },
 SetContentVisible: function (visible) {
  ASPx.SetElementDisplay(this.helper.GetContentContainerElement(), visible);
 },
 AdjustControls: function () {
  if(this.panes.length == 0 && !this.collapsed && !this.isContentUrl)
   ASPx.GetControlCollection().AdjustControls(this.helper.GetContentContainerElement(), true);
 },
 UpdatePanes: function (forceAutoSizeUpdate) {
  this.ForEach("UpdateVisualElements", true);
  this.ForEach("UpdateChildrenSize");
  this.splitter.UpdateAutoSizePanes(forceAutoSizeUpdate);
 },
 UpdateVisualElements: function () {
  this.UpdateButtonsVisibility();
  this.UpdateSeparatorStyle();
  this.UpdatePaneStyle();
 },
 IsBackwardButtonVisible: function () {
  return ASPx.CacheHelper.GetCachedValue(this, "isBackwardButtonVisible", function () {
   if(!this.helper.buttonsTableExists)
    return false;
   if(this.collapsed && (this.maximizedPane == this.prevPane))
    return true;
   if(this.nextPane && this.collapsed && this.nextPane.collapsed)
    return true;
   if(this.prevPane.collapsed)
    return false;
   return this.showCollapseBackwardButton;
  }, this.helper);
 },
 IsForwardButtonVisible: function () {
  return ASPx.CacheHelper.GetCachedValue(this, "isForwardButtonVisible", function () {
   if(!this.helper.buttonsTableExists)
    return false;
   if(this.prevPane.collapsed && (this.prevPane.maximizedPane == this))
    return true;
   if(this.prevPane.collapsed && !this.collapsed)
    return true;
   if(this.collapsed)
    return false;
   return this.showCollapseForwardButton;
  }, this.helper);
 },
 DropCachedButtonsVisible: function () {
  ASPx.CacheHelper.DropCachedValue(this.helper, "isBackwardButtonVisible");
  ASPx.CacheHelper.DropCachedValue(this.helper, "isForwardButtonVisible");
 },
 UpdateSeparatorStyle: function () {
  var separator = this.helper.GetSeparatorElement();
  if(!separator) return;
  var prevPane = this.prevPane,
   isCollapsed = this.collapsed || prevPane && prevPane.collapsed,
   resizingEnabled = SplitterHelper.IsAllowResize(this, prevPane);
  if(this.splitter.IsStateControllerEnabled())
   ASPx.GetStateController().SetMouseStateItemsEnabled(this.helper.GetSeparatorElementId(), null, !isCollapsed && resizingEnabled);
  this.UpdateStyle(separator, isCollapsed);
 },
 UpdatePaneStyle: function () {
  this.UpdateStyle(this.helper.GetPaneElement(),
   this.collapsed && !this.NeedResetSplitterSizeOnCollapsing(this.maximizedPane) && !this.NeedKeepOffsetSizeOnCollapsing()
  );
 },
 UpdateStyle: function (element, isSelect) {
  if(!this.splitter.IsStateControllerEnabled()) return;
  if(isSelect)
   ASPx.GetStateController().SelectElementBySrcElement(element);
  else
   ASPx.GetStateController().DeselectElementBySrcElement(element);
 },
 UpdateButtonsVisibility: function () {
  if(!(this.hasSeparator && this.helper.buttonsExists))
   return;
  var separatorSize = this.GetOffsetSize(!this.isVertical) - this.separatorSizeDiff;
  if(this.helper.buttonsTableExists) {
   var buttonsSize = this.buttonsTableDiffSize;
   if(this.IsBackwardButtonVisible())
    buttonsSize += this.collapseBackwardButtonSize;
   if(this.IsForwardButtonVisible())
    buttonsSize += this.collapseForwardButtonSize;
   var buttonsVisible = (buttonsSize <= separatorSize);
   var backwardButtonVisible = buttonsVisible && this.IsBackwardButtonVisible();
   var forwardButtonVisible = buttonsVisible && this.IsForwardButtonVisible();
   ASPx.SetElementDisplay(this.helper.GetButtonUpdateElement(this.helper.GetCollapseBackwardButton()), backwardButtonVisible);
   ASPx.SetElementDisplay(this.helper.GetButtonUpdateElement(this.helper.GetCollapseForwardButton()), forwardButtonVisible);
   if(this.helper.separatorImageExists) {
    if(!buttonsVisible)
     buttonsSize = this.buttonsTableDiffSize;
    buttonsSize += this.collapseButtonsSeparatorSize;
    var separatorImageVisible = this.splitter.showSeparatorImage && (backwardButtonVisible === forwardButtonVisible) && (buttonsSize <= separatorSize);
    ASPx.SetElementDisplay(this.helper.GetButtonUpdateElement(this.helper.GetCollapseButtonsSeparator()), separatorImageVisible);
   }
  }
  else {
   var separatorImageVisible = this.splitter.showSeparatorImage && (this.collapseButtonsSeparatorSize <= separatorSize);
   ASPx.SetElementDisplay(this.helper.GetCollapseButtonsSeparatorImage(), separatorImageVisible);
  }
 },
 GetSeparatorSize: function () {
  return ASPx.CacheHelper.GetCachedValue(this, "SeparatorSize", function () {
   var separator = this.helper.GetSeparatorElement();
   return separator ? (this.isVertical ? separator.offsetHeight : separator.offsetWidth) : 0;
  }, this.helper);
 },
 GetTotalSeparatorsSize: function (isVertical) {
  if(!ASPx.IsExists(isVertical) || (isVertical == this.isVertical))
   return 0;
  var cacheKey = (isVertical ? "v" : "h") + "TotalSeparatorsSize";
  return ASPx.CacheHelper.GetCachedValue(this, cacheKey, function () {
   var result = 0;
   for(var i = 0; i < this.panes.length; i++)
    result += this.panes[i].GetSeparatorSize();
   return result;
  }, this.helper);
 },
 GetMinSize: function (isVertical) {
  if(!ASPx.IsExists(isVertical))
   isVertical = this.isVertical;
  var cacheKey = (isVertical ? "v" : "h") + "ItemMinSize";
  return ASPx.CacheHelper.GetCachedValue(this, cacheKey, function () {
   var result = 0;
   for(var i = 0; i < this.panes.length; i++)
    if(isVertical != this.isVertical)
     result += this.panes[i].GetMinSize(isVertical);
    else
     result = Math.max(result, this.panes[i].GetMinSize(isVertical));
   result += this.GetTotalSeparatorsSize(isVertical);
   var minSize = (isVertical == this.isVertical) ? this.minSize : this.splitter.defaultMinSize;
   result = Math.max(result, Math.max(minSize, this.GetSizeDiff(isVertical)));
   return result;
  }, this.helper);
 },
 DropCachedSizes: function () {
  ASPx.CacheHelper.DropCachedValue(this.helper, "SeparatorSize");
  ASPx.CacheHelper.DropCachedValue(this.helper, "vTotalSeparatorsSize");
  ASPx.CacheHelper.DropCachedValue(this.helper, "hTotalSeparatorsSize");
  ASPx.CacheHelper.DropCachedValue(this.helper, "ItemMinSize");
 },
 IsMaxSizeSpecified: function () {
  return this.maxSize != Number.MAX_VALUE;
 },
 GetMaxSize: function () {
  return Math.max(this.maxSize, this.GetSizeDiff(this.isVertical));
 },
 PrepareUpdateInfo: function () {
  var updateInfo = {};
  var prepareUpdateInfoPart = function () {
   return {
    panes: [],
    sum: 0,
    sumMin: 0,
    sumMax: 0,
    addPane: function () {
     this.panes.push(pane);
     if(pane.collapsed) {
      var sizeDiff = pane.GetSizeDiff(pane.isVertical);
      this.sum += sizeDiff;
      this.sumMin += sizeDiff;
     }
     else {
      this.sum += pane.size;
      this.sumMin += pane.GetMinSize();
     }
     this.sumMax += pane.GetMaxSize();
    },
    IsIgnoreMaxSize: function () {
     return this.sumMax < this.sum;
    }
   };
  };
  updateInfo.px = prepareUpdateInfoPart();
  updateInfo.prc = prepareUpdateInfoPart();
  updateInfo.collapsed = prepareUpdateInfoPart();
  updateInfo.autoSize = prepareUpdateInfoPart();
  updateInfo.onlyPxPanes = true; 
  updateInfo.hasPxPanesShown = false;
  updateInfo.hasPrcPanesShown = false;
  for(var i = 0; i < this.panes.length; i++) {
   var pane = this.panes[i];
   if(pane.collapsed)
    updateInfo.collapsed.addPane(pane);
   else if(pane.IsAutoSize(this.isVertical) && pane.GetOffsetSize()) {
    updateInfo.autoSize.addPane(pane);
   }
   else if(pane.isSizePx) {
    updateInfo.px.addPane(pane);
    updateInfo.hasPxPanesShown = true;
   }
   else {
    updateInfo.prc.addPane(pane);
    updateInfo.hasPrcPanesShown = true;
   }
   if(!pane.isSizePx)
    updateInfo.onlyPxPanes = false;
  }
  updateInfo.px.isIgnoreMaxSize = (!updateInfo.hasPrcPanesShown && (updateInfo.px.sumMax < updateInfo.px.sum));
  updateInfo.prc.isIgnoreMaxSize = (updateInfo.prc.sumMax < updateInfo.prc.sum);
  return updateInfo;
 },
 SetChildrenSecondSize: function () {
  var orientation = this.isVertical;
  var size = this.GetClientSize(orientation);
  if(this.isRootPane)
   for(var pane = this.panes[0]; pane; pane = pane.nextPane) {
    if(pane.IsAutoSize(!this.isVertical))
     size = Math.max(size, pane.GetOffsetSize(this.isVertical));
   }
  for(var i = 0; i < this.panes.length; i++)
   this.panes[i].SetOffsetSize(size, orientation);
 },
 GetChildrenTotalSize: function () {
  return this.GetClientSize(!this.isVertical) - this.GetTotalSeparatorsSize(!this.isVertical);
 },
 UpdateChildrenSize: function () {
  if(this.collapsed || (this.panes.length == 0))
   return;
  var updateInfo = this.PrepareUpdateInfo();
  var childrenTotalSize = this.GetChildrenTotalSize();
  var asTotalSize = 0;
  for(var i = 0; i < updateInfo.autoSize.panes.length; i++) {
   var pane = updateInfo.autoSize.panes[i];
   pane.size = pane.GetOffsetSize();
   asTotalSize += pane.size;
  }
  if(!updateInfo.hasPxPanesShown && !updateInfo.hasPrcPanesShown) {
   var asMaxSize = childrenTotalSize - (updateInfo.px.sumMin + updateInfo.prc.sumMin + updateInfo.collapsed.sumMin);
   asTotalSize = this.NormalizePanesSizes(updateInfo.autoSize.panes, asTotalSize, asMaxSize);
  }
  else {
   var pxMaxSize = childrenTotalSize - (updateInfo.prc.sumMin + updateInfo.collapsed.sumMin) - asTotalSize,
    isOutOfParentSize = !!(pxMaxSize < 0 && updateInfo.autoSize.panes.length);
   if(isOutOfParentSize)
    pxMaxSize = updateInfo.px.sum;
   var pxTotalSize = 0;
   if(updateInfo.hasPxPanesShown) {
    var c = !updateInfo.hasPrcPanesShown && !isOutOfParentSize && !updateInfo.autoSize.panes.length
     ? (pxMaxSize / (updateInfo.px.sum + updateInfo.autoSize.sum))
     : 1;
    for(var i = 0; i < updateInfo.px.panes.length; i++) {
     var pane = updateInfo.px.panes[i];
     var newSize = pxMaxSize > 0
      ? Math.max(Math.round(pane.size * c), pane.GetMinSize())
      : pane.GetMinSize();
     if(!updateInfo.px.isIgnoreMaxSize)
      newSize = Math.min(newSize, pane.GetMaxSize());
     pane.SetOffsetSize(newSize);
     pxTotalSize += newSize;
    }
    if(pxMaxSize > 0 && (!updateInfo.hasPrcPanesShown || (pxTotalSize > pxMaxSize))) {
     pxTotalSize = this.NormalizePanesSizes(updateInfo.autoSize.panes, pxTotalSize, pxMaxSize);
     pxTotalSize = this.NormalizePanesSizes(updateInfo.px.panes, pxTotalSize, pxMaxSize);
    }
    if(updateInfo.onlyPxPanes && !(this.IsAutoSize(this.isVertical) && !updateInfo.autoSize.panes.length)) {
     for(var i = 0; i < updateInfo.px.panes.length; i++) {
      var pane = updateInfo.px.panes[i];
      pane.size = pane.GetOffsetSize();
     }
    }
   }
   var prcMaxSize = pxMaxSize - pxTotalSize + updateInfo.prc.sumMin;
   var prcTotalSize = 0;
   if((prcMaxSize > 0) && updateInfo.hasPrcPanesShown) {
    var c = 1 / updateInfo.prc.sum;
    for(var i = 0; i < updateInfo.prc.panes.length; i++) {
     var pane = updateInfo.prc.panes[i];
     var newSize = Math.max(Math.round(pane.size * c * (childrenTotalSize - pxTotalSize - asTotalSize)), pane.GetMinSize());
     if(!updateInfo.prc.isIgnoreMaxSize)
      newSize = Math.min(newSize, pane.GetMaxSize());
     pane.SetOffsetSize(newSize);
     prcTotalSize += newSize;
    }
    if(prcTotalSize != prcMaxSize)
     prcTotalSize = this.NormalizePanesSizes(updateInfo.prc.panes, prcTotalSize, prcMaxSize);
   }
  }
  for(var i = 0; i < updateInfo.collapsed.panes.length; i++) {
   var pane = updateInfo.collapsed.panes[i],
    collapsedSize = pane.GetSizeDiff(pane.isVertical);
   pane.SetOffsetSize(collapsedSize);
  }
  if(ASPx.Browser.WebKitFamily && updateInfo.collapsed.panes.length && this.IsAutoSize(this.IsVertical))
   this.splitter.CreateWebkitSpecialElement();
  this.SetChildrenSecondSize();
  for(var i = 0; i < this.panes.length; i++) {
   var pane = this.panes[i];
   if(pane.collapsed)
    pane.SetContentVisible(false);
   else
    pane.SetContentVisible(true);
   if(pane.ApplyElementSize())
    pane.RaiseResizedEvent();
  }
  this.ForEach("UpdateButtonsVisibility", true);
 },
 GetPossibleUp: function () {
  if(this.inResizing)
   return -1;
  return this.GetMaxSize() - this.GetOffsetSize();
 },
 GetPossibleDown: function () {
  if(this.IsAutoSize(!this.isVertical) && !(this.panes.length && !this.helper.HasVisibleAutoSizeChildren(!this.isVertical)))
   return -1;
  if(this.inResizing)
   return -1;
  return this.GetOffsetSize() - this.GetMinSize();
 },
 NormalizePanesSizes: function (panes, size, maxSize) {
  var insufficientSize = Math.ceil(maxSize - size);
  var changeStep = (insufficientSize > 0) ? 1 : -1;
  var possibleChangeFunction = (insufficientSize > 0) ? "GetPossibleUp" : "GetPossibleDown";
  var changed = true;
  while(insufficientSize != 0 && changed) {
   changed = false;
   for(var i = 0; i < panes.length; i++) {
    var pane = panes[i];
    if(pane[possibleChangeFunction]() > 0) {
     pane.SetOffsetSize(pane.GetOffsetSize() + changeStep);
     insufficientSize -= changeStep;
     changed = true;
     if(insufficientSize == 0)
      break;
    }
   }
  }
  return maxSize - insufficientSize;
 },
 GetOffsetSize: function (isVertical) {
  if(!ASPx.IsExists(isVertical))
   isVertical = this.isVertical;
  return isVertical ? this.offsetHeight : this.offsetWidth;
 },
 GetClientSize: function (isVertical) {
  return isVertical ? this.GetClientHeightInternal(true) : this.GetClientWidthInternal(true);
 },
 SetOffsetSize: function (value, isVertical) {
  if(!ASPx.IsExists(isVertical))
   isVertical = this.isVertical;
  if(isVertical)
   this.offsetHeight = value;
  else
   this.offsetWidth = value;
 },
 GetSizeDiff: function (isVertical) {
  return isVertical ? this.GetHeightDiff(true) : this.GetWidthDiff(true);
 },
 GetWidthDiff: function (isContainer) {
  if(this.collapsed)
   return this.collapsedWidthDiff;
  return this.widthDiff + (isContainer ? this.contentContainerWidthDiff : 0);
 },
 GetHeightDiff: function (isContainer) {
  if(this.collapsed)
   return this.collapsedHeightDiff;
  return this.heightDiff + (isContainer ? this.contentContainerHeightDiff : 0);
 },
 GetClientWidthInternal: function (isContainer) {
  if(ASPx.Browser.Firefox && this.autoWidth)
   return this.offsetWidth;
  return this.offsetWidth - this.GetWidthDiff(isContainer);
 },
 GetClientHeightInternal: function (isContainer) {
  if(ASPx.Browser.Firefox && this.autoHeight)
   return this.offsetHeight - (isContainer ? 0 : ASPx.GetVerticalBordersWidth(this.GetElement()));
  return this.offsetHeight - this.GetHeightDiff(isContainer);
 },
 ApplyElementSize: function () {
  if(this.IsSizeChanged()) {
   this.ApplyElementSizeCore();
   var contentContainerElement = this.helper.GetContentContainerElement();
   if(ASPx.Browser.Chrome && ASPx.Browser.MajorVersion >= 3
     || ASPx.Browser.Safari && ASPx.Browser.MajorVersion >= 5) {
    var marginRight = ASPx.PxToInt(contentContainerElement.style.marginRight);
    marginRight -= ASPx.PxToInt(ASPx.GetCurrentStyle(contentContainerElement).marginRight);
    contentContainerElement.style.marginRight = marginRight + "px";
   }
   if(ASPx.Browser.WebKitFamily)
    this.splitter.CreateWebkitSpecialElement(); 
   return true;
  }
  return false;
 },
 ApplyElementSizeCore: function () {
  var paneWidth = this.GetClientWidthInternal(false);
  var paneHeight = this.GetClientHeightInternal(false);
  var contentContainerWidth = this.GetClientWidthInternal(true);
  var contentContainerHeight = this.GetClientHeightInternal(true);
  if(contentContainerWidth < 0) {
   paneWidth -= contentContainerWidth;
   contentContainerWidth = 0;
  }
  if(contentContainerHeight < 0) {
   paneHeight -= contentContainerHeight;
   contentContainerHeight = 0;
  }
  var paneElement = this.helper.GetPaneElement(),
   contentContainerElement = this.helper.GetContentContainerElement();
  if(!isNaN(paneWidth) && !(paneWidth === 0 && !this.collapsed))
   paneElement.style.width = paneWidth + "px";
  if(!isNaN(paneHeight) && !(paneHeight === 0 && !this.collapsed))
   paneElement.style.height = paneHeight + "px";
  if(!this.autoWidth && !isNaN(contentContainerWidth))
   contentContainerElement.style.width = contentContainerWidth + "px";
  if(!this.autoHeight && !isNaN(contentContainerHeight))
   contentContainerElement.style.height = contentContainerHeight + "px";
 },
 IsSizeChanged: function () {
  if(!ASPx.IsExists(this.lastWidth) || !ASPx.IsExists(this.lastHeight) ||
   (this.offsetWidth != this.lastWidth) || (this.offsetHeight != this.lastHeight)) {
   this.lastWidth = this.offsetWidth;
   this.lastHeight = this.offsetHeight;
   return true;
  }
  return false;
 },
 GetSplitter: function () {
  return this.splitter;
 },
 GetParentPane: function () {
  return this.parent;
 },
 GetPrevPane: function () {
  return this.prevPane;
 },
 GetNextPane: function () {
  return this.nextPane;
 },
 IsFirstPane: function () {
  return (this.prevPane == null);
 },
 IsLastPane: function () {
  return (this.nextPane == null);
 },
 IsVertical: function () {
  return this.isVertical;
 },
 GetPaneCount: function () {
  return this.panes.length;
 },
 GetPane: function (index) {
  return (0 <= index && index < this.panes.length) ? this.panes[index] : null;
 },
 GetPaneByName: function (name) {
  for(var i = 0; i < this.panes.length; i++)
   if(this.panes[i].name == name) return this.panes[i];
  for(var i = 0; i < this.panes.length; i++) {
   var pane = this.panes[i].GetPaneByName(name);
   if(pane != null) return pane;
  }
  return null;
 },
 GetClientWidth: function () {
  var clientWidth = this.GetClientWidthInternal(true);
  if(!this.IsContentUrlPane()) {
   var contentContainer = this.helper.GetContentContainerElement();
   if((contentContainer.style.overflow == "auto" && contentContainer.scrollHeight > contentContainer.clientHeight)
     || contentContainer.style.overflow == "scroll"
     || contentContainer.style.overflowY == "scroll") {
    clientWidth = clientWidth - ASPx.GetVerticalScrollBarWidth();
   }
  }
  return clientWidth;
 },
 GetClientHeight: function () {
  return this.GetClientHeightInternal(true);
 },
 Collapse: function (maximizedPane) {
  if(!this.splitter.IsPrepared())
   return false;
  if(this.collapsed)
   return false;
  if(!ASPx.IsExists(maximizedPane) || !maximizedPane.isASPxClientSplitterPane)
   return false;
  return this.CollapseExpandCore(true, maximizedPane, "PaneCollapsed");
 },
 CollapseForward: function () {
  return this.Collapse(this.prevPane);
 },
 CollapseBackward: function () {
  return this.Collapse(this.nextPane);
 },
 Expand: function () {
  if(!this.splitter.IsPrepared())
   return false;
  if(!this.collapsed)
   return false;
  return this.CollapseExpandCore(false, null, "PaneExpanded");
 },
 CollapseExpandCore: function (collapsed, maximizedPane, eventName) {
  this.collapsed = collapsed;
  this.maximizedPane = maximizedPane;
  this.DropCachedButtonsVisible();
  if(this.nextPane != null)
   this.nextPane.DropCachedButtonsVisible();
  this.GetParentPane().UpdatePanes(!collapsed);
  this.GetParentPane().ForEach("AdjustControls");
  this.splitter.RaiseEvent(eventName, this);
  this.splitter.UpdateCookie();
  return true;
 },
 IsCollapsed: function () {
  return this.collapsed;
 },
 NeedResetSplitterSizeOnCollapsing: function (maximizedPane) {
  return maximizedPane.IsMaxSizeSpecified() && maximizedPane.GetParentPane().isRootPane;
 },
 NeedKeepOffsetSizeOnCollapsing: function () {
  return this.maximizedPane.IsMaxSizeSpecified() && !this.GetParentPane().isRootPane && this.GetParentPane().GetPaneCount() == 2;
 },
 IsContentUrlPane: function () {
  return this.isContentUrl;
 },
 GetContentUrl: function () {
  return this.isContentUrl
   ? this.iframeObj.GetContentUrl()
   : "";
 },
 SetContentUrl: function (url, preventBrowserCaching) {
  if(!this.isContentUrl)
   return;
  this.iframeObj.SetContentUrl(url, preventBrowserCaching);
 },
 RefreshContentUrl: function () {
  if(!this.isContentUrl)
   return;
  this.iframeObj.RefreshContentUrl();
 },
 GetContentIFrame: function () {
  return this.isContentUrl
   ? this.helper.GetContentContainerElement()
   : null;
 },
 CreateContentUrlIFrame: function () {
  if(!this.isContentUrl)
   return;
  var contentContainer = this.helper.GetContentContainerElement();
  contentContainer.parentNode.removeChild(contentContainer);
  this.iframeObj = new ASPx.IFrameHelper({
   id: contentContainer.id,
   name: this.iframe.name,
   title: this.iframe.title,
   scrolling: this.iframe.scrolling,
   src: this.iframe.src,
   onCreate: function (containerElement, element) {
    element.className = "dxsplIF";
    this.helper.GetPaneElement().appendChild(containerElement);
    this.helper.DropContentContainerElementFromCache();
    this.ApplyElementSizeCore();
    if(this.autoHeight && this.isVertical)
     containerElement.style.height = "100%";
   }.aspxBind(this),
   onLoad: function () {
    this.splitter.RaiseEvent("PaneContentUrlLoaded", this);
   }.aspxBind(this)
  });
 },
 SetAllowResize: function (allowResize) {
  this.allowResize = allowResize;
  this.UpdateSeparatorStyle();
  if(!this.IsLastPane())
   this.nextPane.UpdateSeparatorStyle();
 },
 RaiseResizedEvent: function () {
  this.splitter.RaiseEvent("PaneResized", this);
 },
 GetElement: function () {
  return this.helper.GetPaneElement();
 },
 SetSize: function (size) {
  if(!this.splitter.IsPrepared())
   return;
  if(this.SetSizeCore(size)) {
   this.parent.ForEach("UpdateChildrenSize");
   this.splitter.UpdateAutoSizePanes();
   this.parent.ForEach("AdjustControls");
   this.splitter.UpdateCookie();
  }
 },
 GetSize: function () {
  return this.size + this.sizeType;
 },
 SetSizeCore: function (size) {
  if(!ASPx.IsExists(size))
   return false;
  if(this.IsAutoSize(!this.isVertical))
   return false;
  if(typeof (size) == "string") {
   var parsedSize = parseInt(size);
   if(isNaN(parsedSize))
    return false;
   this.size = parsedSize;
   this.sizeType = ASPx.IsPercentageSize(size) ? "%" : "px";
  }
  else if(typeof (size) == "number") {
   this.size = size;
   this.sizeType = "px";
  }
  else
   return false;
  this.isSizePx = this.sizeType == "px";
  return true;
 },
 GetScrollTop: function () {
  return this.scrollTop;
 },
 SetScrollTop: function (value) {
  this.helper.GetContentContainerElement().scrollTop = value;
 },
 GetScrollLeft: function () {
  return this.scrollLeft;
 },
 SetScrollLeft: function (value) {
  this.helper.GetContentContainerElement().scrollLeft = value;
 },
 OnDispose: function() {
  if(this.helper != null)
   this.helper.OnDispose();
  this.splitter = null;
  this.helper = null;
 }
});
ASPxClientSplitter.Instances = {
 items: {},
 Add: function(instance) {
  var name = instance.name;
  if(ASPx.IsExists(this.items[name])) {
   this.items[name].OnDispose();
   this.Remove(name);
  }
  this.items[name] = instance;
  if(instance.hasAutoSizePane)
   ASPxClientSplitter.AutoSizePanesUpdater.Start();
 },
 Get: function (name) {
  var instance = this.items[name];
  if(instance) {
   if(instance.GetMainElement())
    return instance;
   this.Remove(name);
  }
  return null;
 },
 Each: function (cb) {
  var hasInstances = false;
  for(var name in this.items) {
   if(this.items.hasOwnProperty(name)) {
    var instance = this.Get(name);
    if(instance) {
     hasInstances = true;
     cb.call(instance);
    }
   }
  }
  return hasInstances;
 },
 Remove: function(name) {
  if(ASPx.IsExists(this.items[name])) {
   try {
    delete this.items[name];
   } catch(e) { }
  }
 }
};
ASPxClientSplitter.AutoSizePanesUpdater = {
 timeoutId: -1,
 Start: function () {
  var updater = ASPxClientSplitter.AutoSizePanesUpdater;
  if(updater.timeoutId > -1)
   return;
  updater.timeoutId = window.setTimeout(updater.OnTimeout, 300);
  updater.devicePixelRatio = window.devicePixelRatio;
 },
 Stop: function () {
  var updater = ASPxClientSplitter.AutoSizePanesUpdater;
  updater.timeoutId = ASPx.Timer.ClearTimer(updater.timeoutId);
 },
 OnTimeout: function () {
  var updater = ASPxClientSplitter.AutoSizePanesUpdater;
  updater.Stop();
  if(ASPxClientSplitter.Instances.Each(function() {
   if(!this.isInitialized)
    return;
   this.UpdateAutoSizePanes();
   if(window.devicePixelRatio !== updater.devicePixelRatio) 
    this.rootPane.ForEach("PrepareInternal", true);
   if(!this.isInLiveResizing && this.hasAutoSizePane && this.IsDocumentWidthChanged() || window.devicePixelRatio !== updater.devicePixelRatio)
    this.UpdateControlSizes();
  }));
  updater.Start();
 }
};
ASPxClientSplitter.timerInterval = 0;
ASPxClientSplitter.GetRegEx = function (idPostfix) {
 if(!this.regExs)
  this.regExs = {};
 if(!this.regExs[idPostfix])
  this.regExs[idPostfix] = "_\\d+(" + ASPx.ItemIndexSeparator + "\\d+)*_" + idPostfix + "$";
 return this.regExs[idPostfix];
};
ASPxClientSplitter.SaveCurrentPos = function (evt) {
 evt = ASPx.Evt.GetEvent(evt);
 ASPxClientSplitter.CurrentXPos = ASPx.Evt.GetEventX(evt);
 ASPxClientSplitter.CurrentYPos = ASPx.Evt.GetEventY(evt);
};
ASPxClientSplitter.FindParentCell = function (element) {
 if(element.tagName != "TD")
  element = ASPx.GetParentByTagName(element, "TD");
 return element;
};
ASPxClientSplitter.FindSplitterInfo = function (evt, regex, suffixLength) {
 var element = ASPxClientSplitter.FindParentCell(ASPx.Evt.GetEventSource(evt));
 if(element) {
  var matchResult = element.id.match(regex);
  if(matchResult) {
   var name = element.id.substring(0, matchResult.index);
   var splitter = ASPxClientSplitter.Instances.Get(name);
   if(splitter != null) {
    var panePath = element.id.substring(matchResult.index + 1, element.id.length - suffixLength);
    return { "splitter": splitter, "panePath": panePath };
   }
  }
 }
 return null;
};
ASPxClientSplitter.OnMouseClick = function (evt) {
 var info = ASPxClientSplitter.FindSplitterInfo(evt, ASPxClientSplitter.GetRegEx("S_CF"), 5);
 if(info) {
  if(info.splitter.enabled)
   info.splitter.OnCollapseButtonClick(info.panePath, true);
 }
 else {
  info = ASPxClientSplitter.FindSplitterInfo(evt, ASPxClientSplitter.GetRegEx("S_CB"), 5);
  if(info && info.splitter.enabled)
   info.splitter.OnCollapseButtonClick(info.panePath, false);
 }
};
ASPxClientSplitter.OnMouseDown = function (evt) {
 var info = ASPxClientSplitter.FindSplitterInfo(evt, ASPxClientSplitter.GetRegEx("S"), 2);
 if(!info)
  info = ASPxClientSplitter.FindSplitterInfo(evt, ASPxClientSplitter.GetRegEx("S_CS"), 5);
 if(info && info.splitter) {
  ASPxClientSplitter.current = info.splitter;
  ASPxClientSplitter.SaveCurrentPos(evt);
  ASPx.Selection.SetElementSelectionEnabled(ASPxClientSplitter.current.GetMainElement(), false);
  ASPxClientSplitter.isInMove = info.splitter.OnSeparatorMouseDown(info.panePath);
  ASPx.Evt.PreventEvent(evt);
 }
};
ASPxClientSplitter.OnMouseUp = function () {
 if(ASPxClientSplitter.isInMove) {
  ASPxClientSplitter.isInMove = false;
  ASPx.Selection.SetElementSelectionEnabled(ASPxClientSplitter.current.GetMainElement(), true);
  ASPxClientSplitter.current.OnSeparatorMouseUp();
 }
};
ASPxClientSplitter.mouseMoveTimeoutId = -1;
ASPxClientSplitter.SuspendedMouseMove = function () {
 if(ASPxClientSplitter.isInMove)
  ASPxClientSplitter.current.OnMouseMove();
 ASPxClientSplitter.mouseMoveTimeoutId = ASPx.Timer.ClearTimer(ASPxClientSplitter.mouseMoveTimeoutId);
};
ASPxClientSplitter.OnMouseMove = function (evt) {
 if(ASPx.Browser.WebKitTouchUI && ASPx.TouchUIHelper.isGesture)
  return;
 if(!ASPxClientSplitter.isInMove)
  return;
 ASPxClientSplitter.SaveCurrentPos(evt);
 if(ASPxClientSplitter.mouseMoveTimeoutId == -1)
  ASPxClientSplitter.mouseMoveTimeoutId = window.setTimeout(ASPxClientSplitter.SuspendedMouseMove, ASPxClientSplitter.timerInterval);
 if(ASPx.Browser.WebKitTouchUI)
  ASPx.Evt.PreventEvent(evt);
};
ASPx.Evt.AttachEventToDocument("click", ASPxClientSplitter.OnMouseClick);
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, ASPxClientSplitter.OnMouseDown);
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, ASPxClientSplitter.OnMouseUp);
ASPx.Evt.AttachEventToElement(window, ASPx.TouchUIHelper.touchMouseMoveEventName, ASPxClientSplitter.OnMouseMove, false, !ASPx.Browser.WebKitTouchUI);
var ASPxClientSplitterPaneEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (pane) {
  this.constructor.prototype.constructor.call(this, pane);
  this.pane = pane;
 }
});
var ASPxClientSplitterPaneCancelEventArgs = ASPx.CreateClass(ASPxClientSplitterPaneEventArgs, {
 constructor: function (pane) {
  this.constructor.prototype.constructor.call(this, pane);
  this.cancel = false;
 }
});
window.ASPxClientSplitter = ASPxClientSplitter;
window.ASPxClientSplitterPane = ASPxClientSplitterPane;
window.ASPxClientSplitterPaneEventArgs = ASPxClientSplitterPaneEventArgs;
window.ASPxClientSplitterPaneCancelEventArgs = ASPxClientSplitterPaneCancelEventArgs;
})();

(function() {
 var queryParamName = "DXMVC";
 var MVCxClientUploadControl = ASPx.CreateClass(ASPxClientUploadControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.callbackUrl = "";
  },
  InlineInitialize: function() {
   var element = this.GetMainElement();
   if(element)
    element.appendChild(ASPx.CreateHiddenField(this.name + "_DXMVCUploadControl"));
   if(this.fileNameHandling)
    this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, {}, {}); };
   ASPxClientUploadControl.prototype.InlineInitialize.call(this);
  },
  CreateCallbackByInfo: function(arg, command, callbackInfo) {
   this.CreateCallbackInternal(arg, command, true, callbackInfo);
  },
  initializeOptions: function() {
   ASPxClientUploadControl.prototype.initializeOptions.call(this);
   this.options.callbackUrl = this.callbackUrl;
  },
  createUploadManager: function(stateHelper) {
   return new MVCxLegacyUploadManager(this.options, stateHelper);
  }
 });
 var MVCxLegacyUploadManager = ASPx.CreateClass(ASPxClientUploadControl.UploadManagerClass, {
  GetUploadFormAction: function(form) {
   if(this.options.callbackUrl != "")
    form.action = this.options.callbackUrl;
   var action = ASPxClientUploadControl.UploadManagerClass.prototype.GetUploadFormAction.call(this, form);
   return this.AddQueryParamToUrl(action, queryParamName, "true");
  }
 });
 MVCxClientUploadControl.Cast = ASPxClientControl.Cast;
 window.MVCxClientUploadControl = MVCxClientUploadControl;
})();

(function() {
var DateFormatter = ASPx.CreateClass(null, {
 constructor: function() {
  this.date = new Date(2000, 0, 1);
  this.mask = "";
  this.specifiers = {};     
  this.spPositions = [];    
  this.parserKeys = [];
  this.knownSpecifiers = ["d", "M", "y", "H", "h", "m", "s", "f", "F", "g", "t"];
  this.savedYear = -1;
  this.isYearParsed = false;
  this.parsedMonth = -1;
  this.replacers = {
   "d": this.ReplaceDay,
   "M": this.ReplaceMonth,
   "y": this.ReplaceYear,
   "H": this.ReplaceHours23,
   "h": this.ReplaceHours12,
   "m": this.ReplaceMinutes,
   "s": this.ReplaceSeconds,
   "F": this.ReplaceMsTrimmed,
   "f": this.ReplaceMs,
   "g": this.ReplaceEra,
   "t": this.ReplaceAmPm
  };
  this.parsers = {
   "d": this.ParseDay,
   "M": this.ParseMonth,
   "y": this.ParseYear,
   "H": this.ParseHours,
   "h": this.ParseHours,
   "m": this.ParseMinutes,
   "s": this.ParseSeconds,
   "F": this.ParseMs,
   "f": this.ParseMs,
   "g": this.ParseEra,
   "t": this.ParseAmPm
  };
 },
 Format: function(date) {
  this.date = date;
  var sp;
  var pos;
  var replacerKey;
  var result = this.mask;
  for(var i = 0; i < this.spPositions.length; i++) {
   pos = this.spPositions[i];
   sp = this.specifiers[pos];
   replacerKey = sp.substr(0, 1);
   if(this.replacers[replacerKey]) {
    result = result.substr(0, pos) + this.replacers[replacerKey].call(this, sp.length) + result.substr(pos + sp.length);
   }
  }
  return result;
 }, 
 Parse: function(str, rememberParserKeys, spPositionsParam, specifiersParam) {
  var spPositions = !!spPositionsParam ? spPositionsParam : this.spPositions;
  var specifiers = !!specifiersParam ? specifiersParam : this.specifiers;
  var now = new Date();  
  this.savedYear = now.getFullYear();
  this.isYearParsed = false;
  this.parsedMonth = -1;
  this.date = new Date(2000, 0, now.getDate());    
  this.strToParse = str;
  this.catchNumbers(str, specifiers);
  var parserKey;
  var sp;
  var pos;
  var parseResult;
  var error = false;
  this.hasAmPm = false;
  for(var i = 0; i < spPositions.length; i++) {
   pos = spPositions[i];
   sp = specifiers[pos];
   parserKey = sp.substr(0, 1);
   if(this.parsers[parserKey]) {
    if(rememberParserKeys)
     this.parserKeys.push(parserKey);
    parseResult = this.parsers[parserKey].call(this, sp.length);
    if(!parseResult) {
     error = true;
     break;
    }
   }
  }
  if(error)
   return false;
  if(this.hasAmPm) {
   if(!this.fixHours())
    return false;
  }
  if(!this.isYearParsed)
   this.date.setYear(this.savedYear);
  if(this.parsedMonth < 0)
   this.parsedMonth = now.getMonth();   
  this.ApplyMonth();
  return this.date;  
 },
 ParseAndMergeWithDate: function(str, sourceDate) {
  this.parserKeys = [];
  var date = this.Parse(str, true);
  if(date && sourceDate)
   date = new Date(
        this.HasYear() ? date.getFullYear() : sourceDate.getFullYear(),
        this.HasMonth() ? date.getMonth() : sourceDate.getMonth(),
        this.HasDay() ? date.getDate() : sourceDate.getDate(),
        this.HasHours() ? date.getHours() : sourceDate.getHours(),
        this.HasMinutes() ? date.getMinutes() : sourceDate.getMinutes(),
        this.HasSeconds() ? date.getSeconds() : sourceDate.getSeconds(),
        this.HasMilliseconds() ? date.getMilliseconds() : sourceDate.getMilliseconds()
        );
  this.parserKeys = [];
  return date;
 },
 HasYear: function() { return this.HasParserKey("y"); },
 HasMonth: function() { return this.HasParserKey("M"); },
 HasDay: function() { return this.HasParserKey("d"); },
 HasHours: function() { return this.HasParserKey("h") || this.HasParserKey("H"); },
 HasMinutes: function() { return this.HasParserKey("m"); },
 HasSeconds: function() { return this.HasParserKey("s"); },
 HasMilliseconds: function() { return this.HasParserKey("f") || this.HasParserKey("F"); },
 HasParserKey: function(key) { return ASPx.Data.ArrayIndexOf(this.parserKeys, key) !== -1; },
 ApplyMonth: function() {
  var trial;
  var day = this.date.getDate();
  while(true) {
   trial = new Date();
   trial.setTime(this.date.getTime());   
   trial.setMonth(this.parsedMonth);
   if(trial.getMonth() == this.parsedMonth)
    break;
   --day;
   this.date.setDate(day);
  }
  ASPx.DateUtils.FixTimezoneGap(this.date, trial);
  this.date = trial;
 },
 SetFormatString: function(mask) {
  var format = this.GetFormat(mask);
  this.specifiers = format.specifiers;
  this.spPositions = format.spPositions;
  this.mask = format.mask;
 },
 GetFormat: function(maskParam) {
  if(maskParam.length == 2 && maskParam.charAt(0) == "%")
   maskParam = maskParam.charAt(1);
  var stringContainsDateSeparator = maskParam && maskParam.indexOf(ASPx.CultureInfo.ds) !== -1;
  var subt = 0;
  var pos = 0;
  var startPos = 0;
  var ch;
  var prevCh = "";
  var skip = false;
  var backslash = false;
  var sp = "";
  var specifiers = {};
  var spPositions = [];
  var mask = "";
  while(true) {
   ch = maskParam.charAt(pos);
   if(ch == "") {
    if(sp.length > 0) {
     var specifier = this.GetSpecifier(startPos, sp, stringContainsDateSeparator, mask);
     spPositions.push(specifier.pos);
     specifiers[specifier.pos] = specifier.sp;
    }
    break;
   }
   if(ch == "\\" && !backslash) {
    backslash = true;
    subt++;
   } else {
    if(!backslash && (ch == "'" || ch == '"')) {
     skip = !skip;
     subt++;
    } else {     
     if(!skip) {
      if(ch == "/")
       ch = ASPx.CultureInfo.ds;
      else if(ch == ":")
       ch = ASPx.CultureInfo.ts;
      else if(this.IsKnownSpecifier(ch)) {
       if(prevCh.length == 0)
        prevCh = ch;
       if(ch == prevCh)
        sp += ch;
       else {
        if(sp.length > 0) {
         var specifier = this.GetSpecifier(startPos, sp, stringContainsDateSeparator, mask);
         spPositions.push(specifier.pos);
         specifiers[specifier.pos] = specifier.sp;
        }
        sp = ch;
        startPos = pos - subt;
       }
      }
     }     
     mask += ch;
    }      
    backslash = false;
   }            
   prevCh = ch;
   pos++;
  }
  spPositions.reverse();
  return { specifiers: specifiers, spPositions: spPositions, mask: mask };
 },
 GetSpecifier: function (pos, sp, stringContainsDateSeparator, mask) {
  if(ASPx.CultureInfo.ds.length > 1 && mask && !stringContainsDateSeparator) {
   var dateParts = mask.split(ASPx.CultureInfo.ds);
   if(dateParts) {
    if(dateParts.length > 0 && dateParts[dateParts.length - 1] == "")
     dateParts.pop();
    pos += (dateParts.length - 1) * (ASPx.CultureInfo.ds.length - 1);
   }
  }
  return { pos: pos, sp: sp };
 },
 ReplaceDay: function(length) {
  if(length < 3) {
   var value = this.date.getDate().toString();
   return length == 2 ? this.padLeft(value, 2) : value;  
  } else if(length == 3) {
   return ASPx.CultureInfo.abbrDayNames[this.date.getDay()];
  } else {
   return ASPx.CultureInfo.dayNames[this.date.getDay()];
  }
 }, 
 ReplaceMonth: function(length) {
  var value = 1 + this.date.getMonth();
  switch(length) {
   case 1:
    return value.toString();
   case 2:
    return this.padLeft(value.toString(), 2);
   case 3:
    return ASPx.CultureInfo.abbrMonthNames[value - 1];
   default:
    for(var i in this.specifiers) {
     if(this.specifiers.hasOwnProperty(i)) {
      var spec = this.specifiers[i];
      if(spec == "d" || spec == "dd")
       return ASPx.CultureInfo.genMonthNames[value - 1];
     }
    }
    return ASPx.CultureInfo.monthNames[value - 1];
  }
 },
 ReplaceYear: function(length) {
  var value = this.date.getFullYear();
  if(length <= 2)
   value = value % 100;
  return this.padLeft(value.toString(), length);
 },
 ReplaceHours23: function(length) {
  var value = this.date.getHours().toString();
  return length > 1 ? this.padLeft(value, 2) : value;
 },
 ReplaceHours12: function(length) {
  var value = this.date.getHours() % 12;
  if(value == 0)
   value = 12;
  value = value.toString();
  return length > 1 ? this.padLeft(value, 2) : value;
 },
 ReplaceMinutes: function(length) {
  var value = this.date.getMinutes().toString();
  return length > 1 ? this.padLeft(value, 2) : value;
 },
 ReplaceSeconds: function(length) {
  var value = this.date.getSeconds().toString();
  return length > 1 ? this.padLeft(value, 2) : value;
 },
 ReplaceMsTrimmed: function(length) {   
  return this.formatMs(length, true);
 },
 ReplaceMs: function(length) { 
  return this.formatMs(length, false);
 },
 ReplaceEra: function(length) {
  return "A.D.";
 },
 ReplaceAmPm: function(length) {
  var value = this.date.getHours() < 12 ? ASPx.CultureInfo.am : ASPx.CultureInfo.pm;
  return length < 2 ? value.charAt(0) : value;
 },
 catchNumbers: function(str, specifiers) {
  this.parseNumbers = [];  
  var regex = /\d+/g;  
  var match;
  for(;;) {
   match = regex.exec(str);
   if(!match)
    break;
   this.parseNumbers.push(this.parseDecInt(match[0]));
  }  
  var spCount = 0;
  var now = new Date();
  for(var i in specifiers) {
   if(specifiers.hasOwnProperty(i)) {
    var sp = specifiers[i];
    if (sp.constructor != String || !this.IsNumericSpecifier(sp)) continue;
    spCount++;
    if(this.parseNumbers.length < spCount) {
     var defaultValue = 0;
     if (sp.charAt(0) == "y") defaultValue = now.getFullYear();
     this.parseNumbers.push(defaultValue);
    }
   }
  }
  var excess = this.parseNumbers.length - spCount;
  if(excess > 0)
   this.parseNumbers.splice(spCount, excess);  
  this.currentParseNumber = this.parseNumbers.length - 1;
 },
 popParseNumber: function() {
  return this.parseNumbers[this.currentParseNumber--];
 },
 findAbbrMonth: function() {
  return this.findMonthCore(ASPx.CultureInfo.abbrMonthNames);
 },
 findFullMonth: function() {
  return this.findMonthCore(ASPx.CultureInfo.genMonthNames);
 },
 findMonthCore: function(monthNames) {
  var inputLower = this.strToParse.toLowerCase();
  var matchMonthNames = monthNames.filter(function(n) { return inputLower.indexOf(n.toLowerCase()) > -1; });
  if(matchMonthNames.length == 0)
   return false;
  var sortedMatchNames = matchMonthNames.sort(function(a, b) { return b.length - a.length; });
  var name = sortedMatchNames[0];
  var emptyMonth = new Array(name.length + 1).join(" ");
  this.strToParse = this.strToParse.replace(new RegExp(name, "gi"), emptyMonth);
  return monthNames.indexOf(name) + 1;
 },
 ParseDay: function(length) {
  if(length < 3) {
   var value = this.popParseNumber();
   if(value < 1 || value > 31)
    return false;
   this.date.setDate(value);
  }
  return true;
 },
 ParseMonth: function(length) {
  var value;
  var actualMonthTextContainsDigitOnly = this.actualDayMonthTextContainsDigitOnly("M", length);
  if(length < 3 || actualMonthTextContainsDigitOnly)
   value = this.popParseNumber();
  else
   value = length === 3 ? this.findAbbrMonth() : this.findFullMonth();
  if(value < 1 || value > 12)
   return false;
  this.parsedMonth = value - 1;
  if(this.actualDayMonthTextContainsAnyDigit("M", length) && !actualMonthTextContainsDigitOnly && length > 2)
   this.currentParseNumber--;
  return true;
 }, 
 ParseYear: function(length) {  
  var value = this.popParseNumber();
  if(value > 9999)
   return false;
  if(value < 100)
   value = ASPx.DateUtils.ExpandTwoDigitYear(value);
  this.date.setFullYear(value);
  this.isYearParsed = true;
  return true;
 },
 ParseHours: function(length) {
  var value = this.popParseNumber();
  if(value > 23)
   return false;
  this.date.setHours(value);
  return true;
 },
 ParseMinutes: function(length) {
  var value = this.parseMinSecCore();
  if(value == -1)
   return false;
  this.date.setMinutes(value);
  return true;
 },
 ParseSeconds: function(length) {
  var value = this.parseMinSecCore();
  if(value == -1)
   return false;
  this.date.setSeconds(value);
  return true;
 },
 ParseMs: function(length) {
  if(length > 3)
   length = 3;
  var thr = 1;
  for(var i = 0; i < length; i++)
   thr *= 10;
  thr -= 1;
  var value = this.popParseNumber();
  while(value > thr)
   value /= 10;
  this.date.setMilliseconds(Math.round(value));
  return true;
 },
 ParseEra: function(length) {
  return true;
 },
 ParseAmPm: function(length) {
  this.hasAmPm = ASPx.CultureInfo.is12HoursCulture;
  return true;
 },
 parseDecInt: function(str) {
  return parseInt(str, 10);
 },
 padLeft: function(str, length) {
  while(str.length < length)
   str = "0" + str;
  return str;
 },
 formatMs: function(length, trim) {
  var value = Math.floor(this.date.getMilliseconds() * Math.pow(10, length - 3));
  value = this.padLeft(value.toString(), length);    
  if(trim) {
   var pos = value.length - 1;
   var req = false;
   while(value.charAt(pos) == "0") {
    req = true;
    pos--;
   }
   if(req)
    value = value.substring(0, pos + 1);   
  }
  return value;
 },
 parseMinSecCore: function() {
  var value = this.popParseNumber();
  return value > 59 ? -1 : value;
 },
 fixHours: function() {
  var state = this.getAmPmState(this.strToParse);
  if(!state) return true;
  var h = this.date.getHours();
  switch(state) {
   case "P":
    if(h > 12) return false;
    if(h < 12)
     this.date.setHours(12 + h);
    break;
   case "A":
    if(h == 12)
     this.date.setHours(0);
  }
  return true;
 },
 getAmPmState: function(str, skipCorrection) {
  var am = ASPx.CultureInfo.am.charAt(0).toLowerCase();
  var pm = ASPx.CultureInfo.pm.charAt(0).toLowerCase();
  var amMatches = new RegExp(am, "gi").exec(str);
  var pmMatches = new RegExp(pm, "gi").exec(str);
  var amCount = amMatches ? amMatches.length : 0;
  var pmCount = pmMatches ? pmMatches.length : 0;
  var hasAm = amCount > 0;
  var hasPm = pmCount > 0;
  if(hasAm ^ hasPm && amCount < 2 && pmCount < 2)
   return hasAm ? "A" : "P";
  if(!skipCorrection) {
   str = str.replace(new RegExp(this.getDayMonthNameReplacePattern(), "gi"), "");
   return this.getAmPmState(str, true);
  }
  return null;
 },
 getDayMonthNameReplacePattern: function() {
  if(!this.dayMonthNameReplacePattern)
   return this.createDayMonthNameReplacePattern();
  return this.dayMonthNameReplacePattern;
 },
 createDayMonthNameReplacePattern: function() {
  var parts = [ ] ;
  parts.push("(?:");
  parts.push(this.createReplacePattern(ASPx.CultureInfo.monthNames));
  parts.push(this.createReplacePattern(ASPx.CultureInfo.genMonthNames));
  parts.push(this.createReplacePattern(ASPx.CultureInfo.abbrMonthNames));
  parts.push(this.createReplacePattern(ASPx.CultureInfo.abbrDayNames));
  parts.push(this.createReplacePattern(ASPx.CultureInfo.dayNames));
  parts.push(")");
  return parts.join("");
 },
 createReplacePattern: function(names) {
  return names && names.length > 0 ? "\\b" + names.join("\\b|\\b") + "\\b" : "";
 },
 IsNumericSpecifier: function(sp) {
  var ch = sp.charAt(0);
  if(ch == "g" || ch == "t" || ((ch == "M" || ch == "d") && !this.actualDayMonthTextContainsAnyDigit(ch, sp.length)))
   return false;
  return true;
 },
 actualDayMonthTextContainsAnyDigit: function(datePart, datePartLength) {
  return this.actualDayMonthTextContainsDigitCore(datePart, datePartLength, function(name) { return /\d+/g.test(name); });
 },
 actualDayMonthTextContainsDigitOnly: function(datePart, datePartLength) {
  return this.actualDayMonthTextContainsDigitCore(datePart, datePartLength, function(name) { return !isNaN(parseInt(name)); });
 },
 actualDayMonthTextContainsDigitCore: function(datePart, datePartLength, matchDigitFunc) {
  if(datePartLength < 3)
   return true;
  var targetNames = this.getDayMonthNames(datePart, datePartLength);
  return targetNames.length > 0 ? matchDigitFunc(targetNames[0]) : false;
 },
 getDayMonthNames: function(datePart, datePartLength) {
  var result = [];
  var useAbbrNames = datePartLength == 3;
  if(datePart == "d")
   result = useAbbrNames ? ASPx.CultureInfo.abbrDayNames : ASPx.CultureInfo.dayNames;
  else
   result = useAbbrNames ? ASPx.CultureInfo.abbrMonthNames : ASPx.CultureInfo.monthNames;
  return result;
 },
 IsKnownSpecifier: function(sp) {
  if(sp.length > 1)
   sp = sp.charAt(0);
  for(var i = 0; i < this.knownSpecifiers.length; i++) {
   if(this.knownSpecifiers[i] == sp)
    return true;
  }
  return false;
 }
});
DateFormatter.Create = function(format) {
 var instance = new DateFormatter();
 instance.SetFormatString(format);
 return instance;
};
DateFormatter.ExpandPredefinedFormat = function(format) {
 switch(format) {
  case "d":
   return ASPx.CultureInfo.shortDate;
  case "D":
   return ASPx.CultureInfo.longDate;
  case "t":
   return ASPx.CultureInfo.shortTime;
  case "T":
   return ASPx.CultureInfo.longTime;
  case "g":
   return ASPx.CultureInfo.shortDate + " " + ASPx.CultureInfo.shortTime;   
  case "f":
   return ASPx.CultureInfo.longDate + " " + ASPx.CultureInfo.shortTime;
  case "G":
   return ASPx.CultureInfo.shortDate + " " + ASPx.CultureInfo.longTime;
  case "F":
  case "U":
   return ASPx.CultureInfo.longDate + " " + ASPx.CultureInfo.longTime;   
  case "M":
  case "m":
   return ASPx.CultureInfo.monthDay;
  case "Y":
  case "y":
   return ASPx.CultureInfo.yearMonth;   
  case "O":
  case "o":
   return "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffff";
  case "R":
  case "r":
   return "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
  case "s":
   return "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
  case "u":
    return "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
 }
 return format;
};
ASPx.DateFormatter = DateFormatter;
})();

(function() {
ASPx.Formatter = {
 Format: function() {
  if(arguments.length < 1) 
   return "";
  var format = arguments[0];
  if(format == null)
   return "";
  var args;
  if(arguments.length > 1 && arguments[1] != null && arguments[1].constructor == Array) {
   args = arguments[1];
  } else {
   args = [ ];
   for(var i = 1; i < arguments.length; i++)
    args.push(arguments[i]);
  }
  var bag = [ ];
  var pos = 0;
  var savedPos = 0;  
  while(pos < format.length) {
   var ch = format.charAt(pos);
   pos++;
   if(ch == '{') {
    bag.push(format.substr(savedPos, pos - savedPos - 1));    
    if(format.charAt(pos) == "{") {
     savedPos = pos;
     pos++;
     continue;
    }
    var spec = this.ParseSpec(format, pos);
    var pos = spec.pos;
    var arg = args[spec.index];
    var argString;
    if(arg == null) {
     argString = "";
    } else if(typeof arg == "number") {
     argString = ASPx.NumberFormatter.Format(spec.format, arg);
    } else if(arg.constructor == Date) {     
     if(spec.format != this.activeDateFormat) {
      this.activeDateFormat = spec.format;
      if(spec.format == "")
       spec.format = "G";      
      if(spec.format.length == 1)
       spec.format = ASPx.DateFormatter.ExpandPredefinedFormat(spec.format);
      this.GetDateFormatter().SetFormatString(spec.format);
     }
     if(this.activeDateFormat == "U")
      arg = ASPx.DateUtils.ToUtcTime(arg);
     argString = this.GetDateFormatter().Format(arg);
    } else {
     argString = String(arg);     
     if(spec.format != "" && argString.length > 0) {
      var num = Number(argString.replace(",", "."));
      if(!isNaN(num))
       argString = ASPx.NumberFormatter.Format(spec.format, num);
     }
    }
    var padLen = spec.width - argString.length;
    if(padLen > 0) {
     if(spec.left)
      bag.push(argString);
     for(var i = 0; i < padLen; i++)
      bag.push(" ");
     if(!spec.left)
      bag.push(argString);
    } else {
     bag.push(argString);
    }
    savedPos = pos;
   }
   else if(ch == "}" && pos < format.length && format.charAt(pos) == "}") {
    bag.push(format.substr(savedPos, pos - savedPos - 1));
    savedPos = pos;
    pos++;
   }
   else if (ch == "}") {
    return "";
   }
  }
  if(savedPos < format.length)
   bag.push(format.substr(savedPos));   
  return bag.join("");
 },
 ParseSpec: function(format, pos) {
  var result = {
   index: -1,   
   left: false,
   width: 0,
   format: "",
   pos: 0
  };
  var savedPos, ch;
  savedPos = pos;
  while(true) {   
   ch = format.charAt(pos);
   if(ch < "0" || ch > "9")
    break;
   pos++;
  }  
  if(pos > savedPos)
   result.index = Number(format.substr(savedPos, pos - savedPos));  
  if(format.charAt(pos) == ",") {
   pos++;
   while(true) {
    ch = format.charAt(pos);
    if(ch != " " && ch != "\t")
     break;
    pos++;
   }
   result.left = format.charAt(pos) == "-";
   if(result.left)
    pos++;   
   savedPos = pos;
   while(true) {
    ch = format.charAt(pos);
    if(ch < "0" || ch > "9")
     break;
    pos++;
   }
   if(pos > savedPos)
    result.width = Number(format.substr(savedPos, pos - savedPos));
  }
  if(format.charAt(pos) == ":") {
   pos++;
   savedPos = pos;
   while(format.charAt(pos) != "}")
    pos++;
   result.format = format.substr(savedPos, pos - savedPos);
  }
  pos++;
  result.pos = pos;
  return result;
 },
 activeDateFormat: null,
 GetDateFormatter: function() {
  if(!this.__dateFormatter)
   this.__dateFormatter = new ASPx.DateFormatter();
  return this.__dateFormatter;
 }
};
ASPx.NumberFormatter = {
 Format: function(format, value) {
  if(isNaN(value))
   return ASPx.CultureInfo.numNan;
  if(!isFinite(value)) {
   return value > 0 
    ? ASPx.CultureInfo.numPosInf 
    : ASPx.CultureInfo.numNegInf;
  }
  this.FillFormatInfo(format);
  if(this.spec == "X")
   return this.FormatHex(value);
  this.FillDigitInfo(value);  
  switch(this.spec) {
   case "C":
    return this.FormatCurrency();
   case "D":
    return this.FormatDecimal();
   case "E":
    return this.FormatExp();
   case "F":
    return this.FormatFixed();
   case "G":   
    return this.FormatGeneral();
   case "N":
    return this.FormatNumber();
   case "P":
    return this.FormatPercent();
   default:
    if(this.custom)
     return this.FormatCustom(format);
    return "?";
  }
 },
 positive: true,
 digits: null,
 pointPos: 0, 
 spec: "",
 prec: -1,  
 upper: true,
 custom: false,
 FormatCurrency: function() {  
  if(this.prec < 0)
   this.prec = ASPx.CultureInfo.currPrec;
  this.Round(this.prec);
  var bag = [ ];
  if(this.positive) {
   switch(ASPx.CultureInfo.currPosPattern) {
    case 0:
     bag.push(ASPx.CultureInfo.currency);
     break;
    case 2:
     bag.push(ASPx.CultureInfo.currency, " ");     
     break;     
   }
  } else {
   switch(ASPx.CultureInfo.currNegPattern) {
    case 0:
     bag.push("(", ASPx.CultureInfo.currency);
     break;
    case 1:
     bag.push("-", ASPx.CultureInfo.currency);
     break;
    case 2:
     bag.push(ASPx.CultureInfo.currency, "-");
     break;
    case 3:
     bag.push(ASPx.CultureInfo.currency);
     break;
    case 4:
     bag.push("(");
     break;
    case 5:
    case 8:
     bag.push("-");
     break;
    case 9:
     bag.push("-", ASPx.CultureInfo.currency, " ");
     break;
    case 11:
     bag.push(ASPx.CultureInfo.currency, " ");
     break;
    case 12:
     bag.push(ASPx.CultureInfo.currency, " -");
     break;
    case 14:
     bag.push("(", ASPx.CultureInfo.currency, " ");
     break;
    case 15:
     bag.push("(");
     break;
   }
  }
  this.AppendGroupedInteger(bag, ASPx.CultureInfo.currGroups, ASPx.CultureInfo.currGroupSeparator);
  if(this.prec > 0) {
   bag.push(ASPx.CultureInfo.currDecimalPoint);
   this.AppendDigits(bag, this.pointPos, this.pointPos + this.prec);
  }
  if(this.positive) {
   switch(ASPx.CultureInfo.currPosPattern) {
    case 1:
     bag.push(ASPx.CultureInfo.currency);
     break;
    case 3:
     bag.push(" ", ASPx.CultureInfo.currency);
     break;     
   }   
  } else {
   switch(ASPx.CultureInfo.currNegPattern) {
    case 0:
    case 14:
     bag.push(")");
     break;
    case 3:
     bag.push("-");
     break;
    case 4:
     bag.push(ASPx.CultureInfo.currency, ")");
     break;
    case 5:
     bag.push(ASPx.CultureInfo.currency);
     break;
    case 6:
     bag.push("-", ASPx.CultureInfo.currency);
     break;
    case 7:
     bag.push(ASPx.CultureInfo.currency, "-");
     break;
    case 8:
     bag.push(" ", ASPx.CultureInfo.currency);
     break;
    case 10:
     bag.push(" ", ASPx.CultureInfo.currency, "-");
     break;
    case 11:
     bag.push("-");
     break;
    case 13:
     bag.push("- ", ASPx.CultureInfo.currency);
     break;
    case 15:
     bag.push(" ", ASPx.CultureInfo.currency, ")");
     break;
   }
  }
  return bag.join("");
 }, 
 FormatDecimal: function() {
  if(this.prec < this.pointPos)
   this.prec = this.pointPos;
  if(this.prec < 1)
   return "0";
  var bag = [ ];
  if(!this.positive)
   bag.push("-");
  this.AppendDigits(bag, this.pointPos - this.prec, this.pointPos);
  return bag.join("");
 },
 FormatExp: function() {  
  if(this.prec < 0)
   this.prec = 6;
  this.Round(1 - this.pointPos + this.prec);
  return this.FormatExpCore(3);
 },
 FormatExpCore: function(minExpDigits) {
  var bag = [ ];
  if(!this.positive)
   bag.push("-");
  this.AppendDigits(bag, 0, 1);
  if(this.prec > 0) {
   bag.push(ASPx.CultureInfo.numDecimalPoint);
   this.AppendDigits(bag, 1, 1 + this.prec);
  }
  bag.push(this.upper ? "E" : "e");
  var order = this.pointPos - 1;  
  if(order >= 0) {
   bag.push("+");
  } else {
   bag.push("-");
   order = -order;
  }
  var orderStr = String(order);
  for(var i = orderStr.length; i < minExpDigits; i++)
   bag.push(0);
  bag.push(orderStr);
  return bag.join("");
 },
 FormatFixed: function() {
  if(this.prec < 0)
   this.prec = ASPx.CultureInfo.numPrec;
  this.Round(this.prec);
  var bag = [ ];
  if(!this.positive)
   bag.push("-");
  if(this.pointPos < 1)
   bag.push(0);
  else
   this.AppendDigits(bag, 0, this.pointPos);
  if(this.prec > 0) {
   bag.push(ASPx.CultureInfo.numDecimalPoint);
   this.AppendDigits(bag, this.pointPos, this.pointPos + this.prec);
  }
  return bag.join(""); 
 },
 FormatGeneral: function() {
  var hasFrac = this.pointPos < this.digits.length;
  var allowExp;
  if(this.prec < 0) {
   allowExp = hasFrac;
   this.prec = hasFrac ? 15 : 10;
  } else {   
   allowExp = true;
   if(this.prec < 1)
    this.prec = hasFrac ? 15 : 10;
   this.Round(this.prec - this.pointPos);
  }
  if(allowExp) {
   if(this.pointPos > this.prec || this.pointPos <= -4) {
    this.prec = this.digits.length - 1;
    return this.FormatExpCore(2);
   }
  }
  this.prec = Math.min(this.prec, Math.max(1, this.digits.length)) - this.pointPos;
  return this.FormatFixed();
 },
 FormatNumber: function() {
  if(this.prec < 0)
   this.prec = ASPx.CultureInfo.numPrec;
  this.Round(this.prec);
  var bag = [ ];
  if(!this.positive) {
   switch(ASPx.CultureInfo.numNegPattern) {
    case 0:
     bag.push("(");
     break;
    case 1:
     bag.push("-");
     break;
    case 2:
     bag.push("- ");
     break;
   }
  }
  this.AppendGroupedInteger(bag, ASPx.CultureInfo.numGroups, ASPx.CultureInfo.numGroupSeparator);
  if(this.prec > 0) {
   bag.push(ASPx.CultureInfo.numDecimalPoint);
   this.AppendDigits(bag, this.pointPos, this.pointPos + this.prec);
  }
  if(!this.positive) {
   switch(ASPx.CultureInfo.numNegPattern) {
    case 0:
     bag.push(")");
     break;
    case 3:
     bag.push("-");
     break;
    case 4:
     bag.push(" -");
     break;
   }
  }
  return bag.join("");
 },
 FormatPercent: function() {
  if(this.prec < 0)
   this.prec = ASPx.CultureInfo.numPrec;
  if(this.digits.length > 0)
   this.pointPos += 2;
  this.Round(this.prec);
  var bag = [ ];
  if(!this.positive)
   bag.push("-");
  if(ASPx.CultureInfo.percentPattern == 2)
   bag.push("%");    
  this.AppendGroupedInteger(bag, ASPx.CultureInfo.numGroups, ASPx.CultureInfo.numGroupSeparator);
  if(this.prec > 0) {
   bag.push(ASPx.CultureInfo.numDecimalPoint);
   this.AppendDigits(bag, this.pointPos, this.pointPos + this.prec);
  }  
  switch(ASPx.CultureInfo.percentPattern) {
   case 0:
    bag.push(" %");
    break;
   case 1:
    bag.push("%");
    break;
  }  
  return bag.join("");
 },
 FormatHex: function(value) {
  var result = value.toString(16);
  if(result.indexOf("(") > -1)
   return result;
  result = this.upper ? result.toUpperCase() : result.toLowerCase();
  if(this.prec <= result.length)
   return result;
  var bag = [ ];
  for(var i = result.length; i < this.prec; i++)
   bag.push(0);
  bag.push(result);
  return bag.join("");
 },
 FormatCustom: function(format) {
  var sectionList = this.GetCustomFormatSections(format);
  var section = this.SelectCustomFormatSection(sectionList);
  if(section == "")
   return this.positive ? "" : "-";
  var info = this.ParseCustomFormatSection(section);
  var lists = this.CreateCustomFormatLists(info);
  if(sectionList.length > 2 && section != sectionList[2]) {
   var zero = lists.i.concat(lists.f).join("").split(0).join("") == "";
   if(zero) {
    section = sectionList[2];
    info = this.ParseCustomFormatSection(section);
    lists = this.CreateCustomFormatLists(info);   
   }   
  }
  return this.FormatCustomCore(section, info, lists);
 },
 GetCustomFormatSections: function(format) {
  var sections = [ ];
  var escaping = false;
  var quote = "";
  var length = 0;
  var prevPos = 0;
  for(var i = 0; i < format.length; i++) {
   var ch = format.charAt(i);
   if(!escaping && quote == "" && ch == ";") {
    sections.push(format.substr(prevPos, length));
    length = 0;
    prevPos = i + 1;
    if(sections.length > 2)
     break;
   } else {
    if(escaping)
     escaping = false;
    else if(ch == quote)
     quote = quote == "" ? ch : "";
    else if(ch == "\\")
     escaping = true;
    else if(ch == "'" || ch == '"')
     quote = ch;
    ++length;
   }
  }
  if(length > 0)
   sections.push(format.substr(prevPos, length));
  if(sections.length < 1)
   sections.push(format);
  return sections;
 },
 SelectCustomFormatSection: function(sections) {
  if(!this.positive && sections.length > 1 && sections[1] != "") {
   this.positive = true;
   return sections[1];
  }
  if(this.digits.length < 1 && sections.length > 2 && sections[2] != "")
   return sections[2];
  return sections[0];
 },
 CreateCustomFormatInfo: function() {
  return {
   pointPos: -1,
   grouping: false,
   exp: false,
   expShowPlus: false,
   percent: false,
   scaling: 0,
   intDigits: 0,
   fracDigits: 0,
   expDigits: 0,
   intSharps: 0,
   fracSharps: 0, 
   expSharps: 0
  };
 },
 ParseCustomFormatSection: function(section) {  
  var quote = "";
  var area = "i"; 
  var canParseIntSharps = true;
  var result = this.CreateCustomFormatInfo();
  var groupSeparators = 0;  
  for(var i = 0; i < section.length; i++) {
   var ch = section.charAt(i);   
   if(ch == quote) {
    quote = "";    
    continue;
   }
   if(quote != "")
    continue;
   if(area == "e" && ch != "0" && ch != "#") {
    area = result.pointPos < 0 ? "i" : "f";
    i--;
    continue;
   }
   switch(ch) {
    case "\\":
     i++;
     continue;
    case "'":
    case '"':
     quote = ch;
     continue;
    case "#":
    case "0":
     if(ch == "#") {
      switch(area) {
       case "i":
        if(canParseIntSharps)
         result.intSharps++;
        break;
       case "f":
        result.fracSharps++;
        break;
       case "e":
        result.expSharps++;
        break;
      }
     } else {
      canParseIntSharps = false;
      switch(area) {
       case "f":
        result.fracSharps = 0;        
        break;
       case "e":
        result.expSharps = 0;
        break;
      }
     }
     switch(area) {
      case "i":
       result.intDigits++;
       if(groupSeparators > 0)
        result.grouping = true;
       groupSeparators = 0;
       break;
      case "f":
       result.fracDigits++;  
       break;
      case "e":
       result.expDigits++;
       break;
     }
     break;
    case "e":
    case "E":
     if(result.exp)
      break;
     result.exp = true;     
     area = "e"; 
     if(i < section.length - 1) {
      var next = section.charAt(1 + i);
      if(next == "+" || next == "-") {
       if(next == "+")
        result.expShowPlus = true;
       i++;
      }
      else if(next != "0" && next != "#") {
       result.exp = false;
       if(result.pointPos < 0)
        area = "i";       
      }
     }
     break;
    case ".":
     area = "f";
     if(result.pointPos < 0)
      result.pointPos = i;
     break;
    case "%":
     result.percent = true;     
     break;
    case ",":
     if(area == "i" && result.intDigits > 0)
      groupSeparators++;
     break;
    default:
     break;
   }
  }
  if(result.expDigits < 1)
   result.exp = false;
  else
   result.intSharps = 0;
  if(result.fracDigits < 1)
   result.pointPos = -1;
  result.scaling = 3 * groupSeparators;  
  return result;
 },
 CreateCustomFormatLists: function(info) {
  var intList = [ ];
  var fracList = [ ];
  var expList = [ ];
  if(this.digits.length > 0) {
   if(info.percent)
    this.pointPos += 2;
   this.pointPos -= info.scaling;
  }
  var expPositive = true;
  if(info.exp && (info.intDigits > 0 || info.fracDigits > 0)) {
   var diff = 0;
   if(this.digits.length > 0) {
    this.Round(info.intDigits + info.fracDigits - this.pointPos);
    diff -= this.pointPos - info.intDigits;
    this.pointPos = info.intDigits;
   }
   expPositive = diff <= 0;   
   expList = String(diff < 0 ? -diff : diff).split("");
  } else {
   this.Round(info.fracDigits);
  }
  if(this.digits.length < 1 || this.pointPos < 1)
   intList = [ 0 ];
  else
   this.AppendDigits(intList, 0, this.pointPos);
  this.AppendDigits(fracList, this.pointPos, this.digits.length);
  if(info.exp) {
   while(intList.length < info.intDigits)
    intList.unshift(0);
   while(expList.length < info.expDigits - info.expSharps)
    expList.unshift(0);
   if(expPositive && info.expShowPlus)
    expList.unshift("+");
   else if(!expPositive)
    expList.unshift("-");
  } else {
   while(intList.length < info.intDigits - info.intSharps)
    intList.unshift(0);    
   if(info.intSharps >= info.intDigits) {
    var zero = true;
    for(var i = 0; i < intList.length; i++) {
     if(intList[i] != 0) {
      zero = false;
      break;
     }
    }
    if(zero)
     intList = [ ];
   }
  }
  while(fracList.length < info.fracDigits - info.fracSharps)
   fracList.push(0);
  return {
   i: intList,
   f: fracList,
   e: expList
  };
 },
 FormatCustomCore: function(section, info, lists) {
  var intLen = 0; 
  var total = 0;
  var groupIndex = 0; 
  var counter = 0;
  var groupSize = 0;
  if(info.grouping && ASPx.CultureInfo.numGroups.length > 0) {
   intLen = lists.i.length;
   for(var i = 0; i < ASPx.CultureInfo.numGroups.length; i++) {
    if(total + ASPx.CultureInfo.numGroups[i] <= intLen) {
     total += ASPx.CultureInfo.numGroups[i];
     groupIndex = i;
    }
   }
   groupSize = ASPx.CultureInfo.numGroups[groupIndex];
   var fraction = intLen > total ? intLen - total : 0;
   if(groupSize == 0) {
    while(groupIndex >= 0 && ASPx.CultureInfo.numGroups[groupIndex] == 0)
     groupIndex--;
    groupSize = fraction > 0 ? fraction : ASPx.CultureInfo.numGroups[groupIndex];
   }
   if(fraction == 0) {
    counter = groupSize;
   } else {
    groupIndex += Math.floor(fraction / groupSize);
    counter = fraction % groupSize;
    if(counter == 0)
     counter = groupSize;
    else
     groupIndex++;
   }
  } else {
   info.grouping = false;
  }
  var bag = [ ];
  var area = "i";
  var intSharps = 0;
  var intListIndex = 0;
  var fracListIndex = 0;
  var savedCh = "";
  for(var i = 0; i < section.length; i++) {
   var ch = section.charAt(i);
   if(ch == savedCh) {
    savedCh = "";
    continue;
   }
   if(savedCh != "") {
    bag.push(ch);
    continue;
   }
   switch(ch) {
    case "\\":
     ++i;
     if(i < section.length)
      bag.push(section.charAt(i));
     continue;
    case "'":
    case '"':     
     savedCh = ch;
     continue;
    case "#":     
    case "0":
     if(area == "i") {
      intSharps++;
      if(ch == "0" || info.intDigits - intSharps < lists.i.length + intListIndex) {
       while(info.intDigits - intSharps + intListIndex < lists.i.length) {
        bag.push(lists.i[intListIndex]);
        intListIndex++;
        if(info.grouping && --intLen > 0 && --counter == 0) {
         bag.push(ASPx.CultureInfo.numGroupSeparator);
         if(--groupIndex < ASPx.CultureInfo.numGroups.length && groupIndex >= 0)
          groupSize = ASPx.CultureInfo.numGroups[groupIndex];
         counter = groupSize;
        }
       }
      }
     } else if(area == "f") {
      if(fracListIndex < lists.f.length) {
       bag.push(lists.f[fracListIndex]);
       fracListIndex++;
      }
     }
     break;
    case "e":
    case "E":
     if(lists.e == null || !info.exp) {
      bag.push(ch);
      break;
     }
     for(var q = i + 1; q < section.length; q++) {
      if(q == i + 1 && (section.charAt(q) == "+" || section.charAt(q) == "-"))
       continue;                   
      if(section.charAt(q) == "0" || section.charAt(q) == "#")
       continue;
      break;
     }
     i = q - 1;
     area = info.pointPos < 0 ? "i" : "f";
     bag.push(ch);
     bag = bag.concat(lists.e);
     lists.e = null;      
     break;
    case ".":
     if(info.pointPos == i && lists.f.length > 0)
      bag.push(ASPx.CultureInfo.numDecimalPoint);
     area = "f";
     break;
    case ",":
     break;
    default:
     bag.push(ch);
     break;
   }
  }
  if(!this.positive)
   bag.unshift("-");
  return bag.join("");
 },
 FillDigitInfo: function(value) {
  this.positive = true;
  if(value < 0) {
   value = -value;
   this.positive = false;   
  }
  this.digits = [ ];
  this.pointPos = 0;    
  if(value == 0 || !isFinite(value) || isNaN(value)) {
   this.pointPos = 1;
   return;
  }
  var list = String(value).split("e");
  var str = list[0];
  if(list.length > 1) {   
   this.pointPos = Number(list[1]);
  }
  var frac = false;
  var decimalCount = 0;
  for(var i = 0; i < str.length; i++) {
   var ch = str.charAt(i);
   if(ch == ".") {
    frac = true;
   } else {
    if(frac)
     decimalCount++;     
    if(ch != "0" || this.digits.length > 0)
     this.digits.push(Number(ch));
   }
  }
  this.pointPos += this.digits.length - decimalCount;
 },
 FillFormatInfo: function(format) {
  this.upper = true;
  this.custom = false;
  this.prec = -1;
  var spec;
  if(format == null || format.length < 1)
   spec = "G";
  else
   spec = format.charAt(0);
  if(spec >= "a" && spec <= "z") {
   spec = spec.toUpperCase();
   this.upper = false;
  }
  if(spec >= "A" && spec <= "Z") {   
   if(format != null && format.length > 1) {
    var prec = Number(format.substr(1));
    if(!isNaN(prec))
     this.prec = prec;
    else
     this.custom = true;
   }
  } else {
   this.custom = true;   
  }  
  this.spec = this.custom ? "0" : spec;
 },
 Round: function(shift) {
  var amount = this.digits.length - this.pointPos - shift;
  if(amount <= 0) 
   return;
  var cutPos = this.pointPos + shift;
  if(cutPos < 0) {
   this.digits = [ ];
   this.pointPos = 0;
   return;
  }
  var digit = this.digits[cutPos];
  if(digit > 4) { 
   for(var i = 0; i < amount; i++) {
    var index = cutPos - 1 - i;
    if(index < 0) {
     this.digits.unshift(0);
     this.pointPos++;
     cutPos++;
     index++;
    }
    digit = this.digits[index];    
    if(digit < 9) {
     this.digits[index] = 1 + digit;
     break;
    } else {
     this.digits[index] = 0;
     amount++;
    }
   }
  }
  for(var i = cutPos - 1; i >= 0; i--) {
   if(this.digits[i] > 0) break;
   cutPos--;
  }
  this.digits.splice(cutPos, this.digits.length - cutPos);
 },
 AppendGroupedInteger: function(list, groups, separator) { 
  if(this.pointPos < 1) {
   list.push(0);
   return;
  }
  var total = 0;
  var groupIndex = 0;
  for(var i = 0; i < groups.length; i++) {
   if(total + groups[i] <= this.pointPos) {
    total += groups[i];
    groupIndex = i;
   }
   else
    break;
  }
  if(groups.length > 0 && total > 0) {
   var counter;
   var groupSize = groups[groupIndex];
   var fraction = this.pointPos > total ? this.pointPos - total : 0;
   if(groupSize == 0) {
    while(groupIndex >= 0 && groups[groupIndex] == 0)
     groupIndex--;
    groupSize = fraction > 0 ? fraction : groups[groupIndex];
   }
   if(fraction == 0) {
    counter = groupSize;
   } else {
    groupIndex += Math.floor(fraction / groupSize);
    counter = fraction % groupSize;
    if(counter == 0)
     counter = groupSize;
    else
     groupIndex++;
   }
   var i = 0;
   while(true) {
    if(this.pointPos - i <= counter || counter == 0) {
     this.AppendDigits(list, i, this.pointPos);
     break;
    }
    this.AppendDigits(list, i, i + counter);
    list.push(separator);
    i += counter;    
    groupIndex--;     
    if(groupIndex < groups.length && groupIndex >= 0)
     groupSize = groups[groupIndex];
    counter = groupSize;
   }
  } else {
   this.AppendDigits(list, 0, this.pointPos);   
  }  
 },
 AppendDigits: function(list, start, end) {
  for(var i = start; i < end; i++) {
   if(i < 0 || i >= this.digits.length)
    list.push(0);
   else
    list.push(this.digits[i]);
  }
 }
};
})();
(function () {
var ProgressBarIDSuffix = {
 DivIndicator: "_DI",
 ValueIndicatorCell: "_VIC"
};
var ASPxClientProgressBarBase = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.displayMode = ASPxClientProgressBarBase.DisplayMode.Percentage;
  this.displayFormat = null;
  this.minimum = 0;
  this.maximum = 0;
  this.position = 0;
  this.onePercentValue = 0;
  this.hasOwner = true;
  this.customDisplayFormat = "";
 },
 InlineInitialize: function (calledByOwner) {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  if(calledByOwner || !this.hasOwner) {
   this.OnePercentValueUpdate();
   if(this.IsIndicatorDivWidthCorrectionRequired())
    this.SetCalculatedDivIndicatorWidth();
  }
 },
 OnePercentValueUpdate: function () {
  this.onePercentValue = (this.maximum - this.minimum) / 100;
 },
 GetMainCell: function () {
  if(!this.mainCell)
   this.mainCell = ASPx.GetNodeByTagName(this.GetMainElement(), "TD", 0);
  return this.mainCell;
 },
 GetIndicatorDiv: function () {
  if(!this.divIndicator)
   this.divIndicator = ASPx.GetElementById(this.name + ProgressBarIDSuffix.DivIndicator);
  return this.divIndicator;
 },
 GetValueIndicatorTable: function () {
  if(!this.valueIndicatorTable)
   this.valueIndicatorTable = ASPx.GetParentByTagName(this.GetValueIndicatorCell(), "TABLE");
  return this.valueIndicatorTable;
 },
 GetValueIndicatorCell: function () {
  if(!this.valueIndicatorCell)
   this.valueIndicatorCell = ASPx.GetElementById(this.name + ProgressBarIDSuffix.ValueIndicatorCell);
  return this.valueIndicatorCell;
 },
 GetValueIndicatorContainer: function() {
  var cell = this.GetValueIndicatorCell();
  if(!cell)
   return null;
  return cell.querySelector(".dxpbVC");
 },
 AdjustControlCore: function () {
  ASPxClientControl.prototype.AdjustControlCore.call(this);
  this.UpdateIndicators();
  this.CorrectIndicatorHeight();
 },
 CorrectIndicatorHeight: function () {
  var mainCell = this.GetMainCell();
  var valueIndicatorTable = this.GetValueIndicatorTable();
  var indicatorDiv = this.GetIndicatorDiv();
  if(indicatorDiv)
   indicatorDiv.style.height = "";
  if(valueIndicatorTable) {
   valueIndicatorTable.style.height = "";
   valueIndicatorTable.style.marginTop = "";
  }
  var height = ASPx.GetClearClientHeight(mainCell);
  if(indicatorDiv)
   indicatorDiv.style.height = (height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(indicatorDiv)) + "px";
  if(valueIndicatorTable) {
   valueIndicatorTable.style.height = (height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(valueIndicatorTable)) + "px";
   valueIndicatorTable.style.marginTop = -height + "px";
  }
 },
 ResetIndicatorHeight: function () {
  ASPx.SetOffsetHeight(this.GetIndicatorDiv(), 1);
  var valueIndicatorTable = this.GetValueIndicatorTable();
  if(valueIndicatorTable)
   ASPx.SetOffsetHeight(valueIndicatorTable, 1);
 },
 GetCalculatedIndicatorDivWidth: function (percent) {
  var progressWidth = ASPx.GetClearClientWidth(this.GetMainCell());
  var indicatorDivStyle = ASPx.GetCurrentStyle(this.GetIndicatorDiv());
  progressWidth -= ASPx.PxToInt(indicatorDivStyle.borderLeftWidth) + ASPx.PxToInt(indicatorDivStyle.borderRightWidth);
  return progressWidth / 100 * percent;
 },
 UpdateIndicators: function () {
  if(this.IsIndicatorDivWidthCorrectionRequired()) {
   this.SetCalculatedDivIndicatorWidth();
  } else {
   var percent = this.GetPercent();
   this.GetIndicatorDiv().style.width = percent < 0 ? 0 : percent + "%";
  }
  var container = this.GetValueIndicatorContainer();
  if(container)
   container.innerHTML = this.GetIndicatorText();
  if(this.accessibilityCompliant) {
   var percent = this.GetPercent();
   ASPx.Attr.SetAttribute(this.GetIndicatorDiv(), "aria-valuenow", percent);
  }
 },
 GetIndicatorText: function () {
  if(this.displayMode == ASPxClientProgressBarBase.DisplayMode.Custom)
   return this.GetCustomText();
  var indicatorValue = this.displayMode == ASPxClientProgressBarBase.DisplayMode.Position ? this.position : this.GetPercent();
  if(this.displayFormat != null)
   indicatorValue = ASPx.Formatter.Format(this.displayFormat, indicatorValue);
  if(this.displayMode == ASPxClientProgressBarBase.DisplayMode.Position)
   return indicatorValue;
  if(this.rtl && ASPx.CultureInfo.percentPattern == 0)
   return indicatorValue + " %";
  return indicatorValue + "%";
 },
 SetCalculatedDivIndicatorWidth: function () {
  this.GetIndicatorDiv().style.width = "0px";
  var indicatorWidth = this.GetCalculatedIndicatorDivWidth(this.GetPercent());
  if(indicatorWidth >= 0)
   this.GetIndicatorDiv().style.width = indicatorWidth + "px";
 },
 IsIndicatorDivWidthCorrectionRequired: function () {
  if(!ASPx.IsExistsElement(this.GetIndicatorDiv()))
   return false;
  var indicatorDivStyle = ASPx.GetCurrentStyle(this.GetIndicatorDiv());
  return ASPx.PxToInt(indicatorDivStyle.borderLeftWidth) > 0 || ASPx.PxToInt(indicatorDivStyle.borderRightWidth) > 0;
 },
 SetCustomDisplayFormat: function (value) {
  this.customDisplayFormat = value;
  this.UpdateIndicators();
 },
 GetDisplayText: function () {
  return this.GetIndicatorText();
 },
 GetCustomText: function () {
  if(this.displayFormat != null) {
   return this.customDisplayFormat
    .replace("{0}", ASPx.Formatter.Format(this.displayFormat, this.position))
    .replace("{1}", ASPx.Formatter.Format(this.displayFormat, this.minimum))
    .replace("{2}", ASPx.Formatter.Format(this.displayFormat, this.maximum));
  }
  else {
   return this.customDisplayFormat
    .replace("{0}", this.position)
    .replace("{1}", this.minimum)
    .replace("{2}", this.maximum);
  }
 },
 SetPosition: function (value) {
  this.position = Math.min(Math.max(value, this.minimum), this.maximum);
  this.UpdateIndicators();
 },
 SetMinMaxValues: function (minValue, maxValue) {
  var preparedMinValue = parseInt(minValue.toString(), 10);
  var preparedMaxValue = parseInt(maxValue.toString(), 10);
  if(isNaN(preparedMinValue))
   preparedMinValue = this.minimum;
  if(isNaN(preparedMaxValue))
   preparedMaxValue = this.maximum;
  if(preparedMaxValue > preparedMinValue) {
   this.maximum = preparedMaxValue;
   this.minimum = preparedMinValue;
   this.OnePercentValueUpdate();
   if(this.accessibilityCompliant) {
    var indicatorDiv = this.GetIndicatorDiv();
    ASPx.Attr.SetAttribute(indicatorDiv, "aria-valuemax", preparedMaxValue);
    ASPx.Attr.SetAttribute(indicatorDiv, "aria-valuemin", preparedMinValue);
   }
   this.SetPosition(this.position);
  }
 },
 GetPosition: function () {
  return this.position;
 },
 GetPercent: function () {
  if(this.minimum === this.maximum)
   return 0;
  return (this.position - this.minimum) / this.onePercentValue;
 }
});
ASPxClientProgressBarBase.DisplayMode = {
 Percentage: 0,
 Position: 1,
 Custom: 2
};
window.ASPxClientProgressBarBase = ASPxClientProgressBarBase;
})();

(function () {
var ASPxClientPopupMenu = ASPx.CreateClass(ASPxClientMenuBase, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.skipNextPEMouseOutBeforePEMouseOver = false; 
  this.cursorOverPopupElement = false;
  this.isPopupMenu = true;
  this.closeAction = "OuterMouseClick";
  this.popupAction = "RightMouseClick";
  this.popupElementIDList = [];
  this.popupElementList = [];
  this.lastUsedPopupElementInfo = {};
  this.popupHorizontalOffset = 0;
  this.popupVerticalOffset = 0;
  this.popupHorizontalAlign = ASPx.PopupUtils.NotSetAlignIndicator;
  this.popupVerticalAlign = ASPx.PopupUtils.NotSetAlignIndicator;
  this.isPopupFullCorrectionOn = true;
  this.left = 0;
  this.top = 0;
 },
 Initialize: function () {
  this.RemoveAllPopupElements();
  this.PopulatePopupElements();
  ASPxClientMenuBase.prototype.Initialize.call(this);
 },
 SetPopupElementReference: function (popupElement, popupElementIndex, attach) {
  if(!ASPx.IsExistsElement(popupElement)) return;
  var setReferenceFunction = attach ? ASPx.Evt.AttachEventToElement : ASPx.Evt.DetachEventFromElement;
  var setContextMenuReferenceFunction = attach ? ASPx.Evt.AttachContextMenuToElement : ASPx.Evt.DetachContextMenuFromElement;
  if(this.closeAction == "MouseOut" || this.popupAction == "MouseOver") {
   setReferenceFunction(popupElement, "mouseover", ASPx.PopupUtils.OverControl.OnMouseOver);
   setReferenceFunction(popupElement, "mouseout", ASPx.PopupUtils.OverControl.OnMouseOut);
  }
  if(this.popupAction == "RightMouseClick")
   setContextMenuReferenceFunction(popupElement, aspxPMOnMouseUp);
  else if(this.popupAction == "LeftMouseClick")
   setReferenceFunction(popupElement, "mouseup", aspxPMOnMouseUp);
  if(attach) {
   popupElement.DXPopupElementControl = this;
   popupElement.DXPopupElementIndex = popupElementIndex;
  } else
   popupElement.DXPopupElementControl = popupElement.DXPopupElementIndex = undefined;
 },
 GetPopupElement: function (indexPopupElement) {
  var popupElement = this.popupElementList[indexPopupElement];
  return popupElement ? popupElement : null;
 },
 GetLastShownPopupElementIndex: function () {
  return ASPx.GetDefinedValue(this.lastUsedPopupElementInfo.shownPEIndex, 0);
 },
 SetLastShownPopupElementIndex: function (popupElementIndex) {
  this.lastUsedPopupElementInfo.shownPEIndex = popupElementIndex;
 },
 GetLastOverPopupElementIndex: function () {
  return ASPx.GetDefinedValue(this.lastUsedPopupElementInfo.overPEIndex, -1);
 },
 SetLastOverPopupElementIndex: function (popupElementIndex) {
  this.lastUsedPopupElementInfo.overPEIndex = popupElementIndex;
 },
 PopulatePopupElementsByIds: function() {
  var ids = this.popupElementIDList;
  for(var i = 0; i < ids.length; i++) {
   var popupElement = ASPx.PopupUtils.FindPopupElementById(ids[i]);
   if(popupElement)
    this.AddPopupElement(popupElement);
  }
 },
 PopulatePopupElements: function() {
  this.PopulatePopupElementsByIds();
 },
 AddPopupElement: function (popupElement) {
  var popupElementIndex = this.AddPopupElementInternal(popupElement);
  this.SetPopupElementReference(popupElement, popupElementIndex, true);
 },
 RemovePopupElement: function (popupElement) {
  this.RemovePopupElementInternal(popupElement);
  this.SetPopupElementReference(popupElement, null, false);
 },
 AddPopupElementInternal: function (element) {
  for(var i = 0; i < this.popupElementList.length; i++) {
   if(!this.popupElementList[i]) {
    this.popupElementList[i] = element;
    return i;
   }
  }
  this.popupElementList.push(element);
  return this.popupElementList.length - 1;
 },
 RemovePopupElementInternal: function (element) {
  for(var i = 0; i < this.popupElementList.length; i++) {
   if(this.popupElementList[i] == element) {
    this.popupElementList[i] = null;
    return;
   }
  }
 },
 RemoveAllPopupElements: function () {
  for(var i = 0; i < this.popupElementList.length; i++)
   this.RemovePopupElement(this.popupElementList[i]);
 },
 IsMenuVisible: function () {
  var element = this.GetMainElement();
  return (element != null) ? ASPx.GetElementDisplay(element) : false;
 },
 IsVisible: function () {
  return this.isShowing || this.IsMenuVisible();
 },
 IsParentElementPositionStatic: function (indexPath) {
  return false;
 },
 GetPopupAbsoluteX: function(pos) {
  return ASPx.PopupUtils.GetPopupAbsoluteX(this.GetMenuMainElement(this.GetMainElement()), this.GetPopupElement(this.GetLastShownPopupElementIndex()), this.popupHorizontalAlign, this.popupHorizontalOffset, pos, this.left, this.rtl, this.isPopupFullCorrectionOn);
 },
 GetPopupAbsoluteY: function(pos) {
  return popupPosition = ASPx.PopupUtils.GetPopupAbsoluteY(this.GetMenuMainElement(this.GetMainElement()),
   this.GetPopupElement(this.GetLastShownPopupElementIndex()), this.popupVerticalAlign, this.popupVerticalOffset, pos, this.top, this.isPopupFullCorrectionOn, false);
 },
 GetClientSubMenuPos: function (element, indexPath, pos, isVertical, isXPos) {
  if(indexPath == "") {
   var popupPosition = null;
   if(isXPos) {
    popupPosition = this.GetPopupAbsoluteX(pos);
   }
   else {
    popupPosition = this.GetPopupAbsoluteY(pos);
   }
   var scrollEnabled = this.scrollInfo.length > 0;
   if (!scrollEnabled && !isXPos)
    popupPosition.position = ASPx.PopupUtils.AdjustPositionToClientScreen(element, popupPosition.position, this.rtl, isXPos); 
   popupPosition.position -= ASPx.GetPositionElementOffset(element, isXPos);
   return popupPosition;
  }
  return ASPxClientMenuBase.prototype.GetClientSubMenuPos.call(this, element, indexPath, pos, isVertical, isXPos);
 },
 OnItemOverTimer: function (indexPath) {
  ASPx.GetMenuCollection().ClearCurrentShowingPopupMenuName();
  if(indexPath == "") {
   ASPx.GetMenuCollection().DoHidePopupMenus(null, -1, this.name, false, "");
   ASPx.GetMenuCollection().DoShowAtCurrentPos(this.name, indexPath);
  }
  else
   ASPxClientMenuBase.prototype.OnItemOverTimer.call(this, indexPath);
 },
 DoShow: function (x, y) {
  var element = this.GetMainElement();
  if(element != null && !ASPx.GetElementDisplay(element)) {
   ASPx.GetMenuCollection().DoHidePopupMenus(null, -1, this.name, false, "");
   if(!this.isInitialized)
    this.PopulatePopupElements();
   this.isShowing = true;
   this.DoShowPopupMenu(element, x, y, "");
   this.isShowing = false;
   this.EnsurePostponedHide();
   var link = this.GetAccessibilityLink(element);
   if(link) this.Focus();
  }
 },
 EnsurePostponedHide: function() {
  if(this.postponedHide) {
   this.Hide();
   this.postponedHide = false;
  }
 },
 GetAccessibilityLink: function(element) {
  return ASPx.GetNodeByClassName(element, ASPx.AccessibilityMarkerClass);
 },
 ShowPopupSubMenuAfterCallback: function (element, callbackResult) {
  this.SetSubMenuInnerHtml(element, callbackResult);
  var indexPath = this.GetIndexPathById(element.id, true);
  var scrollHelper = this.scrollHelpers[indexPath];
  if(scrollHelper) {
   element.style.height = "";
   this.PrepareScrolling(element, scrollHelper, ASPx.PxToInt(element.style.top));
  }
  ASPx.GetControlCollection().AdjustControls(element);
 },
 WrongEventOrderOperaHack: function () {
  this.skipNextPEMouseOutBeforePEMouseOver = true;
 },
 WrongEventOrderOperaRollBack: function () {
  this.skipNextPEMouseOutBeforePEMouseOver = false;
 },
 OnAfterItemOver: function (hoverItem, hoverElement) {
  var afterItemOverAllowed = ASPxClientMenuBase.prototype.AfterItemOverAllowed(this, hoverItem);
  if(afterItemOverAllowed) {
   this.WrongEventOrderOperaHack();
   ASPxClientMenuBase.prototype.OnAfterItemOver.call(this, hoverItem, hoverElement);
  }
 },
 OnPopupElementMouseOver: function (evt, popupElement) {
  if(popupElement != null) {
   if(popupElement.DXPopupElementIndex == this.GetLastShownPopupElementIndex())
    this.cursorOverPopupElement = true;
   this.WrongEventOrderOperaRollBack();
   if(this.popupAction == "MouseOver") {
    var isVisible = this.IsMenuVisible();
    if(popupElement.DXPopupElementIndex != this.GetLastOverPopupElementIndex()) {
     this.ClearDisappearTimer();
     this.ClearAppearTimer();
     if(isVisible) {
      this.Hide();
      isVisible = false;
     }
    }
    if(!isVisible) {
     ASPx.GetMenuCollection().SetCurrentShowingPopupMenuName(this.name);
     this.ShowInternal(evt, popupElement.DXPopupElementIndex);
    }
    this.SetLastOverPopupElementIndex(popupElement.DXPopupElementIndex);
   }
  }
 },
 OnPopupElementMouseOut: function (evt, popupElement) {
  if(popupElement != null) {
   ASPx.GetMenuCollection().ClearCurrentShowingPopupMenuName();
   this.cursorOverPopupElement = false;
   var eventFiredBecauseOfOverlayingPopup = this.closeAction === "MouseOut" && evt.toElement === this.GetMainElement();
   if(!this.IsMenuVisible())
    this.ClearAppearTimer();
   else if(!this.skipNextPEMouseOutBeforePEMouseOver && !eventFiredBecauseOfOverlayingPopup)
    this.SetDisappearTimer();
  }
 },
 DoShowPopupMenuBorderCorrector: function (element, x, y, indexPath, toTheLeft, toTheTop) {
  if(indexPath != "")
   ASPxClientMenuBase.prototype.DoShowPopupMenuBorderCorrector.call(this, element, x, y, indexPath, toTheLeft, toTheTop);
 },
 ShowInternal: function (evt, popupElementIndex) {
  this.SetLastShownPopupElementIndex(popupElementIndex);
  if(evt.type == "mouseover")
   ASPx.GetMenuCollection().SetAppearTimer(this.name, "", this.appearAfter);
  else {
   var coords = this.getEventCoordinates(evt);
   this.DoShow(coords.x, coords.y);
  }
 },
 getEventCoordinates: function(evt) {
  var result = { x: 0, y: 0 };
  result.x = ASPx.Evt.GetEventX(evt);
  result.y = ASPx.Evt.GetEventY(evt);
  if(this.accessibilityCompliant && result.x === 0 && result.y === 0)
   result = this.getEventSourceCoordinates(evt);
  return result;
 },
 getEventSourceCoordinates: function(evt) {
  var result = { x: 0, y: 0 };
  var eventSource = ASPx.Evt.GetEventSource(evt);
  if(!ASPx.IsExistsElement(eventSource))
   return result;
  var elementRect = eventSource.getBoundingClientRect();
  result.x = elementRect.left + elementRect.width/2;
  result.y = elementRect.top + elementRect.height/2;
  return result;
 },
 GetAnimationHorizontalDirection: function (indexPath, popupPosition) {
  if(this.GetMenuLevel(indexPath) == 0)
   return ASPx.PopupUtils.GetAnimationHorizontalDirection(popupPosition, this.popupHorizontalAlign, this.popupVerticalAlign, this.rtl);
  else
   return popupPosition.isInverted ? 1 : -1;
 },
 GetAnimationVerticalDirection: function (indexPath, popupPosition) {
  if(this.GetMenuLevel(indexPath) == 0)
   return ASPx.PopupUtils.GetAnimationVerticalDirection(popupPosition, this.popupHorizontalAlign, this.popupVerticalAlign);
  else
   return 0;
 },
 OnHideByItemOut: function () {
  if(this.closeAction == "MouseOut" && !this.cursorOverPopupElement)
   this.Hide();
  else
   ASPxClientMenuBase.prototype.OnHideByItemOut.call(this);
 },
 SetPopupElementID: function (popupElementId) {
  this.RemoveAllPopupElements();
  this.popupElementIDList = popupElementId.split(';');
  if(this.closeAction == "MouseOut") {
   this.ClearDisappearTimer();
   this.Hide();
  }
  this.PopulatePopupElements();
  this.WrongEventOrderOperaRollBack();
 },
 GetCurrentPopupElementIndex: function () {
  var popupElement = this.GetCurrentPopupElement();
  return popupElement ? popupElement.DXPopupElementIndex : -1;
 },
 GetCurrentPopupElement: function () {
  var popupElement = this.GetPopupElement(this.GetLastShownPopupElementIndex());
  if(popupElement && popupElement.DXPopupElementControl)
   return popupElement;
  return null;
 },
 RefreshPopupElementConnection: function () {
  this.RemoveAllPopupElements();
  this.PopulatePopupElements();
 },
 Hide: function() {
  if(this.isShowing) {
   this.postponedHide = true;
   return;
  }
  ASPx.GetMenuCollection().DoHidePopupMenus(null, -1, this.name, false, "");
 },
 Show: function (popupElementIndex) {
  if(this.GetPopupElement(popupElementIndex) != null)
   this.SetLastShownPopupElementIndex(popupElementIndex);
  this.DoShow(ASPx.InvalidPosition, ASPx.InvalidPosition);
 },
 ShowAtElement: function (htmlElement) {
  this.SetLastShownPopupElementIndex(this.AddPopupElementInternal(htmlElement));
  this.DoShow(ASPx.InvalidPosition, ASPx.InvalidPosition);
  this.RemovePopupElementInternal(htmlElement);
 },
 ShowAtElementByID: function (id) {
  var htmlElement = document.getElementById(id);
  this.ShowAtElement(htmlElement);
 },
 ShowAtPos: function (x, y) {
  var lastIndexBackup = this.GetLastShownPopupElementIndex();
  this.SetLastShownPopupElementIndex(-1);
  this.DoShow(x, y);
  this.SetLastShownPopupElementIndex(lastIndexBackup);
 },
 GetVisible: function () {
  return this.IsMenuVisible();
 },
 SetVisible: function (visible) {
  if(visible && !this.IsMenuVisible())
   this.Show();
  else if(!visible && this.IsMenuVisible())
   this.Hide();
 }
});
ASPx.Ident.scripts.ASPxClientPopupMenu = true;
var ASPxClientPopupMenuExt = ASPx.CreateClass(ASPxClientPopupMenu, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
 },
 NeedCreateItemsOnClientSide: function() {
  return true;
 },
 AddItemAdditionalImageClassName: function(indexPath) {  
  var itemImage = this.GetItemImage(indexPath);
  if(!itemImage) {
   itemImage = this.getSvgElement(indexPath);
   if(itemImage) {
    itemImage.className.baseVal += " " + ASPx.MenuItemClasses.SmallImage;
   }
  }
  else {
   itemImage.className += " " + ASPx.MenuItemClasses.SmallImage;
  }
 }
});
ASPxClientPopupMenu.Cast = ASPxClientControl.Cast;
function aspxPMOnMouseUp(evt, element) {
 var element = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupMenuElement);
 if(element == null || !element.DXPopupElementControl.isPopupMenu)
  return;
 var elementPopupAction = element.DXPopupElementControl.popupAction;
 switch (elementPopupAction) {
  case "LeftMouseClick":
   if(!ASPx.Evt.IsLeftButtonPressed(evt)) return;
   break;
  case "RightMouseClick":
   ASPx.PopupUtils.PreventContextMenu(evt);
 }
 ASPx.GetMenuCollection().ClearDisappearTimer();
 element.DXPopupElementControl.ShowInternal(evt, element.DXPopupElementIndex);
 return ASPx.Evt.CancelBubble(evt);
}
function aspxTestPopupMenuElement(element) {
 return !!element.DXPopupElementControl;
}
ASPx.Evt.AttachEventToDocument("mousemove", aspxPopupMenuDocumentMouseMove);
function aspxPopupMenuDocumentMouseMove(evt) {
 var element = ASPx.PopupUtils.FindEventSourceParentByTestFunc(evt, aspxTestPopupMenuElement);
 if(element != null)
  ASPx.GetMenuCollection().SaveCurrentMouseOverPos(evt, element);
}
window.ASPxClientPopupMenu = ASPxClientPopupMenu;
window.ASPxClientPopupMenuExt = ASPxClientPopupMenuExt;
})();

(function() {
ASPx.currentDragHelper = null;
var currentCursorTargets = null;
var DragHelper = ASPx.CreateClass(null, {
 constructor: function(e, root, clone){
  if(ASPx.currentDragHelper != null) ASPx.currentDragHelper.cancelDrag();
  this.dragArea = 5;
  this.clickX = ASPx.Evt.GetEventX(e);
  this.clickY = ASPx.Evt.GetEventY(e);
  this.centerClone = false;
  this.cachedCloneWidth = -1;
  this.cachedCloneHeight = -1;
  this.cachedOriginalX = -1;
  this.cachedOriginalY = -1;
  this.canDrag = true; 
  if(typeof(root) == "string") 
   root = ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(e), root);
  this.source = e ? ASPx.Evt.GetEventSource(e) : null;
  this.obj = root && root != null ? root : ASPx.Evt.GetEventSource(e);
  this.clone = clone;
  this.dragObj = null; 
  this.additionalObj = null;
  this.onDoClick = null;
  this.onEndDrag = null;
  this.onCancelDrag = null;
  this.onDragDivCreating = null;
  this.onDragDivCreated = null;
  this.onCloneCreating = null;
  this.onCloneCreated = null;
  this.dragDiv = null;
  ASPx.currentDragHelper = this;
  this.clearSelectionOnce = false;
  this.PreventContextMenuOnLongTap();
  ASPx.TouchUIHelper.startPreventingTouchMove();
 }, 
 drag: function(e) {
  if(!this.canDrag) return;
  ASPx.Selection.Clear();
  if(!this.isDragging()) {
   if(!this.isOutOfDragArea(e)) 
    return;
   this.startDragCore(e);
  }
  ASPx.Selection.SetElementSelectionEnabled(document.body, false);
  this.dragCore(e);
 },
 startDragCore: function(e) {  
  this.dragObj = this.clone != true ? this.obj : this.createClone(e);
 },
 dragCore: function(e) { 
  this.updateDragDivPosition(e);
 },
 endDrag: function(e) { 
  if(!this.isDragging() && !this.isOutOfDragArea(e)) {
   if(this.onDoClick)
    this.onDoClick(this, e);
  } else {
   if(this.onEndDrag)
    this.onEndDrag(this, e);
  }
  this.cancelDrag();
 },
 cancel: function(){
  this.cancelDrag();
 },
 cancelDrag: function() {
  ASPx.TouchUIHelper.stopPreventingTouchMove();
  if(this.dragDiv != null) {
   document.body.removeChild(this.dragDiv);
   this.dragDiv = null;
  }
  if(this.onCancelDrag)
   this.onCancelDrag(this);
  ASPx.currentDragHelper = null;
  ASPx.Selection.SetElementSelectionEnabled(document.body, true);
 },
 isDragging: function() {    
  return this.dragObj != null;
 },
 updateDragDivPosition: function(e) {
  if(this.centerClone) {
   this.dragDiv.style.left = ASPx.Evt.GetEventX(e) - this.cachedCloneWidth / 2 + "px";
   ASPx.SetAbsoluteY(this.dragDiv, ASPx.Evt.GetEventY(e) - this.cachedCloneHeight / 2);
  } else {
   this.dragDiv.style.left = this.cachedOriginalX + ASPx.Evt.GetEventX(e) - this.clickX + "px";
   ASPx.SetAbsoluteY(this.dragDiv, this.cachedOriginalY + ASPx.Evt.GetEventY(e) - this.clickY);
  }
 },
 createClone: function(e) {
  this.dragDiv = document.createElement("div");
  if(this.onDragDivCreating)
   this.onDragDivCreating(this, this.dragDiv);
  var clone = this.creatingClone();  
  this.dragDiv.appendChild(clone);
  document.body.appendChild(this.dragDiv);
  this.dragDiv.style.position = "absolute";
  this.dragDiv.style.top = "0";
  this.dragDiv.style.left = "0";
  this.dragDiv.style.cursor = "move";
  this.dragDiv.style.borderStyle = "none";
  this.dragDiv.style.padding = "0";
  this.dragDiv.style.margin = "0";
  this.dragDiv.style.backgroundColor = "transparent";
  this.dragDiv.style.zIndex = 20000; 
  if(this.onCloneCreated)
   this.onCloneCreated(clone);
  this.cachedCloneWidth = clone.offsetWidth;
  this.cachedCloneHeight = clone.offsetHeight;
  if(!this.centerClone) {  
   this.cachedOriginalX = ASPx.GetAbsoluteX(this.obj);
   this.cachedOriginalY = ASPx.GetAbsoluteY(this.obj);
  }
  this.dragDiv.style.width = this.cachedCloneWidth + "px";
  this.dragDiv.style.height = this.cachedCloneHeight + "px";
  if(this.onDragDivCreated)
   this.onDragDivCreated(this, this.dragDiv);
  this.updateDragDivPosition(e);
  return this.dragDiv;
 },
 creatingClone: function() {
  var clone = this.obj.cloneNode(true);
  var scripts = ASPx.GetNodesByTagName(clone, "SCRIPT");
  for(var i = scripts.length - 1; i >= 0; i--)
   ASPx.RemoveElement(scripts[i]);
  ASPx.RippleHelper.RemoveRippleContainer(clone);
  if(!this.onCloneCreating) return clone;
  return this.onCloneCreating(clone);
 },
 addElementToDragDiv: function(element) {
  if(this.dragDiv == null) return;
  this.additionalObj = element.cloneNode(true);
  this.additionalObj.style.visibility = "visible";
  this.additionalObj.style.display = "";
  this.additionalObj.style.top = "";
  this.dragDiv.appendChild(this.additionalObj);
 },
 removeElementFromDragDiv: function() {
  if(this.additionalObj == null || this.dragDiv == null) return;
  this.dragDiv.removeChild(this.additionalObj);
  this.additionalObj = null;
 },
 isOutOfDragArea: function(e) {
  return Math.max(
   Math.abs(ASPx.Evt.GetEventX(e) - this.clickX), 
   Math.abs(ASPx.Evt.GetEventY(e) - this.clickY)
  ) >= this.dragArea;
 },
 PreventContextMenuOnLongTap: function() {
  if(!ASPx.DragUtils.RequirePreventContextMenuOnLongTap(this.obj))
   return;
  this.contextMenuHandler = function(e) {
   ASPx.Evt.DetachEventFromElement(this.obj, "contextmenu", this.contextMenuHandler);
   ASPx.Evt.PreventEvent(e);
  }.bind(this);
  ASPx.Evt.AttachEventToElement(this.obj, "contextmenu", this.contextMenuHandler);
 }
});
var DragUtils = {
 PreventContextMenuOnLongTapMarker: "dxPCM",
 RequirePreventContextMenuOnLongTap: function(element) {
  return element && ASPx.ElementHasCssClass(element, this.PreventContextMenuOnLongTapMarker);
 },
 PreventContextMenuOnLongTap: function(element) {
  if(element && ASPx.Browser.Edge && ASPx.Browser.MSTouchUI) {
   ASPx.AddClassNameToElement(element, this.PreventContextMenuOnLongTapMarker);
  }
 }
};
var CursorTargetTag = { Right: 0, Left: 1, Top: 2, Bottom: 3 };
var CursorTargets = ASPx.CreateClass(null, {
 constructor: function(control) {
  this.control = control;
  this.list = [];
  this.oldtargetElement = null;
  this.oldtargetTag = CursorTargetTag.Right;
  this.targetElement = null;
  this.targetTag = CursorTargetTag.Right;
  this.x = 0;
  this.y = 0;
  this.onTargetCreated = null;
  this.onTargetChanging = null;
  this.onTargetChanged = null;
  this.onTargetAdding = null;
  this.onTargetAllowed = null;
  currentCursorTargets = this;
  this.treeLine = null;
  this.initialScrollOffsetInfo = this.GetParentElementsScrollOffsetInfo();
 },
 addElement: function(element) {
  if(!this.canAddElement(element)) return null;
  var target = new CursorTarget(element);
  if (this.onTargetCreated)
   this.onTargetCreated(this, target);
  this.list.push(target);
  return target;
 },
 removeElement: function(element) {
  for(var i = 0; i < this.list.length; i++) {
   if(this.list[i].element == element) {
    this.list.splice(i, 1);
    return;
   }
  }
 },
 addParentElement: function(parent, child) {
  var target = this.addElement(parent);
  if(target != null) {
   target.targetElement = child;
  }
  return target;
 },
 RegisterTargets: function(element, idPrefixArray) {
  this.addFunc = this.addElement;
  this.RegisterTargetsCore(element, idPrefixArray);
 },
 UnregisterTargets: function(element, idPrefixArray) {
  this.addFunc = this.removeElement;
  this.RegisterTargetsCore(element, idPrefixArray);
 },
 RegisterTargetsCore: function(element, idPrefixArray) {
  if(element == null) return;
  for(var i = 0; i < idPrefixArray.length; i++)
   this.RegisterTargetCore(element, idPrefixArray[i]);
 },
 RegisterTargetCore: function(element, idPrefix) {
  if(!ASPx.IsExists(element.id)) return;
  if(element.id.indexOf(idPrefix) > -1)
   this.addFunc(element);
  for(var i = 0; i < element.childNodes.length; i++)
   this.RegisterTargetCore(element.childNodes[i], idPrefix);
 },
 canAddElement: function(element) {
  if(element == null || !ASPx.GetElementDisplay(element))
   return false;
  for(var i = 0; i < this.list.length; i++) {
   if(this.list[i].targetElement == element) return false;
  }
  if(this.onTargetAdding != null && !this.onTargetAdding(this, element)) return false;
  return element.style.visibility != "hidden";
 },
 getTarget: function(x, y) {
  for(var i = 0; i < this.list.length; i++) {
   var record = this.list[i];
   if(record.contains(x, y)) {
    if(!this.onTargetAllowed || this.onTargetAllowed(record.targetElement, x, y))
     return record.targetElement;
   }
  }
  return null;
 },
 targetChanged: function(element, tag) {
  this.targetElement = element;
  this.targetTag = ASPx.IsExists(tag) ? tag : ASPx.CursorTargetTag.Right;
  if(this.onTargetChanging)
   this.onTargetChanging(this);
  if(this.oldtargetElement != this.targetElement || this.oldtargetTag != this.targetTag) {
   if(this.onTargetChanged)
    this.onTargetChanged(this);
   this.oldtargetElement = this.targetElement;
   this.oldtargetTag = this.targetTag;
  }
 },
 cancelChanging: function() {
  this.targetElement = this.oldtargetElement;
  this.targetTag = this.oldtargetTag;
 },
 refreshTargetTag: function(allowVerticalTags){
  this.targetTag = this.calculateTargetTag(allowVerticalTags);
 },
 calculateTargetTag: function(allowVerticalTags){
  if(allowVerticalTags && this.isCenterPartOfElement())
   return this.isTopPartOfElement() ? CursorTargetTag.Top : CursorTargetTag.Bottom;
  return this.isLeftPartOfElement() ? CursorTargetTag.Left : CursorTargetTag.Right;
 },
 isCenterPartOfElement: function(){
  if(!this.targetElement) return false;
  var coordinate = this.y - this.targetElementY();
  return coordinate < this.targetElement.offsetHeight / 3 || coordinate >  2 * this.targetElement.offsetHeight / 3;
 },
 isLeftPartOfElement: function() {
  if(!this.targetElement) return true;
  var left = this.x - this.targetElementX();
  return left < this.targetElement.offsetWidth / 2;
 },
 isTopPartOfElement: function() {
  if(!this.targetElement) return true;
  var top = this.y - this.targetElementY();
  return top < this.targetElement.offsetHeight / 2;
 },
 targetElementX: function() {
  return this.targetElement != null ? ASPx.GetAbsoluteX(this.targetElement) : 0;
 },
 targetElementY: function() {
  return this.targetElement != null ? ASPx.GetAbsoluteY(this.targetElement) : 0;
 },
 onmousemove: function(e) {
  this.doTargetChanged(e);
 },
 onmouseup: function(e) {
  this.doTargetChanged(e);
  currentCursorTargets = null;
 },
 doTargetChanged: function(e) {
  this.x = ASPx.Evt.GetEventX(e);
  this.y = ASPx.Evt.GetEventY(e);
  var coords = this.GetScrollOffsetCoordinates(this.x, this.y);
  this.targetChanged(this.getTarget(coords.x, coords.y), 0);
 },
 GetScrollOffsetCoordinates: function(x, y) {
  var scrollOffsetInfo = this.GetParentElementsScrollOffsetInfo();
  var dx = scrollOffsetInfo.left - this.initialScrollOffsetInfo.left;
  var dy = scrollOffsetInfo.top - this.initialScrollOffsetInfo.top;
  return {
   x : x + dx,
   y : y + dy
  };
 },
 GetParentElementsScrollOffsetInfo: function() {
  var result = { top : 0, left : 0 };
  var treeLine = this.GetScrollableElementsTreeLine();
  for(var i = 0; i < treeLine.length; i++) {
   result.top += treeLine[i].scrollTop;
   result.left += treeLine[i].scrollLeft;
  }
  return result;
 },
 GetScrollableElementsTreeLine: function() {
  if(!this.treeLine)
   this.treeLine = ASPx.GetElementTreeLine(this.control.GetMainElement().parentNode).filter(function(el) { 
    return ASPx.IsScrollableElement(el); 
   });
  return this.treeLine;
 }
});
var CursorTarget = ASPx.CreateClass(null, {
 constructor: function(element) {
  this.element = element;
  this.targetElement = element;
  this.UpdatePosition();
 },
 contains: function(x, y) {
  return x >= this.absoluteX && x <= this.absoluteX + this.GetElementWidth() &&
   y >= this.absoluteY && y <= this.absoluteY + this.GetElementHeight();
 },
 GetElementWidth: function() {
  return this.element.offsetWidth;
 },
 GetElementHeight: function() {
  return this.element.offsetHeight;
 },
 UpdatePosition: function() {
  this.absoluteX = ASPx.GetAbsoluteX(this.element);
  this.absoluteY = ASPx.GetAbsoluteY(this.element);
 }
});
if(ASPx.Browser.MSTouchUI)
 ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.pointerCancelEventName, function(e) {
  if(ASPx.currentDragHelper != null) {
   ASPx.currentDragHelper.cancel(e);
   return true;
  }
 });
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, function(e) {
  if(ASPx.currentDragHelper != null) {
   ASPx.currentDragHelper.endDrag(e);
   return true;
  }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, function(e) {
 if(ASPx.currentDragHelper != null && !(ASPx.Browser.WebKitTouchUI && ASPx.TouchUIHelper.isGesture)) {
  ASPx.currentDragHelper.drag(e);
  if(ASPx.TouchUIHelper.isTouchEvent(e) && ASPx.currentDragHelper.canDrag) {
   ASPx.Evt.PreventEvent(e);
   ASPx.TouchUIHelper.preventScrollOnEvent(e);
  }
  return true;
 }
});
ASPx.Evt.AttachEventToDocument("keydown", function(e) {
 if(!ASPx.currentDragHelper) return;
 if(e.keyCode == ASPx.Key.Esc)
  ASPx.currentDragHelper.cancelDrag();
 return true;
});
ASPx.Evt.AttachEventToDocument("keyup", function(e) {
 if (!ASPx.currentDragHelper) return;
 if(e.keyCode == ASPx.Key.Esc && ASPx.Browser.WebKitFamily)
  ASPx.currentDragHelper.cancelDrag();
 return true;
});
ASPx.Evt.AttachEventToDocument("selectstart", function(e) {
 var drag = ASPx.currentDragHelper;
 if(drag && (drag.canDrag || drag.clearSelectionOnce)) {
  ASPx.Selection.Clear();
  drag.clearSelectionOnce = false;
  ASPx.Evt.PreventEvent(e);
  return false;
 }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, function(e) { 
 if(currentCursorTargets != null) {
  currentCursorTargets.onmouseup(e);
  return true;
 }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, function(e) {
 if(currentCursorTargets != null) {
  currentCursorTargets.onmousemove(e);
  return true;
 }
});
ASPx.DragHelper = DragHelper;
ASPx.CursorTargets = CursorTargets;
ASPx.CursorTarget = CursorTarget;
ASPx.CursorTargetTag = CursorTargetTag;
ASPx.DragUtils = DragUtils;
})();

(function() {
var GridHeaderFilterMode = { List: 1, CheckedList: 2, DateRangePicker: 3, DateRangeCalendar: 4, NumericRangePicker: 5 };
var GridFilterHelper = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
  this.activeElement = null;
  this.lockFilter = true;
  this.searchFilterTimer = -1;
  this.searchEditorInitialValue = undefined;
  this.savedSearchEditorValue_beforeCallback = undefined;
  this.searchEditorLastClientValue = undefined;
  this.searchEditorValueChangedOnCallbackWaiting = false;
  this.initialHeaderFilterPopupMinWidth = null;
  this.headerFilterPopupWithButtonPanelMinWidth = null;
  this.headerFilterPopupRelatedColumn = null;
  this.headerFilterPopupDimensions = { };
  this.headerFilterColumnIndicesToInitialize = [ ];
  this.initialHeaderFilterState = { };
  this.SearchEditorKeyDownHandler = this.OnSearchEditorKeyDown.bind(this);
  this.SearchEditorValueChangedHandler = this.OnSearchEditorValueChanged.bind(this);
  this.SearchEditorUserInputHandler = this.OnSearchEditorUserInput.bind(this);
  this.HeaderFilterPopup_PopUpHandler = this.OnHeaderFilterPopup_PopUp.bind(this);
  this.HeaderFilterPopup_CloseUpHandler = this.OnHeaderFilterPopup_CloseUp.bind(this);
  this.HeaderFilterPopup_ResizeHandler = this.OnHeaderFilterPopup_Resize.bind(this);
  ASPx.GetControlCollection().ControlsInitialized.AddHandler(this.OnControlsInitialized, this);
 },
 Reset: function() {
  this.initialHeaderFilterState = { };
 },
 IsFilterLocked: function() { return this.lockFilter; },
 LockFilter: function() { this.lockFilter = true; },
 UnlockFilter: function() { this.lockFilter = false; },
 GetActiveElement: function() { return this.activeElement; },
 ResetActiveElement: function() { this.activeElement = null; },
 IsValidInstance: function() { return this.grid.IsValidInstance(); },
 GetAllowSearchFilterTimer: function() { return this.grid.allowSearchFilterTimer; },
 GetSearchFilterDelay: function() { return this.grid.searchFilterDelay; },
 GetEnableAccessibility: function() { return this.grid.accessibilityCompliant; },
 ResolveColumnIndex: function(id) { return this.grid.getColumnIndex(id); },
 GetSearchEditor: function() { return this.grid.GetSearchEditor(); },
 GetCustomSearchPanelEditor: function() { return this.grid.GetCustomSearchPanelEditor(); },
 GetSearchPanelFilter: function() { return this.grid.searchPanelFilter; },
 ApplySearchPanelFilter: function(value) { this.grid.ApplySearchPanelFilter(value, true); },
 GetContentTable: function() { return this.grid.GetMainTable(); },
 OnInit: function() {
  this.LockFilter();
  window.setTimeout(function() { this.UnlockFilter(); }.bind(this), 0);
  this.EnsureSearchEditor();
  window.setTimeout(function() { this.SaveFilterEditorsState(); }.bind(this), 0);
  window.setTimeout(this.InitializeHeaderFilterPopup.bind(this), 0);
 },
 OnAfterCallback: function() {
  this.LockFilter();
  window.setTimeout(function() { this.UnlockFilter(); }.bind(this), 0);
  this.EnsureSearchEditor();
  window.setTimeout(function() { this.SaveFilterEditorsState(); }.bind(this), 0);
  window.setTimeout(this.InitializeHeaderFilterPopup.bind(this), 0);
 },
 OnBeforeCallback: function() {
  this.LockFilter();
  this.UnloadHeaderFilterPopup();
  var edit = this.GetSearchEditor();
  if(edit)
   this.savedSearchEditorValue_beforeCallback = this.GetEditorStringValue(edit);
 },
 OnCancelCallbackCore: function() {
  this.UnlockFilter();
  this.InitializeHeaderFilterPopup();
 },
 SaveFilterEditorsState: function() { },
 ClearFilterEditorsState: function() { },
 OnDispose: function() {
  ASPx.GetControlCollection().ControlsInitialized.RemoveHandler(this.OnControlsInitialized, this);
 },
 LoadSearchEditorValueOnCallback: function() {
  var edit = this.GetSearchEditor();
  if(edit) {
   var value = this.GetEditorStringValue(edit);
   this.searchEditorValueChangedOnCallbackWaiting = value !== this.savedSearchEditorValue_beforeCallback;
   this.searchEditorLastClientValue = value;
   this.savedSearchEditorValue_beforeCallback = undefined;
  }
 },
 SetSearchPanelCustomEditor: function(editor) {
  if(!ASPx.Ident.IsASPxClientEdit(editor) || !editor.GetMainElement())
   return;
  if(this.grid.customSearchPanelEditorID === editor.name)
   return;
  this.RemoveSearchEditorEvents(this.GetSearchEditor());
  this.grid.customSearchPanelEditorID = editor.name;
  this.EnsureSearchEditor();
 },
 AssignSearchEditorEvents: function(edit) {
  if(edit.dxgvFilterHelper === this)
   return;
  if(edit.KeyDown)
   edit.KeyDown.AddHandler(this.SearchEditorKeyDownHandler);
  if(edit.ValueChanged)
   edit.ValueChanged.AddHandler(this.SearchEditorValueChangedHandler);
  if(edit.UserInput)
   edit.UserInput.AddHandler(this.SearchEditorUserInputHandler);
  edit.dxgvFilterHelper = this;
 },
 RemoveSearchEditorEvents: function(edit) {
  if(!edit || edit.dxgvFilterHelper !== this)
   return;
  if(edit.KeyDown)
   edit.KeyDown.RemoveHandler(this.SearchEditorKeyDownHandler);
  if(edit.ValueChanged)
   edit.ValueChanged.RemoveHandler(this.SearchEditorValueChangedHandler);
  if(edit.UserInput)
   edit.UserInput.RemoveHandler(this.SearchEditorUserInputHandler);
  delete edit.dxgvFilterHelper;
 },
 EnsureSearchEditor: function() {
  var edit = this.GetSearchEditor();
  if(!edit) return;
  this.AssignSearchEditorEvents(edit);
  var isCustomEditor = edit === this.GetCustomSearchPanelEditor();
  this.searchEditorInitialValue = isCustomEditor ? this.GetSearchPanelFilter() : this.GetEditorStringValue(edit);
  var applySearchValueOnCallback = this.searchEditorValueChangedOnCallbackWaiting && this.searchEditorInitialValue !== this.searchEditorLastClientValue;
  if(applySearchValueOnCallback) {
   window.setTimeout(function() {
    edit.SetValue(this.searchEditorLastClientValue);
    this.ApplySearchFilterFromEditor(edit);
   }.bind(this), 0);
  }  else {
   if(isCustomEditor)
    window.setTimeout(function() { edit.SetValue(this.GetSearchPanelFilter()); }.bind(this), 0);
  }
  this.searchEditorValueChangedOnCallbackWaiting = false;
 },
 GetEditorStringValue: function(edit) {
  var value = edit.GetValueString();
  return ASPx.IsExists(value) ? value : "";
 },
 OnSearchEditorKeyDown: function(s, e) {
  if(!e.htmlEvent || !this.IsValidInstance())
   return;
  e = e.htmlEvent;
  var clearEditor = e.keyCode == ASPx.Key.Delete && e.ctrlKey;
  if(e.keyCode == ASPx.Key.Enter || clearEditor) {
   if(clearEditor)
    s.SetValue(null);
   this.ApplySearchFilterFromEditor(s);
   ASPx.Evt.PreventEventAndBubble(e);
   return;
  }
  this.CreateSearchFilterTimer(s);
 },
 OnSearchEditorUserInput: function(s, e) {
  if(!this.IsValidInstance() || this.IsSearchFilterTimerActive())
   return;
  this.OnSearchEditorOnPaste(s);
 },
 OnSearchEditorOnPaste: function(editor) {
  this.EnsureEditorRawValue(editor);
  this.CreateSearchFilterTimer(editor);
 },
 OnSearchEditorValueChanged: function(s, e) {
  if(!this.IsValidInstance())
   return;
  window.setTimeout(function() { this.ApplySearchFilterFromEditor(s);  }.bind(this), 0);
 },
 IsSearchFilterTimerActive: function() {
  return this.searchFilterTimer !== -1;
 },
 CreateSearchFilterTimer: function(editor) {
  if(!this.GetAllowSearchFilterTimer()) return;
  this.ClearSearchFilterTimer();
  this.searchFilterTimer = window.setTimeout(function() { this.ApplySearchFilterFromEditor(editor);  }.bind(this), this.GetSearchFilterDelay());
 },
 ClearSearchFilterTimer: function() {
  this.searchFilterTimer = ASPx.Timer.ClearTimer(this.searchFilterTimer);
 },
 ApplySearchFilterFromEditor: function(edit) {
  this.ClearSearchFilterTimer();
  if(this.IsFilterLocked()) return;
  if(!edit || !this.GetContentTable())
   return;
  edit.Validate();
  if(!edit.GetIsValid()) 
   return;
  var value = this.GetEditorStringValue(edit);
  if(value === this.searchEditorInitialValue)
   return;
  this.SaveFilterEditorActiveElement(edit);
  this.ApplySearchPanelFilter(value);
 },
 EnsureEditorRawValue: function(edit) {
  if(ASPx.GetFocusedEditor() === edit && edit.SyncRawValueIfHasTextDecorators) {
   edit.SyncRawValueIfHasTextDecorators();
  }
 },
 SaveFilterEditorActiveElement: function(editor) {
  if(!editor) return;
  var columnIndex = this.ResolveColumnIndex(editor.name);
  if(columnIndex < 0 && editor !== this.GetSearchEditor())
   return;
  this.activeElement = this.GetFilterEditorInputElement(editor);
 },
 GetFilterEditorInputElement: function(editor) {
  if(document.activeElement && !ASPx.Browser.VirtualKeyboardSupported) 
   return document.activeElement;
  if(editor.GetInputElement) 
   return editor.GetInputElement();
  return null;
 },
 GetHeaderFilterPopup: function() { return this.grid.GetHeaderFilterPopup(); },
 GetEnableCallbackAnimation: function() { return this.grid.enableCallbackAnimation; },
 GetEnableHeaderFilterCaching: function() { return this.grid.enableHeaderFilterCaching; },
 GetHeaderFilterIconClassName: function() { return this.grid.HeaderFilterButtonClassName; }, 
 GetColumnHeaders: function(columnIndex) { return [ this.grid.GetHeader(columnIndex, false), this.grid.GetHeader(columnIndex, true) ]; },
 GetColumn: function(columnIndex) { return this.grid._getColumn(columnIndex); },
 GetColumnCount: function() { return this.grid.GetColumnsCount(); },
 ApplyHeaderFilter: function() { this.grid.ApplyHeaderFilterByColumn(); },
 GetCustomizationWindow: function() { return this.grid.GetCustomizationWindow(); },
 ShowLoadingPanelInsideHeaderFilterPopup: function() { this.grid.ShowLoadingPanelInsideHeaderFilterPopup(); },
 GetListBox: function(columnIndex) { 
  var listBox = ASPx.GetControlCollection().Get(this.grid.name + "_HFListBox" + columnIndex); 
  return listBox && !listBox.IsDOMDisposed() ? listBox : null;
 },
 GetSelectAllCheckBox: function(columnIndex) { 
  var checkBox = ASPx.GetControlCollection().Get(this.grid.name + "_HFSACheckBox" + columnIndex); 
  return checkBox && !checkBox.IsDOMDisposed() ? checkBox : null;
 },
 GetDateEdit_From: function(columnIndex) {
  var dateEdit = ASPx.GetControlCollection().Get(this.grid.name + "_HFFDE" + columnIndex); 
  return dateEdit && !dateEdit.IsDOMDisposed() ? dateEdit : null;
 },
 GetDateEdit_To: function(columnIndex) { 
  var dateEdit = ASPx.GetControlCollection().Get(this.grid.name + "_HFTDE" + columnIndex); 
  return dateEdit && !dateEdit.IsDOMDisposed() ? dateEdit : null;
 },
 GetCalendar: function(columnIndex){ 
  var calendar = ASPx.GetControlCollection().Get(this.grid.name + "_HFC" + columnIndex); 
  return calendar && !calendar.IsDOMDisposed() ? calendar: null;
 },
 GetSpinEdit_From: function(columnIndex) {
  var spinEdit = ASPx.GetControlCollection().Get(this.grid.name + "_HFFSE" + columnIndex);
  return spinEdit && !spinEdit.IsDOMDisposed() ? spinEdit : null;
 },
 GetSpinEdit_To: function(columnIndex) {
  var spinEdit = ASPx.GetControlCollection().Get(this.grid.name + "_HFTSE" + columnIndex);
  return spinEdit && !spinEdit.IsDOMDisposed() ? spinEdit : null;
 },
 GetRangeTrackBar: function(columnIndex) {
  var rangeTrackBar = ASPx.GetControlCollection().Get(this.grid.name + "_HFTB" + columnIndex);
  return rangeTrackBar && !rangeTrackBar.IsDOMDisposed() ? rangeTrackBar : null;
 },
 GetHeaderFilterPopupRelatedColumn: function() { return this.headerFilterPopupRelatedColumn; },
 GetHeaderFilterButton: function(isCancelButton) {
  var popup = this.GetHeaderFilterPopup();
  if(popup)
   return ASPx.GetControlCollection().Get(isCancelButton ? popup.cpCancelButtonID : popup.cpOkButtonID);
  return null;
 },
 SendHeaderFilterCallback: function(columnIndex, shiftKey) {
  this.grid.gridFuncCallBack([ ASPxClientGridViewCallbackCommand.FilterPopup, this.grid.name, columnIndex, shiftKey ? "T" : ""], this.OnHeaderFilterCallback);
 },
 OnHeaderFilterCallback: function(values) {
  var grid = ASPx.GetControlCollection().Get(values[0]);
  if(grid)
   grid.GetFilterHelper().ProcessHeaderFilterCallback(values[1], values[2]);
 },
 GetHeaderFilterState: function(columnIndex) {
  var listBoxSelectedIndices = [ ];
  var pickerRange = null;
  var calendarDates = null;
  var listBox = this.GetListBox(columnIndex);
  if(listBox)
   listBoxSelectedIndices = listBox.GetSelectedIndices();
  var column = this.GetColumn(columnIndex);
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker) {
   var dateEditFrom = this.GetDateEdit_From(columnIndex);
   var dateEditTo = this.GetDateEdit_To(columnIndex);
   if(dateEditFrom && dateEditTo)
    pickerRange = { start: dateEditFrom.GetValue(), end: dateEditTo.GetValue() };
  }
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangeCalendar) {
   var calendar = this.GetCalendar(columnIndex);
   if(calendar)
    calendarDates = calendar.GetSelectedDates();
  }
  if(column.HFMode === ASPx.GridHeaderFilterMode.NumericRangePicker) {
   var rangeTrackBar = this.GetRangeTrackBar(columnIndex);
   if(rangeTrackBar)
    pickerRange = { start: rangeTrackBar.GetPositionStart(), end: rangeTrackBar.GetPositionEnd() };
   var spinEdit_From = this.GetSpinEdit_From(columnIndex);
   if(spinEdit_From) {
    if(pickerRange) pickerRange.start = spinEdit_From.GetValue();
    else pickerRange = { start: spinEdit_From.GetValue() };
   }
   var spinEdit_To = this.GetSpinEdit_To(columnIndex);
   if(spinEdit_To) {
    if(pickerRange) pickerRange.end = spinEdit_To.GetValue();
    else pickerRange = { end: spinEdit_To.GetValue() };
   }
  }
  return { listBoxSelectedIndices: listBoxSelectedIndices, pickerRange: pickerRange, calendarDates: calendarDates };
 },
 IsHeaderFilterChanged: function(columnIndex) {
  var initialState = this.initialHeaderFilterState[columnIndex];
  var currentState = this.GetHeaderFilterState(columnIndex);
  if(!initialState || !currentState)
   return false;
  if(!ASPx.Data.ArrayEqual(initialState.listBoxSelectedIndices, currentState.listBoxSelectedIndices))
   return true;
  var column = this.GetColumn(columnIndex);
  if((column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker || column.HFMode === ASPx.GridHeaderFilterMode.NumericRangePicker) && currentState.pickerRange)
   return initialState.pickerRange.start !== currentState.pickerRange.start || initialState.pickerRange.end !== currentState.pickerRange.end;
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangeCalendar && currentState.calendarDates)
   return !ASPx.Data.ArrayEqual(initialState.calendarDates, currentState.calendarDates);
  return false;
 },
 GetHeaderFilterCallbackState: function(columnIndex) {
  var result = [ ];
  var listBox = this.GetListBox(columnIndex);
  if(listBox)
   result = result.concat(listBox.GetSelectedValues());
  var currentState = this.GetHeaderFilterState(columnIndex);
  if(currentState.calendarDates && currentState.calendarDates.length > 0)
   result.push("(Calendar)|" + this.CalcDateRanges(currentState.calendarDates, false).join("|"));
  if(currentState.pickerRange && (currentState.pickerRange.start || currentState.pickerRange.end)) {
   var column = this.GetColumn(columnIndex);
   var pickerType;
   var range;
   if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker) {
    pickerType = "(DateRangePicker)";
    range = [
     currentState.pickerRange.start && ASPx.DateUtils.GetInvariantDateString(currentState.pickerRange.start) || "",
     currentState.pickerRange.end   && ASPx.DateUtils.GetInvariantDateString(currentState.pickerRange.end) || ""
    ];
   }
   if(column.HFMode === ASPx.GridHeaderFilterMode.NumericRangePicker) {
    pickerType = "(NumericRangePicker)";
    range = [
     currentState.pickerRange.start && parseFloat(currentState.pickerRange.start) || "",
     currentState.pickerRange.end   && parseFloat(currentState.pickerRange.end) || ""
    ];
   }
   result.push(pickerType + "|" + range.join("|"));
  }
  return result;
 },
 ProcessHeaderFilterCallback: function(columnIndex, htmlObj) {
  this.headerFilterColumnIndicesToInitialize.push(parseInt(columnIndex));
  this.SetHeaderFilterPopupHtml(htmlObj, columnIndex);
 },
 SetHeaderFilterPopupHtml: function(htmlObj, columnIndex) {
  this.GetHeaderFilterPopup().SetContentHtml(htmlObj, this.GetEnableCallbackAnimation());
 },
 OnControlsInitialized: function() {
  for(var i = 0; i < this.headerFilterColumnIndicesToInitialize.length; i++)
   this.InitHeaderFilter(this.headerFilterColumnIndicesToInitialize[i]);
  this.headerFilterColumnIndicesToInitialize = [ ];
 },
 InitHeaderFilter: function(columnIndex) {
  this.initialHeaderFilterState[columnIndex] = this.GetHeaderFilterState(columnIndex);
  var column = this.GetColumn(columnIndex);
  this.headerFilterPopupRelatedColumn = column;
  this.InitializeListBox(column);
  if(column.HFMode === ASPx.GridHeaderFilterMode.CheckedList)
   this.InitializeSelectAllCheckBox(column);
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker)
   this.InitializeDateRangePicker(column);
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangeCalendar)
   this.InitializeCalendar(column);
  if(column.HFMode === ASPx.GridHeaderFilterMode.NumericRangePicker)
   this.InitializeNumericRangeEditors(column);
  if(this.GetEnableAccessibility())
   this.InitializeAccessibility(column);
 },
 InitializeListBox: function(column) {
  var listBox = this.GetListBox(column.index);
  if(!listBox) return;
  if(column.HFMode === ASPx.GridHeaderFilterMode.List && this.GetEnableAccessibility())
   listBox.ItemClick.AddHandler(this.OnListBoxSelectionChanged.bind(this));
  else {
   listBox.SelectedIndexChanged.AddHandler(this.OnListBoxSelectionChanged.bind(this));
   listBox.KeyDown.AddHandler(this.ProcessHeaderFilterKeyDown.bind(this));
  }
  var element = listBox.GetListTable ? listBox.GetListTable() : listBox.GetMainElement();
  ASPx.Evt.AttachEventToElement(element, "mousedown", function() { window.setTimeout(ASPx.Selection.Clear, 0); });
  listBox.gvColumn = column;
  if(listBox.cpFSI && listBox.cpFSI.length > 0)
   this.PrepareSeparators(listBox);
  if(this.IsListBoxHasScrolling())
   this.AdjustHeaderFilterListBox(column);
 },
 ProcessHeaderFilterKeyDown: function(listbox, args) {
  this.LockHeaderFilterApply();
  var evt = args.htmlEvent;
  if(evt.keyCode == ASPx.Key.Enter) {
   this.UnlockHeaderFilterApply();
   this.OnListBoxSelectionChanged(listbox);
  }
  window.setTimeout(this.UnlockHeaderFilterApply.bind(this), 100);
 },
 LockHeaderFilterApply: function() {
  this.lockHeaderFilterApply = true;
 },
 UnlockHeaderFilterApply: function() {
  this.lockHeaderFilterApply = false;
 },
 IsHeaderFilterApplyLocked: function() {
  return !!this.lockHeaderFilterApply;
 },
 AdjustHeaderFilterListBox: function(column) {
  var listBox = this.GetListBox(column.index);
  if(listBox && listBox.GetMainElement() && this.RequireShowHeaderFilterListBoxScrollbar(column)) {
   ASPx.SetStyles(listBox.GetMainElement(), { minHeight: this.GetHeaderFilterPopupScrollableElement().offsetHeight });
   listBox.AdjustControl();
  }
 },
 InitializeSelectAllCheckBox: function(column) {
  var checkBox = this.GetSelectAllCheckBox(column.index);
  if(!checkBox) return;
  checkBox.CheckedChanged.AddHandler(function(s) { this.OnSelectAllCheckedChanged(s); }.bind(this));
  checkBox.gvColumn = column;
 },
 InitializeDateRangePicker: function(column) {
  var dateEdit_From = this.GetDateEdit_From(column.index);
  var dateEdit_To = this.GetDateEdit_To(column.index);
  if(!dateEdit_From || !dateEdit_To)
   return;
  dateEdit_From.gvColumn = dateEdit_To.gvColumn = column;
  dateEdit_From.ValueChanged.AddHandler(this.OnEditChanged.bind(this));
  dateEdit_To.ValueChanged.AddHandler(this.OnEditChanged.bind(this));
  this.AdjustRangePicker(dateEdit_From, dateEdit_To);
 },
 InitializeNumericRangeEditors: function(column) {
  var spinEdit_From = this.GetSpinEdit_From(column.index);
  var spinEdit_To = this.GetSpinEdit_To(column.index);
  var rangeTrackBar = this.GetRangeTrackBar(column.index);
  if(spinEdit_From) {
   spinEdit_From.gvColumn = column;
   spinEdit_From.ValueChanged.AddHandler(function (s, e) {
    if(rangeTrackBar) rangeTrackBar.SetPositionStart(s.GetValue());
    this.OnEditChanged(s);
   }.bind(this));
  }
  if(spinEdit_To) {
   spinEdit_To.gvColumn = column;
   spinEdit_To.ValueChanged.AddHandler(function (s, e) {
    if(rangeTrackBar) rangeTrackBar.SetPositionEnd(s.GetValue());
    this.OnEditChanged(s);
   }.bind(this));
  }
  if(rangeTrackBar) {
   rangeTrackBar.gvColumn = column;
   rangeTrackBar.ValueChanged.AddHandler(function (s, e) {
    if(spinEdit_From) spinEdit_From.SetValue(s.GetPositionStart());
    if(spinEdit_To) spinEdit_To.SetValue(s.GetPositionEnd());
    this.OnEditChanged(s);
   }.bind(this));
  }
  if(!spinEdit_From || !spinEdit_To)
   return;
  this.AdjustRangePicker(spinEdit_From, spinEdit_To);
 },
 AdjustRangePicker: function(editor_From, editor_To) {
  var firstCaptionCell = editor_From.GetCaptionCell();
  var secondCaptionCell = editor_To.GetCaptionCell();
  var width = Math.max(ASPx.GetClearClientWidth(firstCaptionCell), ASPx.GetClearClientWidth(secondCaptionCell));
  ASPx.SetStyles(firstCaptionCell, { minWidth: width });
  ASPx.SetStyles(secondCaptionCell, { minWidth: width });
 },
 InitializeCalendar: function(column) {
  var calendar = this.GetCalendar(column.index);
  calendar.SelectionChanged.AddHandler(this.OnEditChanged.bind(this));
  calendar.gvColumn = column;
 },
 OnListBoxSelectionChanged: function(listBox) {
  if(!listBox) return;
  var column = listBox.gvColumn;
  if(this.RequireApplyHeaderFilterNow(column.HFMode, column.index))
   this.ApplyHeaderFilter();
  else {
   if(column.HFMode === ASPx.GridHeaderFilterMode.CheckedList)
    this.UpdateSelectAllCheckState(column.index);
   this.UpdateOkButtonEnabledState(column.index);
  }
 },
 OnSelectAllCheckedChanged: function(checkBox) {
  var columnIndex = checkBox.gvColumn.index;
  var listBox = this.GetListBox(columnIndex);
  if(checkBox.GetChecked())
   listBox.SelectAll();
  else
   listBox.UnselectAll();
  this.UpdateOkButtonEnabledState(columnIndex);
 },
 OnEditChanged: function(editor) {
  this.UpdateOkButtonEnabledState(editor.gvColumn.index);
 },
 RequireApplyHeaderFilterNow: function(mode, columnIndex) {
  return mode === ASPx.GridHeaderFilterMode.List && this.IsHeaderFilterChanged(columnIndex) && !this.IsHeaderFilterApplyLocked();
 },
 UpdateSelectAllCheckState: function(columnIndex) {
  var checkBox = this.GetSelectAllCheckBox(columnIndex);
  var listBox = this.GetListBox(columnIndex);
  if(!checkBox || !listBox) 
   return;
  var selectedItemCount = listBox.GetSelectedIndices().length;
  var checkState = ASPx.CheckBoxCheckState.Indeterminate;
  if(selectedItemCount === 0)
   checkState = ASPx.CheckBoxCheckState.Unchecked;
  else if(selectedItemCount === listBox.GetItemCount())
   checkState = ASPx.CheckBoxCheckState.Checked;
  checkBox.SetCheckState(checkState);
 },
 UpdateOkButtonEnabledState: function(columnIndex) {
  if(this.GetColumn(columnIndex).HFMode !== ASPx.GridHeaderFilterMode.List)
   this.SetHFOkButtonEnabled(this.IsHeaderFilterChanged(columnIndex));
 },
 ApplyHeaderFilterInitialState: function(columnIndex) {
  var state = this.initialHeaderFilterState[columnIndex];
  if(!state) return;
  var column = this.GetColumn(columnIndex);
  var listBox = this.GetListBox(columnIndex);
  if(listBox) {
   if(column.HFMode === ASPx.GridHeaderFilterMode.List) {
    if(this.GetEnableAccessibility() && state.listBoxSelectedIndices.length > 0)
     listBox.SelectIndex(state.listBoxSelectedIndices[0]);
   } else {
    listBox.UnselectAll();
    listBox.SelectIndices(state.listBoxSelectedIndices);
   }
  }
  if(column.HFMode === ASPx.GridHeaderFilterMode.CheckedList)
   this.UpdateSelectAllCheckState(columnIndex);
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker) {
   this.GetDateEdit_From(columnIndex).SetValue(state.pickerRange.start);
   this.GetDateEdit_To(columnIndex).SetValue(state.pickerRange.end);
  }
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangeCalendar) {
   var calendar = this.GetCalendar(columnIndex);
   calendar.SetValue(null);
   var dates = state.calendarDates || [ ];
   for(var i = 0; i < dates.length; i++)
    calendar.SelectDate(dates[i]);
  }
  if(column.HFMode === ASPx.GridHeaderFilterMode.NumericRangePicker) {
   var rangeTrackBar = this.GetRangeTrackBar(columnIndex);
   if(rangeTrackBar) {
    rangeTrackBar.SetPositionStart(state.pickerRange.start);
    rangeTrackBar.SetPositionEnd(state.pickerRange.end);
   }
   var spinEdit_From = this.GetSpinEdit_From(columnIndex);
   if(spinEdit_From)
    spinEdit_From.SetValue(state.pickerRange.start);
   var spinEdit_To = this.GetSpinEdit_To(columnIndex);
   if(spinEdit_To)
    spinEdit_To.SetValue(state.pickerRange.end);
  }
  this.SetHFOkButtonEnabled(false);
 },
 IsListBoxHasScrolling: function() { return true; }, 
 RequireShowHeaderFilterListBoxScrollbar: function(column) { return this.IsListBoxHasScrolling() && column && (column.HFMode === ASPx.GridHeaderFilterMode.List || column.HFMode === ASPx.GridHeaderFilterMode.CheckedList); },
 GetHeaderFilterPopupScrollableElement: function() { return this.GetHeaderFilterPopup().GetWindowContentElement(-1); },
 InitializeHeaderFilterPopup: function() {
  var popup = this.GetHeaderFilterPopup();
  if(!popup || !popup.GetWindowElement(-1))
   return;
  this.initialHeaderFilterPopupMinWidth = popup.GetWindowMinWidth();
  popup.PopUp.AddHandler(this.HeaderFilterPopup_PopUpHandler);
  popup.CloseUp.AddHandler(this.HeaderFilterPopup_CloseUpHandler);
  popup.Resize.AddHandler(this.HeaderFilterPopup_ResizeHandler);
  if(this.IsListBoxHasScrolling()) {
   popup.AfterResizing.AddHandler(this.OnHeaderFilter_AfterResizing.bind(this));
   ASPx.Evt.AttachEventToElement(this.GetHeaderFilterPopupScrollableElement(), "scroll", this.OnHeaderFilterPopup_Scroll.bind(this));
  }
  this.InitializeHeaderFilterButtons();
 },
 OnHeaderFilterPopup_PopUp: function(popup) {
  var columnIndex = this.FindColumnIndexByHeaderChild(popup.GetCurrentPopupElement());
  var column = this.GetColumn(columnIndex);
  if(!column) return;
  var shiftKey = popup.GetPopUpReasonMouseEvent().shiftKey;
  var callbackWaiting = this.LoadHeaderFilterPopupData(popup, column, shiftKey);
  if(callbackWaiting) {
   var size = this.GetHeaderFilterPopupSize(columnIndex);
   this.SetHFButtonPanelVisibility(popup, this.RequireButtonPanel(column));
   this.AssignHeaderFilterPopupMinWidth(column);
   if(size) {
    popup.SetSize(size[0], size[1]);
    if(ASPx.Browser.Firefox)
     popup.Shown.AddHandler(function(s) { window.setTimeout(function() { s.SetSize(size[0], size[1]); }, 0); }); 
   }
   this.ShowLoadingPanelInsideHeaderFilterPopup();
  }
  if(this.IsListBoxHasScrolling())
   window.setTimeout(this.UpdateHeaderFilterPopupScroll.bind(this), popup.fadeAnimationDuration);
 },
 LoadHeaderFilterPopupData: function(popup, column, shiftKey) {
  if(column === this.GetHeaderFilterPopupRelatedColumn() && this.UseHeaderFilterContentCaching(column.index) && popup.savedShiftKey === shiftKey) {
   this.ApplyHeaderFilterInitialState(column.index);
  } else {
   this.SendHeaderFilterCallback(column.index, shiftKey);
   popup.SetContentHtml("");
   this.headerFilterPopupRelatedColumn = null;
   popup.savedShiftKey = shiftKey;
   return true;
  }
 },
 UpdateHeaderFilterPopupScroll: function() {
  var column = this.GetHeaderFilterPopupRelatedColumn();
  var disablePopupScroll = this.RequireShowHeaderFilterListBoxScrollbar(column) && this.GetHeaderFilterPopup().IsVisible();
  ASPx.SetStyles(this.GetHeaderFilterPopupScrollableElement(), { overflowY: disablePopupScroll ? "hidden" : "auto" });
 },
 OnHeaderFilterPopup_CloseUp: function(popup) {
  var column = this.GetHeaderFilterPopupRelatedColumn();
  if(column && !this.UseHeaderFilterContentCaching(column.index))
   window.setTimeout(function() { popup.SetContentHtml(""); }, 0);
  this.UpdateHeaderFilterPopupScroll();
 },
 OnHeaderFilterPopup_Resize: function(popup) {
  var columnIndex = this.FindColumnIndexByHeaderChild(popup.GetCurrentPopupElement());
  if(this.GetColumn(columnIndex))
   this.SetHeaderFilterPopupSize(columnIndex, popup.GetWidth(), popup.GetHeight());
 },
 OnHeaderFilter_AfterResizing: function(popup) {
  var column = this.GetHeaderFilterPopupRelatedColumn();
  if(column) {
   this.AdjustHeaderFilterListBox(column);
   var rangeTrackBar = this.GetRangeTrackBar(column.index);
   if(rangeTrackBar)
    rangeTrackBar.AdjustControl();
  }
 },
 OnHeaderFilterPopup_Scroll: function(e) {
  var column = this.GetHeaderFilterPopupRelatedColumn();
  if(this.RequireShowHeaderFilterListBoxScrollbar(column))
   this.GetHeaderFilterPopupScrollableElement().scrollTop = 0;
 },
 InitializeHeaderFilterButtons: function() {
  var popup = this.GetHeaderFilterPopup();
  if(!popup) return;
  var buttons = this.GetHeaderFilterButtons();
  for(var i = 0; i < buttons.length; i++) {
   popup.AddPopupElement(buttons[i]);
   if(this.GetEnableAccessibility())
    ASPx.Evt.AttachEventToElement(buttons[i], "keydown", GridFilterHelper.HeaderFilterButtonKeyDownHandler);
  }
 },
 UnloadHeaderFilterPopup: function() {
  var popup = this.GetHeaderFilterPopup();
  if(!popup) return;
  popup.PopUp.RemoveHandler(this.HeaderFilterPopup_PopUpHandler);
  popup.CloseUp.RemoveHandler(this.HeaderFilterPopup_CloseUpHandler);
  popup.Resize.RemoveHandler(this.HeaderFilterPopup_ResizeHandler);
  popup.RemoveAllPopupElements();
  popup.Hide();
  if(this.GetEnableAccessibility()) {
   var buttons = this.GetHeaderFilterButtons();
   for(var i = 0; i < buttons.length; i++)
    ASPx.Evt.DetachEventFromElement(buttons[i], "keydown", GridFilterHelper.HeaderFilterButtonKeyDownHandler);
  }
 },
 GetHeaderFilterButtons: function() {
  var buttons = [ ];
  var visibleIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < visibleIndices.length; i++) {
   var index = visibleIndices[i];
   var headers = this.GetColumnHeaders(index);
   for(var j = 0; j < headers.length; j++)
    this.PopulateHeaderFilterButtons(headers[j], buttons);
  }
  var custWindow = this.GetCustomizationWindow();
  if(custWindow)
   this.PopulateHeaderFilterButtons(custWindow.GetWindowClientTable(-1), buttons);
  return buttons;
 },
 GetVisibleColumnIndices: function() {
  var indices = [ ];
  for(var i = 0; i < this.GetColumnCount(); i++) {
   if(this.GetColumn(i).visible)
    indices.push(this.GetColumn(i).index);
  }
  return indices;
 },
 PopulateHeaderFilterButtons: function(container, buttons) {
  if(!container) return;
  var images = container.getElementsByTagName("IMG");
  for(var i = 0; i < images.length; i++) {
   var button = ASPx.getSpriteMainElement(images[i]);
   if(ASPx.ElementContainsCssClass(button, this.GetHeaderFilterIconClassName()))
    buttons.push(button);
  }
 },
 RequireButtonPanel: function(column) {
  return column.HFMode !== ASPx.GridHeaderFilterMode.List;
 },
 SetHFButtonPanelVisibility: function(popup, visible) {
  var buttonPanel = this.GetHeaderFilterPopupButtonPanelElement();
  if(buttonPanel) {
   ASPx.SetElementDisplay(buttonPanel, visible);
   this.SetHFOkButtonEnabled(false);
   var okButton = this.GetHeaderFilterButton(false);
   var cancelButton = this.GetHeaderFilterButton(true);
   if(okButton && cancelButton && okButton.GetWidth() != cancelButton.GetWidth())
    ASPx.MakeEqualControlsWidth(popup.cpOkButtonID, popup.cpCancelButtonID);
  }
 },
 SetHFOkButtonEnabled: function(enabled) {
  var button = this.GetHeaderFilterButton(false);
  if(button)
   button.SetEnabled(enabled);
 },
 GetHeaderFilterPopupSize: function(key) {
  var size = this.headerFilterPopupDimensions[key];
  if(size) return size;
  if(!this.headerFilterPopupDimensions["Default"]) {
   var popup = this.GetHeaderFilterPopup();
   this.SetHeaderFilterPopupSize("Default", popup.GetWidth(), popup.GetHeight());
  }
  return this.headerFilterPopupDimensions["Default"];
 },
 SetHeaderFilterPopupSize: function(key, width, height) {
  this.headerFilterPopupDimensions[key] = [ width, height ];
 },
 AssignHeaderFilterPopupMinWidth: function(column) {
  var popup = this.GetHeaderFilterPopup();
  popup.minWidth = this.GetHeaderFilterPopupMinWidth(column);
 },
 GetHeaderFilterPopupMinWidth: function(column) {
  if(this.RequireButtonPanel(column))
   return this.GetHeaderFilterPopupWithButtonPanelMinWidth();
  return this.initialHeaderFilterPopupMinWidth;
 },
 GetHeaderFilterPopupWithButtonPanelMinWidth: function() {
  if(!ASPx.IsExists(this.headerFilterPopupWithButtonPanelMinWidth))
   this.headerFilterPopupWithButtonPanelMinWidth = this.CalculateHeaderFilterPopupWithButtonPanelMinWidth();
  return this.headerFilterPopupWithButtonPanelMinWidth;
 },
 CalculateHeaderFilterPopupWithButtonPanelMinWidth: function() {
  var popup = this.GetHeaderFilterPopup();
  var minWidth = popup.GetWidth();
  var buttonPanel = this.GetHeaderFilterPopupButtonPanelElement();
  if(buttonPanel) {
   var footerElement = buttonPanel.parentNode;
   var excess = buttonPanel.offsetWidth - ASPx.GetClearClientWidth(footerElement);
   minWidth += excess;
  }
  minWidth = Math.max(minWidth, this.initialHeaderFilterPopupMinWidth);
  return minWidth;
 },
 GetHeaderFilterPopupButtonPanelElement: function() {
  var popup = this.GetHeaderFilterPopup();
  return document.getElementById(popup.cpButtonPanelID);
 },
 FindColumnIndexByHeaderChild: function(element) {
  if(!element) 
   return -1;
  var level = 0;
  while(level < 6) {
   var index = this.ResolveColumnIndex(element.id);
   if(index > -1)
    return index;
   element = element.parentNode;
   level++;
  }
  return -1;
 },
 UseHeaderFilterContentCaching: function(columnIndex) {
  if(!this.GetEnableHeaderFilterCaching())
   return false;
  var listBox = this.GetListBox(columnIndex);
  return listBox && listBox.GetMainElement() && listBox.GetItemCount() < 1000; 
 },
 CalcDateRanges: function(dates) { 
  var result = [ ];
  dates.sort(function(a, b) { return a - b; });
  var range = { start: null, end: null };
  for(var i = 0; i < dates.length; i++) {
   var date = dates[i];
   if(!range.start || !range.end)
    range.start = range.end = date;
   var isLastDate = dates.length === i + 1;
   var nextDate = ASPxClientCalendar.AddDays(date, 1);
   if(!isLastDate && ASPx.DateUtils.AreDatesEqualExact(nextDate, dates[i + 1])) {
    range.end = nextDate;
   } else {
    result.push(ASPx.DateUtils.GetInvariantDateString(range.start));
    result.push(ASPx.DateUtils.GetInvariantDateString(range.end));
    range.start = range.end = null;
   }
  }
  return result;
 },
 InitializeAccessibility: function(column) {
  var listBox = this.GetListBox(column.index);
  if(listBox) {
   listBox.SelectedIndexChanged.AddHandler(function() { this.MakeListBoxSelectedItemVisible(column); }.bind(this));
   this.MakeListBoxSelectedItemVisible(column);
  }
  var popup = this.GetHeaderFilterPopup();
  if(popup && !popup.gvAccessibilityEventsAssigned) {
   popup.Shown.AddHandler(function() { this.MakeListBoxSelectedItemVisible(this.GetHeaderFilterPopupRelatedColumn()); }.bind(this));
   ASPx.Evt.AttachEventToElement(popup.GetCurrentWindowElement(), "keydown", this.ProcessAccessibleHeaderFilterPopupKeyDown.bind(this));
   popup.gvAccessibilityEventsAssigned = true;
  }
 },
 MakeListBoxSelectedItemVisible: function(column) {
  if(!column || column.HFMode !== ASPx.GridHeaderFilterMode.List)
   return;
  var listBox = this.GetListBox(column.index);
  var itemIndex = listBox.GetSelectedIndex();
  var div = this.GetHeaderFilterPopupScrollableElement();
  var item = listBox.GetItemElement(itemIndex);
  if(!div || !item)
   return;
  var itemHeight = item.offsetHeight;
  var divHeight = parseInt(ASPx.GetCurrentStyle(div).height);
  var itemStart = item.offsetTop;
  var itemEnd = itemStart + itemHeight;
  var divStart = div.scrollTop;
  var divEnd = divStart + divHeight;
  var scrollTop = divStart;
  var isItemAbove = itemStart < divStart;
  var isItemBelow = itemEnd > divEnd;
  if(isItemAbove)
   scrollTop = itemStart;
  else if(isItemBelow)
   scrollTop = itemEnd - divHeight;
  if(div.scrollTop !== scrollTop)
   div.scrollTop = scrollTop;
 },
 ProcessAccessibleHeaderFilterPopupKeyDown: function(e) {
  var keyCode = ASPx.Evt.GetKeyCode(e);
  if(keyCode !== ASPx.Key.Enter) 
   return;
  var handled = true;
  var column = this.GetHeaderFilterPopupRelatedColumn();
  if(column.HFMode === ASPx.GridHeaderFilterMode.List) {
   this.OnListBoxSelectionChanged(this.GetListBox(column.index));
  } else {
   var applyFilterOnEnter = this.IsHeaderFilterChanged(column.index) && !this.IsCancelButtonEventSource(e) && !this.IsDateEditorDroppedDown(column);
   if(applyFilterOnEnter)
    this.ApplyHeaderFilter();
   else
    handled = false;
  }
  if(handled)
   ASPx.Evt.PreventEventAndBubble(e);
 },
 IsCancelButtonEventSource: function(evt) {
  return ASPx.GetIsParent(this.GetHeaderFilterButton(true).GetMainElement(), ASPx.Evt.GetEventSource(evt));
 },
 IsDateEditorDroppedDown: function(column) {
  if(column.HFMode === ASPx.GridHeaderFilterMode.DateRangePicker)
   return this.GetDateEdit_From(column.index).droppedDown || this.GetDateEdit_To(column.index).droppedDown;
  return false;
 },
 PrepareSeparators: function(listBox) {
  if(typeof(ASPxClientListBox) != "undefined" && listBox instanceof ASPxClientListBox)
   GridHFListBoxWrapper.Initialize(listBox);
  for(var i = 0; i < listBox.cpFSI.length; i++) {
   var separatorIndex = listBox.cpFSI[i];
   var item = listBox.GetItemElement(separatorIndex);
   if(ASPx.IsExists(item)) {
    var tr = ASPx.GetParentByTagName(item, "TR");
    this.AppendSeparatorRow(tr);
   }
  }
 },
 AppendSeparatorRow: function(targetRow){
  var newTr = document.createElement("TR");
  ASPx.InsertElementAfter(newTr, targetRow);
  var td = document.createElement("TD");
  var colSpan = this.GetColSpanSum(targetRow);
  if(colSpan > 1)
   td.colSpan = colSpan;
  newTr.appendChild(td);
  var separatorDiv = document.createElement("DIV");
  separatorDiv.className = this.GetFilterValuesSeparatorClassName();
  td.appendChild(separatorDiv);
 },
 GetColSpanSum: function(tableRow){
  var colSpan = 0;
  var cells = ASPx.GetChildNodesByTagName(tableRow, "TD");
  for(var i = 0; i < cells.length; i++)
   colSpan += cells[i].colSpan;
  return colSpan;
 },
 GetFilterValuesSeparatorClassName: function() { return this.grid.GetCssClassNamePrefix() + "HFSD"; },
});
var GridHFListBoxWrapper = {
 Initialize: function(listBox){
  listBox.GetItemRow = GridHFListBoxWrapper.GetItemRow;
  listBox.GetItemCount = GridHFListBoxWrapper.GetItemCount;
  listBox.OnItemClickCore = listBox.OnItemClick;
  listBox.OnItemClick = GridHFListBoxWrapper.OnItemClick;
  listBox.FindInternalCheckBoxIndexCore = listBox.FindInternalCheckBoxIndex;
  listBox.FindInternalCheckBoxIndex = GridHFListBoxWrapper.FindInternalCheckBoxIndex;
 },
 GetItemRow: function(index){
  var itemRows = GridHFListBoxWrapper.GetItemRows(this);
  if(index >= 0)
   return itemRows[index] || null;
  return null;
 },
 OnItemClick: function(index, evt){
  var correctIndex = GridHFListBoxWrapper.GetCorrectItemIndex(this, index);
  this.OnItemClickCore(correctIndex, evt);
 },
 FindInternalCheckBoxIndex: function(element){
  var index = this.FindInternalCheckBoxIndexCore(element);
  return GridHFListBoxWrapper.GetCorrectItemIndex(this, index);
 },
 GetItemCount: function(){
  return GridHFListBoxWrapper.GetItemRows(this).length;
 },
 GetCorrectItemIndex: function(listBox, index){
  for(var i = 0; i < listBox.cpFSI.length; i++) {
   if(listBox.cpFSI[i] < index)
    index--;
  }
  return index;
 },
 GetItemRows: function(listBox){
  var itemRows = [];
  var listTable = listBox.GetListTable();
  var rows = listTable ? listTable.rows : null;
  for(var i = 0; rows && i < rows.length; i++){
   if(ASPx.ElementContainsCssClass(rows[i], "dxeListBoxItemRow"))
    itemRows.push(rows[i]);
  }
  return itemRows;
 }
};
GridFilterHelper.HeaderFilterButtonKeyDownHandler = function(evt) { ASPx.Evt.InvokeMouseClickByKeyDown(evt, ASPx.PopupElementMouseEvent); };
ASPx.GridHeaderFilterMode = GridHeaderFilterMode;
ASPx.GridFilterHelper = GridFilterHelper;
})();

(function() {
var GridExportItemType = {
 ExportToPdf: "ExportToPdf",
 ExportToDocx: "ExportToDocx",
 ExportToRtf: "ExportToRtf",
 ExportToCsv: "ExportToCsv",
 ExportToXls: "ExportToXls",
 ExportToXlsx: "ExportToXlsx"
};
var TOOLBAR_CLIENT_STATE_KEY = "toolbar";
var CHECKED_CLIENT_STATE_KEY = "checked";
var CLICKED_CLIENT_STATE_KEY = "clicked";
var GridCommandMenuHelper = ASPx.CreateClass(null, {
 constructor: function(exportFormat) {
  this.exportFormat = exportFormat;
 },
 GetItemCommand: function(item) {
  return item.menu.cpItemsProps.commands[item.indexPath];
 },
 IsExportItem: function(itemType) {
  return itemType == GridExportItemType.ExportToPdf
   || itemType == GridExportItemType.ExportToDocx
   || itemType == GridExportItemType.ExportToRtf
   || itemType == GridExportItemType.ExportToCsv
   || itemType == GridExportItemType.ExportToXls
   || itemType == GridExportItemType.ExportToXlsx;
 },
 GetExportFormat: function(exportCommand) {
  var exportFormat = this.exportFormat;
  switch(exportCommand) {
   case GridExportItemType.ExportToPdf:
    return exportFormat.Pdf;
   case GridExportItemType.ExportToDocx:
    return exportFormat.Docx;
   case GridExportItemType.ExportToRtf:
    return exportFormat.Rtf;
   case GridExportItemType.ExportToCsv:
    return exportFormat.Csv;
   case GridExportItemType.ExportToXls:
    return exportFormat.Xls;
   case GridExportItemType.ExportToXlsx:
    return exportFormat.Xlsx;
  }
  return null;
 }
});
var CommandToolbarHelper = ASPx.CreateClass(GridCommandMenuHelper, {
 constructor: function(control, exportFormat) {
  this.constructor.prototype.constructor.call(this, exportFormat);
  this.control = control;
  this.ResetState();
 },
 GetCallbackState: function() {
  var state = { };
  if(this.clickedToolbarIndex >= 0 && this.clickedToolbarMenuItem)
   state[CLICKED_CLIENT_STATE_KEY] = [this.clickedToolbarIndex, this.clickedToolbarMenuItem.indexPath];
  var checkedState = this.GetCheckedItemsState();
  if(checkedState.length > 0)
   state[CHECKED_CLIENT_STATE_KEY] = checkedState;
  return ASPx.Json.ToJson(state);
 },
 GetCheckedItemsState: function() {
  var result = [ ];
  this.ForEachToolbar(function(toolbar, toolbarIndex) {
   if(toolbar.allowCheckItems)
    result.push([toolbarIndex, toolbar.GetCheckedState()]);
  }.bind(this));
  return result;
 },
 ResetState: function() {
  this.clickedToolbarIndex = -1;
  this.clickedToolbarMenuItem = null;
  this.SetClientStateValue(null);
 },
 SaveClientState: function() {
  this.SetClientStateValue(this.GetCallbackState());
 },
 SetClientStateValue: function(value) {
  this.control.stateObject[TOOLBAR_CLIENT_STATE_KEY] = value;
 },
 GetToolbarSettings: function() {
  return this.control.toolbars;
 },
 GetToolbarByIndex: function(index) {
  return this.control.GetToolbar(index);
 },
 GetToolbarByName: function(name) {
  var settings = this.GetToolbarSettings();
  var foundToolbars = settings.filter(function(t) { return t.name === name; });
  if(foundToolbars.length < 1)
   return null;
  return this.GetToolbarByIndex(foundToolbars[0].index);
 },
 GetToolbarNameByIndex: function(index) {
  var settings = this.GetToolbarSettings(),
   foundToolbars = settings.filter(function(t) { return t.index === index; });
  return (foundToolbars.length > 0) ? foundToolbars[0].name : null;
 },
 GetToolbarIndexByName: function(name) {
  var index = -1;
  var success = false;
  var n = name.length - 1;
  while(n >= 0 && !isNaN(parseInt(name.substr(n), 10))) {
   index = parseInt(name.substr(n), 10);
   success = true;
   n--;
  }
  return success ? index: -1;
 },
 InitializeCustomizationWindowHandlers: function() {
  var custWindow = this.GetCustomizationWindow();
  if(custWindow) {
   custWindow.PopUp.AddHandler(function() {
    this.SetCheckedItemsState(this.IsShowCustomizationWindowItem.bind(this), true);
   }.aspxBind(this));
   custWindow.CloseUp.AddHandler(function() {
    this.SetCheckedItemsState(this.IsShowCustomizationWindowItem.bind(this), false);
   }.aspxBind(this));
  }
 },
 OnInit: function() {
  this.InitializeCustomizationWindowHandlers();
 },
 OnBeforeCallback: function() {
  this.SaveClientState();
 },
 OnAfterCallback: function() {
  this.ResetState();
  this.InitializeCustomizationWindowHandlers();
  this.RefreshItemsState();
 },
 RefreshItemsState: function() {
  this.ForEachItem(null, this.RefreshItemState.aspxBind(this));
 },
 SetCheckedItemsState: function(filterFunc, checked) {
  var setCheckedFunc = function(item) { item.SetChecked(checked); };
  this.ForEachItem(filterFunc, setCheckedFunc);
 },
 OnBatchEditItemsStateChanged: function(state) {
  this.OnUpdateEditEnabledChanged(state.enabled);
 },
 OnUpdateEditEnabledChanged: function(enabled) {
  var setEnabledFunc = function(item) { item.SetEnabled(enabled); };
  this.ForEachItem(this.IsUpdateEditItem.aspxBind(this), setEnabledFunc);
 },
 RefreshItemState: function(item) {
  this.RefreshItemBadge(item);
  this.RefreshItemEnabled(item);
 },
 RefreshSelectionBasedItemBadge: function(item, count) {
  this.UpdateItemBadge(item, count > 1 ? count : 0);
 },
 UpdateItemBadge: function(item, count) {
  var menu = item.menu;
  var itemElement = menu.GetItemElement(item.GetIndexPath());
  var badge = ASPx.BadgeManager.findBadge(itemElement);
  if(!badge)
   badge = ASPx.BadgeManager.createBadgeForToolbar(item);
  if(badge) {
   var badgeText = count > 0 ? count : "";
   if(ASPx.BadgeManager.getBadgeText(itemElement) != badgeText) {
    ASPx.BadgeManager.setBadgeText(badge, badgeText);
    menu.renderHelper.CalculateItemMinSize(itemElement, true);
    menu.AdjustControl();
   }
  }
 },
 RefreshItemEnabled: function(item) {
  var itemEnabled = this.GetToolbarItemEnabled(item);
  if(itemEnabled !== null)
   item.SetEnabled(itemEnabled);
 },
 ForEachToolbar: function(actionFunc) {
  var settings = this.GetToolbarSettings();
  for(var i = 0; i < settings.length; i++) {
   var toolbarIndex = settings[i].index;
   var menu = this.GetToolbarByIndex(toolbarIndex);
   actionFunc(menu, toolbarIndex);
  }
 },
 ForEachAdaptiveToolbar: function(actionFunc) {
  this.ForEachToolbar(function(menu) {
   if(menu.IsEnabledAdaptivity())
    actionFunc(menu);
  });
 },
 ForEachItem: function(filterFunc, actionFunc) {
  this.ForEachToolbar(function(menu) {
   this.ForEachItemInternal(menu, filterFunc, actionFunc);
  }.bind(this));
 },
 ForEachItemInternal: function(itemsOwner, filterFunc, actionFunc) {
  if(!itemsOwner) return;
  for(var i = 0; i < itemsOwner.GetItemCount(); i++){
   var item = itemsOwner.GetItem(i);
   if(!filterFunc || filterFunc(item))
    actionFunc(item);
   this.ForEachItemInternal(item, filterFunc, actionFunc);
  }
 },
 RefreshItemBadge: function(item) {
 },
 GetToolbarItemEnabled: function(item){
  return null;
 },
 IsUpdateEditItem: function(item) {
  return false;
 },
 GetCustomizationWindow: function() {
  return null;
 },
 IsShowCustomizationWindowItem: function(item) {
  return false;
 },
 GetSelectedGridItemCount: function() {
  return 0;
 },
 GetSelectedVisibleGridItemCount: function() {
  return 0;
 },
 OnToolbarMenuItemClick: function(toolbar, e) {
  this.clickedToolbarIndex = this.GetToolbarIndexByName(toolbar.name);
  this.clickedToolbarMenuItem = e.item;
  this.SaveClientState();
  var clickedToolbarInfo = { index: this.clickedToolbarIndex, name: this.GetToolbarNameByIndex(this.clickedToolbarIndex) },
   handled = this.control.RaiseToolbarItemClick(clickedToolbarInfo, e.item);
  if(!handled)
   this.ProcessToolbarItemClick(e);
  this.ResetState();
 },
 ProcessToolbarItemClick: function(e) {
  var item = e.item,
   command = this.GetItemCommand(item);
  if(this.IsExportItem(command))
   this.ToolbarExport(command);
 },
 ToolbarExport: function(exportCommand) {
  var exportFormat = this.GetExportFormat(exportCommand);
  this.control.ExportTo(exportFormat);
 },
 ProcessCustomToolbarItemClickOnServer: function(usePostBack) {
 }
});
var GridToolbarHelper = ASPx.CreateClass(CommandToolbarHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid, ASPx.ASPxClientGridExportFormat);
  this.grid = grid;
 },
 OnAfterCallback: function() {
  CommandToolbarHelper.prototype.OnAfterCallback.call(this);
  if(this.grid.IsLastCallbackProcessedAsEndless())
   this.OnUpdateEditEnabledChanged(this.IsUpdateEditItemEnabled());
 },
 ProcessCustomToolbarItemClickOnServer: function(usePostBack) {
  var args = [ "" ];
  if(usePostBack)
   this.SendToolbarPostback(args);
  else
   this.SendToolbarCallback(args);
 },
 OnBatchEditItemsStateChanged: function(state) {
  ASPx.CommandToolbarHelper.prototype.OnBatchEditItemsStateChanged.call(this, state);
  this.ForEachItem(null, function(item) {
   this.UpdateBatchPreviewItemsState(item, state);
  }.bind(this));
 },
 UpdateBatchPreviewItemsState: function(item, state) { },
 SendToolbarCallback: function(args) {
  this.grid.gridCallBack([ ASPxClientGridViewCallbackCommand.Toolbar ].concat(args));
 },
 SendToolbarPostback: function(toolbarCommand) {
  this.grid.gridPostBack([ASPxClientGridViewCallbackCommand.Toolbar, toolbarCommand]);
 },
 ToolbarStartEdit: function() {
  if(this.IsBatchEditMode()) {
   var visibleIndex = 0;
   var columnIndex = 0;
   var cellInfo = this.GetFocusedCellInfo();
   if(cellInfo) {
    visibleIndex = this.grid.ConvertKeyToVisibleIndex(cellInfo.recordKey);
    columnIndex = cellInfo.columnIndex;
   }
   this.grid.batchEditApi.StartEdit(visibleIndex, columnIndex);
  }
  else
   this.grid.StartEditItem(this.GetFocusedItemIndex());
 },
 ToolbarDeleteItem: function() {
  var focusedItemIndex = this.GetFocusedItemIndex();
  if(focusedItemIndex == -1 && this.IsBatchEditMode()) {
   var cellInfo = this.GetFocusedCellInfo();
   if(cellInfo)
    focusedItemIndex = this.grid.ConvertKeyToVisibleIndex(cellInfo.recordKey);
  }
  this.grid.DeleteGridItem(focusedItemIndex);
 },
 ToolbarDeleteSelectedVisibleItems: function() {
  this.ToolbarDeleteSelectedItemsInternal("DeleteSelectedVisible");
 },
 ToolbarDeleteSelectedItemsInternal: function(commandName) {
  if(!this.grid.ConfirmDeleteGridItem())
   return;
  if(this.IsBatchEditMode()) {
   var keys = this.grid.GetSelectedKeysOnPage();
   for(var i = 0, key; key = keys[i]; i++)
    this.grid.DeleteItemByKey(key);
  }
  else
   this.SendToolbarCallback([ commandName ]);
 },
 GetFocusedItemIndex: function(){
  return this.control._getFocusedItemIndex();
 },
 GetFocusedCellInfo: function() {
  var helper = this.control.GetCellFocusHelper();
  return helper ? helper.GetFocusedCellInfo() : null;
 },
 GetSelectedGridItemCount: function() {
  return this.control._getSelectedRowCount();
 },
 GetSelectedVisibleGridItemCount: function() {
  return this.control._getSelectedRowCountOnPage();
 },
 GetCustomizationWindow: function() {
  return this.grid.GetCustomizationWindow();
 },
 IsUpdateEditItemEnabled: function() {
  if(this.IsBatchEditMode())
   return this.grid.batchEditApi.HasChanges();
  return this.grid.allowEdit && this.grid.IsEditing();
 },
 IsEditingItem: function(visibleIndex){
  return this.control.IsEditingItem(visibleIndex);
 },
 GetBatchEditHelper: function() {
  return this.control.GetBatchEditHelper();
 },
 IsBatchEditMode: function(){
  return !!this.GetBatchEditHelper();
 },
 HasBatchEditFocusedCell: function() {
  return this.IsBatchEditMode() && this.GetFocusedCellInfo();
 }
});
ASPx.GridExportItemType = GridExportItemType;
ASPx.GridCommandMenuHelper = GridCommandMenuHelper;
ASPx.CommandToolbarHelper = CommandToolbarHelper;
ASPx.GridToolbarHelper = GridToolbarHelper;
})();
(function() {
var TableHelperBase = ASPx.CreateClass(null, {
 constructor: function(control, contentTableIDSuffix, headerTableIDSuffix, footerTableIDSuffix, horzScroll, vertScroll){
  this.control = control;
  this.horzScroll = horzScroll;
  this.vertScroll = vertScroll;
  this.contentTableIDSuffix = contentTableIDSuffix;
  this.headerTableIDSuffix = headerTableIDSuffix;
  this.footerTableIDSuffix = footerTableIDSuffix;
 },
 GetChildElement: function(idSuffix) {
  return this.control.GetChildElement(idSuffix);
 },
 GetTable: function(tableIDSuffix) {
  return this.GetChildElement(tableIDSuffix);
 },
 GetContentTable: function() {
  return this.GetTable(this.contentTableIDSuffix);
 },
 GetHeaderTable: function() {
  return this.GetTable(this.headerTableIDSuffix);
 },
 GetFooterTable: function() {
  return this.GetTable(this.footerTableIDSuffix);
 },
 HasHorzScroll: function() { return this.horzScroll != ASPx.ScrollBarMode.Hidden; }, 
 HasVertScroll: function() { return this.vertScroll != ASPx.ScrollBarMode.Hidden; },
 IsHorzAutoScroll: function() {
  return this.horzScroll == ASPx.ScrollBarMode.Auto;
 },
 IsVertAutoScroll: function() {
  return this.vertScroll == ASPx.ScrollBarMode.Auto;
 },
 IsRtl: function() { return false; },
 GetArmatureCells: function(table) { return [ ].slice.call(table.rows[0].cells); },
 GetArmatureCell: function(cell) {
  var index = this.GetArmatureCellIndexByOtherCell(cell);
  return this.GetArmatureCells(ASPx.GetParentByTagName(cell, "TABLE"))[index];
 },
 GetArmatureCellIndexByOtherCell: function(cell) {
  return cell.cellIndex;
 },
 GetCellRealWidth: function(cell) {
  var width = this.GetStylePxWidth(this.GetArmatureCell(cell));
  return width > -1 ? width : cell.offsetWidth;
 },
 GetStylePxWidth: function(element) {
  var width = element.style.width;
  if(width && width.indexOf("px") > -1) 
   return parseInt(width, 10);
  return -1;
 }
});
var TableHelperAdapter = ASPx.CreateClass(null, {
 constructor: function(tableHelper) {
  this.tableHelper = tableHelper;
  this.control = this.tableHelper.control;
 },
 GetContentTable: function() {
  return this.tableHelper.GetContentTable();
 },
 GetHeaderTable: function() {
  return this.tableHelper.GetHeaderTable();
 },
 GetFooterTable: function() {
  return this.tableHelper.GetFooterTable();
 },
 GetArmatureCells: function(table) {
  return this.tableHelper.GetArmatureCells(table);
 },
 GetArmatureCell: function(cell) {
  return this.tableHelper.GetArmatureCell(cell);
 },
 GetCellRealWidth: function(cell) {
  return this.tableHelper.GetCellRealWidth(cell);
 },
 GetStylePxWidth: function(element) {
  return this.tableHelper.GetStylePxWidth(element);
 },
 HasHorzScroll: function() {
  return this.tableHelper.HasHorzScroll();
 }, 
 HasVertScroll: function() {
  return this.tableHelper.HasVertScroll();
 },
 IsRtl: function() {
  return this.tableHelper.IsRtl();
 }
});
ASPx.TableHelperBase = TableHelperBase;
ASPx.TableHelperAdapter = TableHelperAdapter;
})();
(function() {
var GridBaseEndlessPagingHelper = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
  this.showLoadingPanelAtBottom = false;
  this.focusedRowIndexInfo =  { 
   beforeCallback: -1,
   underCallback: -1,
   afterCallback: -1
  };
  this.endlessCallbackComplete = false;
 },
 GetItemsContainer: function(){ return this.grid.GetMainTable(); },
 GetItemElements: function(){ 
  var container = this.GetItemsContainer();
  return container.tagName == "TABLE" ? container.rows : container.childNodes; 
 },
 GetEditingItemElements: function(){
  var elements = [ ];
  var row = this.grid.GetEditingRow();
  if(row)
   elements.push(row);
  return elements;
 },
 OnBeforeCallback: function(command) {
  this.endlessCallbackComplete = false;
  this.showLoadingPanelAtBottom = command === ASPxClientGridViewCallbackCommand.NextPage;
  this.focusedRowIndexInfo.beforeCallback = this.focusedRowIndexInfo.underCallback = this.GetFocusedItemIndex();
  this.focusedRowIndexInfo.afterCallback = -1;
  this.ResetActiveElement();
 },
 OnAfterCallback: function() {
  var grid = this.grid;
  var lpContainer = grid.GetEndlessPagingLPContainer();
  if(lpContainer)
   ASPx.SetElementDisplay(lpContainer, grid.pageIndex + 1 != grid.pageCount);
  this.CorrectItemIDs();
  this.focusedRowIndexInfo.afterCallback = this.GetFocusedItemIndex();
  this.CheckFocusedItemIndexChangedOnCallback();
  grid.UpdateItemsStyle();
 },
 GetFocusedItemIndex: function(){
  return -1;
 },
 ResetActiveElement: function() {
  var activeElement = ASPx.GetActiveElement();
  if(activeElement && ASPx.GetIsParent(this.GetItemsContainer(), activeElement)) {
   try { activeElement.blur(); } catch(e) { }
  }
 },
 CheckFocusedItemIndexChangedOnCallback: function() {
  var info = this.focusedRowIndexInfo;
  if(info.beforeCallback === info.underCallback && info.underCallback === info.afterCallback)
   return;
  if(info.beforeCallback !== info.afterCallback) {
   this.grid.ChangeFocusedItemStyle(info.beforeCallback, false);
   this.grid.ChangeFocusedItemStyle(info.underCallback, false);
  } else if(info.beforeCallback !== info.underCallback) {
   this.grid.ChangeFocusedItemStyle(info.beforeCallback, false);
   this.grid.ChangeFocusedItemStyle(info.underCallback, true);
   this.grid.focusedRowIndex = info.underCallback;
  }
  this.grid._setFocusedItemInputValue();
 },
 OnGridFocusedItemChanged: function() { 
  if(this.grid.InCallback())
   this.focusedRowIndexInfo.underCallback = this.GetFocusedItemIndex();
 },
 CorrectItemIDs: function() {
  var grid = this.grid;
  var itemElements = this.GetItemElements();
  if(itemElements.length == 0) return;
  var index = -1;
  var editingElements = this.GetEditingItemElements();
  for(var i = 0; i < itemElements.length; i++) {
   var item = itemElements[i];
   var id = item.id;
   if(!id) continue;
   var editingItemIndex = editingElements.indexOf(item);
   if(editingItemIndex > -1 && !this.IsEditRowHasDisplayedDataRow() && !grid.IsNewItemEditing()) {
    if(editingItemIndex == 0)
     index++;
    continue;
   }
   index = this.CorrectDataItemID(item, index);
  }
  ASPx.CacheHelper.DropCache(grid);
 },
 CorrectDataItemID: function(item, prevVisibleIndex){
  var supposedVisibleIndex = prevVisibleIndex;
  var regEx = this.grid.GetItemVisibleIndexRegExp();
  var matches = regEx.exec(item.id);
  if(matches && matches.length == 3) {
   var visibleIndex = parseInt(matches[2]);
   if(this.IsNewRecord(visibleIndex))
    return supposedVisibleIndex;
   if(this.IsDataItem(item))
    supposedVisibleIndex++;
   if(visibleIndex != supposedVisibleIndex)
    item.id = item.id.replace(regEx, "$1" + supposedVisibleIndex);
  }
  return supposedVisibleIndex;
 },
 IsEditRowHasDisplayedDataRow: function() { return false; },
 IsDataItemID: function(id){
  return false;
 },
 IsDataItem: function(element) {
  if(element)
   return this.IsDataItemID(element.id);
  return false;
 },
 IsBatchEditMode: function() {
  return ASPx.GridCommonUtils.IsBatchEditMode(this.grid);
 },
 IsNewRecord: function(key) {
  return this.IsBatchEditMode() && this.grid.GetBatchEditHelper().IsNewRecord(key);
 },
 NeedShowLoadingPanelAtBottom: function(){
  return this.showLoadingPanelAtBottom && this.grid.GetEndlessPagingLPContainer();
 },
 OnCallback: function(str) {
  if(!this.grid.GetMainElement())
   return;
  var result = eval(str.slice(str.indexOf("|") + 1));
  this.UpdateKeyValues(result.pageKeys);
  this.UpdateGroupState(result.groupState);
  this.UpdateCellMergingState(result.cellMergeState);
  this.UpdateGroupLevelState(result.groupLevelState);
  if(result.removeEditForm)
   this.RemoveEditFormRow();
  if(result.html)
   ASPx.SetInnerHtml(this.grid.GetEndlessPagingUpdatableContainer(), result.html);
  this.UpdateDataItems(result.dataTableInfo);
  this.grid.cButtonIDs = result.cButtonIDs;
  this.endlessCallbackComplete = true;
 },
 UpdateDataItems: function(updateInfo) {
  if(!updateInfo || updateInfo.length == 0)
   return;
  for(var i = 0; i < updateInfo.length; i++)
   this.UpdateDataItemsCore(updateInfo[i]);
 },
 UpdateDataItemsCore: function(updateInfo) {
  if(!updateInfo) 
   return;
  var removeIndex = updateInfo[0];
  var removeCount = updateInfo[1];
  var addIndex = updateInfo[2];
  var html = updateInfo[3];
  this.RemoveDataItems(removeIndex, removeCount);
  if(addIndex < 0 || !html)
   return;
  var startItem = null;
  var visibleIndex = addIndex;
  do {
   startItem = this.grid.GetItem(visibleIndex);
  } while(!startItem && ++visibleIndex < this.grid.pageRowCount);
  var itemElements = this.GetItemElements();
  var startRowIndex = startItem ? ASPx.Data.ArrayIndexOf(itemElements, startItem) : itemElements.length;
  this.InsertItems(this.GetItemsContainer(), html, startRowIndex);
 },
 RemoveDataItems: function(removeIndex, removeCount) {
  if(removeIndex < 0 || removeCount <= 0)
   return;
  var startItem = this.grid.GetItem(removeIndex);
  if(!startItem) {
   startItem = this.grid.GetItem(++removeIndex);
   removeCount--;
  }
  var endItem = null;
  var visibleIndex = removeIndex + removeCount;
  do {
   endItem = this.grid.GetItem(visibleIndex);
  } while(!endItem && ++visibleIndex < this.grid.pageRowCount);
  var itemElements = this.GetItemElements();
  var startRowIndex = ASPx.Data.ArrayIndexOf(itemElements, startItem);
  var endRowIndex = endItem ? ASPx.Data.ArrayIndexOf(itemElements, endItem) : itemElements.length;
  for(var i = endRowIndex - 1; i >= startRowIndex && startRowIndex >= 0; i--)
   this.RemoveItemFromLayout(itemElements[i]);
 },
 InsertItems: function(container, rowsHtml, index) {
  if(!container || container.tagName != "TABLE")
   return;
  ASPx.InsertRowsBefore(container, rowsHtml, index);
 },
 RemoveEditFormRow: function() {
  var editingElements = this.GetEditingItemElements();
  for(var i = 0; i < editingElements.length; i++)
   this.RemoveItemFromLayout(editingElements[i]);
  ASPx.RemoveElement(this.grid.GetEditingErrorItem());
 },
 RemoveItemFromLayout: function(itemElement) {
  ASPx.RemoveElement(itemElement);
 },
 UpdateKeyValues: function(updateInfo) {
  this.UpdateArray(this.grid.keys, updateInfo);
  this.grid.stateObject.keys = this.grid.keys;
  this.grid.EnsureRowKeys();
 },
 UpdateGroupState: function(updateInfo) {
  this.UpdateArray(this.grid.stateObject.endlessPagingGroupState, updateInfo);
 },
 UpdateCellMergingState: function(cellMergeState){ },
 UpdateGroupLevelState: function(groupLevelState) { },
 UpdateArray: function(array, updateInfo) {
  if(!updateInfo)
   return;
  var removeIndex = updateInfo[0];
  var removeCount = updateInfo[1];
  var addIndex = updateInfo[2];
  var newArray = updateInfo[3];
  for(var i = 0; i < removeCount; i++)
   ASPx.Data.ArrayRemoveAt(array, removeIndex);
  for(var i = 0; i < newArray.length; i++)
   ASPx.Data.ArrayInsert(array, newArray[i], addIndex + i);
 }
});
var CardViewEndlessPagingHelper = ASPx.CreateClass(GridBaseEndlessPagingHelper, {
 constructor: function(grid){
  this.constructor.prototype.constructor.call(this, grid);
  grid.FocusedCardChanged.AddHandler(function() { this.OnGridFocusedItemChanged(); }.aspxBind(this));
 },
 IsFlowLayout: function(){
  var mainElement = this.grid.GetMainTable();
  return mainElement && ASPx.ElementHasCssClass(mainElement, "dxcvFT");
 },
 IsBreakpointsLayout: function() {
  var mainElement = this.grid.GetMainTable();
  return mainElement && ASPx.ElementHasCssClass(mainElement, "dxcvBPT");
 },
 IsTableLayout: function() {
  return !this.IsFlowLayout() && !this.IsBreakpointsLayout();
 },
 GetBreakpointsLayoutItemContainer: function(itemElement) {
  if(this.IsBreakpointsLayoutContainer(itemElement.parentNode))
   return itemElement.parentNode;
  return itemElement;
 },
 GetItemsContainer: function(){
  if(this.IsTableLayout())
   return GridBaseEndlessPagingHelper.prototype.GetItemsContainer.call(this);
  return this.grid.GetMainTable().rows[0].cells[0];
 },
 GetItemElements: function(){ 
    if(this.IsFlowLayout())
     return GridBaseEndlessPagingHelper.prototype.GetItemElements.call(this);
  if(this.IsBreakpointsLayout())
   return this.GetBreakpointsLayoutItemElements();
  return this.GetDataCardCells();
 },
 GetBreakpointsLayoutItemElements: function() {
  var itemElements = GridBaseEndlessPagingHelper.prototype.GetItemElements.call(this),
   result = [];
  for(var i = 0; i < itemElements.length; i++) {
   var element = itemElements[i];
   if(this.IsLayoutItem(element))
    result.push(element);
   else if(this.IsBreakpointsLayoutContainer(element)) {
    var innerDataItemsElements = Array.prototype.slice.call(element.children).filter(this.IsLayoutItem.bind(this));
    result = result.concat(innerDataItemsElements);
   }
  }
  return result;
 },
 GetDataCardCells: function(){
  return ASPx.GetNodesByPartialClassName(this.grid.GetMainTable(), "dxcvCard");
 },
 RemoveItemFromLayout: function(itemElement) {
  var element = itemElement;
  if(this.IsBreakpointsLayout() && this.IsLayoutItem(itemElement))
   element = this.GetBreakpointsLayoutItemContainer(itemElement);
  GridBaseEndlessPagingHelper.prototype.RemoveItemFromLayout.call(this, element);
 },
 RemoveDataItems: function(removeIndex, removeCount){
  GridBaseEndlessPagingHelper.prototype.RemoveDataItems.call(this, removeIndex, removeCount);
  if(this.IsTableLayout())
   this.UpdateTableLayout(this.GetDataCardCells());
 },
 InsertItems: function(container, itemsHtml, index){
  if(this.IsTableLayout()) {
   var cells = this.GetDataCardCells();
   this.UpdateTableLayout(this.InsertDataCellsHtml(cells, itemsHtml, index));
  }
  else
   this.InsertDivBasedItems(container, itemsHtml, index);
 },
 InsertDivBasedItems: function(container, itemsHtml, index){
  var item;
  if(index >= 0 && index < container.children.length)
   item = container.children[index];
  if(item)
   item.insertAdjacentHTML("beforeBegin", itemsHtml);
  else
   container.insertAdjacentHTML("beforeEnd", itemsHtml);
 }, 
 InsertDataCellsHtml: function(cells, cellsHtml, index){
  if(!cellsHtml)
   return cells;
  var table = this.grid.GetMainTable();
  var tbody = table.tBodies[0];
  var row = document.createElement("TR");
  var cell = document.createElement("TD");
  cell.innerHTML = "<table><tbody> <tr>" + cellsHtml + "</tr></tbody></table>";
  tbody.appendChild(row);
  row.appendChild(cell);
  var newTable = ASPx.GetNodeByTagName(cell, "TABLE", 0);
  var newCells = Array.prototype.slice.call(newTable.rows[0].cells);
  ASPx.RemoveElement(row);
  return this.InsertRange(cells, newCells, index);
 },
 InsertRange: function(items, newItems, index) {
  var left = items.slice(0, index);
  var middle = newItems;
  var right = items.slice(index);
  return left.concat(middle.concat(right));
 },
 UpdateTableLayout: function(cells){
  if(!cells) return;
  var table = this.grid.GetMainTable();
  var tbody = ASPx.GetChildByTagName(table, "TBODY");
  while(tbody.firstChild)
   ASPx.RemoveElement(tbody.firstChild);
  var colCount = this.grid.colCount * 2 - 1;
  var row;
  for(var i = 0; i < cells.length; i++) {
   if(!row || row.cells.length >= colCount) {
    if(i > 0) 
     tbody.appendChild(this.GetSeparatorRow());
    row = document.createElement("TR");
    tbody.appendChild(row);
   }
   var cell = cells[i];
   row.appendChild(cell);
   if(row.cells.length < colCount)
    row.appendChild(this.GetSeparatorCell());
   if(this.IsNewCard(cell))
    this.FillRowByEmptyCells(row, colCount);
  }
  this.FillRowByEmptyCells(row, colCount);
 },
 FillRowByEmptyCells: function(row, requireCellCount) { 
  if(!row) return;
  var startIndex = row.cells.length;
  for(var i = startIndex; i < requireCellCount; i++) {
   var cell = i % 2 == 0 ? this.GetEmptyHiddenCard() : this.GetSeparatorCell();
   row.appendChild(cell);
    }
 },
 GetEmptyHiddenCard: function() { return this.grid.GetEtalonEmptyHiddenCard().cloneNode(true); },
 GetSeparatorCell: function() { return this.grid.GetEtalonSeparatorCell().cloneNode(true); },
 GetSeparatorRow: function() { return this.grid.GetEtalonSeparatorRow().cloneNode(true); },
 IsCardID: function(id) { return id.indexOf(this.grid.CardID) > 0; },
 IsGroupRowID: function(id) { return id.indexOf(this.grid.GroupRowID) > 0; },
 IsEditCardID: function(id) { return id.indexOf(this.grid.EditingCardID) > 0; },
 IsDataItemID: function(id) { return this.IsCardID(id) || this.IsGroupRowID(id); },
 IsLayoutItemID: function(id) { return this.IsDataItemID(id) || this.IsEditCardID(id); },
 IsLayoutItem: function(element) {
  if(element)
   return this.IsLayoutItemID(element.id);
  return false;
 },
 IsNewCard: function(card) {
  var grid = this.grid;
  var newCardLayoutID = grid.name + "_" + grid.CardLayoutID + grid.NewCardVisibleIndex;
  return card.firstChild && card.firstChild.id == newCardLayoutID;
 },
 IsBreakpointsLayoutContainer: function(element) {
  var breakpointsHelper = ASPx.BreakpointsLayoutCssHelper;
  if(breakpointsHelper)
   return ASPx.ElementHasCssClass(element, breakpointsHelper.BreakpointsLayoutMarkerClass);
  return false;
 },
 GetFocusedItemIndex: function(){
  return this.grid.GetFocusedCardIndex();
 }
});
var GridViewEndlessPagingHelper = ASPx.CreateClass(GridBaseEndlessPagingHelper, {
 constructor: function(grid){
  this.constructor.prototype.constructor.call(this, grid);
  grid.FocusedRowChanged.AddHandler(function() { this.OnGridFocusedItemChanged(); }.aspxBind(this));
 },
 GetFocusedItemIndex: function(){
  return this.grid.GetFocusedRowIndex();
 },
 IsEditRowHasDisplayedDataRow: function() { return this.grid.IsEditRowHasDisplayedDataRow(); },
 IsDataItemID: function(id){
  return id.indexOf(ASPx.GridViewConsts.GroupRowID) > 0 || id.indexOf(ASPx.GridViewConsts.DataRowID) > 0;
 },
 GetItemElements: function() {
  if(this.IsBatchEditMode()) {
   var helper = this.grid.GetBatchEditHelper();
   if(helper && helper.IsChangesViewVisible())
    return helper.GetSavedDataRowsLayout();
  }
  return GridBaseEndlessPagingHelper.prototype.GetItemElements.call(this);
 },
 GetEditingItemElements: function(){
  return this.grid.GetEditingRowElements();
 },
 UpdateCellMergingState: function(cellMergeState) { 
  if(!cellMergeState || cellMergeState.length !== 3) 
   return;
  var serverInfo = cellMergeState[0];
  var splittedColumnIndices = cellMergeState[1];
  var prevRowVisibleIndex = cellMergeState[2];
  var layoutHelper = this.grid.GetLayoutHelper();
  var prevState = layoutHelper.GetMergedCellServerInfo();
  if(Object.keys(prevState).length === 0) {
   layoutHelper.SetMergedCellServerInfo(serverInfo);
   return;
  }
  for(var columnIndex in prevState) {
   if(!prevState.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   var oldColumnIntervals = prevState[columnIndex];
   var newColumnIntervals = serverInfo[columnIndex];
   if(!newColumnIntervals || newColumnIntervals.length === 0)
    continue;
   var lastOldInterval = oldColumnIntervals[oldColumnIntervals.length - 1];
   var requireMergeIntervals = splittedColumnIndices.indexOf(columnIndex) > -1 && lastOldInterval[1] === prevRowVisibleIndex;
   for(var i = 0; i < newColumnIntervals.length; i++) {
    var newInterval = newColumnIntervals[i];
    if(i === 0) {
     if(requireMergeIntervals) {
      newInterval[0] = lastOldInterval[0];
      ASPx.Data.ArrayRemove(oldColumnIntervals, lastOldInterval);
     }
     var cell = layoutHelper.GetCell(newInterval[0], columnIndex, ASPx.GridViewRowType.Data);
     var newRowSpan = newInterval[1] - newInterval[0] + 1;
     ASPx.Attr.ChangeCellSpanCount(cell, newRowSpan);
    }
    oldColumnIntervals.push(newInterval);
   }
  }
 },
 UpdateGroupLevelState: function(groupLevelState) { 
  if(!groupLevelState) return;
  var layoutHelper = this.grid.GetLayoutHelper();
  var prevState = layoutHelper.GetGroupLevelServerInfo();
  if(Object.keys(prevState).length === 0) {
   layoutHelper.SetGroupLevelServerInfo(groupLevelState);
   return;
  }
  for(var level in groupLevelState) {
   if(!groupLevelState.hasOwnProperty(level)) continue;
   level = parseInt(level);
   var oldIntervals = prevState[level];
   var newIntervals = groupLevelState[level];
   if(!oldIntervals || oldIntervals.length === 0) {
    prevState[level] = newIntervals;
    continue;
   }
   var firstNewInterval = newIntervals[0];
   var firstIntervalStart = firstNewInterval[0];
   var result = [ ];
   for(var i = 0; i < oldIntervals.length; i++) {
    var interval = oldIntervals[i];
    var start = interval[0];
    var end = interval[1];
    if(end < firstIntervalStart) {
     result.push(interval);
    } else {
     firstNewInterval[0] = Math.min(start, firstIntervalStart);
     break;
    }
   }
   prevState[level] = result.concat(newIntervals);
  }
  layoutHelper.SetGroupLevelServerInfo(prevState);
 },
 CorrectDataItemID: function(item, prevVisibleIndex){
  if(!this.grid.IsBandedDataRowID(item.id))
   return GridBaseEndlessPagingHelper.prototype.CorrectDataItemID.call(this, item, prevVisibleIndex);
  var supposedVisibleIndex = prevVisibleIndex;
  var regEx = this.grid.GetItemVisibleIndexRegExp();
  var matches = regEx.exec(item.id);
  if(matches && matches.length == 3) {
   var visibleIndex = parseInt(matches[2]);
   var level = this.grid.GetBandedDataRowLevelByID(item.id);
   if(level < 1)
    supposedVisibleIndex++;
   if(visibleIndex != supposedVisibleIndex)
    item.id = item.id.replace(regEx, "$1" + supposedVisibleIndex + "_" + level);
  }
  return supposedVisibleIndex;
 },
 RemoveItemFromLayout: function(itemElement) {
  if(this.IsBatchEditMode()) {
   var helper = this.grid.GetBatchEditHelper();
   var recordKey = helper.owner.GetRecordKeyByElement(itemElement);
   helper.MoveEditorsFromDeletingItem(recordKey);
  }
  GridBaseEndlessPagingHelper.prototype.RemoveItemFromLayout.call(this, itemElement);
 },
 RemoveDataItems: function(removeIndex, removeCount) { 
  GridBaseEndlessPagingHelper.prototype.RemoveDataItems.call(this, removeIndex, removeCount);
  if(this.grid.hasDetailRows && removeIndex >= 0 && removeCount > 0) {
   var indices = ASPx.Data.Range(removeCount, removeIndex);
   for(var i = 0; i < indices.length; i++)
    ASPx.RemoveElement(this.grid.GetDetailRow(indices[i]));
  }
 }
});
ASPx.GridViewEndlessPagingHelper = GridViewEndlessPagingHelper;
ASPx.CardViewEndlessPagingHelper = CardViewEndlessPagingHelper;
})();

(function() {
var BatchEditFocusHelper = ASPx.CreateClass(null, {
 FocusHolderInputID: "BatchEditFocusHolderInput",
 constructor: function(batchEditHelper) {
  this.batchEditHelper = batchEditHelper;
  this.ownerControl = this.batchEditHelper.GetOwnerControl();
  this.activeElementsHash = { };
  this.editTemplateActiveElementsHash = { };
  this.lockEdit = false;
  this.forceRefocusEditor = false;
  this.focusedEditorColumnIndex = -1;
  this.focusedColumnKey = null;
  this.focusHolderInput = null;
  this.currentDataCellMouseDownCoords = null;
  BatchEditMouseDownWatcher.getInstance().Add(this);
 },
 AttachEventToEditor: function(columnIndex, eventName, action) { },
 GetMainTable: function() { },
 GetCellFocusHelper: function() { },
 RaiseBatchEditTemplateCellFocused: function(columnIndex) { },
 TryShowColumn: function(columnIndex, showFullRect) { },
 GetRecordKeys: function(doNotIncludeDeleted) { return this.batchEditHelper.GetRecordKeys(doNotIncludeDeleted); },
 GetRecord: function(recordKey) { return this.GetBatchEditHelperOwner().GetRecord(recordKey); },
 GetDataItem: function(recordKey) { return this.GetRecord(recordKey); },
 GetBatchEditHelperOwner: function() { return this.batchEditHelper.owner; },
 IsEditing: function() { return this.batchEditHelper.IsEditing(); },
 GetTemplateColumnIndices: function() { return this.batchEditHelper.GetTemplateColumnIndices(); },
 IsSingleEditMode: function() { return this.batchEditHelper.IsSingleEditMode(); },
 IsEditingRecord: function(recordKey) { return this.batchEditHelper.IsEditingRecord(recordKey); },
 IsColumnEditing: function(columnIndex) { return this.batchEditHelper.IsColumnEditing(columnIndex); },
 GetEditor: function(columnIndex) { return this.batchEditHelper.GetEditor(columnIndex); },
 IsEditTemplateColumn: function(columnIndex) { return this.batchEditHelper.IsEditTemplateColumn(columnIndex); },
 IsNewItemOnTop: function() { return this.batchEditHelper.IsNewItemOnTop(); },
 GetVisibleColumnIndices: function() { return this.batchEditHelper.GetVisibleColumnIndices(); },
 GetEditColumnIndices: function() { return this.batchEditHelper.GetEditColumnIndices(); },
 GetEditingRecordKey: function() { return this.batchEditHelper.GetEditingRecordKey(); },
 GetEditingDataItemElement: function() { return this.GetDataItem(this.GetEditingRecordKey()); },
 GetIsEditingDataItemChild: function(element) { return this.GetBatchEditHelperOwner().GetIsRecordChild(this.GetEditingDataItemElement(), element); },
 GetDataCell: function(recordKey, columnIndex) { return this.batchEditHelper.GetDataCell(recordKey, columnIndex); },
 GetColumnIndexByChild: function(element) { return this.batchEditHelper.GetColumnIndexByChild(element); },
 GetHighlightDeletedItems: function() { return  this.batchEditHelper.GetHighlightDeletedItems(); },
 IsDeletedItemIndex: function(recordKey) { return this.batchEditHelper.IsDeletedRecord(recordKey); },
 IsActiveElementFocused: function() { 
  if(!document.activeElement) return false;
  for(var key in this.activeElementsHash) {
   if(!this.activeElementsHash.hasOwnProperty(key)) continue;
   var itemActiveElements = this.activeElementsHash[key];
   if(!itemActiveElements) continue;
   for(var columnKey in itemActiveElements) {
    if(!itemActiveElements.hasOwnProperty(columnKey)) continue;
    var cellActiveElements = itemActiveElements[columnKey];
    if(ASPx.Data.ArrayIndexOf(cellActiveElements, document.activeElement) > -1)
     return true;
     }
  } 
  return false;
 },
 IsCommandColumnItem: function(element) { return false; },
 StartEdit: function(recordKey, columnIndex) { this.batchEditHelper.StartEdit(recordKey, columnIndex); },
 EndEdit: function() { return this.batchEditHelper.EndEdit(); },
 Update: function() {
  this.AttachEvents();
  this.LoadActiveElements();
  this.lockEdit = false;
  this.frozenHeightElement = null;
 },
 CanStartEdit: function() { return !this.lockEdit; },
 CanStartEditOnCellClick: function() {
  var helper = this.GetCellFocusHelper();
  if(helper)
   return helper.IsMainTableMouseDownOnFocusedCell();
  return true;
 },
 OnBeforeDataItemDeleted: function(deletedRecordKey) {
  if(this.IsMainTableHasFocus())
   this.FocusMainTable();
 },
 OnDataItemDeleted: function(recordKey) {
  if(!this.IsMainTableHasFocus()) return;
  var columnIndex = null;
  var highlightMode = this.GetHighlightDeletedItems();
  if(highlightMode)
   columnIndex = this.batchEditHelper.GetRecoverButtonColumnKey();
  else {
   var focusedCellInfo = this.GetCellFocusHelper().GetFocusedCellInfo();
   if(!focusedCellInfo) 
    return;
   columnIndex = focusedCellInfo.columnIndex;
   recordKey = this.batchEditHelper.FindNextNotDeletedRecordKey(recordKey);
  }
  this.TryFocusCell(recordKey, columnIndex, true);
 },
 OnBeforeDataItemRecover: function(recordKey) {
  if(!this.IsMainTableHasFocus()) return;
  this.FocusMainTable();
  this.TryFocusCell(recordKey, this.batchEditHelper.GetRecoverButtonColumnKey(), true);
 },
 OnDataItemAdded: function(key) {
  this.LoadDataItemActiveElements(key);
 },
 OnEditStarted: function(recordKey, columnIndices, focusedColumn) {
  if(focusedColumn)
   this.FocusColumnEditor(focusedColumn.index);
  this.lockEndEditOnLostFocus = true;
  window.setTimeout(function() { this.lockEndEditOnLostFocus = false; }.aspxBind(this), 0);
 },
 OnBeforeEditEnded: function() {
  if(this.endEditOnClickTrackingInfo) {
   this.endEditOnClickTrackingInfo.isEndEditCalled = true;
   this.endEditOnClickTrackingInfo.editingRecordKey = this.GetEditingRecordKey();
   this.endEditOnClickTrackingInfo.focusedColumnKey = this.GetFocusedColumnKey();
  }
 },
 OnEditEnded: function() {
  this.BlurFocusedEditor();
 },
 CanEditColumn: function(columnKey) {
  var columnIndex = this.ResolveColumnIndex(columnKey);
  return this.batchEditHelper.CanEditColumn(columnIndex);
 },
 GetColumnKeyByChild: function(element) { return this.GetColumnIndexByChild(element); },
 ResolveColumnKey: function(columnIndex) {
  if(!ASPx.IsExists(columnIndex)) 
   return -1;
  if(typeof(columnIndex) === "string")
   return columnIndex;
  if(typeof(columnIndex) === "number")
   return columnIndex.toString();
  return null;
 },
 ResolveColumnIndex: function(columnKey) { 
  if(!ASPx.IsExists(columnKey)) 
   return -1;
  if(typeof(columnKey) === "number")
   return columnKey;
  if(typeof(columnKey) === "string") {
   var columnIndex = parseInt(columnKey);
   return isNaN(columnIndex) ? -1 : columnIndex;
  }
  return -1;
 },
 LoadActiveElements: function () {
  this.ResetActiveElementsHash();
  this.LoadAllRecordActiveElements();
  var columnIndices = this.GetTemplateColumnIndices();
  for(var i = 0; i < columnIndices.length; i++)
   this.LoadEditTemplateActiveElements(columnIndices[i]);
 },
 LoadAllRecordActiveElements: function () {
  var keys = this.GetRecordKeys();
  for(var i = 0; i < keys.length; i++)
   this.LoadDataItemActiveElements(keys[i]);  
 },
 LoadDataItemActiveElements: function (recordKey) {
  this.ResetDataItemActiveElementsHash(recordKey);
  var elementsInfo = this.GetDataItemActiveElementsInfo(recordKey);
  for (var i = 0; i < elementsInfo.length; i++) {
   var element = elementsInfo[i].element;
   var columnKey = elementsInfo[i].columnKey;
   this.PushElementToActiveElementsHash(element, recordKey, columnKey);
   this.PrepareRecordActiveElement(element, recordKey, columnKey);
  }
 },
 ResetDataItemActiveElementsHash: function (recordKey) { this.activeElementsHash[recordKey] = null; },
 ResetActiveElementsHash: function () { this.activeElementsHash = {}; },
 PushElementToActiveElementsHash: function (element, recordKey, columnIndex) {
  if (!this.activeElementsHash[recordKey])
   this.activeElementsHash[recordKey] = {};
  var recordInfo = this.activeElementsHash[recordKey];
  if (!recordInfo[columnIndex])
   recordInfo[columnIndex] = [];
  recordInfo[columnIndex].push(element);
 },
 PrepareRecordActiveElement: function (element, recordKey, columnKey) {
  element.dxgvColumnKey = columnKey;
  element.dxgvRecordKey = recordKey;
  this.AttachEvent(element, "keydown", this.OnActiveElementKeyDown.bind(this));
  if (!this.IsSingleEditMode())
   this.AttachEvent(element, "blur", this.OnActiveElementBlur.bind(this));
 },
 LoadEditTemplateActiveElements: function(columnIndex) {
  var elements = [ ];
  var editorContainer = this.batchEditHelper.GetEditorContainer(columnIndex);
  var inputs = ASPx.GetNodesByTagName(editorContainer, "INPUT");
  for(var i = 0; i < inputs.length; i++) {
   var input = inputs[i];
   if(input.type !== "hidden")
    elements.push(input);
  }
  var links = ASPx.GetNodesByTagName(editorContainer, "A");
  for(var i = 0; i < links.length; i++)
   elements.push(links[i]);
  this.SortEditTemplateActiveElements(elements);
  this.editTemplateActiveElementsHash[columnIndex] = elements;
 },
 SortDataItemActiveElements: function(rowInfo) { },
 SortEditTemplateActiveElements: function(elements) { },
 GetDataItemActiveElementsInfo: function(recordKey) {
  var dataItem = this.GetDataItem(recordKey);
  if(!dataItem) 
   return [ ];
  var result = [ ];
  var elements = this.GetDataItemChildElements(dataItem);
  for(var i = 0; i < elements.length; i++) {
   var element = elements[i];
   var columnKey = this.GetColumnKeyByChild(element);
   if(columnKey !== null && !this.CanEditColumn(columnKey))
    result.push({ element: element, columnKey: columnKey });
  }
  return result;
 },
 GetDataItemChildElements: function(dataItem) {
  if(dataItem instanceof Array)
   return [].concat.apply([], dataItem.map(
    function(item) {
     return [].slice.call(this.GetDataItemChildElements(item));
    }.aspxBind(this)));
  return ASPx.FindChildActionElements(dataItem);
 },
 OnActiveElementKeyDown: function(e) {
  var keyCode = ASPx.Evt.GetKeyCode(e);
  switch(keyCode) {
   case ASPx.Key.Esc:
    this.FocusMainTable();
    break;
   case ASPx.Key.Tab:
    var src = ASPx.Evt.GetEventSource(e);
    if(this.MoveFocusFromActiveElement(src, e.shiftKey))
     ASPx.Evt.PreventEventAndBubble(e);
    break;
  }  
 },
 OnActiveElementBlur: function(e) {  
  if(this.IsEditing() && this.forceEndEditOnActiveElementBlur)
   this.EndEdit();
 },
 ForceEndEditOnActiveElementBlur: function() {
  this.forceEndEditOnActiveElementBlur = true;
  window.setTimeout(function() { this.forceEndEditOnActiveElementBlur = false; }.aspxBind(this), 50);
 },
 MoveFocusFromActiveElement: function(activeElement, isLeft) {
  var recordKey = activeElement.dxgvRecordKey;
  var columnKey = activeElement.dxgvColumnKey;
  var cellActiveElements = this.GetCellActiveElements(recordKey, columnKey);
  if(cellActiveElements.length > 1) {
   var elementIndex = ASPx.Data.ArrayIndexOf(cellActiveElements, activeElement);
   var inc = isLeft ? -1 : 1;
   var focusElementIndex = elementIndex + inc;
   if(focusElementIndex > -1 && focusElementIndex < cellActiveElements.length)
    return;
  }
  return this.MoveFocus(recordKey, columnKey, isLeft);
 },
 MoveFocusFromEditor: function(editor, isLeft) {
  return this.MoveFocus(this.GetEditingRecordKey(), editor.dxgvColumnIndex, isLeft, true);
 },
 MoveFocusNext: function() {
  if(!this.IsEditing()) return;
  return this.MoveFocus(this.GetEditingRecordKey(), this.GetFocusedColumnKey());
 },
 MoveFocusPrev: function() {
  if(!this.IsEditing()) return;
  return this.MoveFocus(this.GetEditingRecordKey(), this.GetFocusedColumnKey(), true);
 },
 MoveFocus: function(recordKey, columnKey, isLeft, fromEditor) {
  columnKey = this.ResolveColumnKey(columnKey);
  var endEdit = function() { window.setTimeout(function() { this.EndEdit(); }.aspxBind(this), 0); }.aspxBind(this);
  var cellInfo = this.GetNewFocusedCellInfo(recordKey, columnKey, isLeft);
  if(!cellInfo || cellInfo.addNewRow) {
   endEdit();
   return false;
  }
  var newRecordKey = cellInfo.recordKey;
  var newColumnKey = cellInfo.columnKey;
  this.focusedColumnKey = newColumnKey;
  if(this.CanFocusEditColumn(newColumnKey)) {
   this.MoveFocusToEditCell(newRecordKey, newColumnKey, recordKey, columnKey, isLeft, fromEditor);
   return true;
  } 
  var isRowEditMode = !this.IsSingleEditMode();
  this.lockEndEditOnLostFocus = isRowEditMode && this.IsEditingRecord(newRecordKey) && fromEditor;
  var activeElementFocused = this.TryFocusCellActiveElement(newRecordKey, newColumnKey, isLeft);
  if(isRowEditMode && !this.IsEditingRecord(newRecordKey) && !fromEditor || !isRowEditMode && activeElementFocused)
   endEdit();
  return activeElementFocused;
 },
 MoveFocusToEditCell: function(recordKey, columnKey, prevRecordKey, prevColumnKey, isLeft, fromEditor) {
  var columnIndex = this.ResolveColumnIndex(columnKey);
  if(this.IsSingleEditMode() || !this.IsEditing() || recordKey !== prevRecordKey)
   window.setTimeout(function() { 
    this.MoveFocusByStartEditing(recordKey, columnIndex, isLeft, fromEditor); 
   }.aspxBind(this), 0);
  else
   this.MoveFocusToSiblingEditCell(recordKey, columnIndex, isLeft);
  this.TryShowColumn(this.ResolveHtmlColumnIndex(columnIndex, recordKey), true);
 },
 MoveFocusByStartEditing: function(recordKey, columnIndex, isLeft, fromEditor) {
  this.StartEdit(recordKey, columnIndex); 
  if(!this.IsEditing())
   this.MoveFocus(recordKey, columnIndex, isLeft, fromEditor);
 },
 TryFocusCellActiveElement: function(recordKey, columnKey, isLeft) {
  var activeElements = this.GetCellActiveElements(recordKey, columnKey);
  if(activeElements.length === 0)
   return false;
  var index = isLeft ? activeElements.length - 1 : 0;
  var element = activeElements[index];
  ASPx.SetFocus(element);
  return true;
 },
 CanFocusEditColumn: function(columnKey) {
  if(!this.IsSingleEditMode() && this.IsEditing())
   return this.IsColumnEditing(this.ResolveColumnIndex(columnKey));
  return this.CanEditColumn(columnKey);
 },
 MoveFocusToSiblingEditCell: function(recordKey, newColumnIndex, isLeft) { 
  var prevFocusedColumnIndex = this.focusedEditorColumnIndex;
  if(this.CanEditColumn(prevFocusedColumnIndex))
   this.lockEndEditOnLostFocus = true;
  window.setTimeout(function() {
   this.BlurEditor(prevFocusedColumnIndex);
   this.FocusColumnEditor(newColumnIndex, isLeft);
  }.aspxBind(this), 0);
 },
 FocusColumnEditor: function(columnIndex, isLeft) {
  if(this.IsEditTemplateColumn(columnIndex))
   this.FocusEditTemplateEditor(columnIndex, isLeft);
  else
   this.FocusDefaultEditor(columnIndex);
  this.focusedColumnKey = this.ResolveColumnKey(columnIndex);
 },
 FocusDefaultEditor: function(columnIndex) {
  var editor = this.GetEditor(columnIndex);
  if(!editor) return;
  editor.Focus();
 },
 FocusEditTemplateEditor: function(columnIndex, isLeft) {
  var processed = this.RaiseBatchEditTemplateCellFocused(columnIndex);
  if(processed) return;
  var activeElements = this.editTemplateActiveElementsHash[columnIndex];
  if(!activeElements || activeElements.length === 0)
   return;
  var element = !isLeft ? activeElements[0] : activeElements[activeElements.length - 1];
  ASPx.SetFocus(element);
 },
 BlurEditor: function(columnIndex) {
  var editor = this.GetEditor(columnIndex);
  if(!editor || editor !== ASPx.GetFocusedEditor()) 
   return;
  var input = editor.GetFocusableInputElement() || editor.GetInputElement();
  if(input)
   input.blur();
 },
 BlurFocusedEditor: function() {
  this.BlurEditor(this.focusedEditorColumnIndex);
 },
 GetNewFocusedCellInfo: function(recordKey, columnKey, isLeft) {
  var inc = isLeft ? -1 : 1;
  columnKey = this.GetNewFocusedColumnKey(recordKey, columnKey, inc);
  if(columnKey !== null)
   return { recordKey: recordKey, columnKey: columnKey };
  var addNewRow = false;
  var includeDeletedIndices = this.GetHighlightDeletedItems();
  var keys = this.GetRecordKeys(!includeDeletedIndices);
  var index = ASPx.Data.ArrayIndexOf(keys, recordKey) + inc;
  if(index < 0 && this.IsNewItemOnTop() || index == keys.length && !this.IsNewItemOnTop()) {
   addNewRow = true;
   columnKey = null;
   recordKey = null;
  } else if(index >= 0 && index < keys.length) {
   recordKey = keys[index];
  } else
   return null;
  columnKey = this.GetNewFocusedColumnKey(recordKey, columnKey, inc);
  return { recordKey: recordKey, columnKey: columnKey, addNewRow: addNewRow };
 },
 GetNewFocusedColumnKey: function(recordKey, columnKey, inc) {
  var columnKeys = this.GetVisibleColumnKeys();
  var i = ASPx.Data.ArrayIndexOf(columnKeys, columnKey);
  if(i < 0) 
   i = inc < 0 ? columnKeys.length : - 1; 
  do {
   i = i + inc;
   columnKey = columnKeys[i];
   if(this.CanFocusEditCell(recordKey, columnKey))
    return columnKey;
  } while(i >= 0 && i < columnKeys.length);
  return null;
 },
 CanFocusEditCell: function(recordKey, columnKey) {
  var canEditCell = this.CanFocusEditColumn(columnKey) && !this.IsDeletedItemIndex(recordKey);
  var canFocusCell = this.IsCellVisible(recordKey, columnKey) && (canEditCell || this.GetCellActiveElements(recordKey, columnKey).length > 0);
  return canFocusCell && this.TryFocusCell(recordKey, this.ResolveColumnIndex(columnKey));
 },
 IsCellVisible: function(recordKey, columnKey) {
  if(!ASPx.IsExists(columnKey)) return false;
  return this.batchEditHelper.IsCellVisible(recordKey, this.ResolveColumnIndex(columnKey));
 },
 GetVisibleColumnKeys: function() {
  var result = [ ];
  var visibleColumnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < visibleColumnIndices.length; i++)
   result.push(this.ResolveColumnKey(visibleColumnIndices[i]));
  return result;
 },
 AttachEvents: function() {
  var columnIndices = this.GetEditColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   this.AttachEventToEditor(columnIndex, "GotFocus", this.OnEditorGotFocus.bind(this));
   this.AttachEventToEditor(columnIndex, "LostFocus", this.OnEditorLostFocus.bind(this));
   this.AttachEventToEditor(columnIndex, "KeyDown", this.OnEditorKeyDown.bind(this));
   this.AttachEventToEditor(columnIndex, "ValueChanged", this.OnEditorValueChanged.bind(this));
   var editor = this.GetEditor(columnIndex);
   if(this.batchEditHelper.IsComboBoxWithServerItemsColumn(columnIndex))
    this.AttachEventToEditor(columnIndex, "DropDown", this.OnComboBoxDropDown.bind(this));
   if(this.batchEditHelper.IsComboBoxCallbackModeColumn(columnIndex)) {
    this.AttachEventToEditor(columnIndex, "EndCallback", this.OnComboBoxEndCallback.bind(this));
    if(typeof(ASPxClientComboBoxBase) !== "undefined" && editor instanceof ASPxClientComboBoxBase)
     editor.collectCallbackIDs = true;
   }
   if(typeof(ASPxClientDropDownEdit) != "undefined" && editor instanceof ASPxClientDropDownEdit)
    editor.allowFocusDropDownWindow = false;
   if(ASPx.Ident.IsASPxClientEdit(editor))
    editor.onVirtualKeyboardUITouchStart = this.OnMainTableMouseDown.bind(this);
  }
  ASPx.Evt.AttachEventToElement(this.GetMainTable(), "mousedown", this.OnMainTableMouseDown.bind(this));
  this.AttachGridMainElementEvents();
 },
 AttachGridMainElementEvents: function() {
  var element = this.ownerControl.GetMainElement();
  this.AttachEvent(element, "mousedown", this.OnMainElementMouseDown.bind(this));
  this.AttachEvent(element, "mouseout", this.OnMainElementMouseUp.bind(this));
  this.AttachEvent(element, "mouseup", this.OnMainElementMouseUp.bind(this));
 },
 AttachEvent: function(element, eventName, eventHandler) {
  var eventMarker = "beh" + eventName;
  if(!element || element[eventMarker])
   return;
  ASPx.Evt.AttachEventToElement(element, eventName, eventHandler);
  element[eventMarker] = true;
 },
 OnEditorGotFocus: function (s, e) {
  if (ASPx.GridCommonUtils.IsBatchEditFocusEventsLocked(this.ownerControl)) return;
  s.dxgvSkipValueChanged = false;
  this.lockEdit = false;
  this.focusedEditorColumnIndex = s.dxgvColumnIndex;
  this.TryShowColumn(this.ResolveHtmlColumnIndex(s.dxgvColumnIndex, this.GetEditingRecordKey()));
 },
 createFocusHolderInput: function() {
  this.focusHolderInput = document.createElement("INPUT");
  this.focusHolderInput.id = this.ownerControl.name + "_" + this.FocusHolderInputID;
  this.focusHolderInput.style.width = "0px";
  this.focusHolderInput.style.height = "0px";
  this.focusHolderInput.style.padding = "0";
  this.focusHolderInput.style.border = "none";
  this.focusHolderInput.style.position = "absolute";
  this.setFocusHolderInputInitialPosition();
  ASPx.Evt.AttachEventToElement(this.focusHolderInput, "blur", function(e) { this.setFocusHolderInputInitialPosition(); }.bind(this));
  var mainTable = this.GetMainTable();
  mainTable.parentNode.insertBefore(this.focusHolderInput, mainTable);
 },
 setFocusHolderInputInitialPosition: function() {
  this.focusHolderInput.style.left = "-100px";
  this.focusHolderInput.style.top = "-100px";
 },
 ensureFocusHolderInput: function() {
  this.focusHolderInput = this.ownerControl.GetChildElement(this.FocusHolderInputID);
  if(!this.focusHolderInput)
   this.createFocusHolderInput();
 },
 setFocusToFocusHolderInput: function() {
  this.ensureFocusHolderInput();
  this.focusHolderInput.style.left = this.currentDataCellMouseDownCoords.x + "px";
  this.focusHolderInput.style.top = this.currentDataCellMouseDownCoords.y + "px";
  this.focusHolderInput.focus();
 },
 needHoldFocusOnEditorLostFocus: function() {
  return ASPx.Browser.VirtualKeyboardSupported && this.batchEditHelper.IsStartEditOnClick() && this.currentDataCellMouseDownCoords !== null;
 },
 OnEditorLostFocus: function(s, e) {
  if(this.needHoldFocusOnEditorLostFocus())
   this.setFocusToFocusHolderInput();
  if (ASPx.GridCommonUtils.IsBatchEditFocusEventsLocked(this.ownerControl)) return;
  if(this.forceRefocusEditor || !this.lockEndEditOnLostFocus && !this.EndEdit()) {
   this.RefocusEditor(s);
   return;
  }
  s.ResetEditorState();
  this.lockEndEditOnLostFocus = false;
  this.focusedEditorColumnIndex = -1;
  this.FocusMainTableIfRequired();
 },
 RefocusEditor: function(editor) {
  this.lockEdit = true;
  ASPx.Timer.ClearTimer(this.removeLockEditTimerID);
  this.removeLockEditTimerID = window.setTimeout(function() { this.lockEdit = false; }.aspxBind(this), 50);
  this.forceRefocusEditor = false;
  editor.Focus();
 },
 OnEditorValueChanged: function(s, e) {
  if(!s.dxgvSkipValueChanged) 
   this.batchEditHelper.OnEditorValueChanged(s, s.dxgvColumnIndex);
 },
 OnEditorKeyDown: function(s, e) {
  var keyCode = ASPx.Evt.GetKeyCode(e.htmlEvent);
  if(this.EditorHasVisiblePopupWindow(s) && (keyCode === ASPx.Key.Enter || keyCode === ASPx.Key.Esc))
   return;
  switch(keyCode) {
   case ASPx.Key.Esc:
    this.OnEditorEscapePress(s);
    break;
   case ASPx.Key.Enter:
    if(!this.batchEditHelper.IsMemoEdit(s))
     this.OnEditorEnterPress(s, e);
    break;
   case ASPx.Key.Tab:
    this.OnEditorTabPress(s, e);
    break;
  }
 },
 OnEditorEscapePress: function(sender) {
  sender.dxgvSkipValueChanged = true;
  this.ForceFocusMainTableOnEditorLostFocus();
  this.lockEndEditOnLostFocus = false;
  this.BlurEditor(sender.dxgvColumnIndex);
 },
 OnEditorEnterPress: function(sender, event) {
  if(this.ownerControl.accessibilityCompliant)
   this.OnEditorEscapePress(sender);
  else
   this.OnEditorTabPress(sender, event);
 },
 OnEditorTabPress: function(sender, event) {
  if(this.MoveFocusFromEditor(sender, event.htmlEvent.shiftKey))
   ASPx.Evt.PreventEventAndBubble(event.htmlEvent);
 },
 EditorHasVisiblePopupWindow: function(editor) {
  if(!window.ASPxClientDropDownEditBase)
   return false;
  return editor instanceof ASPxClientDropDownEditBase && editor.GetPopupControl() && editor.GetPopupControl().InternalIsWindowVisible(-1);
 },
 OnComboBoxDropDown: function(s, e) {
  s.UpdateDropDownPositionAndSize();
 },
 OnComboBoxEndCallback: function(s, e) {
  var info = this.batchEditHelper.GetComboBoxCallbackModeItemsInfo()[s.dxgvColumnIndex];
  var isServerEventsMode = this.batchEditHelper.IsComboBoxWithServerItemsColumn(s.dxgvColumnIndex);
  var serverIndices = s.cpLoadedOnCallbackIndices;
  this.batchEditHelper.RemoveDuplicatedItem(s);
  if(info && (serverIndices || isServerEventsMode)) {
   for(var i = 0; i < s.GetItemCount() ; i++) {
    var item = s.GetItem(i);
    var value = item.value;
    var hasValueInfo = info.hasOwnProperty(value);
    var isServerIndexLoaded = serverIndices && ASPx.IsExists(serverIndices[value]);
    var needUpdateServerIndex = hasValueInfo && isServerIndexLoaded && info[value].itemServerIndex !== serverIndices[value];
    if(!hasValueInfo || needUpdateServerIndex) {
     var serverIndex = isServerEventsMode ? -1 : serverIndices[value];
     info[value] = { texts: item.texts, imageUrl: item.imageUrl, itemServerIndex: serverIndex };
    }
   }
  }
 },
 OnMainTableMouseDown: function(e) { 
  this.forceRefocusEditor = false;
  this.lockEndEditOnLostFocus = false;
  this.lockUserEndEdit = false;
  var src = ASPx.Evt.GetEventSource(e);
  var targetColumnIndex = this.GetColumnIndexByChild(src);
  var targetEditor = this.GetEditor(targetColumnIndex);
  var targetDataCell = this.GetBatchEditHelperOwner().GetDataCellByChild(src);
  if(targetDataCell && (!targetEditor || !ASPx.GetIsParent(targetEditor.GetMainElement(), src)))
   this.currentDataCellMouseDownCoords = { x: e.x, y: e.y };
  var dataItem = this.GetEditingDataItemElement();
  if(!dataItem || dataItem.length === 0 || !this.IsEditing()) 
   return;
  this.StartEndEditOnClickTraking(src);
  if(!this.IsSingleEditMode()) {
   if(!this.GetIsEditingDataItemChild(src))
    return;
   var sourceColumnIndex = this.ResolveColumnIndex(this.GetFocusedColumnKey());
   if(this.CanEditColumn(sourceColumnIndex) && this.CanEditColumn(targetColumnIndex) && sourceColumnIndex !== targetColumnIndex) {
    this.lockEndEditOnLostFocus = true;
    this.lockUserEndEdit = true;
    window.setTimeout(function() { this.lockUserEndEdit = false; }.aspxBind(this), 200);
   }
   this.focusedColumnKey = this.ResolveColumnKey(targetColumnIndex);
  }
  if(this.focusedEditorColumnIndex < 0) {
   this.lockEndEditOnLostFocus = false;
   return;
  }
  var dataCell = this.GetDataCell(this.GetEditingRecordKey(), this.focusedEditorColumnIndex);
  var editor = this.GetEditor(this.focusedEditorColumnIndex);
  if(!editor || !dataCell) return;
  if(!ASPx.GetIsParent(dataCell, src))
   return;
  var editorMainElement = ASPx.IsFunction(editor.GetICBMainElement) ? editor.GetICBMainElement() : editor.GetMainElement(); 
  var editorElements = [ editorMainElement ];
  if(ASPx.IsFunction(editor.GetPopupControl)) { 
   var editorPopup = editor.GetPopupControl();
   if(editorPopup)
    editorElements.push(editorPopup.GetWindowElement(-1));
  }
  for(var i = 0; i < editorElements.length; i++) {
   if(ASPx.GetIsParent(editorElements[i], src)) {
    this.lockEndEditOnLostFocus = false;
    return;
   }
  }
  this.forceRefocusEditor = true;
 },
 StartEndEditOnClickTraking: function(src) {
  if(this.IsCommandColumnItem(src)) return;
  var helper = this.batchEditHelper;
  var recordElement = helper.GetRecordElementByChild(src);
  if(!recordElement) return;
  var key = this.GetBatchEditHelperOwner().GetRecordKeyByElement(recordElement);
  var columnIndex = helper.GetColumnIndexByChild(src);
  var editColumnIndex = this.ResolveColumnIndex(this.GetFocusedColumnKey());
  if(ASPx.IsExists(key) && editColumnIndex > -1 && columnIndex > -1 && (columnIndex !== editColumnIndex || key !== this.GetEditingRecordKey())) {
   ASPx.Timer.ClearTimer(this.endEditOnClickTrackingTimerId);
   this.endEditOnClickTrackingInfo = { isEndEditCalled: false };
  }
 },
 StopEndEditOnClickTraking: function() {
  if(this.endEditOnClickTrackingInfo) {
   ASPx.Timer.ClearTimer(this.endEditOnClickTrackingTimerId);
   this.endEditOnClickTrackingTimerId = window.setTimeout(function() { delete this.endEditOnClickTrackingInfo; }.bind(this), 150);
  }
 },
 IsEndEditCalledDuringTableClick: function() {
  var info = this.endEditOnClickTrackingInfo;
  if(!info || !info.isEndEditCalled)
   return false;
  return info.editingRecordKey === this.GetEditingRecordKey() && info.focusedColumnKey === this.GetFocusedColumnKey();
 },
 OnMainElementMouseDown: function(e) {
  if(!this.IsEditing()) return;
  var recordKey = this.GetEditingRecordKey();
  var columnIndex = this.batchEditHelper.editedColumnIndices[0];
  if(this.IsStretchedCell(this.GetDataCell(recordKey, columnIndex))) {
   this.frozenHeightElement = this.GetElementToFreezeHeight(recordKey, columnIndex);
   this.batchEditHelper.FixElementHeight(this.frozenHeightElement);
  }
 },
 OnMainElementMouseUp: function(e) {
  this.currentDataCellMouseDownCoords = null;
  this.StopEndEditOnClickTraking();
  if(!this.frozenHeightElement) return;
  this.batchEditHelper.RestoreElementHeight(this.frozenHeightElement);
  this.frozenHeightElement = null;
 },
 IsStretchedCell: function(cell) {
  if(!cell) return false;
  var offsetHeght = Math.floor(this.batchEditHelper.GetElementSizes(cell).height);
  var height = ASPx.PxToInt(cell.style.height);
  var diff = offsetHeght - (height + ASPx.GetTopBottomBordersAndPaddingsSummaryValue(cell));
  return height > 0 && diff > 0;
 },
 GetElementToFreezeHeight: function(recordKey, columnIndex) { 
  var cell = this.GetDataCell(recordKey, columnIndex);
  return cell && cell.parentNode; 
 },
 GetFocusedColumnKey: function() {
  if(this.focusedEditorColumnIndex >= 0)
   return this.ResolveColumnKey(this.focusedEditorColumnIndex);
  return this.focusedColumnKey;
 },
 ResolveHtmlColumnIndex: function(columnIndex, recordKey) { return columnIndex;},
 ProcessMainTableKeyDown: function(e, focusedCellInfo) {
  var sourceTagName = ASPx.Evt.GetEventSource(e).tagName;
  var isEditableSource = sourceTagName == "INPUT" || sourceTagName == "TEXTAREA";
  if(!focusedCellInfo)
   return isEditableSource;
  if(this.IsEditing())
   return true;
  var key = ASPx.Evt.GetKeyCode(e);
  if(this.IsActiveElementFocused()) {
   if(!this.IsArrowKey(key))
    return true;
   this.FocusMainTable();
   return false;
  }
  if(isEditableSource) 
   return true;
  var columnIndex = focusedCellInfo.columnIndex;
  var recordKey = focusedCellInfo.recordKey;
  switch(key) {
   case ASPx.Key.Delete:
    this.batchEditHelper.OnDeleteKeyDown(recordKey);
    return true;
   case ASPx.Key.F2:
   case ASPx.Key.Enter:
    this.ActivateCell(recordKey, columnIndex);
    return true;
  }
 },
 ActivateCell: function(recordKey, columnIndex) {
  if(this.batchEditHelper.CanEditColumn(columnIndex))
   this.StartEdit(recordKey, columnIndex);
  else {
   var cellElements = this.GetCellActiveElements(recordKey, this.ResolveColumnKey(columnIndex));
   if(cellElements.length > 0)
    window.setTimeout(function() { cellElements[0].focus(); }, 0);  
  }
 },
 GetCellActiveElements: function(recordKey, columnKey) {
  var result = [ ];
  var dataItemInfo = this.activeElementsHash[recordKey];
  cellActiveElements = dataItemInfo && dataItemInfo[columnKey];
  if(cellActiveElements)
   result = result.concat(cellActiveElements);
  return result;
 },
 ProcessMainTableKeyUp: function(e, focusedCellInfo) {
  var focusInCheckColumn = focusedCellInfo && this.batchEditHelper.IsCheckColumn(focusedCellInfo.columnIndex);
  var needToggleCheckColumn = focusInCheckColumn && !this.IsEditing() && ASPx.Evt.GetKeyCode(e) === ASPx.Key.Space && this.CanToggleCheckBoxOnSpace(focusedCellInfo);
  if(needToggleCheckColumn) {
   this.StartEdit(focusedCellInfo.recordKey, focusedCellInfo.columnIndex);
   var editor = this.GetEditor(focusedCellInfo.columnIndex);
   if(this.IsEditing() && editor)
    editor.ToogleCheckState();
  }
 },
 CanToggleCheckBoxOnSpace: function(focusedCellInfo) { return true; },
 IsArrowKey: function(key) { return key === ASPx.Key.Down || key === ASPx.Key.Up || key === ASPx.Key.Left || key === ASPx.Key.Right; },
 TryFocusCell: function(recordKey, columnIndex, moveFocusToNeighbourIfFail) {
  var helper = this.GetCellFocusHelper();
  if(!helper) return true;
  return helper.TryFocusCell(recordKey, columnIndex, moveFocusToNeighbourIfFail, true);
 },
 ForceFocusMainTableOnEditorLostFocus: function() {
  this.forceFocusMainTableOnEditorLostFocus = true;
  window.setTimeout(function() { this.forceFocusMainTableOnEditorLostFocus = false; }.aspxBind(this), 50);  
 },
 FocusMainTableIfRequired: function() {
  if(this.forceFocusMainTableOnEditorLostFocus)
   this.FocusMainTable();
  this.forceFocusMainTableOnEditorLostFocus = false;
 },
 FocusMainTable: function() {
  var helper = this.GetCellFocusHelper();
  if(helper)
   helper.FocusMainTable();
 },
 IsMainTableHasFocus: function() {
  var helper = this.GetCellFocusHelper();
  return helper && helper.IsMainTableHasFocus();
 },
 GetFocusedCellInfo: function() {
  var helper = this.GetCellFocusHelper();
  return helper && helper.GetFocusedCellInfo();
 }
});
var BatchEditHelperOwner = ASPx.CreateClass(null, {
 CheckBoxClassName: "dxICheckBox",
 ErrorTableClass: "ErrorTable",
 ErrorTableTextCellClass: "TextCell",
 ErrorTableImageCellClass: "ErrorCell",
 TextContainerClassName: "dxgBCTC",
 BatchEditCellErrorTableID: "DXCErrorTable",
 constructor: function(control) {
  this.control = control;
 },
 IsLastCallbackProcessedAsEndless: function() { return false; },
 AllowDelete: function() { return true; },
 AllowEdit: function() { return true; },
 AllowInsert: function() { return true; },
 CanEditCell: function(recordKey, columnIndex) { return true; },
 GetBatchEditClientState: function() {  },
 GetLoadedClientModifiedValues: function() {  },
 UpdateClientModifiedValues: function(values) {  },
 GetLoadedPageValues: function() {  }, 
 GetSummaryState: function() { return null; },
 GetSelectedCells: function() { return [ ]; },
 GetVisibleColumnIndices: function() {  },
 GetColumn: function(columnIndex) {  },
 GetColumnByFieldName: function(fieldName) { },
 GetRecord: function(key) {  },
 HasKeyField: function() {  },
 IsValidRecord: function(key) { return !!this.GetRecord(key); },
 GetOrderedKeysFromOwnerControl: function() { },
 GetEditor: function(columnIndex) {  },
 GetBatchEditCommandButtons: function() { return [ ]; },
 GetProgressBarControl: function(recordKey, columnIndex) {  },  
 PrepareCommandButtonIDs: function(container, recordKey) { },
 PrepareCommandButtons: function() {  },
 IsRecoverButton: function(button) { return false; },
 IsCancelButton: function(button) { return false; },
 GetChildElement: function(idSuffix) { },
 GetMainElement: function() {  },
 GetDataCell: function(key, columnIndex) {  },
 IsRecordElement: function(element) {  },
 GetRecordKeyByElement: function(element) {  },
 GetEditorsContainer: function() {  },
 GetEditorContainer: function(columnIndex) {  },
 GetRecordError: function(key) {  },
 RemoveRecordError: function(key) {  },
 ChangeEmptyRecordVisibility: function(show) {   },
 RemoveRecordElement: function(key) {   },
 GetDataCellByChild: function(element) {   },
 GetColumnIndexByDataCell: function(cell) { },
 CreateNewItemElement: function(recordKeyInfo) { },
 UpdateRecordStyle: function(recordKey) {  },
 OnBatchEditHelperInit: function() {   },
 OnBatchEditHelperCallback: function() {   },
 OnBeforeDataItemDeleted: function(deletedItemKey, nextNotDeletedRecordKey) {   },
 OnDataItemDeleted: function(deletedRecordKey) {   },
 OnResetChanges: function(isMultiple) {   },
 OnEndMultipleResetChanges: function() {   },
 OnNewRecordAdded: function(newRecordKey) { this.EvaluateNewRecordScriptObjects(newRecordKey);  },
 OnBeforeStartEditNewRecord: function(newRecordKey) { },
 OnDataRecordRecovered: function(key) {   },
 RaiseBatchEditRecordValidating: function(recordKey, args)  {  },
 RaiseBatchEditRecordInserting: function(keyInfo)  {  },
 RaiseBatchEditRecordDeleting: function(recordKey, recordValues)  {  },
 RaiseBatchEditRecordRecovering: function(recordKey, recordValues)  {  },
 RaiseBatchEditStartEditing: function(recordKey, column, recordValues)  {  },
 RaiseBatchEditEndEditing: function(recordKey, focusedColumn, recordValues) { },
 RaiseBatchEditItemChangesCanceling: function(recordKey, recordValues) { },
 RaiseBatchEditChangesSaving: function(modifiedValuesInfo)  {  },
 RaiseBatchEditChangesCanceling: function(modifiedValuesInfo)  {  },
 RaiseBatchEditConfirmShowing: function(requestTriggerID)  {  },
 RaiseBatchEditSummaryDisplayText: function(summaryInfo, text, groupRowVisibleIndex)  {  },
 GetControlName: function() { return this.control.name; },
 IsRecordVisible: function(key) {
  var record = this.GetRecord(key);
  return !!record && ASPx.GetElementDisplay(record); 
 },
 OnRecordEditEnded: function(recordKey) { this.EnsureEllipsisTooltips(recordKey); },
 GetIsRecordChild: function(record, element) { return ASPx.GetIsParent(record, element); },
 GetEtalonCellErrorTable: function() { return this.GetChildElement(this.BatchEditCellErrorTableID); },
 PrepareEtalonElementInnerHtml: function(element, recordkey, recordKeyPlaceHolder) {
  var innerHTML = element.innerHTML;
  innerHTML = innerHTML.replace(new RegExp(recordKeyPlaceHolder, "g"), recordkey); 
  innerHTML = innerHTML.replace(new RegExp("-2147483647", "g"), recordkey); 
  innerHTML = innerHTML.replace(new RegExp("dxss_(\\d+)", "g"), function(str) { return str + Math.floor(10000 * (1 + Math.random())) + "g"; }); 
  this.SetEtalonElementInnerHtml(element, innerHTML);
  var scripts = ASPx.GetNodesByTagName(element, "script");
  ASPx.Data.ForEach(scripts, function (script) { ASPx.Attr.RemoveAttribute(script, "data-executed"); });  
 },
 SetEtalonElementInnerHtml: function(element, rowHtml) {
  element.innerHTML = rowHtml;
 },
 ChangeCellStyle: function(recordKey, columnIndex, style, showEditor) {  
  var cell = this.GetDataCell(recordKey, columnIndex);
  if(!cell)
   return;
  var helper = this.GetStyleHelper();
  helper.UpdateCellBatchEditStyle(style, cell, columnIndex);  
 },
 UpdateCellStyle: function(cell, sizes) { this.GetStyleHelper().AddToBatchEditStyle(cell, sizes); },
 UpdateCommandButtonsEnabled: function(state) {   
  var buttons = this.GetBatchEditCommandButtons();  
  if(buttons.updateSummariesButton)
   this.UpdateCommandButtonVisibility(buttons.updateSummariesButton, state.updateSummariesButtonVisible);
  var keys = ASPx.GetObjectKeys(buttons);
  for(var i = 0; i < keys.length; i++) {
   var key = keys[i];
   if(buttons[key])
    buttons[key].SetEnabled(state.enabled);
  }
 },
 RestoreFocusAccessibleAfterCancelEdit: function() {
  if(!this.control.accessibilityCompliant)
   return;
  var buttons = this.GetBatchEditCommandButtons();
  if(buttons.length > 0 && !buttons[0].GetEnabled()) {
   var focusableElement = ASPx.RestoreFocusHelper.findNeighbourFocusElement(buttons[0].GetMainElement(), document.body);
   ASPx.AccessibilityUtils.SetFocusAccessible(focusableElement);
  }
 },
 ShowRecordError: function(key, errorText) {
  this.RemoveRecordError(key);
  this.InsertRecordValidationError(key, errorText);
 },
 ShowDataCellError: function(textContainer, errorText, makeEllipsible) {
  var errorTable = ASPx.GetChildByPartialClassName(textContainer, this.ErrorTableClass) || this.CreateDataCellErrorTable(textContainer, makeEllipsible);
  var imageCell = ASPx.GetChildByPartialClassName(errorTable.rows[0], this.ErrorTableImageCellClass);
  var img = ASPx.GetNodeByTagName(imageCell, "IMG", 0);
  errorText = ASPx.IsExists(errorText) ? errorText : "";
  ASPx.Attr.SetAttribute(img, "alt", errorText);
  ASPx.Attr.SetAttribute(img, "title", errorText);
 },
 CreateDataCellErrorTable: function(textContainer, makeEllipsible) {
  var html = textContainer.innerHTML;
  if(!ASPx.Str.Trim(html))
   html = "&nbsp;";
  textContainer.innerHTML = "";
  var errorTable = this.GetEtalonCellErrorTable().cloneNode(true);
  ASPx.Attr.RemoveAttribute(errorTable, "id");
  var row = errorTable.rows[0];
  var textCell = ASPx.GetChildByPartialClassName(row, this.ErrorTableTextCellClass);
  textCell.innerHTML = html;
  textContainer.appendChild(errorTable);
  if(makeEllipsible)
   this.MakeEllipsible(textCell);
  return errorTable;
 },
 GetCellTextContainer: function(recordKey, columnIndex, makeEllipsible) {
  var dataCell = this.GetDataCell(recordKey, columnIndex);
  if(dataCell)
   return ASPx.GetChildByClassName(dataCell, this.TextContainerClassName) || this.CreateTextContainer(dataCell, makeEllipsible);
  return null;
 },
 CreateTextContainer: function(dataCell, makeEllipsible) {
  var container = ASPx.CreateHtmlElement("DIV", { className: this.TextContainerClassName });
  if(makeEllipsible)
   this.MakeEllipsible(container);
  for(var i = dataCell.childNodes.length - 1; i >= 0; i--) {
   var child = dataCell.childNodes[i];
   if(container.childNodes.length > 0)
    container.insertBefore(child, container.childNodes[0]);
   else
    container.appendChild(child);
  }
  dataCell.appendChild(container);
  return container;
 },
 MakeEllipsible: function(element) {
  ASPx.AddClassNameToElement(element, "dx-ellipsis");
 },
 EnsureEllipsisTooltips: function(recordKey) { this.AssignEllipsisTooltips(this.GetRecord(recordKey)); },
 AssignEllipsisTooltips: function(element) { this.control.AssignEllipsisTooltipsCore(element, true); },
 AddNewRecord: function(newRecordKeyInfo, siblingRecordKey, isNewRecordOnTop) {
  var newItem = this.CreateNewItemElement(newRecordKeyInfo);
  this.PlaceNewRecord(newItem, siblingRecordKey, isNewRecordOnTop);
  this.PrepareCommandButtons();
 },
 UpdateRecordCommandButtonsVisibility: function(key, state) {   
  this.EnsureExtraCommandButtonsCreated(key, state);
  var buttons = this.GetRecordCommandButtons(key);   
  buttons.forEach(function(button) {
   var isRecover = this.IsRecoverButton(button);
   var isCancel = this.IsCancelButton(button);
   var isDefaultButton = !isRecover && !isCancel;
   var visible = false;
   if(isDefaultButton)
    visible = state.defaultButtonsVisible;
   else {
    var buttonState = isRecover ? state.recoverButton : state.cancelButton;
    visible = buttonState.visible;
   }
   this.UpdateCommandButtonVisibility(button, visible);
  }.bind(this));
 },
 EnsureExtraCommandButtonsCreated: function(key, state) {
  var isRecoverVisible = state.recoverButton.visible;
  var isCancelVisible = state.cancelButton.visible;
  if(!isRecoverVisible && !isCancelVisible)
   return;
  var buttons = this.GetRecordCommandButtons(key);
  var hasRecoverButton = buttons.some(function(button) { return this.IsRecoverButton(button); }.bind(this));
  if(!hasRecoverButton && isRecoverVisible)
   this.AppendExtraCommandButton(key, state.recoverButton.columnIndex, state.recoverButton.html);
  var hasCancelButton = buttons.some(function(button) { return this.IsCancelButton(button); }.bind(this));
  if(!hasCancelButton && isCancelVisible)
   this.AppendExtraCommandButton(key, state.cancelButton.columnIndex, state.cancelButton.html);
 },
 AppendExtraCommandButton: function(recordKey, columnIndex, buttonHTML) {
  if(!buttonHTML) return;  
  var parent = this.GetRecoverButtonParent(recordKey, columnIndex);
  if(!parent) return;     
  var dummyElement = ASPx.CreateHtmlElement();
  dummyElement.innerHTML = buttonHTML;
  this.PrepareCommandButtonIDs(dummyElement, recordKey);
  ASPx.MoveChildrenToElement(dummyElement, parent);
  this.PrepareCommandButtons();  
  ASPx.RunStartupScriptsCreatedOnClient(parent);
 },
 UpdateCommandButtonVisibility: function(button, visible) {
  if(button)
   button.SetVisible(visible);
 },
 ChangeDeletedRecordAppearance: function(key, recover, highlightMode) {
  if(!ASPx.IsExists(key)) return;
  if(highlightMode)
   this.UpdateRecordStyle(key);
  else
   this.ChangeDeletedRecordVisibility(key, recover);
 },
 ChangeDeletedRecordVisibility: function(key, recover) {  },
 GetRecordCommandButtons: function(recordKey) {  },
 UpdateProgressBarColumnValue: function(recordKey, columnIndex, value) {  
  var pb = this.GetProgressBarControl(recordKey, columnIndex);
  if(pb)
   pb.SetValue(value);
 },
 GetColumnIndexByChild: function(element) { return this.GetColumnIndexByDataCell(this.GetDataCellByChild(element)); },
 GetStyleHelper: function() {  },
 GetCellSelectionHelper: function() { return this.control.GetCellSelectionHelper(); },
 EvaluateNewRecordScriptObjects: function(key) {
  var scriptContainers = this.GetRecordElementsToEvaluateScripts(key);
  ASPx.Data.ForEach(scriptContainers, function(container) { ASPx.RunStartupScripts(false, container); });
 },
 GetRecordElementsToEvaluateScripts: function(key) { return [ ]; },
 IsPagerCallback: function() {
  var callbackCommand = this.control.GetCallbackCommand();
  return callbackCommand === ASPxClientGridViewCallbackCommand.PagerOnClick
   || callbackCommand === ASPxClientGridViewCallbackCommand.NextPage
   || callbackCommand === ASPxClientGridViewCallbackCommand.PreviousPage
   || callbackCommand === ASPxClientGridViewCallbackCommand.GotoPage;
 }
});
var BatchEditHelper = ASPx.CreateClass(null, {
 EditType_Cell: 0,
 EditType_Row: 1,
 StartEditAction_Click: 0,
 StartEditAction_DblClick: 1,
 StartEditAction_FocusedCellClick: 2,
 ValidationMode_OnEndEdit: 0,
 ValidationMode_OnSaveChanges: 1,
 InvalidRecordKey: -100000,
 NewItemInitValuesKey: "NIV",
 ParentRecordKeyName: "DX_ParentRecordKey_DX", 
 RecordKeyName: "DX_RecordKey_DX",
 CheckBoxCellClassName: "dxBatchEditCheckBoxCell",
 CheckBoxSwitcherClassName: "dxSwitcher",
 ColorPlaceholder: "||dxcolor||",
 ImageUrlPlaceholder: "e553190285f348808285578878b77111_dximageUrl",
 TextPlaceholder: "||dxtext||",
 CancelButtonKey: "cancel",
 RecoverButtonKey: "recover",   
 DefaultDateFormat: "d",
 constructor: function(owner) {
  this.owner = owner;
  this.pageServerValues = { };
  this.editingRecordKey = this.InvalidRecordKey;
  this.editedColumnIndices = [ ];
  this.invalidItemsInfo = { };
  this.insertedKeysInfo = [ ];
  this.insertedValues = { };
  this.updatedValues = { };
  this.deletedItemKeys = [ ];
  this.serverCellTexts = { };
  this.savedServerValues = { };
  this.savedNonEditableDataColumnsText = { };
  this.focusHelper = this.CreateFocusHelper(); 
  this.updateWatcherHelper = this.CreateUpdateWatcher();
  this.summaryHelper = this.CreateSummaryHelper();
  this.updating = false;
  this.lockEndEdit = false;
  this.resetChangesLock = 0;
 },
 CreateNewRecordKeyInfo: function(parentRecordKey) { },
 GetFocusHelper: function() { return this.focusHelper; },
 CreateFocusHelper: function() {
  var type = this.owner.GetFocusHelperType();
  if(type)
   return new type(this);
 },
 CreateSummaryHelper: function() {
  return new BatchEditSummaryHelper(this);
 },
 GetTotalSummaryValue: function(summaryItemIndex) {
  return this.summaryHelper.GetTotalSummaryValue(summaryItemIndex);
 },
 GetGroupSummaryValue: function(groupRowVisibleIndex, summaryItemIndex) {
  return this.summaryHelper.GetGroupSummaryValue(summaryItemIndex, groupRowVisibleIndex);
 },
 GetTotalSummaryByFieldName: function(summaryFieldName) {
  return this.summaryHelper.GetTotalSummaryByFieldName(summaryFieldName);
 },
 GetGroupSummaryByFieldName: function(summaryFieldName) {
  return this.summaryHelper.GetGroupSummaryByFieldName(summaryFieldName);
 },
 RaiseBatchEditSummaryDisplayText: function(summaryInfo, text, groupRowVisibleIndex) {
  return this.owner.RaiseBatchEditSummaryDisplayText(summaryInfo, text, groupRowVisibleIndex);
 },
 GetBatchEditClientState: function() { return this.owner.GetBatchEditClientState(); },
 GetColumn: function(columnIndex) { return this.owner.GetColumn(columnIndex); },
 GetRecord: function(key) { return this.owner.GetRecord(key); },
 IsValidRecord: function(key) { return this.owner.IsValidRecord(key); },
 IsRecordVisible: function(key) { return this.owner.IsRecordVisible(key); },
 GetDataCell: function(key, columnIndex) { return this.owner.GetDataCell(key, columnIndex); },
 GetCellTextContainer: function(recordKey, columnIndex) { return this.owner.GetCellTextContainer(recordKey, columnIndex, this.IsEllipsisAllowed(columnIndex)); },
 GetEditorContainer: function(columnIndex) { return this.owner.GetBatchEditorContainer(columnIndex); },
 GetEditor: function(columnIndex) { return this.owner.GetEditor(columnIndex); },
 GetVisibleColumnIndices: function() { return this.owner.GetVisibleColumnIndices(); },
 GetRecordError: function(key) { return this.owner.GetRecordError(key); },
 ShowRecordError: function(key, errorText) { this.owner.ShowRecordError(key, errorText); },
 RemoveRecordError: function(key) { this.owner.RemoveRecordError(key); },
 UpdateCommandButtonsEnabled: function(forceEnabled, isOnAfterCallback) { 
  var state = this.GetCommandButtonsEnabledState(forceEnabled, isOnAfterCallback);
  state.updateSummariesButtonVisible = this.IsUpdateSummariesButtonVisible();
  this.owner.UpdateCommandButtonsEnabled(state); 
 },
 GetCommandButtonsEnabledState: function(forceEnabled) { return { enabled: forceEnabled || this.HasChanges() }; },
 HasKeyField: function() { return this.owner.HasKeyField(); },
 RemoveRecordElement: function(key) { this.owner.RemoveRecordElement(key); },   
 IsRecordElement: function(element) { return this.owner.IsRecordElement(element); },
 GetColumnIndexByChild: function(element) { return this.owner.GetColumnIndexByChild(element); },
 ChangeCellStyle: function(recordKey, columnIndex, style, showEditor) { this.owner.ChangeCellStyle(recordKey, columnIndex, style, showEditor); },
 RaiseBatchEditConfirmShowing: function(requestTriggerID) { return this.owner.RaiseBatchEditConfirmShowing(requestTriggerID); },
 GetOwnerControl: function() { return this.owner.control; },
 GetOrderedKeysFromOwnerControl: function() { return this.owner.GetOrderedKeysFromOwnerControl(); },
 GetSelectedCells: function() { return this.owner.GetSelectedCells(); },
 IsSingleEditMode: function() { return this.GetBatchEditClientState().editMode === this.EditType_Cell; },
 IsStartEditOnClick: function() { return this.GetBatchEditClientState().startEditAction === this.StartEditAction_Click; },
 IsStartEditOnDblClick: function() { return this.GetBatchEditClientState().startEditAction === this.StartEditAction_DblClick; },
 IsStartEditOnFocusedCellClick: function() { return this.GetBatchEditClientState().startEditAction === this.StartEditAction_FocusedCellClick; },
 IsNewItemOnTop: function() { return !!this.GetBatchEditClientState().isNewRowOnTop; },
 RequireValidateOnEndEdit: function() { return !!this.GetBatchEditClientState().validateOnEndEdit; },
 AllowEndEditOnError: function() { return !!this.GetBatchEditClientState().allowEndEditOnError; },
 GetPreventUpdateCellTextForDataItemTemplate: function() { return !!this.GetBatchEditClientState().preventUpdateCellTextForDataItemTemplate; },
 IsCallbacksEnabled: function () { return !!this.GetBatchEditClientState().enableCallbacks; },
 GetEditColumnIndices: function() { return this.GetBatchEditClientState().editColumnIndices; },
 GetVisibleNonEditableDataColumnIndices: function() { return this.GetBatchEditClientState().visibleNonEditableDataColumnIndices || []; },
 GetHiddenEditorColumnIndices: function() { return this.GetBatchEditClientState().hiddenEditorColumnIndices; },
 GetUpdateInfo: function() { return this.GetBatchEditClientState().updateInfo; },
 GetValidationInfo: function() { return this.GetBatchEditClientState().validationInfo; },
 GetTemplateColumnIndices: function() { return this.GetBatchEditClientState().templateColumnIndices; },
 GetDataItemTemplateColumnIndices: function() { return this.GetBatchEditClientState().dataItemTemplateColumnIndices; },
 GetBinaryImageColumnsDisplayHtml: function() { return this.GetBatchEditClientState().binaryImageColumnsDisplayHtml; },
 GetCheckColumnsDisplayHtml: function() { return this.GetBatchEditClientState().checkColumnsDisplayHtml; },
 GetColorEditColumnsDisplayHtml: function() { return this.GetBatchEditClientState().colorColumnsDisplayHtml; },
 GetComboBoxColumnsDisplayHtml: function() { return this.GetBatchEditClientState().comboBoxColumnsDisplayHtml; },
 GetExtraCommandButtonsInfo: function() { return this.GetBatchEditClientState().extraCommandButtonsInfo; },
 GetComboBoxCallbackModeItemsInfo: function() { return this.GetBatchEditClientState().comboBoxCallbackModeItemsInfo; },
 GetComboBoxColumnsWithServerItemsIndices: function() { return this.GetBatchEditClientState().comboBoxColumnsWithServerItemsIndices; },
 GetProgerssBarColumnIndices: function() { return this.GetBatchEditClientState().progressBarColumnIndices; },
 GetColumnsNullDisplayTextInfo: function() { return this.GetBatchEditClientState().columnsNullDisplayTextInfo; }, 
 GetHighlightDeletedItems: function() { return !!this.GetBatchEditClientState().highlightDeletedItems; },
 GetHighlightSummaryItems: function() { return !!this.GetBatchEditClientState().highlightSummaryItems; },
 GetNonEditableColumnValues: function() { return this.GetBatchEditClientState().nonEditableColumnValues; },
 IsEllipsisAllowed: function(columnIndex) { return ASPx.Data.ArrayContains(this.GetBatchEditClientState().ellipsisColumns, columnIndex); },
 GetConfirmUpdateText: function() { return this.GetBatchEditClientState().confirmUpdate; },
 GetAllowUpdateCellText: function(columnIndex) {
  if(this.IsDataItemTemplateColumn(columnIndex) && this.GetPreventUpdateCellTextForDataItemTemplate())
   return false;
  return true;
 },
 IsBinaryImageColumn: function(columnIndex) { return !!this.GetBinaryImageColumnsDisplayHtml()[columnIndex]; },
 IsCheckColumn: function(columnIndex) { return !!this.GetCheckColumnsDisplayHtml()[columnIndex]; },
 IsColorEditColumn: function(columnIndex) { return !!this.GetColorEditColumnsDisplayHtml()[columnIndex]; },
 IsComboBoxEditColumn: function(columnIndex, editor) { 
  return !!this.GetComboBoxColumnsDisplayHtml()[columnIndex] && typeof(ASPxClientComboBox) != "undefined" && editor instanceof ASPxClientComboBox; 
 },
 IsEditTemplateColumn: function(columnIndex) { return ASPx.Data.ArrayIndexOf(this.GetTemplateColumnIndices(), columnIndex) >= 0; },
 IsDataItemTemplateColumn: function(columnIndex) { return ASPx.Data.ArrayIndexOf(this.GetDataItemTemplateColumnIndices(), columnIndex) >= 0; },
 IsComboBoxCallbackModeColumn: function(columnIndex) { return !!this.GetComboBoxCallbackModeItemsInfo()[columnIndex]; },
 IsComboBoxWithServerItemsColumn: function (columnIndex) { return ASPx.Data.ArrayIndexOf(this.GetComboBoxColumnsWithServerItemsIndices(), columnIndex) >= 0; },
 IsProgressBarColumn: function(columnIndex) { return ASPx.Data.ArrayIndexOf(this.GetProgerssBarColumnIndices(), columnIndex) >= 0;},
 IsMemoEdit: function(editor) { return ASPx.Ident.IsASPxClientMemo && ASPx.Ident.IsASPxClientMemo(editor); },
 GetEditingRecordKey: function() { return this.editingRecordKey; },
 IsNewRecord: function(key) { return ASPx.Data.ArrayIndexOf(this.GetInsertedRecordKeys(), key) >= 0; },
 IsDeletedRecord: function(key) { return ASPx.Data.ArrayIndexOf(this.deletedItemKeys, key) >= 0; }, 
 IsUpdatedRecord: function(key) { return !!this.updatedValues[key]; },
 IsEditing: function() { return this.editingRecordKey !== this.InvalidRecordKey && this.editedColumnIndices.length > 0; },
 IsColumnEditing: function(columnIndex) { return this.IsEditingCell(this.editingRecordKey, columnIndex) && !this.IsEditorDisabled(columnIndex); },
 IsEditingRecord: function(recordKey) { return this.IsEditing() && this.editingRecordKey === recordKey; },
 IsEditingCell: function(recordKey, columnIndex) { return this.IsEditingRecord(recordKey) && ASPx.Data.ArrayIndexOf(this.editedColumnIndices, columnIndex) >= 0; },
 IsUpdating: function() { return this.updating; },
 IsUpdateConfirmLocked: function() { return this.updateWatcherHelper.lockShowConfirm; },
 CanEditColumn: function(columnIndex) { return this.IsEditableColumn(columnIndex) && !this.IsEditorHiddenForColumn(columnIndex) && !this.IsEditorDisabled(columnIndex); },
 IsDateEdit: function(editor) { return ASPx.Ident.IsASPxClientDateEdit && ASPx.Ident.IsASPxClientDateEdit(editor);},
 IsEditableColumn: function(columnIndex) {return ASPx.Data.ArrayIndexOf(this.GetEditColumnIndices(), columnIndex) >= 0;},
 IsEditorHiddenForColumn: function(columnIndex) {return ASPx.Data.ArrayIndexOf(this.GetHiddenEditorColumnIndices(), columnIndex) >= 0;},
 GetObjectSize: function(obj) { return ASPx.GetObjectKeys(obj).length; },
 IsEditorDisabled: function(columnIndex) { 
  var editor = this.GetEditor(columnIndex);
  return editor ? !editor.GetEnabled() : false;
 },
 IsReadOnlyEditor: function(columnIndex) {
  var editor = this.GetEditor(columnIndex);
  return editor ? editor.GetReadOnly() : false;
 },
 GetChangedRecordKeys: function() { return ASPx.Data.ArrayFlatten([this.GetInsertedRecordKeys(), ASPx.GetObjectKeys(this.updatedValues), this.deletedItemKeys]); },
 GetCurrentPageChangedRecordKeys: function() {
  return this.GetChangedRecordKeys().filter(function(key) {
   return this.IsCurrentPageRecord(key) && !this.IsNewRecord(key);
  }.bind(this));
 },
 GetDeletedRecordKeys: function(isCurrentPageOnly) {
  var keys = this.deletedItemKeys.slice();
  if(isCurrentPageOnly)
   keys = keys.filter(function(key) { return this.IsCurrentPageRecord(key); }.bind(this));
  return keys;
 },
 GetInsertedKeysInfo: function() { return this.insertedKeysInfo.slice(); },
 SetInsertedKeysInfo: function(info) { this.insertedKeysInfo = info; },
 AddInsertedKeyInfo: function(info) { this.insertedKeysInfo.push(info); },
 RemoveInsertedKeyInfo: function(recordKey) {
  this.summaryHelper.RemoveRecord(recordKey, true);
  var index = ASPx.Data.ArrayIndexOf(this.insertedKeysInfo, null, function(info) { return this.CompareInsertedRecordKeys(info.key, recordKey); }.bind(this));
  ASPx.Data.ArrayRemoveAt(this.insertedKeysInfo, index);
 },
 GetInsertedRecordKeys: function(isCurrentPageOnly) { 
  var keys = this.GetInsertedKeysInfo().map(function(info) { return info.key; });
  if(isCurrentPageOnly)
   keys = keys.filter(function(key) { return this.IsCurrentPageRecord(key); }.bind(this));
  return keys; 
 },
 IsCurrentPageRecord: function (key) { return true; },
 CompareInsertedRecordKeys: function(key1, key2) {
  if(!ASPx.IsExists(key1) || !ASPx.IsExists(key2))
   return false;
  return key1 === key2 || key1.toString() === key2.toString();
 },
 GetModifiedValues: function(recordKey) {
  var hash = this.GetClientValuesBag(recordKey);
  return hash && hash[recordKey];
 },
 GetClientValuesBag: function(recordKey) {
  return this.IsNewRecord(recordKey) ? this.insertedValues : this.updatedValues;
 },
 IsDirtyCell: function(recordKey, columnIndex) {
  var recordValues = this.GetModifiedValues(recordKey);
  return recordValues && recordValues.hasOwnProperty(columnIndex);
 },
 GetCellValue: function(recordKey, columnIndex, initial) {
  if(!initial && this.IsDirtyCell(recordKey, columnIndex))
   return this.GetClientValue(recordKey, columnIndex);
  return this.GetServerValue(recordKey, columnIndex);
 },
 GetClientValue: function(recordKey, columnIndex) {
  var recordValues = this.GetModifiedValues(recordKey);
  if(recordValues && recordValues.hasOwnProperty(columnIndex))
   return recordValues[columnIndex][0];
  return null;
 },
 GetClientValueContent: function(recordKey, columnIndex) {
  var recordValues = this.GetModifiedValues(recordKey);
  if(recordValues && recordValues.hasOwnProperty(columnIndex))
   return recordValues[columnIndex][1];
  return null;
 },
 GetServerValue: function(recordKey, columnIndex) {
  if(this.IsNewRecord(recordKey))
   recordKey = this.NewItemInitValuesKey;
  var rowValues = this.pageServerValues[recordKey];
  if (rowValues && rowValues.hasOwnProperty(columnIndex)) {
   if(this.NeedCacheServerValue())
    this.CacheServerValue(recordKey, columnIndex, rowValues[columnIndex], this.GetCellServerHtml(recordKey, columnIndex));
   return rowValues[columnIndex];
  }
  var cachedValue = this.GetCachedServerValue(recordKey, columnIndex);
  return ASPx.IsExists(cachedValue) ? cachedValue : null;
 },
 SetCellValue: function(key, columnIndex, value, text, cancelCellHighlighting) {
  if(this.AreValuesEqual(this.GetServerValue(key, columnIndex), value, columnIndex))
   this.ResetClientValue(key, columnIndex);
  else
   this.SetCellValueCore(key, columnIndex, value, text, cancelCellHighlighting);
 },
 SetCellValueCore: function(key, columnIndex, value, text, cancelCellHighlighting) {  
  this.summaryHelper.ResetRecordValue(key, columnIndex, false);
  var hash = this.GetClientValuesBag(key);
  var recordValues = hash[key];
  if(!recordValues)
   hash[key] = recordValues = { };
  var prevValues = recordValues[columnIndex];
  var cancelHighlight = !!cancelCellHighlighting || (!!prevValues && prevValues[2] && this.AreValuesEqual(prevValues[0],  value));
  recordValues[columnIndex] = [ value, text, cancelHighlight];
  this.EnsureCellServerHtml(key, columnIndex);
  this.summaryHelper.ModifyRecordValues(key, [columnIndex], true);
 },
 GetCellContent: function(key, columnIndex) {
  if(this.IsDirtyCell(key, columnIndex))
   return this.GetClientValueContent(key, columnIndex);
  return this.GetCellServerContent(key, columnIndex);
 },
 GetCellServerContent: function(key, columnIndex) {
  var rowTexts = this.serverCellTexts[key];
  if(!rowTexts)
   this.serverCellTexts[key] = rowTexts = { };
  if(!rowTexts.hasOwnProperty(columnIndex))
   rowTexts[columnIndex] = this.GetCachedServerCellText(key, columnIndex) || this.GetCellServerHtml(key, columnIndex);
  return rowTexts[columnIndex];
 },
 GetCellServerHtml: function(key, columnIndex) {
  var textContainer = this.GetCellTextContainer(key, columnIndex);
  if(!textContainer) return null;
  if(!ASPx.IsExists(textContainer.dxgvSavedHtml))
   textContainer.dxgvSavedHtml = textContainer.innerHTML;
  return textContainer.dxgvSavedHtml;
 },
 UpdateCellValue: function(key, columnIndex, value, text, textChanged) {
  if(this.CanEditColumn(columnIndex) && !this.IsReadOnlyEditor(columnIndex) && !this.IsEditingCell(key, columnIndex)) {
   var editor = this.GetEditor(columnIndex);
   if(editor && this.IsDateEdit(editor) && !ASPx.Ident.IsDate(value)) {
    var displayFormat = editor.displayFormat != null ? ASPx.Formatter.ParseSpec(editor.displayFormat, 1).format : ASPx.CultureInfo.shortDate;
    displayFormat = displayFormat == this.DefaultDateFormat ? ASPx.CultureInfo.shortDate : displayFormat;
    var format = editor.dateFormatter.GetFormat(displayFormat);
    value = editor.dateFormatter.Parse(value, false, format.spPositions, format.specifiers);
    if(!value)
     value = null;
   }
   var validationInfo = this.GetCellValidationInfo(key, columnIndex, value, true);
   if(validationInfo.isValid) {
    var cellText = text;
    if(editor && !textChanged)
     cellText = this.GetFormattedEditorText(editor);
    this.SetCellValue(key, columnIndex, validationInfo.value, cellText);
     this.UpdateCell(key, columnIndex);
   }
  }
 },
 EnsureCellServerHtml: function(key, columnIndex) {
  this.GetCellServerHtml(key, columnIndex);
 },
 ResetClientValue: function(key, columnIndex) {   
  this.summaryHelper.ResetRecordValue(key, columnIndex, true);
  this.ResetClientValueCore(key, columnIndex, this.insertedValues);
  this.ResetClientValueCore(key, columnIndex, this.updatedValues);
 },
 ResetClientValueCore: function(key, columnIndex, hash) {
  var rowValues = hash[key];
  if(rowValues)
   delete rowValues[columnIndex];
  if(this.GetObjectSize(rowValues) === 0)
   delete hash[key];
 },
 GetRecordValues: function(key) {
  var result = { };
  var columnIndices = this.GetEditColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   result[columnIndex] = this.GetCellValueInfo(key, columnIndex);
  }
  return result;
 },
 GetCellValueInfo: function(key, columnIndex) {
  return { 
   value: this.GetCellValue(key, columnIndex), 
   text: this.GetCellContent(key, columnIndex) 
  };
 },
 CacheServerValue: function(key, columnIndex, value, text) {
  var recordValues = this.savedServerValues[key];
  if(!recordValues)
   this.savedServerValues[key] = recordValues = { };
  recordValues[columnIndex] = { value: value, text: text }; 
 },
 NeedCacheServerValue: function() { return this.IsCallbacksEnabled(); },
 GetCachedServerValue: function(key, columnIndex) { 
  var recordValues = this.savedServerValues[key];
  return recordValues && recordValues[columnIndex] && recordValues[columnIndex].value;
 },
 GetCachedServerCellText: function(key, columnIndex) { 
  var recordValues = this.savedServerValues[key];
  return recordValues && recordValues[columnIndex] && recordValues[columnIndex].text;
 },
 ClearSavedServerCellText: function() {
  for(var key in this.savedServerValues) {
   if(this.savedServerValues.hasOwnProperty(key) && this.IsCurrentPageRecord(key)) {
    var recordValues = this.savedServerValues[key];
    for(var columnIndex in recordValues) {
     if(recordValues.hasOwnProperty(columnIndex)) {
      if(recordValues[columnIndex] != null)
       recordValues[columnIndex].text = null;
     }
    }
   }
  }
 },
 CacheNonEditableDataColumnsText: function(key, columnIndex, text) {
  var recordValues = this.savedNonEditableDataColumnsText[key];
  if(!recordValues)
   this.savedNonEditableDataColumnsText[key] = recordValues = {};
  recordValues[columnIndex] = text;
 },
 GetCachedNonEditableDataColumnsText: function(key, columnIndex) {
  var recordValues = this.savedNonEditableDataColumnsText[key];
  return recordValues && recordValues[columnIndex];
 },
 EnsureNonEditableDataColumnsTextCached: function() {
  var columnIndices = this.GetVisibleNonEditableDataColumnIndices();
  var currentPageChangedKeys = this.GetCurrentPageChangedRecordKeys();
  for(var i = 0; i < currentPageChangedKeys.length; i++) {
   var recordKey = currentPageChangedKeys[i];
   for(var j = 0; j < columnIndices.length; j++) {
    var columnIndex = columnIndices[j];
    this.CacheNonEditableDataColumnsText(recordKey, columnIndex, this.GetCellServerHtml(recordKey, columnIndex));
   }
  }
 },
 HasChanges: function(recordKey, columnIndex) {
  if(!ASPx.IsExists(recordKey))
   return this.GetInsertedRecordKeys().length > 0 || this.deletedItemKeys.length > 0 || this.GetObjectSize(this.updatedValues) > 0;
  if(this.IsNewRecord(recordKey))
   return true;
  var columnIndices = !ASPx.IsExists(columnIndex) ? this.GetEditColumnIndices() : [ columnIndex ];
  for(var i = 0; i < columnIndices.length; i++) {
   if(this.IsDirtyCell(recordKey, columnIndices[i]))
    return true;
  }
  return false;
 },
 CreateUpdateWatcher: function() { return new BatchEditUpdateWatcherHelper(this); },
 Init: function() {
  this.LoadPageServerValues(false);
  this.LoadSavedClientValues();
  this.ApplyClientChanges();
  this.ApplyServerState();
  this.summaryHelper.Init();
  this.focusHelper.Update();
  this.UpdateCommandButtonsEnabled();
  this.owner.OnBatchEditHelperInit();
 },
 OnAfterCallback: function() {
  this.ClearSavedServerCellText();
  this.ResetEditState();
  this.LoadPageServerValues(this.owner.IsLastCallbackProcessedAsEndless());
  this.ApplyServerState();
  this.focusHelper.Update();
  this.updating = false;
  this.UpdateSyncInput();
  this.summaryHelper.OnAfterCallback();
  this.UpdateCommandButtonsEnabled(false, true);
  this.EnsureEmptyRecordVisibility();
  this.owner.OnBatchEditHelperCallback();
  delete this.callbackErrorInfo;
 },
 OnBeforeCallback: function() {
  if(this.IsCallbacksEnabled())
   this.EnsureNonEditableDataColumnsTextCached();
  this.summaryHelper.OnBeforeCallback();
 },
 ApplyServerState: function() {
  this.ProcessServerChanges(this.GetUpdateInfo());
  this.ProcessValidationErrors(this.GetValidationInfo());
 },
 ShowCallbackError: function(errorText, errorData) {
  var state = this.GetBatchEditClientState();
  if(!errorData) {
   state.updateInfo = { };
   return;
  }
  this.ProcessServerChanges(errorData.updateInfo, true);
  this.ProcessValidationErrors(errorData.validationInfo);
  state.updateInfo = { };
  this.ShowRecordErrorOnCallbackError(errorData.rowKey, errorText);  
  this.callbackErrorInfo = { data: errorData, text: errorText, errorItem: this.GetRecordError(errorData.rowKey) };
  return !!this.callbackErrorInfo.errorItem;
 },
 ShowRecordErrorOnCallbackError: function(key, errorText) {
  this.RemoveItemErrors();
  this.ShowRecordError(key, errorText); 
 },
 ProcessGridCallbackError: function() { this.callbackErrorInfo = { }; },
 HasCallbackError: function() { return !!this.callbackErrorInfo ; },
 LoadPageServerValues: function(append) {
  var loadedPageValues = this.owner.GetLoadedPageValues(); 
  this.serverCellTexts = { };
  if(append) {
   for(var key in loadedPageValues)
    if(loadedPageValues.hasOwnProperty(key))
     this.pageServerValues[key] = loadedPageValues[key];
  } else
   this.pageServerValues = loadedPageValues;
 },
 LoadSavedClientValues: function() {
  var savedClientState = this.owner.GetLoadedClientModifiedValues();
  if(!savedClientState) return;
  this.SetInsertedKeysInfo(savedClientState.InsertedKeysInfo || [ ]);
  this.insertedValues = savedClientState.InsertedValues || { };
  this.updatedValues = savedClientState.UpdatedValues || { };
  this.deletedItemKeys = savedClientState.DeletedKeys || [ ];
 },
 ResetEditState: function() {
  this.editingRecordKey = this.InvalidRecordKey;
  this.editedColumnIndices = [ ];
  this.invalidItemsInfo = { };
 },
 ProcessServerChanges: function(updateInfo, hasCallbackError) {
  if(!updateInfo) return;
  this.BeginMultipleResetChanges();
  this.ProcessServerInsertedItems(updateInfo.inserted);
  this.ProcessServerUpdatedItems(updateInfo.updated);
  this.ProcessServerDeletedItems(updateInfo.deleted, hasCallbackError);
  this.ApplyClientChanges();
  this.EndMultipleResetChanges();
 },
 ProcessServerInsertedItems: function(recordKeys) {
  recordKeys = recordKeys || [ ];
  for(var i = 0; i < recordKeys.length; i++)
   this.ResetChanges(recordKeys[i]);
 },
 ProcessServerUpdatedItems: function(keys) {
  keys = keys || [ ];
  for(var i = 0; i < keys.length; i++) {
   var key = keys[i];
   if(this.savedServerValues[key])
    delete this.savedServerValues[key];
   this.ResetChanges(keys[i]);
  }
 },
 ProcessServerDeletedItems: function(deletedKeys, needRemoveHtmlItems) {
  deletedKeys = deletedKeys || [ ];
  var clientDeletedKeys = this.deletedItemKeys.slice();
  for(var i = 0; i < deletedKeys.length; i++) {
   var key = deletedKeys[i];
   this.ResetChanges(key);
   if(needRemoveHtmlItems && ASPx.Data.ArrayIndexOf(clientDeletedKeys, key) >= 0)
    this.SafeRemoveHtmlItem(key);
  }
 },
 ApplyClientChanges: function() {
  this.ApplyClientInsertChanges();
  this.ApplyClientUpdateChanges();
  this.ApplyClientDeleteChanges();
  this.UpdateSyncInput();
 },
 ApplyClientInsertChanges: function() {
  if (!this.IsPossibleApplyClientInsertChanges())
   return;
  var editColumnIndices = this.GetEditColumnIndices();
  var insertedKeysInfo = this.GetInfoToApplyClientInsertChanges();
  for(var i = 0; i < insertedKeysInfo.length; i++) {
   var keyInfo = insertedKeysInfo[i];
   if(this.CanAddNewRecord(keyInfo)){
    this.AddNewRecordCore(keyInfo);
    this.OnNewRecordAdded(keyInfo);
    for(var columnIndex = 0; columnIndex < editColumnIndices.length; columnIndex++)
     this.EnsureCellServerHtml(keyInfo.key, editColumnIndices[columnIndex]);
    this.UpdateItem(keyInfo.key, editColumnIndices);
   }
  }
 },
 IsPossibleApplyClientInsertChanges: function() { return true; },
 GetInfoToApplyClientInsertChanges: function() { return this.GetInsertedKeysInfo(); },
 ApplyClientUpdateChanges: function() {
  var editColumnIndices = this.GetEditColumnIndices();
  for(var key in this.updatedValues) {
   if(!this.updatedValues.hasOwnProperty(key)) continue;
   for(var i = 0; i < editColumnIndices.length; i++)
    this.EnsureCellServerHtml(key, editColumnIndices[i]);
   this.UpdateItem(key, editColumnIndices);
  }
 },
 ApplyClientDeleteChanges: function() {
  var keys = this.deletedItemKeys;
  this.deletedItemKeys = [ ];
  for(var i = 0; i < keys.length; i++) {
   var key = keys[i];
   var callbackErrorItem = this.callbackErrorInfo && this.callbackErrorInfo.errorItem;
   var skipDeleteErrorItem = callbackErrorItem && callbackErrorItem === this.GetRecordError(key);
   this.DeleteItem(key, skipDeleteErrorItem, true);
  }
  if (this.IsCallbacksEnabled())
   this.deletedItemKeys = keys;
 },
 ResetAllChanges: function() {
  this.BeginMultipleResetChanges();
  var insertedRecordKeys = this.GetInsertedRecordKeys();
  for(var i = 0; i < insertedRecordKeys.length; i++)
   this.ResetChanges(insertedRecordKeys[i]);
  var keys = this.deletedItemKeys.slice();
  for(var i = 0; i < keys.length; i++)
   this.ResetChanges(keys[i]);
  keys = ASPx.GetObjectKeys(this.updatedValues);
  for(var i = 0; i < keys.length; i++)
   this.ResetChanges(keys[i]);
  this.EndMultipleResetChanges();
 }, 
 ResetChanges: function(key, columnIndex) {
  var columnIndices = !ASPx.IsExists(columnIndex) ? this.GetEditColumnIndices() : [ columnIndex ];
  var entire = !ASPx.IsExists(columnIndex);
  var isNew = this.IsNewRecord(key);
  var isDeleted = !isNew && this.IsDeletedRecord(key);
  var isDeletedAndUpdated = isDeleted && this.GetHighlightDeletedItems() && this.HasChanges(key); 
  var isUpdated = !isNew && (!isDeleted || isDeletedAndUpdated);
  for(var i = 0; i < columnIndices.length; i++) {
   this.ResetClientValue(key, columnIndices[i]);
   this.ResetCellValidationState(key, columnIndices[i]);
  }
  if(entire && this.serverCellTexts.hasOwnProperty(key))
   delete this.serverCellTexts[key];
  this.RemoveRecordError(key);
  if(isNew && entire)
   this.RemoveNewRecord(key);
  if(isDeleted && entire) {
   this.RecoverRecord(key);   
  }
  if(isUpdated)
   this.UpdateItem(key, columnIndices, false, true);
  this.EnsureEmptyRecordVisibility();
  this.UpdateSyncInput();
  var isMultiple = this.IsMultipleResetChangesInProcess();
  this.owner.OnResetChanges(isMultiple);
 },
 BeginMultipleResetChanges: function() {
  this.resetChangesLock++;
 },
 EndMultipleResetChanges: function() {
  this.resetChangesLock--;
  this.owner.OnEndMultipleResetChanges();
 },
 IsMultipleResetChangesInProcess: function() {
  return this.resetChangesLock > 0;
 },
 RemoveNewRecord: function(key) {
  this.SafeRemoveHtmlItem(key);
  this.RemoveInsertedKeyInfo(key);
 },
 ResetItemValidationState: function(recordKey) {
  if(this.invalidItemsInfo[recordKey])
   delete this.invalidItemsInfo[recordKey];
 },
 ApplyCellValidationState: function(recordKey, columnIndex) {
  if(!this.invalidItemsInfo[recordKey])
   this.invalidItemsInfo[recordKey] = [ ];
  if(!ASPx.Data.ArrayContains(this.invalidItemsInfo[recordKey], columnIndex))
   this.invalidItemsInfo[recordKey].push(columnIndex);
 },
 ResetCellValidationState: function(recordKey, columnIndex) {
  var invalidColumnIndices = this.invalidItemsInfo[recordKey];
  if(!invalidColumnIndices) return;
  ASPx.Data.ArrayRemove(invalidColumnIndices, columnIndex);  
  if(invalidColumnIndices.length === 0)
   this.ResetItemValidationState(recordKey);
 },
 HasInvalidItems: function() { return ASPx.GetObjectKeys(this.invalidItemsInfo).length > 0; },
 ProcessValidationErrors: function(validationInfo) {
  if(!validationInfo) return;
  for(var itemKey in validationInfo) {
   if(!validationInfo.hasOwnProperty(itemKey)) continue;
   var itemValidationInfo = validationInfo[itemKey];
   if(!this.IsValidRecord(itemKey)) continue;
   if(itemValidationInfo.row)
    this.ShowRecordError(itemKey, itemValidationInfo.row);
   var editorErrors = itemValidationInfo.editors;
   for(var columnIndex in editorErrors) {
    if(!editorErrors.hasOwnProperty(columnIndex)) continue;
    this.ShowCellValidationError(itemKey, columnIndex, editorErrors[columnIndex]);
   }
  }
 },
 GetServerRecordKeys: function(doNotIncludeDeleted) { 
  return this.GetOrderedKeysFromOwnerControl().filter(function(key) { return this.IsValidRecord(key) && (!this.IsDeletedRecord(key) || !doNotIncludeDeleted); }.bind(this));
 },
 GetRecordKeys: function(doNotIncludeDeleted) { 
  var insertedKeys = this.GetInsertedRecordKeys(true);
    if(doNotIncludeDeleted)
   insertedKeys = insertedKeys.filter(function(key) { return !this.IsDeletedRecord(key); }.bind(this));
  if(this.IsNewItemOnTop())
   insertedKeys.reverse();
  var parts = [ insertedKeys, this.GetServerRecordKeys(doNotIncludeDeleted) ];
  if(!this.IsNewItemOnTop())
   parts.reverse();
  return parts[0].concat(parts[1]);
 },
 GetRecordKeysForValidation: function(validateOnCurrentPageOnly) { return this.GetRecordKeys(); },
 ValidateItems: function() {
  return this.ValidateItemsCore(this.GetRecordKeysForValidation());
 },
 ValidateItemsCore: function(recordKeys, validateNotModified) {
  var pageValidationInfo = { };
  var isValid = true;
  for(var i = 0; i < recordKeys.length; i++) {
   var key = recordKeys[i];
   var itemInfo = this.ValidateItem(key, null, validateNotModified);
   pageValidationInfo[key] = itemInfo;
   isValid &= itemInfo.isValid;
  }
  return { isValid: isValid, dict: pageValidationInfo };
 },
 ValidateItem: function(key, itemValues, validateNotModified) {
  var invalidColumnIndices = [ ];
  var validationInfo = this.GetItemValidationInfo(key, itemValues, validateNotModified);
  if(validationInfo) {
   for(var columnIndex in validationInfo) {
    if(this.IsEditableColumn(columnIndex) && !validationInfo[columnIndex].isValid)
     invalidColumnIndices.push(columnIndex);
   }
  }
  this.ResetItemValidationState(key); 
  var isValid = invalidColumnIndices.length === 0;
  if(!isValid)
   this.invalidItemsInfo[key] = invalidColumnIndices;
  return { isValid: isValid, dict: validationInfo };
 },
 GetItemValidationInfo: function(key, itemValues, validateNotModified) {
  if(this.IsDeletedRecord(key))
   return;
  if(!this.HasChanges(key) && !this.IsEditingRecord(key) && !validateNotModified)
   return;
  var result = { };
  var columnIndices = this.GetEditColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   this.EnsureCellServerHtml(key, columnIndex);
   var value = this.GetCellValue(key, columnIndex);
   if(itemValues && itemValues.hasOwnProperty(columnIndex))
    value = itemValues[columnIndex].value;
   result[columnIndex] = this.GetCellValidationInfo(key, columnIndex, value, false);
  }
  result = this.owner.RaiseBatchEditRecordValidating(key, result);
  return result;
 },
 GetCellValidationInfo: function(recordKey, columnIndex, value, isMultipleCellSelection) {
  var isValid = true;
  var errorText = "";
  var editor = this.GetEditor(columnIndex);
  if(editor) {
   var restoreEditorValue = false;
   var editorPrevValue = editor.GetValue();
   if(this.IsEditingCell(recordKey, columnIndex))
    value = editorPrevValue;
   else {
    editor.LockStyleDecorationUpdate();
    editor.SetValue(value);
    if(isMultipleCellSelection)
     value = editor.GetValue();
    else
     restoreEditorValue = true;
   }
   this.ValidateEditor(editor);
   editor.UnlockStyleDecorationUpdate();
   isValid = editor.GetIsValid();
   errorText = editor.GetErrorText();
   if(restoreEditorValue)
    editor.SetValue(editorPrevValue);
  }
  return { value: value, isValid: isValid, errorText: errorText };
 },
 ValidateEditor: function(editor) { editor.Validate(); },
 ApplyValidationInfo: function(recordKey, validationInfo) {
  if(!this.IsValidRecord(recordKey) || !validationInfo || !validationInfo.dict) 
   return;
  var validColumnIndices = [ ];
  for(var columnIndex in validationInfo.dict) {
   if(!this.IsEditableColumn(columnIndex)) continue;
   var cellInfo = validationInfo.dict[columnIndex];
   if(!cellInfo.isValid)
    this.ShowCellValidationError(recordKey, columnIndex, cellInfo.errorText);
   else
    validColumnIndices.push(columnIndex);
  }
  for(var i = 0; i < validColumnIndices.length; i++) {
   var textContainer = this.GetCellTextContainer(recordKey, validColumnIndices[i]);
   if(textContainer && textContainer.dxgvHasError) {
    this.UpdateItem(recordKey, validColumnIndices);
    break;
   }
  }
 },
 UserValidateItems: function(recordKey, validateOnlyModified, validateOnCurrentPageOnly) { 
  var keys = ASPx.IsExists(recordKey) ? [ recordKey ] : this.GetRecordKeysForValidation(validateOnCurrentPageOnly);
  var validationInfo = this.ValidateItemsCore(keys, !validateOnlyModified);
  for(var key in validationInfo.dict) {
   if(!validationInfo.dict.hasOwnProperty(key)) continue;
   this.ApplyValidationInfo(key, validationInfo.dict[key]);
  }
  return validationInfo;
 },
 AddNewRecord: function(parentRecordKey) {
  var newRecordKeyInfo = this.CreateNewRecordKeyInfo(parentRecordKey);
  if(!this.owner.AllowInsert() || !this.HasKeyField() || !this.CanAddNewRecord(newRecordKeyInfo)) 
   return false;
  this.AddNewRecordCore(newRecordKeyInfo);
  this.summaryHelper.InsertRecord(newRecordKeyInfo.key);
  this.AddInsertedKeyInfo(newRecordKeyInfo);
  this.OnNewRecordAdded(newRecordKeyInfo);
  var newRecordKey = newRecordKeyInfo.key;
  this.OnBeforeStartEditNewRecord(newRecordKey);
  var columnIndex = this.GetFirstVisibleEditColumnIndex(this.GetEditColumnIndices(), newRecordKey);
  this.StartEdit(newRecordKey, columnIndex);
  this.EnsureEmptyRecordVisibility();
  return true;
 },
 OnBeforeStartEditNewRecord: function(newRecordKey) {
  this.owner.OnBeforeStartEditNewRecord(newRecordKey);
 },
 AddNewRecordCore: function(recordKeyInfo) {
  this.owner.AddNewRecord(recordKeyInfo, this.GetNewRecordSiblingKey(), this.IsNewItemOnTop());
 },
 OnNewRecordAdded: function(recordKeyInfo) {
  this.owner.OnNewRecordAdded(recordKeyInfo.key);
  this.focusHelper.OnDataItemAdded(recordKeyInfo.key);
 },
 CanAddNewRecord: function(keyInfo) {
  if(this.IsValidRecord(keyInfo.key)|| this.owner.RaiseBatchEditRecordInserting(keyInfo))
   return false;
  return true;
 },
 GetNewRecordSiblingKey: function() {
  var insertedRecordKeys = this.GetInsertedRecordKeys();
  for(var i = insertedRecordKeys.length - 1; i >= 0; i--) {
   var key = insertedRecordKeys[i];
   if(this.IsValidRecord(key))
    return key;
  }
  return null;
 },
 DeleteItem: function(recordKey, skipErrorItemRemove, skipUpdateCommandButtons) {
  if(!this.owner.AllowDelete() || !this.HasKeyField() || recordKey === null) 
   return;
  if(!this.IsValidRecord(recordKey) || this.deletedItemKeys.indexOf(recordKey) > -1) return;
  if(this.editingRecordKey === recordKey && !this.EndEdit())
   return;
  if(this.owner.RaiseBatchEditRecordDeleting(recordKey, this.GetRecordValues(recordKey)))
   return;  
  this.OnBeforeDataItemDeleted(recordKey);  
  this.ProcessDeleteItem(recordKey);
  this.EnsureEmptyRecordVisibility();
  if(!skipErrorItemRemove)
   this.RemoveRecordError(recordKey);
  this.ResetItemValidationState(recordKey);
  this.UpdateSyncInput();
  if(!skipUpdateCommandButtons)
   this.UpdateCommandButtonsEnabled();
  this.OnDataItemDeleted(recordKey);
 },
 OnBeforeDataItemDeleted: function(deletedItemKey) {
  this.owner.OnBeforeDataItemDeleted(deletedItemKey, this.FindNextNotDeletedRecordKey(deletedItemKey));
  this.focusHelper.OnBeforeDataItemDeleted(deletedItemKey);
 },
 OnDataItemDeleted: function(deletedItemKey) {
  this.focusHelper.OnDataItemDeleted(deletedItemKey);
  this.owner.OnDataItemDeleted(deletedItemKey);  
 },
 ProcessDeleteItem: function(key) {
  var isNew = this.IsNewRecord(key);
  var highlightMode = this.GetHighlightDeletedItems();  
  if(!highlightMode)
   this.ResetChanges(key);
  if(highlightMode || !isNew) {
   this.deletedItemKeys.push(key);
   this.summaryHelper.RemoveRecord(key, true);
   if(this.NeedUpdateCommandButtonsForDeletedRecords())
    this.PrepareCommandButtonsForDeletedItem(key);
   this.ChangeDeletedRecordAppearance(key, false);
  }
 },
 NeedUpdateCommandButtonsForDeletedRecords: function() { return this.GetHighlightDeletedItems() || this.IsCallbacksEnabled(); },
 PrepareCommandButtonsForDeletedItem: function(recordKey) {
  this.UpdateRecordCommandButtonsVisibility(recordKey);
 },
 UpdateRecordCommandButtonsVisibility: function (key) {
  this.owner.UpdateRecordCommandButtonsVisibility(key, this.GetRecordCommandButtonsVisibilityState(key));
  this.focusHelper.LoadDataItemActiveElements(key);  
 },
 GetRecordCommandButtonsVisibilityState: function(key) {
  var info = { };
  info.defaultButtonsVisible = this.GetDefaultCommandButtonsVisibility(key);
  info.recoverButton = { 
   visible: this.GetRecoverButtonVisibility(key), 
   columnIndex: this.GetRecoverButtonColumnKey(key), 
   html: this.GetRecoverButtonHtml(key) 
  };
  info.cancelButton = { 
   visible: this.GetCancelButtonVisibility(key), 
   columnIndex: this.GetCancelButtonColumnKey(key), 
   html: this.GetCancelButtonHtml(key) 
  };
  return info;
 },
 GetDefaultCommandButtonsVisibility: function(recordKey) {return !this.IsDeletedRecord(recordKey); },
 GetRecoverButtonVisibility: function(recordKey) {return this.IsDeletedRecord(recordKey); },
 GetCancelButtonVisibility: function(recordKey) {return !this.IsDeletedRecord(recordKey) && this.HasChanges(recordKey); },
 IsUpdateSummariesButtonVisible: function() { return this.summaryHelper && this.summaryHelper.IsRequiredCallback(); },
 GetRecoverButtonHtml: function(key) { return this.GetExtraCommandButtonHtml(this.RecoverButtonKey, key); },
 GetCancelButtonHtml: function(key) { return this.GetExtraCommandButtonHtml(this.CancelButtonKey, key); },
 GetRecoverButtonColumnKey: function() { return this.GetExtraCommandButtonColumnIndex(this.RecoverButtonKey); }, 
 GetCancelButtonColumnKey: function() { return this.GetExtraCommandButtonColumnIndex(this.CancelButtonKey); }, 
 GetExtraCommandButtonInfo: function(buttonKey) {
  var info = this.GetExtraCommandButtonsInfo();
  return info && info[buttonKey];
 },
 GetExtraCommandButtonHtml: function(buttonKey, recordKey) {
  var info = this.GetExtraCommandButtonInfo(buttonKey);
   if(!info || info[recordKey] === "hidden")
   return null;
  return info[recordKey] || info["etalon"];
 },
 GetExtraCommandButtonColumnIndex: function(buttonKey) {
  var info = this.GetExtraCommandButtonInfo(buttonKey);
  if(!info || !ASPx.IsExists(info.columnIndex))
   return -1;
  return info.columnIndex;
 },
 RecoverRecord: function(key) {
  if(!this.IsDeletedRecord(key) || this.owner.RaiseBatchEditRecordRecovering(key, this.GetRecordValues(key))) return;
  ASPx.Data.ArrayRemove(this.deletedItemKeys, key);
  this.summaryHelper.RecoverRecord(key, true);
  if(!this.GetRecord(key)) 
   return;
  this.RecoverRecordCore(key);
  this.focusHelper.OnBeforeDataItemRecover(key);  
  this.UpdateSyncInput();
  this.UpdateCommandButtonsEnabled();
  this.owner.OnDataRecordRecovered(key);
 },
 RecoverRecordCore: function(key) {
  this.ChangeDeletedRecordAppearance(key, true);
  this.ApplyValidationInfo(key, this.ValidateItem(key, null, true));
  if(this.NeedUpdateCommandButtonsForDeletedRecords())
   this.PrepareCommandButtonsForDeletedItem(key);
 },
 OnEditorValueChanged: function(editor, columnIndex) {
  if(this.IsCheckColumn(columnIndex))
   this.OnCheckBoxValueChanged(columnIndex);
  editor.Validate();
 },
 OnCheckBoxValueChanged: function(columnIndex) {
  var itemValues = this.GetRecordValues(this.editingRecordKey);
  this.LoadEditorValues(itemValues, this.editingRecordKey, this.editedColumnIndices);
  this.toogleCheckBoxColumnIndex = columnIndex;
  this.ApplyChanges(this.editingRecordKey, itemValues);
  this.UpdateItem(this.editingRecordKey, [columnIndex], true);
  this.UpdateCommandButtonsEnabled(this.IsEditing());
  this.toogleCheckBoxColumnIndex = -1;
 },
 OnDeleteKeyDown: function(recordKey) {
  var selectedCells = this.GetSelectedCells();
  if(selectedCells.length > 0) {
   ASPx.Data.ForEach(selectedCells, function(cellInfo) { this.UpdateCellValue(cellInfo.recordKey, cellInfo.columnIndex, "", "", true); }.bind(this));
   this.UpdateCommandButtonsEnabled(false);
  }
  else
   this.DeleteItem(recordKey);
 },
 EnsureEmptyRecordVisibility: function() {
  var show = !this.IsEditing() && this.RequireShowEmptyRecord();
  this.owner.ChangeEmptyRecordVisibility(show);
 }, 
 RequireShowEmptyRecord: function() {
  var keys = this.GetRecordKeys();
  return !keys.some(function(key) { return this.IsValidRecord(key) && this.IsRecordVisible(key); }.bind(this));
 },
 ChangeDeletedRecordAppearance: function(key, recover) {
  if(!ASPx.IsExists(key)) return;
  this.owner.ChangeDeletedRecordAppearance(key, recover, this.GetHighlightDeletedItems());
 },
 SafeRemoveHtmlItem: function(key) {
  if(this.IsValidRecord(key)) {
   this.MoveEditorsFromDeletingItem(key);
   this.RemoveRecordElement(key);
  }
 },
 MoveEditorsFromDeletingItem: function(key) {
  if(this.IsValidRecord(key)) 
   this.MoveEditorsFromDeletingItemCore(key);
 },
 MoveEditorsFromDeletingItemCore: function(key) {
  var editColumnIndices = this.GetEditColumnIndices();
  var editorsContainer = this.owner.GetEditorsContainer();
  for(var i = 0; i < editColumnIndices.length; i++) {
   var columnIndex = editColumnIndices[i];
   var editorContainer = this.GetEditorContainer(columnIndex);
   if(ASPx.GetIsParent(this.GetDataCell(key, columnIndex), editorContainer))
    editorsContainer.appendChild(editorContainer);
  }
 },
 RemoveItemErrors: function() {
  var keys = this.GetRecordKeys();
  for(var i = 0; i < keys.length; i++)
   this.RemoveRecordError(keys[i]);
 },
 ApplyCellValidationError: function(recordKey, columnIndex, errorText) {
  this.ApplyCellValidationState(recordKey, columnIndex);
  this.ShowCellValidationError(recordKey, columnIndex, errorText);
 },
 ResetCellValidationError: function(recordKey, columnIndex) {
  this.ResetCellValidationState(recordKey, columnIndex);
  this.UpdateCell(recordKey, columnIndex);
 },
 ShowCellValidationError: function(recordKey, columnIndex, errorText) {
  var textContainer = this.GetCellTextContainer(recordKey, columnIndex);
  if(!textContainer)
   return;
  this.owner.ShowDataCellError(textContainer, errorText, this.IsEllipsisAllowed(columnIndex));
  textContainer.dxgvHasError = true;  
 },
 GetCheckBoxDisplayText: function(editor, columnIndex) {
  return this.GetCheckColumnDisplayText(editor.GetValue(), columnIndex);
 },
 GetCheckColumnDisplayText: function(value, columnIndex) {
  var columnDisplayHtml = this.GetCheckColumnsDisplayHtml();
  var state = columnDisplayHtml[columnIndex];
  for(var i = 0; i < state.length; i++) {
   var item = state[i];
   if(item && item[0] === value) 
    return item[1].toString();
  }
  return ASPx.IsExists(value) ? value.toString() : "";
 },
 GetColorEditDisplayText: function(editor, columnIndex) {
  return this.GetColorEditColumnDisplayText(editor.GetValue(), columnIndex);
 },
 GetColorEditColumnDisplayText: function(value, columnIndex) {
  if(!ASPx.IsExists(value))
   return "";
  value = ASPxClientColorEdit.ParseColor(value);
  if(!value) 
   return "";
  var displayText = this.GetColorEditColumnsDisplayHtml()[columnIndex];
  while(displayText.indexOf(this.ColorPlaceholder) > -1)
   displayText = displayText.replace(this.ColorPlaceholder, value.toUpperCase());
  return displayText;
 },
 GetBinaryImageDisplayText: function(editor, columnIndex) {
  var html = this.GetBinaryImageColumnsDisplayHtml()[columnIndex];
  if(!html || !editor.GetValue())
   return "&nbsp;";
  var url = editor.GetImageUrl();
  return html.replace(this.ImageUrlPlaceholder, url);
 },
 GetComboBoxEditDisplayText: function(comboBox, columnIndex, text) {
  var selectedItem = comboBox.GetSelectedItem();
  if(selectedItem && selectedItem.imageUrl) {
   var displayHTML = this.GetComboBoxColumnsDisplayHtml()[columnIndex];
   displayHTML = displayHTML.replace(this.ImageUrlPlaceholder, selectedItem.imageUrl);
   displayHTML = displayHTML.replace(this.TextPlaceholder, text);
   return displayHTML;
  }
  return text;
 },
 ProcessTableClick: function(item, src, evt, isDblClick) {
  if(!this.IsRecordElement(item) || src.tagName === "A" || src.tagName === "TEXTAREA")
   return;
  if(src.tagName === "INPUT" && !this.CanProcessInputClick(item, src))
   return;
  var key = this.owner.GetRecordKeyByElement(item);
  var columnIndex = this.GetColumnIndexByChild(src);
  var toogleCheckBox = !this.IsEditing() && this.CanEditColumn(columnIndex) && this.IsCheckBoxDisplayControlClicked(columnIndex, src);
  if(toogleCheckBox) {
   this.StartEdit(key, columnIndex);
   var editor = this.GetEditor(columnIndex);
   if(editor && this.IsEditing())
    editor.ToogleCheckState();
   else
    this.OnCancelDisplayCheckBoxClick(key, columnIndex);
  } else if(this.CanStartEditOnClick(src, columnIndex, evt, isDblClick))
   this.StartEdit(key, columnIndex);
 },
 OnCancelDisplayCheckBoxClick: function(key, columnIndex) { },
 CanProcessInputClick: function (item, src) {
  return false;
 },
 CanStartEditOnClick: function(element, columnIndex, evt, isDblClick) {
  if(this.owner.GetCellSelectionHelper() && (evt.ctrlKey || evt.shiftKey))
   return false;
  if(this.IsStartEditOnDblClick() ^ isDblClick)
   return false;
  if(this.IsStartEditOnFocusedCellClick() && !this.focusHelper.CanStartEditOnCellClick())
   return false;
  if(this.IsSingleEditMode() && !this.CanEditColumn(columnIndex))
   return false;   
  if(this.IsTimeSectionTimeEditChildElement(element, columnIndex))
   return false;
  return true;
 },
 CanStartEditOnTableClick: function(item, evt) { 
  if(this.IsRecordElement(item)) {
   var columnIndex = this.GetColumnIndexByChild(ASPx.Evt.GetEventSource(evt));
   return this.CanEditColumn(columnIndex);
  }
  return false;
 },
 IsTimeSectionTimeEditChildElement: function(src, columnIndex) {
  var editor = this.GetEditor(columnIndex);
  if(editor && this.IsDateEdit(editor) && editor.GetShowTimeSection()) {
   var timeEdit = editor.GetTimeEdit();
   if(timeEdit)
    return ASPx.GetIsParent(timeEdit.GetMainElement(), src);
  }
  return false;
 },
 GetRecordElementByChild: function(element) { return ASPx.GetParent(element, this.IsRecordElement.aspxBind(this)); }, 
 StartEditCell: function(recordKey, columnIndex) {
  var columnIndices = this.GetEditColumnIndices();
  if(!ASPx.IsExists(columnIndex) || columnIndex < 0 || !ASPx.Data.ArrayIndexOf(columnIndices, columnIndex))
   columnIndex = this.GetFirstVisibleEditColumnIndex(columnIndices, recordKey);
  this.StartEdit(recordKey, columnIndex);
 },
 StartEdit: function(recordKey, columnIndex) { 
  if(this.IsDeletedRecord(recordKey))
   return;
  var isNewRecord = this.IsNewRecord(recordKey);
  if(!this.owner.AllowEdit() && !isNewRecord || !this.focusHelper.CanStartEdit())
   return;
  if(this.IsSingleEditMode() && this.IsEditingCell(recordKey, columnIndex))
   return;
  if(!this.IsSingleEditMode() && this.IsEditingRecord(recordKey)) {
   if(this.CanEditColumn(columnIndex))
    this.focusHelper.FocusColumnEditor(columnIndex);
   return;
  }
  if(this.IsEditing() && !this.EndEdit())
   return;
  if(isNewRecord)
   this.StartEditNewRecord(recordKey, columnIndex);
  else
   this.StartEditExistingRecord(recordKey, columnIndex);
 },
 StartEditExistingRecord: function(recordKey, columnIndex) {
  if(!this.focusHelper.TryFocusCell(recordKey, columnIndex))
   return;
  var indices = this.IsSingleEditMode() ? [ columnIndex ] : this.GetEditColumnIndices();
  this.StartEditCore(recordKey, indices, columnIndex);
 },
 StartEditNewRecord: function(recordKey, columnIndex) {
  if(!this.focusHelper.TryFocusCell(recordKey, columnIndex, true))
   return;
  var isSingleEditMode = this.IsSingleEditMode();
  if(isSingleEditMode) {
   var focusedCellInfo = this.focusHelper.GetFocusedCellInfo();
   if(focusedCellInfo)
    columnIndex = focusedCellInfo.columnIndex;
  }
  var indices = isSingleEditMode ? [ columnIndex ] : this.GetEditColumnIndices();
  this.StartEditCore(recordKey, indices, columnIndex);
 },
 StartEditCore: function(recordKey, columnIndices, focusedColumnIndex) {
  if(!this.IsValidRecord(recordKey) || !columnIndices || columnIndices.length === 0)
   return;
  columnIndices = this.ExcludeNonEditableColumnIndices(columnIndices, recordKey);
  columnIndices = this.IntersectColumnIndices(this.GetEditColumnIndices(), columnIndices);
  if(columnIndices.length === 0)
   return;
  if(!ASPx.IsExists(focusedColumnIndex) || !this.CanEditColumn(focusedColumnIndex))
   focusedColumnIndex = this.GetFirstVisibleEditColumnIndex(columnIndices, recordKey);
  var startEditArgs = this.owner.RaiseBatchEditStartEditing(recordKey, this.GetColumn(focusedColumnIndex), this.GetRecordValues(recordKey));
  if(!startEditArgs || startEditArgs.cancel || this.GetObjectSize(startEditArgs.itemValues) === 0) 
   return;
  var itemValues = startEditArgs.itemValues;
  columnIndices = this.IntersectColumnIndices(ASPx.GetObjectKeys(itemValues), columnIndices);
  if(columnIndices.length === 0)
   return;
  ASPx.Selection.Clear();
  this.MoveEditors(recordKey, columnIndices);
  this.SetEditorValues(itemValues, columnIndices);
  this.UpdateItem(recordKey, columnIndices, true);
  this.editingRecordKey = recordKey;
  this.editedColumnIndices = columnIndices;
  this.focusHelper.OnEditStarted(recordKey, columnIndices, startEditArgs.focusedColumn);
  this.UpdateCommandButtonsEnabled(true);
 },
 SetEditorValues: function(itemValues, columnIndices) {
  this.SetEditorValuesCore(itemValues, columnIndices);
 },
 SetEditorValuesCore: function(itemValues, columnIndices) {
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var editor = this.GetEditor(columnIndex);
   if(editor && itemValues.hasOwnProperty(columnIndex)) {
    if(this.IsComboBoxCallbackModeColumn(columnIndex))
     this.PrepareComboBoxInCallbackMode(editor, columnIndex, itemValues[columnIndex].value);
    editor.SetIsValid(true);
    editor.SetValue(itemValues[columnIndex].value);
   }
  }
 },
 PrepareComboBoxInCallbackMode: function(comboBox, columnIndex, value) {
  this.PrepareComboBoxFilteringInCallbackMode(comboBox);
  this.PrepareComboBoxCustomItemsRangeLoading(comboBox);
  var hasItem = !!comboBox.FindItemByValue(value);
  if(hasItem) return;
  comboBox.ClearItems();
  var itemInfo = this.GetComboBoxCallbackModeItemsInfo()[columnIndex][value];
  if(itemInfo)
   comboBox.AddItem(itemInfo.texts, value, itemInfo.imageUrl);
  var serverModeEnabled = this.IsComboBoxWithServerItemsColumn(columnIndex);
  var requiredLoadItemsFromRange = !serverModeEnabled || !itemInfo;
  if(requiredLoadItemsFromRange) {
   var startIndex = itemInfo ? itemInfo.itemServerIndex : 0;
   comboBox.ForceLoadCustomItemsRangeOnDropDown(startIndex, value);
  }
  else
   comboBox.InitScrollSpacerVisibility(); 
  comboBox.dxgvBatchAddedValue = value;
 },
 PrepareComboBoxFilteringInCallbackMode: function(comboBox) {
  comboBox.dxgvBatchFiltered = false;
  var filterStrategy = comboBox.filterStrategy;
  if(!filterStrategy || filterStrategy.dxgBatchEndFilteringAssigned) 
   return;
  var endFilteringOrigin = filterStrategy.OnEndFiltering;
  filterStrategy.OnEndFiltering =  function(visibleCollectionChanged) {
   endFilteringOrigin.call(filterStrategy, visibleCollectionChanged);
   comboBox.dxgvBatchFiltered = true;
  };
  filterStrategy.dxgBatchEndFilteringAssigned = true;
 },
 PrepareComboBoxCustomItemsRangeLoading: function(comboBox) {
  if(comboBox.dxgvBatchOnSuccessCustomItemsRangeLoad) return;
  var nativeMethod = comboBox.OnSuccessCustomItemsRangeLoad;
  comboBox.OnSuccessCustomItemsRangeLoad = function() {
   if(!this.customItemsRangeInfo) return;
   if(this.cpLoadedOnCallbackIndices) {
    var serverIndices = this.cpLoadedOnCallbackIndices;
    var firstItem = this.GetItem(0);
    if(firstItem && ASPx.IsExists(serverIndices[firstItem.value]) && serverIndices[firstItem.value] != this.customItemsRangeInfo.startIndex)
     this.customItemsRangeInfo.startIndex = serverIndices[firstItem.value];
   }
   nativeMethod.call(this);
  };
  comboBox.dxgvBatchOnSuccessCustomItemsRangeLoad = true;
 },
 RemoveDuplicatedItem: function(comboBox) { 
  var valueToCheck = comboBox && comboBox.dxgvBatchAddedValue;
  if(!valueToCheck) return;
  var firstItem = comboBox.GetItem(0);
  if(firstItem && firstItem.value === valueToCheck) { 
   for(var i = 1; i < comboBox.GetItemCount(); i++) {
    var item = comboBox.GetItem(i);
    if(item && item.value === valueToCheck) {
     comboBox.RemoveItem(0);
     comboBox.CancelLoadCustomRangeOnDropDown();
     break;
    }
   }
  }
  comboBox.dxgvBatchAddedValue = null;
 },
 MoveEditors: function(recordKey, columnIndices) {
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var editorContainer = this.GetEditorContainer(columnIndex);
   var textContainer = this.GetCellTextContainer(recordKey, columnIndex);
   if(!editorContainer || !textContainer)
    continue;
   ASPx.SetElementDisplay(editorContainer, false);
   ASPx.SetElementDisplay(textContainer, true);
   var dataCell = textContainer.parentNode;
   if(editorContainer.parentNode !== dataCell) {
    dataCell.appendChild(editorContainer);
    ASPx.GetStateController().ClearElementCacheInContainer(editorContainer);
   }
  }
 },
 EndEdit: function(skipValidation) {
  if(this.IsEndEditLocked() || this.focusHelper.IsEndEditCalledDuringTableClick())
   return false;
  this.focusHelper.OnBeforeEditEnded();
  this.LockEndEdit();
  if(!this.IsEditing() || !this.IsValidRecord(this.editingRecordKey)) {
   this.UnlockEndEdit();
   return true;
  }
  var itemValues = this.GetRecordValues(this.editingRecordKey);
  this.LoadEditorValues(itemValues, this.editingRecordKey, this.editedColumnIndices);
  var endEditArgs = this.owner.RaiseBatchEditEndEditing(this.editingRecordKey, this.GetFocusedColumn(), itemValues);
  if(!endEditArgs || endEditArgs.cancel) {
   this.UnlockEndEdit();
   return false;
  }
  var endEditValidationInfo = this.GetEndEditValidationInfo(endEditArgs.itemValues, skipValidation);
  if(!endEditValidationInfo.allowEndEdit) {
   this.UnlockEndEdit();
   return false;
  }
  var validationInfo = endEditValidationInfo.info;
  itemValues = this.FilterItemValues(endEditArgs.itemValues, this.editedColumnIndices);
  this.ApplyChanges(this.editingRecordKey, itemValues);
  this.UpdateItem(this.editingRecordKey, this.editedColumnIndices);
  this.ApplyValidationInfo(this.editingRecordKey, validationInfo);
  this.UpdateSyncInput();
  this.ClearComboBoxesInCallbackMode(this.editedColumnIndices);
  var prevKey = this.editingRecordKey;
  this.editingRecordKey = this.InvalidRecordKey;
  this.editedColumnIndices = [];
  this.UnlockEndEdit();
  this.focusHelper.OnEditEnded();
  this.UpdateCommandButtonsEnabled();
  this.owner.OnRecordEditEnded(prevKey);
  this.RemoveRecordErrorIfHasNoChanges(prevKey);
  return true;
 },
 LockEndEdit: function() { this.lockEndEdit = true; },
 UnlockEndEdit: function() { this.lockEndEdit = false; },
 IsEndEditLocked: function() { return this.lockEndEdit; },
 RemoveRecordErrorIfHasNoChanges: function(prevKey) {
  if(!this.HasChanges(prevKey))
   this.RemoveRecordError(prevKey);
 },
 GetEndEditValidationInfo: function(itemValues, skipValidation) {
  var info = null;
  var allowEndEdit = true;
  if(!skipValidation && this.RequireValidateOnEndEdit()) {
   info = this.ValidateItem(this.editingRecordKey, itemValues);
   var isValid = this.IsSingleEditMode() ? info.dict[this.editedColumnIndices[0]].isValid : info.isValid;
   if(!isValid && !this.AllowEndEditOnError())
    allowEndEdit = false;
  }
  return { info: info, allowEndEdit: allowEndEdit };
 },
 LoadEditorValues: function(recordValues, recordKey, columnIndices) {
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var editor = this.GetEditor(columnIndex);
   if(!editor) continue;
   if(ASPx.IsFunction(editor.ForceTextChanged) && this.RequireEditorTextChanged(editor))
    editor.ForceTextChanged();
   var value = editor.GetValue();
   if(value === null && editor.convertEmptyStringToNull && this.GetServerValue(recordKey, columnIndex) === "")
    value = "";
   var text = this.GetEditorDisplayText(editor, columnIndex);
   recordValues[columnIndex] = { value: value, text: text };
  }
 },
 RequireEditorTextChanged: function(editor) {
  if(editor.isNative && typeof(ASPxClientNativeComboBox) !== "undefined" && editor instanceof ASPxClientNativeComboBox)
   return false;
  return true;
 },
 ClearComboBoxesInCallbackMode: function(columnIndices) {
  for(var i = 0; i < columnIndices.length; i++) { 
   var columnIndex = columnIndices[i];
   var editor = this.GetEditor(columnIndex);
   if(!editor || !this.IsComboBoxCallbackModeColumn(columnIndex))
    continue;
   editor.CancelLoadCustomRangeOnDropDown();
   var filterStrategy = editor.filterStrategy;
   if(filterStrategy && ASPx.IsExists(filterStrategy.filter) && (filterStrategy.filter !== "" || editor.dxgvBatchFiltered)) {
    filterStrategy.ClearFilter();
    filterStrategy.OnEscape();
    editor.ClearItems();
    editor.ResetWaitingCallbacks();
   }
  }
 },
 ApplyChanges: function(recordKey, itemValues) {
  for(var columnIndex in itemValues) {
   if(!itemValues.hasOwnProperty(columnIndex)) continue;
   var info = itemValues[columnIndex];
   this.SetCellValue(recordKey, columnIndex, info.value, info.text);
  }
 },
 AreValuesEqual: function(val1, val2, columnIndex) { 
  if(val1 === val2)
   return true;
  if(!ASPx.IsExists(val1) || !ASPx.IsExists(val2))
   return false;
  if(this.IsColorEditColumn(columnIndex) && val1 !== "" && val2 !== "") {
   val1 = ASPxClientColorEdit.ParseColor(val1);
   val2 = ASPxClientColorEdit.ParseColor(val2);
  }
  var text1 = this.PrepareStrToCompare(val1.toString());
  var text2 = this.PrepareStrToCompare(val2.toString());
  return text1 === text2;
 },
 PrepareStrToCompare: function(text) {
  return text.replace(/\r/g,'\n'); 
 },
 UpdateItem: function(recordKey, columnIndices, showEditors, reset, fromAPI) { 
  if(!this.IsValidRecord(recordKey)) return;
  var cellSizes = showEditors ? this.GetCellSizes(recordKey, columnIndices) : null;
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var cellSize = cellSizes ? cellSizes[columnIndex] : null;
   this.UpdateCell(recordKey, columnIndex, showEditors, reset, cellSize, fromAPI);
  }
  this.UpdateRecordCommandButtonsVisibility(recordKey);
 },
 UpdateCell: function(recordKey, columnIndex, showEditor, reset, cellSize, fromAPI) {
  if(reset) showEditor = false;
  var dataCell = this.GetDataCell(recordKey, columnIndex);
  var editorContainer = this.GetEditorContainer(columnIndex);
  var textContainer = this.GetCellTextContainer(recordKey, columnIndex);
  if(!dataCell || !editorContainer || !textContainer) 
   return;
  if(showEditor) 
   this.FixElementHeight(dataCell.parentNode);
  ASPx.SetElementDisplay(textContainer, !showEditor);
  if(!showEditor)
   this.UpdateCellText(recordKey, columnIndex);
  var style = this.GetCellStyle(recordKey, columnIndex, showEditor, reset);
  this.ChangeCellStyle(recordKey, columnIndex, style, showEditor);
  if(showEditor && this.IsCheckColumn(columnIndex))
   this.AppendCheckBoxClassName(dataCell);
  if(showEditor && cellSize)
   this.UpdateCellSizes(showEditor, cellSize, dataCell);
  var display = showEditor ? "" : "none";
  if(!fromAPI)
   ASPx.SetStyles(editorContainer, { display: display });
  var editor = this.GetEditor(columnIndex);
  if(showEditor && this.IsMemoEdit(editor) && editor.heightCorrectionRequired) {
   ASPx.SetStyles(editorContainer, { height: "100%" });
   editor.AdjustControl();
   ASPx.SetStyles(editorContainer, { height: "" });
  }
  if(ASPx.Browser.Firefox && editor) {
   var input = editor.GetInputElement();
   try {
    if(input)
     input.setSelectionRange(0, 0, "backward");
   } catch(e) { }
  }
  if(showEditor)
   this.RestoreElementHeight(dataCell.parentNode);
  textContainer.dxgvHasError = false;
 },
 AppendCheckBoxClassName: function(cell) {
  var helper = this.owner.GetStyleHelper();
  helper.AddToBatchEditStyle(cell, null, [this.CheckBoxCellClassName]);
 },
 UpdateCellSizes: function(showEditor, cellSize, dataCell) {
  var width = showEditor ? cellSize.width - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(dataCell) : "";
  var height = showEditor ? cellSize.height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(dataCell) : "";
  if(ASPx.IsNumber(width) && width < 0)
   width = 0;
  if(ASPx.IsNumber(height) && height < 0)
   height = 0;
  this.owner.UpdateCellStyle(dataCell, { width: width, height: height });
 },
 FixElementHeight: function(element) { 
  if(element) {
   var height = this.GetElementSizes(element).height;
   ASPx.Attr.ChangeStyleAttribute(element, "height", height + "px"); 
   this.owner.GetStyleHelper().AddStyleToElementInitialCssText(element, { height: height });
  }
 },
 RestoreElementHeight: function(element) { 
  if(element) {
   ASPx.Attr.RestoreStyleAttribute(element, "height");
   this.owner.GetStyleHelper().ResetElementInitialCssText(element);
  }
 },
 GetCellSizes: function(recordKey, columnIndices) {
  var result = { };
  for(var i = 0; i < columnIndices.length; i++) { 
   var columnIndex = columnIndices[i];
   var dataCell = this.GetDataCell(recordKey, columnIndex);
   if(dataCell)
    result[columnIndex] = this.GetElementSizes(dataCell);
  }
  return result;
 },
 GetElementSizes: function(element) {
  if(ASPx.Browser.Edge) {
   var rect = element.getBoundingClientRect();
   return {
    width: this.TruncateSizeValue(rect.width), 
    height: this.TruncateSizeValue(rect.height)
   };
  }
  else
   return { width: element.offsetWidth, height: element.offsetHeight };
 },
 TruncateSizeValue: function(value) {
  return Math.floor(value * 100) / 100;
 },
 UpdateCellText: function(recordKey, columnIndex) {
  if(!this.GetAllowUpdateCellText(columnIndex)) return;
  if(this.IsProgressBarColumn(columnIndex)) {
   this.owner.UpdateProgressBarColumnValue(recordKey, columnIndex, this.GetCellValue(recordKey, columnIndex));
  } else {
   var textContainer = this.GetCellTextContainer(recordKey, columnIndex);
   ASPx.SetInnerHtml(textContainer, this.GetCellContent(recordKey, columnIndex));
  }
 },
 GetEditorDisplayText: function(editor, columnIndex) {
  if(this.IsCheckColumn(columnIndex))
   return this.GetCheckBoxDisplayText(editor, columnIndex);
  if(this.IsColorEditColumn(columnIndex))
   return this.GetColorEditDisplayText(editor, columnIndex);
  if(this.IsBinaryImageColumn(columnIndex))
   return this.GetBinaryImageDisplayText(editor, columnIndex);
  var text = this.GetFormattedEditorText(editor);
  if(this.IsComboBoxEditColumn(columnIndex, editor))
   return this.GetComboBoxEditDisplayText(editor, columnIndex, text);
  if(this.IsMemoEdit(editor) && !this.IsEllipsisAllowed(columnIndex))
   return text.replace(/(\r\n|\r|\n)/g, '<br />');
  var input = editor.GetInputElement();
  if(ASPx.IsExists(text) && text.length > 0 && input && ASPx.Attr.GetAttribute(input, "type") == "password") {
   var bag = [ ];
   bag[text.length] = "";
   text = bag.join("*");
  }
  return text;
 },
 GetFormattedEditorText: function(editor) {
  var text = ASPx.IsFunction(editor.GetFormattedText) ? editor.GetFormattedText() : editor.GetText();
  if(!text && editor.GetValue() === null)
   text = this.GetColumnNullDisplayText(editor.dxgvColumnIndex);
  text = editor.HtmlEncode(text);
  return text;
 },
 GetColumnNullDisplayText: function(columnIndex) {
  var info = this.GetColumnsNullDisplayTextInfo();
  if(!info || !info[columnIndex])
   return "";
  return info[columnIndex];
 },
 GetCellStyle: function(recordKey, columnIndex, showEditor, reset) {
  var helper = this.owner.GetStyleHelper();
  if(reset) return helper.GetEmptyCellStyle();
  if(this.HasModifiedStyle(recordKey, columnIndex))
   return showEditor ? helper.GetBatchEditMergedModifiedCellStyle() : helper.GetBatchEditModifiedCellStyle(columnIndex);
  return showEditor ? helper.GetBatchEditCellStyle() : helper.GetEmptyCellStyle();
 },
 HasModifiedStyle: function(recordKey, columnIndex) {
  if(this.toogleCheckBoxColumnIndex === columnIndex)
   return !this.AreValuesEqual(this.GetEditor(columnIndex).GetValue(), this.GetServerValue(recordKey, columnIndex), columnIndex);
  return this.IsDirtyCell(recordKey, columnIndex) && !this.CancelCellHighlight(recordKey, columnIndex);
 },
 CancelCellHighlight: function(recordKey, columnIndex) {
  var hash = this.GetClientValuesBag(recordKey);  
  var rowValues = hash[recordKey];
  return !!rowValues && rowValues.hasOwnProperty(columnIndex) && rowValues[columnIndex][2];
 },
 GetVisibleRecordsOnPageCount: function() {
  var visibleInsertedRows = this.GetInsertedRecordKeys(true).filter(function(key) { return this.IsRecordVisible(key); }.bind(this));
  var result = this.GetOwnerControl().pageRowCount + visibleInsertedRows.length;
  if(!this.GetHighlightDeletedItems())
   result -= this.GetDeletedRecordKeys(true).length;
  return result;
 },
 IsValidRecordKey: function(key) { return ASPx.Data.ArrayContains(this.GetServerRecordKeys(true), key) || this.IsNewRecord(key); },
 CanUpdate: function() {
  if(this.IsEditing() && !this.EndEdit())
   return false;  
  var isCallbackMode = this.IsCallbacksEnabled();
  var hasInvalidItems = this.HasInvalidItems();
  if(!this.RequireValidateOnEndEdit() || isCallbackMode)
   hasInvalidItems = !this.DelayedValidateItems();
  var canUpdate = !hasInvalidItems && this.HasChanges();  
  if(hasInvalidItems && isCallbackMode)
   this.ShowInvalidItemsInCallbackMode();
  return canUpdate && !this.owner.RaiseBatchEditChangesSaving(this.GetChangedValuesInfo());
 },
 ShowInvalidItemsInCallbackMode: function() { },
 DelayedValidateItems: function() {
  var pageValidationInfo = this.ValidateItems();
  if(!pageValidationInfo.isValid) {
   for(var key in pageValidationInfo.dict) {
    if(!pageValidationInfo.dict.hasOwnProperty(key)) continue;
    this.ApplyValidationInfo(key, pageValidationInfo.dict[key]);
   }
  }
  return pageValidationInfo.isValid;
 },
 CancelEdit: function(recordKey) {
  if(!this.EndEdit(true))
   return;
  if(recordKey !== null) {
   var cancelEditArgs = this.owner.RaiseBatchEditItemChangesCanceling(recordKey, this.GetRecordValues(recordKey));
   if(cancelEditArgs && cancelEditArgs.cancel)
    return;
  }
  isRecordReset = ASPx.IsExists(recordKey) && this.IsValidRecord(recordKey);
  if(isRecordReset) {
   this.ResetChanges(recordKey);
  } else {
   if(this.owner.RaiseBatchEditChangesCanceling(this.GetChangedValuesInfo()))
    return;
   this.ProcessCancelEdit();
   this.ResetAllChanges();
   this.RemoveItemErrors();
  }
  this.UpdateCommandButtonsEnabled();
  this.owner.RestoreFocusAccessibleAfterCancelEdit();
 },
 ProcessCancelEdit: function() { },
 OnUpdate: function() {
  this.ResetChangesInDeletedItems();
  this.updating = true;
  this.UpdateSyncInput();
 },
 ResetChangesInDeletedItems: function() {
  if(!this.GetHighlightDeletedItems())
   return;
  var keysToDelete = [ ];
  for(var i = 0; i < this.deletedItemKeys.length; i++) {
   var key = this.deletedItemKeys[i];
   if(ASPx.Data.ArrayContains(this.GetInsertedRecordKeys(), key)) {
    this.SafeRemoveHtmlItem(key);
    this.RemoveInsertedKeyInfo(key);
    keysToDelete.push(key);
   }
   delete this.insertedValues[key];
   delete this.updatedValues[key];
  }
  ASPx.Data.ForEach(keysToDelete, function(key) { ASPx.Data.ArrayRemove(this.deletedItemKeys, key); }.bind(this));
 },
 GetColumnDisplayTextByEditor: function(value, columnIndex) {
  var editor = this.GetEditor(columnIndex);
  if(!editor)
   return ASPx.IsExists(value) ? this.GetValueString(value) : "";
  var prevValue = editor.GetValue();
  editor.SetValue(value);
  var processedText = this.GetEditorDisplayText(editor, columnIndex);
  editor.SetValue(prevValue);
  return processedText;
 },
 OnItemStyleChanged: function(key, appliedStyle) { },
 UpdateSyncInput: function() { 
  this.owner.UpdateClientModifiedValues({ ClientState: this.GetClientState(), EditState: this.GetEditState() });
 },
 GetClientState: function() { 
  return { InsertedKeysInfo: this.GetInsertedKeysInfo(), InsertedValues: this.insertedValues, UpdatedValues: this.updatedValues, DeletedKeys: this.deletedItemKeys }; 
 },
 GetEditState: function() {
  var insertedRecordKeys = this.GetInsertedRecordKeys();
  var excludedKeys = this.deletedItemKeys.filter(function(key) { return ASPx.Data.ArrayContains(insertedRecordKeys, key); });
  var deletedKeys = this.deletedItemKeys.filter(function(key) { return !ASPx.Data.ArrayContains(excludedKeys, key); });
  var modifiedValues = { };
  var insertedRowValues = { };
  var editColumnIndices = this.GetEditColumnIndices();
  for(var rowKey in this.updatedValues) {
   if(!this.updatedValues.hasOwnProperty(rowKey)) continue;
   modifiedValues[rowKey] = this.CreateItemEditState(rowKey, editColumnIndices);
  }
  var insertedRecordKeysInfo = this.GetInsertedKeysInfo();
  for(var i = 0; i < insertedRecordKeysInfo.length; i++) {
   var keyInfo = insertedRecordKeysInfo[i];
   var newRecordKey = keyInfo.key;
   var rowValues = this.CreateItemEditState(newRecordKey, editColumnIndices);
   if(keyInfo.parentRecordKey) {
    rowValues[this.ParentRecordKeyName] = keyInfo.parentRecordKey;
    rowValues[this.RecordKeyName] = newRecordKey;
   }
   if(!ASPx.Data.ArrayContains(excludedKeys, newRecordKey))
    insertedRowValues[newRecordKey] = rowValues;
  }
  return { insertedRowValues : insertedRowValues, modifiedRowValues : modifiedValues, deletedRowKeys : deletedKeys };
 },
 CreateItemEditState: function(recordKey, columnIndices) {
  var result = { };
  var recordModifiedColumns = this.GetRecordModifiedColumns(recordKey);
  var hiddenModifiedColumns = recordModifiedColumns.filter(function(columnIndex) { return !ASPx.Data.ArrayContains(columnIndices, columnIndex); });
  columnIndices = columnIndices.concat(hiddenModifiedColumns);
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var fieldName = this.GetColumn(columnIndex).fieldName;
   var value = this.GetCellValue(recordKey, columnIndex);
   result[fieldName] = this.GetValueString(value);
  }
  this.AppendNonEditableColumnValues(result, recordKey);
  return result;
 },
 GetRecordModifiedColumns: function(recordKey) {
  var hash = this.GetClientValuesBag(recordKey);
  var recordValues = hash[recordKey];
  if(!recordValues)
   return [ ];
  return ASPx.GetObjectKeys(recordValues).map(function(columnKey) { return parseInt(columnKey); }); 
 },
 AppendNonEditableColumnValues: function(itemState, recordKey) {
  var values = this.GetNonEditableColumnValues();
  var rowValues = values && values[recordKey];
  if(!rowValues) return;
  for(var columnKey in rowValues) {
   if(rowValues.hasOwnProperty(columnKey)) {
    var columnIndex = parseInt(columnKey);
    var fieldName = this.GetColumn(columnIndex).fieldName;
    var value = rowValues[columnIndex];
    if(!itemState.hasOwnProperty(columnKey)) 
     itemState[fieldName] = this.GetValueString(value);
   }
  }
 },   
 UpdateSummaries: function(result) {
  this.summaryHelper.OnSummariesDataCallback(result);
 },
 GetFocusedColumn: function() {
  var focusedColumnIndex = this.focusHelper.ResolveColumnIndex(this.focusHelper.GetFocusedColumnKey());  
  return this.GetColumn(focusedColumnIndex);
 },
 GetValueString: function(value) {
  if(value == null) return null;
  if(ASPx.Ident.IsDate(value))
   return ASPx.DateUtils.GetInvariantDateTimeString(value);
  return value.toString();
 },
 GetFirstVisibleEditColumnIndex: function(columnIndices, recordKey) {
  if(columnIndices.length === 1)
   return columnIndices[0];
  var visibleColumnIndices = this.ExcludeNonEditableColumnIndices(this.GetVisibleColumnIndices(), recordKey);
  for(var i = 0; i < visibleColumnIndices.length; i++) {
   var columnIndex = visibleColumnIndices[i];
   if(ASPx.Data.ArrayIndexOf(columnIndices, columnIndex) >= 0 && this.IsCellVisible(recordKey, columnIndex))
    return columnIndex;
  }
  return -1;
 },
 IsCellVisible: function(recordKey, columnIndex) {
  var cell = this.GetDataCell(recordKey, columnIndex);
  if(!cell) return false;
  return ASPx.IsElementVisible(cell);
 },
 FindNextNotDeletedRecordKey: function(key) {  
  var keys = this.GetRecordKeys();
  var index = keys.indexOf(key);
  if(index < 0) return keys.filter(function(k) { return !this.IsDeletedRecord(k); }.bind(this))[0];
  var beforeKeys = keys.slice(0, index).reverse();
  var afterKeys = keys.slice(index + 1);
  var length = Math.max(beforeKeys.length, afterKeys.length);
  var sortedKeys = [ ];
  for(var i = 0; i < length; i++) {
   sortedKeys.push(afterKeys[i]);
   sortedKeys.push(beforeKeys[i]);
  }
  return sortedKeys.filter(function(k) { return ASPx.IsExists(k) && !this.IsDeletedRecord(k); }.bind(this))[0];
 },
 FilterItemValues: function(rowValues, columnIndices) {
  var result = { };
  if(!rowValues || columnIndices.length === 0)
   return result;
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   if(rowValues[columnIndex])
    result[columnIndex] = rowValues[columnIndex];
  }
  return result;
 },
 IntersectColumnIndices: function(indices1, indices2) {
  var hash = { };
  for(var i = 0; i < indices1.length; i++)
   hash[indices1[i]] = true;
  var result = [ ];
  for(var i = 0; i < indices2.length; i++) {
   var index = indices2[i];
   if(hash[index])
    result.push(index);
  }
  return result;
 },
 ExcludeNonEditableColumnIndices: function(columnIndices, recordKey) {
  return columnIndices.filter(function(columnIndex) { return !this.IsEditorHiddenForColumn(columnIndex) && this.owner.CanEditCell(recordKey, columnIndex); }.bind(this));
 },
 IsCheckBoxDisplayControlClicked: function (columnIndex, element) {
  var isCheckBoxElementClicked = ASPx.ElementContainsCssClass(element, this.owner.CheckBoxClassName)
   || ASPx.ElementContainsCssClass(element, this.CheckBoxSwitcherClassName);
  return this.IsCheckColumn(columnIndex) && isCheckBoxElementClicked;
 },
 GetChangedValuesInfo: function() {
  var info = { };
  info.updatedValues = this.GetUpdatedValues();
  info.insertedValues = this.GetInsertedValues();
  info.deletedValues = this.GetValues(this.deletedItemKeys);
  return info;
 },
 GetUpdatedValues: function() {
  var result = { };
  for(var key in this.updatedValues) {
   if(!this.updatedValues.hasOwnProperty(key)) continue;
   result[key] = rowValues = { };
   var updatedRowValues = this.updatedValues[key];
   for(var columnKey in updatedRowValues) {
    if(!updatedRowValues.hasOwnProperty(columnKey)) continue;
    var columnIndex = parseInt(columnKey);
    rowValues[columnIndex] = updatedRowValues[columnKey][0];
   }
  }  
  return result;
 },
 GetInsertedValues: function() {
  var recordKeysInfo = this.GetInsertedKeysInfo();
  var result = this.GetValues(this.GetInsertedRecordKeys());
  for(var i = 0; i < recordKeysInfo.length; i++) {
   var keyInfo = recordKeysInfo[i];
   var recordValues = result[keyInfo];
   if(recordValues)
    recordValues[this.ParentRecordKeyName] = keyInfo.parentRecordKey;
  }
  return result;
 },
 GetValues: function(itemKeys) {
  var result = { };
  for(var i = 0; i < itemKeys.length; i++) {
   var recordKey = itemKeys[i];
   result[recordKey] = { };
   var itemValues = this.GetRecordValues(recordKey);
   for(var columnKey in itemValues) {
    if(!itemValues.hasOwnProperty(columnKey)) continue;
    result[recordKey][columnKey] = itemValues[columnKey].value;
   }
  }
  return result;
 },
 UpdateAllRecordActiveElements: function () {
  this.focusHelper.LoadAllRecordActiveElements();
 }
});
BatchEditHelper.isBatchEditUnusedEditor = function(control) {
 var mainElement = control && control.GetMainElement();
 return !!mainElement && ASPx.GetParentByPartialClassName(control.GetMainElement(), "dxBEC");
};
var BatchEditUpdateWatcherHelper = ASPx.CreateClass(ASPx.UpdateWatcherHelper, {
 ShowConfirmWindowTimeout: 150,
 constructor: function(owner) {
  this.lockShowConfirm = false;
  this.constructor.prototype.constructor.call(this, owner);
 },
 GetControl: function() { return this.owner.GetOwnerControl(); },
 GetName: function() { return this.GetControl().name; },
 GetControlMainElement: function() { return this.GetControl().GetMainElement(); },
 CanShowConfirm: function(requestOwnerID) {
  if(this.lockShowConfirm)
   return false;
  this.lockShowConfirm = true;
  ASPx.Timer.ClearTimer(this.lockShowConfirmTimerID);
  this.lockShowConfirmTimerID = window.setTimeout(function(){ this.lockShowConfirm = false; }.aspxBind(this), this.ShowConfirmWindowTimeout);
  return !this.owner.RaiseBatchEditConfirmShowing(requestOwnerID);
 },
 HasChanges: function() {
  return this.owner.HasChanges() && this.GetControlMainElement() && !this.owner.IsUpdating();
 },
 GetConfirmUpdateText: function() {
  return this.owner.GetConfirmUpdateText();
 },
 NeedConfirmOnCallback: function (dxCallbackOwner) {
  if (this.owner.IsCallbacksEnabled())
   return false;
  return ASPx.GetIsParent(dxCallbackOwner.GetMainElement(), this.GetControlMainElement()) && !this.IsControlFuncCallback(dxCallbackOwner);
 },
 ResetClientChanges: function() {
  this.owner.CancelEdit();
  this.GetControl().UpdateStateHiddenField();
 },
 IsControlFuncCallback: function(dxCallbackOwner) { }
});
var BatchEditMouseDownWatcher = ASPx.CreateClass(null, {
 constructor: function() {
  this.helpers = { };
 },
 Add: function(helper) {
  this.helpers[helper.ownerControl.name] = helper;
 },
 GetActiveHelper: function() {
  for(var key in this.helpers) { 
   if(!this.helpers.hasOwnProperty(key)) continue;
   var helper = this.helpers[key];
   if(helper.IsEditing() && !helper.IsSingleEditMode()) 
    return helper;
  }
 },
 GetParentDataItem: function(focusHelper, src) {
  return focusHelper.batchEditHelper.GetRecordElementByChild(src);
 },
 OnMouseDown: function(e) {
  var src = ASPx.Evt.GetEventSource(e);
  var activeHelper = this.GetActiveHelper();
  if(activeHelper && !this.GetParentDataItem(activeHelper, src))
   activeHelper.ForceEndEditOnActiveElementBlur();
 }
});
BatchEditMouseDownWatcher.Instance = null;
BatchEditMouseDownWatcher.getInstance = function() {
 if (!BatchEditMouseDownWatcher.Instance) {
  BatchEditMouseDownWatcher.Instance = new BatchEditMouseDownWatcher();
  ASPx.Evt.AttachEventToDocument("mousedown", function(e) { BatchEditMouseDownWatcher.Instance.OnMouseDown(e); });
 }
 return BatchEditMouseDownWatcher.Instance;
};
var BatchEditSummaryItemCssClasses = {};
 BatchEditSummaryItemCssClasses.Prefix = "dxg-";
 BatchEditSummaryItemCssClasses.Disabled = BatchEditSummaryItemCssClasses.Prefix + "disabled";
 BatchEditSummaryItemCssClasses.Modified = BatchEditSummaryItemCssClasses.Prefix + "modified";
 BatchEditSummaryItemCssClasses.Unknown = BatchEditSummaryItemCssClasses.Prefix + "unknown";
var BatchEditSummaryHelper = ASPx.CreateClass(null, {
 constructor: function(batchEditHelper) {
  this.batchEditHelper = batchEditHelper;
  this.owner = batchEditHelper.owner;
  this.summaryValuesCache = {};
  this.lockResetSummaryValuesCache = false;
  this.filteredOutModifiedKeys = [];
  this.serializedEnumColumnTypeInfo = {};
 },
 GetOwnerID: function() { return this.owner.GetControlName(); },
 GetSummaryState: function() { return this.owner.GetSummaryState(); },
 GetMainElement: function() { return this.owner.GetMainElement(); },
 IsPagerCallback: function() { return this.owner.IsPagerCallback(); },
 GetColumnByFieldName: function(fieldName) { return this.owner.GetColumnByFieldName(fieldName); },
 UpdateCommandButtonsEnabled: function() { this.batchEditHelper.UpdateCommandButtonsEnabled(); },
 IsDeletedRecord: function(rowKey) { return this.batchEditHelper.IsDeletedRecord(rowKey); },
 GetCellValue: function(rowKey, columnIndex) { return this.batchEditHelper.GetCellValue(rowKey, columnIndex); },
 GetServerValue: function(rowKey, columnIndex) { return this.batchEditHelper.GetServerValue(rowKey, columnIndex); },
 GetCellServerHtml: function(rowKey, columnIndex) { return this.batchEditHelper.GetCellServerHtml(rowKey,columnIndex); },
 GetUpdatedValues: function() { return this.batchEditHelper.GetUpdatedValues(); },
 GetRecordModifiedColumns: function(rowKey) { return this.batchEditHelper.GetRecordModifiedColumns(rowKey); },
 GetVisibleColumnIndices: function() { return this.batchEditHelper.GetVisibleColumnIndices(); },
 GetVisibleNonEditableDataColumnIndices: function() { return this.batchEditHelper.GetVisibleNonEditableDataColumnIndices(); },
 GetCurrentPageChangedRecordKeys: function() { return this.batchEditHelper.GetCurrentPageChangedRecordKeys(); },
 IsCurrentPageRecord: function(rowKey) { return this.batchEditHelper.IsCurrentPageRecord(rowKey); },
 IsEmptyRecordVisible: function() { return this.batchEditHelper.RequireShowEmptyRecord(); },
 NeedCacheServerValue: function() { return this.batchEditHelper.NeedCacheServerValue(); },
 CacheServerValue: function(key, columnIndex, value, text) { return this.batchEditHelper.CacheServerValue(key, columnIndex, value, text); },
 GetServerRecordKeys: function(doNotIncludeDeleted) { return this.batchEditHelper.GetServerRecordKeys(doNotIncludeDeleted); },
 HasChanges: function() { return this.batchEditHelper.HasChanges(); },
 IsEnabledHighlighting: function() { return this.batchEditHelper.GetHighlightSummaryItems(); },
 GetInsertedRecordKeys: function() { return this.batchEditHelper.GetInsertedRecordKeys(); },
 GetDeletedRecordKeys: function() { return this.batchEditHelper.GetDeletedRecordKeys(); },
 GetUpdatedRecordKeys: function() { return ASPx.GetObjectKeys(this.GetUpdatedValues()); },
 RaiseBatchEditSummaryDisplayText: function(summaryInfo, text, groupRowVisibleIndex) { return this.batchEditHelper.RaiseBatchEditSummaryDisplayText(summaryInfo, text, groupRowVisibleIndex); },
 IsEnabled: function() { return (this.TotalSummaries && this.TotalSummaries.length > 0) || (this.GroupSummaries && this.GroupSummaries.length > 0); },
 EnsureNonEditableDataColumnsValuesCached: function() {
  var columnIndices = this.GetVisibleNonEditableDataColumnIndices();
  var currentPageChangedKeys = this.GetCurrentPageChangedRecordKeys();
  for(var i = 0; i < currentPageChangedKeys.length; i++) {
   var recordKey = currentPageChangedKeys[i];
   for(var j = 0; j < columnIndices.length; j++) {
    var columnIndex = columnIndices[j];
    this.CacheServerValue(recordKey, columnIndex, this.GetServerValue(recordKey, columnIndex), this.GetCellServerHtml(recordKey, columnIndex));
   }
  }
 },
 CreateTotalSummaryItem: function(summaryInfo) {
  return new ASPxClientTotalSummaryItem(this, summaryInfo);
 },
 CreateGroupSummaryItem: function(summaryInfo) {
  return new ASPxClientGroupSummaryItem(this, summaryInfo);
 },
 Init: function() {
  this.Invalidate();
  this.InitSummaries();
  this.RecalculateChanges();
  this.RefreshSummariesCells();
 },
 OnBeforeCallback: function() {
  if(this.NeedCacheServerValue() && this.GroupSummaries.length > 0)
   this.EnsureNonEditableDataColumnsValuesCached();
  this.lockResetSummaryValuesCache = true;
  this.EnsureSummaryValuesCached();
 },
 OnAfterCallback: function() {
  if(!this.IsPagerCallback())
   this.ResetSummaryValuesCache();
  this.Init();
  this.lockResetSummaryValuesCache = false;
 },
 OnSummariesDataCallback: function(result) {
  this.UpdateSummaries(result);
 },
 Invalidate: function() {
  this.TotalSummaries = [];
  this.GroupSummaries = [];
  this.GroupRowsValues = {};
  ASPx.CacheHelper.DropCache(this);
 },
 InitSummaries: function() {
  var summaryState = this.GetSummaryState();
  if(!summaryState)
   return;
  this.InitEnumInfo(summaryState["serializedEnumColumnTypeInfo"]);
  this.InitTotalSummaries(summaryState["totalSummaryState"]);
  this.InitGroupSummaries(summaryState["groupSummaryState"]);
  this.filteredOutModifiedKeys = summaryState["filteredOutModifiedKeys"] || [];
 },
 InitTotalSummaries: function(summaryState) {
  if(!summaryState)
   return;
  this.TotalDataRowCount = summaryState["dataRowCount"];
  var info = summaryState["info"];
  for(var i = 0; i < info.length; i++) {
   var totalSummaryItem = this.CreateTotalSummaryItem(info[i]);
   this.TotalSummaries.push(totalSummaryItem);
  }
 },
 InitGroupSummaries: function(summaryState) {
  if(!summaryState)
   return;
  this.GroupRowsValues = summaryState["rowValues"];
  var info = summaryState["info"];
  for(var i = 0; i < info.length; i++) {
   var groupSummaryItem = this.CreateGroupSummaryItem(info[i]);
   this.GroupSummaries.push(groupSummaryItem);
  }
 },
 InitEnumInfo: function(enumInfo) {
  if(enumInfo)
   this.serializedEnumColumnTypeInfo = enumInfo;
 },
 UpdateSummaries: function(summariesInfo) {
  if(summariesInfo["total"])
   this.UpdateTotalSummaries(summariesInfo["total"]);
  if(summariesInfo["group"])
   this.UpdateGroupSummaries(summariesInfo["group"]);
  this.UpdateCommandButtonsEnabled();
 },
 UpdateTotalSummaries: function(totalSummariesInfo) {
  for(var summaryItemIndex in totalSummariesInfo) {
   if(!totalSummariesInfo.hasOwnProperty(summaryItemIndex)) continue;
   var totalSummaryUpdateValue = totalSummariesInfo[summaryItemIndex];
   var summary = this.TotalSummaries[summaryItemIndex];
   summary.UpdateSummary(totalSummaryUpdateValue);
   summary.RefreshCells();
  }
 },
 UpdateGroupSummaries: function(groupSummariesInfo) {
  for(var groupRowIndex in groupSummariesInfo) {
   if(!groupSummariesInfo.hasOwnProperty(groupRowIndex)) continue;
   var groupRowSummariesInfo = groupSummariesInfo[groupRowIndex];
   var summaryKeys = ASPx.GetObjectKeys(groupRowSummariesInfo);
   if(summaryKeys.length === 0)
    this.UpdateCompleteVisibleGroup(groupRowIndex);
   for(var i = 0; i < summaryKeys.length; i++) {
    var summaryItemIndex = summaryKeys[i];
    var groupSummaryUpdateValue = groupRowSummariesInfo[summaryItemIndex];
    var summary = this.GroupSummaries[summaryItemIndex];
    summary.UpdateSummary(groupRowIndex, groupSummaryUpdateValue);
    summary.RefreshCellValue(groupRowIndex);
   }
  }
 },
 UpdateCompleteVisibleGroup: function(groupRowIndex) {
  this.ForEachGroupSummary(function(summary) {
   summary.UpdateCompleteVisibleGroup(groupRowIndex);
  });
 },
 IsRequiredCallback: function() {
  var result = false;
  this.ForEachSummary(function(summary) {
   if(summary.IsRequiredCallback())
    result = true;
  });
  return result;
 },
 ForEachSummary: function(action) {
  this.ForEachTotalSummary(action);
  this.ForEachGroupSummary(action);
 },
 ForEachTotalSummary: function(action) {
  if(!this.TotalSummaries)
   return;
  for(var i = 0; i < this.TotalSummaries.length; i++)
   action.call(this, this.TotalSummaries[i], this.TotalSummaries[i].GetColumnIndex());
 },
 ForEachGroupSummary: function(action) {
  if(!this.GroupSummaries)
   return;
  for(var i = 0; i < this.GroupSummaries.length; i++)
   action.call(this, this.GroupSummaries[i], this.GroupSummaries[i].GetColumnIndex());
 },
 RefreshSummariesCells: function() {
  this.ForEachSummary(function(summary) { summary.RefreshCells(); });
 },
 GetSummariesPlaceholders: function() {
  return ASPx.CacheHelper.GetCachedElements(this, "placeholders",
   function() {
    var mainElement = this.GetMainElement();
    return ASPx.NodeListToArray(mainElement.querySelectorAll("[data-besph]"));
   });
 },
 ToggleHighlightingClasses: function(element, isModified, isDisabled, isUnknown) {
  ASPx.ToggleClassNameToElement(element, BatchEditSummaryItemCssClasses.Disabled, isDisabled && this.IsEnabledHighlighting());
  ASPx.ToggleClassNameToElement(element, BatchEditSummaryItemCssClasses.Unknown, isUnknown && this.IsEnabledHighlighting());
  ASPx.ToggleClassNameToElement(element, BatchEditSummaryItemCssClasses.Modified, isModified && this.IsEnabledHighlighting());
 },
 IsExcludedKey: function(rowKey) {
  return ASPx.Data.ArrayContains(this.filteredOutModifiedKeys, rowKey);
 },
 GetTotalSummaryValue: function(summaryItemIndex) {
  return summaryItemIndex < 0 ? null : this.TotalSummaries[summaryItemIndex].GetSummaryValue();
 },
 GetGroupSummaryValue: function(summaryItemIndex, groupRowVisibleIndex) {
  return summaryItemIndex < 0 ? null : this.GroupSummaries[summaryItemIndex].GetSummaryValue(groupRowVisibleIndex);
 },
 GetTotalSummaryByFieldName: function(summaryFieldName) {
  return this.GetSummaryByFieldName(this.TotalSummaries, summaryFieldName);
 },
 GetGroupSummaryByFieldName: function(summaryFieldName) {
  return this.GetSummaryByFieldName(this.GroupSummaries, summaryFieldName);
 },
 GetSummaryByFieldName: function(summaries, summaryFieldName) {
  var filteredSummaries = summaries.filter(function(summary) { return summary.FieldName == summaryFieldName; });
  return filteredSummaries.length > 0 ? filteredSummaries[0].Index : -1;
 },
 PrepareSummaryEventArgInfo: function(summary, calcInfo, value, summaryElement) {
  var result = {};
  result.isGroupSummary = summary.IsGroupSummary();
  result.summaryIndex = summary.Index;
  result.summaryType = summary.Type;
  result.summaryFieldName = summary.FieldName;
  result.serverValue = calcInfo.ServerValue;
  result.value = value;
  result.summaryElement = summaryElement;
  return result;
 },
 RecalculateChanges: function() {
  this.ProcessUpdatedValues();
  this.ProcessInsertedValues();
  this.ProcessDeletedValues();
 },
 ProcessUpdatedValues: function() {
  var updatedKeys = this.GetUpdatedRecordKeys();
  var columnIndices = this.GetVisibleColumnIndices();
  ASPx.Data.ForEach(updatedKeys, function(rowKey) {
   this.ModifyRecordValues(rowKey, columnIndices, false);
  }.bind(this));
 },
 ProcessInsertedValues: function() {
  var insertedKeys = this.GetInsertedRecordKeys();
  ASPx.Data.ForEach(insertedKeys, function(rowKey) {
   this.RecoverRecord(rowKey, false);
  }.bind(this));
 },
 ProcessDeletedValues: function() {
  var deletedKeys = this.GetDeletedRecordKeys();
  ASPx.Data.ForEach(deletedKeys, function(rowKey) {
   this.RemoveRecord(rowKey, false);
  }.bind(this));
 },
 InsertRecord: function(rowKey) {
  if(!this.IsEnabled())
   return;
  this.ForEachTotalSummary(function(summary) {
   summary.AddRow(rowKey);
   summary.RefreshCells();
  });
 },
 RemoveRecord: function(rowKey, refreshCell) {
  if(!this.IsEnabled())
   return;
  this.ProcessSummaryChanges(rowKey, this.GetVisibleColumnIndices(), function(summary, value, prevValue) {
   summary.EditValue(rowKey, null, value);
   summary.DeleteRow(rowKey, value);
   if(refreshCell)
    summary.RefreshCells();
  });
 },
 RecoverRecord: function(rowKey, refreshCell) {
  if(!this.IsEnabled())
   return;
  this.ProcessSummaryChanges(rowKey, this.GetVisibleColumnIndices(), function(summary, value, prevValue) {
   summary.AddRow(rowKey);
   summary.EditValue(rowKey, value, null);
   if(refreshCell)
    summary.RefreshCells();
  });
 },
 ResetRecordValue: function(rowKey, columnIndex, refreshCell) {
  if(!this.IsEnabled())
   return;
  this.ProcessSummaryChanges(rowKey, [columnIndex], function(summary, value, prevValue) {
   summary.EditValue(rowKey, prevValue, value);
   if(refreshCell)
    summary.RefreshCells();
  });
 },
 ModifyRecordValues: function(rowKey, columnIndices, refreshCell) {
  if(!this.IsEnabled())
   return;
  this.ProcessSummaryChanges(rowKey, columnIndices, function(summary, value, prevValue) {
   summary.EditValue(rowKey, value, prevValue);
   if(refreshCell)
    summary.RefreshCells();
  });
 },
 ProcessSummaryChanges: function(rowKey, columnIndices, action) {
  this.ForEachSummary(function(summary, columnIndex) {
   if(summary.CanRecalculate(columnIndices, columnIndex))
    action(summary, this.GetCellValue(rowKey, columnIndex), this.GetServerValue(rowKey, columnIndex));
  });
 },
 OnSummaryRecalculation: function() {
  if(!this.lockResetSummaryValuesCache)
   this.ResetSummaryValuesCache();
 },
 EnsureSummaryValuesCached: function() {
  this.ForEachSummary(function(summary) {
   if(summary.IsRequireCacheSummaryValue()) { 
    var info = summary.GetSummaryValuesInfo();
    for(var i = 0; i < info.length; i++) {
     var entry = info[i];
     if(entry.value !== null)
      this.summaryValuesCache[entry.key] = entry.value;
    }
   }
  });
 },
 HasCachedSummaryValue: function(cacheKey) {
  return this.summaryValuesCache.hasOwnProperty(cacheKey);
 },
 GetCachedSummaryValue: function(cacheKey) {
  return this.HasCachedSummaryValue(cacheKey) ? this.summaryValuesCache[cacheKey] : null;
 },
 ResetSummaryValuesCache: function() {
  this.summaryValuesCache = { };
 }
});
var ASPxClientSummaryItemBase = ASPx.CreateClass(null, {
 constructor: function(summaryHelper, info) {
  this.summaryHelper = summaryHelper;
  this.Index   = info["index"];
  this.Type    = info["type"];
  this.FieldName  = info["fieldName"];
  this.DisplayFormat = info["displayFormat"];
  this.ValueFormat = info["valueFormat"];
  this.SerializedEnumTypeInfo = null;
  this.InitializeSerializedEnumTypeInfo(summaryHelper, info);
 },
 GetOwnerID: function() {
  return this.summaryHelper.GetOwnerID();
 },
 GetColumnIndex: function() {
  var column = this.summaryHelper.GetColumnByFieldName(this.FieldName);
  return column ? column.index : -1;
 },
 HasChanges: function() { return this.summaryHelper.HasChanges(); },
 ToggleHighlightingClasses: function(element, isModified, isDisabled, isUnknown) { this.summaryHelper.ToggleHighlightingClasses(element, isModified, isDisabled, isUnknown); },
 GetServerValue: function(rowKey) { return this.summaryHelper.GetServerValue(rowKey, this.GetColumnIndex()); },
 IsExcludedKey: function(rowKey) { return this.summaryHelper.IsExcludedKey(rowKey); },
 GetAllPlaceholders: function() { return this.summaryHelper.GetSummariesPlaceholders(); },
 GetPlaceholderArgs: function(placeholder) { return eval(ASPx.Attr.GetAttribute(placeholder, "data-besph")); },
 InitializeSerializedEnumTypeInfo: function(summaryHelper, info) {
  var enumTypeName = info["enumTypeName"];
  if(!enumTypeName)
   return;
  this.SerializedEnumTypeInfo = summaryHelper.serializedEnumColumnTypeInfo[enumTypeName];
 },
 CreateCalculationInfo: function(value, count, hasInvisibleDataRows, requireRecalculation) {
  var parsedValue = this.ParseToNumber(value);
  var displayText = value;
  if(this.SerializedEnumTypeInfo)
   displayText = this.FindEnumItemDisplayNameByName(value);
  var formattedValue = ASPx.Formatter.Format(this.ValueFormat, displayText);
  return {
   Value: parsedValue,
   ServerValue: parsedValue,
   FormattedServerValue: formattedValue,
   Count: count,
   HasInvisibleDataRows: hasInvisibleDataRows,
   RequireRecalculation: requireRecalculation
  };
 },
 ApplyHighlightingState: function(placeholder, calcInfo, groupRowVisibleIndex) {
  var isDisabled = !calcInfo.RequireRecalculation && this.HasChanges();
  var isCached = this.HasCachedSummaryValue(calcInfo, groupRowVisibleIndex);
  var isUnknown = calcInfo.RequireRecalculation && this.IsUnknownValue(calcInfo) && !isCached;
  var isModified = calcInfo.RequireRecalculation && !isUnknown && this.IsModified(calcInfo, groupRowVisibleIndex);
  this.ToggleHighlightingClasses(placeholder, isModified, isDisabled, isUnknown);
 },
 IsModified: function(calcInfo, groupRowVisibleIndex) {
  var value = calcInfo.Value;
  if(this.SerializedEnumTypeInfo)
   value = this.FindEnumItemDisplayNameByValue(value);
  if(calcInfo.IsRequiredCallback)
   value = this.GetCachedSummaryValue(calcInfo, groupRowVisibleIndex);
  var currentFormattedValue = ASPx.Formatter.Format(this.ValueFormat, value); 
  return currentFormattedValue != calcInfo.FormattedServerValue;
 },
 ParseToNumber: function(value) {
  var result = value;
  if(ASPx.IsNumber(value))
   result = parseFloat(value);
  else if(this.SerializedEnumTypeInfo)
   result = this.FindEnumItemValue(value);
  return result;
 },
 FindEnumItemDisplayNameByName: function(name) {
  return this.FindEnumItemDisplayNameByKeyValuePair("name", name);
 },
 FindEnumItemDisplayNameByValue: function(enumItemValue) {
  return this.FindEnumItemDisplayNameByKeyValuePair("value", enumItemValue);
 },
 FindEnumItemDisplayNameByKeyValuePair: function(key, value) {
  var result = null;
  var enumItemInfo = this.FindEnumItemInfoByKeyValuePair(key, value);
  if(enumItemInfo)
   result = enumItemInfo["annotatedName"] || enumItemInfo["name"];
  return result;
 },
 FindEnumItemValue: function(name) {
  var result = null;
  var enumItemInfo = this.FindEnumItemInfoByKeyValuePair("name", name);
  if(enumItemInfo)
   result = enumItemInfo["value"];
  return result;
 },
 FindEnumItemInfoByKeyValuePair: function(key, value) {
  if(!ASPx.IsExists(value))
   return null;
  var result = null;
  for(var i = 0; i < this.SerializedEnumTypeInfo.length; i++) {
   var enumItemInfo = this.SerializedEnumTypeInfo[i];
   if(enumItemInfo[key] === value) {
    result = enumItemInfo;
    break;
   }
  }
  return result;
 },
 RefreshCells: function() { },
 GetSummaryDisplayText: function(calcInfo, placeholder, groupRowVisibleIndex) {
  var summaryValue = this.getSummaryValueInternal(calcInfo, groupRowVisibleIndex);
  var formattedValue = this.GetFormattedSummaryValue(summaryValue, calcInfo, groupRowVisibleIndex);
  var text = ASPx.Formatter.Format(this.DisplayFormat, formattedValue, this.FieldName);
  var summaryArgsInfo = this.summaryHelper.PrepareSummaryEventArgInfo(this, calcInfo, summaryValue, placeholder);
  return this.summaryHelper.RaiseBatchEditSummaryDisplayText(summaryArgsInfo, text, groupRowVisibleIndex);
 },
 GetFormattedSummaryValue: function(value, calcInfo, groupRowVisibleIndex) {
  if(this.IsUnknownValue(calcInfo) && !this.HasCachedSummaryValue(calcInfo, groupRowVisibleIndex))
   return "?";
  return ASPx.Formatter.Format(this.ValueFormat, value);
 },
 IsGroupSummary: function() { return false; },
 IsRequiredCallback: function() { return false; },
 AddRow: function() { },
 DeleteRow: function(rowKey, deletedValue) { },
 EditValue: function(rowKey, newValue, oldValue) { },
 IsUnknownValue: function(calcInfo) {
  switch(this.Type) {
   case ASPxClientSummaryItemType.Average:
    return calcInfo.Count === 0;
   case ASPxClientSummaryItemType.Max:
   case ASPxClientSummaryItemType.Min:
    return calcInfo.Count === 0 || calcInfo.IsRequiredCallback;
   default:
    return false;
  }
 },
 CanRecalculate: function(columnIndices, columnIndex) {
  return this.Type === ASPxClientSummaryItemType.Count || ASPx.Data.ArrayContains(columnIndices, columnIndex);
 },
 EditValueCore: function(rowKey, newValue, prevValue, calcInfo, groupRowInfo) {
  var newValueNum = this.ParseToNumber(newValue);
  var prevValueNum = this.ParseToNumber(prevValue);
  switch(this.Type) {
   case ASPxClientSummaryItemType.Sum:
    calcInfo.Value += newValueNum - prevValueNum;
    break;
   case ASPxClientSummaryItemType.Average:
    calcInfo.Value *= calcInfo.Count;
    if(calcInfo.Count > 0) {
     calcInfo.Value += newValueNum - prevValueNum;
     calcInfo.Value /= calcInfo.Count;
    }
    break;
   case ASPxClientSummaryItemType.Max:
   case ASPxClientSummaryItemType.Min:
    this.RecalculateEdgeValue(rowKey, newValue, calcInfo, groupRowInfo);
    if(calcInfo.HasInvisibleDataRows && calcInfo.InvisibleDataRowsValue == null)
     calcInfo.IsRequiredCallback = this.isRequiredSummaryCallback(rowKey, newValue, calcInfo, groupRowInfo);
    break;
  }
  this.OnSummaryRecalculation();
 },
 AddRowCore: function(calcInfo) {
  switch(this.Type) {
   case ASPxClientSummaryItemType.Count:
    calcInfo.Value++;
    break;
   case ASPxClientSummaryItemType.Average:
    calcInfo.Value *= calcInfo.Count;
    calcInfo.Count++;
    calcInfo.Value /= calcInfo.Count;
    break;
   case ASPxClientSummaryItemType.Max:
   case ASPxClientSummaryItemType.Min:
    calcInfo.Count++;
    break;
  }
  this.OnSummaryRecalculation();
 },
 DeleteRowCore: function(rowKey, deletedValue, calcInfo, groupRowInfo) {
  switch(this.Type) {
   case ASPxClientSummaryItemType.Count:
    calcInfo.Value--;
    break;
   case ASPxClientSummaryItemType.Average:
    calcInfo.Value *= calcInfo.Count;
    calcInfo.Count--;
    if(calcInfo.Count > 0)
     calcInfo.Value /= calcInfo.Count;
    break;
   case ASPxClientSummaryItemType.Max:
   case ASPxClientSummaryItemType.Min:
    calcInfo.Count--;
    if(deletedValue == null) break;
    this.RecalculateEdgeValue(rowKey, null, calcInfo, groupRowInfo);
    if(calcInfo.HasInvisibleDataRows && calcInfo.InvisibleDataRowsValue == null)
     calcInfo.IsRequiredCallback = this.isRequiredSummaryCallback(rowKey, null, calcInfo, groupRowInfo);
    break;
  }
  this.OnSummaryRecalculation();
 },
 RecalculateEdgeValue: function(rowKey, newValue, calcInfo, groupRowInfo) {
  var rowsValues = this.getVisibleAndModifiedRowsValues(rowKey, groupRowInfo);
  var parsedRowsValues = rowsValues.map(function(value) { return this.ParseToNumber(value); }.bind(this));
  var action = this.getSummaryAction();
  calcInfo.Value = action.apply(null, parsedRowsValues);
  var newValueNum = this.ParseToNumber(newValue);
  if(newValue != null)
   calcInfo.Value = action(calcInfo.Value, newValueNum);
  if(calcInfo.HasInvisibleDataRows) {
   if(calcInfo.InvisibleDataRowsValue != null) {
    calcInfo.Value = action(calcInfo.Value, calcInfo.InvisibleDataRowsValue);
    calcInfo.IsRequiredCallback = false;
    if(newValue != null && !this.summaryHelper.IsCurrentPageRecord(rowKey) && newValue == this.GetServerValue(rowKey))
     calcInfo.InvisibleDataRowsValue = action(calcInfo.InvisibleDataRowsValue, newValueNum);
   }
   else
    calcInfo.Value = action(calcInfo.Value, calcInfo.ServerValue);
  }
 },
 getSummaryValueInternal: function(calcInfo, groupRowVisibleIndex) {
  var result = this.getDisplayTextByValue(calcInfo.ServerValue);
  if(calcInfo.RequireRecalculation) {
   if(this.IsUnknownValue(calcInfo))
    result = this.GetCachedSummaryValue(calcInfo, groupRowVisibleIndex);
   else
    result = this.getDisplayTextByValue(calcInfo.Value);
  }
  return result;
 },
 getDisplayTextByValue: function(value) {
  var result = value;
  if(this.SerializedEnumTypeInfo)
   result = this.FindEnumItemDisplayNameByValue(value);
  return result;
 },
 getSummaryAction: function() {
  return this.Type == ASPxClientSummaryItemType.Min ? Math.min : Math.max;
 },
 isRequiredSummaryCallback: function(rowKey, newValue, calcInfo, groupRowInfo) {
  var action = this.getSummaryAction();
  var rowsValues = this.getVisibleAndModifiedRowsValues(rowKey, groupRowInfo);
  var parsedRowsValues = rowsValues.map(this.ParseToNumber.bind(this));
  var parsedRowsValue = action.apply(null, parsedRowsValues);
  var parsedNewValue = this.ParseToNumber(newValue);
  if(newValue != null)
   parsedRowsValue = action(parsedRowsValue, parsedNewValue);
  var isOverridenValue = action(parsedRowsValue, calcInfo.ServerValue) == parsedRowsValue;
  var hasDuplicateValue = ASPx.Data.ArrayContains(parsedRowsValues, calcInfo.ServerValue);
  var modifiedServerValues = this.getModifiedServerValue(groupRowInfo);
  var parsedModifiedServerValues = modifiedServerValues.map(this.ParseToNumber.bind(this));
  var isServerValueModified = ASPx.Data.ArrayContains(parsedModifiedServerValues, calcInfo.ServerValue);
  return !isOverridenValue && !hasDuplicateValue && isServerValueModified;
 },
 getVisibleAndModifiedRowsValues: function(excludeRowKey, groupRowInfo) {
  var rowsKeys = this.getVisibleAndModifiedRowsKeys(groupRowInfo).filter(function(key) { return key != excludeRowKey; });
  return this.getRowsValues(rowsKeys);
 },
 getVisibleAndModifiedRowsKeys: function(groupRowInfo) {
  var visibleRowsKeys = this.getVisibleRowsKeys();
  var insertedKeys = this.getInsertedKeys();
  var updatedKeys = this.getUpdatedKeys().filter(function(key) { return !ASPx.Data.ArrayContains(visibleRowsKeys, key); });
  return visibleRowsKeys.concat(insertedKeys).concat(updatedKeys);
 },
 getVisibleRowsKeys: function() {
  return this.summaryHelper.GetServerRecordKeys(true);
 },
 getInsertedKeys: function() {
  return this.summaryHelper.GetInsertedRecordKeys(false).filter(function(key) { return !this.summaryHelper.IsDeletedRecord(key); }.bind(this));
 },
 getUpdatedKeys: function() {
  return this.summaryHelper.GetUpdatedRecordKeys().filter(function(key) { return !this.summaryHelper.IsDeletedRecord(key); }.bind(this));
 },
 getRowsValues: function(rowsKeys) {
  return rowsKeys.map(function(rowKey) { return this.summaryHelper.GetCellValue(rowKey, this.GetColumnIndex()); }.bind(this)).filter(function(val) { return val != null; });
 },
 getModifiedServerValue: function(groupRowInfo) {
  var modifiedKeys = this.getModifiedRowsKeys(groupRowInfo);
  return modifiedKeys.map(function(rowKey) { return this.GetServerValue(rowKey); }.bind(this));
 },
 getModifiedRowsKeys: function(groupRowInfo) {
  return this.getUpdatedKeys().concat(this.summaryHelper.GetDeletedRecordKeys());
 },
 OnSummaryRecalculation: function() { this.summaryHelper.OnSummaryRecalculation(); },
 IsRequireCacheSummaryValue: function() { return this.Type == ASPxClientSummaryItemType.Min || this.Type == ASPxClientSummaryItemType.Max; },
 HasCachedSummaryValue: function(calcInfo, groupRowVisibleIndex) { return this.summaryHelper.HasCachedSummaryValue(this.GetSummaryValueInfoKey(calcInfo, groupRowVisibleIndex)); },
 GetCachedSummaryValue: function(calcInfo, groupRowVisibleIndex) { return this.summaryHelper.GetCachedSummaryValue(this.GetSummaryValueInfoKey(calcInfo, groupRowVisibleIndex)); },
 CreateSummaryValueInfo: function(calcInfo, value, groupRowVisibleIndex) { return { key: this.GetSummaryValueInfoKey(calcInfo, groupRowVisibleIndex), value: value }; },
 GetSummaryValueInfoKey: function(calcInfo, groupRowVisibleIndex) {
  var sb = [];
  sb.push(this.IsGroupSummary() ? "g" : "t");
  sb.push(this.Index);
  sb.push(calcInfo.ServerValue);
  sb.push(groupRowVisibleIndex);
  return sb.join("_");
 },
 GetSummaryValuesInfo: function() { }
});
var ASPxClientTotalSummaryItem = ASPx.CreateClass(ASPxClientSummaryItemBase, {
 constructor: function(summaryHelper, info) {
  this.constructor.prototype.constructor.call(this, summaryHelper, info);
  this.CalculationInfo = this.CreateCalculationInfo(
   info["value"],
   summaryHelper.TotalDataRowCount,
   info["hasInvisibleRows"],
   !info["disabled"]
  );
 },
 IsEmptyRecordVisible: function() {
  return this.summaryHelper.IsEmptyRecordVisible();
 },
 GetPlaceholders: function() {
  var placeholders = this.GetAllPlaceholders();
  return placeholders.filter(function(placeholder) {
   var args = this.GetPlaceholderArgs(placeholder);
   return ASPx.Ident.IsArray(args) && args.length === 2 && args[0] === this.GetOwnerID() && args[1] === this.Index;
  }.bind(this));
 },
 RefreshCells: function() {
  var placeholders = this.GetPlaceholders();
  for(var i = 0; i < placeholders.length; i++)
   this.RefreshCellValue(placeholders[i]);
 },
 RefreshCellValue: function(placeholder) {
  if(placeholder) {
   this.ApplyHighlightingState(placeholder, this.CalculationInfo);
   ASPx.SetInnerHtml(placeholder, this.GetSummaryDisplayText(this.CalculationInfo, placeholder, null));
  }
 },
 GetSummaryValue: function() { return this.getSummaryValueInternal(this.CalculationInfo); },
 UpdateSummary: function(invisibleRowsValue) {
  this.CalculationInfo.InvisibleDataRowsValue = this.ParseToNumber(invisibleRowsValue);
  this.RecalculateEdgeValue(null, null, this.CalculationInfo);
 },
 GetFormattedSummaryValue: function(value, calcInfo, groupRowVisibleIndex) {
  if(this.IsUnknownValue(calcInfo) && this.IsEmptyRecordVisible())
   return "";
  return ASPxClientSummaryItemBase.prototype.GetFormattedSummaryValue.call(this, value, calcInfo, groupRowVisibleIndex);
 },
 GetSummaryValuesInfo: function() {
  return [this.CreateSummaryValueInfo(this.CalculationInfo, this.GetSummaryValue())];
 },
 IsRequiredCallback: function() {
  return this.CalculationInfo.IsRequiredCallback && !this.HasCachedSummaryValue(this.CalculationInfo);
 },
 EditValue: function(rowKey, newValue, prevValue) {
  if(this.CalculationInfo.RequireRecalculation && !this.IsExcludedKey(rowKey))
   this.EditValueCore(rowKey, newValue, prevValue, this.CalculationInfo);
 },
 AddRow: function(rowKey) {
  if(this.CalculationInfo.RequireRecalculation && !this.IsExcludedKey(rowKey))
   this.AddRowCore(this.CalculationInfo);
 },
 DeleteRow: function(rowKey, deletedValue) {
  if(this.CalculationInfo.RequireRecalculation && !this.IsExcludedKey(rowKey))
   this.DeleteRowCore(rowKey, deletedValue, this.CalculationInfo);
 }
});
var ASPxClientGroupSummaryItem = ASPx.CreateClass(ASPxClientSummaryItemBase, {
 constructor: function(summaryHelper, info) {
  this.constructor.prototype.constructor.call(this, summaryHelper, info);
  this.RowsInfo = this.LoadRowsInfo(info["rowsInfo"]);
 },
 GetPlaceholder: function(rowIndex) {
  var placeholders = this.GetAllPlaceholders();
  for(var i = 0; i < placeholders.length; i++) {
   var placeholder = placeholders[i];
   var args = this.GetPlaceholderArgs(placeholder);
   if(ASPx.Ident.IsArray(args) && args.length === 3 && args[0] === this.GetOwnerID() && args[1] === this.Index && args[2] === rowIndex)
    return placeholder;
  }
  return null;
 },
 IsGroupSummary: function() { return true; },
 DisableRowInvisibleDataRows: function(groupRowIndex) {
  var calcInfo = this.GetRowInfoByRowIndex(groupRowIndex).CalculationInfo;
  calcInfo.HasInvisibleDataRows = false;
  calcInfo.IsRequiredCallback = false;
 },
 LoadRowsInfo: function(rowsInfo) {
  var result = [];
  for(var i = 0; i < rowsInfo.length; i++) {
   var rowInfo = rowsInfo[i];
   result.push({
    RowIndex: rowInfo["visibleIndex"],
    CalculationInfo: this.CreateCalculationInfo(
     rowInfo["value"],
     rowInfo["childCount"],
     rowInfo["hasInvisibleRows"],
     !rowInfo["disabled"],
     rowInfo["enumTypeName"]
    )});
  }
  return result;
 },
 IsChildOfGroup: function(rowKey, groupRowInfo) {
  if(this.IsExcludedKey(rowKey))
   return false;
  var groupRowValues = this.summaryHelper.GroupRowsValues[groupRowInfo.RowIndex];
  for(var columnIndex in groupRowValues){
   if(!groupRowValues.hasOwnProperty(columnIndex)) continue;
   if(!this.AreGroupValuesEqual(this.summaryHelper.GetServerValue(rowKey, columnIndex), groupRowValues[columnIndex]))
    return false;
  }
  return true;
 },
 AreGroupValuesEqual: function(val1, val2) {
  if(ASPx.Ident.IsDate(val1) && ASPx.Ident.IsDate(val2))
   return ASPx.DateUtils.AreDatesEqualExact(val1, val2);
  return val1 == val2;
 },
 RefreshCells: function() {
  for(var i = 0; i < this.RowsInfo.length; i++)
   this.RefreshCellValue(this.RowsInfo[i].RowIndex);
 },
 RefreshCellValue: function(groupRowIndex) {
  var rowInfo = this.GetRowInfoByRowIndex(groupRowIndex);
  var placeholder = this.GetPlaceholder(rowInfo.RowIndex);
  if(placeholder) {
   this.ApplyHighlightingState(placeholder, rowInfo.CalculationInfo, rowInfo.RowIndex);
   ASPx.SetInnerHtml(placeholder, this.GetSummaryDisplayText(rowInfo.CalculationInfo, placeholder, rowInfo.RowIndex));
  }
 },
 GetSummaryValue: function(groupRowVisibleIndex) {
  if(groupRowVisibleIndex >= this.RowsInfo.length)
   return null;
  return this.getSummaryValueInternal(this.RowsInfo[groupRowVisibleIndex].CalculationInfo, groupRowVisibleIndex);
 },
 GetRowInfoByRowIndex: function(groupRowIndex) {
  return this.RowsInfo.filter(function(i) { return i.RowIndex == groupRowIndex; })[0];
 },
 GetSummaryValuesInfo: function() {
  var result = [];
  for(var i = 0; i < this.RowsInfo.length; i++)
   result.push(this.CreateSummaryValueInfo(this.RowsInfo[i].CalculationInfo, this.GetSummaryValue(i), this.RowsInfo[i].RowIndex));
  return result;
 },
 IsRequiredCallback: function() {
  return this.RowsInfo.filter(function(i) {
   return i.CalculationInfo.IsRequiredCallback && !this.HasCachedSummaryValue(i.CalculationInfo, i.RowIndex);
  }.bind(this)).length > 0;
 },
 UpdateCompleteVisibleGroup: function(groupRowIndex) {
  if(this.Type == ASPxClientSummaryItemType.Max || this.Type == ASPxClientSummaryItemType.Min) {
   this.DisableRowInvisibleDataRows(groupRowIndex);
   this.UpdateSummary(groupRowIndex, null);
   this.RefreshCellValue(groupRowIndex);
  }
 },
 UpdateSummary: function(groupRowIndex, invisibleRowsValue) {
  var rowInfo = this.GetRowInfoByRowIndex(groupRowIndex);
  var calcInfo = rowInfo.CalculationInfo;
  calcInfo.InvisibleDataRowsValue = this.ParseToNumber(invisibleRowsValue);
  this.RecalculateEdgeValue(null, null, calcInfo, rowInfo);
 },
 EditValue: function(rowKey, newValue, prevValue) {
  for(var i = 0; i < this.RowsInfo.length; i++) {
   var groupRowInfo = this.RowsInfo[i];
   if(groupRowInfo.CalculationInfo.RequireRecalculation && this.IsChildOfGroup(rowKey, groupRowInfo))
    this.EditValueCore(rowKey, newValue, prevValue, groupRowInfo.CalculationInfo, groupRowInfo);
  }
 },
 AddRow: function(rowKey) {
  for(var i = 0; i < this.RowsInfo.length; i++) {
   var groupRowInfo = this.RowsInfo[i];
   if(groupRowInfo.CalculationInfo.RequireRecalculation && this.IsChildOfGroup(rowKey, groupRowInfo))
    this.AddRowCore(groupRowInfo.CalculationInfo);
  }
 },
 DeleteRow: function(rowKey, deletedValue) {
  for(var i = 0; i < this.RowsInfo.length; i++) {
   var groupRowInfo = this.RowsInfo[i];
   if(groupRowInfo.CalculationInfo.RequireRecalculation && this.IsChildOfGroup(rowKey, groupRowInfo))
    this.DeleteRowCore(rowKey, deletedValue, groupRowInfo.CalculationInfo, groupRowInfo);
  }
 },
 getVisibleAndModifiedRowsKeys: function(groupRowInfo) {
  var visibleRowsKeys = ASPxClientSummaryItemBase.prototype.getVisibleAndModifiedRowsKeys.call(this, groupRowInfo);
  return visibleRowsKeys.filter(function(key) { return this.IsChildOfGroup(key, groupRowInfo); }.bind(this));
 },
 getModifiedRowsKeys: function(groupRowInfo) {
  var modifiedRowsKeys = ASPxClientSummaryItemBase.prototype.getModifiedRowsKeys.call(this, groupRowInfo);
  return modifiedRowsKeys.filter(function(key) { return this.IsChildOfGroup(key, groupRowInfo); }.bind(this));
 }
});
ASPx.BatchEditFocusHelper = BatchEditFocusHelper;
ASPx.BatchEditHelperOwner = BatchEditHelperOwner;
ASPx.BatchEditHelper = BatchEditHelper;
ASPx.BatchEditUpdateWatcherHelper = BatchEditUpdateWatcherHelper;
ASPx.BatchEditSummaryHelper = BatchEditSummaryHelper;
})();

(function() {
var GridBatchEditFocusHelper = ASPx.CreateClass(ASPx.BatchEditFocusHelper, {
 constructor: function(batchEditHelper) { 
  this.constructor.prototype.constructor.call(this, batchEditHelper);
  this.grid = this.ownerControl;
 },
 GetMainTable: function() { return this.grid.GetMainTable(); },
 GetCellFocusHelper: function() { return this.grid.GetCellFocusHelper(); },
 AttachEventToEditor: function(columnIndex, eventName, action) { this.grid.AttachEventToEditor(columnIndex, eventName, action); },
 RaiseBatchEditTemplateCellFocused: function(columnIndex) { return this.grid.RaiseBatchEditTemplateCellFocused(columnIndex); },
 ConvertKeyToVisibleIndex: function(key) { return this.GetBatchEditHelperOwner().ConvertKeyToVisibleIndex(key); },
 ConvertVisibleIndexToKey: function(visibleIndex) { return this.GetBatchEditHelperOwner().ConvertVisibleIndexToKey(visibleIndex); },
 TryShowColumn: function(columnIndex, showFullRect) {
  var fixedColumnHelper = this.grid.GetFixedColumnsHelper && this.grid.GetFixedColumnsHelper(); 
  if(fixedColumnHelper)
   fixedColumnHelper.TryShowColumn(columnIndex, showFullRect);
 },
 IsCommandColumnItem: function(element) { return this.grid.IsCommandColumnItem(element); }
});
var GridViewBatchEditFocusHelper = ASPx.CreateClass(GridBatchEditFocusHelper, { 
 constructor: function(batchEditHelper) { 
  this.constructor.prototype.constructor.call(this, batchEditHelper);
 },
 IsChangesViewVisible: function() { return this.batchEditHelper.IsChangesViewVisible(); },
 GetNewFocusedCellInfo: function(recordKey, columnKey, isLeft) {
  if(!this.IsChangesViewVisible())
   return GridBatchEditFocusHelper.prototype.GetNewFocusedCellInfo.call(this, recordKey, columnKey, isLeft);
  var inc = isLeft ? -1 : 1;
  var helper = this.GetCellFocusHelper();
  if(helper) {
   var cellInfo = helper.CreateCellInfo(recordKey, this.ResolveColumnIndex(columnKey));
   var newCellInfo = helper.GetNavigationCellInfo(cellInfo, inc, false);
   if(newCellInfo) {
    var newCellColumnKey = this.ResolveColumnKey(newCellInfo.columnIndex);
    if(this.CanFocusEditCell(newCellInfo.recordKey, newCellColumnKey))
     return { recordKey: newCellInfo.recordKey, columnKey: newCellColumnKey };
    return this.GetNewFocusedCellInfo(newCellInfo.recordKey, newCellColumnKey, isLeft);
   }
  }
  return null;
 }
});
var CardViewBatchEditFocusHelper = ASPx.CreateClass(GridBatchEditFocusHelper, { 
 constructor: function(batchEditHelper) { 
  this.constructor.prototype.constructor.call(this, batchEditHelper);
 },
 GetColumnKeyByChild: function(element) {
  var owner = this.GetBatchEditHelperOwner();
  var layoutItemCell = owner.GetDataCellByChild(element);
  return owner.GetColumnKey(layoutItemCell);
 },
 ResolveColumnKey: function(columnIndex) { 
  if(!ASPx.IsExists(columnIndex)) 
   return null;
  if(typeof(columnIndex) === "string")
   return columnIndex;
  if(typeof(columnIndex) === "number")
   return this.grid.GetItemPathByColumnIndex(columnIndex);
  return null;
 },
 ResolveColumnIndex: function(columnKey) { 
  if(!ASPx.IsExists(columnKey)) 
   return -1;
  if(typeof(columnKey) === "number")
   return columnKey;
  if(typeof(columnKey) === "string")
   return this.FindColumnIndexByKey(columnKey);
  return -1;
 },
 FindColumnIndexByKey: function(columnKey) { return this.grid.GetColumnIndexByItemPath(columnKey); }
});
var VerticalGridBatchEditFocusHelper = ASPx.CreateClass(GridBatchEditFocusHelper, { 
 constructor: function(batchEditHelper) { 
  this.constructor.prototype.constructor.call(this, batchEditHelper);
 },
 LoadAllRecordActiveElements: function () {
  var grid = this.grid;
  var elements = [];
  var tables = [grid.GetMainTable(), grid.GetFixedTable()];
  ASPx.Data.ForEach(tables, function (table) {
   if (table)
    elements = elements.concat(ASPx.FindChildActionElements(table));
  });
  for (var i = 0; i < elements.length; i++) {
   var element = elements[i];
   var dataCell = grid.getRecordCellByChild(element);
   if (dataCell) {
    var visibleIndex = grid.GetRecordCellVisibleIndex(dataCell);
    var recordKey = this.ConvertVisibleIndexToKey(visibleIndex);
    var columnKey = this.GetBatchEditHelperOwner().GetColumnIndexByDataCell(dataCell);
    this.PushElementToActiveElementsHash(element, recordKey, columnKey);
    this.PrepareRecordActiveElement(element, recordKey, columnKey);
   }
  }
 },
 GetDataItemChildElements: function(dataItem) {
  var result = [];
  var cells = this.grid.GetRecordCells(dataItem.visibleIndex);
  for(var i = 0; i < cells.length; i++) {
   if(!cells[i]) continue;
   var elements = GridBatchEditFocusHelper.prototype.GetDataItemChildElements.call(this, cells[i]);
   result = result.concat(elements);
  }
  return result;
 },
 GetElementToFreezeHeight: function(recordKey, columnIndex) { return this.grid.GetHtmlRow(columnIndex); },  
 CanFocusEditColumn: function(columnKey) {
  var canFocus = GridBatchEditFocusHelper.prototype.CanFocusEditColumn.call(this, columnKey);
  if(columnKey) {
   var columnIndex = this.ResolveColumnIndex(columnKey);
   var column = this.grid.GetColumn(columnIndex);
   canFocus &= column.parentIndex == -1 || this.grid.GetColumnStateExpandedHierarchically(column.parentIndex);
  }
  return canFocus;
 },
 ResolveHtmlColumnIndex: function(columnIndex, recordKey) { return this.grid.ConvertKeyToVisibleIndex(recordKey); }
});
var GridBatchEditHelperOwner = ASPx.CreateClass(ASPx.BatchEditHelperOwner, {
 constructor: function(control) {
  this.constructor.prototype.constructor.call(this, control);
  this.grid = this.control;
 },
 GetRecordByVI: function(visibleIndex) {  },
 ChangeDeletedRecordVisibilityByVisibleIndex: function(visibleIndex, recover) {  },
 InsertRecordValidationErrorCore: function(record, itemError, errorText) {  },
 GetRecordCommandButtonsByVI: function(visibleIndex) {  },
 OnVisibleRowCountChanged: function() { },
 AllowDelete: function() { return this.grid.allowDelete; },
 AllowEdit: function() { return this.grid.allowEdit; },
 AllowInsert: function() { return this.grid.allowInsert; },
 GetBatchEditClientState: function() { return this.grid.batchEditClientState; },
 GetLoadedClientModifiedValues: function() { return  this.grid.stateObject.batchEditClientModifiedValues; },
 UpdateClientModifiedValues: function(values) { this.grid.stateObject.batchEditClientModifiedValues = values; },
 GetLoadedPageValues: function() { return this.grid.batchEditPageValues; },
 GetProgressBarControl: function(recordKey, columnIndex) { return this.grid.GetProgressBarControl(this.ConvertKeyToVisibleIndex(recordKey), columnIndex); },
 GetColumn: function(columnIndex) { return this.grid._getColumn(columnIndex); },
 GetColumnByFieldName: function(fieldName) { return this.grid.GetColumnByField(fieldName); },
 GetSummaryState: function() { return this.grid.batchEditSummaryState; },
 GetOrderedKeysFromOwnerControl: function() { return this.grid.keys; },
 GetDataCell: function(key, columnIndex) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  return this.GetDataCellByVI(visibleIndex, columnIndex);
 },
 GetDataCellByVI: function(visibleIndex) { return this.grid.GetDataCell(visibleIndex, columnIndex); },
 HasKeyField: function() { return this.grid.HasKeyField(); },
 IsRecordElement: function(element) {
  var visibleIndex = this.GetVisibleIndexFromID(element);
  return ASPx.IsExists(visibleIndex) && element.id === this.GetDataItemID(visibleIndex);
 },
 GetSelectedCells: function() {
  var helper = this.grid.GetCellSelectionHelper();
  if(helper)
   return helper.GetSelectedCells();
  return [ ];
 },
 GetChildElement: function(idSuffix) { return this.grid.GetChildElement(idSuffix); },
 GetMainElement: function() { return this.grid.GetMainElement(); },
 GetRecord: function(key) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  return this.GetRecordByVI(visibleIndex);
 }, 
 GetRecordKeyByElement: function(element) {  
  var visibleIndex = this.GetVisibleIndexFromID(element);
  return ASPx.IsExists(visibleIndex) ? this.ConvertVisibleIndexToKey(visibleIndex) : null;
 }, 
 GetBatchEditCommandButtons: function() { return this.grid.GetBatchEditCommandButtons(); },  
 PrepareCommandButtons: function() { this.grid.PrepareCommandButtons(); },
 UpdateCommandButtonsEnabled: function(state) {
  ASPx.BatchEditHelperOwner.prototype.UpdateCommandButtonsEnabled.call(this, state);
  this.grid.ChangeToolbarBatchEditItemsState(state);
  var buttons = this.GetBatchEditCommandButtons();
  this.UpdatePreviewButtonsVisibility(state, buttons.previewChangesButton, buttons.hidePreviewButton);
 },
 UpdatePreviewButtonsVisibility: function(state, previewChangesButton, hidePreviewButton) {
  if(previewChangesButton)
   this.UpdatePreviewChangesButtonVisibility(previewChangesButton, state.previewChangesButtonVisible, state.previewChangesButtonChangesCount, state.previewChangesButtonPreventAnimation);
  this.UpdateCommandButtonVisibility(hidePreviewButton, state.hidePreviewButtonVisible);
 },
 UpdatePreviewChangesButtonVisibility: function(button, visible, changesCount, preventAnimation) { },
 GetEditorsContainer: function() { return this.grid.GetBatchEditorsContainer(); },
 GetBatchEditorContainer: function(columnIndex) { return this.grid.GetBatchEditorContainer(columnIndex); },
 GetEditor: function(columnIndex) { return this.grid.GetEditor(columnIndex); }, 
 GetStyleHelper: function() { return this.grid.GetStyleHelper(); },
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(); },
 GetRecordError: function(key) { return this.GetRecordErrorByVI(this.ConvertKeyToVisibleIndex(key)); }, 
 GetRecordErrorByVI: function(visibleIndex) { return ASPx.GetElementById(this.GetRecordErrorID(visibleIndex)); }, 
 RemoveRecordError: function(key) { this.RemoveRecordErrorByVI(this.ConvertKeyToVisibleIndex(key)); },
 RemoveRecordErrorByVI: function(visibleIndex) { ASPx.RemoveElement(this.GetRecordErrorByVI(visibleIndex)); },
 OnBeforeDataItemDeleted: function(deletedItemKey, nextNotDeletedRecordKey) {
  var grid = this.grid;
  var visibleIndex = this.ConvertKeyToVisibleIndex(deletedItemKey);
  if(grid._getFocusedItemIndex() === visibleIndex)
   grid._setFocusedItemIndex(this.ConvertKeyToVisibleIndex(nextNotDeletedRecordKey));
 },
 OnDataItemDeleted: function(deletedRecordKey) {
  this.OnVisibleRowCountChanged();
  this.grid.InvalidateLayout();
 },
 OnResetChanges: function(isMultiple) {
  this.OnVisibleRowCountChanged(); 
 },
 OnNewRecordAdded: function(newRecordKey) {
  ASPx.BatchEditHelperOwner.prototype.OnNewRecordAdded.call(this, newRecordKey);
  this.OnVisibleRowCountChanged();
  this.grid.InvalidateLayout();   
 }, 
 OnDataRecordRecovered: function(key) { this.grid.InvalidateLayout(); },
 UpdateRecordCommandButtonsVisibility: function(recordKey, state) {
  ASPx.BatchEditHelperOwner.prototype.UpdateRecordCommandButtonsVisibility.call(this, recordKey, state);
  ASPx.SetElementDisplay(this.GetSelectCheckBox(recordKey), state.defaultButtonsVisible);
 },
 IsRecoverButton: function(button) { return this.grid.IsRecoverButton(button); },
 IsCancelButton: function(button) { return this.grid.IsCancelButton(button); }, 
 UpdateRecordStyle: function(recordKey) { this.grid.UpdateItemStyle(this.ConvertKeyToVisibleIndex(recordKey)); },
 ChangeEmptyRecordVisibility: function(show) {
  var emptyItem = this.grid.GetEmptyDataItem();
  ASPx.SetElementDisplay(emptyItem, show);
 },
 ChangeDeletedRecordVisibility: function(key, recover) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  this.ChangeDeletedRecordVisibilityByVisibleIndex(visibleIndex, recover);
 },
 RemoveRecordElement: function(key) { ASPx.RemoveElement(this.GetRecord(key)); }, 
 RaiseBatchEditRecordValidating: function(recordKey, args) { return this.grid.RaiseBatchEditItemValidating(this.ConvertKeyToVisibleIndex(recordKey), args); },
 RaiseBatchEditRecordInserting: function(keyInfo) { return this.grid.RaiseBatchEditItemInserting(keyInfo.key); },
 RaiseBatchEditRecordDeleting: function(recordKey, recordValues) { return this.grid.RaiseBatchEditItemDeleting(this.ConvertKeyToVisibleIndex(recordKey), recordValues); },
 RaiseBatchEditRecordRecovering: function(recordKey, recordValues) { return this.grid.RaiseBatchEditItemRecovering(this.ConvertKeyToVisibleIndex(recordKey), recordValues); },
 RaiseBatchEditStartEditing: function(recordKey, column, recordValues) { 
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  return this.grid.RaiseBatchEditStartEditing(visibleIndex, column, recordValues); 
 },
 RaiseBatchEditEndEditing: function(recordKey, focusedColumn, recordValues) { return this.grid.RaiseBatchEditEndEditing(this.ConvertKeyToVisibleIndex(recordKey), focusedColumn, recordValues); },
 RaiseBatchEditItemChangesCanceling: function(recordKey, recordValues) { return this.grid.RaiseBatchEditItemChangesCanceling(this.ConvertKeyToVisibleIndex(recordKey), recordValues); },
 RaiseBatchEditChangesSaving: function(modifiedValuesInfo) { return this.grid.RaiseBatchEditChangesSaving(this.PrepareModifiedValuesInfo(modifiedValuesInfo));  },
 RaiseBatchEditChangesCanceling: function(modifiedValuesInfo) { return this.grid.RaiseBatchEditChangesCanceling(this.PrepareModifiedValuesInfo(modifiedValuesInfo)); },
 RaiseBatchEditConfirmShowing: function(requestTriggerID) { return this.grid.RaiseBatchEditConfirmShowing(requestTriggerID); },
 RaiseBatchEditSummaryDisplayText: function(summaryInfo, text, groupRowVisibleIndex) { return this.grid.RaiseBatchEditSummaryDisplayText(summaryInfo, text, groupRowVisibleIndex); },
 RequireIntersectVisibleColumnIndices: function() { return false; },
 OnRemoveItemErrors: function() {  },
 OnProcessValidationErrors: function() {  },
 GetFocusHelperType: function() { return GridBatchEditFocusHelper; },
 GetChangesPreviewHelperType: function() { return null; },
 GetInsertedRecordKeys: function() { return this.grid.GetBatchEditHelper().GetInsertedRecordKeys(); }, 
 ConvertKeyToVisibleIndex: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 ConvertVisibleIndexToKey: function(visibleIndex) { return this.grid.ConvertVisibleIndexToKey(visibleIndex);},
 GetSelectCheckBox: function(key) {  
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  return ASPx.GetParentByPartialClassName(this.grid.GetDataRowSelBtn(visibleIndex), this.CheckBoxClassName); 
 },
 InsertRecordValidationError: function(key, errorText) { 
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  if(visibleIndex === null) return;
  var record = this.GetRecordByVI(visibleIndex);
  var itemError = this.GetErrorItem(visibleIndex) || this.CreateItemError(visibleIndex);
  if(!record || !itemError) return;
  this.InsertRecordValidationErrorCore(record, itemError, errorText);
 }, 
 CreateItemError: function(visibleIndex) {
  var item = this.grid.CreateEditingErrorItem(visibleIndex);
  item.id = this.GetRecordErrorID(visibleIndex);
  return item;
 },
 PlaceNewRecord: function(newRecord, siblingRecordKey, isNewRecordOnTop) {
  var sibling = this.GetNewRecordSibling(siblingRecordKey, isNewRecordOnTop);
  if(!newRecord || !sibling) return;
  if(isNewRecordOnTop)
   sibling.parentNode.insertBefore(newRecord, sibling);
  else
   ASPx.InsertElementAfter(newRecord, sibling);
  this.ShowRecord(newRecord);
 },
 GetNewRecordSibling: function(siblingRecordKey, isNewRecordOnTop) {
  var item = this.GetRecord(siblingRecordKey);
  if(!item || item instanceof Array && item.length === 0)
   return this.GetEtalonNewItem();
  return item;
 },
 ShowRecord: function(record) {  ASPx.SetElementDisplay(record, true); },
 CreateNewItemElement: function(recordKeyInfo) {  
  var recordKey = recordKeyInfo.key;
  var newItem = this.CreateNewItemElementCore(recordKey);
  this.AssignNewItemId(newItem, recordKey);
  this.PrepareNewRecordCommanButtonsIDList(newItem);
  return newItem;
 },
 PrepareNewRecordCommanButtonsIDList: function(newRecord) { this.grid.PrepareCommandButtonsIDList(newRecord); },
 AssignNewItemId: function(newItem, recordKey) { newItem.id = this.GetDataItemID(recordKey); },
 GetDataItemID: function(index) { return this.grid.name + "_" + this.GetDataItemIDPrefix() + index.toString(); },
 GetDataItemIDPrefix: function() { },
 GetRecordErrorID: function(visibleIndex) { return this.grid.name + "_" + this.grid.EditingErrorItemID + visibleIndex; },
 CreateNewItemElementCore: function(recordKey) {   },
 GetEtalonNewItem: function() { return this.grid.GetChildElement(this.grid.GetDataItemIDPrefix() + this.GetEtalonRecordPostFix()); },
 GetEtalonRecordPostFix: function() { return this.grid.EtalonBatchRecordPostFix; },
 GetVisibleIndexFromID: function(element) {
  if(!element || !element.id) return null;
  return this.grid.getItemIndex(element.id);
 },
 PrepareCommandButtonIDs: function(container, recordKey) { this.grid.PrepareCommandButtonsIDList(container); },
 GetRecoverButtonParent: function(key, columnIndex) { return this.GetDataCell(key, columnIndex); },
 GetRecordCommandButtons: function(recordKey) {  
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  return this.GetRecordCommandButtonsByVI(visibleIndex);
 },
 GetCommandButtonsInContainer: function(element) { return this.grid.GetCommandButtonsInContainer(element); },
 PrepareModifiedValuesInfo: function(info) {
  var result = { };
  result.updatedValues = this.PrepareModifiedValues(info.updatedValues);
  result.insertedValues = this.PrepareModifiedValues(info.insertedValues);
  result.deletedValues = this.PrepareModifiedValues(info.deletedValues);
  return result;
 },
 PrepareModifiedValues: function(values) {
  var result = { };
  for(var key in values) {
   if(!values.hasOwnProperty(key)) continue;   
   var visibleIndex = this.ConvertKeyToVisibleIndex(key);
   result[visibleIndex] = values[key];
  }
  return result;
 },
 ChangeFormLayoutItemStyle: function(element, style) {
  if(!ASPx.FormLayoutConsts) return;  
  var cell = ASPx.GetParentByPartialClassName(element, ASPx.FormLayoutConsts.GROUP_CELL_PARTIAL_CLASS_NAME);
  if(cell && cell.tagName === "DIV") 
   cell = cell.parentNode;
  var itemElement = ASPx.GetNodeByClassName(cell, ASPx.FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
  if(itemElement) {
   var helper = this.GetStyleHelper();
   ASPxClientFormLayout.UpdateNestedControlTypeClassName(itemElement, helper.IsBatchEditCellStyle(style) || helper.IsBatchEditMergedModifiedCellStyle(style));
  }
 },
 LoadCellAlign: function(targetCell, columnIndex) { 
 },
 GetErrorItem: function(visibleIndex) { return this.grid.GetEditingErrorItem(null, visibleIndex); }
});
var GridViewBatchEditHelperOwner = ASPx.CreateClass(GridBatchEditHelperOwner, {
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
 },
 GetChangesPreviewHelperType: function() { return GridViewBatchEditChangesPreviewHelper; }, 
 GetFocusHelperType: function() { return GridViewBatchEditFocusHelper; },
 IsLastCallbackProcessedAsEndless: function() { return this.grid.IsLastCallbackProcessedAsEndless(); },
 GetColumnIndexByDataCell: function(dataCell) { return this.grid.GetColumnIndexByDataCell(dataCell); },
 GetVisibleColumnIndices: function() { return this.grid.GetColumnHelper().GetVisibleColumnIndices(true); },
 GetRecordByVI: function(visibleIndex) {
  if(this.IsBandedDataRowsMode())
   return this.grid.GetBatchBandedDataRows(visibleIndex); 
  return this.grid.GetBatchDataRow(visibleIndex);
 },
 IsValidRecord: function(key) {  
  var record = this.GetRecord(key) || this.grid.GetDataRow(this.ConvertKeyToVisibleIndex(key)); 
  if(!record) return false;
  return this.IsBandedDataRowsMode() ? record.length > 0 : record instanceof Element;
 },
 IsRecordVisible: function(key) {
  if(this.IsBandedDataRowsMode()) {
   var bandedRecord = this.GetRecord(key);
   return bandedRecord.reduce(function(accum, bandElement) { return accum && ASPx.GetElementDisplay(bandElement); }, true);
  }
  return GridBatchEditHelperOwner.prototype.IsRecordVisible.call(this, key);
 },
 IsRecordElement: function(element){
  if(!element || !element.id) return false;
  if(this.IsBandedDataRowsMode())
   return this.grid.IsBandedDataRowID(element.id);
  return this.GetLayoutHelper().IsDataRow(element) || this.IsAdaptiveDetailRow(element);
 },
 GetDataCellByVI: function(visibleIndex, columnIndex) {
  return this.grid.GetBatchDataCell(visibleIndex, columnIndex);
 },
 GetDataCellByChild: function(element) { return this.GetLayoutHelper().GetDataCellByChild(element); },
 OnBatchEditHelperInit: function() {
  GridBatchEditHelperOwner.prototype.OnBatchEditHelperInit.call(this);
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
 },
 OnBatchEditHelperCallback: function() {
  GridBatchEditHelperOwner.prototype.OnBatchEditHelperCallback.call(this);
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
 },
 OnResetChanges: function(isMultiple) {
  if(!isMultiple)
   this.grid.CalculateAdaptivity(true);
  GridBatchEditHelperOwner.prototype.OnResetChanges.call(this);
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
 },
 OnEndMultipleResetChanges: function() {
  this.grid.CalculateAdaptivity(true);
 },
 OnNewRecordAdded: function(newRecordKey) {
  GridBatchEditHelperOwner.prototype.OnNewRecordAdded.call(this, newRecordKey);
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
  this.grid.MakeRowVisible(newRecordKey);
 },
 OnBeforeStartEditNewRecord: function(newRecordKey) { 
  this.grid.CalculateAdaptivity(true); 
 },
 OnDataItemDeleted: function(deletedRecordKey) {
  GridBatchEditHelperOwner.prototype.OnDataItemDeleted.call(this, deletedRecordKey);
  this.grid.UpdateFirstAndLastVisibleRowMarkers(); 
 },
 RemoveRecordElement: function(key) {
  var rowsToDelete = this.GetRecordRelatedRows(key, true, true, true, true);
  rowsToDelete.forEach(function(row) { ASPx.RemoveElement(row); });
 },
 ChangeDeletedRecordAppearance: function(key, recover, highlightMode) {
  var includeAdaptive = highlightMode || !recover;
  var rows = this.GetRecordRelatedRows(key, includeAdaptive, true, true, !highlightMode );
  if(highlightMode) {
   this.UpdateRecordStyle(key); 
   this.ChangeRowsDeletedStyle(rows, recover);
  } else
   this.ChangeDeletedRowsVisibility(rows, recover);
 },
 ChangeDeletedRowsVisibility: function (rows, visible) { ASPx.Data.ForEach(rows, function(row){ ASPx.SetElementDisplay(row, visible); }); },
 ChangeEmptyRecordVisibility: function(show) {
  show = show && !this.HasVisibleGroupRows();
  GridBatchEditHelperOwner.prototype.ChangeEmptyRecordVisibility.call(this, show);
 },
 RemoveRecordErrorByVI: function(visibleIndex) { 
  var itemError = this.GetRecordErrorByVI(visibleIndex);
  this.GetLayoutHelper().UpdateOnErrorRowDeleting(visibleIndex, itemError);
  ASPx.RemoveElement(itemError);
 },
 ChangeCellStyle: function(recordKey, columnIndex, style, showEditor) {  
  var cell = this.GetDataCell(recordKey, columnIndex);
  if(!cell) return;
  GridBatchEditHelperOwner.prototype.ChangeCellStyle.call(this, recordKey, columnIndex, style, showEditor);
  var isColumnInRightTreeLine = this.grid.GetColumnHelper().IsColumnInRightTreeLine(columnIndex);
  if(isColumnInRightTreeLine && !this.grid.HasScrolling())
   ASPx.SetStyles(cell, { borderRightWidth: 0 });
  this.ChangeFormLayoutItemStyle(cell, style);
 },
 CanEditCell: function(recordKey, columnIndex) { 
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  var layoutHelper = this.GetLayoutHelper();
  return !layoutHelper.IsMergedCell(visibleIndex, columnIndex);
 },
 GetIsRecordChild: function(record, element) {
  var rowsToCheck = this.GetRecordRows(record);
  return rowsToCheck.some(function(row) { return ASPx.GetIsParent(row, element); });
 },
 CreateNewItemElementCore: function(recordKey) {
  var etalonItem = this.GetEtalonNewItem();
  var createClone = function(node) { return this.CloneEtalonDataRow(node, recordKey); }.bind(this);
  return this.ExecuteOnItem(etalonItem, createClone);
 },
 CloneEtalonDataRow: function(etalon, recordKey) {
  if(!etalon)
   return null;
  var clone = etalon.cloneNode(true);
  this.PrepareEtalonElementInnerHtml(clone, recordKey, this.GetEtalonRecordPostFix());
  return clone;
 },
 ApplyNewRowStyle: function(row) {
  var helper = this.GetStyleHelper(); 
  var style = helper.GetBatchEditNewItemStyle();
  helper.ApplyElementStyle(row, style, true);
 },
 ShowRecord: function(record) {
  var baseMethod = GridBatchEditHelperOwner.prototype.ShowRecord.aspxBind(this);
  this.ExecuteOnItem(record, baseMethod);
 },
 PlaceNewRecord: function(newRecord, siblingRecordKey, isNewRecordOnTop) {
  var applyStyle = function(node) { return this.ApplyNewRowStyle(node); }.bind(this); 
  this.ExecuteOnItem(newRecord, applyStyle);
  if(!this.IsBandedDataRowsMode())
   return GridBatchEditHelperOwner.prototype.PlaceNewRecord.call(this, newRecord, siblingRecordKey, isNewRecordOnTop);
  var sibling = this.GetNewRecordSibling(siblingRecordKey, isNewRecordOnTop);
  if(isNewRecordOnTop) 
   newRecord.forEach(function(bandElement) { sibling.parentNode.insertBefore(bandElement, sibling); });
  else
   newRecord.reverse().forEach(function(bandElement) { ASPx.InsertElementAfter(bandElement, sibling); });
  this.ShowRecord(newRecord);
 },
 GetNewRecordSibling: function(siblingRecordKey, isNewRecordOnTop) {
  var sibling = GridBatchEditHelperOwner.prototype.GetNewRecordSibling.call(this,siblingRecordKey, isNewRecordOnTop);
  if(!this.IsBandedDataRowsMode()) {
   var adaptivityHelper = this.grid.GetAdaptivityHelper();
   var isAdaptivityModeActive = adaptivityHelper && adaptivityHelper.IsAdaptivityMode() && adaptivityHelper.HasAnyAdaptiveElement();
   var hasAdaptiveSibling = isAdaptivityModeActive && siblingRecordKey !== null;
   return hasAdaptiveSibling ? this.grid.GetAdaptiveDetailRow(siblingRecordKey) : sibling;
  }
  if(isNewRecordOnTop)
   return sibling[0];
  return sibling[sibling.length - 1];
 },
 PrepareNewRecordCommanButtonsIDList: function(newRecord) {
  var baseMethod = GridBatchEditHelperOwner.prototype.PrepareNewRecordCommanButtonsIDList.aspxBind(this);
  this.ExecuteOnItem(newRecord, baseMethod);
 },
 AssignNewItemId: function(newItem, key) {
  if(this.IsBandedDataRowsMode())
   newItem.forEach(function(row, index) { row.id = this.GetBandedRowID(key, index); }.aspxBind(this));
  else
   GridBatchEditHelperOwner.prototype.AssignNewItemId.call(this, newItem, key);
 },
 GetEtalonNewItem: function() { return this.IsBandedDataRowsMode() ? this.GetEtalonNewBandedRows() : GridBatchEditHelperOwner.prototype.GetEtalonNewItem.call(this); },
 GetRecordCommandButtonsByVI: function(visibleIndex) {
  var buttons = [];
  var grid = this.grid;
  var rows = this.GetRecordRelatedRowsByVI(visibleIndex, true, false, false, true);
  for(var i = 0; i < rows.length; i++)
   buttons = buttons.concat(this.GetCommandButtonsInContainer(rows[i]));
  return buttons.filter(function(button) { return !grid.IsAdaptiveDetailHideButton(button) && !grid.IsAdaptiveDetailShowButton(button); });
 },
 EnsureEllipsisTooltips: function(recordKey) { 
  this.ExecuteOnItem(this.GetRecord(recordKey), this.AssignEllipsisTooltips.bind(this)); 
 },
 InsertRecordValidationErrorCore: function(record, itemError, errorText) {  
  var grid = this.grid;
  var cell = grid.GetLastNonAdaptiveIndentCell(itemError);
  cell.innerHTML = errorText;
  var errorRowSibling = this.GetLastRowOfRecord(record);
  var visibleIndex = this.GetVisibleIndexFromID(errorRowSibling);
  var adaptiveRow = grid.GetAdaptiveDetailRow(visibleIndex);
  if(adaptiveRow)
   errorRowSibling = adaptiveRow;
  this.grid.UpdateEditingErrorRowColSpan(itemError, errorRowSibling);
  this.GetLayoutHelper().UpdateOnErrorRowInserting(visibleIndex, itemError);
  ASPx.InsertElementAfter(itemError, errorRowSibling);
 },
 UpdatePreviewChangesButtonVisibility: function(button, visible, changesCount, preventAnimation) {
  if(!button) return;
  this.UpdateCommandButtonVisibility(button, visible);
  this.UpdatePreviewChangesButtonChangesBadge(button, changesCount, preventAnimation);
 },
 UpdatePreviewChangesButtonChangesBadge: function(button, changesCount, preventAnimation) {
  var badgeContainer = button.GetMainElement();
  if(badgeContainer && button.IsLink())
   badgeContainer = badgeContainer.parentNode;
  var hasChanges = changesCount > 0;
  var badge = ASPx.BadgeManager.findBadge(badgeContainer);
  if(!badge && hasChanges)
   badge = ASPx.BadgeManager.createBadgeForButton(button);
  if(badge) {
   var currentCount = parseInt(ASPx.BadgeManager.getBadgeText(badgeContainer)) || 0;
   var statusBarElement = this.grid.GetStatusBar();
   var prevStatusBarWidth = ASPx.GetElementOffsetWidth(statusBarElement);
   ASPx.BadgeManager.setBadgeText(badge, hasChanges ? changesCount + "" : "");
   if(ASPx.GetElementOffsetWidth(statusBarElement) > prevStatusBarWidth)
    this.grid.UpdateScrollableControls();
   if(!preventAnimation && hasChanges && changesCount !== currentCount)
    ASPx.AnimationHelper.fadeIn(badge);
  }
 },
 GetDataItemIDPrefix: function() { return ASPx.GridViewConsts.DataRowID; },
 GetLayoutHelper: function() { return this.grid.GetLayoutHelper(); },
 GetAdaptiveDataCellByChild: function(dataItem, element) { return this.GetLayoutHelper().GetAdaptiveDataCellByChild(dataItem, element); },  
 IsAdaptiveDetailRow: function(row) { return this.GetLayoutHelper().IsAdaptiveDetailRow(row); },
 IsBandedDataRowsMode: function() { return this.grid.HasBandedDataRows(); },  
 IsBandedDataRows: function(item) { return this.IsBandedDataRowsMode() && item instanceof Array; },
 ExecuteOnItem: function(item, action) {
  if(this.IsBandedDataRows(item))
   return item.map(action);
  return action(item);
 },
 GetBandedRowID: function(key, bandLevel) {
  var id = this.GetDataItemID(key);
  if(!isNaN(bandLevel))
   id += "_" + bandLevel;
  return id;
 },
 GetEtalonNewBandedRows: function() {
  var result = [];
  var partialId = this.grid.GetDataItemIDPrefix() + this.GetEtalonRecordPostFix();
  var mainElement = this.grid.GetMainElement();
  ASPx.GetNodesByPartialId(mainElement, partialId, result);
  return result;
 },
 GetRecordRelatedRows: function(recordKey, includeAdaptive, includePreview, includeDetail, includeData) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  return this.GetRecordRelatedRowsByVI(visibleIndex, includeAdaptive, includePreview, includeDetail, includeData);
 },
 GetRecordRelatedRowsByVI: function(visibleIndex, includeAdaptive, includePreview, includeDetail, includeData) {
  var grid = this.grid;  
  var rows = [ ];
  if(includeData) {
   var dataItem = this.GetRecordByVI(visibleIndex);
   if(dataItem instanceof Array) {
    rows = rows.concat(dataItem);
   } else {
    rows.push(dataItem);
   }
  }
  if(includePreview)
   rows.push(grid.GetPreviewRow(visibleIndex));
  if(includeDetail)
   rows.push(grid.GetDetailRow(visibleIndex));
  if(includeAdaptive && grid.HasAnyAdaptiveElement())
   rows.push(grid.GetAdaptiveDetailRow(visibleIndex));
  return rows.filter(function(row) { return !!row; });
 },
 ChangeRowsDeletedStyle: function(rows, recover) {  
  var grid = this.grid; 
  var helper = this.GetStyleHelper();
  var style = recover ? helper.GetClearItemStyle(): helper.GetBatchEditDeletedItemStyle();
  ASPx.Data.ForEach(rows, function(row){ grid.ApplyElementStyle(row, style); });
 }, 
 HasVisibleGroupRows: function() {
  var grid = this.grid;
  var indices = grid.GetCurrentPageIndices();
  return indices.some(function(index) { 
   var row = grid.GetGroupRow(index);
   return row && ASPx.GetElementDisplay(row);
  });
 },  
 GetLastRowOfRecord: function(record){
  if(this.IsBandedDataRowsMode())
   return record[record.length - 1];
  return record;
 },
 GetRecordRows: function(record) { return this.IsBandedDataRows(record) ? record : [ record ]; }, 
 OnVisibleRowCountChanged: function() {
  var scrollHelper = this.grid.GetScrollHelper();
  if(!scrollHelper || !this.grid.HasVertScroll())
   return;
  ASPx.Timer.ClearTimer(this.updateScrollDivPaddingTimer);
  this.updateScrollDivPaddingTimer = window.setTimeout(function() { scrollHelper.UpdateScrollContainerPadding(); }, 0);
 },
 GetRecordElementsToEvaluateScripts: function(key) { return this.GetRecordRelatedRows(key, true, false, false, true); }
});
var CardViewBatchEditHelperOwner = ASPx.CreateClass(GridBatchEditHelperOwner, {
 EmptyHiddenCardClassName: "dxcvEmptyHiddenCard",
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
  this.breakpointsLayoutEtalonItemContainer = null;
 },
 GetBreakpointsLayoutItemContainer: function(item) { return item.parentNode; },
 GetRecordCommandButtonsByVI: function(visibleIndex) { return this.GetCommandButtonsInContainer(this.GetRecordByVI(visibleIndex)); },
 GetColumnKey: function(dataCell) { return this.grid.GetItemPathByCell(dataCell); },
 GetColumnIndexByDataCell: function(dataCell) { return this.grid.GetBatchEditHelper().focusHelper.ResolveColumnIndex(this.GetColumnKey(dataCell)); },  
 GetDataCellByChild: function(element) { return this.grid.GetFormLayoutItemCellByChild(element); },
 GetDataCellByVI: function(visibleIndex, columnIndex) {  
  return this.grid.GetFormLayoutNestedControlCell(visibleIndex, columnIndex); 
 },
 GetRecordByVI: function(visibleIndex) { return this.grid.GetItem(visibleIndex); },
 GetDataItemIDPrefix: function() { return this.grid.CardID; },
 GetLayoutControl: function(visibleIndex) { return this.grid.GetCardLayoutControl(visibleIndex); }, 
 GetFocusHelperType: function() { return CardViewBatchEditFocusHelper; },
 CreateNewItemElementCore: function(recordKey) {
  var etalonItem = this.GetEtalonNewItem();
  var wrapper = document.createElement("DIV");
  var outerHTML = etalonItem.outerHTML;
  if(this.grid.IsTableLayoutMode())
   outerHTML = "<table><tbody>" + outerHTML + "</tbody></table>";
  wrapper.innerHTML = outerHTML;
  this.PrepareEtalonElementInnerHtml(wrapper, recordKey, this.GetEtalonRecordPostFix());
  return this.GetNewItemElementInWrapper(wrapper);
 },
 GetNewItemElementInWrapper: function(wrapper) {
  return ASPx.GetNodesByPartialClassName(wrapper, this.grid.GetCssClassNamePrefix())[0];
 },
 PlaceNewRecord: function(newRecord, siblingRecordKey, isNewRecordOnTop) {
  if(this.grid.IsTableLayoutMode()) {
   var itemToReplace = this.FindEmptyItemToReplaceByNew(isNewRecordOnTop);
   ASPx.InsertElementAfter(newRecord, itemToReplace);
   ASPx.RemoveElement(itemToReplace);
  } else {
   var recordElement = newRecord;
   if(this.grid.IsBreakpointsLayoutMode()) {
    recordElement = this.CreateBreakpointsLayoutNewItemContainerElement();
    recordElement.appendChild(newRecord); 
    this.ShowRecord(newRecord);
   }
   GridBatchEditHelperOwner.prototype.PlaceNewRecord.call(this, recordElement, siblingRecordKey, isNewRecordOnTop);
  }
 },
 GetNewRecordSibling: function(siblingRecordKey, isNewRecordOnTop) {
  var baseSibling = GridBatchEditHelperOwner.prototype.GetNewRecordSibling.call(this, siblingRecordKey, isNewRecordOnTop);
  return this.grid.IsBreakpointsLayoutMode() ? this.GetBreakpointsLayoutItemContainer(baseSibling) : baseSibling;
 },
 CreateBreakpointsLayoutNewItemContainerElement: function() {
  if(!this.breakpointsLayoutEtalonItemContainer) {
   var etalonItem = this.GetEtalonNewItem();
   this.breakpointsLayoutEtalonItemContainer = this.GetBreakpointsLayoutItemContainer(etalonItem).cloneNode();
  }
  return this.breakpointsLayoutEtalonItemContainer.cloneNode();
 },
 FindEmptyItemToReplaceByNew: function(isNewRecordOnTop) {
  var colCount = this.grid.colCount;
  var mainTable = this.grid.GetMainTable();
  var etalonItem = this.GetEtalonNewItem();
  var etalonRow = etalonItem.parentNode;
  var etalonRowIndex = etalonRow.sectionRowIndex;
  var insertedCardCount = this.GetInsertedCardCount();
  var createNewRow = insertedCardCount === 0 || insertedCardCount % colCount === 0;
  if(!createNewRow) {
   var index = isNewRecordOnTop ? 0 : mainTable.rows.length - 1;
   return ASPx.GetChildByPartialClassName(mainTable.rows[index], this.EmptyHiddenCardClassName);
  }
  var step = isNewRecordOnTop ? 1 : -1;
  var etalonSeparatorRow = mainTable.rows[etalonRowIndex + step];
  var newDataRow = etalonRow.cloneNode(true);
  var newSeparatorRow = etalonSeparatorRow.cloneNode(true);
  ASPx.SetElementDisplay(newDataRow, true);
  ASPx.SetElementDisplay(newSeparatorRow, true);
  if(isNewRecordOnTop) {
   etalonRow.parentNode.insertBefore(newSeparatorRow, mainTable.rows[0]);
   etalonRow.parentNode.insertBefore(newDataRow, mainTable.rows[0]);
  } else {
   ASPx.InsertElementAfter(newSeparatorRow, mainTable.rows[mainTable.rows.length - 1]);
   ASPx.InsertElementAfter(newDataRow, mainTable.rows[mainTable.rows.length - 1]);
  }
  return newDataRow.cells[0];
 },
 GetInsertedCardCount: function () {
  var keys = this.GetInsertedRecordKeys().filter(function(key) { return this.IsValidRecord(key); }.bind(this));
  return keys.length;
 },
 RemoveRecordElement: function(key) { 
  var record = this.GetRecord(key);
  if(this.grid.IsFlowLayoutMode()) {
   ASPx.RemoveElement(record);
   return;
  }
  if(this.grid.IsBreakpointsLayoutMode()) {
   ASPx.RemoveElement(this.GetBreakpointsLayoutItemContainer(record));
   return;
  }
  var isNewRecord = this.GetInsertedRecordKeys().indexOf(key) > -1;
  if(isNewRecord) {
   this.RemoveInsertedCard(key);
   return;
  }
  var emptyCard = this.CreateEmptyCard();
  if(emptyCard) {
   ASPx.InsertElementAfter(emptyCard, record);
   ASPx.RemoveElement(record);
  }
 },
  RemoveInsertedCard: function(key) {
  var item = this.GetRecord(key);
  var replaceInfo = this.GetRemovingItemReplaceInfo(key);
  ASPx.RemoveElement(item);
  for(var i = 0; i < replaceInfo.length; i++)
   this.ReplaceElementByInfo(replaceInfo[i]);   
  var newItemOnTop = this.GetBatchEditClientState().isNewRowOnTop;
  var mainTable = this.grid.GetMainTable();
  var lastRow = mainTable.rows[newItemOnTop ? 0 : mainTable.rows.length - 1];
  var lastSeparator = mainTable.rows[newItemOnTop ? 1 : mainTable.rows.length - 2];
  var dataCards = [ ];
  ASPx.GetNodesByPartialId(lastRow, this.GetDataItemIDPrefix(), dataCards);
  if(dataCards.length === 0) {
   ASPx.RemoveElement(lastRow);
   ASPx.RemoveElement(lastSeparator);
  }
 },
 GetRemovingItemReplaceInfo: function(recordKey) {
  var insertedKeys = this.GetInsertedRecordKeys();
  var keys = insertedKeys.slice(insertedKeys.indexOf(recordKey));
  var cardsToMove = [ ];
  for(var i = 0; i < keys.length; i++)
   cardsToMove.push(this.GetRecord(keys[i]));
  var oneColumnLayout = this.grid.colCount === 1;
  if(!oneColumnLayout)
   cardsToMove.push(this.CreateEmptyCard()); 
  var result = [ ];  
  for(var i = 1; i < cardsToMove.length; i++) {
   var prevItem = cardsToMove[i - 1];
   var currentItem = cardsToMove[i];
   var info = { element: currentItem };
   if(!oneColumnLayout) {
    var prevItemIndex = prevItem.cellIndex;
    var isLast = prevItemIndex === prevItem.parentNode.cells.length - 1;
    var refElementIndex = prevItemIndex + (isLast ? -1 : 1);
    info.refElement = prevItem.parentNode.cells[refElementIndex];
    info.insertAfter = isLast;
   } else
    info.containerToInsert = prevItem.parentNode;
   result.push(info);
  }
  return result;
 },
 ReplaceElementByInfo: function(info) {
  if(!info) return;
  var element = info.element;
  ASPx.RemoveElement(element);
  if(info.containerToInsert)
   info.containerToInsert.appendChild(element);
  else if(info.insertAfter)
   ASPx.InsertElementAfter(element, info.refElement);
  else
   info.refElement.parentNode.insertBefore(element, info.refElement);
 },
 CreateEmptyCard: function() {
  var etalonItem = this.GetEtalonNewItem();
  var etalonRow = etalonItem.parentNode;
  var emptyCards = ASPx.GetNodesByPartialClassName(etalonRow, this.EmptyHiddenCardClassName);
  return emptyCards.length > 0 && emptyCards[0].cloneNode(true);
 },
 ChangeCellStyle: function(recordKey, columnIndex, style, showEditor) {
  GridBatchEditHelperOwner.prototype.ChangeCellStyle.call(this, recordKey, columnIndex, style, showEditor);
  var cell = this.GetDataCell(recordKey, columnIndex);
  if(cell)
   this.ChangeFormLayoutItemStyle(cell, style);
 },
 GetRecoverButtonParent: function(key, columnIndex) { 
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  var cell = this.grid.GetFormLayoutItemCell(visibleIndex, columnIndex);
  return ASPx.GetNodesByPartialClassName(cell, "dxflCommandItemSys")[0];
 },
 ChangeDeletedRecordVisibilityByVisibleIndex: function(visibleIndex, show) { 
  var layoutControl = this.GetLayoutControl(visibleIndex);
  if(!layoutControl) return;
  layoutControl.SetVisible(show);
  this.ChangeDataItemDeleteMessageContainerVisibility(visibleIndex, show);
 },
 ChangeDataItemDeleteMessageContainerVisibility: function(visibleIndex, show) {
  var deleteMessageContainer = this.GetDataItemDeleteMessageContainer(visibleIndex);
  ASPx.SetElementDisplay(deleteMessageContainer, !show);
  var dataItem = this.GetRecordByVI(visibleIndex);
  dataItem.style.opacity = show ? 1 : 0.3;
  dataItem.style.textAlign = "center";
  dataItem.style.verticalAlign = "middle";
 },
 GetDataItemDeleteMessageContainer: function(visibleIndex) {
  var dataItem = this.GetRecordByVI(visibleIndex);
  if(!dataItem.delMessageContainer) {
   var container = document.createElement("SPAN");
   container.innerHTML = this.grid.deletedCardCaption;
   this.appendDataItemDeleteMessageContainer(dataItem, container);
   dataItem.delMessageContainer = container;
  }
  return dataItem.delMessageContainer;
 },
 appendDataItemDeleteMessageContainer: function(dataItem, deleteMessageContainer) {
  dataItem.appendChild(deleteMessageContainer);
 },
 InsertRecordValidationErrorCore: function(record, itemError, errorText) {  
  itemError.innerHTML = errorText;
  var errorItemContainer = this.grid.GetErrorItemContainer(record);
  errorItemContainer.appendChild(itemError);
 },
 GetRecordElementsToEvaluateScripts: function(key) { return [ this.GetRecord(key) ]; }
});
var VerticalGridBatchEditHelperOwner = ASPx.CreateClass(GridBatchEditHelperOwner, {
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
  this.insertedRecordArmCells = { };
 },
 EmptyRecordVisibililityClassName: "dxvgERV",
 GetTableHelper: function() { return this.grid.GetTableHelper(); },
 GetFocusHelperType: function() { return VerticalGridBatchEditFocusHelper; },
 GetRecordByVI: function(visibleIndex) { 
  if(!this.IsValidRecordByVI(visibleIndex))
   return null;
  return this.grid.GetItem(visibleIndex); 
 },
 GetDataCellByVI: function(visibleIndex, columnIndex) { 
  return this.grid.GetRecordCell(visibleIndex, columnIndex); 
 },
 GetDataCellByChild: function(element) { return this.grid.getRecordCellByChild(element); },
 GetColumnIndexByDataCell: function(dataCell) {
  if(!dataCell)
   return -1;
  return this.grid.GetColumnIndexFromHtmlRow(dataCell.parentNode);
 },
 GetRecordCells: function(key) {  return this.grid.GetRecordCells(this.ConvertKeyToVisibleIndex(key)); },
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(true); },
 IsRecordElement: function(element) { return element && ASPx.IsExists(element.visibleIndex) && this.IsValidRecordByVI(element.visibleIndex); },
 IsRecordVisible: function(key) {
  var record = this.GetRecord(key);
  if(!record)
   return false;
  var cells = this.grid.GetRecordCells(record.visibleIndex);
  return cells.filter(function(cell) { return ASPx.GetElementDisplay(cell); }).length > 0;
 },
 IsValidRecord: function(key) {  
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  return this.IsValidRecordByVI(visibleIndex);
 },
 IsValidRecordByVI: function(visibleIndex) { 
  if(this.IsNewItem(visibleIndex)) {   
   var armCell = this.insertedRecordArmCells[visibleIndex];
   var isValid = ASPx.IsValidElement(armCell);
   if(!isValid)
    delete this.insertedRecordArmCells[visibleIndex];
   return isValid;
  }
  var cells = this.grid.GetRecordCells(visibleIndex).filter(function(cell) { return !!cell; });
  return cells.length > 0;
 },
 IsNewItem: function(key) { return this.GetInsertedRecordKeys().indexOf(key) > -1; },
 GetArmatureCellsByVisibleIndex: function(visibleIndex) {
  var grid = this.grid;
  var tables = [ grid.GetFixedTable(), grid.GetMainTable() ];
  return tables.map(function(table) { return grid.GetTableHelper().GetArmatureCellByVisibleIndex(table, visibleIndex); });
 },
 CreateNewItemElementCore: function(recordKey) {
  this.UpdateFixedColumnHelper();
  var newCellsInfo = this.CreateNewRecordCells(false);
  if(this.grid.hasFixedRows)
   newCellsInfo = newCellsInfo.concat(this.CreateNewRecordCells(true));
  this.insertedRecordArmCells[recordKey] = newCellsInfo[0].newCell;
  ASPx.Data.ForEach(newCellsInfo, function(cellInfo) { 
   this.PrepareEtalonElementInnerHtml(cellInfo.newCell, recordKey, this.GetEtalonRecordPostFix()); 
  }.bind(this));
  return newCellsInfo;
 },
 AssignNewItemId: function(newItem, recordKey) { 
  var newCellsInfo = newItem;
  var newCell = newCellsInfo[0].newCell;
  newCell.id += recordKey;
 },
 PlaceNewRecord: function(newRecord, siblingRecordKey, isNewRecordOnTop) {
  var newCellsInfo = newRecord;
  for(var i = 0; i < newCellsInfo.length; i++) {
   var info = newCellsInfo[i];
   ASPx.InsertElementAfter(info.newCell, info.refCell);
   ASPx.SetElementDisplay(info.newCell, true);
  }
  this.grid.GetTableHelper().DropRecordCellsCache();
 },
 PrepareNewRecordCommanButtonsIDList: function(newRecord) {
  var grid = this.grid;
  var cells = newRecord.map(function(info) { return info.newCell; });
  cells.forEach(function(cell) { grid.PrepareCommandButtonsIDList(cell); });
 },
 OnNewRecordAdded: function(newRecordKey) {
  GridBatchEditHelperOwner.prototype.OnNewRecordAdded.call(this, newRecordKey);
  this.grid.UpdateCategoryRowsExpandButtonPosition();
 },
 OnVisibleRowCountChanged: function() {
  var grid = this.grid;
  grid.UpdateCategoryRowsExpandButtonPosition();
  var scrollHelper = grid.GetScrollHelper();
  if(!scrollHelper) return;
  ASPx.Timer.ClearTimer(this.updateScrollDivPaddingTimer);
  this.updateScrollDivPaddingTimer = window.setTimeout(function() { scrollHelper.UpdateScrollableControlsSize(); }, 0);
 },
 ChangeDeletedRecordVisibilityByVisibleIndex: function(visibleIndex, show) {
  var grid = this.grid;
  var armCells = this.GetArmatureCellsByVisibleIndex(visibleIndex);
  for(var i = 0; i < armCells.length; i++)
   ASPx.SetElementDisplay(armCells[i], show);
  var columns = grid.GetVisibleColumns();
  for(var i = 0; i < columns.length; i++) {
   var column = columns[i];
   if(column.isCategoryColumn)
    this.ChangeCategoryCellColSpan(grid.GetHeader(column.index), show);
   else
    this.ChangeCellVisibility(grid.GetRecordCell(visibleIndex, column.index), show);
  }
  var row = grid.GetEditingErrorRow();
  if(row)
   ASPx.SetElementDisplay(grid.GetTableHelper().GetRecordCellByRow(row, visibleIndex), show);
 },
 GetRecordCommandButtonsByVI: function(visibleIndex) {
  var buttons = []; 
  var grid = this.grid;
  var cells = grid.GetCommandCells(visibleIndex);
  for(var i = 0; i < cells.length; i++)
   buttons = buttons.concat(this.GetCommandButtonsInContainer(cells[i]));
  return buttons;
 },
 RemoveRecordElement: function(key) {
  var grid = this.grid;
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  var columns = grid.GetVisibleColumns();
  for(var i = 0; i < columns.length; i++) {
   var column = columns[i];
   if(column.isCategoryColumn) {
    this.ChangeCategoryCellColSpan(grid.GetHeader(column.index), false);
   } else {
    var cell = grid.GetRecordCell(visibleIndex, column.index);
    ASPx.RemoveElement(cell);
   }
  }
  var row = grid.GetEditingErrorRow();
  if(row)
   ASPx.RemoveElement(grid.GetTableHelper().GetRecordCellByRow(row, visibleIndex));
  var armCells = this.GetArmatureCellsByVisibleIndex(visibleIndex);
  for(var i = 0; i < armCells.length; i++)
   ASPx.RemoveElement(armCells[i]);
  grid.GetTableHelper().DropRecordCellsCache();
  delete this.insertedRecordArmCells[visibleIndex];
 },
 ChangeEmptyRecordVisibility: function(show) {
  var grid = this.grid;
  var className = this.EmptyRecordVisibililityClassName;
  var tables = [ grid.GetMainTable(), grid.GetFixedTable() ];
  ASPx.Data.ForEach(tables, function(table) {
   if(!table) return;
   if(show) ASPx.AddClassNameToElement(table, className);
   else ASPx.RemoveClassNameFromElement(table, className);
  });
 },
 CreateItemError: function(visibleIndex) {
  var result = GridBatchEditHelperOwner.prototype.CreateItemError.call(this, visibleIndex);
  this.grid.UpdateEditingErrorRowVisibility();
  return result;
 },
 RemoveRecordErrorByVI: function(visibleIndex) {
  var itemError = this.GetRecordError(visibleIndex);
  if(itemError)
   itemError.parentNode.style.height = 0;
  GridBatchEditHelperOwner.prototype.RemoveRecordErrorByVI.call(this, visibleIndex);
  this.grid.UpdateEditingErrorRowVisibility();
 },
 InsertRecordValidationErrorCore: function(record, itemError, errorText) {
  itemError.innerHTML = errorText;
 },
 RequireIntersectVisibleColumnIndices: function() { return true; },
 EnsureEllipsisTooltips: function(recordKey) {
  var recordCells = this.grid.GetRecordCells(this.ConvertKeyToVisibleIndex(recordKey));
  recordCells.forEach(this.AssignEllipsisTooltips.bind(this));
 },
 OnRemoveItemErrors: function() { this.grid.UpdateEditingErrorRowExtraCellHeight(0); },
 OnProcessValidationErrors: function() { this.grid.UpdateEditingErrorRowCellsHeight(); },
 UpdateFixedColumnHelper: function() {
  var grid = this.grid;
  var fixedColumnsHelper = grid.GetFixedColumnsHelper();
  if(fixedColumnsHelper) {
   fixedColumnsHelper.UpdateCellsVisibility(0);
   grid.SetHorizontalScrollPosition(0);
  }
 },
 CreateNewRecordCells: function(useFixedTable) {
  var grid = this.grid;
  var info = [ ];
  var table = useFixedTable ? grid.GetFixedTable() : grid.GetMainTable();
  var armCells = grid.GetTableHelper().GetArmatureCells(table);
  var armHeaderCell = armCells[grid.headerPartCellCount - 1];
  info.push(this.CreateNewCellInfo(armHeaderCell));
  var columns = grid.GetVisibleColumns().filter(function(column) { return column.isFixed === useFixedTable; });
  for(var i = 0; i < columns.length; i++) {
   var column = columns[i];
   var headerCell = grid.GetHeader(column.index);
   if(column.isCategoryColumn)
    this.ChangeCategoryCellColSpan(headerCell, true);
   else 
    info.push(this.CreateNewCellInfo(headerCell));
  }
  var row = grid.GetEditingErrorRow();
  if(!useFixedTable && row)
   row.insertCell(0);
  return info;
 },
 CreateNewCellInfo: function(refCell) {
  var row = refCell.parentNode;
  var etalonCell = row.cells[row.cells.length - 1];
  var newCell = etalonCell.cloneNode(true);
  return { newCell: newCell, refCell: refCell };
 },
 ChangeCellVisibility: function(cell, visible) {
  var manager = this.grid.GetStyleHelper();
  manager.AddToInitialStyle(cell, { display: visible ? "" : "none" });
 },
 ChangeCategoryCellColSpan: function(cell, inc) {
  if(cell)
   cell.colSpan += inc ? 1 : -1;
 },
 GetRecordElementsToEvaluateScripts: function(key) { return this.GetRecordCells(key); }
});
var GridBatchEditHelper = ASPx.CreateClass(ASPx.BatchEditHelper, {
 constructor: function(owner) {
  this.constructor.prototype.constructor.call(this, owner);
  this.grid = this.owner.control;
  this.maxActualVisibleIndex = 1000000000000000;
  this.changesViewHelper = this.CreateChangesViewHelper();
  this.currentPageInsertedKeysInfo = [ ];
 },
 CreateChangesViewHelper: function() {
  var type = this.owner.GetChangesPreviewHelperType();
  if(type && this.IsCallbacksEnabled())
   return new type(this);
  return null;
 },
 CreateUpdateWatcher: function() { return new GridBatchEditUpdateWatcherHelper(this); },
 CreateNewRecordKeyInfo: function(parentRecordKey) {
  var insertedKeys = this.GetInsertedRecordKeys();
  var lastIndex = insertedKeys.length > 0 ? insertedKeys[insertedKeys.length - 1] : 0;
  return { key: lastIndex - 1, parentRecordKey: parentRecordKey };
 },
 GetEditColumnIndices: function() {
  var indices = ASPx.BatchEditHelper.prototype.GetEditColumnIndices.call(this);
  if(this.owner.RequireIntersectVisibleColumnIndices())
   indices = this.IntersectColumnIndices(indices, this.GetVisibleColumnIndices());
  return indices;
 }, 
 GetInvalidRecordKeys: function () { return ASPx.GetObjectKeys(this.invalidItemsInfo); },
 OnItemStyleChanged: function(key, appliedStyle) { 
  if(typeof(ASPxClientGridView) != "undefined" && this.grid instanceof ASPxClientGridView) {  
   var helper = this.grid.GetStyleHelper();
   if(this.IsDeletedRecord(key) && !helper.IsBatchEditDeletedItemStyle(appliedStyle))
    this.ChangeDeletedRecordAppearance(key, false);
   this.grid.UpdateFirstAndLastVisibleRowMarkers();
  }
 }, 
 IsCurrentPageRecord: function (key) {
  var isNew = this.IsNewRecord(key);
  if((!this.IsCallbacksEnabled() || this.grid.useEndlessPaging) && isNew)
   return true;
  var keys = isNew ? this.GetCurrentPageInsertedKeys() : this.GetServerRecordKeys();
  return ASPx.Data.ArrayContains(keys, key);
 },
 GetCurrentPageInsertedKeys: function() { return this.currentPageInsertedKeysInfo.map(function(info) { return info.key; }); },
 RemoveInsertedKeyInfo: function(recordKey) {
  ASPx.BatchEditHelper.prototype.RemoveInsertedKeyInfo.call(this, recordKey);
  var index = ASPx.Data.ArrayIndexOf(this.currentPageInsertedKeysInfo, null, function(info) { return this.CompareInsertedRecordKeys(info.key, recordKey); }.bind(this));
  ASPx.Data.ArrayRemoveAt(this.currentPageInsertedKeysInfo, index);
 },
 RecoverRecordCore: function(key) {
  var isPreviewChangesVisible = this.IsChangesViewVisible();
  if(!isPreviewChangesVisible && !this.IsCurrentPageRecord(key))
   return;
  ASPx.BatchEditHelper.prototype.RecoverRecordCore.call(this, key);
  if(isPreviewChangesVisible)
   this.changesViewHelper.ProcessRecoverRecord(key);   
 },
 RemoveItemErrors: function() {
  ASPx.BatchEditHelper.prototype.RemoveItemErrors.call(this);
  this.owner.OnRemoveItemErrors();
 },
 ProcessValidationErrors: function(validationInfo) {
  if(validationInfo && this.IsCallbacksEnabled())
   this.ShowPreviewChanges();
  ASPx.BatchEditHelper.prototype.ProcessValidationErrors.call(this, validationInfo);
  this.owner.OnProcessValidationErrors();
 },
 ProcessCancelEdit: function() {
  if(this.IsChangesViewVisible())
     this.HideChanges();
 },
 CacheServerValue: function(key, columnIndex, value, text) {
  ASPx.BatchEditHelper.prototype.CacheServerValue.call(this, key, columnIndex, value, text);
  var cachedObject = this.savedServerValues[key];
  if(cachedObject)
   cachedObject.visibleIndex = this.grid.ConvertKeyToVisibleIndex(key);
 },
 GetSavedVisibleIndexByKey: function(key) {
  var recordValues = this.savedServerValues[key];
  return recordValues && recordValues.visibleIndex;
 },
 GetSavedKeyByVisibleIndex: function(visibleIndex) {
  var values = this.savedServerValues;
  for(var key in  values) {
   if(!values.hasOwnProperty(key)) continue;
   if(values[key].visibleIndex === visibleIndex)
    return key;
  }
  return null;
 },
 GetDefaultCommandButtonsVisibility: function(recordKey) {
  if(this.IsChangesViewVisible() && (this.HasChanges(recordKey) || this.IsDeletedRecord(recordKey)))
   return false;
  return ASPx.BatchEditHelper.prototype.GetDefaultCommandButtonsVisibility.call(this, recordKey);
 },
 IsUpdateSummariesButtonVisible: function() {
  if(this.IsChangesViewVisible())
   return false;
  return ASPx.BatchEditHelper.prototype.IsUpdateSummariesButtonVisible.call(this);
 },
 ShowPreviewChanges: function(preventValidate) {
  if(!this.changesViewHelper || this.IsChangesViewVisible() || !this.HasChanges())
   return;
  this.changesViewHelper.ShowChanges(preventValidate);
 },
 HideChanges: function() {  
  if(!this.changesViewHelper || !this.IsChangesViewVisible())
   return;
  this.changesViewHelper.HideChanges();
 },
 IsChangesViewVisible: function() {  
  return this.changesViewHelper && this.changesViewHelper.IsChangesViewVisible();
 }, 
 GetSavedDataRowsLayout: function() {
  if(!this.changesViewHelper || !this.IsChangesViewVisible())
   return null;
  return this.changesViewHelper.GetSavedDataRowsLayout();
 },
 UpdateItem: function(recordKey, columnIndices, showEditors, reset, fromAPI) { 
  ASPx.BatchEditHelper.prototype.UpdateItem.call(this, recordKey, columnIndices, showEditors, reset, fromAPI);
  if(this.changesViewHelper && this.IsChangesViewVisible())
   this.changesViewHelper.UpdateRecord(recordKey, showEditors);
 },
 UpdateItemByVI: function(visibleIndex, columnIndices, showEditors, reset, fromAPI) { 
  var recordKey = this.grid.ConvertVisibleIndexToKey(visibleIndex);
  this.UpdateItem(recordKey, columnIndices, showEditors, reset, fromAPI);
 },
 OnAfterCallback: function() {
  var helper = this.changesViewHelper;
  var hasCallbackError = this.HasCallbackError();
  if(helper && !hasCallbackError) {
   if(this.IsChangesViewVisible() && this.owner.IsLastCallbackProcessedAsEndless())
    helper.HideChanges();
   helper.Invalidate();
   this.UpdateSavedRowVisibleIndices();
  }
  ASPx.BatchEditHelper.prototype.OnAfterCallback.call(this);
  if(!hasCallbackError && !this.GetValidationInfo())
   this.currentPageInsertedKeysInfo = [ ];
 },
 OnChildControlEndCallback: function(childControl) {
  if(this.GetTemplateColumnIndices().length > 0) {
   var childControlElement = childControl.GetMainElement();
   var isEditItemTemplateChild = childControlElement && !!ASPx.GetParentByPartialId(childControlElement, "_" + ASPx.GridViewConsts.BatchEditorContainerID);
   if(isEditItemTemplateChild)
    this.focusHelper.LoadActiveElements();
  }
 },
 IsPossibleApplyClientInsertChanges: function() { 
  if(this.IsCallbacksEnabled())
   return this.HasCallbackError() || !!this.GetValidationInfo();
  return ASPx.BatchEditHelper.prototype.IsPossibleApplyClientInsertChanges.call(this);
 },
 GetInfoToApplyClientInsertChanges: function() { 
  if(!this.IsCallbacksEnabled())
   return ASPx.BatchEditHelper.prototype.GetInfoToApplyClientInsertChanges.call(this);
  return this.currentPageInsertedKeysInfo; 
 },
 ShowRecordErrorOnCallbackError: function(key, errorText) {
  var helper = this.changesViewHelper;
  if(helper && !this.IsChangesViewVisible()) {
   helper.Invalidate();
   this.ShowPreviewChanges();
  }
  ASPx.BatchEditHelper.prototype.ShowRecordErrorOnCallbackError.call(this, key, errorText);  
 }, 
 ShowRecordError: function(key, errorText) {
  ASPx.BatchEditHelper.prototype.ShowRecordError.call(this, key, errorText);
  if(this.IsChangesViewVisible() && this.IsCurrentPageRecord(key))
   this.changesViewHelper.AddErrorRowToLayout(key);
 },
 AddInsertedKeyInfo: function(info) { 
  ASPx.BatchEditHelper.prototype.AddInsertedKeyInfo.call(this, info);
  this.currentPageInsertedKeysInfo.push(info);
 },
 OnBeforeStartEditNewRecord: function(newRecordKey) {
  ASPx.BatchEditHelper.prototype.OnBeforeStartEditNewRecord.call(this, newRecordKey);
  if(this.IsChangesViewVisible()) {   
   var helper = this.changesViewHelper;
   helper.AddNewRecordRowsToLayout(newRecordKey);
   helper.ShowRecord(newRecordKey);
   helper.UpdateGroupRowsVisibility();
  }
 },
 SafeRemoveHtmlItem: function(key) {
  if(this.IsChangesViewVisible())
   this.changesViewHelper.ProcessRemoveRecordElements(key);
  ASPx.BatchEditHelper.prototype.SafeRemoveHtmlItem.call(this, key);
 },
 RemoveNewRecord: function (key) {
  ASPx.BatchEditHelper.prototype.RemoveNewRecord.call(this, key);
  if(this.IsChangesViewVisible())
   this.changesViewHelper.UpdateRecord(key);   
 },
 UpdateSavedRowVisibleIndices: function() {
  this.grid.EnsureServerVisibleIndicesHash();
  var keyVisibleIndicesHash = this.grid.serverVisibleIndicesHash;
  var htmlRowKeys = ASPx.GetObjectKeys(keyVisibleIndicesHash);
  var batchStateKeys = ASPx.GetObjectKeys(this.savedServerValues);
  for(var i = 0; i < batchStateKeys.length; i++) {
   var key = batchStateKeys[i];
   if(htmlRowKeys.indexOf(key) > -1)
    this.savedServerValues[key].visibleIndex = keyVisibleIndicesHash[key];
  }
  var otherPageRowKeys = batchStateKeys.filter(function(key) { return htmlRowKeys.indexOf(key) < 0 && !this.IsNewRecord(key); }.bind(this));
  for(var i = 0; i < otherPageRowKeys.length; i++) {
   var key = otherPageRowKeys[i];
   this.savedServerValues[key].visibleIndex = this.maxActualVisibleIndex++;
  }
 },
 ShowInvalidItemsInCallbackMode: function() {
  if(this.changesViewHelper && !this.IsChangesViewVisible())
   this.changesViewHelper.ShowChanges();
 },
 GetRecordKeysForValidation: function(validateOnCurrentPageOnly) { 
  var keys = this.GetRecordKeys();
  if(!validateOnCurrentPageOnly)
   keys = keys.concat(this.GetOtherPagesChangedRecordKeys()); 
  return keys;
 },
 GetOtherPagesChangedRecordKeys: function() {
  var currentPageKeys = this.GetRecordKeys();
  var changedKeys = this.GetChangedRecordKeys();
  return changedKeys.filter(function(key) { return currentPageKeys.indexOf(key) == -1; });
 },
 GetRecoverButtonVisibility: function(recordKey) {   
  if(!ASPx.BatchEditHelper.prototype.GetRecoverButtonVisibility.call(this, recordKey))
   return false;
  return this.GetHighlightDeletedItems() || this.IsChangesViewVisible();
 },
 GetCommandButtonsEnabledState: function(forceEnabled, isOnAfterCallback) { 
  var state = ASPx.BatchEditHelper.prototype.GetCommandButtonsEnabledState.call(this, forceEnabled);
  var isPreviewChangesVisible = this.IsChangesViewVisible();
  state.previewChangesButtonVisible = !isPreviewChangesVisible;
  state.previewChangesButtonChangesCount = this.GetPreviewChangesButtonChangesCount();
  state.previewChangesButtonPreventAnimation = isOnAfterCallback;
  state.hidePreviewButtonVisible = isPreviewChangesVisible;
  return state;
 },
 GetPreviewChangesButtonChangesCount: function() {
  if(!this.IsCallbacksEnabled()) return 0;
  var count = this.GetChangedRecordKeys().length;
  var toogleCheckBoxColumnIndex = this.toogleCheckBoxColumnIndex;
  if(ASPx.IsExists(toogleCheckBoxColumnIndex) && toogleCheckBoxColumnIndex > -1 && this.IsEditing() ) {
   var value = this.GetCellValue(this.editingRecordKey, toogleCheckBoxColumnIndex);
   var editor = this.GetEditor(toogleCheckBoxColumnIndex);
   var valueChanged = !this.AreValuesEqual(value, editor.GetValue(), toogleCheckBoxColumnIndex);
   var modifiedColumns = this.GetModifiedColumnIndices(this.editingRecordKey);
   var hasChanges = modifiedColumns.length > 0;
   var isModifiedOnlyCheckColumn = modifiedColumns.length == 1 && modifiedColumns[0] == toogleCheckBoxColumnIndex;
   if(valueChanged) {
    if(!hasChanges) {
     count++;
    } else if(isModifiedOnlyCheckColumn) {
     count--;
    }
   }
  }
  return count;
 },
 GetModifiedColumnIndices: function(recordKey) {
  var columnIndices = [ ];
  var recordValues = this.GetModifiedValues(recordKey);
  if(recordValues)
   columnIndices = ASPx.GetObjectKeys(recordValues);
  return columnIndices;
 },
 UpdateRecordInChangesPreview: function(visibleIndex) {
  if(!this.IsChangesViewVisible()) return;
  var key = this.grid.ConvertVisibleIndexToKey(visibleIndex);
  if(ASPx.IsExists(key))
   this.changesViewHelper.UpdateRecordRowsInLayout(key);
 },
 UpdateChangesPreviewOnHierarchyChange: function(layoutRows) {
  if(!layoutRows || !this.IsChangesViewVisible()) return;
  this.changesViewHelper.UpdateLayoutWithRelatedRows(layoutRows);
 }
});
var GridViewBatchEditChangesPreviewHelper = ASPx.CreateClass(null, {
 InsertedGroupRowIndex: 0,
 UpdatedGroupRowIndex: 1,
 DeletedGroupRowIndex: 2,
 PreviewChangesCreatedCellClass: "dxgvBECPCC",
 constructor: function(batchEditHelper) {
  this.batchEditHelper = batchEditHelper;
  this.grid = this.batchEditHelper.GetOwnerControl();
  this.changesViewInfo = { };
  this.savedScrollTop = -1;
 },
 Invalidate: function() { 
  this.changesViewInfo = { };
  this.savedScrollTop = -1;
  this.ChangeViewVisibilityState(false);
 },
 IsInsertedRecord: function(key) { return this.batchEditHelper.IsNewRecord(key); },
 IsUpdatedRecord: function(key) { return this.batchEditHelper.IsUpdatedRecord(key); },
 IsDeletedRecord: function(key) { return this.batchEditHelper.IsDeletedRecord(key); },
 IsInvalidRecord: function(key) { return this.batchEditHelper.GetInvalidRecordKeys().indexOf(key) !== -1; },
 GetChangedRecordKeys: function() { return this.batchEditHelper.GetChangedRecordKeys(); },
 GetVisibleColumnIndices: function() { return this.batchEditHelper.GetVisibleColumnIndices(); },
 GetBatchEditHelperOwner: function() { return this.batchEditHelper.owner; },
 GetEtalonDataRows: function() { return this.GetBatchEditHelperOwner().GetEtalonNewBandedRows(); },
 GetEtalonRecordPostFix: function () { return this.GetBatchEditHelperOwner().GetEtalonRecordPostFix(); },
 GetVisibleIndexByKey: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 GetCurrentPageVisibleIndices: function() { return this.grid.GetCurrentPageIndices(); },
 IsChangesViewVisible: function() { return ASPx.ElementHasCssClass(this.grid.GetGridTD(), ASPx.GridViewConsts.BatchEditChangesPreviewClassName); },
 ChangeViewVisibilityState: function (visible) {
  ASPx.ToggleClassNameToElement(this.grid.GetGridTD(), ASPx.GridViewConsts.BatchEditChangesPreviewClassName, visible);
 },
 HasChanges: function(key) { return this.batchEditHelper.HasChanges(key) || this.IsDeletedRecord(key); }, 
 ConvertKeyToVisibleIndex: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 GetLayoutHelper: function() { return this.grid.GetLayoutHelper(); },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 UpdateRecord: function(recordKey, showEditors) {
  if(!this.IsChangesViewVisible() || showEditors)
   return;
  var hasChanges = this.HasChanges(recordKey);
  var recordRows = this.GetRecordRows(recordKey);
  var isVisible = recordRows.length > 0 && !recordRows.some(function(row) { return ASPx.ElementHasCssClass(row, ASPx.GridViewConsts.BatchEditHiddenItemClassName); });
  if(hasChanges){
   if(!isVisible)
    this.ShowRecord(recordKey);
  } else {
   if(isVisible)
    this.HideRecord(recordKey);
  }
  if(!this.batchEditHelper.HasChanges())
   this.HideChanges();
  this.UpdateGroupRowsVisibility();
 },
 ShowRecord: function(key) {
  var recordRows = this.GetRecordRows(key);
  if(recordRows.length === 0) {
   recordRows = this.CreateDataRowsCore(key);
   this.PrepareCreatedRows(recordRows, key);
  } else
   this.PlaceRecordRowsInView(recordRows, key);
  if(this.IsDeletedRecord(key))
   this.UpdateCurrentPageDeletedRecordInHiddenMode(key, recordRows, true, true);
  recordRows.forEach(function(row) { this.ChangeElementVisibility(row, true); }.bind(this));
  this.SeparateMergedCellsForPreview(key);
  this.UpdateRecordCommandButtonsVisibility(key);
 },
 HideRecord: function(key) {
  var recordRows = this.GetRecordRows(key);
  recordRows.forEach(function(row) { 
   this.ChangeElementVisibility(row); 
   this.RemoveRowFromViewInfo(row);
  }.bind(this));
  if(this.IsDeletedRecord(key))
   this.UpdateCurrentPageDeletedRecordInHiddenMode(key, recordRows);
  this.UpdateRecordCommandButtonsVisibility(key);
  this.RestoreMergedCells(key);
 },
 SeparateMergedCellsForPreview: function(key) {
  var layoutHelper = this.GetLayoutHelper();
  if(!layoutHelper.HasCellMerging()) return;
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  var columnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   if(!layoutHelper.IsMergedCell(visibleIndex, columnIndex)) continue;
   if(layoutHelper.IsMergedCellFirstRow(visibleIndex, columnIndex)) {
    ASPx.Attr.ChangeAttribute(layoutHelper.GetDataCell(visibleIndex, columnIndex), "rowSpan", 1);
   } else {    
    var pos = this.GetCellPositionInLayout(columnIndex);
    if(pos.levelIndex > -1 && pos.cellIndex > -1) {
     var cell = this.CreateCellFromEtalon(pos, columnIndex);
     var row = layoutHelper.GetRow(visibleIndex, pos.levelIndex, ASPx.GridViewRowType.Data);
     this.InsertCell(cell, row, pos.cellIndex);     
    }
   }
  }
  this.batchEditHelper.UpdateItem(key, this.batchEditHelper.GetEditColumnIndices());
 },
 CreateCellFromEtalon: function(layoutPosition, columnIndex) {
  var etalonRows = this.GetEtalonDataRows();
  var etlalonRow = etalonRows[layoutPosition.levelIndex];
  var etalonCell = etlalonRow.cells[layoutPosition.cellIndex];
  var cell = etalonCell.cloneNode();
  ASPx.AddClassNameToElement(cell, this.PreviewChangesCreatedCellClass);
  cell.columnIndex = columnIndex; 
  return cell; 
 },
 InsertCell: function(cell, row, cellIndex) {
  if(!cell || !row) return;
  if(cellIndex === 0)
   row.insertBefore(cell, row.cells[0]);
  else
   ASPx.InsertElementAfter(cell, row.cells[cellIndex - 1]);
 },
 GetCellPositionInLayout: function(columnIndex) {
  var layout = this.GetLayoutHelper().GetEtalonDataRowLayout();
  return this.GetColumnHelper().FindColumnLayoutPos(layout, columnIndex);
 },
 RestoreMergedCells: function(key) {
  var layoutHelper = this.GetLayoutHelper();
  if(!layoutHelper.HasCellMerging()) return;
  this.GetRecordRows(key).forEach(function(row) { this.RemoveCellsCreatedInPreview(row); }.bind(this));
  var visibleIndex = this.ConvertKeyToVisibleIndex(key);
  var columnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var needRestoreCellRowSpan = layoutHelper.IsMergedCell(visibleIndex, columnIndex) && layoutHelper.IsMergedCellFirstRow(visibleIndex, columnIndex);
   if(needRestoreCellRowSpan) 
    ASPx.Attr.RestoreAttribute(layoutHelper.GetDataCell(visibleIndex, columnIndex), "rowSpan");
  }
 },
 RemoveCellsCreatedInPreview: function(row) {
  var cellsToDelete = ASPx.GetNodesByPartialClassName(row, this.PreviewChangesCreatedCellClass);
  for(var j = 0; j < cellsToDelete.length; j++)
   row.removeChild(cellsToDelete[j]);
 },
 UpdateCurrentPageDeletedRecordInHiddenMode: function (key, recordRows, applyDeletedStyle, visible) {
  var helper = this.batchEditHelper;
  if(helper.GetHighlightDeletedItems() || !helper.IsCurrentPageRecord(key))
   return;
  var batchEditHelperOwner = this.GetBatchEditHelperOwner();
  batchEditHelperOwner.ChangeRowsDeletedStyle(recordRows, !applyDeletedStyle);
  batchEditHelperOwner.ChangeDeletedRowsVisibility(recordRows, visible);  
 },
 UpdateRecordCommandButtonsVisibility: function(key) { this.batchEditHelper.UpdateRecordCommandButtonsVisibility(key); },
 GetRecordRows: function(key, skipErrorRow) { 
  var visibleIndex = this.GetVisibleIndexByKey(key);
  return this.GetRecordRowsByVI(visibleIndex, skipErrorRow);
 },
 GetRecordRowsByVI: function (visibleIndex, skipErrorRow){
  var grid = this.grid;
  var rows = grid.GetBandedDataRows(visibleIndex);
  var adaptiveDetailRow = grid.GetAdaptiveDetailRow(visibleIndex);
  if(adaptiveDetailRow)
   rows.push(adaptiveDetailRow);
  var errorRow = grid.GetEditingErrorItem(null, visibleIndex);
  if(errorRow && !skipErrorRow)
   rows.push(errorRow);
  return rows;
 },
 CreateDataRowsCore: function(key) {
  var visibleIndex = this.GetVisibleIndexByKey(key);
  var owner = this.GetBatchEditHelperOwner();
  var newItem = owner.CreateNewItemElementCore(visibleIndex);
  owner.AssignNewItemId(newItem, visibleIndex);
  var rows = newItem instanceof Array ? newItem : [ newItem ]; 
  return rows;
 },
 PrepareCreatedRows: function(recordRows, key) {
  this.PlaceRecordRowsInView(recordRows, key);
  var grid = this.grid;
  recordRows.forEach(function(row) { 
   row.dxGridBatchCHangesViewCreatedRow = true;
   var commandCells = ASPx.GetChildNodesByPartialClassName(row, ASPx.GridViewConsts.CommandColumnCellCssClass);
   commandCells.forEach(function(cell) { ASPx.SetInnerHtml(cell, ""); });
   ASPx.SetElementDisplay(row, true);
   var adaptiveExpandButtonCell = ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
   if(adaptiveExpandButtonCell) 
    grid.PrepareCommandButtonsIDList(adaptiveExpandButtonCell);  
  }.bind(this));
  grid.PrepareCommandButtons();
  if(this.IsDeletedRecord(key)) {
   this.PrepareDeletedRecord(key);
   this.ApplyDeletedRecordStyle(recordRows);
  } 
  if(this.IsInsertedRecord(key))
   this.ApplyInsertedRecordStyle(recordRows);
  var helper = this.batchEditHelper;
  if(!helper.IsCurrentPageRecord(key))
   this.PrepareNonEditableCells(key, helper.GetVisibleNonEditableDataColumnIndices());
  helper.UpdateItem(key, helper.GetEditColumnIndices());
  helper.ApplyValidationInfo(key, helper.ValidateItem(key, null, true));
 },
 PrepareNonEditableCells: function(key, columnIndices) {
  var helper = this.batchEditHelper;
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var text = helper.GetCachedNonEditableDataColumnsText(key, columnIndex);
   if(text) {
    var textContainer = helper.GetCellTextContainer(key, columnIndex);
    ASPx.SetInnerHtml(textContainer, text);
   }
  }
 },
 PrepareDeletedRecord: function (key) {
  this.batchEditHelper.PrepareCommandButtonsForDeletedItem(key);
 },
 ApplyDeletedRecordStyle: function(rows) {
  this.GetBatchEditHelperOwner().ChangeRowsDeletedStyle(rows);   
 }, 
 ApplyInsertedRecordStyle: function(rows) {
  rows.forEach(function(row) { this.GetBatchEditHelperOwner().ApplyNewRowStyle(row); }.bind(this));
 },
 ChangeRecordCommandButtonsVisibility: function (key, visible) {   
  var buttons = this.GetBatchEditHelperOwner().GetRecordCommandButtons(key);
   buttons.forEach(function(button) {
   if(button)
    button.SetVisible(visible);
  }.bind(this));
 },
 PlaceRecordRowsInView: function (rows, key) {
  var target = this.GetRecordRowsTargetRow(key);
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   ASPx.InsertElementAfter(row, target);
   this.UpdateViewInfo(key, row);
   target = row;
  }
 },
 ProcessRecoverRecord: function (key) {
  var recordHasChanges = this.IsInsertedRecord(key) || this.IsUpdatedRecord(key);
  this.UpdateCurrentPageDeletedRecordInHiddenMode(key, this.GetRecordRows(key), false, true);
  if(!recordHasChanges)
   this.UpdateRecord(key);
  else {
   this.PlaceRecordRowsInView(this.GetRecordRows(key), key);
  }
  this.UpdateGroupRowsVisibility();
 },
 UpdateViewInfo: function(key, row) {
  this.RemoveRowFromViewInfo(row);
  var infoKey = this.GetViewInfoKey(key);
  if(!infoKey) return;
  if(!this.changesViewInfo[infoKey])
   this.changesViewInfo[infoKey] = [ ];
  this.changesViewInfo[infoKey].push(row);
 },
 RemoveRowFromViewInfo: function(row) {
  var keys = [ "deleted", "new", "updated"];  
  keys.forEach(function(key) { 
   var info = this.changesViewInfo[key];
   if(info)
    ASPx.Data.ArrayRemove(info, row);
  }.bind(this));
 },
 GetViewInfoKey: function(key) {
  if(this.IsDeletedRecord(key))
   return "deleted";
  if(this.IsInsertedRecord(key))
   return "new";
  if(this.IsUpdatedRecord(key))
   return "updated";
 }, 
 GetRecordRowsTargetRow: function(key) {
  var infoKey = this.GetViewInfoKey(key);
  var rows = this.changesViewInfo[infoKey];
  if(rows && rows.length > 0)
   return rows[rows.length - 1];
  if(this.IsDeletedRecord(key))
   return this.GetDeletedGroupRow();
  if(this.IsInsertedRecord(key))
   return this.GetInsertedGroupRow();
  if(this.IsUpdatedRecord(key) || this.IsInvalidRecord(key))
   return this.GetUpdatedGroupRow();
  return this.GetEtalonDataRows()[0];
 }, 
 ProcessRemoveRecordElements: function (key) {
  var isNewRecord = this.IsInsertedRecord(key);
  this.GetRecordRows(key).forEach(function(row) { 
   this.RemoveRowFromViewInfo(row); 
   if(isNewRecord)
    this.RemoveRowFromLayout(row);
  }.bind(this));
 },
 ChangeElementVisibility: function(element, visible) {
  var styleHelper = this.grid.GetStyleHelper();
  var classNameAction = visible ? styleHelper.RemoveClassFromElement : styleHelper.AddClassToElement;
  classNameAction.call(styleHelper, element, ASPx.GridViewConsts.BatchEditHiddenItemClassName);
 },
 ShowChanges: function(preventValidate) {
  if(this.RaiseBatchEditChangesPreviewShowing())
   return;
  var grid = this.grid;
  this.savedScrollTop = grid.GetVerticalScrollPosition();
  this.ResetAdaptivity(); 
  this.MoveDataTableToScrollDivIfRequired();
  this.ChangeGridRowsVisibility();
  this.ShowUnsavedChangesAndInvalidRows();
  grid.GetNavigationHelper().Invalidate();
  this.batchEditHelper.UpdateCommandButtonsEnabled();
  if(!preventValidate)
   this.batchEditHelper.ValidateItems();
  this.CalculateAdaptivity();
  grid.UpdateFirstAndLastVisibleRowMarkers();
  this.UpdateToolbarItemsVisibility(true);
  this.RaiseBatchEditChangesPreviewShown();
 },
 RaiseBatchEditChangesPreviewShowing: function() { return this.grid.RaiseBatchEditChangesPreviewShowing(); },
 RaiseBatchEditChangesPreviewShown: function() { return this.grid.RaiseBatchEditChangesPreviewShown(); },
 HideChanges: function() {
  var grid = this.grid;
  this.ResetAdaptivity();
  this.MoveDataTableFromScrollDivIfRequired();
  this.HideUnsavedChanges();
  this.ChangeGridRowsVisibility(true);
  this.RestoreGridDataRowsLayout();
  this.changesViewInfo = { };
  grid.GetNavigationHelper().Invalidate();
  this.batchEditHelper.UpdateCommandButtonsEnabled();
  this.CalculateAdaptivity();
  this.UpdateToolbarItemsVisibility(false);
  grid.UpdateFirstAndLastVisibleRowMarkers();
  grid.UpdateScrollableControls();
  grid.SetVerticalScrollPosition(this.savedScrollTop);
 },
 ResetAdaptivity: function() {
  var adaptivityHelper = this.grid.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.ResetAdaptivity();
 },
 CalculateAdaptivity: function() {
  var adaptivityHelper = this.grid.GetAdaptivityHelper();
  if(adaptivityHelper)
   adaptivityHelper.CalculateAdaptivity(true);
 },
 ChangeGridRowsVisibility: function(visible) {
  var rows = this.grid.GetLayoutHelper().GetGridElementsToChangeVisibilityInBatchChangesView();
  rows = rows.filter(function(row) { return !row.dxGridBatchCHangesViewCreatedRow; });
  rows.forEach(function(row) {
   this.ChangeElementVisibility(row, visible); 
  }.bind(this));
 },
 UpdateToolbarItemsVisibility: function(previewVisible) {
  var helper = this.grid.GetToolbarHelper();
  if(helper)
   helper.UpdateItemsOnBatchPreviewVisibilityChange(previewVisible);
 },
 ShowUnsavedChangesAndInvalidRows: function () {
  this.ChangeViewVisibilityState(true);
  this.UpdateGroupRowsVisibility();
  this.SaveGridDataRowsLayout();
  var recordsToShowKeys = this.GetChangedRecordKeys();
  recordsToShowKeys = recordsToShowKeys.concat(this.batchEditHelper.GetInvalidRecordKeys());
  for(var i = 0; i < recordsToShowKeys.length; i++)
   this.ShowRecord(recordsToShowKeys[i]);
 },  
 MoveDataTableToScrollDivIfRequired: function() {
  if(!this.RequireMoveDataTableToScrollDiv())
   return;
  var grid = this.grid;
  var dataTable = grid.GetMainTable();
  var scrollDiv = ASPx.GetChildByPartialClassName(this.GetPreviewChangesScrollDivContainer(), ASPx.GridViewConsts.BatchEditChangesPreviewScrollDivClassName);
  if(!scrollDiv) {
   scrollDiv = document.createElement("div");
   ASPx.AddClassNameToElement(scrollDiv, ASPx.GridViewConsts.BatchEditChangesPreviewScrollDivClassName);
   dataTable.parentNode.insertBefore(scrollDiv, dataTable);   
  }
  ASPx.Attr.SetAttribute(scrollDiv.style, "height", this.GetPreviewChangesScrollDivHeight() + "px"); 
  ASPx.ChangeElementContainer(dataTable, scrollDiv);
  this.ChangeElementVisibility(scrollDiv, true);
 },
 GetPreviewChangesScrollDivContainer: function() {
  return this.grid.GetGridTD();
 },
 GetPreviewChangesScrollDivHeight: function() {
  var grid = this.grid;
  var height = ASPx.GetClearClientHeight(grid.GetMainElement());
  var statusBar = grid.GetStatusBar();
  if(statusBar)
   height -= ASPx.GetClearClientHeight(statusBar);
  return height;
 },
  MoveDataTableFromScrollDivIfRequired: function() {
  if(!this.RequireMoveDataTableToScrollDiv())
   return;
  var grid = this.grid;
  var dataTable = grid.GetMainTable();
  var scrollDiv = ASPx.GetChildByPartialClassName(this.GetPreviewChangesScrollDivContainer(), ASPx.GridViewConsts.BatchEditChangesPreviewScrollDivClassName);
  if(scrollDiv && dataTable) {
   ASPx.InsertElementAfter(dataTable, scrollDiv);
   this.ChangeElementVisibility(scrollDiv, false);
  }
 },
 RequireMoveDataTableToScrollDiv: function() { return !this.grid.HasScrolling() && !ASPx.Browser.MobileUI; },
 GetSavedDataRowsLayout: function() {
  return this.changesViewInfo.savedLayout || null;
 },
 SaveGridDataRowsLayout: function() {  
  var rows = this.grid.GetMainTable().rows;
  this.changesViewInfo.savedLayout = ASPx.NodeListToArray(rows);
 },
 RestoreGridDataRowsLayout: function() {
  if(!this.changesViewInfo.savedLayout)
   return;
  var layout = this.changesViewInfo.savedLayout;
  var table = this.grid.GetMainTable();
  layout = layout.filter(function(row) { return ASPx.GetIsParent(table, row); });
  for(var i = 0; i < layout.length; i++)
   this.RestoreGridRowInTable(table, layout[i], i > 0 ? layout[i - 1] : null);
  delete this.changesViewInfo.savedLayout;
 },
 RestoreGridRowInTable: function(table, row, previousRow) {
  var isCorrectPosition = previousRow ? previousRow.nextSibling === row : table.rows[0] === row;
  if(!isCorrectPosition) {
   if(previousRow)
    ASPx.InsertElementAfter(row, previousRow);
   else
    table.insertBefore(row, table.rows[0]);
  }
 },
 RemoveRowFromLayout: function(row) {
  if(this.changesViewInfo.savedLayout)
     ASPx.Data.ArrayRemove(this.changesViewInfo.savedLayout, row);
 },
 AddNewRecordRowsToLayout: function (key) {
  var rows = this.GetRecordRows(key);
  var layout = this.changesViewInfo.savedLayout;
  if(!layout || rows.length === 0) return;
  var isNewRecordOnTop = this.batchEditHelper.IsNewItemOnTop();
  var insertedKeys = this.batchEditHelper.GetInsertedRecordKeys();
  var index = insertedKeys.indexOf(key);  
  var refRows = index > 0 ? this.GetRecordRows(insertedKeys[index - 1]) : this.GetEtalonDataRows();
  var refRow = isNewRecordOnTop ? refRows[0] : refRows[refRows.length - 1];
  var layoutIndex = layout.indexOf(refRow);
  if(!isNewRecordOnTop)
   layoutIndex++;
  layout.splice.apply(layout, [layoutIndex, 0].concat(rows));
 },
 AddErrorRowToLayout: function(key) {
  var rows = this.GetRecordRows(key, true);
  var layout = this.changesViewInfo.savedLayout;
  var visibleIndex = this.GetVisibleIndexByKey(key);
  var errorRow = this.grid.GetEditingErrorItem(null, visibleIndex);
  if(!errorRow || rows.length === 0 || !layout)
   return;  
  ASPx.Data.ArrayRemove(layout, errorRow);
  var layoutIndex = layout.indexOf(rows[rows.length - 1]);
  if(layoutIndex > -1)
   ASPx.Data.ArrayInsert(layout, errorRow, layoutIndex + 1);
 },
 UpdateRecordRowsInLayout: function(key) {
  this.UpdateLayoutWithRelatedRows(this.GetRecordRows(key));  
 },
 UpdateLayoutWithRelatedRows: function(rows) {
  var layout = this.changesViewInfo.savedLayout;
  if(!layout || rows.length === 0) return;
  var lastIndexInLayout = -1;
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   if(ASPx.Data.ArrayContains(layout, row))
    lastIndexInLayout = layout.indexOf(row);
   else if(lastIndexInLayout > -1)
    ASPx.Data.ArrayInsert(layout, row, ++lastIndexInLayout);
  }
 },
 UpdateGroupRowsVisibility: function() {
  visible = this.IsChangesViewVisible();
  var keys = this.GetChangedRecordKeys();
  var insertedCount = keys.filter(this.IsInsertedRecord.bind(this)).length;
  var updatedCount = keys.filter(this.IsUpdatedRecord.bind(this)).length;
  var deletedCount = keys.filter(this.IsDeletedRecord.bind(this)).length;
  this.ChangeElementVisibility(this.GetInsertedGroupRow(), visible && insertedCount > 0);
  this.ChangeElementVisibility(this.GetUpdatedGroupRow(), visible && updatedCount > 0);
  this.ChangeElementVisibility(this.GetDeletedGroupRow(), visible && deletedCount > 0);
 },
 GetInsertedGroupRow: function() {  return this.GetCategoryRow(this.InsertedGroupRowIndex);  },
 GetUpdatedGroupRow: function() {  return this.GetCategoryRow(this.UpdatedGroupRowIndex);  },
 GetDeletedGroupRow: function() {  return this.GetCategoryRow(this.DeletedGroupRowIndex);  },
 GetCategoryRow: function(index) { return this.grid.GetBatchChangesPreviewGroupRow(index); },
 HideUnsavedChanges: function () {
  this.ChangeViewVisibilityState(false);
  this.UpdateGroupRowsVisibility();
  var rowsToHideKeys = this.GetChangedRecordKeys();
  rowsToHideKeys = rowsToHideKeys.concat(this.batchEditHelper.GetInvalidRecordKeys());
  for(var i = 0; i < rowsToHideKeys.length; i++)
   this.HideRecord(rowsToHideKeys[i]);
 }
});
var GridBatchEditUpdateWatcherHelper = ASPx.CreateClass(ASPx.BatchEditUpdateWatcherHelper, {
 GridFuncCallbackWaitingTimeout: 15,
 IsControlFuncCallback: function(dxCallbackOwner) {
  var grid = this.GetControl();
  return dxCallbackOwner === grid && grid.GetCallbackHelper().HasWaitedFuncCallbacksFromInterval(this.GridFuncCallbackWaitingTimeout);
 }
});
ASPx.GridBatchEditFocusHelper = GridBatchEditFocusHelper;
ASPx.GridViewBatchEditFocusHelper = GridViewBatchEditFocusHelper;
ASPx.CardViewBatchEditFocusHelper = CardViewBatchEditFocusHelper;
ASPx.GridViewBatchEditChangesPreviewHelper = GridViewBatchEditChangesPreviewHelper;
ASPx.GridViewBatchEditHelperOwner = GridViewBatchEditHelperOwner;
ASPx.CardViewBatchEditHelperOwner = CardViewBatchEditHelperOwner;
ASPx.VerticalGridBatchEditHelperOwner = VerticalGridBatchEditHelperOwner;
ASPx.GridBatchEditHelper = GridBatchEditHelper;
})();

(function() {
var TableNavigationHelper = ASPx.CreateClass(null, { 
 constructor: function(owner) {
  this.owner = owner;
  this.layoutMatrix = null;
  this.savedPos = null;
 },
 IsDeletedItem: function(recordKey)  { },
 Invalidate: function() { 
  this.layoutMatrix = null;
  this.savedPos = null;
 },
 GetRecordKeys: function() { return this.owner.GetRecordKeys(); },
 GetFirstRecordKey: function() { return this.GetRecordKeys()[0]; },
 GetBatchEditHelper: function() { return this.owner.GetBatchEditHelper(); },
 GetRecoverButtonColumnIndex: function() {
  var helper = this.GetBatchEditHelper();
  return helper && helper.GetRecoverButtonColumnKey();
 },
 EnsureLayoutMatrix: function() {
  if(!this.layoutMatrix) {
   this.layoutMatrix = [ ];
   this.PopulateLayoutMatrix();
  }
 },
 PopulateLayoutMatrix: function() {
  var keys = this.GetRecordKeys();
  for(var i = 0; i < keys.length; i++) {
   var info = this.CreateItemMatrixInfo(keys[i]);
   this.InsertItemSubMatrix(info);
  }
 },
 CreateItemMatrixInfo: function(key) {
  var matrix = this.CreateItemMatrix(key);
  var rect = this.CalcMatrixRect(key);
  return { matrix: matrix, rect: rect };
 },
 CreateItemMatrix: function(key) { 
  if(this.IsDeletedItem(key) && !this.owner.accessibilityCompliant)
   return this.CreateDeletedItemMatrix(key);
  return this.CreateItemMatrixCore(key);
 },
 CreateDeletedItemMatrix: function(key) { },
 CreateItemMatrixCore: function(key) { },
 CalcMatrixRect: function(key) { 
  var width = this.GetItemMatrixWidth(key);
  var height = this.GetItemMatrixHeight(key);
  var x = this.GetItemMatrixRectLeft(key);
  var y = this.GetItemMatrixRectTop(key);
  return { 
   top: y,
   bottom: y + height - 1,
   left:   x,
   right:  x + width - 1
  };
 },
 GetItemMatrixWidth: function(key) { },
 GetItemMatrixHeight: function(key) { },
 GetItemMatrixRectLeft: function(matrix, key) { },
 GetItemMatrixRectTop: function(matrix, key) { },
 InsertItemSubMatrix: function(info) {
  var subMatrix = info.matrix;
  var rect = info.rect;
  for(var i = rect.top; i <= rect.bottom; i++) {
   if(!this.layoutMatrix[i])
    this.layoutMatrix[i] = [ ];
   for(var j = rect.left; j <= rect.right; j++) {
    this.layoutMatrix[i][j] = subMatrix[i - rect.top][j - rect.left];
   }
  }
 },
 CreateMatrixElement: function(recordKey, columnIndex) { return { recordKey: recordKey, columnIndex: columnIndex }; },
 GetNavigationCellInfo: function(info, inc, isVert) {
  this.EnsureLayoutMatrix();
  var pos = this.savedPos;
  if(!pos || !this.IsInfoEqual(this.GetMatrixInfo(pos), info))
   pos = this.ResolvePos(info);
  var newPos = this.GetNavigationPos(pos, inc, isVert);
  if(newPos)
   this.savedPos = newPos;
  return this.GetMatrixInfo(newPos);
 },
 GetNavigationPos: function(pos, inc, isVert) {
  var height = this.layoutMatrix.length;
  if(height === 0)
   return null;
  var width = this.layoutMatrix[0].length;
  var newPos = { x: pos.x, y: pos.y };
  var key = isVert ? "y" : "x";
  while(this.IsInfoEqualOnPos(pos, newPos)) {
   newPos[key] += inc;
   if(newPos.x < 0 || newPos.x >= width) {
    newPos.y += inc;
    newPos.x = inc > 0 ? 0 : width - 1;
   } else if(newPos.y < 0 || newPos.y >= height) {
    newPos.x += inc;
    newPos.y = inc > 0 ? 0 : height - 1;
   }
   if(newPos.x < 0 || newPos.x >= width || newPos.y < 0 || newPos.y >= height)
    return null;
  }
  return newPos;
 },
 IsInfoEqualOnPos: function(pos1, pos2) { 
  return this.IsInfoEqual(this.GetMatrixInfo(pos1), this.GetMatrixInfo(pos2));
 },
 IsInfoEqual: function(info1, info2) {
  return info1 && info2 && info1.columnIndex === info2.columnIndex && info1.recordKey === info2.recordKey;
 },
 GetMatrixInfo: function(pos) {
  if(pos) {
   var row = this.layoutMatrix[pos.y];
   if(row)
    return row[pos.x];
  }
  return null;
 },
 ResolvePos: function(info) {
  for(var i = 0; i < this.layoutMatrix.length; i++) {
   var row = this.layoutMatrix[i];
   for(var j = 0; j < row.length; j++) {
    if(this.IsInfoEqual(row[j], info))
     return { x: j, y: i };
   }
  }
  return { x: 0, y: 0 };
 },
 ResolveLastPos: function(info) {
  for(var i = this.layoutMatrix.length - 1; i >= 0; i--) {
   var row = this.layoutMatrix[i];
   for(var j = row.length - 1; j >= 0; j--) {
    if(this.IsInfoEqual(row[j], info))
     return { x: j, y: i };
   }
  }
  return { x: 0, y: 0 };
 },
 GetFirstCellInfo: function() {
  this.EnsureLayoutMatrix();
  var pos = { x: 0, y: 0 };
  return this.GetMatrixInfo(pos);
 },
 GetLastCellInfo: function() {
  this.EnsureLayoutMatrix();
  var matrix = this.layoutMatrix;
  var pos = {
   x: matrix[0].length - 1,
   y : matrix.length - 1
  };
  return this.GetMatrixInfo(pos);
 },
 GetSelectionCellsInfo: function(firstCell, secondCell) {
  this.EnsureLayoutMatrix();
  var keys = this.GetRecordKeys();
  var isFirstCellHigher = ASPx.Data.ArrayIndexOf(keys, firstCell.recordKey) < ASPx.Data.ArrayIndexOf(keys, secondCell.recordKey);
  var firstPos = isFirstCellHigher ? this.ResolvePos(firstCell) : this.ResolveLastPos(firstCell);
  var secondPos = !isFirstCellHigher ? this.ResolvePos(secondCell) : this.ResolveLastPos(secondCell);
  var x = [ firstPos.x, secondPos.x ].sort(function(a, b) { return a - b; });
  var y = [ firstPos.y, secondPos.y ].sort(function(a, b) { return a - b; });
  return this.layoutMatrix.slice(y[0], y[1] + 1).map(function(row) { return row.slice(x[0], x[1] + 1); });
 },
 CreateEmptyMatrix: function(rowCount) { return ASPx.Data.Range(rowCount).map(function() { return [ ]; }); },
 JoinMatrices: function(matrices, maxWidth) {
  for(var i = 0; i < matrices.length; i++)
   matrices[i] = this.AdjustMatrix(matrices[i], maxWidth);
  var result = [ ];
  for(var i = 0; i < matrices.length; i++)
   result = result.concat(matrices[i]);
  return result;
 },
 AdjustMatrix: function(matrix, maxWidth) {
  var width = matrix[0].length;
  if(width >= maxWidth)
   return matrix;
  var newMatrix = [ ];
  for(var i = 0; i < matrix.length; i++) {
   var newRow = [ ];
   var row = matrix[i];
   var newRowWidth = maxWidth;
   for(var j = 0; j < row.length; j++) {
    var cell = row[j];
    var factor = Math.ceil(newRowWidth / (row.length - j));
    for(var k = 0; k < factor; k++)
     newRow.push(cell);
    newRowWidth -= factor;
   }
   newMatrix.push(newRow);
  }
  return newMatrix;
 },
 FillMatrixRect: function(matrix, rect, element) {
  for(var i = rect.top; i <= rect.bottom; i++) {
   while(!matrix[i])
    matrix.push([ ]);
   for(var j = rect.left; j <= rect.right; j++)
    matrix[i][j] = element;
  }
 },
 FindFreeCellIndex: function(matrix, rowIndex) {
  var row = matrix[rowIndex];
  var index = 0;
  if(row) {
   while(row[index])
    index++;
  }
  return index;
 }
});
var GridNavigationHelper = ASPx.CreateClass(TableNavigationHelper, { 
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.grid = this.owner;
 },
 IsDeletedItem: function(recordKey)  { return this.grid.IsBatchEditDeletedItem(this.ConvertKeyToVisibleIndex(recordKey)); },
 ConvertKeyToVisibleIndex: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 ConvertVisibleIndexToKey: function(visibleIndex) { return this.grid.ConvertVisibleIndexToKey(visibleIndex); },
});
var GridViewNavigationHelper = ASPx.CreateClass(GridNavigationHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.maxMatrixWidth = -1;
 },
 Invalidate: function() { 
  GridNavigationHelper.prototype.Invalidate.call(this);
  this.maxMatrixWidth = -1;
 },
 GetLayoutHelper: function() { return this.grid.GetLayoutHelper(); },
 AreDataRowsHidden: function() { return this.GetLayoutHelper().AreDataRowsHidden(); },
 GetDataRowLayout: function(recordKey) { return this.GetLayoutHelper().GetAdaptiveRowLayoutInfo(this.ConvertKeyToVisibleIndex(recordKey)).dataRowLayout; },
 GetAdaptiveRowLayout: function(recordKey) { return this.GetLayoutHelper().GetAdaptiveRowLayoutInfo(this.ConvertKeyToVisibleIndex(recordKey)).adaptiveRowLayout; },
 GetRecordKeys: function() { return this.grid.GetRecordKeysForNavigation(); },
 CreateMatrixElement: function(recordKey, columnIndex) { 
  var visibleIndex = this.GetLayoutHelper().ResolveMergedCellVisibleIndexForNavigation(this.ConvertKeyToVisibleIndex(recordKey), columnIndex);
  return GridNavigationHelper.prototype.CreateMatrixElement.call(this, this.ConvertVisibleIndexToKey(visibleIndex), columnIndex);
 },
 CreateItemMatrixCore: function(key) {
  var dataRowLayout = this.GetDataRowLayout();
  var adaptiveRowLayout = this.GetAdaptiveRowLayout(key);
  var matrices = [
   this.CreateItemMatrixByLayout(dataRowLayout, key),
   this.CreateItemMatrixByLayout(adaptiveRowLayout, key),
  ];
  return this.JoinMatrices(matrices.filter(function(m) { return m && m.length > 0 && m[0]; }), this.GetMaxMatrixWidth());
 },
 GetMaxMatrixWidth: function() {
  if(this.maxMatrixWidth < 0)
   this.maxMatrixWidth = this.GetRecordKeys().reduce(function(prevValue, key) { return Math.max(prevValue, this.GetItemMatrixWidth(key)); }.bind(this), 0);
  return this.maxMatrixWidth;
 },
 GetItemMatrixWidth: function(recordKey) { 
  return Math.max(this.GetRowMatrixWidth(recordKey, false), this.GetRowMatrixWidth(recordKey, true));
 },
 GetItemMatrixHeight: function(recordKey) {
  return this.GetRowMatrixHeight(recordKey, false) + this.GetRowMatrixHeight(recordKey, true);
 },
 GetRowMatrixWidth:function(recordKey, isAdaptive) {
  var layout = isAdaptive ? this.GetAdaptiveRowLayout(recordKey) : this.GetDataRowLayout();
  return this.GetLayoutHelper().GetLayoutWidthCore(layout);
 },
 GetRowMatrixHeight: function(recordKey, isAdaptive) {
  if(this.IsDeletedItem(recordKey))
   return isAdaptive ? 0 : 1;
  if(!isAdaptive && this.AreDataRowsHidden())
   return 0;
  var layout = isAdaptive ? this.GetAdaptiveRowLayout(recordKey) : this.GetDataRowLayout();
  return this.GetLayoutHelper().GetLayoutHeightCore(layout);
 },
 GetItemMatrixRectLeft: function(recordKey) { return 0; },
 GetItemMatrixRectTop: function(recordKey) {
  var result = 0;
  var keys = this.GetRecordKeys();
  var relativeIndex = keys.indexOf(recordKey);
  for(var i = 0; i < relativeIndex; i++)
   result += this.GetItemMatrixHeight(keys[i]);
  return result;
 },
 CreateDeletedItemMatrix: function(recordKey) {
  var columnIndex = this.GetRecoverButtonColumnIndex();
  var matrixWidth = this.GetMaxMatrixWidth();
  var matrix = [ ];
  matrix[0] = ASPx.Data.Range(matrixWidth).map(function() { return this.CreateMatrixElement(recordKey, columnIndex); }.bind(this));
  return matrix;
 },
 CreateItemMatrixByLayout: function(layout, recordKey) { 
  var matrix = [ ];
  for(var i = 0; i < layout.length; i++) {
   var level = layout[i];
   for(var j = 0; j < level.length; j++) {
    var node = level[j];
    var left = this.FindFreeCellIndex(matrix, i);
    var rect = { top: i, bottom: i + node.rowSpan - 1, left: left, right: left + node.colSpan - 1 };
    this.FillMatrixRect(matrix, rect, this.CreateMatrixElement(recordKey, node.columnIndex));
   }
  }
  return matrix;
 }
});
var CardViewNavigationHelper = ASPx.CreateClass(GridNavigationHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.divBasedModeColCount = -1;
 },
 Invalidate: function() { 
  GridNavigationHelper.prototype.Invalidate.call(this);
  this.divBasedModeColCount = -1;
 },
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(); },
 PopulateLayoutMatrix: function() {
  GridNavigationHelper.prototype.PopulateLayoutMatrix.call(this);
  this.FillLayoutEmptyCells();
 },
 CreateDeletedItemMatrix: function(recordKey) {
  var matrixHeight = this.GetItemMatrixHeight(recordKey);
  var columnIndex = this.GetRecoverButtonColumnIndex();
  var columnIndices = ASPx.Data.Range(matrixHeight).map(function() { return columnIndex; });
  var colCount = this.GetItemMatrixWidth();
  return this.CreateFormLayoutMatrix(recordKey, columnIndices, colCount);
 },
 CreateItemMatrixCore: function(recordKey) {
  var columnIndices = this.GetVisibleColumnIndices();
  var colCount = this.GetItemMatrixWidth();
  return this.CreateFormLayoutMatrix(recordKey, columnIndices, colCount);
 },
 GetItemMatrixWidth: function(recordKey) { return this.grid.cardLayoutColCount; },
 GetItemMatrixHeight: function(recordKey) { 
  var columnIndices = this.GetVisibleColumnIndices();
  var colCount = this.GetItemMatrixWidth();
  return Math.ceil(columnIndices.length / colCount);
 },   
 GetItemMatrixRectLeft: function(recordKey) { 
  var width = this.GetItemMatrixWidth(recordKey);
  var cardIndex = this.GetRecordKeys().indexOf(recordKey);
  var cardX = cardIndex % this.GetControlColCount();
  return cardX * width;
 },
 GetItemMatrixRectTop: function(recordKey) {
  var height = this.GetItemMatrixHeight();
  var cardIndex = this.GetRecordKeys().indexOf(recordKey);
  var cardY = Math.floor(cardIndex / this.GetControlColCount());
  return cardY * height;
 },
 GetControlColCount: function() {
  return this.grid.IsTableLayoutMode() ? this.grid.colCount : this.GetDivBasedModeControlColCount();
 },
 GetDivBasedModeControlColCount: function() {
  if(this.divBasedModeColCount < 1)
   this.divBasedModeColCount = this.CalcDivBasedModeColCount();
  return this.divBasedModeColCount;
 },
 CalcDivBasedModeColCount: function() {
  var cards = this.GetDivBasedCards();
  var colCount = 1;
  var firstCardTop = cards[0].offsetTop;
  for(var i = 1; i < cards.length; i++) {
   if(cards[i].offsetTop > firstCardTop)
    break;
   colCount++;
  }
  return colCount;
 },
 GetDivBasedCards: function() {
  var classNamePrefix = this.grid.IsFlowLayoutMode() ? this.grid.FlowCardClassNamePrefix : this.grid.BreakpointsCardClassNamePrefix;
  return ASPx.GetNodesByPartialClassName(this.grid.GetMainTable(), classNamePrefix).filter( function(item) { return ASPx.IsElementVisible(item); });
 },
 FillLayoutEmptyCells: function() {
  if(this.layoutMatrix.length === 0) return;
  var width = this.layoutMatrix[0].length;
  for(var i = 0; i < this.layoutMatrix.length; i++) {
   var row = this.layoutMatrix[i];
   var prevCell = row[0];
   for(var j = 1; j < width; j++) {
    var cell = row[j];
    if(!cell)
     row[j] = prevCell;
    else
     prevCell = cell;
   }
  }
 },
 CreateFormLayoutMatrix: function(recordKey, columnIndices, colCount) { 
  var rowCount = Math.ceil(columnIndices.length / colCount);
  var result = this.CreateEmptyMatrix(rowCount);
  for(var i = 0; i < rowCount; i++) {
   for(var j = 0; j < colCount; j++) {
    var index = i * colCount + j;
    if(columnIndices.length <= index)
     index = columnIndices.length - 1;
    result[i][j] = this.CreateMatrixElement(recordKey, columnIndices[index]);
   }
  }
  return result;
 }
});
var VerticalGridNavigationHelper = ASPx.CreateClass(GridNavigationHelper, {
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(true); },
 CreateItemMatrixCore: function(recordKey) { 
  var columnIndices = this.GetVisibleColumnIndices();
  var matrix = this.CreateEmptyMatrix(columnIndices.length);
  for(var i = 0; i < columnIndices.length; i++)
   matrix[i][0] = this.CreateMatrixElement(recordKey, columnIndices[i]);
  return matrix;
 },
 CreateDeletedItemMatrix: function(recordKey) {
  var matrixHeight = this.GetItemMatrixHeight(recordKey);
  var matrix = this.CreateEmptyMatrix(matrixHeight);
  for(var i = 0; i < matrixHeight; i++)
   matrix[i][0] = this.CreateMatrixElement(recordKey, this.GetRecoverButtonColumnIndex());
  return matrix;
 },
 GetItemMatrixWidth: function(recordKey) { return 1; },
 GetItemMatrixHeight: function(recordKey) {  return this.GetVisibleColumnIndices().length; },
 GetItemMatrixRectLeft: function(recordKey) { return this.GetRecordKeys().indexOf(recordKey); },
 GetItemMatrixRectTop: function(recordKey) { return 0; }
});
ASPx.TableNavigationHelper = TableNavigationHelper;
ASPx.GridViewNavigationHelper = GridViewNavigationHelper;
ASPx.CardViewNavigationHelper = CardViewNavigationHelper;
ASPx.VerticalGridNavigationHelper = VerticalGridNavigationHelper;
})();

(function() {
var CellFocusHelper = ASPx.CreateClass(null, {
 FocusInputID: "DXFI",
 FocusedStylePrefix: "FocusedCell",
 FocusMoveDirectionRight: 0,
 FocusMoveDirectionLeft: 1,
 constructor: function(owner) {
  this.owner = owner;
  this.focusedCellInfo = null;
  this.mainTableMouseDownOnFocusedCell = false;
  this.needRestoreFocusAfterCallback = false;
  this.accessibilityCompliant = this.owner.accessibilityCompliant;
  this.accessibilityCellFocusHelper = null;
  this.unfocusableAreaElements = [];
  this.Initialize();
 },
 GetBatchEditHelper: function() { return this.owner.GetBatchEditHelper(); },
 GetStyleHelper: function() { return this.owner.GetStyleHelper(); },
 GetNavigationHelper: function() { return this.owner.GetNavigationHelper(); },
 IsCommandColumnItem: function() { },
 CanFocusOnCommandColumnItemMouseDown: function(element) { return false; },
 IsDeletedItem: function(recordKey) { }, 
 GetMainTable: function() { },
 GetChildElement: function(id) { },
 GetCssClassNamePrefix: function() { },
 OnBeforeFocusedCellChanging: function(cellInfo, htmlEvent) { },
 RaiseFocusedCellChanging: function(cellInfo) { return false; },
 OnFocusedCellChanged: function(cellInfo) { },
 GetScrollHelper: function() { },
 GetDataItem: function(recordKey) { },
 GetRecordKeyByChild: function(cell) { },
 GetColumnIndexByCell: function(cell) { },
 TryShowColumn: function(columnIndex, showFullRect) { },
 GetDataCellCore: function(recordKey, columnIndex) { },
 GetDataCellByChild: function(element) { },
 GetVisibleColumnIndices: function() { },
 Initialize: function() {
  if(this.accessibilityCompliant)
   this.accessibilityCellFocusHelper = new AccessibilityCellFocusHelper(this);
 },
 Update: function() {
  this.PrepareMainTable();
  this.AttachEvents();
  this.LoadUnfocusableAreaElements();
 },
 OnBeforeCallback: function() {
  this.needRestoreFocusAfterCallback = this.IsMainTableHasFocus();
 },
 OnAfterCallback: function() {
  this.Update();
  if(this.needRestoreFocusAfterCallback)
   this.RestoreCellFocus();
 },
 PrepareMainTable: function() { 
  this.PrepareMainTableCore(this.GetMainTable());
 },
 PrepareMainTableCore: function(table) {
  if(!table) return;
  table.tabIndex = 0;
  table.style.outline = "none";
  if(this.accessibilityCompliant)
     this.accessibilityCellFocusHelper.PrepareMainTable(table);
 },
 AttachEvents: function() {
  this.AttachTableEvents(this.GetMainTable());
  this.AttachInputEvents();
 },
 AttachTableEvents: function(table) {
  this.AttachEvent(table, "keydown", function(e) { this.OnMainTableKeyDown(e); }.bind(this));
  this.AttachEvent(table, "keyup", function(e) { this.OnMainTableKeyUp(e); }.bind(this));
  this.AttachEvent(table, "mousedown", function(e) { this.OnMainTableMouseDown(e); }.bind(this));
  this.AttachEvent(table, "blur", function(e) { this.OnMainTableBlur(e); }.bind(this));
  this.AttachEvent(table, "focus", function(e) { this.OnMainTableFocus(e); }.bind(this));
 },
 AttachInputEvents: function() {
  var focusInputs = [ this.GetPrevFocusInput(), this.GetAfterFocusInput() ];
  for(var i = 0; i < focusInputs.length; i++) {
   this.AttachEvent(focusInputs[i], "focus", function(e) { this.OnFocusInputGotFocus(e); }.bind(this));
   this.AttachEvent(focusInputs[i], "keydown", function(e) { this.OnFocusInputKeyDown(e); }.bind(this));
  }
 },
 AttachEvent: function(element, eventName, eventHandler) {
  if(!element) return;
  var eventMarker = "cfh" + eventName;
  if(element[eventMarker])
   return;
  ASPx.Evt.AttachEventToElement(element, eventName, eventHandler);
  element[eventMarker] = true;
 },
 OnMainTableKeyDown: function(e) {
  if(this.IsUnfocusableAreaActiveElement(e.target)) {
   this.ProcessKeyDownOnUnfocusableArea(e);
   return;
  }
  if(this.IsKeyDownNavigationLocked(ASPx.Evt.GetEventSource(e)))
   return;
  var controller = this.GetFocusController();
  if(controller && controller.ProcessMainTableKeyDown(e, this.GetFocusedCellInfo()))
   return;
  var key = ASPx.Evt.GetKeyCode(e);
  if(this.owner.rtl) {
   if(key == ASPx.Key.Left)
    key = ASPx.Key.Right;
   else if(key == ASPx.Key.Right)
    key = ASPx.Key.Left;
  }
  switch(key) {
   case ASPx.Key.Tab:
    this.ProcessTabPress(e);
    ASPx.Evt.PreventEventAndBubble(e);
    break;
   case ASPx.Key.Down:
    this.ProcessDownPress(e);
    ASPx.Evt.PreventEventAndBubble(e);
    break;
   case ASPx.Key.Up:
    this.ProcessUpPress(e);
    ASPx.Evt.PreventEventAndBubble(e);
    break;
   case ASPx.Key.Right:
    this.ProcessRightPress(e);
    ASPx.Evt.PreventEventAndBubble(e);
    break;
   case ASPx.Key.Left:
    this.ProcessLeftPress(e);
    ASPx.Evt.PreventEventAndBubble(e);
    break;
   case ASPx.Key.Space:
    ASPx.Evt.PreventEventAndBubble(e);
    break;
  }
 },
 IsKeyDownNavigationLocked: function(src) { return false; },
 ProcessTabPress: function(e) {
  var isLeft = e.shiftKey;
  var inc = isLeft ? -1 : 1;
  if(this.MoveCellFocus(inc, false, e) || this.ActivateUnfocusableAreaByTab(isLeft ? this.FocusMoveDirectionLeft : this.FocusMoveDirectionRight))
   return;
  this.MoveFocusFromMainTable(isLeft);
 },
 ProcessDownPress: function(e) { this.MoveCellFocus(1, true, e); },
 ProcessUpPress: function(e) { this.MoveCellFocus(-1, true, e); },
 ProcessLeftPress: function(e) { this.MoveCellFocus(-1, false, e); },
 ProcessRightPress: function(e) { this.MoveCellFocus(1, false, e); },
 OnMainTableKeyUp: function(e) {
  if(this.IsUnfocusableAreaActiveElement(e.target))
   return;
  if(this.IsKeyDownNavigationLocked(ASPx.Evt.GetEventSource(e)))
   return;
  var controller = this.GetFocusController();
  if(controller && controller.ProcessMainTableKeyUp)
   controller.ProcessMainTableKeyUp(e, this.GetFocusedCellInfo());
 },
 OnMainTableMouseDown: function(e) {
  if(this.IsUnfocusableAreaActiveElement(e.target)) {
   this.ClearFocus();
   return;
  }
  var dataCell = this.GetDataCellByChild(ASPx.Evt.GetEventSource(e));
  var prevFocusedCell = this.GetCurrentFocusedCell();
  this.ProcessMainTableMouseDown(e);
  this.mainTableMouseDownOnFocusedCell = dataCell !== null && (dataCell === prevFocusedCell) && (prevFocusedCell === this.GetCurrentFocusedCell());
 }, 
 GetCurrentFocusedCell: function() {
  if(!this.IsCellFocused())
   return null;
  return this.GetDataCell(this.GetFocusedCellInfo());
 },
 OnMainTableBlur: function (e) {
  if (ASPx.GridCommonUtils.IsBatchEditFocusEventsLocked(this.owner)) return;
  this.PostponedClearFocus();
 },
 PostponedClearFocus: function() {
  ASPx.Timer.ClearTimer(this.clearFocusTimerID);
  this.clearFocusTimerID = window.setTimeout(function() {
   if(!this.IsMainTableHasFocus())
    this.ClearFocus(); 
   delete this.clearFocusTimerID;
  }.bind(this), 50);
 },
 OnMainTableFocus: function (e) {
  if (ASPx.GridCommonUtils.IsBatchEditFocusEventsLocked(this.owner)) return;
  if(this.IsUnfocusableAreaActiveElement(e.target)) {
   this.ClearFocus();
   return;
  }
  this.RestoreMainTableScrollPosition();
  var target = e.target;
  if(this.IsCommandColumnItem(target)) 
   return;
  if(this.IsAnyOfFocusableTables(target) || !this.SetFocusByElement(target, e))
   this.RestoreCellFocus();
 },
 IsAnyOfFocusableTables: function(table) { return table === this.GetMainTable(); },
 OnFocusInputGotFocus: function(e) {
  var src = ASPx.Evt.GetEventSource(e);
  if(!src.lockFocusMainTable)
   this.FocusMainTableFromInput(src);
  src.lockFocusMainTable = false;
 },
 OnFocusInputKeyDown: function(e) {  
  var key = ASPx.Evt.GetKeyCode(e);
  if(key !== ASPx.Key.Tab)
   return;
  var src = ASPx.Evt.GetEventSource(e);
  var isLeft = e.shiftKey;
  if(src === this.GetPrevFocusInput() && !isLeft || src === this.GetAfterFocusInput() && isLeft) {
   ASPx.Evt.PreventEventAndBubble(e);
   this.FocusMainTableFromInput(src);
  }
 },
 GetFocusController: function() { 
  if(this.GetBatchEditHelper())
   return this.GetBatchEditHelper().GetFocusHelper();
  return null;
 },
 GetFocusedCellInfo: function() { return this.focusedCellInfo; },
 CreateCellInfo: function(recordKey, columnIndex) { return { recordKey: recordKey, columnIndex: columnIndex }; },
 CanFocusCell: function(cellInfo) {
  var cell = this.GetDataCell(cellInfo);
  if(!cell || this.IsDeletedItem(cellInfo.recordKey) && !this.CanFocusDeletedItemCell(cellInfo))
   return false;  
  return this.CanFocusCellCore(cellInfo);
 },
 CanFocusCellCore: function(cellInfo) {
  return ASPx.IsElementVisible(this.GetDataCell(cellInfo));
 },
 CanFocusDeletedItemCell: function(cellInfo) { 
  var helper = this.GetBatchEditHelper();
  if(!helper || !helper.GetHighlightDeletedItems())
   return false;
  return this.accessibilityCompliant || cellInfo.columnIndex === helper.GetRecoverButtonColumnKey();  
 },
 FocusFirstCell: function() {
  var cellInfo = this.GetNavigationHelper().GetFirstCellInfo();
  return this.SetFocus(cellInfo) || this.MoveFocusToNeibourCell(cellInfo, 1);
 },
 FocusLastCell: function() {
  var cellInfo = this.GetNavigationHelper().GetLastCellInfo(); 
  return this.SetFocus(cellInfo) || this.MoveFocusToNeibourCell(cellInfo, -1);
 },
 GetNavigationCellInfo: function(cellInfo, inc, isVert) {
  return this.GetNavigationHelper().GetNavigationCellInfo(cellInfo, inc, isVert);
 },
 MoveFocusToNeibourCell: function(cellInfo, inc, isVert, htmlEvent) {
  if(!cellInfo) return false;
  var newCellInfo = this.GetNavigationCellInfo(cellInfo, inc, isVert);
  return this.SetFocus(newCellInfo, true, false, htmlEvent) || this.MoveFocusToNeibourCell(newCellInfo, inc, isVert, htmlEvent);
 },
 GetRecoverButtonCellInfo: function(recordKey) {
  var helper = this.GetBatchEditHelper();
  if(!helper && !ASPx.IsExists(recordKey))
   return null;
  return this.CreateCellInfo(recordKey, helper.GetRecoverButtonColumnKey());
 },
 GetPrevFocusInput: function() { return this.GetFocusInput(true); },
 GetAfterFocusInput: function() { return this.GetFocusInput(); },
 GetFocusInput: function(prev) {
  var input = this.GetChildElement(this.GetFocusInputID(prev));
  if(!input)
   input = this.CreateFocusInput(prev);
  return input;
 },
 GetFocusInputID: function(prev) {
  var postfix = prev ? "_0" : "_1";
  return this.FocusInputID + postfix;
 },
 CreateFocusInput: function(prev) {
  var input = document.createElement("INPUT");
  input.id = this.owner.name + "_" + this.GetFocusInputID(prev);
  input.setAttribute("type", "text");
  ASPx.Attr.SetAttribute(input.style, "border-width", "0px");
  ASPx.Attr.SetAttribute(input.style, "width", "0px");
  ASPx.Attr.SetAttribute(input.style, "height", "0px");
  ASPx.Attr.SetAttribute(input.style, "padding", "0px");
  ASPx.Attr.SetAttribute(input.style, "margin", "0px");
  ASPx.Attr.SetAttribute(input.style, "background-color", "transparent");
  ASPx.Attr.SetAttribute(input.style, "readonly", "readonly");
  if(this.accessibilityCompliant)
   ASPx.Attr.Aria.SetOrRemoveLabel(input, ASPx.AccessibilitySR.CellFocusInputText);
  var wrapper = document.createElement("DIV");
  ASPx.Attr.SetAttribute(wrapper.style, "font-size", "0px");
  ASPx.Attr.SetAttribute(wrapper.style, "height", "0px");
  ASPx.Attr.SetAttribute(wrapper.style, "border-width", "0px");
  ASPx.Attr.SetAttribute(wrapper.style, "line-height", "0");
  wrapper.appendChild(input);
  this.AddWrapperToDOM(wrapper, prev);
  return input;
 },
 IsVirtualScrolling: function() {
  var control = this.owner;
  return !!control.IsVirtualScrolling && control.IsVirtualScrolling();
 },
 AddWrapperToDOM: function(wrapper, prev) {
  var table = this.GetMainTable();
  var target = prev ? table : table.nextSibling;
  table.parentNode.insertBefore(wrapper, target);
 },
 IsMainTableHasFocus: function() { return this.IsMainTableHasFocusCore(this.GetMainTable()); },
 IsMainTableHasFocusCore: function(table) {
  var focusedElement = ASPx.GetActiveElement();
  return table === focusedElement || ASPx.GetIsParent(table, focusedElement);
 },
 IsCellFocused: function(checkHidden) {
  var cell = this.GetDataCell(this.GetFocusedCellInfo());
  if(!cell) return false;
  var focusedStylePrefix = this.GetCssClassNamePrefix() + this.FocusedStylePrefix;
  var result = ASPx.ElementContainsCssClass(cell, focusedStylePrefix);
  if(!checkHidden)
   result &= ASPx.IsElementVisible(cell);
  return result;
 },
 IsMainTableMouseDownOnFocusedCell: function() { return this.mainTableMouseDownOnFocusedCell; },
 ClearFocus: function() {
  if(!this.IsCellFocused(true))
   return;
  ASPx.Timer.ClearTimer(this.clearFocusTimerID);
  var cell = this.GetDataCell(this.GetFocusedCellInfo());
  this.ApplyFocusedStyle(cell, true);
  if(this.accessibilityCompliant)
   this.accessibilityCellFocusHelper.OnClearFocus();
 },
 ApplyFocusedStyle: function(cell, reset) {
  var styleHelper = this.GetStyleHelper();
  var style = reset ? styleHelper.GetEmptyCellStyle() : styleHelper.GetFocusedCellStyle();
  styleHelper.UpdateCellFocusedStyle(style, cell);
 },
 TryFocusCell: function(recordKey, columnIndex, moveFocusToNeighbourIfFail, makeCellVisible) {
  var info = this.CreateCellInfo(recordKey, columnIndex);
  if(this.SetFocus(info, makeCellVisible)) 
   return true;
  return moveFocusToNeighbourIfFail && (this.MoveFocusToNeibourCell(info, 1) || this.FocusFirstCell());
 },
 SetFocus: function(cellInfo, makeCellVisible, fromApi, htmlEvent) {
  if(!this.CanFocusCell(cellInfo) || this.OnBeforeFocusedCellChanging(cellInfo, htmlEvent)) 
   return false;
  var cell = this.GetDataCell(cellInfo);
  var isAlreadyFocused = this.IsCellFocused() && this.IsEqualInfo(this.GetFocusedCellInfo(), cellInfo);
  if(!isAlreadyFocused && !fromApi && this.RaiseFocusedCellChanging(cellInfo))
   return false;  
  if(!isAlreadyFocused)
   this.SetFocusCore(cell, cellInfo, makeCellVisible);
  if(this.accessibilityCompliant)
   this.accessibilityCellFocusHelper.OnSetFocus(cell, cellInfo);
  this.OnFocusedCellChanged(this.GetFocusedCellInfo(), htmlEvent);
  return true;
 },
 SetFocusCore: function(cell, cellInfo, makeCellVisible) {
  this.ClearFocus();
  var cell = this.GetDataCell(cellInfo);
  this.ApplyFocusedStyle(cell);
  this.focusedCellInfo = cellInfo;
  window.setTimeout(function() {
   if(!this.IsMainTableHasFocus())
    this.FocusMainTable(); 
  }.aspxBind(this), 50);
  if(makeCellVisible)
   this.MakeCellVisible(cell);
  return true;
 }, 
 IsEqualInfo: function(info1, info2) { 
  return info1 && info2 && info1.columnIndex === info2.columnIndex && info1.recordKey === info2.recordKey;
 },
 MakeCellVisible: function(cell) {
  if(!cell) return;
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper && scrollHelper.MakeCellVisible)
   scrollHelper.MakeCellVisible(cell);
  this.ScrollDocumentToShowCell(cell);
  this.ScrollDocumentToShowCell(cell, true);
  this.TryShowColumn(this.GetMainTableColumnIndex(this.GetFocusedCellInfo()), true);
 },
 ScrollDocumentToShowCell: function(cell, isHorizontal){
  if(!this.IsDocumentScrollBarVisible(isHorizontal))
   return;
  var scrollStart = isHorizontal ? ASPx.GetDocumentScrollLeft() : ASPx.GetDocumentScrollTop();
  var documentSize = isHorizontal ? ASPx.GetDocumentClientWidth() : ASPx.GetDocumentClientHeight();
  var cellStart = isHorizontal ? ASPx.GetAbsoluteX(cell) : ASPx.GetAbsoluteY(cell);
  var cellSize =  isHorizontal ? cell.offsetWidth : cell.offsetHeight;
  var scrollMethod = !!isHorizontal ? ASPx.SetDocumentScrollLeft : ASPx.SetDocumentScrollTop;
  var diff = scrollStart - cellStart;
  if(diff > 0)
   scrollMethod(scrollStart - diff);
  var scrollEnd = scrollStart + documentSize + 1;
  var cellEnd = cellStart + cellSize;
  diff = cellEnd - scrollEnd;
  if(diff > 0)
   scrollMethod(scrollStart + diff);
 },
 IsDocumentScrollBarVisible: function(isHorizontal) {
  if(isHorizontal)
   return  ASPx.GetHorizontalScrollIsNotHidden() && ASPx.GetDocumentWidth() > ASPx.GetDocumentClientWidth();
  return ASPx.GetVerticalScrollIsNotHidden() && ASPx.GetDocumentHeight() > ASPx.GetDocumentClientHeight();
 },
 GetMainTableColumnIndex: function(cellInfo) { return cellInfo && cellInfo.columnIndex; },
 RestoreCellFocus: function() {
  var isCellFocusedTotally = this.IsCellFocused() && !this.accessibilityCompliant;
  var isExistsAccessibleFocusElement = this.accessibilityCompliant && ASPx.RestoreFocusHelper.findFocusElement(this.owner);
  if(isCellFocusedTotally || isExistsAccessibleFocusElement) return;
  var cellInfo = this.GetFocusedCellInfo();
  if(this.SetFocus(cellInfo)) return;
  cellInfo = this.CreateCellInfo(this.GetFirstRecordKey(), this.GetColumnIndexToRecoverFocus(cellInfo && cellInfo.columnIndex));
  if(!this.SetFocus(cellInfo))
   this.FocusFirstCell();
 },
 FocusMainTable: function() {
  var table = this.GetMainTable();
  if(table.setActive) {
   table.setActive();
  } else {
   this.SaveMainTableScrollPosition();
   table.focus();
  }
 },
 SaveMainTableScrollPosition: function() {
  this.savedDocumentScrollTop = ASPx.GetDocumentScrollTop();
  this.savedDocumentScrollLeft = ASPx.GetDocumentScrollLeft();
  window.setTimeout(function() { this.ResetMainTableScrollPosition(); }.aspxBind(this), 150);
 },
 RestoreMainTableScrollPosition: function() {
  if(ASPx.IsExists(this.savedDocumentScrollTop))
   ASPx.SetDocumentScrollTop(this.savedDocumentScrollTop);
  if(ASPx.IsExists(this.savedDocumentScrollLeft))
   ASPx.SetDocumentScrollLeft(this.savedDocumentScrollLeft);
 },
 ResetMainTableScrollPosition: function() {
  this.savedDocumentScrollTop = null;
  this.savedDocumentScrollLeft = null;
 },
 MoveFocusFromMainTable: function(isleft) {
  var input = this.GetFocusInput(isleft);
  var newActiveElement = this.FindNextTabStop(input, isleft);
  if(newActiveElement === input)  
   input.lockFocusMainTable = true;
  window.setTimeout(function() {  newActiveElement.focus(); }, 0);
 },
 FocusMainTableFromInput: function(src) {
  if(this.ActivateUnfocusableAreaFromInput(src))
   return;
  if(src == this.GetPrevFocusInput())
   this.FocusFirstCell();
  else
   this.FocusLastCell();
 },
 FindNextTabStop: function(el, prev) { 
  var list = ASPx.FindChildActionElements(document);
  var inc = prev ? -1 : 1;
  var index = list.indexOf(el) + inc;
  if(index < 0 || index >= list.length)
   return el;
  return list[index];
 },
 SetFocusedCell: function(recordKey, columnIndex) { 
  if(ASPx.IsExists(recordKey) && ASPx.IsExists(columnIndex))  
   this.SetFocus(this.CreateCellInfo(recordKey, columnIndex), false, true); 
  else
   this.ClearFocus();
 },
 ProcessMainTableMouseDown: function(e) { 
  var src = ASPx.Evt.GetEventSource(e);
  if(this.IsCommandColumnItem(src) && !this.CanFocusOnCommandColumnItemMouseDown(src))
   return false;
  if(this.SetFocusByElement(src, e))
   return true;
  var recordKey = this.GetRecordKeyByChild(src);
  if(!ASPx.IsExists(recordKey))
   return false;
  if(this.IsDeletedItem(recordKey))
   return this.SetFocus(this.GetRecoverButtonCellInfo(recordKey));
  if(this.GetDataCellByChild(src)) 
   return false;
  var prevCellInfo = this.GetFocusedCellInfo();
  var cellInfo = this.CreateCellInfo(recordKey, this.GetColumnIndexToRecoverFocus(prevCellInfo && prevCellInfo.columnIndex));
  return this.SetFocus(cellInfo);
 },
 SetFocusByElement: function(element, htmlEvent) {
  var cell = this.GetDataCellByChild(element);
  if(!cell) return false;
  var recordKey = this.GetRecordKeyByChild(cell);
  var columnIndex = this.GetColumnIndexByCell(cell);
  return this.SetFocus(this.CreateCellInfo(recordKey, columnIndex), false, false, htmlEvent);
 },
 MoveCellFocus: function(inc, isVert, htmlEvent) {
  return this.MoveFocusToNeibourCell(this.GetFocusedCellInfo(), inc, isVert, htmlEvent);
 },
 GetDataCell: function(info) {  
  if(!info) return null;
  return this.GetDataCellCore(info.recordKey, info.columnIndex);
 },
 GetFirstRecordKey: function() { return this.GetNavigationHelper().GetFirstRecordKey(); },
 GetColumnIndexToRecoverFocus: function(columnIndex) {
  var columnIndices = this.GetVisibleColumnIndices();
  if(ASPx.Data.ArrayIndexOf(columnIndices,  columnIndex) > -1)
   return columnIndex;
  return columnIndices[0];
 },
 ProcessKeyDownOnUnfocusableArea: function(e) {
  if(ASPx.Evt.GetKeyCode(e) !== ASPx.Key.Tab)
   return;
  var direction = e.shiftKey ? this.FocusMoveDirectionLeft : this.FocusMoveDirectionRight;
  if(this.LeaveUnfocusableAreaByTab(ASPx.Evt.GetEventSource(e), direction))
   ASPx.Evt.PreventEventAndBubble(e);
  else
   this.ClearFocus();
 },   
 LeaveUnfocusableAreaByTab: function(source, direction) {  
  var needLeaveTopArea = this.IsUnfocusableAreaActiveElementCore(source, true);
  if(needLeaveTopArea)
   return this.LeaveTopUnfocusableAreaByTab(source, direction);
  return this.LeaveBottomUnfocusableAreaByTab(source, direction);
 },
 LeaveTopUnfocusableAreaByTab: function(source, direction) {
  var canLeave = this.CanLeaveTopUnfocusableArea(source, direction);
  if(canLeave) {
   if(direction === this.FocusMoveDirectionLeft) {
    this.MoveFocusFromMainTable(true);
   } else {
    this.FocusFirstCell();
    this.FocusMainTable();
   } 
  }
  return canLeave;
 },
 CanLeaveTopUnfocusableArea: function(element, direction) {
  var toLeft = direction === this.FocusMoveDirectionLeft;
  var elements = this.unfocusableElementsInfo.topArea;
  var index = elements.indexOf(element);
  var isFirst = index === 0;
  var isLast = index === elements.length - 1;
  return isFirst && toLeft || isLast && !toLeft;
 },
 LeaveBottomUnfocusableAreaByTab: function(source, direction) {
  var canLeave = this.CanLeaveBottomUnfocusableArea(source, direction);
  if(canLeave) {
   if(direction === this.FocusMoveDirectionLeft) {
    this.FocusLastCell();
    this.FocusMainTable();
   } else {
    this.MoveFocusFromMainTable();
   } 
  }
  return canLeave;
 },
 CanLeaveBottomUnfocusableArea: function(element, direction) {
  var toLeft = direction === this.FocusMoveDirectionLeft;
  var elements = this.unfocusableElementsInfo.bottomArea;
  var index = elements.indexOf(element);
  var isFirst = index === 0;
  var isLast = index === elements.length - 1;
  return isFirst && !toLeft || isLast && toLeft;
 },
 ActivateUnfocusableAreaByTab: function(direction) { 
  var isTopArea = direction === this.FocusMoveDirectionLeft;
  return this.ActivateUnfocusableAreaCore(isTopArea, direction);
 },
 ActivateUnfocusableAreaFromInput: function(src) {  
  var isTopArea = src === this.GetPrevFocusInput();
  var direction = isTopArea ? this.FocusMoveDirectionRight : this.FocusMoveDirectionLeft;
  return this.ActivateUnfocusableAreaCore(isTopArea, direction);
 },
 ActivateUnfocusableAreaCore: function(isTop, direction) {
  var info = this.unfocusableElementsInfo;
  if(!info) return false;
  var elements = isTop ? info.topArea : info.bottomArea;
  var canActivate = elements.length > 0;
  if(canActivate) {
   var needActivateFirstElement = direction === this.FocusMoveDirectionRight;
   var index = needActivateFirstElement ? 0 : elements.length - 1;
   elements[index].focus();
  }
  return canActivate;
 },
 IsUnfocusableAreaActiveElement: function(element) {  
  return this.IsUnfocusableAreaActiveElementCore(element, true) || this.IsUnfocusableAreaActiveElementCore(element, false);
 },
 IsUnfocusableAreaActiveElementCore: function(element, checkTopArea) {
  var info = this.unfocusableElementsInfo;
  if(!info) return false;
  var elementsToCheck = checkTopArea ? info.topArea : info.bottomArea;
  return ASPx.Data.ArrayContains(elementsToCheck, element);
 },
 LoadUnfocusableAreaElements: function() {
  this.unfocusableElementsInfo = { };
  this.unfocusableElementsInfo.topArea = this.LoadUnfocusableAreaElementsCore(this.GetUnfocusableTopAreaRows());
  this.unfocusableElementsInfo.bottomArea = this.LoadUnfocusableAreaElementsCore(this.GetUnfocusableBottomAreaRows());
 },
 LoadUnfocusableAreaElementsCore: function(rows) {
  var elements = [];
  for(var i = 0; i < rows.length; i++) {
   var list = ASPx.FindChildActionElements(rows[i]);
   for(var j = 0; j < list.length; j++)
    elements.push(list[j]);
  }
  return elements;
 },
 GetUnfocusableTopAreaRows: function() { return [ ]; },
 GetUnfocusableBottomAreaRows: function() { return [ ]; },
 IsRecordFocused: function(key) { return false; },
 IsRecordSelected: function(key) { return false; },
 GetRowIdentificator: function(key) { return key; }
});
var AccessibilityCellFocusHelper = ASPx.CreateClass(null, {
 constructor: function(cellFocusHelper) { 
  this.batchEditHelper = cellFocusHelper.GetBatchEditHelper();
  this.cellFocusHelper = cellFocusHelper;
  this.control = cellFocusHelper.owner;
  this.pronouncerType = ASPx.AccessibilityPronouncerType.live;
  this.prevPronouncedRowKey = null;
 },
 GetMainTable: function() { return this.cellFocusHelper.GetMainTable();},
 PrepareMainTable: function(table) {
  ASPx.Attr.SetAttribute(table, "role", "grid");
  this.PrepareTableParentNode(table.parentNode);
  var layoutCells = table.querySelectorAll("span:not([role]), img:not([role]):not([alt]), table[role=\"presentation\"] > tbody > tr > td:not([role])");
  for(var i = 0; i < layoutCells.length; i++)
   ASPx.Attr.SetAttribute(layoutCells[i], "role", "presentation");
 },
 PrepareTableParentNode: function(parentNode) {
  if(parentNode.tagName !== "DIV")
   return;
  ASPx.Attr.SetAttribute(parentNode, "role", "application");
  if(this.control.HasScrolling())
   ASPx.Attr.Aria.SetOrRemoveLabel(parentNode, ASPx.AccessibilitySR.GridDataTableCaptionText);
  else
   ASPx.Attr.Aria.SetSilence(parentNode);
 },
 OnSetFocus: function(cell, cellInfo) {
  if(!this.isMainTableFocused())
   return;
  var rowKey = this.cellFocusHelper.GetRowIdentificator(cellInfo.recordKey);
  this.prepareCell(cell, rowKey, cellInfo.columnIndex);
  var description = this.getCellDescription(cell, cellInfo);
  this.control.PronounceMessageInternal(description, this.pronouncerType);
 },
 OnClearFocus: function() {
  ASPx.AccessibilityPronouncer.RestoreControlState(this.pronouncerType, this.control.GetMainElement());
 },
 isMainTableFocused: function() {
  return ASPx.GetActiveElement() === this.GetMainTable();
 },
 getCellDescription: function(cell, cellInfo) {
  return [
   this.getRowDescriptionPart(cellInfo),
   this.getCellMainDescriptionPart(cell, cellInfo),
   this.getChangeDescriptionPart(cellInfo),
   this.getControlDescriptionPart(this.getChildControlElement(cell))
  ];
 },
 getRowDescriptionPart: function(cellInfo) {
  var key = cellInfo.recordKey;
  if(key === this.prevPronouncedRowKey)
   return;
  this.prevPronouncedRowKey = key;
  var cellFocusHelper = this.cellFocusHelper;
  var isFocused = cellFocusHelper.IsRecordFocused(key);
  var isSelected = cellFocusHelper.IsRecordSelected(key);
  var isDeleted = this.batchEditHelper.IsDeletedRecord(key);
  var result = null;
  if(isFocused && isSelected)
   result = ASPx.AccessibilitySR.BatchFocusedSelectedRowText;
  else if(isFocused)
   result = ASPx.AccessibilitySR.BatchFocusedRowText;
  else if(isSelected)
   result = ASPx.AccessibilitySR.BatchSelectedRowText;
  else if(isDeleted)
   result = ASPx.AccessibilitySR.BatchDeletedRowText;
  return result;
 },
 getCellMainDescriptionPart: function(cell, cellInfo) {
  var cellText = this.getCellText(cell, cellInfo);
  var batchEditHelper = this.batchEditHelper;
  var isEditable = batchEditHelper.CanEditColumn(cellInfo.columnIndex) && !batchEditHelper.IsDeletedRecord(cellInfo.recordKey);  
  var formatString = isEditable ? ASPx.AccessibilitySR.BatchEditableCellFormatString : 
   ASPx.AccessibilitySR.BatchNotEditableCellFormatString;
  return ASPx.Str.TrimStart(ASPx.Str.ApplyReplacement(formatString, [["{0}", cellText]]));
 },
 getChangeDescriptionPart: function(cellInfo) {
  if(this.batchEditHelper.HasModifiedStyle(cellInfo.recordKey, cellInfo.columnIndex))
   return ASPx.AccessibilitySR.BatchChangedText;
 },
 getCellText: function(cell, cellInfo) {
  var batchEditHelper = this.batchEditHelper;
  if(batchEditHelper.IsProgressBarColumn(cellInfo.columnIndex))
   return "";
  var containerDiv = batchEditHelper.GetCellTextContainer(cellInfo.recordKey, cellInfo.columnIndex);
  var result = "";
  if(containerDiv)
   result = this.getChildNodesText(containerDiv, false);
  if(!containerDiv || !result)
   result = this.getChildNodesText(cell, true);
  return result;
 },
 getChildNodesText: function(container, excludeCellTextContainer) {
  var textParts = [ ];
  for(var i = 0; i < container.childNodes.length; i++) {
   var childNode = container.childNodes[i];
   var isExcludedNode = excludeCellTextContainer && this.isTextContainerNode(childNode);
   var isValidNode = childNode.nodeType === 3 || this.isVisibleNode(childNode);
   if(isValidNode && !isExcludedNode) {
    var textPart = ASPx.GetInnerText(childNode);
    textPart = ASPx.RemoveComment(textPart);
    if(textPart)
     textParts.push(textPart);
   }
  }
  return textParts.join(", ");
 },
 isVisibleNode: function(node) {
  return node.tagName !== "SCRIPT" && node.style && ASPx.GetElementDisplay(node);
 },
 isTextContainerNode: function(node) {
  return ASPx.ElementHasCssClass(node, this.batchEditHelper.owner.TextContainerClassName);
 },
 getChildControlElement: function(container) {
  var controls = container.querySelectorAll("[role]:not([role=\"presentation\"]):not([role=\"application\"])");
  for(var i = 0; i < controls.length; i++) {
   var control = controls[i];
   if(ASPx.IsElementVisible(control))
    return control;
  }
 },
 getControlDescriptionPart: function(controlElement) {
  if(!controlElement)
   return null;
  var stateText = "";
  var role = ASPx.Attr.GetAttribute(controlElement, "role");
  switch(role) {
   case "checkbox":
   case "radio":
    var state = ASPx.Attr.GetAttribute(controlElement, "aria-checked");
    stateText = state === "true" ? ASPx.AccessibilitySR.CheckedText : ASPx.AccessibilitySR.UncheckedText;
    break;
   case "progressbar":
    var value = ASPx.Attr.GetAttribute(controlElement, "aria-valuenow");
    stateText = value + "%";
    break;
  }
  var roleFormatString = this.getRoleFormatString(role);
  return ASPx.Str.ApplyReplacement(roleFormatString, [["{0}", stateText]]);
 }, 
 prepareCell: function(cell, rowKey, columnIndex) {
  if(!cell.id)
   cell.id = this.createCellId(rowKey, columnIndex);
 },
 createCellId: function(rowKey, columnIndex) {  
  return this.control.name + "_" + "r" + rowKey + "c" + columnIndex;
 },
 getRoleFormatString: function(role) {
  switch(role) {
   case "checkbox": return ASPx.AccessibilitySR.BatchCheckBoxDescriptionFormatString;
   case "radio": return ASPx.AccessibilitySR.BatchRadioButtonDescriptionFormatString;
   case "progressbar": return ASPx.AccessibilitySR.BatchProgressBarDescriptionFormatString;
   default: return role;
  }
 }
});
ASPx.CellFocusHelper = CellFocusHelper;
})();

(function() {
var GridCellFocusHelper = ASPx.CreateClass(ASPx.CellFocusHelper, { 
 constructor: function(owner) {
  this.constructor.prototype.constructor.call(this, owner);
  this.grid = owner;
 },
 ConvertKeyToVisibleIndex: function(key) { return this.grid.ConvertKeyToVisibleIndex(key); },
 ConvertVisibleIndexToKey: function(visibleIndex) { return this.grid.ConvertVisibleIndexToKey(visibleIndex); },
 IsCommandColumnItem: function(element) { return this.grid.IsCommandColumnItem(element); },
 CanFocusOnCommandColumnItemMouseDown: function(source) {
  var grid = this.grid;
  var button = grid.FindCommandButtonByChildElement(source);
  return !!button && !grid.IsNewButton(button) && !grid.IsEditButton(button) && !grid.IsDeleteButton(button) && !grid.IsCancelButton(button); 
 },
 IsDeletedItem: function(recordKey)  { return this.grid.IsBatchEditDeletedItem(this.ConvertKeyToVisibleIndex(recordKey)); },
 GetMainTable: function() { return this.grid.GetMainTable();},
 GetChildElement: function(id) { return this.grid.GetChildElement(id); },
 GetCssClassNamePrefix: function() { return this.grid.GetCssClassNamePrefix(); },
 RaiseFocusedCellChanging: function(cellInfo) { return this.grid.RaiseFocusedCellChanging(cellInfo); },
 OnBeforeFocusedCellChanging: function(cellInfo, htmlEvent) { return this.grid.OnBeforeFocusedCellChanging(cellInfo, htmlEvent); },
 OnFocusedCellChanged: function(cellInfo, htmlEvent) { this.grid.OnFocusedCellChanged(cellInfo, htmlEvent); },
 GetScrollHelper: function() { return this.grid.GetScrollHelper(); },
 GetDataItem: function(recordKey) { return this.grid.GetDataItem(this.ConvertKeyToVisibleIndex(recordKey)); },
 GetRecordKeyByChild: function(element) {
  var item = this.GetGridItemByChild(element);
  if(!item) return;
  var visibleIndex = this.grid.getItemIndex(item.id);
  return this.ConvertVisibleIndexToKey(visibleIndex);
 },
 GetColumnIndexByCell: function(cell) { return this.grid.GetColumnIndexByDataCell(cell); },
 TryShowColumn: function(columnIndex) {
  if(this.grid.GetFixedColumnsHelper && this.grid.GetFixedColumnsHelper())
   this.grid.GetFixedColumnsHelper().TryShowColumn(columnIndex, true);
 },
 GetGridItemByChild: function(element) {
  var regEx = this.GetGridItemVisibleIndexRegExp();
  return ASPx.GetParent(element, function(item) { 
   var matches = regEx.exec(item.id);
   return matches && matches.length == 3;
  }.aspxBind(this)); 
 },
 GetGridItemVisibleIndexRegExp: function() {
  return this.grid.GetItemVisibleIndexRegExp();
 },
 IsDataItem: function(item) {
  if(!item || !item.id) return false;
  var prefixes = this.GetDataItemIDPrefixes();
  for(var i = 0; i < prefixes.length; i++) {
   if(item.id.indexOf(prefixes[i]) > -1) 
    return true;
  }
  return false;
 },
 GetDataItemIDPrefixes: function() { return null; },
 IsRecordFocused: function(key) { return this.grid.GetFocusedRowIndex() === this.ConvertKeyToVisibleIndex(key); },
 IsRecordSelected: function(key) { return this.grid.IsRowSelectedOnPage(this.ConvertKeyToVisibleIndex(key)); },
 GetRowIdentificator: function(key) { return this.ConvertKeyToVisibleIndex(key); }
});
var GridViewCellFocusHelper = ASPx.CreateClass(GridCellFocusHelper, {
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
  this.nextPageLoading = false;
 },
 Update: function() {
  GridCellFocusHelper.prototype.Update.call(this);
  this.SetNextPageLoading(false);
 },
 GetAdaptivityHelper: function() { return this.grid.GetAdaptivityHelper(); },
 GetDataItemIDPrefixes: function() { return [ASPx.GridViewConsts.DataRowID, ASPx.GridViewConsts.AdaptiveDetailRowID]; },
 GetDataItem: function(recordKey) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  if(this.grid.HasBandedDataRows())
   return this.grid.GetBandedDataRows(visibleIndex);
  return GridCellFocusHelper.prototype.GetDataItem.call(this, visibleIndex);
 },
 GetDataCellCore: function(recordKey, columnIndex) {
  if(columnIndex < 0) return null;
  var grid = this.grid;
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  var cell = grid.GetBatchDataCell(visibleIndex, columnIndex);
  var helper = this.GetAdaptivityHelper();
  if(helper && helper.HasAnyAdaptiveElement() && (helper.IsAdaptivityMode() || grid.IsCellAdaptiveHidden(cell)))
   return grid.GetAdaptiveCell(visibleIndex, columnIndex);
  return cell;
 },
 GetDataCellByChild: function(element) { 
  var helper = this.grid.GetLayoutHelper();
  return helper.GetDataCellByChild(element);
 },
 GetGridItemByChild: function(element) {
  var row = GridCellFocusHelper.prototype.GetGridItemByChild.call(this, element);
  if(this.IsGroupRow(row)) {
   while(row !== null && !this.IsDataItem(row))
    row = row.nextSibling;
  }
  return row;
 },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 GetVisibleColumnIndices: function() { return this.GetColumnHelper().GetVisibleColumnIndices(); },
 IsGroupRow: function(row) { return !!row && row.id.indexOf( ASPx.GridViewConsts.GroupRowID) > -1;},
 IsKeyDownNavigationLocked: function(src) { 
  var id = this.grid.name + "_" + ASPx.GridViewConsts.DetailRowID;
  return !!ASPx.GetParentByPartialId(src, id);    
 },
 ProcessDownPress: function(e) {
  if(this.IsNextPageLoading())
   return;
  if(this.RequireVirtScrollToNextPage())
   this.ScrollToNextPage();
  else
   GridCellFocusHelper.prototype.ProcessDownPress.call(this, e);    
 },
 ProcessUpPress: function(e) {
  if(this.IsNextPageLoading())
   return;
  if(this.RequireVirtScrollToNextPage(true))
   this.ScrollToNextPage(true);
  else
   GridCellFocusHelper.prototype.ProcessUpPress.call(this, e);    
 },
 RequireVirtScrollToNextPage: function(isUpPressed) {
  if(!this.GetFocusedCellInfo() || !this.grid.IsVirtualScrolling())
   return false;
  var keys = this.grid.GetRecordKeys();
  var focusedItemIndex = keys.indexOf(this.GetFocusedCellInfo().recordKey);
  if(isUpPressed)
   return focusedItemIndex === 0;
  return focusedItemIndex === keys.length - 1;
 },
 ScrollToNextPage: function(prevPage) {
  var helper = this.grid.GetScrollHelper();
  var cell = this.GetCurrentFocusedCell();
  if(helper && cell) {
   var inc = cell.offsetHeight;
   if(prevPage) inc = -inc;
   helper.SetVertScrollPosition(helper.GetVertScrollPosition() + inc);
   this.SetNextPageLoading(true);
  }  
 },
 IsNextPageLoading: function() { return this.nextPageLoading; },
 SetNextPageLoading: function(value) {
  this.nextPageLoading = value;
  ASPx.Timer.ClearTimer(this.virtScrollLockTimerID);
  if(value) {
   this.virtScrollLockTimerID = window.setTimeout(function() {
    if(!this.grid.InCallback() && this.IsNextPageLoading())
     this.SetNextPageLoading(false);
   }.bind(this), 800);
  }
 },
 GetUnfocusableTopAreaRows: function() {
  var layoutHelper = this.grid.GetLayoutHelper();
  var rows = [ ].concat(
   layoutHelper.GetHeaderRows(),
   layoutHelper.GetFilterRows()
  );
  var mainTable = this.GetMainTable();
  return rows.filter(function(row) { return ASPx.GetIsParent(mainTable, row); });
 },
 GetUnfocusableBottomAreaRows: function() { 
  var layoutHelper = this.grid.GetLayoutHelper();
  var mainTable = this.GetMainTable();
  return layoutHelper.GetFooterRows().filter(function(row) { return ASPx.GetIsParent(mainTable, row); });
 },
});
var CardViewCellFocusHelper = ASPx.CreateClass(GridCellFocusHelper, {
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
 },
 GetDataCellCore: function(recordKey, columnIndex) { return this.grid.GetFormLayoutItemCell(this.ConvertKeyToVisibleIndex(recordKey), columnIndex); },
 GetDataCellByChild: function(element) { return this.grid.GetFormLayoutItemCellByChild(element); },
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(); },
 GetDataItemIDPrefixes: function() { return [this.grid.CardID]; },
 IsRecordFocused: function(key) { return this.grid.GetFocusedCardIndex() === this.ConvertKeyToVisibleIndex(key); },
 IsRecordSelected: function(key) { return this.grid.IsCardSelectedOnPage(this.ConvertKeyToVisibleIndex(key)); },
});
var VerticalGridCellFocusHelper = ASPx.CreateClass(GridCellFocusHelper, {
 constructor: function(grid) { 
  this.constructor.prototype.constructor.call(this, grid);
 },
 AttachEvents: function() {
  this.AttachTableEvents(this.GetFixedTable());
  GridCellFocusHelper.prototype.AttachEvents.call(this);
 },
 PrepareMainTable: function() { 
  GridCellFocusHelper.prototype.PrepareMainTable.call(this);
  this.PrepareMainTableCore(this.GetFixedTable());
 },
 IsAnyOfFocusableTables: function(table) { return table === this.GetMainTable() || table === this.GetFixedTable(); },
 IsMainTableHasFocus: function() { return this.IsMainTableHasFocusCore(this.GetMainTable()) || this.IsMainTableHasFocusCore(this.GetFixedTable()); },
 GetFixedTable: function() { return this.grid.GetFixedTable(); },
 GetDataCellCore: function(recordKey, columnIndex) { return this.grid.GetRecordCell(this.ConvertKeyToVisibleIndex(recordKey), columnIndex); },
 GetDataCellByChild: function(element) { return this.grid.getRecordCellByChild(element); },
 GetRecordKeyByChild: function(element) {
  var cell = this.GetDataCellByChild(element);
  if(!cell) return;
  var visibleIndex = this.grid.GetRecordCellVisibleIndex(cell);
  return this.ConvertVisibleIndexToKey(visibleIndex);
 },
 GetGridItemByChild: function(element) { return this.grid.getItemByChild(element); },
 GetVisibleColumnIndices: function() { return this.grid.GetVisibleColumnIndices(true); },
 CanFocusCellCore: function(cellInfo) {
  return GridCellFocusHelper.prototype.CanFocusCellCore.call(this, cellInfo) || !this.grid.GetColumnStateExpandedHierarchically(cellInfo.columnIndex);
 },
 MakeCellVisible: function(cell) {
  GridCellFocusHelper.prototype.MakeCellVisible.call(this, cell);
  var columnIndex = this.GetColumnIndexByCell(cell);
  if(!this.grid.GetColumnStateExpandedHierarchically(columnIndex))
   this.grid.MakeRowVisible(columnIndex);
 },
 AddWrapperToDOM: function(wrapper, prev) {
  var fixedTable = this.GetFixedTable();
  if(fixedTable && prev)
   fixedTable.parentNode.insertBefore(wrapper, fixedTable);
  else
   GridCellFocusHelper.prototype.AddWrapperToDOM.call(this, wrapper, prev);
 },
 GetMainTableColumnIndex: function(cellInfo) { return cellInfo && cellInfo.recordKey; },
 IsRecordFocused: function(key) { return false; },
 IsRecordSelected: function(key) { return this.grid._isRowSelected(this.ConvertKeyToVisibleIndex(key)); },
});
ASPx.GridViewCellFocusHelper = GridViewCellFocusHelper;
ASPx.CardViewCellFocusHelper = CardViewCellFocusHelper;
ASPx.VerticalGridCellFocusHelper = VerticalGridCellFocusHelper;
})();

(function() {
var GridClipboardHelper = ASPx.CreateClass(null, {
 constructor: function(control) {
  this.control = control;
  this.focusedCellInfo = null;
  this.Initialize();
 },
 GetMainElement: function() { return this.control.GetMainElement(); },
 GetMainTable: function() { return this.control.GetMainTable(); },
 GetCellSelectionHelper: function() { return this.control.GetCellSelectionHelper(); },
 GetBatchEditHelper: function() { return this.control.GetBatchEditHelper(); },
 RaiseClipboardCellPasting: function(cellInfo, text, value) { return this.control.RaiseClipboardCellPasting(cellInfo, this.GetCellContent(cellInfo.recordKey, cellInfo.columnIndex), { text: text, value: value }); },
 GetRecordKeys: function() { return this.control.GetRecordKeys(); },
 GetIncorrectSelectionErrorText: function() { return this.control.incorrectSelectionError; },
 GetClipboardAccessDeniedErrorText: function() { return this.control.clipboardAccessDeniedError; },
 IsMainTableActive: function() { return ASPx.GetIsParent(this.GetMainTable(), ASPx.GetActiveElement()); },
 IsSelectionEnabled: function() { return !!this.GetCellSelectionHelper(); },
 GetDataRowLayout: function(recordKey) {
  var layout = [];
  var columnIndices = this.control.GetVisibleColumnIndices();
  ASPx.Data.ForEach(columnIndices, function(visibleIndex) {
   layout.push({ columnIndex: visibleIndex });
  }.bind(this));
  return [layout];
 },
 GetSelectedCells: function() {
  if(this.IsSelectionEnabled())
   return this.GetCellSelectionHelper().GetSelectedCells();
  return [this.focusedCellInfo];
 },
 Initialize: function() {
  this.AttachEvents();
 },
 AttachEvents: function() {
  ASPx.Evt.AttachEventToDocument("keydown", this.OnKeyDown.bind(this));
  ASPx.Evt.AttachEventToDocument("paste", this.OnPasteFromClipboard.bind(this));
 },
 OnKeyDown: function(evt) {
  var keyCode = ASPx.Evt.GetKeyCode(evt);
  if(evt.ctrlKey && keyCode === ASPx.KeyCode.Key_c && this.IsMainTableActive()) 
   this.CopyToClipboard();
 },
 OnFocusedCellChanged: function(cellInfo) {
  this.focusedCellInfo = cellInfo;
 },
 CopyToClipboard: function() {
  var selection = window.getSelection();
  if(selection && selection.toString().length > 0)
   return;
  var cells = this.GetSelectedCells();
  if(cells.length > 1)
   this.CopyMultipleCellsToClipboard(cells);
  else if(cells.length === 1)
   this.CopySingleCellToClipboard(cells[0]);
 },
 CopySingleCellToClipboard: function(cellInfo) {
  var cellContent = this.GetCellContent(cellInfo.recordKey, cellInfo.columnIndex);
  if(navigator.clipboard)
   navigator.clipboard.writeText(cellContent.text);
  else {
   var container = this.CreateHiddenContainer();
   var textArea = document.createElement("TEXTAREA");
   textArea.value = cellContent.text;
   container.appendChild(textArea);
   textArea.select();
   if(document.queryCommandEnabled("copy"))
    document.execCommand("copy");
   this.GetMainElement().removeChild(container);
  }
 },
 CopyMultipleCellsToClipboard: function(cells) {
  var matrix = this.CreateSelectionMatrix(cells);
  if(!this.ValidateSelection(matrix)) {
   alert(this.GetIncorrectSelectionErrorText());
   return;
  }
  var layout = this.EnsureTableLayout(matrix);
  var table = this.RenderSelectionTable(layout);
  if(navigator.clipboard && window.ClipboardItem) {
   var blob = new Blob([table.outerHTML], { type: "text/html" });
   navigator.clipboard.write([new ClipboardItem({ "text/html": blob })]);
  } else {
   var container = this.CreateHiddenContainer();
   container.appendChild(table);
   var selection = window.getSelection();
   selection.removeAllRanges();
   selection.selectAllChildren(table);
   if(document.queryCommandEnabled("copy"))
    document.execCommand("copy");
   selection.removeAllRanges();
   this.GetMainElement().removeChild(container);
  }
 },
 CreateHiddenContainer: function() {
  var container = document.createElement("DIV");
  ASPx.SetStyles(container, { "height": "1px", "width": "1px", "overflow": "hidden", "position": "absolute", "opacity": "0", "background-color": "white", "color": "black", "font-size": "14px" });
  this.GetMainElement().appendChild(container);
  return container;
 },
 CreateSelectionMatrix: function(cells) {
  return cells.reduce(function(map, element) {
   var key = element.recordKey;
   if(!map[key])
    map[key] = [];
   map[key].push(element.columnIndex);
   return map;
  }, {});
 },
 ValidateSelection: function(matrix) {
  var etalon = [];
  var keys = ASPx.GetObjectKeys(matrix);
  for(var i = 0; i < keys.length; i++) {
   var matrixRow = matrix[keys[i]];
   ASPx.Data.ArrayIntegerAscendingSort(matrixRow);
   if(i === 0)
    etalon = matrixRow;
   else if(!ASPx.Data.ArrayEqual(matrixRow, etalon))
    return false;
  }
  return true;
 },
 EnsureTableLayout: function(matrix) {
  var result = [];
  var keys = this.GetRecordKeys();
  var selectedKeys = ASPx.GetObjectKeys(matrix);
  ASPx.Data.ForEach(keys, function(key) {
   if(ASPx.Data.ArrayContains(selectedKeys, key))
    result.push(this.CreateRowLayout(key, matrix));
  }.bind(this));
  return ASPx.Data.ArrayFlatten(result);
 },
 CreateRowLayout: function(recordKey, matrix) {
  var result = [];
  var rowSpanCorrection = 0;
  var rowLayout = this.GetDataRowLayout(recordKey);
  ASPx.Data.ForEach(rowLayout, function(layout) {
   var row = [];
   ASPx.Data.ForEach(layout, function(cellInfo) {
    if(ASPx.Data.ArrayContains(matrix[recordKey], cellInfo.columnIndex)) {
     var cellContent = this.GetCellContent(recordKey, cellInfo.columnIndex);
     row.push({ colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan, cellInfo: { recordKey: recordKey, columnIndex: cellInfo.columnIndex }, content: cellContent });
    }
   }.bind(this));
   if(row.length > 0)
    result.push(row);
   else
    rowSpanCorrection++;
  }.bind(this));
  if(rowSpanCorrection > 0)
   this.CorrectRowSpans(result, rowSpanCorrection);
  return result;
 },
 CorrectRowSpans: function(rowLayout, correctionValue) {
  ASPx.Data.ForEach(rowLayout, function(layout) {
   ASPx.Data.ForEach(layout, function(cellInfo) {
    cellInfo.rowSpan = cellInfo.rowSpan - correctionValue;
   });
  });
 },
 RenderSelectionTable: function(layout) {
  var table = document.createElement("TABLE");
  ASPx.SetStyles(table, { "border-collapse": "collapse", "border-spacing": 0 });
  ASPx.Data.ForEach(layout, function(rowLayout) {
   var tr = table.insertRow();
   ASPx.Data.ForEach(rowLayout, function(cellInfo) {
    var td = tr.insertCell();
    td.appendChild(document.createTextNode(cellInfo.content.text || cellInfo.content.value || ""));
    td.colSpan = cellInfo.colSpan || 1;
    td.rowSpan = cellInfo.rowSpan || 1;
    if(cellInfo.content.value && cellInfo.content.value !== cellInfo.content.text)
     ASPx.Attr.SetAttribute(td, "data-dxvalue", cellInfo.content.value);
   }.bind(this));
  }.bind(this));
  return table;
 },
 GetCellContent: function(recordKey, columnIndex) {
  var batchHelper = this.GetBatchEditHelper();
  var info = batchHelper.GetCellValueInfo(recordKey, columnIndex);
  info.text = info.text.replace(/(<([^>]+)>)/ig, '').replace(/\s{2,}/g, '') || "";
  return info;
 },
 PasteFromClipboard: function() {
  if(navigator.clipboard && ASPx.Browser.WebKitFamily) {
   navigator.permissions.query({ name: 'clipboard-read' }).then(function(permission) {
    if(permission.state !== 'denied')
     navigator.clipboard.read().then(function(content) {
      for(var i = 0; i < content.length; i++) {
       if(ASPx.Data.ArrayContains(content[i].types, 'text/html'))
        content[i].getType('text/html').then(function(blob) { blob.text().then(this.PasteHtmlFromClipboard.bind(this)); }.bind(this));
       else if(ASPx.Data.ArrayContains(content[i].types, 'text/plain'))
        content[i].getType('text/plain').then(function(blob) { blob.text().then(this.PasteTextFromClipboard.bind(this)); }.bind(this));
      }
     }.bind(this));
    else
     alert(this.GetClipboardAccessDeniedErrorText());
   }.bind(this));
  }
  else
   alert(this.GetClipboardAccessDeniedErrorText());
 },
 OnPasteFromClipboard: function(evt) {
  if(evt && evt.clipboardData && evt.clipboardData.items && this.IsMainTableActive()) {
   var htmlData = evt.clipboardData.getData('text/html');
   if(htmlData.length > 0)
    this.PasteHtmlFromClipboard(htmlData);
   else {
    var textData = evt.clipboardData.getData('text/plain');
    this.PasteTextFromClipboard(textData);
   }
  }
 },
 PasteTextFromClipboard: function(textData) {
  if(textData.length > 0) {
   var cells = this.GetSelectedCells();
   ASPx.Data.ForEach(cells, function(cellInfo) {
    this.SetCellContent(cellInfo, textData);
   }.bind(this));
   this.OnPasteComplete();
  }
 },
 PasteHtmlFromClipboard: function(htmlData) {
  var bodyMatches = htmlData.match(/<body>([\s\S]+)<\/body>/mi);
  var htmlToParse = bodyMatches && bodyMatches.length > 1 ? bodyMatches[1] : htmlData;
  var element = ASPx.CreateHtmlElementFromString(htmlToParse);
  var parsedData = this.ParseClipboardElement(element);
  if(parsedData.length === 0 && element.innerText)
   this.PasteTextFromClipboard(element.innerText);
  else
   this.PasteMultipleData(parsedData);
 },
 ParseClipboardElement: function(element) {
  var result = [];
  if(element.tagName === "TABLE")
   result = this.ParseTable(element);
  else {
   var tables = ASPx.GetChildNodesByTagName(element, "TABLE");
   ASPx.Data.ForEach(tables, function(table) { result = result.concat(this.ParseTable(table)); }.bind(this));
  }
  if(element.nextElementSibling)
   result = result.concat(this.ParseClipboardElement(element.nextElementSibling));
  return result;
 },
 ParseTable: function(table) {
  var result = [];
  for(var i = 0; i < table.rows.length; i++) {
   var rowArr = [];
   for(var j = 0; j < table.rows[i].cells.length; j++) {
    var cellValue = ASPx.Attr.GetAttribute(table.rows[i].cells[j], "data-dxvalue");
    var content = cellValue ? [table.rows[i].cells[j].innerText, cellValue] : table.rows[i].cells[j].innerText;
    rowArr.push(content);
   }
   result.push(rowArr);
  }
  return result;
 },
 PasteMultipleData: function(data) {
  var cells = this.GetSelectedCells();
  var matrix = this.CreateSelectionMatrix(cells);
  var layout = this.EnsureTableLayout(matrix);
  for(var i = 0; i < data.length && i < layout.length; i++) {
   for(var j = 0; j < data[i].length && j < layout[i].length; j++)
    this.SetCellContent(layout[i][j].cellInfo, data[i][j]);
  }
  this.OnPasteComplete();
 },
 SetCellContent: function(cellInfo, content) {
  var text = ASPx.Ident.IsArray(content) ? content[0] : content;
  var value = ASPx.Ident.IsArray(content) ? content[1] : content;
  value = this.TryCorrectValue(cellInfo.columnIndex, value, text);
  var args = this.RaiseClipboardCellPasting(cellInfo, text, value);
  if(!args.cancel) {
   var batchHelper = this.GetBatchEditHelper();
   batchHelper.UpdateCellValue(cellInfo.recordKey, cellInfo.columnIndex, args.newValue, args.newText, args.newText != text);
  }
 },
 OnPasteComplete: function() {
  var batchHelper = this.GetBatchEditHelper();
  batchHelper.UpdateCommandButtonsEnabled(false);
 },
 TryCorrectValue: function(columnIndex, value, text) {
  var batchHelper = this.GetBatchEditHelper();
  var editor = batchHelper.GetEditor(columnIndex);
  if(editor) {
   if(window.ASPxClientSpinEditBase && editor instanceof ASPxClientSpinEditBase && !ASPx.IsNumber(value))
    value = (value || text).replace(/[^\d.,]/g, "");
   if(window.ASPxClientComboBoxBase && editor instanceof ASPxClientComboBoxBase) {
    var item = editor.FindItemByText(text);
    if(item && item.value !== null)
     value = item.value;
   }
  }
  return value || text;
 }
});
var GridViewClipboardHelper = ASPx.CreateClass(GridClipboardHelper, {
 constructor: function(gridView) {
  this.constructor.prototype.constructor.call(this, gridView);
  this.gridView = gridView;
 },
 GetLayoutHelper: function() { return this.gridView.GetLayoutHelper(); },
 GetDataRowLayoutInfo: function(visibleIndex) { return this.GetLayoutHelper().GetAdaptiveRowLayoutInfo(visibleIndex); },
 ConvertKeyToVisibleIndex: function(key) { return this.gridView.ConvertKeyToVisibleIndex(key); },
 GetDataRowLayout: function(recordKey) {
  var visibleIndex = this.ConvertKeyToVisibleIndex(recordKey);
  return this.GetDataRowLayoutInfo(visibleIndex).dataRowLayout;
 },
});
var VerticalGridClipboardHelper = ASPx.CreateClass(GridClipboardHelper, {
 constructor: function(verticalGrid) {
  this.constructor.prototype.constructor.call(this, verticalGrid);
  this.verticalGrid = verticalGrid;
 },
 EnsureTableLayout: function(matrix) {
  var layout = ASPx.GridClipboardHelper.prototype.EnsureTableLayout.call(this, matrix);
  return layout[0].map(function(col, i) { return layout.map(function(row) { return row[i]; }); });
 }
});
ASPx.GridClipboardHelper = GridClipboardHelper;
ASPx.GridViewClipboardHelper = GridViewClipboardHelper;
ASPx.VerticalGridClipboardHelper = VerticalGridClipboardHelper;
})();

(function() {
var GridCellSelectionHelper = ASPx.CreateClass(null, {
 constructor: function(control) {
  this.control = control;
  this.focusedCellInfo = null;
  this.kbdSourceCellInfo = null;
  this.selectedCellsInfo = [];
  this.lastMouseMoveElement = null;
  this.onMouseMoveHandler = this.OnMouseMove.bind(this);
  this.Initialize();
 },
 GetBatchEditHelper: function() { return this.control.GetBatchEditHelper(); },
 GetStyleHelper: function() { return this.control.GetStyleHelper(); },
 GetNavigationHelper: function() { return this.control.GetNavigationHelper(); },
 GetMainElement: function() { return this.control.GetMainElement(); },
 GetMainTable: function() { return this.control.GetMainTable(); },
 GetItemByHtmlEvent: function(evt) { return this.control.getItemByHtmlEvent(evt); },
 GetColumnIndex: function(element) { return this.GetBatchEditHelper().GetColumnIndexByChild(element); },
 RaiseCellSelectionChanging: function(cellInfo, isSelected) { return this.control.RaiseCellSelectionChanging(cellInfo, isSelected); },
 IsDataItemElement: function(item) { return false; },
 IsKeyboardEvent: function(e) { return e instanceof KeyboardEvent; },
 CreateCellInfo: function(recordKey, columnIndex) { return { recordKey: recordKey, columnIndex: columnIndex }; },
 IsCellInfoEqual: function(info1, info2) {
  return info1 && info2 && info1.columnIndex === info2.columnIndex && info1.recordKey === info2.recordKey;
 },
 GetDataCell: function(info) {
  return this.GetBatchEditHelper().GetDataCell(info.recordKey, info.columnIndex);
 },
 GetCellInfo: function(evt) {
  var source = ASPx.Evt.GetEventSource(evt);
  var item = this.GetItemByHtmlEvent(evt);
  if(this.IsDataItemElement(item)) {
   var key = this.GetBatchEditHelper().owner.GetRecordKeyByElement(item);
   var columnIndex = this.GetColumnIndex(source);
   return this.CreateCellInfo(key, columnIndex);
  }
  return null;
 },
 IsEditingCell: function(evt) {
  var cellInfo = this.GetCellInfo(evt);
  return cellInfo && this.GetBatchEditHelper().IsEditingCell(cellInfo.recordKey, cellInfo.columnIndex);
 },
 GetSelectedCells: function() {
  return this.selectedCellsInfo;
 },
 GetSelectedInfoIndex: function(cellInfo) {
  return ASPx.Data.ArrayIndexOf(this.selectedCellsInfo, cellInfo, this.IsCellInfoEqual);
 },
 IsCellSelected: function(cellInfo) {
  return this.GetSelectedInfoIndex(cellInfo) > -1;
 },
 SelectCell: function(cellInfo) {
  if(!this.IsCellSelected(cellInfo) && !this.RaiseCellSelectionChanging(cellInfo, true)) {
   var cell = this.GetDataCell(cellInfo);
   this.ApplySelectedStyle(cell, false);
   this.selectedCellsInfo.push(cellInfo);
  }
 },
 UnselectCell: function(cellInfo) {
  if(this.IsCellSelected(cellInfo) && !this.RaiseCellSelectionChanging(cellInfo, false)) {
   var cell = this.GetDataCell(cellInfo);
   this.ApplySelectedStyle(cell, true);
   var index = this.GetSelectedInfoIndex(cellInfo);
   this.selectedCellsInfo.splice(index, 1);
  }
 },
 UnselectAllCells: function() {
  ASPx.Data.ForEach(this.selectedCellsInfo.slice(), this.UnselectCell.bind(this));
 },
 ApplySelectedStyle: function(cell, reset) {
  var styleHelper = this.GetStyleHelper();
  var style = reset ? styleHelper.GetEmptyCellStyle() : styleHelper.GetSelectedCellStyle();
  styleHelper.UpdateCellSelectedStyle(style, cell);
 },
 Initialize: function() {
  this.AttachEvents();
 },
 Update: function() {
  this.AttachTableEvents();
 },
 OnAfterCallback: function() {
  this.selectedCellsInfo = [];
  this.Update();
 },
 AttachEvents: function() {
  ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.OnMouseUp.bind(this));
 },
 AttachTableEvents: function() {
  ASPx.Evt.AttachEventToElement(this.GetMainTable(), ASPx.TouchUIHelper.touchMouseDownEventName, this.OnMouseDown.bind(this));
 },
 OnMouseDown: function(e) {
  if(ASPx.Evt.IsLeftButtonPressed(e) && !e.shiftKey && !e.ctrlKey && !this.IsEditingCell(e)) {
   this.lastMouseMoveElement = null;
   ASPx.Evt.AttachEventToElement(this.GetMainTable(), ASPx.TouchUIHelper.touchMouseMoveEventName, this.onMouseMoveHandler);
  }
 },
 OnMouseUp: function(e) {
  if(ASPx.Evt.IsLeftButtonPressed(e))
   ASPx.Evt.DetachEventFromElement(this.GetMainTable(), ASPx.TouchUIHelper.touchMouseMoveEventName, this.onMouseMoveHandler);
 },
 OnMouseMove: function(e) {
  if(ASPx.Evt.IsLeftButtonPressed(e) && !e.shiftKey && !e.ctrlKey) {
   ASPx.Selection.ClearOnMouseMove(e);
   var source = ASPx.Evt.GetEventSource(e);
   if(this.lastMouseMoveElement !== source) {
    this.lastMouseMoveElement = source;
    var cellInfo = this.GetCellInfo(e);
    if(cellInfo && this.focusedCellInfo)
     this.RectangledSelect(cellInfo, this.focusedCellInfo);
   }
  }
 },
 OnFocusedCellChanged: function(cellInfo, e) {
  if(!e || ASPx.Evt.IsRightButtonPressed(e) && this.IsCellSelected(cellInfo))
   return;
  if(e.shiftKey)
   this.SelectWithShift(cellInfo, e);
  else if(e.ctrlKey)
   this.SelectWithCtrl(cellInfo);
  else
   this.SelectFocusedCell(cellInfo);
  this.focusedCellInfo = cellInfo;
  if(!this.IsKeyboardEvent(e) || !e.shiftKey)
   this.kbdSourceCellInfo = cellInfo;
 },
 SelectFocusedCell: function(cellInfo) {
  this.UnselectAllCells();
  this.SelectCell(cellInfo);
 },
 SelectWithCtrl: function(cellInfo) {
  if(!this.IsCellSelected(cellInfo))
   this.SelectCell(cellInfo);
  else
   this.UnselectCell(cellInfo);
 },
 SelectWithShift: function(cellInfo, e) {
  var srcCellInfo = this.focusedCellInfo;
  if(this.IsKeyboardEvent(e) && this.kbdSourceCellInfo)
   srcCellInfo = this.kbdSourceCellInfo;
  ASPx.Selection.Clear();
  this.RectangledSelect(srcCellInfo, cellInfo);
 },
 RectangledSelect: function(srcCell, destCell) {
  var helper = this.GetNavigationHelper();
  if(helper) {
   var selectionMatrix = helper.GetSelectionCellsInfo(srcCell, destCell);
   var selectionCellsInfo = ASPx.Data.ArrayFlatten(selectionMatrix);
   ASPx.Data.ForEach(this.selectedCellsInfo.slice(), function(cellInfo) {
    if(ASPx.Data.ArrayIndexOf(selectionCellsInfo, cellInfo, this.IsCellInfoEqual.bind(this)) < 0)
     this.UnselectCell(cellInfo);
   }.bind(this));
   ASPx.Data.ForEach(selectionCellsInfo, this.SelectCell.bind(this));
  }
 }
});
var GridViewCellSelectionHelper = ASPx.CreateClass(GridCellSelectionHelper, {
 constructor: function(gridView) {
  this.constructor.prototype.constructor.call(this, gridView);
  this.gridView = gridView;
 },
 IsDataItemElement: function(item) { return this.gridView.IsDataItemElement(item); },
});
var VerticalGridCellSelectionHelper = ASPx.CreateClass(GridCellSelectionHelper, {
 constructor: function(verticalGrid) {
  this.constructor.prototype.constructor.call(this, verticalGrid);
  this.verticalGrid = verticalGrid;
 },
 IsDataItemElement: function(item) { return item && this.verticalGrid.IsDataItem(item.visibleIndex); }
});
ASPx.GridCellSelectionHelper = GridCellSelectionHelper;
ASPx.GridViewCellSelectionHelper = GridViewCellSelectionHelper;
ASPx.VerticalGridCellSelectionHelper = VerticalGridCellSelectionHelper;
})();

(function() {
var TableScrollHelperCollection = {
 instances: { },
 add: function(helper){
  if(!helper || !helper.control)
   return;
  this.instances[helper.control.name] = helper;
 },
 onResize: function(){
  for(var key in this.instances) {
   if(!this.instances.hasOwnProperty(key)) continue;
   this.instances[key].OnWindowResize();
  }
 },
 RemoveDisposedObjects: function(){
  for(var key in this.instances){
   if(!this.instances.hasOwnProperty(key)) continue;
   var helper = this.instances[key];
   if(!helper || !helper.control || !ASPx.IsExists(helper.control.GetMainElement()))
    delete this.instances[key];
  }
 }
};
var TableScrollHelperBase = ASPx.CreateClass(ASPx.TableHelperAdapter, {
 constructor: function(tableHelper) {
  this.constructor.prototype.constructor.call(this, tableHelper);
  this.touchUIScroller = null;
  this.savedScrollLeft = this.IsRtl() ? 0x1fffffff : -1;
  this.savedScrollTop = 0;
  this.posLoggerHandler = null;
  this.scrollableControlHeight = -1;
  this.activeElementSettings = [ ];
  TableScrollHelperCollection.add(this);
 },
 Update: function() {
  this.AssignPosLoggerHandler(this.GetScrollDiv(this.GetContentTable()));
  if(this.HasHorzScroll()) {
   this.AssignScrollEvent(this.GetScrollDiv(this.GetHeaderTable()));
   this.AssignScrollEvent(this.GetScrollDiv(this.GetContentTable()));
  }
  if(ASPx.Browser.WebKitTouchUI)
   this.UpdateTouchUIScroller();
  this.UpdateScrollableControlsSize();
  if(this.tableHelper.control.resetScrollTop) {
   this.ResetScrollTop();
   this.tableHelper.control.resetScrollTop = false;
  }
  this.LoadScrollPosition();
  this.ApplyScrollPosition();
 },
 UpdateTouchUIScroller: function() {
  this.touchUIScroller = this.touchUIScroller || this.CreateTouchUIScroller();
  if(!ASPx.IsExistsElement(this.touchUIScroller.element))
   this.touchUIScroller.ChangeElement(this.GetScrollDiv(this.GetContentTable()));
 },
 CreateTouchUIScroller: function() {
  return ASPx.TouchUIHelper.MakeScrollable(this.GetScrollDiv(this.GetContentTable()), { 
   showHorizontalScrollbar: this.ShowTouchHorizontalScrollbar(),
   showVerticalScrollbar: this.ShowTouchVerticalScrollbar(),
   scrollPageIfCannotScrollDiv: true,
   forceCustomScroll: this.UseTouchCustomScroll()
  });
 },
 ShowTouchHorizontalScrollbar: function() {
  return this.HasHorzScroll();
 },
 ShowTouchVerticalScrollbar: function() {
  return this.HasVertScroll();
 },
 UseTouchCustomScroll: function() {
  return false;
 },
 AssignScrollEvent: function(element) {
  if(!element || element.scrollHelper == this || !this.tableHelper.control.IsDOMInitialized()) 
   return;
  element.scrollHelper = this;
  ASPx.Evt.AttachEventToElement(element, "scroll", this.OnScroll);
 },
 OnScroll: function(event) {
  var src = ASPx.Evt.GetEventSource(event);
  var helper = src.scrollHelper;
  if(helper)
   helper.OnScrollCore(src);
 },
 OnScrollCore: function(src) {
  var scrollDivs = [ this.GetScrollDiv(this.GetHeaderTable()), this.GetScrollDiv(this.GetContentTable()), this.GetScrollDiv(this.GetFooterTable()) ];
  if(src === scrollDivs[0] && this.NeedPreventHeaderScrollEvt()) 
   return;
  for(var i = 0; i < scrollDivs.length; i++) {
   var div = scrollDivs[i];
   if(!div || div == src)
    continue;
   if(i == 1)
    this.SetScrollLeftPostponed(div, src);
   else
    this.SetScrollLeft(div, src);
  }
 },
 OnBeforeCallback: function(command) {},
 SetScrollLeftPostponed: function(target, source) {
  if(!this.scrollUpdateTimerID || this.scrollUpdateTimerID == -1) {
   this.scrollUpdateTimerID = window.setTimeout(function() {
    this.SetScrollLeft(target, source);
    this.scrollUpdateTimerID = ASPx.Timer.ClearTimer(this.scrollUpdateTimerID);
   }.aspxBind(this), 0);
  }
 },
 SetScrollLeft: function(target, source) {
  if(target.scrollLeft != source.scrollLeft)
   target.scrollLeft = source.scrollLeft;
 },
 AssignPosLoggerHandler: function(element) {
  if(!element || !this.tableHelper.control.IsDOMInitialized()) return;
  if(!this.posLoggerHandler)
   this.posLoggerHandler = function() { this.LogScrollPosition(); }.aspxBind(this);
  ASPx.Evt.DetachEventFromElement(element, "scroll", this.posLoggerHandler);
  ASPx.Evt.AttachEventToElement(element, "scroll", this.posLoggerHandler);
 },
 OnWindowResize: function() {
  if(!this.IsOriginalWidthPercentage())
   return;
  window.setTimeout(function() { 
   this.UpdateScrollableControlsSize(true);
   var resizingHelper = this.GetResizingHelper();
   if(this.IsOriginalWidthPercentage() && resizingHelper)
    resizingHelper.ValidateColumnWidths();
  }.aspxBind(this), 0);
 },
 UpdateScrollableControlsSize: function(onResize) { 
  if(!this.control.IsDisplayed()) {
   this.control.ResetControlAdjustment();
   return;
  }
  if(this.control.GetMainElement())
   this.UpdateScrollableControlsSizeCore();
 },
 UpdateScrollableControlsSizeCore: function() {
  this.BeginUpdateScrollControlSize();
  var adjustedSize = this.CalcAutoAdjustedSize(); 
  var width = adjustedSize.rootCellWidth;
  var parts = this.GetDataParts();
  var scrollingParts = parts.filter(function(part) { return !this.RequireAddScrollPadding(part); }.bind(this));
  for(var i = 0; i < scrollingParts.length; i++) {
   var div = scrollingParts[i].parentNode;
   this.BringScrollableDivBackToFlow(div);
  }
  var scrollContainerPadding = this.GetScrollContainerPadding();
  for(var i = 0; i < parts.length; i++) {
   var part = parts[i];
   var div = part.parentNode;
   var excess = ASPx.GetLeftRightBordersAndPaddingsSummaryValue(this.RequireAddScrollPadding(part) ? div.parentNode : div);
   if(this.RequireAddScrollPadding(part)) {
    div.parentNode.style.paddingRight = scrollContainerPadding + "px";
    excess += scrollContainerPadding;
    this.BringScrollableDivBackToFlow(div);
   }
   if(!this.HasHorzScroll() && i === 0) {
    var actualWidth = part.offsetWidth + excess;
    if(!this.RequireAddScrollPadding(part))
     actualWidth += scrollContainerPadding;
    if(actualWidth > width)
     width = actualWidth;
   }
   if(this.RequireChangeScrollDivWidth())
    this.SetElementWidth(div, width - excess);
  }
  this.EndUpdateScrollControlSize(adjustedSize.mainElementWidth);
 },
 BringScrollableDivBackToFlow: function(scrollableDiv) {
  ASPx.SetStyles(scrollableDiv, { width: "", display: "" });
 },
 GetDataParts: function() { 
  var result = [];
  var parts = this.GetDataPartsCore();
  for(var i = 0; i < parts.length; i++)
   if(parts[i]) result.push(parts[i]);
  return result;
 },
 GetDataPartsCore: function() { return [ this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable() ]; },
 BeginUpdateScrollControlSize: function() {
  this.SaveActiveElement();
  if(this.HasVertScroll() && this.scrollableControlHeight > -1)
   this.SetHeightCore(this.scrollableControlHeight);
  var mainElement = this.control.GetMainElement();
  var contentScrollDiv = this.GetScrollDiv(this.GetContentTable());
  this.savedScrollInfo = { 
   scrollTop: contentScrollDiv.scrollTop, 
   scrollLeft: contentScrollDiv.scrollLeft,
   mainElementHeight: mainElement.style.height,
   outerScrollPosition: ASPx.GetOuterScrollPosition(mainElement),
  };
 },
 EndUpdateScrollControlSize: function(mainElementWidth) {
  var mainElement = this.control.GetMainElement();
  var contentScrollDiv = this.GetScrollDiv(this.GetContentTable());
  mainElement.style.width = mainElementWidth + "px";
  mainElement.style.height = this.savedScrollInfo.mainElementHeight;
  contentScrollDiv.scrollTop = this.savedScrollInfo.scrollTop;
  contentScrollDiv.scrollLeft = this.savedScrollInfo.scrollLeft;
  ASPx.RestoreOuterScrollPosition(this.savedScrollInfo.outerScrollPosition);
  if(this.IsContentTableEmpty() && this.HasHorzScroll() && this.GetHeaderTable()) 
   this.GetContentTable().style.width = this.GetHeaderTable().offsetWidth + "px";
  this.RestoreActiveElement();
  ASPx.GetControlCollection().AdjustControls(this.control.GetMainElement());
 },
 CalcAutoAdjustedSize: function() {
  var mainElement = this.control.GetMainElement();
  var rootCell = this.control.GetGridTD();
  ASPx.RestoreElementOriginalWidth(mainElement);
  mainElement.style.height = rootCell.offsetHeight + "px";
  this.HideInnerControls();
  var mainElementWidth = mainElement.offsetWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainElement);
  var rootCellWidth = mainElementWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(rootCell);
  return { mainElementWidth: mainElementWidth, rootCellWidth: rootCellWidth };
 },
 HideInnerControls: function() {
  var parts = this.GetDataParts();
  for(var i = 0; i < parts.length; i++) {
   var part = parts[i];
   var div = part.parentNode;
   this.RemoveScrollableDivFromFlow(div);
   if(this.RequireAddScrollPadding(part))
    div.parentNode.style.paddingRight = "";
  }
 },
 RemoveScrollableDivFromFlow: function(scrollableDiv) {
  scrollableDiv.style.display = "none";
 },
 RequireChangeScrollDivWidth: function() { return true; },
 RequireAddScrollPadding: function(part) { return part != this.GetContentTable(); },
 IsVerticalScrollBarShowed: function() {
  if(!this.HasVertScroll())
   return false;
  if(this.tableHelper.IsVertAutoScroll())
   return this.GetContentTableExcessHeight() > 0;
  return true;
 },
 GetContentTableExcessHeight: function() {
  var contentDiv = this.GetScrollDiv(this.GetContentTable());
  if(this.CanHaveHorzScrollBar())
   return this.GetContentTableExcessHeightCore(contentDiv);
  return contentDiv.scrollHeight > contentDiv.clientHeight;
 },
 GetContentTableExcessHeightCore: function(contentDiv) {
  var scrollSize = ASPx.GetVerticalScrollBarWidth();
  var contentWidth = 0;
  var contentHeight = 0;
  for(var i = 0; i < contentDiv.childNodes.length; i++) {
   var child = contentDiv.childNodes[i];
   if(child.nodeType != 1) 
    continue;
   contentWidth = Math.max(contentWidth, child.offsetWidth);
   contentHeight += child.offsetHeight;
  }
  var divWidth = ASPx.GetClearClientWidth(contentDiv);
  var divHeight = ASPx.GetClearClientHeight(contentDiv);
  var divHasHorzScroll = contentWidth > divWidth;
  var divHasVertScroll = contentHeight > divHeight;
  if(!divHasHorzScroll && divHasVertScroll)
   divHasHorzScroll = contentWidth > (divWidth - scrollSize);
  if(divHasHorzScroll && !divHasVertScroll)
   divHasVertScroll = contentHeight > (divHeight - scrollSize);
  var result = contentHeight - divHeight;
  if(divHasVertScroll)
   result += scrollSize;
  return result;
 },
 CanHaveHorzScrollBar: function() { return true; },
 UpdateScrollContainerPadding: function() {
  var padding = this.GetScrollContainerPadding();
  var tables = [ this.GetHeaderTable(), this.GetFooterTable() ];
  for(var i = 0; i < tables.length; i++) {
   var scrollDiv = this.GetScrollDiv(tables[i]);
   if(!scrollDiv) continue;
   var oldPadding = ASPx.PxToInt(scrollDiv.parentNode.style.paddingRight);
   if(oldPadding === padding) continue;
   this.UpdateScrollContainerPaddingCore(scrollDiv, oldPadding, padding);
  }
 },
 UpdateScrollContainerPaddingCore: function(scrollDiv, oldPadding, padding) {
  var paddingDiff = oldPadding - padding;
  var scrollDivWidth = ASPx.PxToInt(scrollDiv.style.width) + paddingDiff;
  scrollDiv.parentNode.style.paddingRight = padding + "px";
  scrollDiv.style.width = scrollDivWidth + "px";
 },
 GetScrollContainerPadding: function() { 
  if(!this.IsVerticalScrollBarShowed())
   return 0;
  var contentTableScrollDiv = this.GetScrollDiv(this.GetContentTable());
  if(ASPx.Browser.WebKitTouchUI && ASPx.TouchUIHelper.HasCustomizedNativeScrollBarClass(contentTableScrollDiv))
   return contentTableScrollDiv.offsetWidth - contentTableScrollDiv.clientWidth - ASPx.GetHorizontalBordersWidth(contentTableScrollDiv);
  return ASPx.GetVerticalScrollBarWidth(); 
 },
 IsContentTableEmpty: function() { return false; },
 SetElementWidth: function(element, width) {
  if(!element || width <= 0) 
   return;
  element.style.width = width + "px";
 },
 GetScrollDiv: function(childTable) {
  if(!childTable) return null;
  return childTable.parentNode;
 },
 GetArmatureExtraCell: function(table) {
  var cells = this.GetArmatureCells(table);
  return cells[cells.length - 1];
 },
 MakeCellVisible: function(cell) {
  var div = this.GetScrollDiv(this.GetContentTable());
  if(div == null || !cell) 
   return;
  if(this.HasVertScroll())
   this.ScrollDivToShowCell(div, cell);
  if(this.HasHorzScroll() && ASPx.GetCurrentStyle(div).overflowX !== "hidden")
   this.ScrollDivToShowCell(div, cell, true);
 },
 ScrollDivToShowCell: function(div, cell, isHorizontal){
  var divScrollStart = isHorizontal ? div.scrollLeft : div.scrollTop;
  var divStart = isHorizontal ? ASPx.GetAbsoluteX(div) : ASPx.GetAbsoluteY(div);
  var divSize = isHorizontal ? div.clientWidth : div.clientHeight;
  var cellStart = isHorizontal ? ASPx.GetAbsoluteX(cell) : ASPx.GetAbsoluteY(cell);
  var cellSize = isHorizontal ? cell.offsetWidth : cell.offsetHeight;
  var scrollMethod = function(pos) {
   if(isHorizontal) {
    this.PreventHeaderScrollEvt();
    this.SetHorzScrollPosition(pos);
   } else
    this.SetVertScrollPosition(pos);
  }.aspxBind(this);
  var diff = divStart - cellStart;
  if(diff > 0){
   scrollMethod(divScrollStart - diff);
   return;
  }
  var divEnd = divStart + divSize + 1;
  var cellEnd = cellStart + cellSize;
  diff = cellEnd - divEnd;
  if(diff > 0) {
   scrollMethod(divScrollStart + diff);
  }
 },
 PreventHeaderScrollEvt: function() {
  this.preventHeaderScrollEvt = true;
  if(this.preventHeaderScrollEvtTimerID)
    ASPx.Timer.ClearTimer(this.preventHeaderScrollEvtTimerID);
  this.preventHeaderScrollEvtTimerID = window.setTimeout(function() {
   this.preventHeaderScrollEvt = false;
   delete this.preventHeaderScrollEvtTimerID;
  }.aspxBind(this), 50);
 },
 NeedPreventHeaderScrollEvt: function() { return !!this.preventHeaderScrollEvt; },
 MakeRowVisible: function(row, fromKbdHelper) {
  var div = this.GetScrollDiv(this.GetContentTable());
  if(div == null || !row || !this.HasVertScroll()) 
   return;
  var divTop = ASPx.GetAbsoluteY(div);
  var rowTop = ASPx.GetAbsoluteY(row);
  var topDiff = divTop - rowTop;
  if(topDiff > 0) {
   div.scrollTop -= topDiff;
   return; 
  }
  var divBottom = divTop + div.clientHeight + 1;
  var rowBottom = rowTop + row.offsetHeight;
  var bottomDiff = rowBottom - divBottom;
  if(bottomDiff <= 0) return;
  var diff = fromKbdHelper ? bottomDiff : topDiff * -1;
  div.scrollTop += diff;
 },
 GetHorzScrollableControl: function() {
  if(this.HasHorzScroll()) 
   return this.GetScrollDiv(this.GetContentTable());
  return null;
 },
 GetVertScrollableControl: function() {
  if(this.HasVertScroll()) 
   return this.GetScrollDiv(this.GetContentTable());
  return null;
 },
 LogScrollPosition: function() {
  if(!this.control.GetMainElement()) return;
  if(this.HasHorzScroll())
   this.savedScrollLeft = this.GetHorzScrollableControl().scrollLeft;
  if(this.HasVertScroll())
   this.savedScrollTop = this.GetVertScrollableControl().scrollTop;
  this.SaveScrollPosition();
 },
 SetScrollState: function(state) { },
 GetScrollState: function() { },
 SaveScrollPosition: function() {
  this.SetScrollState([this.savedScrollLeft, this.savedScrollTop]);
 },
 LoadScrollPosition: function() {
  var savedState = this.GetScrollState();
  if(savedState && savedState.length === 2) {
   this.savedScrollLeft = Number(savedState[0]);
   this.savedScrollTop = Number(savedState[1]);
  }
 },
 ApplyScrollPosition: function() {
  this.SetHorzScrollPosition(this.savedScrollLeft);
  this.SetVertScrollPosition(this.savedScrollTop);
 },
 SetHorzScrollPosition: function(pos) {
  if(!this.HasHorzScroll() || pos < 0) 
   return;
  this.SetScrollPositionCore(this.GetHorzScrollableControl(), pos, false);
 },
 SetVertScrollPosition: function(pos) {
  if(!this.HasVertScroll() || pos < 0)
   return;
  this.SetScrollPositionCore(this.GetVertScrollableControl(), pos, true);
 },
 SetScrollPositionCore: function(element, pos, isTop) {
  if(isTop) {
   if(element.scrollTop != pos)
    element.scrollTop = pos;
  } else if(element.scrollLeft != pos) {
   element.scrollLeft = pos;
  }
 },
 GetHorzScrollPosition: function() {
  if(!this.HasHorzScroll()) return 0;
  return this.GetScrollPositionCore(this.GetHorzScrollableControl(), false);
 },
 GetVertScrollPosition: function() {
  if(!this.HasVertScroll()) return 0;
  return this.GetScrollPositionCore(this.GetVertScrollableControl(), true);
 },
 GetScrollPositionCore: function(element, isTop) {
  return isTop ? element.scrollTop : element.scrollLeft;
 },
 ResetScrollTop: function() {
  this.savedScrollTop = 0;
  this.SaveScrollPosition();
 },
 SetHeight: function(height) {
  if(!this.HasVertScroll() || this.scrollableControlHeight === height) 
   return;
  this.scrollableControlHeight = height;
  this.SetHeightCore(height);
  this.Update();
 },
 SetHeightCore: function(height) {
  var mainElement = this.control.GetMainElement();
  var div = this.GetVertScrollableControl();
  var mainElementHeight = mainElement.offsetHeight;
  height = ASPx.PxToFloat(div.style.height) + (height - mainElementHeight);
  div.style.height = Math.max(height, 0) + "px";
 },
 OnSetWidth: function() {
  ASPx.DropElementOriginalWidth(this.control.GetMainElement());
 },
 IsOriginalWidthPercentage: function() {
  var mainElement = this.control.GetMainElement();
  var width = String(ASPx.GetElementOriginalWidth(mainElement));
  return ASPx.IsPercentageSize(width);
 },
 SaveActiveElement: function () { ASPx.GridCommonUtils.SaveActiveElement(this.control); },
 RestoreActiveElement: function () { ASPx.GridCommonUtils.RestoreActiveElement(this.control); },
 GetPopupEditFormHorzOffsetCorrection: function(popup) {
  var scrollDiv = this.GetHorzScrollableControl();
  if(!scrollDiv) return 0;
  var horzAlign = popup.GetHorizontalAlign();
  if(ASPx.PopupUtils.IsRightSidesAlign(horzAlign) || ASPx.PopupUtils.IsOutsideRightAlign(horzAlign))
   return scrollDiv.scrollWidth - scrollDiv.offsetWidth;
  if(ASPx.PopupUtils.IsCenterAlign(horzAlign))
   return (scrollDiv.scrollWidth - scrollDiv.offsetWidth) / 2;
  return 0;
 }
});
TableScrollHelperBase.prevBodyWidth = document.body ? document.body.offsetWidth : -1;
ASPx.Evt.AttachEventToElement(window, "resize", function(e) {
 if(!document.body) return; 
 var width = document.body.offsetWidth;
 if(width == TableScrollHelperBase.prevBodyWidth)
  return;
 TableScrollHelperBase.prevBodyWidth = width;
 TableScrollHelperCollection.onResize();
});
ASPx.TableScrollHelperCollection = TableScrollHelperCollection;
ASPx.TableScrollHelperBase = TableScrollHelperBase;
})();

(function() {
var GridTableScrollHelper = ASPx.CreateClass(ASPx.TableScrollHelperBase, {
 constructor: function(tableHelper) {
  this.constructor.prototype.constructor.call(this, tableHelper);
 },
 UpdateScrollableControlsSize: function(onResize) {
  var hasFixedColumns = this.HasFixedColumns();
  if(onResize && hasFixedColumns)
   return;
  if(hasFixedColumns)
   this.CollapseFixedDivs();
  ASPx.TableScrollHelperBase.prototype.UpdateScrollableControlsSize.call(this, onResize);
  if(hasFixedColumns){
   this.RestoreFixedDivSize();
   if(this.scrollableControlHeight > -1)
    this.RestoreScrollableControlHeight();
  }
 },
 GetFixedDivs: function() {
  var fixedHelper = this.control.GetFixedColumnsHelper();
  if(!fixedHelper)
   return [];
  var fixedDiv = fixedHelper.GetFixedDiv();
  var divs = [fixedDiv, this.GetScrollDiv(this.GetContentTable())];
  return divs;
 },
 CollapseFixedDivs: function() {
  var divs = this.GetFixedDivs();
  for(var i = 0; i < divs.length; i++)
   this.SetElementWidth(divs[i], 1);
  var fixedHelper = this.control.GetFixedColumnsHelper();
  if(fixedHelper)
   fixedHelper.UpdateFixedDivHeight();
 },
 RestoreFixedDivSize: function() {
  var fixedHelper = this.control.GetFixedColumnsHelper();
  if(!fixedHelper) return;
  var mainTable = this.control.GetMainElement();
  var divs = this.GetFixedDivs();
  if(this.IsOriginalWidthPercentage(mainTable))
   ASPx.RestoreElementOriginalWidth(mainTable);
  var width = mainTable.offsetWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainTable);
  if(width < 0) 
   width = 0;
  for(var i = 0; i < divs.length; i++)
   this.SetElementWidth(divs[i], width - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(divs[i]));
  fixedHelper.Update();
 },
 HasFixedColumns: function() { return true; },
 ShowTouchHorizontalScrollbar: function() {
  return this.HasHorzScroll() && !this.HasFixedColumns();
 },
 UseTouchCustomScroll: function() {
  return this.HasFixedColumns();
 },
 SetScrollState: function(position) {
  this.control.stateObject.scrollState = position;
 },
 GetScrollState: function() {
  return this.control.stateObject.scrollState;
 },
 AssignPosLoggerHandler: function(element) {
  if(this.HasVertScroll() || !this.HasFixedColumns())
   ASPx.TableScrollHelperBase.prototype.AssignPosLoggerHandler.call(this, element);
  if(this.HasFixedColumns())
   ASPx.TableScrollHelperBase.prototype.AssignPosLoggerHandler.call(this, this.control.GetFixedColumnsDiv());
 },
 GetHorzScrollableControl: function() {
  if(this.HasFixedColumns())
   return this.control.GetFixedColumnsDiv();
  return ASPx.TableScrollHelperBase.prototype.GetHorzScrollableControl.call(this);
 },
 LoadScrollPosition: function() {
  ASPx.TableScrollHelperBase.prototype.LoadScrollPosition.call(this);
  var grid = this.control;
  if(grid.rtl && this.HasFixedColumns() && this.savedScrollLeft == 0)
   this.savedScrollLeft = 1;
 },
 RestoreScrollableControlHeight: function() {
  var fixedHelper = this.control.GetFixedColumnsHelper();
  if(!fixedHelper)
   return;
  if(fixedHelper.CanUpdateFixedDivVisibility() && !ASPx.GetElementDisplay(fixedHelper.GetFixedDiv()))
   this.SetHeightCore(this.scrollableControlHeight);
 }
});
ASPx.GridTableScrollHelper = GridTableScrollHelper;
})();

(function() {
var TableFixedColumnsHelper = ASPx.CreateClass(ASPx.TableHelperAdapter, {
 HiddenFixedColumnClassName: "dxgvHFC",
 StyleSheetRowHeightsId: "RowHeights",
 constructor: function(tableHelper, fixedDivName, fixedContentDivName, fixedColumnCount){
  this.constructor.prototype.constructor.call(this, tableHelper);
  this.FixedDivName = fixedDivName;
  this.FixedContentDivName = fixedContentDivName;
  this.FixedColumnCount = fixedColumnCount;
  this.hiddenColumnCount = 0;
  this.touchUIScroller = null;
  this.mouseScroller = null;
  this.leafIndices = null;
  this.savedScrollPos = -1;
 },
 GetAllTables: function() { return [this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable()].filter(function(table) { return !!table; }); },
 GetFixedDiv: function() { return this.tableHelper.GetChildElement(this.FixedDivName); },
 GetFixedContentDiv: function() { return this.tableHelper.GetChildElement(this.FixedContentDivName); },
 GetFixedCellCount: function() { return this.FixedColumnCount; },
 GetHorizontalExtraCellClassName: function() { }, 
 Update: function() {
  this.AttachEvent(this.GetFixedDiv(), "scroll", this.OnScroll);
  this.PreventTablesScroll();
  if(ASPx.Browser.TouchUI)
   this.UpdateMouseScroller();
  if(ASPx.Browser.WebKitTouchUI)
   this.UpdateTouchUIScroller();
  if(ASPx.Browser.MacOSPlatform && (ASPx.Browser.WebKitFamily || ASPx.Browser.Firefox)) 
   this.UpdateWheelScroller();
  this.UpdateFixedDivSize();
  if(this.CanUpdateFixedDivVisibility())
   this.UpdateFixedDivVisibility();
 },
 PreventTablesScroll: function() {
  var contentDiv = this.GetContentTable().parentNode;
  var expectedLeft = this.control.rtl ? 0x1fffffff : 0;
  var scrollDivs = this.GetAllTables().map(function(table) { return table.parentNode; });
  this.AttachEvent(contentDiv, "scroll", function() {
   scrollDivs.forEach(function(div) {
    if(div.scrollLeft !== expectedLeft)
     div.scrollLeft = expectedLeft;
   });
  });
 },
 UpdateFixedDivSize: function() {
  var fixedDiv = this.GetFixedDiv();
  if(ASPx.Browser.WebKitFamily && fixedDiv.scrollLeft == 0 && this.savedScrollPos > 0) 
   fixedDiv.scrollLeft = this.savedScrollPos;
  var fixedContentDiv = this.GetFixedContentDiv();
  var contentDivStyleWidth = fixedContentDiv.style.width;
  var contentDivWidth = this.GetFixedContentDivWidth() + "px";
  if(contentDivStyleWidth !== contentDivWidth)
   fixedContentDiv.style.width = contentDivWidth;
  this.UpdateFixedDivHeight();
  this.UpdateRowHeights();
 },
 CanUpdateFixedDivVisibility: function() {
  return this.control.GetTableHelper().IsHorzAutoScroll();
 },
 UpdateFixedDivVisibility: function() {
  var fixedDiv = this.GetFixedDiv();
  if(!fixedDiv) return;
  var fixedDivWidth = this.GetElementWidth(fixedDiv);
  var fixedContentDivWidth = this.GetElementWidth(this.GetFixedContentDiv());
  var visible = fixedDivWidth < fixedContentDivWidth;
  if(!visible && ASPx.GetElementDisplay(fixedDiv))
   this.UpdateCellsVisibility(0);
  ASPx.SetElementDisplay(fixedDiv, visible);
 },
 GetElementWidth: function(element) {
  return ASPx.PxToInt(ASPx.GetElementOriginalWidth(element));
 },
 UpdateFixedDivHeight: function() {
  var fixedDiv = this.GetFixedDiv();
  var fixedContentDiv = this.GetFixedContentDiv();
  var contentDivHeight = this.GetFixedContentDivHeight() + "px";
  var contentDivStyleHeight = fixedContentDiv.style.height;
  if(contentDivStyleHeight !== contentDivHeight || fixedDiv.style.height !== contentDivHeight)
   fixedContentDiv.style.height = fixedDiv.style.height = contentDivHeight;
 },
 GetFixedContentDivWidth: function() {
  var armCells = this.GetArmatureCells(this.GetHeaderTable() || this.GetContentTable());
  var totalWidth = 0;
  for(var i = 0; i < armCells.length; i++) {
   var width = this.GetStylePxWidth(armCells[i]);
   totalWidth += width > -1 ? width : 0;
  }
  if(this.control.HasVertScroll()) 
   totalWidth += ASPx.GetVerticalScrollBarWidth();
  return totalWidth;
 },
 GetFixedContentDivHeight: function() {
  var scrollHeigth = ASPx.GetVerticalScrollBarWidth() + 1; 
  if(ASPx.Browser.MacOSPlatform && ASPx.Browser.WebKitFamily && ASPx.GetVerticalScrollBarWidth() == 0) 
   scrollHeigth = 12;
  return scrollHeigth;
 },
 OnScroll: function(event) {
  var src = ASPx.Evt.GetEventSource(event);
  var helper = src.fixedHelper;
  helper.savedScrollPos = src.scrollLeft;
  helper.UpdateCellsVisibility(helper.GetColumnsToHide(src.scrollLeft));
 },
 AttachEvent: function(element, eventName, eventHandler) {
  if(!element) return;
  var eventMarker = "gvfh" + eventName;
  if(element[eventMarker])
   return;
  ASPx.Evt.AttachEventToElement(element, eventName, eventHandler);
  element[eventMarker] = true;
  element.fixedHelper = this;
 },
 DetacheEvent: function(element, eventName, eventHandler) {
  if(!element) return;
  ASPx.Evt.DetachEventFromElement(element, eventName, eventHandler);
  var eventMarker = "gvfh" + eventName;
  element[eventMarker] = false;
  element.fixedHelper = null;
 },
 SetScrollLeft: function(target, scrollLeft) {
  if(target.scrollLeft != scrollLeft)
   target.scrollLeft = scrollLeft;
 },
 UpdateMouseScroller: function() {
  var getContentDiv = function() { return this.GetContentTable().parentNode; }.aspxBind(this);
  if(!this.mouseScroller) {
   this.mouseScroller = ASPx.MouseScroller.Create(
    getContentDiv,
    function() { return this.GetFixedDiv(); }.aspxBind(this),
    getContentDiv,
    function(element) { return this.control.IsHeaderChild(element); }.aspxBind(this),
    true,
    function(e) { this.UpdateTouchScrollBars(); }.aspxBind(this),
    function(e) { this.UpdateTouchScrollBars(); }.aspxBind(this),
    function(e) { this.UpdateTouchScrollBars(true); }.aspxBind(this),
    function(e) { this.UpdateTouchScrollBars(true); }.aspxBind(this)
   );
  } else {
   this.mouseScroller.update();
  }
 },
 UpdateTouchUIScroller: function() {
  this.touchUIScroller = this.touchUIScroller || this.CreateTouchUIScroller();
  if(!ASPx.IsExistsElement(this.touchUIScroller.element))
   this.touchUIScroller.ChangeElement(this.GetFixedDiv());
  this.touchUIScroller.updateInitData();
 },
 CreateTouchUIScroller: function() {
  return ASPx.TouchUIHelper.MakeScrollable(this.GetFixedDiv(), { 
   showHorizontalScrollbar: true, 
   showVerticalScrollbar: false,
   forceCustomScroll: true
  });
 },
 UpdateTouchScrollBars: function(hide) {
  if(!this.touchUIScroller) 
   return;
  if(hide) {
   this.touchUIScroller.hideScrollBars();
  } else {
   this.touchUIScroller.updateScrollHandles();
   this.touchUIScroller.showScrollBars();
  }
 },
 UpdateWheelScroller: function() {
  var contentDiv = this.GetContentTable().parentNode;
  if(this.wheelHandler)
   ASPx.Evt.DetachEventFromElement(contentDiv, ASPx.Evt.GetMouseWheelEventName(), this.wheelHandler);
  this.wheelHandler = this.wheelHandler || this.CreateWheelHandler();
  ASPx.Evt.AttachEventToElement(contentDiv, ASPx.Evt.GetMouseWheelEventName(), this.wheelHandler);
 },
 CreateWheelHandler: function() {
  return function(e) {
   var wheelDelta = ASPx.Evt.GetWheelDeltaX(e);
   if(!wheelDelta)
    return;
   var fixedDiv = this.GetFixedDiv();
   var delta = wheelDelta / 120;
   var leftDirection = delta > 0;
   var isLeftmost = fixedDiv.scrollLeft == 0;
   var isRightmost = fixedDiv.scrollLeft + fixedDiv.offsetWidth == fixedDiv.scrollWidth;
   if(leftDirection && isLeftmost || !leftDirection && isRightmost)
    return;
   fixedDiv.scrollLeft += -1 * delta * 100;
   return ASPx.Evt.PreventEvent(e);
  }.aspxBind(this);
 },
 GetColumnsToHide: function(pos) {
  var grid = this.control;
  var indices = this.GetVisibleColumnIndices();
  if(grid.rtl)
   pos = this.GetFixedContentDiv().scrollWidth - pos - ASPx.GetClearClientWidth(grid.GetMainElement());
  var i;
  var width = 0;
  for(i = this.FixedColumnCount; i < indices.length; i ++) {
   if(width >= pos) break;    
   width += this.GetColumnWidth(indices[i]);
  }
  return i - this.FixedColumnCount;
 },
 GetVisibleColumnIndices: function() { return []; },
 UpdateCellsVisibility: function(columnsToHide) {
  if(this.hiddenColumnCount == columnsToHide)
   return;
  var prevHiddenColumnCount = this.hiddenColumnCount;
  this.hiddenColumnCount = columnsToHide;
  var startIndex = Math.min(prevHiddenColumnCount, this.hiddenColumnCount) + this.GetFixedCellCount();
  var endIndex = Math.max(prevHiddenColumnCount, this.hiddenColumnCount) + this.GetFixedCellCount();
  var visible = this.hiddenColumnCount - prevHiddenColumnCount <= 0;
  this.UpdateCellsVisibilityCore(startIndex, endIndex, visible);
 },
 UpdateCellsVisibilityCore: function(startIndex, endIndex, visible) {
  var display = visible ? "" : "none";
  var tables = [ this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable() ];
  for(var tableIndex = 0; tableIndex < tables.length; tableIndex++) {
   var table = tables[tableIndex];
   if(!table)
    continue;
   var armCells = this.GetArmatureCells(table);
   for(var i = startIndex; i < endIndex; i++)
    this.SetCellVisible(armCells[i], visible);
   for(var rowIndex = 0; rowIndex < table.rows.length; rowIndex++) {
    var row = table.rows[rowIndex];
    this.ChangeCellsVisibility(row, startIndex, endIndex - 1, display);
   }
  }
 },
 ChangeCellsVisibility: function(row, startIndex, endIndex, display) { 
  var visible = display !== "none";
  var cells = this.GetRowCells(row);
  for(var i = startIndex; i <= endIndex; i++) {
   if(!cells[i])
    break;
   this.SetCellVisible(cells[i], visible);
  }
 },
 GetRowCells: function(row) {
  return row.cells;
 },
 UpdateRowHeights: function(forceUpdate) {
  var rows = this.GetRowsForHeightCorrection();
  var skipCorrection = true;
  for(var i = 0; i < rows.length; i++)
   skipCorrection &= !!rows[i].heightCorrected;
  if(skipCorrection && !forceUpdate)
   return;
  var savedColumnsToHide = this.hiddenColumnCount;
  if(savedColumnsToHide !== 0)
   this.UpdateCellsVisibility(0);
  this.UpdateRowHeightsCore(rows);
  if(savedColumnsToHide !== 0)
   this.UpdateCellsVisibility(savedColumnsToHide);
  for(var i = 0; i < rows.length; i++)
   rows[i].heightCorrected = true;
 },
 UpdateRowHeightsCore: function(rows) {
  this.ClearFixedColumnsStyleSheet(this.StyleSheetRowHeightsId);
  var styleSheetRules = this.GetStyleSheetRulesForHeightCorrection(rows);
  this.UpdateFixedColumnsStyleSheet(this.StyleSheetRowHeightsId, styleSheetRules);
 },
 ClearFixedColumnsStyleSheet: function(styleName) {
  ASPx.GridDynamicStyleSheetHelper.Instance.ClearStyleSheet(this.control, styleName);
 },
 UpdateFixedColumnsStyleSheet: function(styleName, rules) {
  ASPx.GridDynamicStyleSheetHelper.Instance.Update(this.control, styleName, rules);
 },
 GetRowsForHeightCorrection: function() {
  var tables = [ this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable() ];
  var rows = [ ];
  for(var tableIndex = 0; tableIndex < tables.length; tableIndex++) {
   var table = tables[tableIndex];
   if(!table) continue;
   for(var i = 0; i < table.rows.length; i++)
    rows.push(table.rows[i]);
  }
  return rows;
 },
 GetStyleSheetRulesForHeightCorrection: function(rows) {
  var selectors = { };
  var selectorMask = [ "#", "id", " > ", "td", "." + this.GetHorizontalExtraCellClassName() ];
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   if(row.cells.length < 1 || !row.id || !ASPx.GetElementDisplay(row)) 
    continue;
   var cell = this.GetExtraCell(row);
   var h = cell.offsetHeight;
   if(h <= 0) continue;
   if(!selectors[h])
    selectors[h] = [ ];
   var selectorArgs = selectorMask.slice(0);
   selectorArgs[1] = row.id;
   selectors[h].push(selectorArgs.join(""));
  }
  var rules = [ ];
  for(var height in selectors) {
   if(!selectors.hasOwnProperty(height)) continue;
   rules.push({ 
    selector: selectors[height].join(", "), 
    cssText: "height:" + height + "px"
   });
  }
  return rules;
 },
 GetExtraCellIndex: function(row) { return row.cells.length - 1; },
 GetExtraCell: function(row) { return row.cells[this.GetExtraCellIndex(row)]; },
 GetColumnWidth: function(columnIndex) { },
 SaveCallbackSettings: function() {
  this.savedScrollPos = -1;
 },
 RestoreCallbackSettings: function() {
  if(this.control.IsLastCallbackProcessedAsEndless())
   return;
  this.FixedColumnCount = this.control.fixedColumnCount;
  if(this.RequireResetHiddenColumnCount())
   this.ResetHiddenColumnCount();
  this.ClearFixedColumnsStyleSheet(this.StyleSheetRowHeightsId);
 },
 RequireResetHiddenColumnCount: function() {
  var scrollHelper = this.control.GetScrollHelper();
  var fixedDiv = this.GetFixedDiv();
  return fixedDiv.scrollLeft != scrollHelper.savedScrollLeft;
 },
 ResetHiddenColumnCount: function() {
  this.hiddenColumnCount = 0;
 },
 SetCellVisible: function(cell, visible) {
  if(!cell) return;
  var action = visible ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
  action(cell, this.HiddenFixedColumnClassName);
  this.control.ChangeCellInitialClass(cell, this.HiddenFixedColumnClassName, !visible);
 },
 TryShowColumn: function(columnIndex, showFullRect) {
  var cellIndex = this.ConvertToCellIndex(columnIndex);
  if(cellIndex < 0) return false;
  var hiddenColumnCount = this.CalcHiddenColumnCount(cellIndex, showFullRect);
  if(this.hiddenColumnCount === hiddenColumnCount)
   return false;
  var columnsWidth = this.GetHiddenColumnsTotalWidth(hiddenColumnCount);
  var scrollLeft = columnsWidth > 10 ? columnsWidth - 10 : 0;
  this.UpdateCellsVisibility(hiddenColumnCount);
  this.control.SetHorizontalScrollPosition(scrollLeft);
  return true;
 },
 CalcHiddenColumnCount: function(cellIndex, showFullRect) {
  var scrollDivWidth = this.GetContentTable().parentNode.offsetWidth;
  var columnDimensions = this.CalculateColumnDimensions();
  var columnCount = this.GetColumnCount();
  return this.CalcHiddenColumnCountCore(cellIndex, showFullRect, scrollDivWidth, columnDimensions, this.FixedColumnCount, this.hiddenColumnCount, columnCount);
 },
 CalcHiddenColumnCountCore: function(cellIndex, showFullRect, scrollDivWidth, columnDimensions, fixedColumnCount, hiddenColumnCount, columnCount) {
  var scrolledPartWidth = scrollDivWidth - columnDimensions.fixedWidth;
  var start = fixedColumnCount + hiddenColumnCount;
  var end = this.GetLastColumnIndexFromBound(columnDimensions.columnWidths, scrolledPartWidth, start, showFullRect);
  var inc = cellIndex > start ? 1 : -1;
  if(start > end)
   return cellIndex - fixedColumnCount;
  while(cellIndex < start || cellIndex > end) {
   start += inc;
   end = this.GetLastColumnIndexFromBound(columnDimensions.columnWidths, scrolledPartWidth, start, showFullRect);
   if(end === columnCount - 1)
    break;
  }
  return start - fixedColumnCount;
 },
 ChangeCellColspan: function(cell, startIndex, endIndex, columnCount, visible) {
  var colSpanDiff = endIndex - startIndex + 1;
  var addColSpan = visible ? 1 : -1;
  var newColSpan = cell.colSpan + colSpanDiff * addColSpan;
  var maxCellColSpan = columnCount + 1 + this.GetIndexCorrection(cell.parentNode);
  cell.colSpan = newColSpan <= maxCellColSpan ? newColSpan : maxCellColSpan;
 },
 ConvertToCellIndex: function(index) { return index; },
 GetIndexCorrection: function(row) { return 0; }
});
ASPx.TableFixedColumnsHelper = TableFixedColumnsHelper;
})();

(function() {
var GridViewLayoutHelper = ASPx.CreateClass(ASPx.GridLayoutHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.adaptiveLayoutInfo = null;
  this.mergeIntervals = null;
  this.groupLevels = null;
  this.spannedRowIds = [
   ASPx.GridViewConsts.GroupRowID,
   ASPx.GridViewConsts.GroupRowExpID,
   ASPx.GridViewConsts.PreviewRowID,
   ASPx.GridViewConsts.DetailRowID,
   ASPx.GridViewConsts.EmptyDataRowID,
   ASPx.GridViewConsts.EditingErrorItemID
  ];
  this.spannedTemplatedRowIds = [
   ASPx.GridViewConsts.DataRowID,
   ASPx.GridViewConsts.FooterRowID,
   ASPx.GridViewConsts.GroupFooterRowID,
   ASPx.GridViewConsts.FilterRowID,
   ASPx.GridViewConsts.EditingRowID
  ];
  this.spannedTemplatedCellIds = [
   ASPx.GridViewConsts.DataRowTemplateCellID,
   ASPx.GridViewConsts.FooterRowTemplateCellID,
   ASPx.GridViewConsts.GroupFooterRowTemplateCellID,
   ASPx.GridViewConsts.FilterRowTemplateCellID,
   ASPx.GridViewConsts.EditFormTableCellID
  ];
  this.cachedHasCellMerging = null;
  this.cachedHasServerGroupLevelInfo = null;
 },
 GetSpannedRowRegexp: function() {
  if(!this.spannedRowRegExp)
   this.spannedRowRegExp = new RegExp(this.GetSpannedElementPattern(this.spannedRowIds));
  return this.spannedRowRegExp;
 },
 GetSpannedTemplatedRowRegexp: function() {
  if(!this.spannedTemplatedRowRegExp)
   this.spannedTemplatedRowRegExp = new RegExp(this.GetSpannedElementPattern(this.spannedTemplatedRowIds));
  return this.spannedTemplatedRowRegExp;
 },
 GetSpannedTemplatedCellRegexp: function() {
  if(!this.spannedTemplatedCellRegExp)
   this.spannedTemplatedCellRegExp = new RegExp(this.GetSpannedElementPattern(this.spannedTemplatedCellIds));
  return this.spannedTemplatedCellRegExp;
 },
 GetSpannedElementPattern: function(idParts) {
  return "^" + this.grid.name + "_(" + idParts.join("|") + ")(-?\\d+)?(_\\d+)?$"; 
 },
 IsSpannedRow: function(row) { 
  if(!row) return false;
  var isTemplateRow = this.GetSpannedTemplatedRowRegexp().test(row.id);
  if(isTemplateRow) {
   var cell = this.GetSpannedCell(row);
   return this.IsSpannedCell(cell);
  }
  return this.GetSpannedRowRegexp().test(row.id) || this.IsBatchChangesViewCategoryRow(row);
 },
 IsSpannedCell: function(cell) {
  return cell && this.GetSpannedTemplatedCellRegexp().test(cell.id);
 },
 IsBatchChangesViewCategoryRow: function(row) {
  return row.id.indexOf(ASPx.GridViewConsts.BatchChangesPreviewGroupRowID) > 0;
 },
 GetSpannedCell: function(row) { return this.grid.GetLastNonAdaptiveIndentCell(row); },
 IsArmatureRowRequired: function() { return this.grid.HasScrolling() || this.grid.AllowResizing(); }, 
 GetArmatureRows: function() { return this.GetAllTables().map(function(table) { return table.rows[0]; }); },
 GetColumnWidthInfo: function() { return this.grid.clientMoveColumnWidths; },
 GetColumnWidth: function(columnIndex) { 
  var info = this.GetColumnWidthInfo();
  if(!info) return null;
  var colWidth = info[columnIndex];
  return colWidth || "";
 },
 GetGridName: function() { return this.grid.name; },
 GetTotalIndentCount: function() { return this.grid.indentColumnCount; },
 GetGroupFooterVisibleIndices: function() { return this.grid.GetGroupFooterVisibleIndices(); },
 GetShowColumnHeaders: function() { return this.grid.showColumnHeaders; },
 GetShowFilterRow: function() { return !!this.grid.GetFilterRow(); },
 GetShowFooterRow: function() { return !!this.grid.GetFooterRow(); },
 GetShowEditingRow: function() { return this.IsInlineEditMode() && this.grid.GetEditingRow(); },
 IsBatchEditMode: function() { return this.grid.IsBatchEditMode(); },
 IsBatchEditPreviewChangesMode: function() { return this.grid.IsBatchChangesViewMode(); },
 IsInlineEditMode: function() { return this.grid.IsInlineEditMode(); },
 IsFixedTableLayout: function() {
  return this.grid.GetMainTable().style.tableLayout === "fixed";
 },
 HasMergedGroups: function() { return !!this.grid.hasMergedGroups; },
 GetAllTableRows: function() {
  var rows = [];
  var tables = this.GetAllTables();
  for(var i = 0; i < tables.length; i++)
   rows = rows.concat([].slice.call(tables[i].rows));
  return rows;
 },
 GetAllTables: function() {
  var grid = this.grid;
  var helper = grid.GetTableHelper();
  var headerTable = helper ? helper.GetHeaderTable() : null;
  var contentTable = grid.GetMainTable();
  var footerTable = helper ? helper.GetFooterTable() : null;
  return [ headerTable, contentTable, footerTable ].filter(function(table) { return !!table; });
 },
 GetMainElementCell: function() {
  return this.grid.GetMainElement().rows[0].cells[0];
 },
 Invalidate: function() { 
  ASPx.GridLayoutHelper.prototype.Invalidate.call(this);
  this.adaptiveLayoutInfo = null;
  this.mergeIntervals = null;
  this.groupLevels = null;
  this.cachedHasCellMerging = null;
  this.cachedHasServerGroupLevelInfo = null;
 },
 GetFixedColumnsHelper: function() { return this.grid.GetFixedColumnsHelper(); },
 GetIndentColumnCount: function() { return this.grid.indentColumnCount; },
 GetHasDetailRows: function() { return this.grid.hasDetailRows; },
 GetShowDetailButton: function() { return this.grid.showDetailButton; },
 GetHasDetailButton: function() { return this.GetHasDetailRows() && this.GetShowDetailButton(); },
 GetShowGroupButton: function() { return this.grid.showGroupButton; },
 GetHasGroupButton: function(visibleIndex) { return this.GetGroupIndentsCount() > 0 && this.GetShowGroupButton() && !this.GetHasGroupRowTemplate(visibleIndex); },
 GetAdaptiveButtonPos: function() { return this.grid.adaptiveButtonPos; },
 GetHasFilterRowTemplate: function() { return this.grid.hasFilterRowTemplate; },
 GetHasDataRowTemplate: function() { return this.grid.hasDataRowTemplate; },
 GetHasGroupRowTemplate: function(visibleIndex) {
  if(this.grid.hasGroupRowTemplate)
   return true;
  var groupLevel = this.GetGroupRowLevel(visibleIndex);
  var groupColumns = this.GetColumnHelper().GetGroupColumns();
  return groupLevel >= 0 && groupLevel < groupColumns.length ? !!groupColumns[groupLevel].hasGroupRowTemplate : false;
 },
 GetHasGroupFooterRowTemplate: function() { return this.grid.hasGroupFooterRowTemplate; },
 GetHasFooterRowTemplate: function() { return this.grid.hasFooterRowTemplate; },
 IsDataRow: function(row) {
  if(!row || !row.id) return false;
  var dataRowIdPrefix = this.grid.name + "_" + ASPx.GridViewConsts.DataRowID;
  return row.id.indexOf(dataRowIdPrefix) > -1;
 },
 IsAdaptiveCell: function(cell) {
  var adaptiveClasses = [ASPx.GridViewConsts.AdaptiveDetailDataCellCssClass, ASPx.GridViewConsts.AdaptiveDetailCommandCellCssClass];
  return adaptiveClasses.some(function(className) { return ASPx.ElementHasCssClass(cell, className); });
 }, 
 IsServiceCell: function(cell) {
  var serviceCssClasses = [ASPx.GridViewConsts.IndentCellCssClass, ASPx.GridViewConsts.HorizontalExtraCellClassName, ASPx.GridViewConsts.AdaptiveIndentCellCssClass];
  return serviceCssClasses.some(function(className) { return ASPx.ElementHasCssClass(cell, className); });
 },
 HasServerGroupLevelInfo: function() {
  if(this.cachedHasServerGroupLevelInfo === null) {
   var groupLevelInfo = this.GetGroupLevelServerInfo();
   this.cachedHasServerGroupLevelInfo = groupLevelInfo && Object.keys(groupLevelInfo).length > 0;
  }
  return this.cachedHasServerGroupLevelInfo;
 },
 HasCellMerging: function() { 
  if(this.cachedHasCellMerging === null) {
   var mergedCellInfo = this.GetMergedCellServerInfo();
   this.cachedHasCellMerging = mergedCellInfo && Object.keys(mergedCellInfo).length > 0;
  }
  return this.cachedHasCellMerging;
 },
 GetGroupLevelServerInfo: function() { return this.grid.stateObject.groupLevelState || { }; },
 SetGroupLevelServerInfo: function(info) { this.grid.stateObject.groupLevelState = info; },
 GetGroupRowLevel: function(visibleIndex) { 
  this.EnsureGroupLevelInfo();
  if(!this.groupLevels) return -1;
  var level = this.groupLevels[visibleIndex];
  return ASPx.IsExists(level) ? level : -1;
 },
 EnsureGroupLevelInfo: function() {
  if(this.groupLevels || !this.HasServerGroupLevelInfo()) 
   return;
  var serverInfo = this.GetGroupLevelServerInfo();
  this.groupLevels = { };
  for(var level in serverInfo) {
   if(!serverInfo.hasOwnProperty(level)) continue;
   level = parseInt(level);
   var intervals = serverInfo[level];
   for(var i = 0; i < intervals.length; i++) {
    var interval = intervals[i];
    var start = interval[0];
    var end = interval[1];
    for(var visibleIndex = start; visibleIndex <= end; visibleIndex++)
     this.groupLevels[visibleIndex] = level;
   }
  }
 },
 GetGroupRowColSpan: function(visibleIndex) { 
  var groupLevel = this.GetGroupRowLevel(visibleIndex);
  if(!ASPx.IsExists(groupLevel))
   return -1;
  var groupIndentsCount = this.GetGroupIndentsCount();
  var layoutWidth = this.GetLayoutWidth();
  var detailButtonWidth = this.GetHasDetailButton() ? 1 : 0;
  var groupButtonWidth = this.GetHasGroupButton(visibleIndex) ? 1 : 0;
  return layoutWidth + detailButtonWidth + groupIndentsCount - groupLevel - groupButtonWidth;
 },
 GetGroupFooterRowColSpan: function(visibleIndex) { 
  var layoutWidth = this.GetLayoutWidth();
  var groupLevel = this.GetGroupRowLevel(visibleIndex);
  var footerIndentCount = this.GetGroupIndentsCount() - groupLevel - 1;
  return layoutWidth + footerIndentCount;
 },
 GetGroupIndentsCount: function() {
  return this.HasMergedGroups() ? 1 : this.GetColumnHelper().GetGroupColumnCount();
 },
 GetIndentCellCount: function(visibleIndex, levelIndex, rowType) { 
  var result = this.GetIndentCellCountCore(visibleIndex, rowType);
  if(levelIndex === 0)
   return Math.max(0, result);
  var groupIndentsCount = this.GetGroupIndentsCount();
  var detailButtonWidth = this.GetHasDetailButton() ? 1 : 0;
  if(rowType === ASPx.GridViewRowType.Footer && groupIndentsCount > 0) 
   result--;
  switch(rowType) {
   case ASPx.GridViewRowType.Footer:
   case ASPx.GridViewRowType.Filter:
   case ASPx.GridViewRowType.Data:
   case ASPx.GridViewRowType.BatchEtalon:
   case ASPx.GridViewRowType.GroupFooter:
    if(detailButtonWidth > 0)
     result--;
    break;
   case ASPx.GridViewRowType.Header:
    result = 0;
  }
  return Math.max(0, result);
 },
 GetIndentCellCountCore: function(visibleIndex, rowType) {
  var groupButtonWidth = this.GetHasGroupButton(visibleIndex) ? 1 : 0;
  var detailButtonWidth = this.GetHasDetailButton() ? 1 : 0;
  var leftAdaptiveButtonWidth = this.GetAdaptiveButtonPos() === ASPx.GridViewAdaptiveDetailButtonPosition.Left ? 1 : 0;
  var groupIndentsCount = this.GetGroupIndentsCount();
  var groupLevel = this.GetGroupRowLevel(visibleIndex);
  var totalIndentCount = groupIndentsCount + leftAdaptiveButtonWidth + detailButtonWidth;
  switch(rowType) {
   case ASPx.GridViewRowType.Header:
   case ASPx.GridViewRowType.Filter:
   case ASPx.GridViewRowType.Data:
   case ASPx.GridViewRowType.BatchEtalon:
   case ASPx.GridViewRowType.InlineEdit:
    return totalIndentCount;
   case ASPx.GridViewRowType.Footer:
    return leftAdaptiveButtonWidth + detailButtonWidth + (groupIndentsCount > 0 ? 1 : 0);
   case ASPx.GridViewRowType.Group:
    return groupLevel + groupButtonWidth;
   case ASPx.GridViewRowType.GroupFooter:
    var footerIndentCount = groupIndentsCount - groupLevel - 1;
    var dataIndentCount = totalIndentCount - footerIndentCount;
    var footerIndentWidth = (footerIndentCount > 0 && !this.GetHasGroupFooterRowTemplate()) ? 1 : 0;
    return dataIndentCount + footerIndentWidth;
  }
  return 0;
 },
 GetRowInfo: function(rowID) {
  if(!rowID) return null;
  var pattern = "^" + this.GetGridName() + "_([a-z]+)(-?\\d+)?(_\\d+)?$";
  var regex = new RegExp(pattern, "i");
  var matches = regex.exec(rowID);
  if(!matches || matches.length !== 4)
   return null;
  var firstNumber = parseInt(matches[2]);
  var secondNumber = matches[3] !== undefined ? parseInt(matches[3].substr(1)) : NaN;
  var rowType = this.GetRowTypeByPartialID(matches[1]);
  if(rowType === null)
   return null;
  var visibleIndex = -1;
  var level = 0;
  switch(rowType) {
   case ASPx.GridViewRowType.Header:
    if(!isNaN(secondNumber)) return null;
    level = firstNumber;
    break;
   case ASPx.GridViewRowType.Filter:
   case ASPx.GridViewRowType.Footer:
   case ASPx.GridViewRowType.InlineEdit:
   case ASPx.GridViewRowType.BatchEtalon:
    if(!isNaN(firstNumber)) return null;
    level = secondNumber;
    break;
   case ASPx.GridViewRowType.Group:
    if(isNaN(firstNumber) || !isNaN(secondNumber)) return null;
    visibleIndex = firstNumber;
    break;
   case ASPx.GridViewRowType.Data:
   case ASPx.GridViewRowType.GroupFooter:
    if(isNaN(firstNumber)) return null;
    visibleIndex = firstNumber;
    level = secondNumber;
    break;
  }
  if(isNaN(level))
   level = 0;
  return { rowType: rowType, visibleIndex: visibleIndex, level: level };
 },
 GetRowTypeByPartialID: function(partialID) {
  switch(partialID) {
   case ASPx.GridViewConsts.HeaderRowID:
    return ASPx.GridViewRowType.Header;
   case ASPx.GridViewConsts.FilterRowID:
    return ASPx.GridViewRowType.Filter;
   case ASPx.GridViewConsts.DataRowID:
    return ASPx.GridViewRowType.Data;
   case ASPx.GridViewConsts.GroupRowID:
   case ASPx.GridViewConsts.GroupRowExpID:
    return ASPx.GridViewRowType.Group;
   case ASPx.GridViewConsts.GroupFooterRowID:
    return ASPx.GridViewRowType.GroupFooter;
   case ASPx.GridViewConsts.FooterRowID:
    return ASPx.GridViewRowType.Footer;
   case ASPx.GridViewConsts.EditingRowID:
    return ASPx.GridViewRowType.InlineEdit; 
   case ASPx.GridViewConsts.DataRowID + this.GetEtalonBatchRecordPostfix():
    return ASPx.GridViewRowType.BatchEtalon;
  }
  return null;
 },
 GetEtalonBatchRecordPostfix: function() { return this.grid.EtalonBatchRecordPostFix; },
 GetRowCellMap: function(info) {
  if(!info || info.rowType === ASPx.GridViewRowType.Group) 
   return null;
  var layout = null;
  if(info.rowType === ASPx.GridViewRowType.Header)
   layout = this.GetHeaderLayout();
  else 
   layout = info.rowType === ASPx.GridViewRowType.Data ? this.GetDataRowLayout(info.visibleIndex) : this.GetEtalonDataRowLayout();
  var result = { };
  var indentCount = this.GetIndentCellCount(info.visibleIndex, info.level, info.rowType);
  var level = layout[info.level];
  for(var i = 0; i < level.length; i++)
   result[level[i].columnIndex] = indentCount + i;
  return result;
 },
 CopyIndentCells: function(row, cloneRow, visibleIndex, cloneLevelIndex, rowType) {
  if(!this.IsSpannedRow(row)) {
   this.CopyIndentCellsFromLeft(row, cloneRow, visibleIndex, cloneLevelIndex, rowType);
   this.CopyIndentCellsFromRight(row, cloneRow, visibleIndex, cloneLevelIndex, rowType);
  }
 },
 CopyIndentCellsFromLeft: function(row, cloneRow, visibleIndex, cloneLevelIndex, rowType) {
  if(rowType === ASPx.GridViewRowType.Header)
   return;
  var firstRowIndentCellCount = this.GetIndentCellCount(visibleIndex, 0, rowType);
  var cloneRowIndentCellCount = this.GetIndentCellCount(visibleIndex, cloneLevelIndex, rowType);
  var indentCellIndices = ASPx.Data.Range(firstRowIndentCellCount, 0);
  var detailIndentCellIndex = this.GetDetailIndentCellIndex(visibleIndex, 0, rowType);
  var footerGroupIndentCellIndex = this.GetFooterGroupIndentCellIndex(visibleIndex, 0, rowType);
  ASPx.Data.ArrayRemove(indentCellIndices, detailIndentCellIndex);
  ASPx.Data.ArrayRemove(indentCellIndices, footerGroupIndentCellIndex);
  if(indentCellIndices.length !== cloneRowIndentCellCount)
   throw "Wrong indent cell count for clonned row";
  this.CloneIndentCells(row, cloneRow, indentCellIndices);
 },
 CopyIndentCellsFromRight: function(row, cloneRow, visibleIndex, cloneLevelIndex, rowType) { 
  var layoutWidth = this.GetLayoutWidth(rowType === ASPx.GridViewRowType.Header);
  var indentCellCount = this.GetIndentCellCount(visibleIndex, 0, rowType);
  var rightIndentCellIndex = indentCellCount + layoutWidth;
  var indentCellIndices = ASPx.Data.Range(row.cells.length - rightIndentCellIndex, rightIndentCellIndex);
  this.CloneIndentCells(row, cloneRow, indentCellIndices);
 },
 CloneIndentCells: function(row, cloneRow, cellIndices) {
  var targetElement = cloneRow.insertCell();
  for(var i = 0; i < cellIndices.length; i++) {
   var cellIndex = cellIndices[i];
   var cloneCell = row.cells[cellIndex].cloneNode();
   cloneRow.insertBefore(cloneCell, targetElement);
  }
  ASPx.RemoveElement(targetElement);
 },
 GetDetailIndentCellIndex: function(visibleIndex, levelIndex, rowType) {
  if(!this.GetHasDetailButton() || levelIndex > 0) 
   return -1;
  var indentCellCount = this.GetIndentCellCount(visibleIndex, 0, rowType);
  return indentCellCount - 1;
 },
 GetFooterGroupIndentCellIndex: function(visibleIndex, levelIndex, rowType) {
  if(rowType !== ASPx.GridViewRowType.Footer || this.GetHasFooterRowTemplate() || levelIndex > 0) 
   return -1;
  var indentCellCount = this.GetIndentCellCount(visibleIndex, 0, rowType);
  var result = indentCellCount - 1;
  if(this.GetHasDetailButton())
   result--;
  return result;
 },
 UpdateIndentCellRowSpan: function(visibleIndex, rowType) {
  var indentCellCount = this.GetIndentCellCount(visibleIndex, 0, rowType);
  var totalIndentCellIndices = ASPx.Data.Range(indentCellCount, 0);
  var detailIndentCellIndex = this.GetDetailIndentCellIndex(visibleIndex, 0, rowType);
  var footerGroupIndentCellIndex = this.GetFooterGroupIndentCellIndex(visibleIndex, 0, rowType);
  var cellIndices = rowType === ASPx.GridViewRowType.Header ? totalIndentCellIndices : [ detailIndentCellIndex, footerGroupIndentCellIndex ];
  var height = this.GetLayoutHeight(rowType === ASPx.GridViewRowType.Header);
  var row = this.GetRow(visibleIndex, 0, rowType);
  for(var i = 0; i < cellIndices.length; i++) {
   var cellIndex = cellIndices[i];
   if(cellIndex >= 0 && cellIndex < row.cells.length)
    row.cells[cellIndex].rowSpan = height;
  }
 },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 GetAdaptivityHelper: function() { return this.grid.GetAdaptivityHelper(); },
 GetMergedCellServerInfo: function() { return this.grid.stateObject.mergedCellState || { }; },
 SetMergedCellServerInfo: function(info) { this.grid.stateObject.mergedCellState = info; },
 GetHeaderLayout: function() { return this.GetColumnHelper().GetHeaderLayout(); },
 GetEtalonDataRowLayout: function() { return this.GetColumnHelper().GetDataRowLayout(); },
 GetDataRowLayout: function(visibleIndex) {
  var layout = this.GetEtalonDataRowLayout();
  if(!ASPx.IsExists(visibleIndex) || !this.HasCellMerging())
   return layout;
  var newLayout = [ ];
  for(var i = 0; i < layout.length; i++) {
   var level = layout[i].slice();
   for(var j = level.length - 1; j >= 0; j--) {
    if(this.IsHiddenMergedCell(visibleIndex, level[j].columnIndex))
     level.splice(j, 1); 
   }
   newLayout.push(level);
  }
  return newLayout;
 },
 GetHasRowTemplate: function(rowType) {
  switch(rowType) {
   case ASPx.GridViewRowType.Filter:
    return this.GetHasFilterRowTemplate();
   case ASPx.GridViewRowType.Data:
    return this.GetHasDataRowTemplate();
   case ASPx.GridViewRowType.GroupFooter:
    return this.GetHasGroupFooterRowTemplate();
   case ASPx.GridViewRowType.Footer:
    return this.GetHasFooterRowTemplate();
  }
  return false;
 },
 GetRow: function(visibleIndex, levelIndex, rowType) {
  switch(rowType) {
   case ASPx.GridViewRowType.Header:
    return this.grid.GetHeaderRow(levelIndex);
   case ASPx.GridViewRowType.Filter:
    return this.grid.GetFilterRow(levelIndex);
   case ASPx.GridViewRowType.Data:
    return this.grid.GetDataRow(visibleIndex, levelIndex);
   case ASPx.GridViewRowType.GroupFooter:
    return this.grid.GetGroupFooterRow(visibleIndex, levelIndex);
   case ASPx.GridViewRowType.Footer:
    return this.grid.GetFooterRow(levelIndex);
   case ASPx.GridViewRowType.InlineEdit:
    return this.grid.GetEditingRow(this.grid, levelIndex);
   case ASPx.GridViewRowType.BatchEtalon:
    return this.grid.GetBatchEtalonRow(levelIndex);   
  }
  return null;
 },
 GetStretchedRowColsSpan: function(visibleIndex, rowType) { 
  var layoutWidth = this.GetLayoutWidth();
  switch(rowType) {
   case ASPx.GridViewRowType.Filter:
   case ASPx.GridViewRowType.Data:
   case ASPx.GridViewRowType.Footer:
    return layoutWidth;
   case ASPx.GridViewRowType.Group:
    return this.GetGroupRowColSpan(visibleIndex);
   case ASPx.GridViewRowType.GroupFooter:
    return this.GetGroupFooterRowColSpan(visibleIndex);
  }
  return 0;
 },
 GetCell: function(visibleIndex, columnIndex, rowType) {
  switch(rowType) {
   case ASPx.GridViewRowType.Header:
    return this.GetHeaderCell(columnIndex);
   case ASPx.GridViewRowType.Filter:
    return this.GetFilterCell(columnIndex);
   case ASPx.GridViewRowType.Data:
    return this.GetDataCell(visibleIndex, columnIndex);
   case ASPx.GridViewRowType.GroupFooter:
    return this.GetGroupFooterCell(visibleIndex, columnIndex);
   case ASPx.GridViewRowType.Footer:
    return this.GetFooterCell(columnIndex);
   case ASPx.GridViewRowType.BatchEtalon:
    return this.GetBatchEtalonCell(visibleIndex, columnIndex);
   case ASPx.GridViewRowType.InlineEdit:
    return this.GetInlineEditCell(columnIndex);
  }
  return null;
 },
 UpdateStretchedRowsColSpan: function() {
  var helper = this.GetFixedColumnsHelper();
  this.UpdateStretchedRowsColSpanCore(helper ? helper.hiddenColumnCount : 0);
 },
 UpdateStretchedRowsColSpanCore: function(columnsToHide) {
  var groupRowRegexp = new RegExp(this.GetSpannedElementPattern([ ASPx.GridViewConsts.GroupRowID, ASPx.GridViewConsts.GroupRowExpID ]));
  var groupFooterRegexp = new RegExp(this.GetSpannedElementPattern([ ASPx.GridViewConsts.GroupFooterRowID ]));
  var totalSpan = this.GetLayoutWidth(false);
  var stretchedRows = this.GetAllTableRows().filter(function(row) { return this.IsSpannedRow(row); }.aspxBind(this));
  for(var i = 0; i < stretchedRows.length; i++) {
   var row = stretchedRows[i];
   var cell = this.GetSpannedCell(row);
   var colSpan = totalSpan;
   if(groupRowRegexp.test(row.id)) {
    var matches = row.id.match(groupRowRegexp);
    var visibleIndex = parseInt(matches[2]);
    colSpan = this.GetStretchedRowColsSpan(visibleIndex, ASPx.GridViewRowType.Group);
   }
   if(groupFooterRegexp.test(row.id)) {
    var matches = row.id.match(groupFooterRegexp);
    var visibleIndex = parseInt(matches[2]);
    colSpan = this.GetStretchedRowColsSpan(visibleIndex, ASPx.GridViewRowType.GroupFooter);
   }
   ASPx.Attr.ChangeCellSpanCount(cell, colSpan - columnsToHide, true);
  }
 },
 GetHeaderCell: function(columnIndex) { return this.grid.GetHeader(columnIndex); },
 GetFilterCell: function(columnIndex) { return this.GetCellCore(-1, columnIndex, ASPx.GridViewRowType.Filter); },
 GetDataCell: function(visibleIndex, columnIndex) { return this.GetCellCore(visibleIndex, columnIndex, ASPx.GridViewRowType.Data); },
 GetGroupFooterCell: function(visibleIndex, columnIndex) { return this.GetCellCore(visibleIndex, columnIndex, ASPx.GridViewRowType.GroupFooter); },
 GetFooterCell: function(columnIndex) { return this.GetCellCore(-1, columnIndex, ASPx.GridViewRowType.Footer); },
 GetBatchEtalonCell: function(visibleIndex, columnIndex) { return this.GetCellCore(visibleIndex, columnIndex, ASPx.GridViewRowType.BatchEtalon); },
 GetInlineEditCell: function(columnIndex) { 
  if(this.IsInlineEditMode())
   return this.GetCellCore(-1, columnIndex, ASPx.GridViewRowType.InlineEdit); 
  return null;
 },
 GetCellCore: function(visibleIndex, columnIndex, rowType) {
  if(this.GetHasRowTemplate(rowType)) return null;
  columnIndex = parseInt(columnIndex);
  var layout = this.GetEtalonDataRowLayout();
  var pos = this.GetColumnHelper().FindColumnLayoutPos(layout, columnIndex);
  if(pos.levelIndex < 0 || pos.cellIndex < 0)
   return null;
  var cellIndex = pos.cellIndex + this.GetIndentCellCount(visibleIndex, pos.levelIndex, rowType);
  if(!this.IsBatchEditPreviewChangesMode()) {
   visibleIndex = this.ResolveMergedCellVisibleIndex(visibleIndex, columnIndex);   
   if(this.HasCellMerging() && (rowType === ASPx.GridViewRowType.Data || rowType === ASPx.GridViewRowType.BatchEtalon))
    cellIndex -= this.CalcHiddenMergedCellCount(visibleIndex, columnIndex);
  }
  var row = this.GetRow(visibleIndex, pos.levelIndex, rowType);
  return row && cellIndex >= 0 && cellIndex < row.cells.length ? row.cells[cellIndex] : null;
 },
 GetHeaderRows: function() {
  var height = this.GetShowColumnHeaders() ? this.GetLayoutHeight(true) : 0;
  return ASPx.Data.Range(height, 0).map(function(i) { return this.grid.GetHeaderRow(i); }.bind(this));
 },
 GetFilterRows: function() {
  var height = this.GetLayoutHeight(false);
  return ASPx.Data.Range(height, 0).map(function(i) { return this.grid.GetFilterRow(i); }.bind(this));
 },
 GetFooterRows: function() {
  var height = this.GetLayoutHeight(false);
  return ASPx.Data.Range(height, 0).map(function(i) { return this.grid.GetFooterRow(i); }.bind(this));
 },
 GetLayoutWidth: function(isHeader) {
  var layout = isHeader ? this.GetHeaderLayout() : this.GetEtalonDataRowLayout();
  return this.GetLayoutWidthCore(layout);
 },
 GetLayoutWidthCore: function(layout) {
  if(!layout || layout.length === 0) 
   return 0;
  var firstLevel = layout[0];
  if(!firstLevel || firstLevel.length === 0)
   return 0;
  return firstLevel.reduce(function(prevValue, node) { return prevValue + node.colSpan; }, 0);
 },
 GetLayoutHeight: function(isHeader) {
  var layout = isHeader ? this.GetHeaderLayout() : this.GetEtalonDataRowLayout();
  return this.GetLayoutHeightCore(layout);
 },
 GetLayoutHeightCore: function(layout) {
  return layout ? layout.length : 0;
 },
 GetColumnIndex: function(cellIndex, visibleIndex, levelIndex) { 
  if(!levelIndex || levelIndex < 0)
   levelIndex = 0;
  var layout = this.GetDataRowLayout(visibleIndex); 
  if(layout.length <= levelIndex)
   return -1;
  var level = layout[levelIndex];
  cellIndex -= this.GetIndentCellCount(visibleIndex, levelIndex, ASPx.GridViewRowType.Data);
  return cellIndex >= 0 && cellIndex < level.length ? level[cellIndex].columnIndex : -1;
 },
 GetDataCellIndex: function(columnIndex, visibleIndex) { 
  var layout = this.GetDataRowLayout(visibleIndex);
  var pos = this.GetColumnHelper().FindColumnLayoutPos(layout, columnIndex);
  if(pos.levelIndex < 0 || pos.cellIndex < 0)
   return -1;
  return pos.cellIndex + this.GetIndentCellCount(visibleIndex, pos.levelIndex, ASPx.GridViewRowType.Data);
 },
 IsMergedCell: function(visibleIndex, columnIndex) { 
  return !!this.GetMergeInterval(visibleIndex, columnIndex);
 },
 IsHiddenMergedCell: function(visibleIndex, columnIndex) {
  return visibleIndex !== this.ResolveMergedCellVisibleIndex(visibleIndex, columnIndex);
 },
 IsMergedCellFirstRow: function(visibleIndex, columnIndex) { 
  var interval = this.GetMergeInterval(visibleIndex, columnIndex);
  return !!interval && interval[0] === visibleIndex;
 },
 IsMergedCellLastRow: function(visibleIndex, columnIndex) { 
  var interval = this.GetMergeInterval(visibleIndex, columnIndex);
  return !!interval && interval[1] === visibleIndex;
 },
 ResolveMergedCellVisibleIndex: function(visibleIndex, columnIndex) {
  if(!this.HasCellMerging()) return visibleIndex;
  var interval = this.GetMergeInterval(visibleIndex, columnIndex);
  return interval ? interval[0] : visibleIndex;
 },
 ResolveMergedCellVisibleIndexForNavigation: function(visibleIndex, columnIndex) {
  return this.IsBatchEditPreviewChangesMode() ? visibleIndex : this.ResolveMergedCellVisibleIndex(visibleIndex, columnIndex);
 },
 CalcHiddenMergedCellCount: function(visibleIndex, columnIndex) {
  var layout = this.GetEtalonDataRowLayout();
  var pos = this.GetColumnHelper().FindColumnLayoutPos(layout, columnIndex);
  if(pos.levelIndex < 0 || pos.cellIndex < 0)
   return 0;
  var result = 0;
  var level = layout[pos.levelIndex];
  for(var j = 0; j < pos.cellIndex; j++) {
   if(this.IsHiddenMergedCell(visibleIndex, level[j].columnIndex))
    result++;
  }
  return result;
 },
 GetMergeInterval: function(visibleIndex, columnIndex) {
  this.EnsureMergeIntervals();
  var columnIntervals = this.mergeIntervals[columnIndex];
  return columnIntervals ? columnIntervals[visibleIndex] : null;
 },
 EnsureMergeIntervals: function() {
  if(this.mergeIntervals) return;
  this.mergeIntervals = { };
  var serverInfo = this.GetMergedCellServerInfo();
  for(var columnIndex in serverInfo) {
   if(!serverInfo.hasOwnProperty(columnIndex)) continue;
   var columnIntervals = { };
   var serverIntervals = serverInfo[columnIndex];
   for(var i = 0; i < serverIntervals.length; i++) {
    var interval = serverIntervals[i];
    var start = interval[0];
    var end = interval[1];
    for(var j = start; j <= end; j++)
     columnIntervals[j] = interval;
   }
   this.mergeIntervals[parseInt(columnIndex)] = columnIntervals;
  }
 },
 GetAdaptiveRowLayoutInfo: function(visibleIndex) {
  if(!this.adaptiveLayoutInfo) 
   this.adaptiveLayoutInfo = this.CreateAdaptiveLayoutInfo();
  var baseAdaptiveLayout = this.adaptiveLayoutInfo.adaptiveRowLayout || [ ];
  return { 
   dataRowLayout: this.adaptiveLayoutInfo.dataRowLayout || this.GetEtalonDataRowLayout(),
   adaptiveRowLayout : this.IsAdaptiveDetailExpanded(visibleIndex) ? baseAdaptiveLayout : [ ]
  };
 },
 CreateAdaptiveLayoutInfo: function() {
  var adaptiveHelper = this.GetAdaptivityHelper();
  if(!adaptiveHelper) 
   return { };
  var dataRowLayout = [ ];
  var adaptiveColumnIndices = [ ];
  var columnHelper = this.GetColumnHelper();
  var isFormLayoutMode = adaptiveHelper.IsAdaptiveFormLayoutMode();
  if(adaptiveHelper.IsAdaptivityMode()) {
   var hasAnyAdaptive = adaptiveHelper.HasAnyAdaptiveElement();
   if(hasAnyAdaptive) {
    dataRowLayout = [ ];
    adaptiveColumnIndices = isFormLayoutMode ? adaptiveHelper.GetAdaptiveLayoutColumnIndices() : columnHelper.GetVisibleColumnIndices();
   } else {
    dataRowLayout = this.GetEtalonDataRowLayout();
    adaptiveColumnIndices = [ ];
   }
  } else {
   var adaptiveInfo = columnHelper.GetAdaptiveRowInfo();
   dataRowLayout = adaptiveInfo.dataRowLayout;
   var columnIndicesForAdaptiveIndicesOrder = isFormLayoutMode ? adaptiveHelper.GetAdaptiveLayoutColumnIndices() : columnHelper.GetVisibleColumnIndices();
   for(var i = 0; i < columnIndicesForAdaptiveIndicesOrder.length; i++) {
    var columnIndex = columnIndicesForAdaptiveIndicesOrder[i];
    if(adaptiveInfo.adaptiveColumnIndices.indexOf(columnIndex) > -1)
     adaptiveColumnIndices.push(columnIndex);
   }
  }
  return { dataRowLayout: dataRowLayout, adaptiveRowLayout: this.CreateAdaptiveRowLayout(adaptiveColumnIndices) };
 },
 CreateAdaptiveRowLayout: function(columnIndices) {
  var layout = [ ];
  var width = this.GetAdaptiveLayoutWidth();
  var height = Math.ceil(columnIndices.length / width);
  for(var i = 0; i < height; i++) {
   var level = [ ];
   for(var j = 0; j < width; j++) {
    var index = i * width + j;
    if(index < columnIndices.length)
     level.push({ columnIndex: columnIndices[index], colSpan: 1, rowSpan: 1 });
    else
     level[level.length - 1].colSpan++;
   }
   layout.push(level);
  }
  return layout;
 },
 IsAdaptiveDetailExpanded: function(visibleIndex) {
  var helper = this.GetAdaptivityHelper();
  if(!helper || !helper.HasAnyAdaptiveElement())
   return false;
  return helper.IsAdaptivityMode() || helper.IsAdaptiveDetailExpanded(visibleIndex);
 },
 GetAdaptiveLayoutWidth: function() {
  var helper = this.GetAdaptivityHelper();
  return helper.GetAdaptiveLayoutColumnCount();
 },
 AreDataRowsHidden: function() {
  var helper = this.GetAdaptivityHelper();
  return helper && helper.IsAdaptivityMode() && helper.HasAnyAdaptiveElement();
 },
 GetAdaptiveDataCellByChild: function(dataItem, element) {
  while(element && element.tagName !== "BODY") {
   if(ASPx.ElementHasCssClass(element, ASPx.GridViewConsts.AdaptiveDetailDataCellCssClass))
    return element;
   element = element.parentNode;
  }
  return null;
 },
 IsAdaptiveDetailRow: function(row) {
  if(!row || !row.id) return false;
  var grid = this.grid;
  var indexInfo = grid.tryGetNumberFromEndOfString(row.id);
  if(!indexInfo.success) return false;
  return row.id === this.GetAdaptiveDetailRowID(indexInfo.value);
 },
 GetAdaptiveDetailRowID: function(index) { return this.grid.name + "_" + ASPx.GridViewConsts.AdaptiveDetailRowID + index.toString(); },
 UpdateOnErrorRowInserting: function(visibleIndex, errorRow) {
  var mergedIndices = this.GetErrorRowMergedColumnIndices(visibleIndex);
  if(!mergedIndices.length) return;
  this.CreateErrorRowExtraCells(errorRow, this.GetErrorRowColSpans(mergedIndices));
  this.UpdateErrorRowIntersectedMergedCells(visibleIndex, 1);
  errorRow.dxMergedCellsIntersect = true;
 },
 UpdateOnErrorRowDeleting: function(visibleIndex, errorRow) {
  if(errorRow && errorRow.dxMergedCellsIntersect)
   this.UpdateErrorRowIntersectedMergedCells(visibleIndex, -1);
 },
 GetErrorRowMergedColumnIndices: function(visibleIndex) {
  return this.GetColumnHelper().GetVisibleColumnIndices().filter(function(columnIndex) { 
   return this.IsMergedCell(visibleIndex, columnIndex) && !this.IsMergedCellLastRow(visibleIndex, columnIndex); 
  }.bind(this));
 },
 CreateErrorRowExtraCells: function(errorRow, colSpans) {
  var errorRowCells = Array(colSpans.length);
  errorRowCells[0] = this.grid.GetLastNonAdaptiveIndentCell(errorRow);
  for(var i = 0; i < colSpans.length; i++) {
   if(!errorRowCells[i]) {
    var td = ASPx.CreateHtmlElement("TD", { className: ASPx.GridViewConsts.GridViewMarkerCssClass });
    ASPx.InsertElementAfter(td, errorRowCells[i - 1]);
    errorRowCells[i] = td;
   }
   ASPx.Attr.ChangeCellSpanCount(errorRowCells[i], colSpans[i], true);
  }
 },
 GetErrorRowColSpans: function(mergedIndices) {
  var columnIndices = this.GetColumnHelper().GetVisibleColumnIndices();
  var colSpans = [ ];
  for(var i = 0; i < columnIndices.length; i++) { 
   var isMergedCell = mergedIndices.indexOf(columnIndices[i]) > -1;
   if(isMergedCell || colSpans.length === 0)
    colSpans.push(0);
   if(!isMergedCell)
    ++colSpans[colSpans.length - 1];
  }
  return colSpans.filter(function(span) { return span > 0; });
 },
 UpdateErrorRowIntersectedMergedCells: function(visibleIndex, inc) {
  var indices = this.GetErrorRowMergedColumnIndices(visibleIndex);
  for(var i = 0; i <indices.length; i++) {
   var mergedCell = this.GetDataCell(visibleIndex, indices[i]);
   ASPx.Attr.ChangeCellSpanCount(mergedCell, mergedCell.rowSpan + inc);
  }
 },
 GetDataCellByChild: function(element) {
  return ASPx.GetParent(element, function(item) {
   if(this.IsServiceCell(item))
    return false;
   return this.IsAdaptiveCell(item) || this.IsDataRow(item.parentNode);
  }.aspxBind(this)); 
 },
 GetBatchOtherPagesChangedRecordVisibleIndices: function() { return this.grid.GetBatchOtherPagesChangedRecordVisibleIndices(); },
 GetGridElementsToChangeVisibilityInBatchChangesView: function() {
  var grid = this.grid;   
  var mainElement = grid.GetMainElement();
  var elements = [ ];
  elements.push(ASPx.GetNodesByPartialClassName(mainElement, "dxgvPagerBottomPanel")[0]);
  elements.push(ASPx.GetNodesByPartialClassName(mainElement, "dxgvPagerTopPanel")[0]);
  elements.push(ASPx.GetNodesByPartialClassName(mainElement, ASPx.GridViewConsts.GroupPanelCssClass)[0]);
  elements.push(grid.GetChildElement("DXSearchPanel"));
  elements.push(grid.GetChildElement("DXFilterBar"));
  elements.push(grid.GetAdaptiveGroupPanel());
  elements.push(grid.GetAdaptiveHeaderPanel());
  elements.push(grid.GetAdaptiveFooterPanel());
  elements.push(grid.GetAdaptiveFooterPanel());
  elements = elements.concat(this.GetRowsToChangeVisibilityInBatchChangesView());
  elements = elements.concat(this.GetIndentCellsToChangeVisibilityInBatchChangesView());
  var commandColumnIndices = this.GetColumnHelper().GetVisibleColumnIndices().filter(function(columnIndex) { return grid.GetColumn(columnIndex).isCommandColumn; });
  var selectAllElements = commandColumnIndices.map(function(columnIndex) {
   var el = grid.GetSelectAllBtn(columnIndex);
   return el && el.parentNode.parentNode; 
  });
  elements = elements.concat(selectAllElements);
  var filterHelper = grid.GetFilterHelper();
  if(filterHelper)
   elements = elements.concat(filterHelper.GetHeaderFilterButtons().map(function(b) { return b && b.parentNode; })); 
  var scrollHelper = grid.GetScrollHelper();
  if(scrollHelper) {
   elements.push(scrollHelper.GetVirtualScrollMarginDiv());
   elements.push(scrollHelper.GetVirtualScrollMarginDiv(true));
  }  
  return elements.filter(function(el) { return !!el; });
 },
 GetIndentCellsToChangeVisibilityInBatchChangesView: function () {
  var cells = [ ];
  var grid = this.grid;  
  var headerRow = grid.GetHeaderRow(0);
  if(headerRow) {
   var groupIndentsCount = this.GetGroupIndentsCount();
   var detailButtonWidth = this.GetHasDetailButton() ? 1 : 0;
   var indentCount = groupIndentsCount + detailButtonWidth;
   for(var i = 0; i < indentCount; i++)
    cells.push(headerRow.cells[i]);
   }  
  return cells;
 },
 GetRowsToChangeVisibilityInBatchChangesView: function() {
  var rows = [ ];
  var grid = this.grid;
  rows = rows.concat(this.GetFilterRows());
  var indices = grid.GetCurrentPageIndices();
  var batchHelper = grid.GetBatchEditHelper();
  indices = indices.concat(grid.useEndlessPaging ? batchHelper.GetInsertedRecordKeys() : batchHelper.GetCurrentPageInsertedKeys());
  for(var i = 0; i < indices.length; i++) {
   var visibleIndex = indices[i];
   rows = rows.concat(grid.GetBandedDataRows(visibleIndex));
   var extraRows = [ grid.GetGroupRow(visibleIndex), grid.GetPreviewRow(visibleIndex), grid.GetDetailRow(visibleIndex), grid.GetAdaptiveDetailRow(visibleIndex), grid.GetEditingErrorItem(null, visibleIndex) ];
   rows = rows.concat(extraRows);
  }
  var pagerEmptyRows = ASPx.Data.CollectionToArray(grid.GetMainTable().getElementsByClassName(ASPx.GridViewConsts.EmptyPagerRowCssClass));
  rows = rows.concat(pagerEmptyRows);
  var levelCount = this.GetLayoutHeight();
  for(var i = 0; i <= levelCount; i++) {
   var groupFooterVisibleIndices = grid.GetGroupFooterVisibleIndices();
   for(var j = 0; j < groupFooterVisibleIndices.length; j++)
    rows.push(grid.GetGroupFooterRow(groupFooterVisibleIndices[j], i));
   rows.push(grid.GetFooterRow(i));
  }
  return rows;
 }
});
ASPx.GridViewLayoutHelper = GridViewLayoutHelper;
})();
(function() {
var GridViewFilterHelper = ASPx.CreateClass(ASPx.GridFilterHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.initialFilterRowState = { };
  this.filterKeyPressTimerId = -1;
  this.filterKeyPressEditor = null;
  this.preparedToCallbackFilterValue = undefined;
  this.preparedFilterValueClearDelay = 150;
  this.filterRowMenuColumnIndex = -1;
  this.currentCheckedItemIndex = -1;
 },
 GetCustDialogHelper: function() { return this.grid.GetCustDialogHelper(); },
 GetBatchEditHelper: function() { return this.grid.GetBatchEditHelper(); },
 GetAutoFilterDelay: function() { return this.grid.autoFilterDelay; },
 IsMultiColumnAutoFilter: function() { return this.grid.allowMultiColumnAutoFilter; },
 GetFilterRowMenu: function() { return this.grid.GetFilterRowMenu(); },
 GetAutoFilterEditor: function(columnIndex) { return this.grid.GetAutoFilterEditor(columnIndex); },
 GetFilterConditionState: function() { return this.grid.filterRowConditions; },
 AutoFilterByColumnCore: function(columnIndex, editorValue) { 
  this.grid.AutoFilterByColumn(columnIndex, editorValue); 
 },
 AutoFilterByMultipleColumns: function(args) {
  this.grid.gridCallBack([ASPxClientGridViewCallbackCommand.ApplyMultiColumnFilter].concat(args));
 },
 SendCallbackToChangeFilterCondition: function(args) {
  this.grid.gridCallBack([ASPxClientGridViewCallbackCommand.FilterRowMenu].concat(args));
 },
 GetColumnIndicesForFilterRow: function() { 
  var columnHelper = this.grid.GetColumnHelper();
  if(this.GetCustDialogHelper())
   return columnHelper.GetAllColumns().map(function(c) { return c.index; });
  return columnHelper.GetVisibleColumnIndices();
 },
 GetFilterCondition: function(columnIndex) { 
  var state = this.GetFilterConditionState();
  return state ? state[columnIndex] : "";
 },
 SetFilterCondition: function(columnIndex, value) { 
  var state = this.GetFilterConditionState();
  if(state)
   state[columnIndex] = value; 
 },
 IsCustDialogVisible: function() {
  var helper = this.GetCustDialogHelper();
  return helper && helper.IsDialogVisible();
 },
 AutoFilterByColumn: function(columnIndex, editorValue) { 
  if(!this.IsCustDialogVisible())
   this.AutoFilterByColumnCore(columnIndex, editorValue); 
 },
 IsBatchUpdateConfirmLocked: function() {
  var batchHelper = this.GetBatchEditHelper();
  return batchHelper && batchHelper.IsUpdateConfirmLocked();
 },
 ApplyColumnAutoFilterCore: function(editor) {
  if(this.IsFilterLocked()) 
   return;
  this.ClearAutoFilterInputTimer();
  var editorValue = editor.GetValueString();
  if(this.IsBatchUpdateConfirmLocked() && this.preparedToCallbackFilterValue != "undefined"  && editorValue === this.preparedToCallbackFilterValue) 
   return;
  var columnIndex = this.ResolveColumnIndex(editor.name);
  if(columnIndex < 0 || !this.IsColumnAutoFilterChanged(columnIndex)) 
   return;
  this.SaveFilterEditorActiveElement(editor);
  this.preparedToCallbackFilterValue = editorValue;
  window.setTimeout(function() { delete this.preparedToCallbackFilterValue;  }.bind(this), this.preparedFilterValueClearDelay);
  this.AutoFilterByColumn(columnIndex, editorValue);
  this.OnChange(columnIndex);
 },
 ApplyMultiColumnAutoFilter: function(editor) {
  if(this.IsFilterLocked()) 
   return;
  this.SaveFilterEditorActiveElement(editor);
  var args = this.SerializeChangedAutoFilterValues();
  if(args.length > 0)
   this.AutoFilterByMultipleColumns(args);
  var name = editor ? editor.name : "";
  this.OnChange(this.ResolveColumnIndex(name));
 },
 SerializeChangedAutoFilterValues: function() {
  var result = [ ];
  var changedValues = this.GetChangedAutoFilterValues();
  for(var columnIndex in changedValues) {
   if(!changedValues.hasOwnProperty(columnIndex)) continue;
   result.push(columnIndex);
   result.push(changedValues[columnIndex].value);
   result.push(changedValues[columnIndex].filterCondition);
  }
  return result;
 },
 SaveFilterEditorsState: function() {
  ASPx.GridFilterHelper.prototype.SaveFilterEditorsState.call(this);
  this.initialFilterRowState = this.GetFilterRowState();
 },
 ClearFilterEditorsState: function() { 
  ASPx.GridFilterHelper.prototype.ClearFilterEditorsState.call(this);
  this.initialFilterRowState = { };
 },
 GetFilterRowState: function() {
  var indices = this.GetColumnIndicesForFilterRow();
  return ASPx.Data.ArrayToHash(indices, function(columnIndex) { return columnIndex; }, function(columnIndex) { 
   var editor = this.GetAutoFilterEditor(columnIndex);
   return {
    value: editor && editor.GetMainElement() ? editor.GetValueString() : "",
    filterCondition: this.GetFilterCondition(columnIndex)
   };
  }.bind(this));
 },
 GetChangedAutoFilterValues: function() {
  var result = { };
  var currentFilterRowState = this.GetFilterRowState();
  for(var columnIndex in this.initialFilterRowState) {
   if(!this.initialFilterRowState.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   var initialState = this.initialFilterRowState[columnIndex];
   var currentState = currentFilterRowState[columnIndex];
   if(currentState.value !== initialState.value || currentState.filterCondition !== initialState.filterCondition)
    result[columnIndex] = { filterCondition: currentState.filterCondition, value: currentState.value !== null ? currentState.value : "" };
  }
  return result;
 },
 OnColumnFilterInputKeyPress: function(editor, e) {
  if(this.OnColumnFilterInputSpecKeyPress(editor, e))
   return;
  this.ClearAutoFilterInputTimer();
  this.CreateAutoFilterTimer(editor);
  this.OnChange(this.ResolveColumnIndex(editor.name));
 },
 OnColumnFilterInputSpecKeyPress: function(editor, e) {
  if(e.htmlEvent) 
   e = e.htmlEvent;
  if(e.keyCode == ASPx.Key.Tab) 
   return true;
  if(e.keyCode == ASPx.Key.Enter) {
   ASPx.Evt.PreventEventAndBubble(e);
   window.setTimeout(function() {
    editor.Validate();
    if(this.IsMultiColumnAutoFilter())
     this.ApplyMultiColumnAutoFilter(editor);
    else
     this.ApplyColumnAutoFilterCore(editor);
   }.bind(this), 0);
   return true;
  }
  if(e.keyCode == ASPx.Key.Delete && e.ctrlKey) {
   ASPx.Evt.PreventEventAndBubble(e);
   window.setTimeout(function() {
    editor.SetValue(null);
    if(!this.IsMultiColumnAutoFilter())
     this.ApplyColumnAutoFilterCore(editor);
   }.bind(this), 0);
   return true;
  }
  return false;
 },
 OnFilterKeyPressTick: function() {
  if(this.filterKeyPressEditor && this.IsValidInstance())
   this.ApplyColumnAutoFilterCore(this.filterKeyPressEditor);
 },
 OnColumnFilterInputChanged: function(editor) {
  this.ApplyColumnAutoFilterCore(editor);
 },
 OnColumnFilterUserInput: function(editor) {
  if(this.IsAutoFilterTimerActive()) return;
  this.ColumnFilterOnPaste(editor);
 },
 ColumnFilterOnPaste: function(editor) {
  this.EnsureEditorRawValue(editor);
  this.CreateAutoFilterTimer(editor);
 },
 IsAutoFilterTimerActive: function() {
  return this.filterKeyPressTimerId !== -1;
 },
 CreateAutoFilterTimer: function(editor) {
  this.filterKeyPressEditor = editor;
  this.filterKeyPressTimerId = window.setTimeout(this.OnFilterKeyPressTick.bind(this), this.GetAutoFilterDelay());
 },
 ClearAutoFilterInputTimer: function() {
  this.filterKeyPressTimerId = ASPx.Timer.ClearTimer(this.filterKeyPressTimerId);
 },
 OnChange: function(columnIndex) {
  if(this.IsCustDialogVisible())
   window.setTimeout(function() { this.GetCustDialogHelper().ProcessFilterChange(columnIndex); }.bind(this), 0);
 },
 ClearColumnFilter: function(columnIndex) {
  this.ClearColumnAutoFilter(columnIndex);
  this.ClearColumnHeaderFilter(columnIndex);
  this.OnChange(columnIndex);
 },
 ClearColumnAutoFilter: function(columnIndex) {
  var editor = this.GetAutoFilterEditor(columnIndex);
  if(editor)
   editor.SetValue(null);   
 },
 ClearColumnHeaderFilter: function(columnIndex) {
  var column = this.GetColumn(columnIndex);
  var hfMode = column.HFMode;
  var listBox = this.GetListBox(columnIndex);
  if(listBox) {
   listBox.UnselectAll();
   if(hfMode ===  ASPx.GridHeaderFilterMode.List)
    listBox.SelectIndex(0);
  }
  if(hfMode === ASPx.GridHeaderFilterMode.CheckedList) {
   var checkbox = this.GetSelectAllCheckBox(columnIndex); 
   if(checkbox)
    checkbox.SetCheckState(ASPx.CheckBoxCheckState.Unchecked);
  }
  if(hfMode === ASPx.GridHeaderFilterMode.DateRangePicker) {
   var dateEdit_From = this.GetDateEdit_From(columnIndex);
   if(dateEdit_From) 
    dateEdit_From.SetValue(null);
   var dateEdit_To = this.GetDateEdit_To(columnIndex);
   if(dateEdit_To)
    dateEdit_To.SetValue(null);
  }
  if(hfMode === ASPx.GridHeaderFilterMode.DateRangeCalendar) {
   var calendar = this.GetCalendar(columnIndex);
   if(calendar)
    calendar.SetValue(null);
  }
 },
 HasFilter: function(columnIndex) {
  return this.HasHeaderFilter(columnIndex) || this.HasAutoFilter(columnIndex);
 },
 HasHeaderFilter: function(columnIndex) {
  var state = this.GetHeaderFilterState(columnIndex);
  var column = this.GetColumn(columnIndex);
  if(!state || !column)
   return false;
  if(column.HFMode === ASPx.GridHeaderFilterMode.List && state.listBoxSelectedIndices[0] === 0)
   return false;
  var hasDateRange = state.pickerRange && (state.pickerRange.start || state.pickerRange.end);
  var hasSelectedDates = state.calendarDates && state.calendarDates.length > 0;
  return state.listBoxSelectedIndices.length > 0 || hasDateRange || hasSelectedDates;  
 },
 HasAutoFilter: function(columnIndex) {
  var editor = this.GetAutoFilterEditor(columnIndex);   
  var value = editor && editor.GetMainElement() && editor.GetValueString();
  return !!value;
 },
 IsColumnAutoFilterChanged: function(columnIndex) {   
  var editor = this.GetAutoFilterEditor(columnIndex);
  var initState = this.initialFilterRowState[columnIndex];
  if (!editor || !editor.GetMainElement() || !initState) 
   return false;
  var currentValue = editor.GetValueString();
  return initState.value !== currentValue || initState.filterCondition !== this.GetFilterCondition(columnIndex);
 },
 FilterRowMenuButtonClick: function(columnIndex, element) {
  var menu = this.GetFilterRowMenu();
  if(!menu) return;
  var column = this.GetColumn(columnIndex);
  if(!column) return;
  var checkedItemIndex;
  for(var i = menu.GetItemCount() - 1; i >= 0; i--) {
   var item = menu.GetItem(i);
   var isItemChecked = item.name.substr(0, item.name.indexOf("|")) == this.GetFilterCondition(columnIndex);
   item.SetChecked(isItemChecked);
   if(isItemChecked)
    checkedItemIndex = item.index;
   item.SetVisible(this.GetFilterRowMenuItemVisible(item, column));
  }
  menu.ShowAtElement(element);
  this.filterRowMenuColumnIndex = columnIndex;
  this.currentCheckedItemIndex = checkedItemIndex;
  if(this.GetEnableAccessibility())
   menu.accessibleFocusElement = element;
 },
 FilterRowMenuItemClick: function(item) { 
  var itemName = item.name.substr(0, item.name.indexOf("|"));
  item.menu.ProcessLostFocus();
  if(this.currentCheckedItemIndex === item.index)
   return;
  if(this.IsMultiColumnAutoFilter() || this.IsCustDialogVisible()) {
   this.SetFilterCondition(this.filterRowMenuColumnIndex, parseInt(itemName));
   this.OnChange(this.filterRowMenuColumnIndex);
  } else {
   var args = [this.filterRowMenuColumnIndex, itemName];
   if(!this.IsCustDialogVisible())
    this.SendCallbackToChangeFilterCondition(args);
  }
 },
 GetFilterRowMenuItemVisible: function(item, column) {
  if(column.filterRowTypeKind) {
   var visible = item.name.indexOf(column.filterRowTypeKind) > -1;
   if(!visible && column.showFilterMenuLikeItem)
    return item.name.indexOf("L") > -1;
   return visible;
  }
  return false;
 },
 SetHeaderFilterPopupHtml: function(htmlObj, columnIndex) {
  var processedByCustDialogHelper = false;
  if(this.IsCustDialogVisible())
   processedByCustDialogHelper = this.GetCustDialogHelper().ProcessHeaderFilterCallback(htmlObj, columnIndex);
  if(!processedByCustDialogHelper)
   ASPx.GridFilterHelper.prototype.SetHeaderFilterPopupHtml.call(this, htmlObj, columnIndex);
 },
 OnListBoxSelectionChanged: function(listBox) {
  ASPx.GridFilterHelper.prototype.OnListBoxSelectionChanged.call(this, listBox);
  this.OnChange(listBox.gvColumn.index);
 },
 OnSelectAllCheckedChanged: function(checkBox) {
  ASPx.GridFilterHelper.prototype.OnSelectAllCheckedChanged.call(this, checkBox);
  this.OnChange(checkBox.gvColumn.index);
 },
 OnEditChanged: function(editor) {
  ASPx.GridFilterHelper.prototype.OnEditChanged.call(this, editor);
  this.OnChange(editor.gvColumn.index);
 },
 RequireApplyHeaderFilterNow: function(mode, columnIndex) {
  if(this.IsCustDialogVisible())
   return false;
  return ASPx.GridFilterHelper.prototype.RequireApplyHeaderFilterNow.call(this, mode, columnIndex);
 },
 OnControlsInitialized: function() {
  ASPx.GridFilterHelper.prototype.OnControlsInitialized.call(this);
  if(this.IsCustDialogVisible())
   this.GetCustDialogHelper().ClearHeaderFilterAfterLoadValues();
 },
 AdjustHeaderFilterListBox: function(column) {
  if(this.IsCustDialogVisible() && this.RequireShowHeaderFilterListBoxScrollbar(column)) {
   var listBox = this.GetListBox(column.index);
   var listBoxMainElement = listBox && listBox.GetMainElement();
   if(listBoxMainElement) {
    ASPx.SetStyles(listBoxMainElement, { minHeight: listBoxMainElement.parentNode.offsetHeight });
    listBox.AdjustControl();
   }
  } else
   ASPx.GridFilterHelper.prototype.AdjustHeaderFilterListBox.call(this, column);
 }
});
ASPx.GridViewFilterHelper = GridViewFilterHelper;
})();

(function() {
var GridViewContextMenuItemType = {
 FullExpand: "FullExpand",
 FullCollapse: "FullCollapse",
 SortAscending: "SortAscending",
 SortDescending: "SortDescending",
 ClearSorting: "ClearSorting",
 ShowFilterBuilder: "ShowFilterEditor",
 ShowFilterRow: "ShowFilterRow",
 ClearFilter: "ClearFilter",
 ShowFilterRowMenu: "ShowFilterRowMenu",
 GroupByColumn: "GroupByColumn",
 UngroupColumn: "UngroupColumn",
 ClearGrouping: "ClearGrouping",
 ShowGroupPanel: "ShowGroupPanel",
 ShowSearchPanel: "ShowSearchPanel",
 ShowColumn: "ShowColumn",
 HideColumn: "HideColumn",
 ShowCustomizationDialog: "ShowCustomizationDialog",
 ShowCustomizationWindow: "ShowCustomizationWindow",
 ShowFooter: "ShowFooter",
 ExpandRow: "ExpandRow",
 CollapseRow: "CollapseRow",
 ExpandDetailRow: "ExpandDetailRow",
 CollapseDetailRow: "CollapseDetailRow",
 NewRow: "NewRow",
 EditRow: "EditRow",
 DeleteRow: "DeleteRow",
 Refresh: "Refresh",
 CopyToClipboard: "CopyToClipboard",
 PasteFromClipboard: "PasteFromClipboard",
 SummarySum: "SummarySum",
 SummaryMin: "SummaryMin",
 SummaryMax: "SummaryMax",
 SummaryAverage: "SummaryAverage",
 SummaryCount: "SummaryCount",
 SummaryNone: "SummaryNone",
 GroupSummarySum: "GroupSummarySum",
 GroupSummaryMin: "GroupSummaryMin",
 GroupSummaryMax: "GroupSummaryMax",
 GroupSummaryAverage: "GroupSummaryAverage",
 GroupSummaryCount: "GroupSummaryCount",
 GroupSummaryNone: "GroupSummaryNone",
 CustomItem: "CustomItem"
};
var CONTEXT_MENU_CLIENT_STATE_KEY = "contextMenu";
var GridViewContextMenuHelper = ASPx.CreateClass(ASPx.GridCommandMenuHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, ASPx.ASPxClientGridExportFormat);
  this.grid = grid;
  this.emptyElementIndex = -1;
  this.sourceContextMenuRow = null;
  this.activeContextMenu = null;
  this.contextMenuActivating = false;
  this.clickedMenuItem = null;
 },
 GetGridName: function() { return this.grid.name; },
 GetCustWindowSuffix: function() { return this.grid.CustomizationWindowSuffix; }, 
 IsDetailGrid: function() { return this.grid.IsDetailGrid(); },
 GetGroupPanelContextMenu: function() { return this.grid.GetGroupPanelContextMenu(); },
 GetColumnContextMenu: function() { return this.grid.GetColumnContextMenu(); },
 GetRowContextMenu: function() { return this.grid.GetRowContextMenu(); },
 GetFooterContextMenu: function() { return this.grid.GetFooterContextMenu(); },
 GetGroupFooterContextMenu: function() { return this.grid.GetGroupFooterContextMenu(); },
 GetRowHotTrackStyle: function() { return this.rowHotTrackStyle; },
 GetEnableAccessibility: function() { return this.grid.accessibilityCompliant; },
 IsCustWindowVisible: function() { return this.grid.IsCustomizationWindowVisible(); },
 HasContextMenuEventHandler: function() { return !this.grid.ContextMenu.IsEmpty(); },
 RaiseContextMenu: function(objectType, index, htmlEvent, menu, showBrowserMenu) { 
  return this.grid.RaiseContextMenu(objectType, index, htmlEvent, menu, showBrowserMenu);
 },
 RaiseContextMenuItemClick: function(e, itemInfo) {
  return this.grid.RaiseContextMenuItemClick(e, itemInfo);
 },
 HasAnyContextMenu: function() {
  return this.GetGroupPanelContextMenu() || this.GetColumnContextMenu() || this.GetRowContextMenu() || this.GetFooterContextMenu();
 },
 SendContextMenuCallback: function(args) {
  return this.grid.gridCallBack([ ASPxClientGridViewCallbackCommand.ContextMenu ].concat(args));
 },
 SendContextMenuPostBack: function(args) {
  return this.grid.gridPostBack([ ASPxClientGridViewCallbackCommand.ContextMenu ].concat(args));
 },
 OnAfterCallack: function() { 
  this.ResetState();
 },
 GetCallbackState: function() {
  if(!this.clickedMenuItem)
   return "";
  var menu = this.clickedMenuItem.menu;
  var elementInfo = menu.elementInfo;
  return menu.cpType + "," + this.clickedMenuItem.indexPath + "," + elementInfo.index;
 },
 SaveClientState: function() {
  this.SetClientStateValue(this.GetCallbackState());
 },
 ResetState: function() {
  this.clickedMenuItem = null;
  this.SetClientStateValue(null);
 },
 SetClientStateValue: function(value) {
  this.grid.stateObject[CONTEXT_MENU_CLIENT_STATE_KEY] = value;
 },
 OnContextMenuClick: function(e) {
  var showDefaultMenu = ASPx.EventStorage.getInstance().Load(e);
  if(showDefaultMenu)
   return showDefaultMenu;
  if(this.IsDetailGrid())
   ASPx.EventStorage.getInstance().Save(e, true);
  var args = this.GetContextMenuArgs(e);
  if(!args.objectType && !this.HasAnyContextMenu())
   return true;
  var menu = this.GetPreparedContextMenu(args);
  var showBrowserMenu = !menu && !this.HasContextMenuEventHandler();
  showBrowserMenu = this.RaiseContextMenu(args.objectType, args.index, e, menu, showBrowserMenu);
  if(menu && !showBrowserMenu) {
   if(this.GetEnableAccessibility())
    menu.accessibleFocusElement = ASPx.Evt.GetEventSource(e);
   this.ShowContextMenu(e, menu);
   return false;
  }
  return showBrowserMenu;
 },
 ShowContextMenu: function(mouseEvent, menu) {
  this.contextMenuActivating = true;
  this.HandleContextMenuHover(menu, mouseEvent);
  menu.ShowInternal(mouseEvent);
 },
 HandleContextMenuHover: function(menu, mouseEvent) {
  menu.handler = menu.handler || this.OnContextMenuCloseUp.bind(this);
  menu.CloseUp.AddHandler(menu.handler);
  if(!this.GetRowHotTrackStyle())
   return;
  this.activeContextMenu = menu;
  this.sourceContextMenuRow = this.grid.getItemByHtmlEvent(mouseEvent);
  ASPx.AddAfterClearHoverState(function(source, args) { this.OnClearHoverState(args.item, args.element, args.toElement); }.bind(this));
 },
 OnClearHoverState: function(hoverItem, hoverElement, newHoverElement) {
  if(!this.activeContextMenu || !this.activeContextMenu.GetVisible() || !this.sourceContextMenuRow) {
   ASPx.RemoveClassNameFromElement(hoverElement, this.GetRowHotTrackStyle()[0]);
   return;
  }
  if(this.sourceContextMenuRow.id === hoverElement.id) {
   var newHoverItem = hoverItem.Clone();
   newHoverItem.Apply(hoverElement);
  }
 },
 OnContextMenuCloseUp: function(e) {
  this.contextMenuActivating = false;
  if(!this.sourceContextMenuRow || !this.activeContextMenu || this.activeContextMenu.GetVisible()) return;
  var stateController = ASPx.GetStateController();
  if(!stateController) return;
  if(stateController.currentHoverElement !== this.sourceContextMenuRow)
   stateController.DoClearHoverState(this.sourceContextMenuRow, null);
  this.sourceContextMenuRow = null;
  this.activeContextMenu = null;
 },
 GetPreparedContextMenu: function(args) { 
  var menu = null;
  switch(args.objectType) {
   case "grouppanel":
    menu = this.GetGroupPanelContextMenu();
    break;
   case "header":
   case "emptyheader":
    menu = this.GetColumnContextMenu();
    break;
   case "row":
   case "grouprow":
   case "emptyrow":
    menu = this.GetRowContextMenu();
    break;
   case "footer":
    menu = this.GetFooterContextMenu();
    break;
   case "groupfooter":
    menu = this.GetGroupFooterContextMenu();
    break;
  }
  if(menu)
   this.ActivateContextMenuItems(menu, args);
  return menu;
 },
 GetContextMenuArgs: function(e) { 
  var args = this.GetContextMenuArgsCore(e);
  if(args.objectType || !this.grid.HasBandedDataRows())
   return args;
  var index = -1;
  var grid = this.grid;
  var dataRowIdPrefix = grid.name + "_" + ASPx.GridViewConsts.DataRowID;
  var isBandedDataRowFound = !!ASPx.GetParent(ASPx.Evt.GetEventSource(e), function(element){
   index = grid.getItemIndex(element.id);
   var level = grid.GetBandedDataRowLevelByID(element.id);
   return element.id == dataRowIdPrefix + index + "_" + level;
  });
  if(isBandedDataRowFound)
   args = { objectType: "row", index: index };
  return args;
 },
 GetContextMenuArgsCore: function(e) { 
  var objectTypes = this.GetObjectTypes();
  var src = ASPx.Evt.GetEventSource(e);
  var element = src;
  while(element && element.tagName !== "BODY") {
   var id = element.id;
   element = element.parentNode;
   if(!id) continue;
   var indexInfo = this.grid.tryGetNumberFromEndOfString(id);
   var index = indexInfo.success ? indexInfo.value : "";
   for(var partialID in objectTypes) {
    if(id == partialID + index) {
     var type = objectTypes[partialID];
     var isGroupFooter = type == "groupfooter";
     if(type == "footer" || isGroupFooter) {
      if(!isGroupFooter)
       index = this.grid.GetFooterCellIndex(src);
      else
       index = this.grid.GetGroupFooterCellIndex(src);
      if(index < 0)
       return { objectType: null, index: -1 };
     } else if(type == "emptyheader" || type == "grouppanel" || type == "emptyrow") {
      index = this.emptyElementIndex;
     }
     return { objectType: type, index: index };
    }
   }
  }
  return { objectType: null, index: -1 };
 },
 ActivateContextMenuItems: function(menu, args) {
  menu.elementInfo = args;
  this.SyncMenuItemsInfoSettings(menu, args.index, menu.cpItemsInfo);
 },
 SyncMenuItemsInfoSettings: function(menu, groupElementIndex, itemsInfo) {
  for(var i = 0; i < menu.GetItemCount() ; ++i) {
   var item = menu.GetItem(i);
   var itemInfo = itemsInfo[item.indexPath];
   var visible = this.GetItemServerState(itemInfo[0], groupElementIndex);
   var enabled = this.GetItemServerState(itemInfo[1], groupElementIndex);
   var checked = this.GetItemServerState(itemInfo[2], groupElementIndex);
   if(item.name === GridViewContextMenuItemType.ShowCustomizationWindow)
    checked = this.IsCustWindowVisible();
   var column;
   if(item.name === GridViewContextMenuItemType.GroupByColumn) {
    column = this.grid.GetColumn(menu.elementInfo.index);
    enabled &= this.grid.canGroupByColumn(column);
   }
   if(item.name === GridViewContextMenuItemType.HideColumn) {
    column = this.grid.GetColumn(menu.elementInfo.index);
    enabled &= this.grid.canHideColumn(column);
   }
   item.SetVisible(visible);
   item.SetEnabled(enabled);
   item.SetChecked(checked);
   if(visible && enabled && !checked)
    this.SyncMenuItemsInfoSettings(item, groupElementIndex, itemsInfo);
  }
 },
 GetContextMenuItemChecked: function(item) {
  var itemInfo = item.menu.cpItemsInfo[item.indexPath];
  var elementIndex = item.menu.elementInfo.index;
  return this.GetItemServerState(itemInfo[2], elementIndex);
 },
 GetItemServerState: function(itemInfo, groupElementIndex) {
  var saveVisible = !!itemInfo[0];
  var indices = itemInfo.length === 1 ? [ ] : itemInfo[1];
  return ASPx.Data.ArrayIndexOf(indices, groupElementIndex) > -1 ? saveVisible : !saveVisible;
 },
 OnContextMenuItemClick: function(e) {
  var elementInfo = e.item.menu.elementInfo;
  this.clickedMenuItem = e.item;
  this.SaveClientState();
  if(this.GetEnableAccessibility() && !e.item.items.length)
   e.item.menu.ProcessLostFocus();
  if(this.RaiseContextMenuItemClick(e, elementInfo))
   return true;
  this.ProcessContextMenuItemClick(e);
  this.ResetState();
 },
 ProcessContextMenuItemClick: function(e){
  var item = e.item;
  var elementInfo = item.menu.elementInfo;
  if(!elementInfo) return;
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewContextMenuItemType.FullExpand:
    this.grid.ExpandAll();
    break;
   case GridViewContextMenuItemType.FullCollapse:
    this.grid.CollapseAll();
    break;
   case GridViewContextMenuItemType.SortAscending:
    this.grid.SortBy(elementInfo.index, "ASC", false);
    break;
   case GridViewContextMenuItemType.SortDescending:
    this.grid.SortBy(elementInfo.index, "DSC", false);
    break;
   case GridViewContextMenuItemType.ClearSorting:
    this.grid.SortBy(elementInfo.index, "NONE", false);
    break;
   case GridViewContextMenuItemType.ShowFilterBuilder:
    this.grid.ShowFilterControl();
    break;
   case GridViewContextMenuItemType.ShowFilterRow:
    this.ContextMenuShowFilterRow(!this.GetContextMenuItemChecked(item));
    break;
   case GridViewContextMenuItemType.ClearFilter:
    this.grid.AutoFilterByColumn(this.grid.GetColumn(elementInfo.index));
    break;
   case GridViewContextMenuItemType.ShowFilterRowMenu:
    this.ContextMenuShowFilterRowMenu(!this.GetContextMenuItemChecked(item));
    break;
   case GridViewContextMenuItemType.ShowGroupPanel:
    this.ContextMenuShowGroupPanel(!this.GetContextMenuItemChecked(item));
    break;
   case GridViewContextMenuItemType.ShowSearchPanel:
    this.ContextMenuShowSearchPanel(!this.GetContextMenuItemChecked(item));
    break;
   case GridViewContextMenuItemType.ShowCustomizationDialog:
    this.grid.ShowCustomizationDialog();
    break;
   case GridViewContextMenuItemType.ShowCustomizationWindow:
    if(!this.IsCustWindowVisible())
     this.grid.ShowCustomizationWindow(false, e.item.menu.accessibleFocusElement);
    else
     this.grid.HideCustomizationWindow();
    break;
   case GridViewContextMenuItemType.ShowFooter:
    this.ContextMenuShowFooter(!this.GetContextMenuItemChecked(item));
    break;
   case GridViewContextMenuItemType.ExpandRow:
    this.grid.ExpandRow(elementInfo.index);
    break;
   case GridViewContextMenuItemType.CollapseRow:
    this.grid.CollapseRow(elementInfo.index);
    break;
   case GridViewContextMenuItemType.ExpandDetailRow:
    this.grid.ExpandDetailRow(elementInfo.index);
    break;
   case GridViewContextMenuItemType.CollapseDetailRow:
    this.grid.CollapseDetailRow(elementInfo.index);
    break;
   case GridViewContextMenuItemType.NewRow:
    this.grid.AddNewItem();
    break;
   case GridViewContextMenuItemType.EditRow:
    this.ContextMenuStartEditItem(elementInfo.index, e.item.menu);
    break;
   case GridViewContextMenuItemType.DeleteRow:
    this.grid.DeleteGridItem(elementInfo.index);
    break;
   case GridViewContextMenuItemType.Refresh:
    this.grid.Refresh();
    break;
   case GridViewContextMenuItemType.CopyToClipboard:
    this.grid.CopyToClipboard();
    break;
   case GridViewContextMenuItemType.PasteFromClipboard:
    this.grid.PasteFromClipboard();
    break;
   case GridViewContextMenuItemType.HideColumn:
    var groupped = ASPx.IsExists(this.grid.GetHeader(elementInfo.index, true));
    this.grid.MoveColumn(elementInfo.index, -1, false, false, groupped);
    break;
   case GridViewContextMenuItemType.ShowColumn:
    this.grid.MoveColumn(elementInfo.index, elementInfo.index);
    break;
   case GridViewContextMenuItemType.SummarySum:
    this.ContextMenuSetSummary(item, elementInfo.index, 0);
    break;
   case GridViewContextMenuItemType.SummaryMin:
    this.ContextMenuSetSummary(item, elementInfo.index, 1);
    break;
   case GridViewContextMenuItemType.SummaryMax:
    this.ContextMenuSetSummary(item, elementInfo.index, 2);
    break;
   case GridViewContextMenuItemType.SummaryCount:
    this.ContextMenuSetSummary(item, elementInfo.index, 3);
    break;
   case GridViewContextMenuItemType.SummaryAverage:
    this.ContextMenuSetSummary(item, elementInfo.index, 4);
    break;
   case GridViewContextMenuItemType.SummaryNone:
    this.ContextMenuClearSummary(elementInfo.index);
    break;
   case GridViewContextMenuItemType.GroupSummarySum:
    this.ContextMenuSetGroupSummary(item, elementInfo.index, 0);
    break;
   case GridViewContextMenuItemType.GroupSummaryMin:
    this.ContextMenuSetGroupSummary(item, elementInfo.index, 1);
    break;
   case GridViewContextMenuItemType.GroupSummaryMax:
    this.ContextMenuSetGroupSummary(item, elementInfo.index, 2);
    break;
   case GridViewContextMenuItemType.GroupSummaryCount:
    this.ContextMenuSetGroupSummary(item, elementInfo.index, 3);
    break;
   case GridViewContextMenuItemType.GroupSummaryAverage:
    this.ContextMenuSetGroupSummary(item, elementInfo.index, 4);
    break;
   case GridViewContextMenuItemType.GroupSummaryNone:
    this.ContextMenuClearGroupSummary(elementInfo);
    break;
   case GridViewContextMenuItemType.ClearGrouping:
    this.ContextMenuClearGrouping();
    break;
   case GridViewContextMenuItemType.GroupByColumn:
    var column = this.grid.GetColumn(elementInfo.index);
    if(column) {
     var order = null;
     if(column.sortOrder !== ASPx.GridSortOrder.None)
      order = column.sortOrder === ASPx.GridSortOrder.Ascending ? "ASC" : "DSC";
     this.grid.GroupBy(elementInfo.index, null, order);
    }
    break;
   case GridViewContextMenuItemType.UngroupColumn:
    this.grid.UnGroup(elementInfo.index);
    break;
  }
  if(this.IsExportItem(command))
   this.ContextMenuExport(item);
 },
 ContextMenuExport: function(item) {
  var command = this.GetItemCommand(item),
   exportFormat = this.GetExportFormat(command);
  this.grid.ExportTo(exportFormat);
 },
 ContextMenuStartEditItem: function(visibleIndex, menu) {
  var rowCells = this.grid.GetRow(visibleIndex).children;
  var colIndex = -1;
  var menuLocationX = menu.GetMainElement().getBoundingClientRect().left;
  for(var i = 0; i < rowCells.length; ++i) {
   var cell = rowCells[i];
   if(cell.tagName !== "TD") continue;
   var cellRect = cell.getBoundingClientRect();
   if(cellRect.left > menuLocationX) break;
   if(menuLocationX > cellRect.left && menuLocationX < cellRect.right) {
    colIndex = i;
    break;
   }
  }
  this.grid.StartEditItem(visibleIndex, colIndex);
 },
 ProcessCustomContextMenuItemClick: function(usePostBack) {
  var args = [ "" ];
  if(usePostBack)
   this.SendContextMenuPostBack(args);
  else
   this.SendContextMenuCallback(args);
 },
 ContextMenuShowGroupPanel: function(show) {
  this.SendContextMenuCallback([ "ShowGroupPanel", show ? 1 : 0 ]);
 },
 ContextMenuShowSearchPanel: function(show) {
  this.SendContextMenuCallback([ "ShowSearchPanel", show ? 1 : 0 ]);
 },
 ContextMenuShowFilterRow: function(show) {
  this.SendContextMenuCallback([ "ShowFilterRow", show ? 1 : 0 ]);
 },
 ContextMenuShowFilterRowMenu: function(show) {
  this.SendContextMenuCallback([ "ShowFilterRowMenu", show ? 1 : 0 ]);
 },
 ContextMenuShowFooter: function(show) {
  this.SendContextMenuCallback([ "ShowFooter", show ? 1 : 0 ]);
 },
 ContextMenuClearGrouping: function() {
  this.SendContextMenuCallback([ "ClearGrouping" ]);
 },
 ContextMenuSetSummary: function(item, index, typeSummary) {
  var checkSummary = this.GetContextMenuItemChecked(item) ? 0 : 1;
  this.SendContextMenuCallback([ "SetSummary", index, typeSummary, checkSummary ]);
 },
 ContextMenuSetGroupSummary: function(item, index, typeSummary, isGroupSummary) {
  var checkSummary = this.GetContextMenuItemChecked(item) ? 0 : 1;
  var isGroupFooterSummary = this.IsGroupFooterMenuItem(item) ? "1" : "0";
  this.SendContextMenuCallback([ "SetGroupSummary", index, typeSummary, checkSummary, isGroupFooterSummary ]);
 },
 ContextMenuClearSummary: function(index) {
  this.SendContextMenuCallback([ "ClearSummary", index ]);
 },
 ContextMenuClearGroupSummary: function(elementInfo) {
  var isGroupFooterSummary = elementInfo.objectType === "groupfooter" ? "1" : "0";
  this.SendContextMenuCallback([ "ClearGroupSummary", elementInfo.index, isGroupFooterSummary ]);
 },
 IsGroupFooterMenuItem: function(item) {
  return item.menu.name === this.grid.GetGroupFooterContextMenuName();
 },
 GetObjectTypes: function() {
  if(!this.objectTypes)
   this.objectTypes = this.CreateObjectTypes();
  return this.objectTypes;
 },
 CreateObjectTypes: function() {
  var gridName = this.GetGridName();
  var result = { };
  result[gridName + "_" + "grouppanel"]          = "grouppanel";
  result[gridName + "_" + ASPx.GridViewConsts.AdaptiveGroupPanelID]   = "grouppanel";
  result[gridName + "_" + ASPx.GridViewConsts.HeaderRowID]   = "emptyheader";
  result[gridName + "_" + "col"]           = "header";
  result[gridName + this.GetCustWindowSuffix() + "_" + "col"]   = "header";
  result[gridName + "_" + "groupcol"]         = "header";
  result[gridName + "_" + ASPx.GridViewConsts.DataRowID]     = "row";
  result[gridName + "_" + ASPx.GridViewConsts.DetailRowID]   = "row";
  result[gridName + "_" + ASPx.GridViewConsts.AdaptiveDetailRowID] = "row";
  result[gridName + "_" + ASPx.GridViewConsts.EmptyDataRowID]   = "emptyrow";
  result[gridName + "_" + ASPx.GridViewConsts.GroupRowID]    = "grouprow";
  result[gridName + "_" + ASPx.GridViewConsts.GroupRowID + "Exp"]  = "grouprow";
  result[gridName + "_" + ASPx.GridViewConsts.FooterRowID]   = "footer";
  result[gridName + "_" + ASPx.GridViewConsts.FilterRowID]   = "filterrow";
  result[gridName + "_" + ASPx.GridViewConsts.GroupFooterRowID]    = "groupfooter";
  return result;
 },
});
ASPx.GridViewContextMenuHelper = GridViewContextMenuHelper;
})();

(function() {
var GridViewToolbarCommandType = {
 Custom: "Custom",
 FullExpand: "FullExpand",
 FullCollapse: "FullCollapse",
 ClearSorting: "ClearSorting",
 ShowFilterBuilder: "ShowFilterEditor",
 ShowFilterRow: "ShowFilterRow",
 ClearFilter: "ClearFilter",
 ShowFilterRowMenu: "ShowFilterRowMenu",
 ClearGrouping: "ClearGrouping",
 ShowGroupPanel: "ShowGroupPanel",
 ShowSearchPanel: "ShowSearchPanel",
 ShowCustomizationWindow: "ShowCustomizationWindow",
 ShowFooter: "ShowFooter",
 ShowCustomizationDialog: "ShowCustomizationDialog",
 ExpandRow: "ExpandRow",
 CollapseRow: "CollapseRow",
 ExpandDetailRow: "ExpandDetailRow",
 CollapseDetailRow: "CollapseDetailRow",
 New: "New",
 Edit: "Edit",
 Delete: "Delete",
 DeleteSelectedRowsOnPage: "DeleteSelectedRowsOnPage",
 Refresh: "Refresh",
 Update: "Update",
 Cancel: "Cancel",
 PreviewChanges: "PreviewChanges",
 HidePreview: "HidePreview",
 UpdateSummaries: "UpdateSummaries"
};
var GridViewToolbarHelper = ASPx.CreateClass(ASPx.GridToolbarHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
 },
 ProcessToolbarItemClick: function(e) {
  var item = e.item,
   command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.FullExpand:
    this.grid.ExpandAll();
    break;
   case GridViewToolbarCommandType.FullCollapse:
    this.grid.CollapseAll();
    break;
   case GridViewToolbarCommandType.ClearSorting:
    this.ToolbarClearSorting();
    break;
   case GridViewToolbarCommandType.ShowFilterBuilder:
    this.grid.ShowFilterControl();
    break;
   case GridViewToolbarCommandType.ShowFilterRow:
    this.ToolbarShowFilterRow(item.GetChecked());
    break;
   case GridViewToolbarCommandType.ClearFilter:
    this.grid.ClearFilter();
    break;
   case GridViewToolbarCommandType.ShowFilterRowMenu:
    this.ToolbarShowFilterRowMenu(item.GetChecked());
    break;
   case GridViewToolbarCommandType.ShowGroupPanel:
    this.ToolbarShowGroupPanel(item.GetChecked());
    break;
   case GridViewToolbarCommandType.ShowSearchPanel:
    this.ToolbarShowSearchPanel(item.GetChecked());
    break;
   case GridViewToolbarCommandType.ShowCustomizationWindow:
    if(!this.grid.IsCustomizationWindowVisible())
     this.grid.ShowCustomizationWindow();
    else
     this.grid.HideCustomizationWindow();
    break;
   case GridViewToolbarCommandType.ShowFooter:
    this.ToolbarShowFooter(item.GetChecked());
    break;
   case GridViewToolbarCommandType.ShowCustomizationDialog:
    this.grid.ShowCustomizationDialog();
    break;
   case GridViewToolbarCommandType.ExpandRow:
    this.grid.ExpandRow(this.grid.GetFocusedRowIndex());
    break;
   case GridViewToolbarCommandType.CollapseRow:
    this.grid.CollapseRow(this.grid.GetFocusedRowIndex());
    break;
   case GridViewToolbarCommandType.ExpandDetailRow:
    this.grid.ExpandDetailRow(this.grid.GetFocusedRowIndex());
    break;
   case GridViewToolbarCommandType.CollapseDetailRow:
    this.grid.CollapseDetailRow(this.grid.GetFocusedRowIndex());
    break;
   case GridViewToolbarCommandType.New:
    this.grid.AddNewItem();
    break;
   case GridViewToolbarCommandType.Edit:
    this.ToolbarStartEdit();
    break;
   case GridViewToolbarCommandType.Delete:
    this.ToolbarDeleteItem();
    break;
   case GridViewToolbarCommandType.DeleteSelectedRowsOnPage:
    this.ToolbarDeleteSelectedVisibleItems();
    break;
   case GridViewToolbarCommandType.Refresh:
    this.grid.Refresh();
    break;
   case GridViewToolbarCommandType.ClearGrouping:
    this.ToolbarClearGrouping();
    break;
   case GridViewToolbarCommandType.Update:
    this.grid.UpdateEdit();
    break;
   case GridViewToolbarCommandType.Cancel:
    this.grid.CancelEdit();
    break;
   case GridViewToolbarCommandType.PreviewChanges:
    this.ToolbarPreviewChanges();
    break;
   case GridViewToolbarCommandType.HidePreview:
    this.ToolbarHidePreview();
    break;
   case GridViewToolbarCommandType.UpdateSummaries:
    this.grid.UpdateSummaries();
    break;
   default:
    ASPx.GridToolbarHelper.prototype.ProcessToolbarItemClick.call(this, e);
    break;
  }
 },
 ToolbarShowGroupPanel: function(show) {
  this.SendToolbarCallback([ "ShowGroupPanel", show ? 1 : 0 ]);
 },
 ToolbarShowSearchPanel: function(show) {
  this.SendToolbarCallback([ "ShowSearchPanel", show ? 1 : 0 ]);
 },
 ToolbarShowFilterRow: function(show) {
  this.SendToolbarCallback([ "ShowFilterRow", show ? 1 : 0 ]);
 },
 ToolbarShowFilterRowMenu: function(show) {
  this.SendToolbarCallback([ "ShowFilterRowMenu", show ? 1 : 0 ]);
 },
 ToolbarShowFooter: function(show) {
  this.SendToolbarCallback([ "ShowFooter", show ? 1 : 0 ]);
 },
 ToolbarClearGrouping: function() {
  this.SendToolbarCallback([ "ClearGrouping" ]);
 },
 ToolbarClearSorting: function() {
  this.SendToolbarCallback([ "ClearSorting" ]);
 },
 ToolbarPreviewChanges: function() {
  var helper = this.GetBatchEditHelper();
  if(helper)
   helper.ShowPreviewChanges();
 },
 ToolbarHidePreview: function() {
  var helper = this.GetBatchEditHelper();
  if(helper)
   helper.HideChanges();
 },
 IsUpdateEditItem: function(item) {
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.Update:
   case GridViewToolbarCommandType.Cancel:
   case GridViewToolbarCommandType.PreviewChanges:
   case GridViewToolbarCommandType.HidePreview:
    return true;
  }
  return false;
 },
 IsShowCustomizationWindowItem: function(item) {
  return this.GetItemCommand(item) === GridViewToolbarCommandType.ShowCustomizationWindow;
 },
 RefreshItemBadge: function(item) {
  if(this.GetItemCommand(item) === GridViewToolbarCommandType.DeleteSelectedRowsOnPage)
   this.RefreshSelectionBasedItemBadge(item, this.GetSelectedVisibleGridItemCount());
 },
 GetToolbarItemEnabled: function(item){
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.Edit:
    return this.GetEditItemEnabled();
   case GridViewToolbarCommandType.Delete:
    return this.GetDeleteItemEnabled();
   case GridViewToolbarCommandType.DeleteSelectedRowsOnPage:
    return this.GetDeleteSelectedRowsOnPageItemEnabled();
   case GridViewToolbarCommandType.ExpandRow:
    return this.GetExpandRowItemEnabled();
   case GridViewToolbarCommandType.CollapseRow:
    return this.GetCollapseRowItemEnabled();
   case GridViewToolbarCommandType.ExpandDetailRow:
    return this.GetExpandDetailRowEnabled();
   case GridViewToolbarCommandType.CollapseDetailRow:
    return this.GetCollapseDetailRowEnabled();
  }
  return null;
 },
 GetEditItemEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return this.grid.allowEdit && this.IsDataRow(focusedIndex) && (this.HasBatchEditFocusedCell() || !this.IsEditingItem(focusedIndex));
 },
 GetDeleteItemEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return this.grid.allowDelete && this.IsDataRow(focusedIndex) && (this.HasBatchEditFocusedCell() || !this.IsEditingItem(focusedIndex));
 },
 GetDeleteSelectedRowsItemEnabled: function() {
  return this.grid.allowDelete && this.GetSelectedGridItemCount() > 0;
 },
 GetDeleteSelectedRowsOnPageItemEnabled: function() {
  return this.grid.allowDelete && this.GetSelectedVisibleGridItemCount() > 0;
 },
 GetExpandRowItemEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return this.IsGroupRow(focusedIndex) && !this.IsGroupRowExpanded(focusedIndex);
 },
 GetCollapseRowItemEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return this.IsGroupRow(focusedIndex) && this.IsGroupRowExpanded(focusedIndex);
 },
 GetExpandDetailRowEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return !this.IsGroupRow(focusedIndex) && !this.GetDetailRow(focusedIndex);
 },
 GetCollapseDetailRowEnabled: function(){
  var focusedIndex = this.GetFocusedItemIndex();
  return !!this.GetDetailRow(focusedIndex);
 },
 IsDataRow: function(visibleIndex) {
  return this.control.IsDataRow(visibleIndex);
 },
 IsGroupRow: function(visibleIndex) {
  return this.control.IsGroupRow(visibleIndex);
 },
 IsGroupRowExpanded: function(visibleIndex){
  return this.control.IsGroupRowExpanded(visibleIndex);
 },
 GetDetailRow: function(visibleIndex){
  return this.control.GetDetailRow(visibleIndex);
 },
 IsCustomItemVisibleOnChangesPreview: function(item) {
  return ASPx.Data.ArrayContains(item.menu.cpItemsProps.ibpv, item.indexPath);
 },
 UpdateBatchPreviewItemsState: function(item, state) {
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.PreviewChanges:
    this.UpdateItemBadge(item, state.previewChangesButtonChangesCount);
    item.SetVisible(state.previewChangesButtonVisible);
    break;
   case GridViewToolbarCommandType.HidePreview:
    item.SetVisible(state.hidePreviewButtonVisible);
    break;
   case GridViewToolbarCommandType.UpdateSummaries:
    item.SetVisible(state.updateSummariesButtonVisible);
    break;
  }
 },
 UpdateItemsOnBatchPreviewVisibilityChange: function(previewVisible) {  
  var setVisibleFunc = function(item) { 
   var visible = this.GetItemVisibilityOnChangesPreview(item, previewVisible);
   item.SetVisible(visible); 
  }.bind(this);
  this.ForEachItem(null, setVisibleFunc);
 },
 GetItemVisibilityOnChangesPreview: function(item, previewVisible) {
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.HidePreview:
    return previewVisible;
   case GridViewToolbarCommandType.UpdateSummaries:
    var helper = this.GetBatchEditHelper();
    return !previewVisible && helper && helper.IsUpdateSummariesButtonVisible();
  }
  return !previewVisible || this.IsItemVisibleOnChangesPreview(item);
 },
 IsItemVisibleOnChangesPreview: function(item) {
  var command = this.GetItemCommand(item);
  switch(command) {
   case GridViewToolbarCommandType.New:
   case GridViewToolbarCommandType.Edit:
   case GridViewToolbarCommandType.Delete:
   case GridViewToolbarCommandType.DeleteSelectedRowsOnPage:
   case GridViewToolbarCommandType.Refresh:
   case GridViewToolbarCommandType.Update:
   case GridViewToolbarCommandType.Cancel:
    return true;
   case GridViewToolbarCommandType.Custom:
    return this.IsCustomItemVisibleOnChangesPreview(item);
  }
  return false;
 }
});
ASPx.GridViewToolbarHelper = GridViewToolbarHelper;
})();
(function() {
var GridViewTableHelper = ASPx.CreateClass(ASPx.TableHelperBase, {
 GridDetailIndentClassName : "dxgvDI",
 GridGroupIndentClassName : "dxgvGI",
 constructor: function(control, contentTableIDSuffix, headerTableIDSuffix, footerTableIDSuffix, horzScroll, vertScroll) {
  this.constructor.prototype.constructor.call(this, control, contentTableIDSuffix, headerTableIDSuffix, footerTableIDSuffix, horzScroll, vertScroll);
 },
 GetArmatureCellIndexByOtherCell: function(cell) {
  var grid = this.control;
  if(!grid.IsHeaderRow(cell.parentNode))
   ASPx.TableHelperBase.prototype.GetArmatureCellIndexByOtherCell.call(this, cell);
  var columnIndex = grid.getColumnIndex(cell.id);
  return this.GetArmatureCellIndex(columnIndex);
 },
 GetArmatureCellIndex: function(columnIndex) {
  var grid = this.control;
  return grid.indentColumnCount + grid.GetHeaderMatrix().GetLeafIndex(columnIndex);
 },
 UpdateIndentCellWidths: function() {
  var result = null;
  var grid = this.control;
  var layoutHelper = grid.GetLayoutHelper();
  var hasAnyIndentCell = grid.indentColumnCount > 0 || layoutHelper.GetAdaptiveButtonPos() === ASPx.GridViewAdaptiveDetailButtonPosition.Right;
  if(layoutHelper.IsFixedTableLayout() && hasAnyIndentCell)
   result = this.UpdateIndentCellWidthsCore();
  return result;
 },
 UpdateIndentCellWidthsCore: function() {
  var info = this.GetIndentsWidthInfo();
  var tables = [this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable()];
  for(var i = 0; i < tables.length; i++) {
   var table = tables[i];
   if(!table) continue;
   var armCells = this.GetArmatureCells(table);
   for(var j = 0; j < armCells.length; j++) {
    if(!info[j]) continue;
    var width = info[j];
    var cell = armCells[j];
    if(this.GetStylePxWidth(cell) != width)
     cell.style.width = width + "px";
   }
  }
 },
 GetIndentsWidthInfo: function() {
  var grid = this.control;
  var showAdaptiveDetailButton = grid.IsResponsiveAdaptivityMode() && !grid.HasAnyAdaptiveElement();
  if(showAdaptiveDetailButton)
   grid.GetAdaptivityHelper().SetAdaptivitySelectorVisible(true); 
  var result = this.GetIndentsWidthInfoCore();
  if(showAdaptiveDetailButton)
   grid.GetAdaptivityHelper().SetAdaptivitySelectorVisible(false);
  return result;
 },
 GetIndentsWidthInfoCore: function() {
  var grid = this.control;
  var table = this.GetHeaderTable() || this.GetContentTable() || this.GetFooterTable();
  var armCells = this.GetArmatureCells(table).filter(function(cell) { 
   return ASPx.ElementHasCssClass(cell, this.GridDetailIndentClassName) || ASPx.ElementHasCssClass(cell, this.GridGroupIndentClassName); 
  }.bind(this));
  var headerRow = grid.GetHeaderRow(0);
  var dataRow = this.FindFirstVisibleRow(false, false);
  var adaptiveDataRow = this.FindFirstVisibleRow(false, true);
  var groupRow = this.FindFirstVisibleRow(true);
  var result = { };
  var rows = [ headerRow, groupRow, dataRow, adaptiveDataRow ];
  for(var i = 0; i < armCells.length; i++){
   var cellIndex = armCells[i].cellIndex;
   var button = this.FindExpandCollapseButton(cellIndex, rows);
   result[cellIndex] = this.GetButtonWidth(button);
  }
  return result;
 },
 FindExpandCollapseButton: function(cellIndex, rows) {
  for(var i = 0; i < rows.length; i++) {
   var button = this.FindExpandCollapseButtonCore(rows[i], cellIndex);
   if(button) 
    return button;
  }
  return null;
 },
 FindExpandCollapseButtonCore: function(row, cellIndex) {
  if(row && cellIndex >= 0 && cellIndex < row.cells.length) {
   var cell = row.cells[cellIndex];
   if(cell.offsetWidth > 0)
    return this.FindExpandCollapseButtonInContainer(cell);
  }
  return null;
 },
 FindExpandCollapseButtonInContainer: function(container) {
  return ASPx.GetChildByTagName(container, "IMG");
 },
 FindFirstVisibleRow: function(isGroup, isAdaptive) { 
  var grid = this.control;
  var start = grid.GetTopVisibleIndex();
  var end = start + grid.GetVisibleRowsOnPage();
  for(var i = start; i < end; i++) {
   var row = isGroup ? grid.GetGroupRow(i) : (isAdaptive ? grid.GetAdaptiveDetailRow(i) : grid.GetDataRow(i));
   if(row) return row;
  }
 },
 GetButtonWidth: function(button) {
  if(!button) return -1;
  return button.offsetWidth + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(button.parentNode);
 },
 IsRtl: function() { return this.control.rtl; }
});
ASPx.GridViewTableHelper = GridViewTableHelper;
})();
(function() {
var GridViewTableScrollHelper = ASPx.CreateClass(ASPx.GridTableScrollHelper, {
 VirtualScrollTopMarginID: "DXVSTM",
 VirtualScrollBottomMarginID: "DXVSBM",
 constructor: function(tableHelper) {
  this.constructor.prototype.constructor.call(this, tableHelper);
  this.isVirtualScrolling = this.control.IsVirtualScrolling();
  this.isVirtualSmoothScrolling = this.control.IsVirtualSmoothScrolling();
  this.lockVirtualScrolling = false;
  this.virtualScrollRowHeight = -1;
  this.virtualScrollPrevPos = -1;
  this.virtualScrollTimerID = -1;
  this.virtualScrollHandler = null;
  this.useEndlessPaging = this.control.useEndlessPaging;
  this.allowFixedGroups = this.control.allowFixedGroups;
 },
 GetLayoutHelper: function() { return this.control.GetLayoutHelper(); },
 GetVirtualScrollMarginDiv: function(isTop) { 
  var id = isTop ? this.VirtualScrollTopMarginID : this.VirtualScrollBottomMarginID;
  return this.tableHelper.GetChildElement(id);
 },
 Update: function() {
  if(this.isVirtualScrolling)
   this.UpdateVirtualScrolling();
  if(this.useEndlessPaging)
   this.UpdateEndlessPaging();
  if(this.HasHorzScroll())
   ASPx.RemoveClassNameFromElement(this.GetContentTable(), ASPx.GridViewConsts.HiddenHorizontalExtraCellMarkerClassName);
  ASPx.GridTableScrollHelper.prototype.Update.call(this);
  if(this.virtualScrollRowHeight !== this.GetVirtualScrollRowHeightCore()) {
   this.virtualScrollRowHeight = -1;
   this.UpdateVirtualScrollMargins();
  }
  if(this.HasHorzScroll())
   this.UpdatePreExtraCellRightBorders();
 },
 UpdatePreExtraCellRightBorders: function() {
  var tables = this.GetLayoutHelper().GetAllTables();
  for(var i = 0; i < tables.length; i++) {
   var armCell = this.GetArmatureExtraCell(tables[i]);
   var action = armCell.offsetWidth > 0 ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
   action(tables[i], ASPx.GridViewConsts.HiddenHorizontalExtraCellMarkerClassName);
  }
 },
 OnScrollCore: function(src) {
  if(ASPx.currentDragHelper && ASPx.currentDragHelper.isDragging())
   this.UpdateScrollableControlsOnDrag(src);
  else 
   ASPx.GridTableScrollHelper.prototype.OnScrollCore.call(this, src);
 },
 UpdateScrollableControlsOnDrag: function(src) {
  var grid = src.scrollHelper.control;
  var dragHelper = grid.GetDragHelper();
  if(dragHelper)
   dragHelper.UpdateScrollableControlsOnDrag(src);
 },
 RequireChangeScrollDivWidth: function() { return this.control.adaptivityMode === 0; },
 SetHeight: function(val) {
  if(this.useEndlessPaging)
   this.CheckEndlessPagingLoadNextPage();
  ASPx.GridTableScrollHelper.prototype.SetHeight.call(this, val);
 },
 HasFixedColumns: function() {
  return this.control.fixedColumnCount > 0 && this.control.GetFixedColumnsDiv();
 },
 IsContentTableEmpty: function() {
  return this.control.pageRowCount < 1;
 },
 IsRestoreScrollPosition: function(){
  var grid = this.control;
  if(this.savedScrollTop > -1 && this.savedScrollTop !== grid.GetVerticalScrollPosition())
   return true;
  if(this.savedScrollLeft > -1 && this.savedScrollLeft !== grid.GetHorizontalScrollPosition())
   return true;
  return false;
 },
 LogScrollPosition: function() {
  if(!this.control.GetMainElement()) return;
  if(this.RequireRtlScrollLeftCorrection())
   this.savedRtlWidth = this.GetHorzScrollableControl().clientWidth;
  ASPx.GridTableScrollHelper.prototype.LogScrollPosition.call(this);
 },
 LoadScrollPosition: function() {
  ASPx.GridTableScrollHelper.prototype.LoadScrollPosition.call(this);
  if(this.RequireRtlScrollLeftCorrection())
   this.savedScrollLeft = this.CorrectRtlScrollLeft(this.savedScrollLeft);
 },
 RequireRtlScrollLeftCorrection: function() { return this.HasHorzScroll() && this.IsRtl(); },
 CorrectRtlScrollLeft: function(scrollLeft) {
  var width = this.GetHorzScrollableControl().clientWidth;
  if(!ASPx.IsExists(this.savedRtlWidth))
   this.savedRtlWidth = width;
  var diff = this.savedRtlWidth - width;
  return scrollLeft + diff;
 },
 ApplyScrollPosition: function() {
  if(!this.isVirtualScrolling && this.savedScrollTop > -1 || this.restoreScrollPosition)
   this.SetVertScrollPosition(this.savedScrollTop);
  if(this.savedScrollLeft > -1) {
   var savedScrollLeft = this.savedScrollLeft;
   window.setTimeout(function() { this.SetHorzScrollPosition(savedScrollLeft); }.aspxBind(this), 0);
  }
 },
 SetScrollPositionCore: function(element, pos, isTop) {
  this.lockVirtualScrolling = true;
  try {
   ASPx.GridTableScrollHelper.prototype.SetScrollPositionCore.call(this, element, pos, isTop);
   if(isTop)
    this.UpdatePopupEditFormPosition();
  } finally {
   this.lockVirtualScrolling = false;
  }
 },
 UpdatePopupEditFormPosition: function() {
  var grid = this.control;
  var popup = grid.GetPopupEditForm();
  if(!popup || !popup.GetVisible())
   return;
  var visibleIndex = grid.getItemIndex(popup.GetCurrentPopupElement().id);
  var visibleInViewPortIndices = grid.GetRowIndicesVisibleInViewPort();
  var needPopupElementCorrect = visibleIndex > -1 && visibleInViewPortIndices.length > 0 && !ASPx.Data.ArrayContains(visibleInViewPortIndices, visibleIndex);
  if(needPopupElementCorrect) {
   var newElement = grid.GetDataRow(visibleInViewPortIndices[0]);
   popup.SetPopupElementID(newElement.id);
  }
  popup.UpdatePosition();
 },
 GetResizingHelper: function() { return this.control.GetResizingHelper(); },
 UpdateVirtualScrolling: function() {
  this.UpdateVirtualScrollMargins();
  this.UpdateVirtualScrollHandler(true);
 },
 UpdateVirtualScrollHandler: function(attach) {
  if(!this.virtualScrollHandler) 
   this.virtualScrollHandler = this.OnVirtualScroll.aspxBind(this);
  var scrollDiv = this.GetVertScrollableControl();
  ASPx.Evt.DetachEventFromElement(scrollDiv, "scroll", this.virtualScrollHandler);
  if(attach)
   window.setTimeout(function() { ASPx.Evt.AttachEventToElement(scrollDiv, "scroll", this.virtualScrollHandler); }.aspxBind(this), 0);
 },
 UpdateVirtualScrollMargins: function() {
  var grid = this.control;
  if(grid.pageCount < 1 || grid.GetMainElement().offsetHeight === 0)
   return;
  var topDiv = this.GetVirtualScrollMarginDiv(true);
  var bottomDiv = this.GetVirtualScrollMarginDiv();  
  var isLastPage = grid.pageIndex === grid.pageCount -1;
  var topRowCount = grid.visibleStartIndex;
  var bottomRowCount = !isLastPage ? (grid.pageCount - grid.pageIndex - 1) * grid.pageRowSize : grid.pageRowSize - grid.pageRowCount;
  if(this.isVirtualSmoothScrolling) {
   var lastVisibleRowIndex = grid.visibleStartIndex + grid.pageRowCount - 1;
   bottomRowCount = grid.totalRowCount - lastVisibleRowIndex - 1;
  }
  var rowHeight = this.GetVirtualScrollRowHeight();
  var topDivHeight = topRowCount * rowHeight;
  var bottomDivHeight = bottomRowCount * rowHeight;
  var requireChangeTopDivHeight = topDiv && topDiv.offsetHeight !== topDivHeight;
  var requireChangeBottomDivHeight = bottomDiv && bottomDiv.offsetHeight !== bottomDivHeight;
  if(!requireChangeTopDivHeight && !requireChangeBottomDivHeight)
   return;
  this.PrepareVirtualScrollMarginDiv(topDiv, topDivHeight);
  this.PrepareVirtualScrollMarginDiv(bottomDiv, bottomDivHeight);
  var newVertScrollPosition = topDivHeight;
  if(this.restoreScrollPosition)
   newVertScrollPosition = this.virtualScrollPrevPos;
  else if(this.isVirtualSmoothScrolling)
   newVertScrollPosition = grid.pageIndex * grid.pageRowSize * rowHeight;
  window.setTimeout(function() {
   this.SetVertScrollPosition(newVertScrollPosition);
   this.virtualScrollPrevPos = newVertScrollPosition;
   this.restoreScrollPosition = false;
  }.aspxBind(this), 0);
 },
 PrepareVirtualScrollMarginDiv: function(div, height) {
  if(!div) return;
  while(div.firstChild)
   ASPx.RemoveElement(div.firstChild);
  var maxPieceHeight = 1100000;
  if(height <= maxPieceHeight) {
   div.style.height = height + "px";
  } else {
   while(height > 0) {
    var pieceHeight = height >= maxPieceHeight ? maxPieceHeight : height;
    height -= maxPieceHeight;
    var pieceDiv = document.createElement("DIV");
    pieceDiv.style.height = pieceHeight + "px";
    div.appendChild(pieceDiv);
   } 
  }
 },
 OnVirtualScroll: function() {
  this.ClearVirtualScrollTimer();
  var deferredHandler = function() { this.HandleVirtualScroll(); }.aspxBind(this);
  this.virtualScrollTimerID = window.setTimeout(deferredHandler, this.control.virtualScrollingDelay);
 },
 OnBeforeCallback: function(command) {
  var safeCommandsToRestoreScroll = [
   ASPxClientGridViewCallbackCommand.StartEdit, ASPxClientGridViewCallbackCommand.CancelEdit, ASPxClientGridViewCallbackCommand.UpdateEdit,
   ASPxClientGridViewCallbackCommand.ExpandRow, ASPxClientGridViewCallbackCommand.CollapseRow, ASPxClientGridViewCallbackCommand.ShowDetailRow,
   ASPxClientGridViewCallbackCommand.HideDetailRow, ASPxClientGridViewCallbackCommand.CustomCallback
  ];
  if(this.isVirtualScrolling && safeCommandsToRestoreScroll.some(function(x) { return x === command; }))
   this.restoreScrollPosition = true;
 },
 isElementInScrollableContainerVisible: function (element) {
  if(!element)
   return false;
  var scrollableElement = this.GetScrollDiv(this.GetContentTable());
  var scrollDivTop = ASPx.GetAbsoluteY(scrollableElement);
  var scrollDivBottom = scrollDivTop + scrollableElement.offsetHeight;
  var elementTop = ASPx.GetAbsoluteY(element);
  var elementBottom = elementTop + element.offsetHeight;
  var isTopEdgeVisible = elementTop >= scrollDivTop && elementTop <= scrollDivBottom;
  var isBottomEdgeVisible = elementBottom >= scrollDivTop && elementBottom <= scrollDivBottom;
  return isTopEdgeVisible || isBottomEdgeVisible;
 },
 IsVirtualScrollLocked: function () {
  var grid = this.control;
  var isNewRowEditFormVisible = grid.IsNewRowEditing() && this.isElementInScrollableContainerVisible(grid.GetEditingRow());
  return grid.IsBatchChangesViewMode() || isNewRowEditFormVisible;
 },
 HandleVirtualScroll: function() {
  var grid = this.control;
  if(this.IsVirtualScrollLocked())
   return; 
  var pos = this.GetVertScrollPosition();
  if(pos == this.virtualScrollPrevPos)
   return;
  this.virtualScrollPrevPos = pos;
  if(this.lockVirtualScrolling) 
   return;
  var index = this.GetPageIndexForVirtualScrollPos(pos);
  if(index !== grid.pageIndex && index >= 0 && index <= grid.pageCount - 1 && grid.pageIndex >= 0) {
   this.UpdateVirtualScrollHandler();
   grid.PreventCallbackAnimation();
   grid.GotoPage(index);
   if(this.isVirtualSmoothScrolling)
    this.restoreScrollPosition = true;
  }
 },
 GetPageIndexForVirtualScrollPos: function(pos) {
  var grid = this.control;
  if(grid.totalRowCount === 0)
   return 0;
  if(!this.isVirtualSmoothScrolling)
   return this.GetElementIndex(pos, grid.pageCount);
  var topRowIndex = this.GetElementIndex(pos, grid.totalRowCount);
  if(topRowIndex >= grid.visibleStartIndex && topRowIndex <= grid.visibleStartIndex + grid.pageRowCount - 1)
   return grid.pageIndex + (this.IsTableBottomSideIntersected() ? 1 : 0);
  var container = this.GetContentTable().parentNode;
  var middleRowIndex = this.GetElementIndex(pos + container.clientHeight / 2, grid.totalRowCount);
  return Math.floor(middleRowIndex / grid.pageRowSize);
 },
 GetElementIndex: function(pos, totalElementCount) {
  var container = this.GetContentTable().parentNode;
  var index = Math.floor(totalElementCount * pos / container.scrollHeight);
  if(this.IsTableBottomSideIntersected())
   index++;
  return Math.min(totalElementCount - 1, index);
 },
 IsTableBottomSideIntersected: function() {
  var table = this.GetContentTable();
  var container = table.parentNode;
  var tableTop = ASPx.GetAbsoluteY(table);
  var containerTop = ASPx.GetAbsoluteY(container);
  var tableBottom = tableTop + table.offsetHeight;
  var containerBottom = containerTop + container.clientHeight;
  return tableTop <= containerTop && tableBottom >= containerTop && tableBottom <= containerBottom;
 },
 ClearVirtualScrollTimer: function() {
  this.virtualScrollTimerID = ASPx.Timer.ClearTimer(this.virtualScrollTimerID);
 },
 GetVirtualScrollRowHeight: function() {
  if(this.virtualScrollRowHeight < 0)
   this.virtualScrollRowHeight = this.GetVirtualScrollRowHeightCore();
  return this.virtualScrollRowHeight;
 },
 GetVirtualScrollRowHeightCore: function() {
  var grid = this.control;
  var dataRow = grid.GetDataRow(grid.visibleStartIndex);
  var previewRow = grid.GetPreviewRow(grid.visibleStartIndex);
  var height = dataRow ? dataRow.offsetHeight : 20;
  if(previewRow)
   height += previewRow.offsetHeight;
  return height;
 },
 UpdateEndlessPaging: function() {
  var container = this.GetVertScrollableControl();
  if(container.dxEndlessPaging)
   return;
  ASPx.Evt.AttachEventToElement(container, "scroll", function(e) { this.OnEndlessPagingScroll(e); }.aspxBind(this)); 
  ASPx.Evt.AttachEventToElement(container, ASPx.Evt.GetMouseWheelEventName(), function(e) { this.OnEndlessPagingMouseWheel(e); }.aspxBind(this));
  container.dxEndlessPaging = true;
 },
 OnEndlessPagingMouseWheel: function(e) {
  if(!this.control.InCallback()) return;
  var canScrollBottom = this.CalculateBottomExcess(true) > 0;
  var isScrollingToBottom = ASPx.Evt.GetWheelDelta(e) < 0;
  if(!canScrollBottom && isScrollingToBottom)
   return ASPx.Evt.PreventEvent(e);
 },
 OnEndlessPagingScroll: function(e) {
  this.CheckEndlessPagingLoadNextPage();
 },
 CheckEndlessPagingLoadNextPage: function() {
  var grid = this.control;
  if(grid.pageIndex + 1 === grid.pageCount || grid.pageCount === 0 || grid.InCallback())
   return;
  var avgPageHeight = this.CalculateAveragePageHeight();
  var bottomExcess = this.CalculateBottomExcess();
  if(bottomExcess < avgPageHeight / 3) {
   grid.NextPage();
  }
 },
 CalculateBottomExcess: function(withLoadingPanel) {
  var table = this.GetContentTable();
  var scrollDiv = this.GetScrollDiv(table);
  var contentHeight = table.offsetHeight;
  var result = contentHeight - scrollDiv.clientHeight - scrollDiv.scrollTop;
  if(withLoadingPanel){
   var lpContainer = this.control.GetEndlessPagingLPContainer();
   if(lpContainer)
    result += lpContainer.clientHeight;
  }
  return result;
 },
 CalculateAveragePageHeight: function() {
  var grid = this.control;
  var contentHeight = this.GetContentTable().offsetHeight;
  return grid.pageRowSize * contentHeight / grid.pageRowCount;
 }
});
ASPx.GridViewTableScrollHelper = GridViewTableScrollHelper;
})();

(function() {
var GridViewFixedGroupsHelper = ASPx.CreateClass(ASPx.TableHelperAdapter, {
 IndicatorClassName: "dxgvFGI",
 FixedRowClassName: "dxgvFGFixed",
 FloatingRowClassName: "dxgvFGFloating",
 DefaultIndicatorRight: 5,
 RootNodeIndex: -100000,
 ResizeTimeout: 100,
 HiddenIndicatorImage: "dxgvHiddenFGI",
 constructor: function(tableHelper) {
  this.tableHelper = tableHelper;
  this.rowsHeight = { };
  this.root = null;
  this.nodes = [ ];
  this.leafs = [ ];
  this.intervals = [ ];
 },
 Initialize: function() {
  this.CreateTree();
  this.PopulateIntervals();
  this.UpdateIntervalHeights();
  this.PrepareScrollableContainer();
  this.AttachEvents();
 },
 AttachEvents: function() {
  ASPx.Evt.AttachEventToElement(this.GetScrollDiv(), "scroll", this.OnScroll.bind(this));
 },
 OnAfterCallback: function() {
  this.Reset();
  this.Initialize();
  this.OnScroll();
 },
 OnBrowserWindowResize: function() {
  clearTimeout(this.windowResizeTimer);
  this.windowResizeTimer = setTimeout(function() {
   this.UpdateIntervalHeights();
   this.scrollTop = -1;
   this.OnScroll();
  }.bind(this), this.ResizeTimeout);
 },
 Reset: function() {
  this.root = null;
  this.leafs = [ ];
  this.etalonPlaceholder = null;
  this.prevInterval = null;
  this.rowsHeight = { };
  this.RemoveRowPlaceholders(); 
  this.nodes = [ ];
  this.intervals = [ ];
  this.scrollTop = -1;
 },
 CreateTree: function() { 
  this.root = this.CreateNode(this.RootNodeIndex);
  this.PopulateTree();
  this.PopulateLeafs();
  this.PopulateIsLastChild();
 },
 PopulateTree: function() {
  var indices = ASPx.Data.Range(this.GetPageRowCount(), this.GetVisibleStartIndex());
  indices = this.GetParentGroupIndices().concat(indices);
  var parents = [ this.root ];
  for(var i = 0; i < indices.length; i++) {
   var index = indices[i];
   var parent = parents[parents.length - 1];
   var node = this.CreateNode(index);
   var isGroup = node.groupLevel > -1;
   var isNewGroup = isGroup && !parent.isRoot && parent.groupLevel >= node.groupLevel;
   if(isNewGroup) {
    while(node.groupLevel <= parent.groupLevel) {
     parents.pop();
     parent = parents[parents.length - 1];
    }
   }
   if(isGroup)
    parents.push(node);
   parent.children.push(node);
   node.parent = parent;
   node.isGroup = isGroup;
   this.nodes.push(node);
  }
 },
 CreateNode: function(index) {
  return {
   index: index,
   groupLevel: this.GetGroupRowLevel(index),
   parent: null,
   children: [ ],
   row: this.GetRow(index),
   isRoot: index === this.RootNodeIndex
  };
 },
 PopulateLeafs: function() {
  this.leafs = this.nodes.filter(function(node) { return node.children.length === 0; });
 },
 PopulateIsLastChild: function() {
  for(var i = 0; i < this.nodes.length; i++) {
   var node = this.nodes[i];
   var siblings = node.parent.children;
   var lastNodeIndex = siblings.length - 1;
   node.isLastChild = siblings[lastNodeIndex] === node;
  }
 },
 PopulateIntervals: function() {
  var intervals = [];
  var notLastChildren = [];
  var collapsedGroupsOnSameLevel = [];
  for(var i = 0; i < this.leafs.length; i++) {
   var leaf = this.leafs[i];
   if(!leaf.isGroup) {
    if(collapsedGroupsOnSameLevel.length > 0) {
     intervals.push(this.CreateInterval(collapsedGroupsOnSameLevel));
     collapsedGroupsOnSameLevel = [];
     notLastChildren = [];
    }
   }
   else
    collapsedGroupsOnSameLevel.push(leaf);
   if(leaf.isLastChild) {
    if(notLastChildren.length > 0)
     intervals.push(this.CreateInterval(notLastChildren));
    intervals.push(this.CreateInterval(this.GetLastChildTreeLine(leaf)));
    collapsedGroupsOnSameLevel = [];
    notLastChildren = [];
   }
   else
    notLastChildren.push(leaf);
  }
  this.intervals = intervals;
 }, 
 CreateInterval: function(nodes) {
  var fixed = this.GetFixedTreeLine(nodes[0]);
  var floating = nodes.filter(function(n) { return n.children.length > 0; }).map(function(n) { return n.index; });
  return {
   fixedIndices: fixed,
   floatingIndices: floating,
   nodeIndices: nodes.map(function(n) { return n.index; }),
   fixedNodes: fixed.map(this.FindNode.bind(this)),
   floatingNodes: floating.map(this.FindNode.bind(this)),
   nodes: nodes
  };
 },
 GetFixedTreeLine: function(node) {
  var result = [ ];
  var requireFix = false;
  while(!node.parent.isRoot) {
   requireFix |= !node.isLastChild;
   if(requireFix)
    result.push(node.parent.index);
   node = node.parent;
  }
  return result.reverse();
 },
 GetLastChildTreeLine: function(node) {
  var result = [ node ];
  while(node.isLastChild && !node.parent.isRoot) {
   result.push(node.parent);
   node = node.parent;
  }
  return result.reverse();
 },
 PopulateIntervalHeights: function() {
  var top = this.GetIntervalStartPosition();
  for(var i = 0; i < this.intervals.length; i++) {
   var height = this.GetRowHeightSum(this.intervals[i].nodeIndices);
   var start = top;
   var end = start + height - 1;
   this.intervals[i].start = start;
   this.intervals[i].end = end;
   top += height;
  }
 },
 GetIntervalStartPosition: function() {
  var result = 0;
  if(this.IsVirtualScrolling()) {
   var strut = ASPx.GetPreviousSibling(this.GetContentTable());
   if(strut)
    result = strut.clientHeight;
  }
  return result;
 },
 OnScroll: function() {
  var top = this.GetScrollTop();
  this.Update(top);
 },
 Update: function(top) {
  var interval = this.FindInterval(top);
  if(!interval) return;
  if(this.scrollTop !== top) {
   this.scrollTop = top;
   this.UpdateRows(interval);
  } else {
   this.UpdateHorScrollLeftPosition(interval);
   this.UpdateFloatingGroupIndicatorPosition(interval, false);
  }
  this.UpdateFirstVisibleGroupRowIndicatorImageClassName();
 },
 UpdateFirstVisibleGroupRowIndicatorImageClassName: function() {
  var firstVisibleGroupRow = this.GetFirstVisibleGroupRow();
  if(firstVisibleGroupRow) {
   var firstVisibleGroupRowIndicatorImage = this.GetIndicatorImageByRow(firstVisibleGroupRow);
   if(this.scrollTop === 0 && this.GetControl().parentGroupIndices.length === 0)
    ASPx.AddClassNameToElement(firstVisibleGroupRowIndicatorImage, this.HiddenIndicatorImage);
   else
    ASPx.RemoveClassNameFromElement(firstVisibleGroupRowIndicatorImage, this.HiddenIndicatorImage);
  }
 },
 OnFixedColumnsVisibilityChanged: function() {
  var top = this.GetScrollTop();
  var interval = this.FindInterval(top);
  if(!interval) return;
  this.prevInterval = interval;
  this.UpdateRowStyles(interval, true);
  this.UpdateRowStyles(interval, false);
 },
 UpdateRows: function(interval) {
  if(interval === this.prevInterval) return;
  if(this.prevInterval)
   this.UpdateRowStyles(this.prevInterval, true);
  this.UpdateRowStyles(interval, false);
  if(this.IsScrollTopValid())
   this.CompensateViaPadding(interval);
  this.prevInterval = interval;
 },
 UpdateRowStyles: function(interval, resetStyles) {
  this.UpdateFixedNodes(interval, resetStyles);
  this.UpdateFloatingNodes(interval, resetStyles);
  this.UpdateFloatingGroupIndicatorPosition(interval, resetStyles);
 },
 UpdateFixedNodes: function(interval, reset) {
  var fixedNodes = interval.fixedNodes;
  var left = this.GetRowLeftOffset();
  var right = this.GetRowRightOffset();
  for(var i = 0; i < fixedNodes.length; i++) {
   var node = fixedNodes[i];
   var row = fixedNodes[i].row;
   var style = { };
   if(reset) {
    this.GetStyleHelper().RemoveClassFromElement(row, this.FixedRowClassName);
    style = this.GetFixedRowStyle("", "", "", "");
    this.GetStyleHelper().ResetElementInitialCssText(row);
   } else {
    style = this.GetFixedRowStyle(this.GetFixedNodeTop(node, interval), right, row.offsetHeight, fixedNodes.length - i);
    this.UpdateFixedNodeCellLeft(node, left);
    this.GetStyleHelper().AddClassToElement(row, this.FixedRowClassName);
    this.GetStyleHelper().AddStyleToElementInitialCssText(row, style);
   }
   ASPx.SetStyles(row, style);
   if(!this.IsScrollTopValid())
    this.CompensateViaRowPlaceholder(node, reset);
   this.UpdateFixedNodeIndentsWidth(fixedNodes[i], reset);
  }
 },
 GetStyleHelper: function() {
  return this.tableHelper.control.GetStyleHelper();
 },
 GetFixedRowStyle: function(top, right, height, zIndex) {
  return { top: top, right: right, height: height, zIndex: zIndex };
 },
 GetFixedNodeTop: function(node, interval) {
  var prevFixedNodesCount = interval.fixedIndices.indexOf(node.index);
  var indices = interval.fixedIndices.slice(0, prevFixedNodesCount);
  return this.GetRowHeightSum(indices);
 },
 UpdateFloatingNodes: function(interval, reset) {
  var floatingNodes = interval.floatingNodes;
  for(var i = 0; i < floatingNodes.length; i++) {
   var node = floatingNodes[i];
   var transformValue;
   if(reset) {
    ASPx.RemoveClassNameFromElement(node.row, this.FloatingRowClassName);
    transformValue = 0;
   } else {
    ASPx.AddClassNameToElement(node.row, this.FloatingRowClassName);
    transformValue = this.GetNodeTransformValue(node, interval);
   }
   this.SetNodeRowTransform(node, transformValue);
  }
 },
 GetNodeTransformValue: function(node, interval) {
  var lastIntervalNode = interval.nodes[interval.nodes.length - 1];
  var diff = lastIntervalNode.index - node.index;
  var indices = ASPx.Data.Range(diff - 1, node.index + 1).filter(function(index) { return interval.floatingIndices.indexOf(index) === -1; });
  return this.GetRowHeightSum(indices);
 },
 SetNodeRowTransform: function(node, value) { 
  for(var i = 0; i < node.row.cells.length; i++)
   this.SetTransform(node.row.cells[i], value);
 },
 UpdateFixedNodeIndentsWidth: function(node, requireResetWidth) {
  var indentCount = this.GetLayoutHelper().GetIndentCellCount(node.index, 0, ASPx.GridViewRowType.Group);
  var cells = [].slice.call(node.row.cells, 0, indentCount);
  var armCells = this.GetArmatureCells();
  var getArmCellWidth = function(cellIndex) { return armCells[cellIndex].offsetWidth; }; 
  var cellIndex = 0;
  for(var i = 0; i < cells.length; i++) {
   var cell = cells[i];
   var armIndices = ASPx.Data.Range(cell.colSpan, cellIndex);
   cellIndex += cell.colSpan;
   var width = requireResetWidth ? "" : ASPx.Data.Sum(armIndices, getArmCellWidth);
   width -= ASPx.GetLeftRightBordersAndPaddingsSummaryValue(cell);
   ASPx.SetStyles(cell, { width: width });
  }
 },
 SetTransform: function(el, value) {
  var translateValue = "translate(0, " + value + "px)";
  var style = { };
  style.transform = translateValue;
  style.msTransform = translateValue;
  style.webkitTransform = translateValue;
  ASPx.SetStyles(el, style);
 },
 UpdateIntervalHeights: function() {
  this.PopulateRowsHeight();
  this.PopulateIntervalHeights();
 },
 PopulateRowsHeight: function () {
  this.rowsHeight = ASPx.Data.ArrayToHash(this.nodes, 
   function(n) { return n.index; }, 
   function(n) { return this.GetRowHeight(n); }.bind(this)
  );
 },
 GetRowHeight: function(node) {
  if(!node.row) return 0;
  var rowIndices = this.GetRowIndicesWithSameVisibleIndex(node);
  var rows = this.GetContentTableRows().filter(function(row, index) { return rowIndices.indexOf(index) > -1; });
  return ASPx.Data.Sum(rows, this.GetRowHeightCore.bind(this));
 },
 GetRowIndicesWithSameVisibleIndex: function(node) {
  var rowIndices = [ node.row.rowIndex ];
  var nextNode = this.FindNode(node.index + 1);
  if(nextNode && nextNode.row) {
   var nodeRowIndex = node.placeholder ? node.placeholder.rowIndex : node.row.rowIndex;
   var rowsDiff = nextNode.row.rowIndex - nodeRowIndex;
   rowIndices = rowIndices.concat(ASPx.Data.Range(rowsDiff - 1, node.row.rowIndex + 1));
  }
  return rowIndices;
 },
 GetRowHeightCore: function(row) {
  if(row.getBoundingClientRect) {
   var rect = row.getBoundingClientRect();
   return rect.height || rect.bottom - rect.top;
  }
  return row.outerHeight;
 },
 GetRowHeightSum: function(indices) {
  return ASPx.Data.Sum(indices, function(i) { return this.rowsHeight[i]; }.bind(this));
 },
 PrepareScrollableContainer: function() {
  var scrollDiv = this.GetScrollDiv();
  if(scrollDiv.wrapper) return;
  var scrollTop = scrollDiv.scrollTop;
  var wrapper = ASPx.CreateHtmlElement("DIV", { position: "relative" });
  ASPx.InsertElementAfter(wrapper, scrollDiv);
  scrollDiv.wrapper = wrapper;
  wrapper.appendChild(scrollDiv);
  scrollDiv.scrollTop = scrollTop;
 },
 UpdateHorScrollLeftPosition: function(interval) {
  var left = this.GetRowLeftOffset();
  for(var i = 0; i < interval.fixedNodes.length; i++) {
   var node = interval.fixedNodes[i];
   this.UpdateFixedNodeCellLeft(node, left);
  }
 },
 UpdateFixedNodeCellLeft: function(node, left) {
  var helper = this.GetLayoutHelper();
  var indentCount = helper.GetIndentCellCount(node.index, 0, ASPx.GridViewRowType.Group);
  var armCells = this.GetArmatureCells();
  var row = node.row;
  var cells = [].slice.call(row.cells, 0, indentCount + 1);
  var indentCells = [].slice.call(cells, 0, indentCount);
  var indentArmCells = indentCells.map(function(indent) { return armCells[indent.cellIndex]; });
  var indentWidths = indentArmCells.map(function(indent) { return ASPx.PxToInt(indent.style.width); });
  for(var i = 0; i < indentCells.length; i++) {
   ASPx.SetStyles(indentCells[i], { left: left });
   left += indentWidths[i];
  }
  ASPx.SetStyles(cells[indentCount], { left: left, right: 0 });
 },
 UpdateFloatingGroupIndicatorPosition: function(interval, reset) {
  if(!this.GetControl().HasHorzScroll()) return;
  var nodes = interval.floatingNodes;
  for(var i = 0; i < nodes.length; i++)
   ASPx.SetStyles(this.GetIndicatorImage(nodes[i]), { right : this.GetFloatingGroupIndicatorRight(reset) });
 },
 GetIndicatorImage: function(node) {
  return this.GetIndicatorImageByRow(node.row);
 },
 GetIndicatorImageByRow: function(row) {
  if(!row.indicator)
   row.indicator = row.querySelector("." + this.IndicatorClassName);
  return row.indicator;
 },
 GetFloatingGroupIndicatorRight: function(reset) { 
  if(reset)
   return "";
  var div = this.GetScrollDiv();
  return this.DefaultIndicatorRight + div.scrollWidth - div.clientWidth - div.scrollLeft;
 },
 FindNode: function(index) { return this.nodes.filter(function(node) { return node.index === index; })[0]; },
 FindInterval: function(top) {
  return this.intervals.filter(function(interval) { return top >= interval.start &&  top <= interval.end; })[0];
 },
 CompensateViaRowPlaceholder: function(node, removePlaceholder) {
  if(removePlaceholder)
   this.RemoveRowPlaceholder(node);
  else 
   this.AddRowPlaceholder(node);
 },
 CompensateViaPadding: function(interval) {
  ASPx.SetStyles(this.GetContentTable(), { paddingTop : this.GetRowHeightSum(interval.fixedIndices) });
 },
 RemoveRowPlaceholder: function(node) {
  if(node.placeholder) {
   ASPx.RemoveElement(node.placeholder);
   delete node.placeholder;
  }
 },
 AddRowPlaceholder: function(node) {
  if(node.placeholder) return;
  node.placeholder = this.GetEtalonRowPlaceholder().cloneNode(true);
  ASPx.SetStyles(node.placeholder, { height: this.GetRowHeightSum([ node.index ]) });
  ASPx.InsertElementAfter(node.placeholder, node.row);
 },
 GetEtalonRowPlaceholder: function() {
  if(!this.etalonPlaceholder)
   this.etalonPlaceholder = this.CreateEtalonRowPlaceholder();
  return this.etalonPlaceholder;
 },
 CreateEtalonRowPlaceholder: function() {
  var row = ASPx.CreateHtmlElement("TR");
  var cell = row.insertCell();
  var armCells = [].slice.call(this.GetContentTable().rows[0].cells);
  var hasAdaptiveIntent = ASPx.ElementHasCssClass(armCells[armCells.length - 1], ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
  if(hasAdaptiveIntent)
   ASPx.AddClassNameToElement(row.insertCell(), ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
  cell.colSpan = armCells.length - (hasAdaptiveIntent ? 1 : 0);
  return row;
 },
 GetPlaceholderCells: function() {
  if(!this.nodes || this.IsScrollTopValid()) return [ ];
  var etalonCell = this.GetEtalonRowPlaceholder().cells[0];
  var placeholdersCells = this.nodes.filter(function(node) { return !!node.placeholder; }).map(function(node) { return node.placeholder.cells[0]; });
  return [ etalonCell ].concat(placeholdersCells);
 },
 RemoveRowPlaceholders: function() {
  if(this.GetControl().useEndlessPaging)
   this.nodes.forEach(this.RemoveRowPlaceholder.bind(this));
 },
 GetContentTable: function() { return this.GetControl().GetMainTable(); },
 GetContentTableRows: function() { 
  var tbody = this.GetContentTable().tBodies[0];
  return ASPx.GetChildNodesByTagName(tbody, "TR");
 },
 GetScrollDiv: function() {
  var scrollHelper = this.GetControl().GetScrollHelper();
  return scrollHelper ? scrollHelper.GetScrollDiv(this.GetContentTable()) : null;
 },
 GetControl: function() { return this.tableHelper.control; },
 GetLayoutHelper: function() { return this.GetControl().GetLayoutHelper(); },
 GetRow: function(index) { return this.GetControl().GetRow(index); },
 GetGroupRow: function(index) { return this.GetControl().GetGroupRow(index); },
 GetGroupRowLevel: function(index) { return this.GetLayoutHelper().GetGroupRowLevel(index); },
 GetVisibleStartIndex: function() { return this.GetControl().visibleStartIndex; },
 GetFirstVisibleGroupRow: function() { return this.GetControl().GetGroupRow(this.GetVisibleStartIndex()); },
 GetPageRowCount: function() { return this.GetControl().pageRowCount; },
 IsVirtualScrolling: function() { return this.GetControl().IsVirtualScrolling(); },
 GetParentGroupIndices: function() { return this.GetControl().parentGroupIndices; },
 GetScrollTop: function() { return this.GetScrollDiv().scrollTop; },
 GetScrollLeft: function() { return this.GetScrollDiv().scrollLeft; },
 GetRowLeftOffset: function() { return -this.GetScrollLeft(); },
 GetRowRightOffset: function() {
  var extraCellWidth = 0;
  var fixedColumnHelper = this.GetControl().GetFixedColumnsHelper();
  if(fixedColumnHelper)
   extraCellWidth = fixedColumnHelper.GetExtraCell(this.GetContentTable().rows[0]).offsetWidth;
  return this.GetScrollDiv().offsetWidth - this.GetScrollDiv().clientWidth + extraCellWidth; 
 },
 IsScrollTopValid: function() { return !ASPx.Browser.WebKitFamily; },
 GetArmatureCells: function() { return this.tableHelper.GetArmatureCells(this.GetContentTable()); },
});
ASPx.GridViewFixedGroupsHelper = GridViewFixedGroupsHelper;
})();
(function() {
var GridViewTableFixedColumnsHelper = ASPx.CreateClass(ASPx.TableFixedColumnsHelper, {
 FixedColumnsWrapperClassName: "dxgvFCW",
 FixedColumnsScrolledWrapperClassName: "dxgvFCSW",
 StyleSheetMarginsId: "Margins",
 constructor: function(tableHelper, fixedDivName, fixedContentDivName, fixedColumnCount, indentCount) {
  this.constructor.prototype.constructor.call(this, tableHelper, fixedDivName, fixedContentDivName, fixedColumnCount, indentCount);
  this.scrollableRowSettingsMap = {
   scrollGroupRow: [ ASPx.GridViewConsts.GroupRowID, ASPx.GridViewConsts.GroupRowExpID ],
   scrollData: [ ASPx.GridViewConsts.DataRowID ],
   scrollPreview: [ ASPx.GridViewConsts.PreviewRowID ],
   scrollDetail: [ ASPx.GridViewConsts.DetailRowID ],
  };
  this.scrollableRowIds = [ ASPx.GridViewConsts.EditingRowID ];
 },
 GetColumnHelper: function() { return this.control.GetColumnHelper(); },
 GetLayoutHelper: function() { return this.control.GetLayoutHelper(); },
 GetSpannedElementPattern: function(idParts) { return this.GetLayoutHelper().GetSpannedElementPattern(idParts); },
 GetHorizontalExtraCellClassName: function() { return ASPx.GridViewConsts.HorizontalExtraCellClassName; },
 GetFixedCellCount: function() { return this.control.indentColumnCount + ASPx.TableFixedColumnsHelper.prototype.GetFixedCellCount.call(this); },
 OnScroll: function(event) {
  var src = ASPx.Evt.GetEventSource(event);
  var helper = src.fixedHelper.control.GetDragHelper();
  if(helper)
   helper.UpdateTargetPositionPostponed();
  ASPx.TableFixedColumnsHelper.prototype.OnScroll.call(this, event);
 },
 UpdateCellsVisibility: function(columnsToHide, reset) {
  var layoutHelper = this.GetLayoutHelper();
  this.UpdateArmatureCellsVisibility(columnsToHide);
  var prevHeaderVisibilityInfo = !reset ? this.CalcColumnVisibilityInfo(this.hiddenColumnCount, true) : null;
  var prevDataVisibilityInfo = !reset ? this.CalcColumnVisibilityInfo(this.hiddenColumnCount) : null;
  var headerVisibilityInfo = this.CalcColumnVisibilityInfo(columnsToHide, true);
  var dataVisibilityInfo = this.CalcColumnVisibilityInfo(columnsToHide);
  var headerDiff = this.CalcVisibilityInfoDiff(headerVisibilityInfo, prevHeaderVisibilityInfo, true);
  var dataDiff = this.CalcVisibilityInfoDiff(dataVisibilityInfo, prevDataVisibilityInfo);
  var rows = layoutHelper.GetAllTableRows();
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   var rowInfo = layoutHelper.GetRowInfo(row.id);
   if(!rowInfo) continue;
   var map = layoutHelper.GetRowCellMap(rowInfo);
   if(!map) continue;
   var isHeader = rowInfo.rowType === ASPx.GridViewRowType.Header;
   var visibilityInfo = isHeader ? headerDiff : dataDiff;
   var cells = row.cells;
   for(var columnIndex in map) {
    if(!map.hasOwnProperty(columnIndex)) continue;
    var columnInfo = visibilityInfo[columnIndex];
    if(columnInfo) {
     var cellIndex = map[columnIndex];
     var cell = cells[cellIndex];
     if(columnInfo.changeVisibility)
      this.SetCellVisible(cell, columnInfo.visible);
     if(columnInfo.changeColSpan)
      ASPx.Attr.ChangeCellSpanCount(cell, Math.max(1, columnInfo.colSpan), true);
    }
   }
  }
  var columnVisibilityChanged = this.hiddenColumnCount != columnsToHide;
  this.hiddenColumnCount = columnsToHide;
  var stretchedRows = rows.filter(function(row) { return this.IsSpannedRow(row); }.bind(this));
  if(stretchedRows.length > 0) {
   layoutHelper.UpdateStretchedRowsColSpan();
   this.UpdateScrollableRowsMargins();
   this.UpdateFrozenRowWidths();
  }
  if(columnVisibilityChanged)
   this.OnColumnVisibilityChanged();
 },
 OnColumnVisibilityChanged: function() {
  var groupsHelper = this.control.GetFixedGroupsHelper();
  if(groupsHelper)
   groupsHelper.OnFixedColumnsVisibilityChanged();
  var scrollHelper = this.control.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.UpdatePreExtraCellRightBorders();
 },
 CalcColumnVisibilityInfo: function(columnsToHide, isHeader) {
  var layoutHelper = this.GetLayoutHelper();
  var layout = isHeader ? layoutHelper.GetHeaderLayout() : layoutHelper.GetEtalonDataRowLayout();
  var matrix = this.GetColumnHelper().CreateLayoutMatrixInfo(layout).matrix;
  var height = matrix.length;
  var hiddenSpans = { };
  var start = this.FixedColumnCount;
  var end = start + columnsToHide - 1;
  for(var j = start; j <= end; j++) {
   var indices = this.GetColIndices(height, matrix, j);
   indices = ASPx.Data.GetDistinctArray(indices);
   for(var k = 0; k < indices.length; k++) {
    var columnIndex = indices[k];
    if(isNaN(hiddenSpans[columnIndex])) 
     hiddenSpans[columnIndex] = 0;
    hiddenSpans[columnIndex]++;
   }
  }
  var info = { };
  for(var i = 0; i < layout.length; i++) {
   var level = layout[i];
   for(var j = 0; j < level.length; j++) {
    var node = level[j];
    var hideColSpan = hiddenSpans[node.columnIndex] || 0;
    var newColSpan = node.colSpan - hideColSpan;
    info[node.columnIndex] = { colSpan: newColSpan, visible: newColSpan > 0 };
   }
  }
  return info;
 },
 GetColIndices: function(height, matrix, colIndex) {
  return ASPx.Data.Range(height, 0).map(function(i) { return matrix[i][colIndex]; });
 },
 CalcVisibilityInfoDiff: function(info, prevInfo, isHeader) {
  prevInfo = prevInfo || { };
  var requireChangeColSpan = this.control.GetLayoutHelper().GetLayoutHeight(isHeader) > 1;
  var result = { };
  for(var columnIndex in info) {
   if(!info.hasOwnProperty(columnIndex)) continue;
   var currentColumnInfo = info[columnIndex];
   var prevColumnInfo = prevInfo[columnIndex];
   currentColumnInfo.changeVisibility = !prevColumnInfo || currentColumnInfo.visible !== prevColumnInfo.visible;
   currentColumnInfo.changeColSpan = (!prevColumnInfo || currentColumnInfo.colSpan !== prevColumnInfo.colSpan) && requireChangeColSpan;
   if(currentColumnInfo.changeVisibility || currentColumnInfo.changeColSpan)
    result[columnIndex] = currentColumnInfo;
  }
  return result;
 },
 UpdateArmatureCellsVisibility: function(columnsToHide) {
  var tables = this.GetLayoutHelper().GetAllTables();
  for(var i = 0; i < tables.length; i++)
   this.UpdateArmatureCellsVisibilityCore(tables[i], columnsToHide);
 },
 UpdateArmatureCellsVisibilityCore: function(table, columnsToHide) {
  if(!table) return;
  var fixedCellCount = this.GetFixedCellCount();
  var firstVisibleCellIndex = fixedCellCount + columnsToHide;
  var armCells = this.GetArmatureCells(table);
  for(var i = fixedCellCount; i < armCells.length; i++)
   this.SetCellVisible(armCells[i], i >= firstVisibleCellIndex);
 },
 OnColumnClientMove: function() {
  var grid = this.control;
  if(grid.allowChangeColumnHierarchy) {
   var columnHelper = this.GetColumnHelper();
   var leafs = columnHelper.GetHeaderLeafs();
   this.FixedColumnCount = leafs.filter(function(n) { return columnHelper.IsColumnFixed(n.columnIndex); }).length;
  }
  this.UpdateCellsVisibility(0, true);
  this.UpdateCellsVisibility(this.GetColumnsToHide(this.GetFixedDiv().scrollLeft)); 
  this.UpdateFixedDivSize(); 
 },
 GetColumnWidth: function(columnIndex) {
  var grid = this.control;
  return this.GetHeaderRowCount() ? this.GetCellRealWidth(grid.GetHeader(columnIndex)) : this.GetArmatureColumnWidth(columnIndex);
 },
 GetHeaderRowCount: function() {
  return this.control.showColumnHeaders ? this.control.GetHeaderMatrix().GetRowCount() : 0;
 },
 GetArmatureColumnWidth: function(columnIndex) {
  var index = this.GetLeafIndex(columnIndex);
  var armatureCell = this.GetArmatureCells(this.GetContentTable())[index];
  return this.GetStylePxWidth(armatureCell);
 },
 GetVisibleColumnIndices: function() {
  return this.GetColumnHelper().GetVisibleColumnIndices(true);
 },
 GetLeafIndex: function(columnIndex) {
  return this.control.GetHeaderMatrix().GetLeafIndex(columnIndex);
 },
 ConvertToCellIndex: function(index) { 
  if(ASPx.IsExists(index) && index >= 0) {
   var result = this.GetLeafIndex(index);
   if(result >= this.FixedColumnCount)
    return result;
  }
  return -1;
 },
 GetColumnCount: function() { return this.GetVisibleColumnIndices().length; },
 CalculateColumnDimensions: function() {
  var result = { columnWidths : [ ], fixedWidth: 0 };
  var columnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var width = this.GetColumnWidth(columnIndices[i]);
   result.columnWidths[i] = width;
   if(i < this.FixedColumnCount)
    result.fixedWidth += width;
  }
  return result;
 },
 GetLastColumnIndexFromBound: function(columnWidths, rectWidth, start, allowRightBound) {
  var startColumnWidthExceedsRectWidth = columnWidths[start] > rectWidth;
  if(startColumnWidthExceedsRectWidth)
   return start;
  for(var i = start; i < columnWidths.length; i++) {
   rectWidth -= columnWidths[i];
   if(rectWidth > 0) continue;
   if(allowRightBound && rectWidth !== 0) 
    i--;
   return i;
  }
  return columnWidths.length - 1;
 },
 GetHiddenColumnsTotalWidth: function(hiddenColumnCount) {
  var totalWidth = 0;
  var indices = this.GetVisibleColumnIndices();
  for(var i = 0; i < hiddenColumnCount; i++)
   totalWidth += this.GetColumnWidth(indices[i + this.FixedColumnCount]);
  return totalWidth;
 },
 HideColumnsRelyOnScrollPosition: function() {
  var scrollHelper = this.control.GetScrollHelper();
  var fixedDiv = this.GetFixedDiv();
  var maxScrollLeft = fixedDiv.scrollWidth - fixedDiv.offsetWidth;
  var scrollLeft = Math.min(scrollHelper.savedScrollLeft, maxScrollLeft);
  var columnsToHide = this.GetColumnsToHide(scrollLeft);
  this.UpdateCellsVisibility(columnsToHide);
 },
 IsSpannedRow: function(row) { return this.GetLayoutHelper().IsSpannedRow(row); },
 IsScrollableRow: function(row) {
  return this.scrollableRowIds.length && new RegExp(this.GetSpannedElementPattern(this.scrollableRowIds)).test(row.id);
 },
 IsFrozenRow: function(row) { return this.IsSpannedRow(row) && !this.IsScrollableRow(row); },
 GetSpannedCell: function(row) { return this.GetLayoutHelper().GetSpannedCell(row); },
 SetFixedColumnScrollableRows: function(scrollableRowSettings) {
  this.ProcessScrollableRowSettings(scrollableRowSettings);
  var rows = this.GetLayoutHelper().GetAllTableRows();
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   if(this.IsSpannedRow(row))
    this.WrapScrollableRowContentCell(this.GetSpannedCell(row));
  }
  this.UpdateFrozenRowWidths();
 },
 ProcessScrollableRowSettings: function(scrollableRowSettings) {
  for(var setting in scrollableRowSettings)
   if(scrollableRowSettings[setting])
    this.scrollableRowIds = this.scrollableRowIds.concat(this.scrollableRowSettingsMap[setting]);
 },
 UpdateFrozenRowWidths: function() {
  var rows = this.GetLayoutHelper().GetAllTableRows().filter(function(row) { return this.IsFrozenRow(row); }.aspxBind(this));
  var helper = this.control.GetScrollHelper();
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   var cell = this.GetSpannedCell(row);
   var wrapper = cell.wrapper;
   if(!wrapper)
    return;
   var table = ASPx.GetParentByTagName(row, "table");
   var scrollDiv = helper.GetScrollDiv(table);
   var indentsWidth = ASPx.GetAbsoluteX(cell) - ASPx.GetAbsoluteX(scrollDiv);
   var cellWidth = cell.offsetWidth;
   var cellPaddings = ASPx.GetLeftRightBordersAndPaddingsSummaryValue(cell);
   var wrapperWidth = Math.min(scrollDiv.clientWidth - indentsWidth - cellPaddings, cellWidth - cellPaddings);
   ASPx.SetStyles(wrapper, { width: wrapperWidth });
  }
 },
 WrapScrollableRowContentCell: function(cell) {
  if(!cell.wrapper)
   cell.wrapper = this.CreateWrapper(cell);
  ASPx.RemoveClassNameFromElement(cell.wrapper, this.FixedColumnsScrolledWrapperClassName);
  ASPx.SetStyles(cell.wrapper, { width: "auto" });
  if(this.IsScrollableRow(cell.parentNode)) {
   ASPx.AddClassNameToElement(cell.wrapper, this.FixedColumnsScrolledWrapperClassName);
   ASPx.SetStyles(cell, { overflow: "hidden" });
  }
  return cell.wrapper;
 },
 CreateWrapper: function(cell) {
  var wrapper = ASPx.CreateHtmlElement("div");
  ASPx.AddClassNameToElement(wrapper, this.FixedColumnsWrapperClassName);
  ASPx.MoveChildrenToElement(cell, wrapper);
  cell.appendChild(wrapper);
  return wrapper;
 },
 TryScrollToFocusedEditor: function(editor) {
  var scrollDiv = this.control.GetMainTable().parentNode;
  var editFormCell = this.control.GetEditFormTableCell();
  var editorElement = editor.GetMainElement();
  var editorLeft = ASPx.GetAbsoluteX(editorElement);
  var editorRight = editorLeft + editorElement.offsetWidth;
  var containerLeft = ASPx.GetAbsoluteX(editFormCell);
  var containerRight = ASPx.GetAbsoluteX(scrollDiv) + scrollDiv.offsetWidth;
  var excessLeft = containerLeft - editorLeft;
  var excessRight = editorRight - containerRight;
  if(excessLeft <= 0 && excessRight <= 0)
   return false;
  var indices = this.GetVisibleColumnIndices().slice(this.FixedColumnCount);
  var columnCount = this.GetHiddenColumnCountToMakeEditorVisible(this.hiddenColumnCount, indices, excessLeft, excessRight);
  if(this.hiddenColumnCount === columnCount)
   return false;
  this.UpdateCellsVisibility(columnCount);
  this.control.SetHorizontalScrollPosition(this.GetHiddenColumnsTotalWidth(columnCount));
  return true;
 },
 GetHiddenColumnCountToMakeEditorVisible: function(hiddenColCount, indices, excessLeft, excessRight) {
  var isLeft = excessLeft > 0;
  var excess = isLeft ? excessLeft : excessRight;
  var limit = !isLeft ? Math.abs(excessLeft) : null;
  var hiddenIndices = indices.slice(0, hiddenColCount).reverse();
  var visibleIndices = indices.slice(hiddenColCount);
  indices = isLeft ? hiddenIndices : visibleIndices;
  var inc = isLeft ? -1 : 1;
  for(var i = 0; i < indices.length; i++) {
   if(excess <= 0) break;
   var width = this.GetColumnWidth(indices[i]);
   excess -= width;
   limit -= width;
   if(isLeft || limit > 0)
    hiddenColCount += inc;
  }
  return hiddenColCount;
 },
 CalculateScrollableRowsWrappersMargin: function() {
  var armCells = this.GetArmatureCells(this.GetContentTable());
  var result = 0;
  var start = this.GetFixedCellCount();
  var end = start + this.hiddenColumnCount;
  for(var i = start; i < end; i++)
   result -= ASPx.PxToInt(armCells[i].style.width);
  return result;
 },
 UpdateScrollableRowsMargins: function() {
  var marginLeft = this.CalculateScrollableRowsWrappersMargin();
  var rules = [{
   selector: "#" + this.control.GetMainElement().id + " ." + this.FixedColumnsScrolledWrapperClassName,
   cssText: "margin-left: " + marginLeft + "px"
  }];
  this.UpdateFixedColumnsStyleSheet(this.StyleSheetMarginsId, rules);
 },
 Update: function() {
  ASPx.TableFixedColumnsHelper.prototype.Update.call(this);
  this.PrepareColumnActiveElements();
 },
 PrepareColumnActiveElements: function() {
  var indices = this.GetVisibleColumnIndices();
  for(var i = 0; i < indices.length; i++)
   this.InitializeColumnActiveElements(indices[i]);
 },
 InitializeColumnActiveElements: function(columnIndex) {
  var elements = this.GetColumnActiveElements(columnIndex);
  var handler = function() { this.TryShowColumn(columnIndex, true); }.bind(this);
  for(var i = 0; i < elements.length; i++)
    this.AttachEvent(elements[i], "focus", handler);
 },
 GetColumnActiveElements: function(columnIndex) {
  var layoutHelper = this.GetLayoutHelper();
  var cells = [ layoutHelper.GetHeaderCell(columnIndex), layoutHelper.GetFilterCell(columnIndex)];
  cells = cells.filter(function(cell) { return !!cell; });
  return cells.reduce(function(accum, cell) { return accum = accum.concat(ASPx.FindChildActionElements(cell)); }, [ ]);
 }
});
ASPx.GridViewTableFixedColumnsHelper = GridViewTableFixedColumnsHelper;
})();
(function() {
ASPx.tableColumnResizing = null;
var TableResizingHelperBase = ASPx.CreateClass(ASPx.TableHelperAdapter, {
 PostponeResizingBarWrapperClassName: "dxgvPRB",
 PostponeVisibleResizingBarWrapperClassName: "dxgvPRBVisible",
 PostponeResizingBarLabelClassName: "dxgvPRBL",
 PostponeResizingOriginalBarClassName: "dxgvPRBO",
 PostponeResizingNewBarClassName: "dxgvPRBN",
 PostponeResizingBarAniimationDuration: 125,
 constructor: function(tableHelper) {
  this.constructor.prototype.constructor.call(this, tableHelper);
  this.maximumOffset = ASPx.Browser.TouchUI ? 10 : 3;
  this.defaultMinWidth = 16;
  this.prevX = 0;
  this.colInfo = { };
  this.nextColInfo = { };
  this.resizingInfo = null;
 },
 Initialize: function() {
  this.UpdateControlMinWidth();
 },
 OnAfterCallback: function() {
  this.UpdateControlMinWidth();
 },
 UpdateControlMinWidth: function() {
  this.controlMinWidth = undefined;
  if(this.IsControlColumnResizeMode() && !this.HasHorzScroll())
   this.controlMinWidth = this.CalcControlMinWidth();
 },
 IsResizing: function() { 
  return ASPx.tableColumnResizing == this;
 },
 CanStartResizing: function(e, headerCell) {
  this.prevX = ASPx.Evt.GetEventX(e);
  var left = ASPx.GetAbsoluteX(headerCell);
  var right = left + headerCell.offsetWidth - 1;
  var leftOffset = this.prevX - left;
  var rightOffset = right - this.prevX;
  var isLeftEdge = leftOffset < this.maximumOffset && leftOffset >= 0;
  var isRightEdge = rightOffset <= this.maximumOffset && rightOffset >= 0;
  if(!isLeftEdge && !isRightEdge)
   return false;
  return this.CanStartResizingCore(headerCell.id, isLeftEdge, isRightEdge);
 },
 CanStartResizingCore: function(cellId, isLeftEdge, isRightEdge) {
  var columnIndex = this.GetColumnIndexById(cellId);
  var rtl = this.IsRtl();
  if(isLeftEdge && !rtl || isRightEdge && rtl)
   return !this.IsLeftmostColumn(columnIndex);
  if(isRightEdge && !rtl || isLeftEdge && rtl) {
   if(!this.IsNextColumnResizable())
    return true;
   return !this.IsRightmostColumn(columnIndex);
  }
 },
 GetResizingColumnIndex: function(e, headerCell) {
  var isLeft = ASPx.Evt.GetEventX(e) < ASPx.GetAbsoluteX(headerCell) + headerCell.offsetWidth / 2;
  if(this.IsRtl())
   isLeft = !isLeft;
  var columnIndex = this.GetColumnIndexById(headerCell.id);
  return this.GetResizingColumnIndexCore(columnIndex, isLeft);
 },
 GetResizingColumnIndexCore: function(columnIndex, isLeft) {
  if(isLeft)
   return this.GetColumnNeighbor(columnIndex, true);
  return columnIndex;
 },
 StartResizing: function(columnIndex) {
  if(this.IsControlModeWithHorizontalScrolling())
   this.EnsureCellsHavePixelWidths();
  this.colInfo = this.GetColumnInfo(columnIndex);
  if(this.IsNextColumnResizable())
   this.nextColInfo = this.GetColumnInfo(this.GetColumnNeighbor(columnIndex, false));
  ASPx.tableColumnResizing = this;
  ASPx.Selection.SetElementSelectionEnabled(document.body, false);
  if(this.IsPostponeMode())
   this.StartPosponeResizing();
 },
 EndResizing: function(e) {
  this.ResetHorizontalScrollCorrection();
  if(this.IsPostponeMode())
   this.EndPostponeResizing();
  if(!this.colInfo.headerCell)
   return;
  this.SaveControlDimensions();
  this.AdjustInnerControls();
  this.control.AssignEllipsisTooltips();
  this.OnResized(this.colInfo.index);
 },
 CancelResizing: function() {
  this.ResetHorizontalScrollCorrection();
  ASPx.tableColumnResizing = null;
  ASPx.Selection.SetElementSelectionEnabled(document.body, true);
  this.prevX = 0;
  this.colInfo = { };
  this.nextColInfo = { };
  this.calculatedMinWidth = 0;
  this.UpdateScrollControlsSize();
 },
 AdjustInnerControls: function() {
  ASPx.GetControlCollection().AdjustControls(this.control.GetMainElement());
 },
 UpdateScrollControlsSize: function() {
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   scrollHelper.Update();
 },
 OnMouseMove: function(e) {
  if(ASPx.TouchUIHelper.isTouchEvent(e) && !ASPx.TouchUIHelper.isGesture)
   ASPx.Evt.PreventEvent(e);
  if(this.colInfo.headerCell.cellIndex < 0) { 
   this.CancelResizing(e);
   return;
  }
  ASPx.Selection.Clear();
  this.Resize(e);
 },
 OnMouseUp: function(e) {
  this.EndResizing();
  this.CancelResizing();
 },
 Resize: function(e) {
  var resizingInfo = this.CalculateResizingInfo(e) || this.resizingInfo;
  if(!resizingInfo)
   return;
  if(this.IsPostponeMode())
   this.ResizePostpone(resizingInfo);
  else
   this.ResizeLive(resizingInfo);
 },
 StartPosponeResizing: function() {
  this.UpdateResizingBar(true);
  this.SetResizingBarVisible(true);
 },
 ResizePostpone: function(resizingInfo) {
  this.resizingInfo = resizingInfo;
  this.UpdateResizingBar(false);
 },
 ResizeLive: function(resizingInfo) {
  if(!resizingInfo) return;
  if(this.RequireHorizontalScrollCorrection() && this.IsRtl() && !this.initialScrollRight)
   this.initialScrollRight = this.GetScrollableDivScrollRight();
  this.ApplyColumnWidths(resizingInfo);
  if(this.RequireHorizontalScrollCorrection())
   this.CorrectHorizontalScroll(resizingInfo.delta);
 },
 EndPostponeResizing: function() {
  this.SetResizingBarVisible(false);
  this.ApplyColumnWidths(this.resizingInfo);
  this.resizingInfo = null;
 },
 SetResizingBarVisible: function(visible) {
  var wrapper = this.GetResizingBarWrapper();
  if(visible) {
   ASPx.SetElementDisplay(wrapper, visible);
   setTimeout(function() {
    ASPx.AddClassNameToElement(wrapper, this.PostponeVisibleResizingBarWrapperClassName);
   }.bind(this), 0);
  }
  else {
   ASPx.RemoveClassNameFromElement(wrapper, this.PostponeVisibleResizingBarWrapperClassName);
   setTimeout(function() {
    ASPx.SetElementDisplay(wrapper, visible);
   }, this.PostponeResizingBarAniimationDuration);
  }
 },
 UpdateResizingBar: function(updateOriginalBar) {
  var dimensions = this.CalcResizingBarDimensions(this.colInfo.headerCell);
  var wrapper = this.GetResizingBarWrapper();
  ASPx.SetAbsoluteY(wrapper, dimensions.top);
  ASPx.SetAbsoluteX(wrapper, dimensions.left);
  ASPx.SetOffsetWidth(wrapper, dimensions.width);
  ASPx.SetOffsetHeight(wrapper, dimensions.height);
  if(updateOriginalBar)
   ASPx.SetStyles(this.GetResizingOriginalBar(), { width: dimensions.width });
  this.UpdateResizingBarLabel(dimensions.columnWidth, dimensions.width);
 },
 UpdateResizingBarLabel: function(colWidth, barWidth) {
  var label = this.GetResizingBarLabel();
  label.innerHTML = "w: " + colWidth + "px";
 },
 CalcResizingBarDimensions: function(cell) {
  var borderCorrection = this.GetHeaderCellBorderCorrection(cell);
  var cellWidth = this.GetCellRealWidth(cell) + borderCorrection.width;
  var delta = this.resizingInfo ? this.resizingInfo.delta : 0;
  var columnWidth = cellWidth + delta;
  var top = ASPx.GetAbsoluteY(cell) - borderCorrection.top;
  var left = ASPx.GetAbsoluteX(cell) + borderCorrection.left;
  var width = this.CalcResizingBarWidth(columnWidth);
  var height = this.CalculatePostponeResizingBarHeight() + borderCorrection.top*2;
  var scrollCorrections = this.CorrectResizingBarScrollOverflow(left, cellWidth);
  if(this.IsRtl())
   left -= delta;
  return { 
   top: top, 
   left:   left + scrollCorrections.left, 
   width:  width + scrollCorrections.width, 
   height: height, 
   columnWidth: columnWidth 
  };
 },
 CorrectResizingBarScrollOverflow: function(cellLeft, cellWidth) {
  var result = { left: 0, width: 0 };
  var scrollHelper = this.GetScrollHelper();
  if(!scrollHelper || !scrollHelper.HasHorzScroll())
   return result;
  var scrollDiv = scrollHelper.GetScrollDiv(this.GetContentTable());
  var scrollDivLeft = ASPx.GetAbsoluteX(scrollDiv);
  if(!this.IsRtl()) {
   var diff = scrollDivLeft - cellLeft;
   if(diff > 0) {
    result.left = diff;
    result.width = -diff;
   }
  } else {
   var scrollDivRight = scrollDivLeft + scrollDiv.offsetWidth;
   var cellRight = cellLeft + cellWidth;
   var diff = cellRight - scrollDivRight;
   if(diff > 0)
    result.width = -diff;
  }
  return result;
 },
 CalcResizingBarWidth: function(columnWidth) { return columnWidth; }, 
 CalculatePostponeResizingBarHeight: function() {
  var result = 0;
  var scrollHelper = this.GetScrollHelper();
  var tables = [ this.GetHeaderTable(), this.GetContentTable() ];
  for(var i = 0; i < tables.length; i++) {
   var table = tables[i];
   if(table) {
    var height = table.offsetHeight;
    if(this.HasVertScroll())
     height = scrollHelper.GetScrollDiv(table).offsetHeight;
    result += height;
   }
  }
  if(this.HasHorzScroll() && this.HasVertScroll()) {
   var scrollDiv = scrollHelper.GetScrollDiv(this.GetContentTable());
   result -= scrollDiv.offsetHeight - scrollDiv.clientHeight;
  }
  if(!this.HasVertScroll())
   result -= this.GetFooterHeight();
  return result;
 },
 GetHeaderCellBorderCorrection: function(cell) {
  var result = { left: 0, width: 0, top: 0 };
  this.barBorderWidth = this.barBorderWidth || ASPx.PxToInt(ASPx.GetCurrentStyle(this.GetResizingOriginalBar()).borderTopWidth);
  var cellStyle = ASPx.GetCurrentStyle(cell);
  var borderLeftWidth = ASPx.PxToInt(cellStyle.borderLeftWidth);
  var borderRightWidth = ASPx.PxToInt(cellStyle.borderRightWidth);
  var borderTopWidth = ASPx.PxToInt(cellStyle.borderTopWidth);
  result.top = borderTopWidth ? this.barBorderWidth - borderTopWidth : this.barBorderWidth;
  if(borderRightWidth) {
   result.left = -borderRightWidth;
   result.width = borderRightWidth;
  } else if(borderLeftWidth)
   result.width = borderLeftWidth;
  return result;
 },
 ApplyColumnWidths: function(resizingInfo) {
  if(!resizingInfo) return;
  this.prevX = resizingInfo.newX;
  var table = this.control.GetMainElement();
  var tableWidth = table.offsetWidth;
  this.ApplyColumnWidth(this.colInfo.index, resizingInfo.newWidth + "px");
  this.colInfo.armCell.widthRestrictionsAssigned = false;
  if(this.IsNextColumnResizable()) {
   this.ApplyColumnWidth(this.nextColInfo.index, resizingInfo.nextColNewWidth + "px");
   this.nextColInfo.armCell.widthRestrictionsAssigned = false;
  } else if(!this.HasHorzScroll()) {
   ASPx.DropElementOriginalWidth(table);
   table.style.width = (tableWidth + resizingInfo.delta) + "px";
   if(this.HasVertScroll())
    this.GetScrollHelper().Update();
  }
 },
 IsHorzAutoScroll: function() { return this.tableHelper.IsHorzAutoScroll(); },
 GetScrollableDivScrollLeft: function() { return this.GetScrollableDiv().scrollLeft; },
 GetScrollableDivScrollRight: function() { return this.GetElementScrollRight(this.GetScrollableDiv()); },
 SetScrollableDivScrollRight: function(scrollRight) { this.SetElementScrollRight(this.GetScrollableDiv(), scrollRight); },
 GetScrollableDiv: function() {
  var scrollHelper = this.GetScrollHelper();
  if(!scrollHelper) return null;
  return scrollHelper.GetScrollDiv(scrollHelper.GetContentTable());
 },
 GetElementScrollRight: function(element) { return element.scrollWidth - element.clientWidth - element.scrollLeft; },
 SetElementScrollRight: function(element, value) { 
  element.scrollLeft = element.scrollWidth - element.clientWidth - value; 
 },
 RequireHorizontalScrollCorrection: function() {
  return this.IsControlModeWithHorizontalScrolling() && !this.IsPostponeMode();
 },
 IsControlModeWithHorizontalScrolling: function() {
  return this.HasHorzScroll() && this.IsControlColumnResizeMode();
 },
 IsControlColumnResizeMode: function() { return this.control.columnResizeMode === ASPx.ColumnResizeMode.Control; },
 CorrectHorizontalScroll: function(delta) {
  var scrollPosition = this.IsRtl() ? this.GetScrollableDivScrollLeft() : this.GetScrollableDivScrollRight();
  if(scrollPosition === 0 && delta < 0) {
   var extraCell = this.GetScrollHelper().GetArmatureExtraCell(this.GetScrollHelper().GetContentTable());
   this.SetExtraCellsWidth(extraCell.offsetWidth + Math.abs(delta));
  } else if(this.IsRtl())
   this.SetScrollableDivScrollRight(this.initialScrollRight);
 },
 EnsureCellsHavePixelWidths: function() {
  var tables = this.GetAllTables();
  for(var i = 0; i < tables.length; i++) {
   var armCells = this.GetScrollHelper().GetArmatureCells(tables[i]); 
   for(var j = 0; j < armCells.length; j++) {
    var cell = armCells[j];
    if(ASPx.IsPercentageSize(cell.style.width))
     ASPx.SetStyles(cell, { width: cell.offsetWidth });
   }
  }
 },
 SetExtraCellsWidth: function(width) {
  var tables = this.GetAllTables();
  var extraCells = tables.map(function(table) { return this.GetScrollHelper().GetArmatureExtraCell(table); }.bind(this));
  for(var i = 0; i < extraCells.length; i++)
   ASPx.SetStyles(extraCells[i], { width : width }); 
 },
 ResetHorizontalScrollCorrection: function() {
  if(this.RequireHorizontalScrollCorrection()) {
   this.SetExtraCellsWidth("auto");
   this.initialScrollRight = null;
  }
 },
 CalculateResizingInfo: function(e) {
  var newX = Math.round(ASPx.Evt.GetEventX(e));
  var delta = newX - this.prevX;
  if(this.IsRtl())
   delta = -delta;
  var newWidth = this.GetCellRealWidth(this.colInfo.headerCell) + delta;
  var minWidth = this.CalculateColumnMinWidth(this.colInfo, newWidth);
  var maxWidth = this.colInfo.maxWidth;
  var nextColNewWidth = 0;
  var nextColMinWidth = 0;
  var nextColMaxWidth = Number.MAX_VALUE;
  if(this.IsNextColumnResizable()) {
   nextColNewWidth = this.GetCellRealWidth(this.nextColInfo.headerCell) - delta;
   nextColMinWidth = this.nextColInfo.minWidth > 0 ? this.nextColInfo.minWidth : this.defaultMinWidth;
   nextColMaxWidth = this.nextColInfo.maxWidth;
  }
  if(newWidth < minWidth || nextColNewWidth < nextColMinWidth || (maxWidth > 0 && newWidth > maxWidth) || (nextColMaxWidth > 0 && nextColNewWidth > nextColMaxWidth))
   return null;
  return {
   delta: delta,
   newX: newX,
   newWidth: newWidth,
   minWidth: minWidth,
   nextColNewWidth: nextColNewWidth,
   nextColMinWidth: nextColMinWidth
  };
 },
 CalculateColumnMinWidth: function(colInfo, newWidth) {
  var columnMinWidth = colInfo.minWidth > 0 ? colInfo.minWidth : this.defaultMinWidth;
  if(!this.controlMinWidth)
   return columnMinWidth;
  if(!this.calculatedMinWidth) {
   var controlWidth = this.control.GetMainElement().offsetWidth;
   this.calculatedMinWidth = Math.max(columnMinWidth, newWidth - controlWidth + this.controlMinWidth);
  }
  return this.calculatedMinWidth;
 },
 CalcControlMinWidth: function() {
  var mainElement = this.control.GetMainElement();
  var contentElements = this.GetAllTables();
  var scrollHelper = this.GetScrollHelper();
  if(scrollHelper)
   contentElements = contentElements.map(function(table) { return scrollHelper.GetScrollDiv(table); });
  var scrollableTreeLine = this.GetScrollableTreeLine(mainElement);
  var controlStyleWidth = mainElement.style.width;
  ASPx.SetStyles(mainElement, { width: 1 });
  contentElements.forEach(function(el) { ASPx.SetElementDisplay(el, false); });
  var controlMinWidth = mainElement.offsetWidth;
  contentElements.forEach(function(el) { ASPx.SetElementDisplay(el, true); });
  mainElement.style.width = controlStyleWidth;
  for(var i = 0; i < scrollableTreeLine.length; i++) {
   var node = scrollableTreeLine[i];
   if(node.isDocumentElement)
    ASPx.SetDocumentScrollTop(node.scrollTop);
   else
    node.element.scrollTop = node.scrollTop;
  }
  return controlMinWidth;
 },
 GetScrollableTreeLine: function(rootElement) {
  var treeLine = ASPx.GetElementTreeLine(rootElement, "BODY").map(function(el) { return { element: el, scrollTop: el.scrollTop }; });
  treeLine.push({ element: null, scrollTop: ASPx.GetDocumentScrollTop(), isDocumentElement: true });
  return treeLine.filter(function(node) { return node.scrollTop > 0; });
 },
 ApplyColumnWidth: function(columnIndex, width) {
  var cellIndex = this.GetArmatureCellIndex(columnIndex);
  this.ApplyCellWidth(this.GetHeaderTable(), cellIndex, width);
  this.ApplyCellWidth(this.GetContentTable(), cellIndex, width);
  if(this.NeedResizeFooterTable())
   this.ApplyCellWidth(this.GetFooterTable(), cellIndex, width);
 },
 ApplyCellWidth: function(table, cellIndex, width) {
  if(!table)
   return;
  this.GetArmatureCells(table)[cellIndex].style.width = width;
 },
 GetResizingBarWrapper: function() {
  return ASPx.CacheHelper.GetCachedElement(this, "postponeResizingBar", this.CreatePostponeResizingBar);
 },
 GetResizingOriginalBar:  function() { return ASPx.GetChildByClassName(this.GetResizingBarWrapper(), this.PostponeResizingOriginalBarClassName, 0); },
 GetResizingBarLabel: function() { return ASPx.GetChildByClassName(this.GetResizingBarWrapper(), this.PostponeResizingBarLabelClassName, 0); },
 CreatePostponeResizingBar: function() {
  var bar = ASPx.CreateHtmlElement("div", { display: "none" });
  ASPx.AddClassNameToElement(bar, this.PostponeResizingBarWrapperClassName);
  ASPx.AddClassNameToElement(bar, this.GetResizingBarThemedClassName());
  var originalBar = ASPx.CreateHtmlElement("div");
  ASPx.AddClassNameToElement(originalBar, this.PostponeResizingOriginalBarClassName);
  if(this.IsRtl())
   ASPx.AddClassNameToElement(originalBar, "rtl");
  var newBar = ASPx.CreateHtmlElement("div");
  ASPx.AddClassNameToElement(newBar, this.PostponeResizingNewBarClassName);
  var label = ASPx.CreateHtmlElement("div");
  ASPx.AddClassNameToElement(label, this.PostponeResizingBarLabelClassName);
  bar.appendChild(originalBar);
  bar.appendChild(newBar);
  bar.appendChild(label);
  ASPx.InsertElementAfter(bar, this.control.GetMainElement());
  return bar;
 },
 GetResizingBarThemedClassName: function() {
  var controlClassName = this.GetControlClassName();
  var controlClassNames = ASPx.GetClassNameList(this.control.GetMainElement());
  var themedClassName = controlClassNames.filter(function(className) { return className.indexOf(controlClassName > -1); }.aspxBind(this))[0];
  var theme = themedClassName.substr(controlClassName.length);
  return theme ? this.PostponeResizingBarWrapperClassName + theme : "";
 },
 GetFooterHeight: function() { return 0; },
 GetAllTables: function() { return [ this.GetHeaderTable(), this.GetContentTable(), this.GetFooterTable() ].filter(function(table) { return !!table; }); },
 GetControlClassName: function() { },
 IsNextColumnResizable: function() { },
 IsPostponeMode: function() { },
 GetColumnIndices: function() { },
 GetColumnIndexById: function(id) { },
 GetColumnMinWidth: function(columnIndex) { },
 GetColumnMaxWidth: function(columnIndex) { },
 GetHeaderCell: function(columnIndex) { },
 GetArmatureCellIndex: function(columnIndex) { },
 GetScrollHelper: function() { },
 OnResized: function(columnIndex) { },
 NeedResizeFooterTable: function() { },
 GetControlDimensions: function() { },
 SetControlDimensions: function(dimensions) { },
 GetColumnNeighbor: function(columnIndex, isLeft) {
  var indices = this.GetColumnIndices();
  var index = -1;
  for(var i = 0; i < indices.length; i++) {
   if(indices[i] === columnIndex) {
    index = isLeft ? i - 1 : i + 1;
    break;
   }
  }
  if(index < 0 || index >= indices.length)
   return -1;
  return indices[index];
 },
 IsLeftmostColumn: function(columnIndex) {
  return this.GetColumnIndices()[0] === columnIndex;
 },
 IsRightmostColumn: function(columnIndex) {
  var indices = this.GetColumnIndices();
  return indices[indices.length - 1] === columnIndex;
 },
 SaveControlDimensions: function(onlyControlWidth) {
  if(onlyControlWidth && this.GetControlDimensions())
   return;
  var state = { };
  var controlWidthPx = ASPx.GetElementOriginalWidth(this.control.GetMainElement());
  var controlWidth = ASPx.PxToInt(controlWidthPx);
  if(controlWidth > 0 && this.AllowStoreControlWidth())
   state["ctrlWidth"] = controlWidth;
  if(!onlyControlWidth)
   ASPx.Data.MergeHashTables(state, this.GetColumnWidths());
  this.SetControlDimensions(ASPx.Json.ToJson(state));
 },
 AllowStoreControlWidth: function() {
  return !this.control.widthValueSetInPercentage;
 },
 GetColumnWidths: function(){
  var state = { };
  var indices = this.GetColumnIndices();
  for(var i = 0; i < indices.length; i++) {
   var index = indices[i];
   state[index] = this.GetCellRealWidth(this.GetHeaderCell(index));
  }
  return state;
 },
 UpdateCursor: function(e, headerCell) {
  if(this.IsResizing() || this.CanStartResizing(e, headerCell))
   ASPx.Attr.ChangeStyleAttribute(headerCell, "cursor", "w-resize");
 },
 GetColumnInfoList: function() {
  var list = [ ];
  var indices = this.GetColumnIndices();
  for(var i = 0; i < indices.length; i++)
   list.push(this.GetColumnInfo(indices[i]));
  list.sort(function(i1, i2) { 
   var w1 = i1.minWidth;
   var w2 = i2.minWidth;
   if(w1 > w2)
    return 1;
   else if(w1 < w2)
    return -1;
   else
    return 0;
  });
  return list;
 },
 GetColumnInfo: function(columnIndex) {
  var headerCell = this.GetHeaderCell(columnIndex);
  if(!headerCell) return { };
  var armCell = this.GetArmatureCell(headerCell);
  return {
   index: columnIndex,
   headerCell: headerCell,
   armCell: armCell,
   minWidth: this.GetColumnMinWidth(columnIndex),
   maxWidth: this.GetColumnMaxWidth(columnIndex),
   pxWidth: this.GetStylePxWidth(armCell),
   widthRestrictionsAssigned: armCell.widthRestrictionsAssigned
  };
 },
 ValidateColumnWidths: function() {
  var columnInfoList = this.GetColumnInfoList();
  var validationRequired = false;
  for(var i = 0; i < columnInfoList.length; i++) {
   if(columnInfoList[i].minWidth > 0 || columnInfoList[i].maxWidth > 0) {
    validationRequired = true;
    break;
   }
  }
  if(!validationRequired)
   return;
  var totalColumnWidth = 0;
  var allColumnsHasWidth = true;
  for(var i = 0; i < columnInfoList.length && allColumnsHasWidth; i++) {
   var info = columnInfoList[i];
   allColumnsHasWidth &= info.pxWidth > 0;
   totalColumnWidth += info.pxWidth;
  }
  var mainElement = this.control.GetMainElement();
  var tablePxWidth = this.GetStylePxWidth(mainElement);
  if(allColumnsHasWidth && tablePxWidth > -1 && tablePxWidth <= totalColumnWidth)
   return;
  var processedList = [ ];
  for(var i = 0; i < columnInfoList.length; i++) {
   var info = columnInfoList[i];
   if((info.minWidth > 0 || info.maxWidth > 0) && (info.pxWidth <= 0 || info.widthRestrictionsAssigned))
    processedList.push(info);
  }
  var savedTableOffsetWidth = ASPx.GetElementOffsetWidth(mainElement);
  this.ValidateColumnWidthsCore(processedList);
  this.AdjustColumnsPercentageWidth();
  var needAdjustInnerControls = savedTableOffsetWidth !== ASPx.GetElementOffsetWidth(mainElement);
  if(this.HasVertScroll())
   this.GetScrollHelper().Update();
  else if(needAdjustInnerControls) 
   this.AdjustInnerControls();
 },
 ValidateColumnWidthsCore: function(columnInfoList) {
  for(var i = 0; i < columnInfoList.length; i++) {
   var info = columnInfoList[i];
   if(info.widthRestrictionsAssigned)
    info.widthRestrictionsAssigned = !this.TryRestoreColumnWidth(info);
   else
    info.widthRestrictionsAssigned = this.TryCorrectColumnWidth(info);
  }
  for(var i = 0; i < columnInfoList.length; i++) {
   var info = columnInfoList[i];
   if(!info.widthRestrictionsAssigned)
    this.TryCorrectColumnWidth(info);
  }
 },
 AdjustColumnsPercentageWidth: function() {
  var columnInfoList = this.GetColumnInfoList();
  var percentageColumnInfos = columnInfoList.filter(function(info) { return ASPx.IsPercentageSize(info.armCell.style.width); });
  if(percentageColumnInfos.length > 0) {
   var currentPercentageWidthSummary = 0;
   for(var i = 0; i < percentageColumnInfos.length; i++)
    currentPercentageWidthSummary += ASPx.PercentageToFloat(percentageColumnInfos[i].armCell.style.width);
   var accumulativePercentageSummary = 0;
   for(var i = 0; i < percentageColumnInfos.length; i++) {
    var width = 0;
    if(i == percentageColumnInfos.length - 1)
     width = 1 - accumulativePercentageSummary;
    else {
     width = ASPx.PercentageToFloat(percentageColumnInfos[i].armCell.style.width) / currentPercentageWidthSummary;
     accumulativePercentageSummary += width;
    }
    this.ApplyColumnWidth(percentageColumnInfos[i].index,width * 100 + "%");
   }
  }
 },
 TryRestoreColumnWidth: function(columnInfo) {
  var armCell = columnInfo.armCell;
  armCell.style.width = armCell.savedWidth;
  if(armCell.offsetWidth <= columnInfo.minWidth) {
   armCell.style.width = columnInfo.minWidth + "px";
   return false;
  }
  this.ApplyColumnWidth(columnInfo.index, armCell.savedWidth);
  armCell.widthRestrictionsAssigned = false;
  armCell.savedWidth = null;
  return true;
 },
 TryCorrectColumnWidth: function(columnInfo) {
  var armCell = columnInfo.armCell;
  var armCellWidth = armCell.offsetWidth;
  var maxWidth = columnInfo.maxWidth > 0 ? columnInfo.maxWidth : Number.MAX_VALUE;
  if(armCellWidth >= columnInfo.minWidth && armCellWidth <= maxWidth)
   return false;
  armCell.savedWidth = armCell.style.width;
  armCell.widthRestrictionsAssigned = true;
  var widthToApply = armCellWidth < columnInfo.minWidth ? columnInfo.minWidth : maxWidth;
  this.ApplyColumnWidth(columnInfo.index, widthToApply + "px");
  return true;
 },
 ResetStretchedColumnWidth: function() {
  if(this.HasHorzScroll())
   return;
  var columnIndex = this.FindStretchedColumn();
  if(columnIndex > -1)
   this.ApplyColumnWidth(columnIndex, "");
 },
 FindStretchedColumn: function() {
  var columnInfoList = this.GetColumnInfoList();
  if(columnInfoList.length == 0)
   return -1;
  for(var i = 0; i < columnInfoList.length; i++) {
   if(columnInfoList[i].pxWidth < 0)
    return -1;
  }
  var indices = this.GetColumnIndices();
  return indices[indices.length - 1];
 },
 GenerateRandomClassName: function() {
  return "dx" + Math.floor((Math.random() + 1) * 100000).toString(36);
 }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, function(e) {
 if(ASPx.tableColumnResizing != null && !(ASPx.Browser.WebKitTouchUI && ASPx.TouchUIHelper.isGesture)) {
  ASPx.tableColumnResizing.OnMouseMove(e);
  return true;
 }
});
ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, function(e) {
 if(ASPx.tableColumnResizing != null) {
  ASPx.tableColumnResizing.OnMouseUp(e);
  return true;
 }
});
ASPx.TableResizingHelperBase = TableResizingHelperBase;
})();

(function() {
var GridViewTableResizingHelper = ASPx.CreateClass(ASPx.TableResizingHelperBase, {
 constructor: function(tableHelper) {
  this.constructor.prototype.constructor.call(this, tableHelper);
 },
 IsNextColumnResizable: function() { 
  return this.control.columnResizeMode == ASPx.ColumnResizeMode.NextColumn;
 },
 IsPostponeMode: function() {
  return this.control.enablePostponeResizing;
 },
 GetFooterHeight: function() {
  var footer = this.control.GetFooterRow();
  if(footer)
   return footer.offsetHeight;
  return ASPx.TableResizingHelperBase.prototype.GetFooterHeight.call(this);
 },
 GetControlClassName: function() { return ASPx.GridViewConsts.ControlClassName; },
 IsRightmostColumn: function(columnIndex) {
  return !ASPx.IsExists(this.GetHeaderMatrix().GetRightNeighbor(columnIndex, true));
 },
 GetScrollHelper: function() { 
  return this.control.GetScrollHelper(); 
 },
 GetHeaderCell: function(columnIndex) { 
  return this.control.GetHeader(columnIndex); 
 },
 GetColumnHelper: function(){
  return this.control.GetColumnHelper();
 },
 GetHeaderMatrix: function(){
  return this.control.GetHeaderMatrix();
 },
 GetColumnIndices: function() { 
  return this.GetHeaderMatrix().GetLeafIndices(); 
 },
 GetColumnIndexById: function(id) { 
  return this.control.getColumnIndex(id); 
 },
 GetColumnMinWidth: function(columnIndex) {
  return this.control.GetColumn(columnIndex).minWidth;
 },
 GetColumnMaxWidth: function(columnIndex) {
  return this.control.GetColumn(columnIndex).maxWidth;
 },
 GetArmatureCellIndex: function(columnIndex) {
  return this.tableHelper.GetArmatureCellIndex(columnIndex);
 },
 GetColumnNeighbor: function(columnIndex, isLeft) {
  var matrix = this.GetHeaderMatrix();
  return matrix.GetLeaf(columnIndex, isLeft, true);
 },
 GetResizingColumnIndexCore: function(columnIndex, isLeft) {
  var matrix = this.GetHeaderMatrix();
  return matrix.GetLeaf(columnIndex, isLeft, isLeft);
 },
 NeedResizeFooterTable: function() {
  return !this.control.hasFooterRowTemplate;
 },
 OnResized: function(columnIndex) {
  var fixedGroupsHelper = this.control.GetFixedGroupsHelper();
  if(fixedGroupsHelper)
   fixedGroupsHelper.UpdateIntervalHeights();
  var fixedColumnHelper = this.control.GetFixedColumnsHelper();
  if(fixedColumnHelper)
   fixedColumnHelper.UpdateRowHeights(true);
  this.control.RaiseColumnResized(this.control.GetColumn(columnIndex));
 },
 GetControlDimensions: function() {
  return this.control.stateObject.resizingState;
 },
 SetControlDimensions: function(dimensions) {
  this.control.stateObject.resizingState = dimensions;
 },
 IsAdaptiveCollapsed: function() {
  var adaptivityHelper = this.control.GetAdaptivityHelper();
  if(adaptivityHelper)
   return !adaptivityHelper.IsResponsiveMode() && adaptivityHelper.HasAnyAdaptiveElement();
  return false;
 },
 CanStartResizing: function(e, headerCell) {
  if(this.IsAdaptiveCollapsed())
   return false;
  var dragHelper = this.control.GetDragHelper();
  return ASPx.TableResizingHelperBase.prototype.CanStartResizing.call(this, e, headerCell) && dragHelper.IsDataHeaderTarget(headerCell);
 },
 CanStartResizingCore: function(cellId, isLeftEdge, isRightEdge) {
  if(this.IsAdaptiveCollapsed())
   return false;
  var fixedColumnHelper = this.control.GetFixedColumnsHelper();
  if(fixedColumnHelper) {
   var columnIndex = this.GetColumnIndexById(cellId);
   var leftNeighborColumnIndex = this.GetColumnNeighbor(columnIndex, true);
   var leftNeighborCellIndex = this.GetColumnIndices().indexOf(leftNeighborColumnIndex);
   if(isLeftEdge && leftNeighborCellIndex < fixedColumnHelper.hiddenColumnCount + fixedColumnHelper.FixedColumnCount)
    return false;
  }
  return ASPx.TableResizingHelperBase.prototype.CanStartResizingCore.call(this, cellId, isLeftEdge, isRightEdge);
 },
 ResetStretchedColumnWidth: function() {
  if(this.IsAdaptiveCollapsed())
   return;
  ASPx.TableResizingHelperBase.prototype.ResetStretchedColumnWidth.call(this);
 },
 ValidateColumnWidths: function() {
  if(this.IsAdaptiveCollapsed())
   return;
  ASPx.TableResizingHelperBase.prototype.ValidateColumnWidths.call(this);
 },
 GetColumnWidths: function(){
  var leafWidths = ASPx.TableResizingHelperBase.prototype.GetColumnWidths.call(this);
  return this.GetColumnWidthsByLeafWidths(leafWidths);
 },
 GetColumnWidthsByLeafWidths: function(leafWidths){
  var columnWidths = ASPx.Data.MergeHashTables({ }, leafWidths);
  var layout = this.GetColumnHelper().GetHeaderLayout();
  for(var level = layout.length - 2; level >= 0; level--){
   var rowLayout = layout[level];
   for(var i = 0; i < rowLayout.length; i++){
    var node = rowLayout[i];
    if(columnWidths.hasOwnProperty(node.columnIndex)) continue;
    var columnWidth = 0;
    for(var j = 0; j < node.children.length; j++)
     columnWidth += columnWidths[node.children[j].columnIndex] || 0;
    columnWidths[node.columnIndex] = columnWidth;
   }
  }
  return columnWidths;
 },
 UpdateScrollControlsSize: function() {
  ASPx.TableResizingHelperBase.prototype.UpdateScrollControlsSize.call(this);
  var fixedColumnHelper = this.control.GetFixedColumnsHelper();
  if(fixedColumnHelper && this.IsHorzAutoScroll() && this.HasVertScroll() && this.IsControlColumnResizeMode())
   this.GetScrollHelper().Update();
 },
});
ASPx.GridViewTableResizingHelper = GridViewTableResizingHelper;
})();
(function() {
var Constants = {
 INFINITY_WIDTH: -1000,
 MAX_ITERATION_COUNT: 1000,
 WidthType: {
  AUTO: 0,
  FIXED: 1,
  PERCENTAGE: 2
 },
 SpecColumnIndex: {
  NON_PERCENT_SPACE: -1,
  INDENT: -2
 }
};
var GridViewColumnAdaptivityHelperBase = ASPx.CreateClass(null, {
 constructor: function() {
  this.calculationAdaptivityLocked = false;
 },
 IsCalculationLocked: function() {
  return this.calculationAdaptivityLocked;
 },
 LockCalculationAdaptivity: function() {
  this.calculationAdaptivityLocked = true;
 },
 UnlockCalculationAdaptivity: function() {
  this.calculationAdaptivityLocked = false;
 },
 OnBrowserWindowResize: function(e) {
  if(e && e.virtualKeyboardShownOnAndroid)
   this.LockCalculationAdaptivity();
  else
   this.UnlockCalculationAdaptivity();
 },
 CalculateAdaptivity: function(forceCalculate) {
  if(forceCalculate || !this.IsCalculationLocked())
   this.CalculateAdaptivityCore(forceCalculate);
  this.UnlockCalculationAdaptivity();
 },
 CalculateAdaptivityCore: function(forceCalculate) { }
});
var GridViewColumnAdaptivityHelper = ASPx.CreateClass(GridViewColumnAdaptivityHelperBase, {
 StyleSheetFocusedRowId: "StyleSheetFocusedRow",
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this);
  this.grid = grid;
  this.hasAdaptiveElements = false;
  this.hasAdaptiveGroupPanel = false;
  this.activeAdaptiveDetailVisibleIndex = null;
  this.allowOnlyOneAdaptiveDetailExpanded = false;
  this.adaptiveDetailColumnCount = -1;
  this.adaptivePagerEmptyRows = [ ];
  this.expandedAdaptiveDetailIndices = [ ];
  this.allowScrollToAdaptiveDetailOnExpand = true;
  this.calculator = this.CreateCalculator();
 },
 OnInitialize: function() {
  this.syncFocusedAdaptiveDetailsRowsForeColor();
 },
 OnAfterCallback: function() {
  this.syncFocusedAdaptiveDetailsRowsForeColor();
 },
 CalculateAdaptivityCore: function(forceCalculate) {
  var gridParentNode = this.grid.GetMainElement().parentNode;
  var gridParentNodeScrollInfo = ASPx.GetOuterScrollPosition(gridParentNode);
  this.calculator.CalculateAdaptivity(forceCalculate);
  ASPx.RestoreOuterScrollPosition(gridParentNodeScrollInfo);
 },
 IsResponsiveMode: function() { return this.grid.adaptivityMode === 1; },
 IsAdaptivityMode: function() { return this.grid.adaptivityMode === 2; },
 IsAdaptiveFormLayoutMode: function() { return this.IsAdaptivityMode() && this.HasAnyAdaptiveElement() && !!this.adaptiveLayoutColumnIndices; },
 GetAdaptiveLayoutColumnIndices: function() { return this.adaptiveLayoutColumnIndices; },
 GetAdaptiveLayoutColumnCount: function() {
  return this.IsAdaptiveFormLayoutMode() ? this.GetAdaptiveFormLayoutColCount() : this.GetAdaptiveDetailColumnCount();
 },
 CreateCalculator: function() {
 },
 GetMainElement: function() { return this.grid.GetMainElement(); },
 GetMainElementCell: function() {
  return this.GetLayoutHelper().GetMainElementCell();
 },
 GetMainTable: function() { return this.grid.GetMainTable(); },
 GetAllTables: function() {
  return this.GetLayoutHelper().GetAllTables();
 },
 HasAnyAdaptiveElement: function() { return this.hasAdaptiveElements; },
 GetColumn: function(columnIndex) { return this.grid.GetColumn(columnIndex); },
 GetColumnCount: function() { return this.grid.GetColumnCount(); },
 GetAdaptiveDataRow: function(visibleIndex) { return this.grid.GetAdaptiveDataRow(visibleIndex); },
 GetBandedAdaptiveDataRows: function(visibleIndex) { return this.grid.GetBandedAdaptiveDataRows(visibleIndex); },
 GetAdaptiveItems: function(visibleIndex) { return this.HasBandedDataRows() ? this.GetBandedAdaptiveDataRows(visibleIndex) : [this.GetAdaptiveDataRow(visibleIndex)]; },
 GetAdaptiveDetailRow: function(visibleIndex, forceCreate) { return this.grid.GetAdaptiveDetailRow(visibleIndex, forceCreate); },
 GetAdaptiveDetailCell: function(visibleIndex, forceCreate) { return this.grid.GetAdaptiveDetailCell(visibleIndex, forceCreate); },
 GetDataCell: function(visibleIndex, columnIndex) {
  var dataCell = this.grid.GetDataCell(visibleIndex, columnIndex);
  if(dataCell)
   return dataCell;
  if(this.grid.IsInlineEditMode())
   return this.grid.GetDataCellByRow(this.grid.GetEditingRow(), columnIndex, visibleIndex);
  return null;
 },
 GetAdaptiveHeaderContainer: function(columnIndex, adaptivePanel) { return this.grid.GetAdaptiveHeaderContainer(columnIndex, adaptivePanel); },
 GetHeader: function(columnIndex) { return this.grid.GetHeader(columnIndex); },
 GetGroupPanel: function() { return ASPx.GetNodesByPartialClassName(this.GetMainElement(), ASPx.GridViewConsts.GroupPanelCssClass)[0]; },
 GetAdaptiveGroupPanel: function() { return this.grid.GetAdaptiveGroupPanel(); },
 GetGroupPanelHeaders: function(panel) { return ASPx.GetNodesByPartialClassName(panel, ASPx.GridViewConsts.HeaderCellCssClass); },
 GetAdaptiveFooterPanel: function() { return this.grid.GetAdaptiveFooterPanel(); },
 GetVisibleColumnIndices: function() { return this.grid.GetColumnHelper().GetVisibleColumnIndices(true); },
 GetLeafColumnsIndices: function() { return this.grid.GetHeaderMatrix().GetLeafIndices(); },
 GetBatchEditHelper: function() { return this.grid.GetBatchEditHelper(); },
 GetToolbarHelper: function() { return this.grid.GetToolbarHelper(); },
 GetFixedGroupHelper: function() { return this.grid.GetFixedGroupsHelper(); },
 GetIndentColumnCount: function() { return this.grid.indentColumnCount; },
 GetAdaptiveDetailColumnCount: function() { return this.adaptiveDetailColumnCount; },
 GetAdaptiveFormLayoutColCount: function() { },
 GetLayoutHelper: function() { return this.grid.GetLayoutHelper(); },
 HasBandedDataRows: function() { return this.grid.HasBandedDataRows(); },
 ApplySettings: function(data) {
  this.allowOnlyOneAdaptiveDetailExpanded = data.allowOnlyOneAdaptiveDetailExpanded;
  this.adaptiveDetailColumnCount = data.adaptiveDetailColumnCount;
  this.calculator.ApplySettings(data);
 },
 GetVisibleRowsIndicesForAdaptivity: function() { return this.grid.GetVisibleRowsIndicesForAdaptivity(); },
 IsLeafColumn: function(columnIndex) { return ASPx.Data.ArrayContains(this.GetLeafColumnsIndices(), columnIndex); },
 IsColSpanReassignmentRequired: function(cell) {
  return cell && (cell.colSpan > 1 || cell.originalColSpan && cell.colSpan !== cell.originalColSpan);
 },
 GetAdaptiveColumnHeaderHideInfo: function(columnIndex) {
  var toHide = [ ];
  var toSpan = [ ];
  var leafIndices = this.GetLeafColumnsIndices();
  if(leafIndices.indexOf(columnIndex) > -1) {
   var column = this.GetColumn(columnIndex);
   while(column) {
    var headerCell = this.GetHeader(column.index, false);
    if(headerCell) {
     var isLeaf = leafIndices.indexOf(column.index) > -1;
     if(isLeaf || headerCell.colSpan === 1) {
      toHide.push(headerCell);
      if(headerCell.originalColSpan && headerCell.colSpan !== headerCell.originalColSpan)
       toSpan.push(headerCell);
     }
     else
      toSpan.push(headerCell);
    }
    column = this.GetColumn(column.parentIndex);
   }
  }
  return { toHide: toHide, toSpan: toSpan };
 },
 GetEmptyPagerRows: function() {
  if(this.adaptivePagerEmptyRows.length == 0)
   this.adaptivePagerEmptyRows = this.GetMainTable().getElementsByClassName(ASPx.GridViewConsts.EmptyPagerRowCssClass);
  return this.adaptivePagerEmptyRows;
 },
 ResetAdaptivityOnCallback: function() {
  this.ResetAdaptivity();
  this.activeAdaptiveDetailVisibleIndex = null;
 },
 ResetAdaptivity: function() {
  this.UpdateAdaptiveGroupPanelVisibility(false);
  this.RestoreAdaptiveDetails();
  this.UpdateAdaptivitySelector(true);
  this.UpdateAdaptiveToolbarsVisibility(false);
 },
 RestoreAdaptivityState: function(){
  for(var i = 0; i < this.expandedAdaptiveDetailIndices.length; i++) {
   var visibleIndex = this.expandedAdaptiveDetailIndices[i];
   if(!this.IsAdaptiveDetailsVisible(visibleIndex))
    this.ToggleAdaptiveDetails(visibleIndex, true);
  }
  this.grid.ApplyAdaptiveScrollTop();
  this.adaptivePagerEmptyRows = [ ];
 },
 HideAllAdaptiveColumns: function() {
 },
 IsAdaptiveDetailExpanded: function(visibleIndex) {
  return this.expandedAdaptiveDetailIndices.indexOf(visibleIndex) > -1;
 },
 IsAdaptiveDetailsVisible: function(visibleIndex){
  if(!this.HasAnyAdaptiveElement()) return false;
  var row = this.GetAdaptiveDetailRow(visibleIndex);
  return row && ASPx.GetElementDisplay(row);
 },
 UpdateAdaptivity: function() {
  this.UpdateAdaptiveGroupPanelVisibility(this.HasAnyAdaptiveElement() || this.hasAdaptiveGroupPanel);
  this.UpdateAdaptiveDetails();
  this.UpdateAdaptivitySelector();
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
  this.UpdateAdaptiveToolbarsVisibility(true);
 },
 ToggleAdaptiveDetails: function(visibleIndex, preventStoreIndices, fromUI) {
  if(!this.HasAnyAdaptiveElement()) return;
  if(!preventStoreIndices)
   ASPx.Data.ArrayRemove(this.expandedAdaptiveDetailIndices, visibleIndex);
  if(ASPx.IsExists(this.activeAdaptiveDetailVisibleIndex) && this.activeAdaptiveDetailVisibleIndex !== visibleIndex)
   this.UpdateRowAdaptiveDetails(this.activeAdaptiveDetailVisibleIndex, true);
  var newVisible = !this.IsAdaptiveDetailsVisible(visibleIndex);
  this.UpdateRowAdaptiveDetails(visibleIndex, true);
  this.UpdateDataRowBordersVisibility(visibleIndex, newVisible);
  if(newVisible && fromUI)
   this.MakeAdaptiveDetailsRowVisible(visibleIndex);
  if(this.allowOnlyOneAdaptiveDetailExpanded)
   this.activeAdaptiveDetailVisibleIndex = newVisible ? visibleIndex : null;
  if(!preventStoreIndices && newVisible) {
   if(this.allowOnlyOneAdaptiveDetailExpanded)
    this.expandedAdaptiveDetailIndices = [ ];
   this.expandedAdaptiveDetailIndices.push(visibleIndex);
  }
 },
 MakeAdaptiveDetailsRowVisible: function(visibleIndex) {
  if(!this.grid.HasVertScroll() || !this.allowScrollToAdaptiveDetailOnExpand) return;
  var adaptiveRow = this.GetAdaptiveDetailRow(visibleIndex);
  if(adaptiveRow)
   this.grid.GetScrollHelper().MakeRowVisible(adaptiveRow);
 },
 UpdateDataRowBordersVisibility: function(visibleIndex, visible){
  var dataRow = this.GetAdaptiveDataRow(visibleIndex);
  if(!dataRow) return;
  for(var i = 0; i < this.GetIndentColumnCount(); i++){
   var cell = dataRow.cells[i];
   if(ASPx.ElementHasCssClass(cell, ASPx.GridViewConsts.DetailIndentCellCssClass) ||
      ASPx.ElementHasCssClass(cell, ASPx.GridViewConsts.DetailButtonCellCssClass) ||
      ASPx.ElementHasCssClass(cell, ASPx.GridViewConsts.AdaptiveIndentCellCssClass))
    continue;
   ASPx.Attr.RestoreStyleAttribute(cell, "border-bottom-width");
   if(visible)
    ASPx.Attr.ChangeStyleAttribute(cell, "border-bottom-width", "0px");
  }
 },
 GetHideAdaptiveDetailButtonCore: function(row){
  var cell = ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
  return ASPx.GetChildByClassName(cell, ASPx.GridViewConsts.AdaptiveDetailHideButtonCssClass);
 },
 UpdateRowAdaptiveButtonsVisibility: function(visibleIndex, visible){
  var adaptiveRowButtons = this.GetShowAdaptiveDetailButtons(visibleIndex);
  var setRowButtonVisibility = function (btn) { if (btn) ASPx.SetElementDisplay(btn, !visible); };
  adaptiveRowButtons.forEach(setRowButtonVisibility);
  var detailRowButton = this.GetHideAdaptiveDetailButton(visibleIndex);
  if(detailRowButton) detailRowButton.style.display = visible ? "block" : "none";
 },
 GetShowAdaptiveDetailButtons: function(visibleIndex) {
  var rows = this.GetAdaptiveItems(visibleIndex);
  var containerCells = rows.map(function(row) { return ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass); });
  var buttons = containerCells.map(function(cell) { return ASPx.GetChildByClassName(cell, ASPx.GridViewConsts.AdaptiveDetailShowButtonCssClass); });
  return buttons.filter(function(b) { return !!b; });
 },
 GetHideAdaptiveDetailButton: function(visibleIndex) {
  var row = this.GetAdaptiveDetailRow(visibleIndex);
  var btn = this.GetHideAdaptiveDetailButtonCore(row);
  if(!btn){
   btn = this.GetHideAdaptiveDetailButtonCore(this.GetAdaptiveDataRow(visibleIndex));
   if(btn){
    var cell = ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
    cell.innerHTML = "";
    cell.appendChild(btn);
   }
  }
  return btn;
 },
 UpdateAdaptiveGroupPanelVisibility: function(show){
  var groupPanel = this.GetGroupPanel();
  var adaptiveGroupPanel = this.GetAdaptiveGroupPanel();
  if(!groupPanel || !adaptiveGroupPanel) return;
  var source = show ? groupPanel : adaptiveGroupPanel;
  var headers = this.GetGroupPanelHeaders(source);
  for(var i = 0; i < headers.length; i++){
   var header = headers[i];
   if(show) {
    var container = this.GetAdaptiveHeaderContainer(this.grid.getColumnIndex(header.id), adaptiveGroupPanel);
    header.savedNeighbor = header.nextSibling;
    ASPx.ChangeElementContainer(header, container);
   } else {
    var neighbor = header.savedNeighbor || this.grid.GetGroupPanel();
    neighbor.parentElement.insertBefore(header, neighbor);
     }
   header.adaptiveMoved = show;
  }
  this.grid.UpdateScrollableControls();
  ASPx.SetElementDisplay(groupPanel, !show);
  ASPx.SetElementDisplay(adaptiveGroupPanel, show);  
 },
 UpdateAdaptiveDetails: function(){
  var indices = this.GetVisibleRowsIndicesForAdaptivity();
  for(var i = 0; i < indices.length; i++) 
   this.UpdateRowAdaptiveDetails(indices[i]);
 },
 RestoreAdaptiveDetails: function(){
  var indices = this.GetVisibleRowsIndicesForAdaptivity();
  for(var i = 0; i < indices.length; i++) 
   this.RestoreRowAdaptiveDetails(indices[i]);
 },
 UpdateRowAdaptiveDetails: function(visibleIndex, changeVisible) {
  var rowHoverStateWasCleared = this.EnsureRowHotTrackHoverStateCleared(visibleIndex);
  var forceCreate = changeVisible || this.CanCreateRowAdaptiveDetailsOnUpdating();
  var row = this.GetAdaptiveDetailRow(visibleIndex, forceCreate);
  if(row) {
   if(this.CanCreateRowAdaptiveDetailsOnUpdating()) {
    ASPx.SetElementDisplay(row, true);
    this.grid.UpdateItemStyle(visibleIndex);
   }
   if(changeVisible) {
    var visible = !ASPx.GetElementDisplay(row);
    ASPx.SetElementDisplay(row, visible);
    this.UpdateRowAdaptiveButtonsVisibility(visibleIndex, visible);
    this.ReplaceBorderBottomWidthRules(visibleIndex, visible);
   }
   if(!this.HasAnyAdaptiveElement()){
    ASPx.SetElementDisplay(row, false);
    this.UpdateRowAdaptiveButtonsVisibility(visibleIndex, false);
    this.UpdateDataRowBordersVisibility(visibleIndex, false);
    this.activeAdaptiveDetailVisibleIndex = null;
    this.expandedAdaptiveDetailIndices = [ ];
   }
  }
  if(this.HasAnyAdaptiveElement()) {
   var cell = this.GetAdaptiveDetailCell(visibleIndex);
   if(cell) 
    this.CreateAdaptiveDetailsContent(cell, visibleIndex);
   this.UpdateDetailButton(visibleIndex, true);
  }
  if(rowHoverStateWasCleared)
   this.RestoreRowHotTrackHoverState(visibleIndex);
 },
 EnsureRowHotTrackHoverStateCleared: function (visibleIndex) {
  var rowHoverStateWasCleared = false;
  if(!this.grid.IsRowHotTrackEnabled())
   return rowHoverStateWasCleared;
  var dataRow = this.getDataRow(visibleIndex);
  var stateController = ASPx.GetStateController();
  if(stateController.GetCurrentHoverElement() === dataRow) {
   rowHoverStateWasCleared = true;
   stateController.SetCurrentHoverElement(null);
  }
  return rowHoverStateWasCleared;
 },
 RestoreRowHotTrackHoverState: function(visibleIndex) {
  var dataRow = this.getDataRow(visibleIndex);
  ASPx.GetStateController().SetCurrentHoverElement(dataRow);
 },
 CanCreateRowAdaptiveDetailsOnUpdating: function() {
  return false;
 },
 UpdateDetailButton: function(visibleIndex, moveFromDataRow) {
 },
 ReplaceBorderBottomWidthRules: function(visibleIndex, visible){
  if(!this.grid.IsLastDataRow(visibleIndex)) return;
  this.grid.UpdateFirstAndLastVisibleRowMarkers();
  var dataRow = this.getDataRow(visibleIndex);
  if(visible){
   var replaceBorderRules = false;
   for(var i = this.GetIndentColumnCount(); i < dataRow.cells.length; i++){
    var cell = dataRow.cells[i];
    if(cell.style.borderBottomWidth == "0px"){
     replaceBorderRules = true;
     ASPx.Attr.ChangeStyleAttribute(cell, "border-bottom-width", "");
    }
   }
   if(!replaceBorderRules) return;
   ASPx.Attr.ChangeStyleAttribute(this.GetAdaptiveDetailCell(visibleIndex), "border-bottom-width", "0px");
   var adaptiveDetailIndentCell = this.GetAdaptiveDetailIndentCell(visibleIndex);
   if(adaptiveDetailIndentCell)
    ASPx.Attr.ChangeStyleAttribute(adaptiveDetailIndentCell, "border-bottom-width", "0px");
  } else{
   var adaptiveDetailCell = this.GetAdaptiveDetailCell(visibleIndex);
   if(adaptiveDetailCell.style.borderBottomWidth != "0px") return;
   ASPx.Attr.RestoreStyleAttribute(adaptiveDetailCell, "border-bottom-width");
   var adaptiveDetailIndentCell = this.GetAdaptiveDetailIndentCell(visibleIndex);
   if(adaptiveDetailIndentCell)
    ASPx.Attr.RestoreStyleAttribute(adaptiveDetailIndentCell, "border-bottom-width");
   for(var i = this.GetIndentColumnCount(); i < dataRow.cells.length; i++){
    var cell = dataRow.cells[i];
    ASPx.Attr.RestoreStyleAttribute(cell, "border-bottom-width");
   }
  }
 },
 getDataRow: function(visibleIndex) {
  var dataRow = null;
  if(this.HasBandedDataRows()) {
   var bandedRows = this.GetBandedAdaptiveDataRows(visibleIndex);
   if(bandedRows.length)
    dataRow = bandedRows[bandedRows.length - 1];
  } else {
   dataRow = this.GetAdaptiveDataRow(visibleIndex);
  }
  return dataRow;
 },
 syncFocusedAdaptiveDetailsRowsForeColor: function() {
  var focusedItemStyle = this.grid.GetStyleHelper().GetFocusedItemStyle();
  if(!focusedItemStyle || !focusedItemStyle.cssText)
   return;
  var foreColor = ASPx.CreateHtmlElement("DIV", focusedItemStyle).style.color;
  if(!foreColor)
   return;
  var gridSelector = ["#", this.grid.name].join("");
  var dataCellSelector = [gridSelector, focusedItemStyle.className, ASPx.GridViewConsts.AdaptiveDetailDataCellCssClass].join(" .");
  var captionCellSelector = [gridSelector, focusedItemStyle.className, ASPx.GridViewConsts.AdaptiveDetailCaptionCellCssClass].join(" .");
  var selector = [dataCellSelector, captionCellSelector].join(",");
  var rules = [{
   selector: selector,
   cssText: ["color:", foreColor, ";"].join("")
  }];
  ASPx.GridDynamicStyleSheetHelper.Instance.Update(this.grid, this.StyleSheetFocusedRowId, rules);
 },
 GetAdaptiveDetailIndentCell: function(visibleIndex){
  var row = this.GetAdaptiveDetailRow(visibleIndex);
  return ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
 },
 RestoreRowAdaptiveDetails: function(visibleIndex){
  var cell = this.GetAdaptiveDetailCell(visibleIndex);
  if(cell) this.RestoreAdaptiveDetailsContent(cell, visibleIndex);
  this.UpdateDetailButton(visibleIndex, false);
 },
 CreateAdaptiveDetailsContent: function(parentElement, visibleIndex) {
  if(parentElement.childNodes.length > 0) return;
  var table = document.createElement("TABLE");
  parentElement.appendChild(table);
  table.className = ASPx.GridViewConsts.AdaptiveDetailTableCssClass;
  table.border = 0;
  table.cellPadding = 0;
  table.cellSpacing = 0;
  var tbody = document.createElement("TBODY");
  table.appendChild(tbody);
  var visibleIndices = this.GetVisibleColumnIndices();
  var columnCount = this.adaptiveDetailColumnCount, tr;
  for(var i = 0; i < visibleIndices.length; i++) {
   var column = this.GetColumn(visibleIndices[i]);
   if(!column || !column.adaptiveHidden) continue;
   if(columnCount == this.adaptiveDetailColumnCount) {
    tr = document.createElement("TR");
    tbody.appendChild(tr);
   }
   var dataColSpan = 1;
   var header = this.GetHeader(column.index);
   if(column.isCommandColumn) {
    if(!this.CommandColumnHasCaptionForAdaptiveSimpleContent(header)) 
     dataColSpan = 3 * this.adaptiveDetailColumnCount - 1;
    else {
     var titleText = header ? header.innerHTML : this.GetColumnCaption(column);
     this.CreateAdaptiveDetailsTitleCell(tr, titleText + ":");
    }
   }
   else {
    var textNode = this.GetHeaderCellTextNode(header);
    var titleText = header ? ASPx.GetInnerText(textNode) : this.GetColumnCaption(column);
    this.CreateAdaptiveDetailsTitleCell(tr, titleText + ":");
   }
   var dataCell = this.CreateAdaptiveDetailsDataCell(tr, column, dataColSpan);
   var renderedCellVisibleIndex = this.GetLayoutHelper().ResolveMergedCellVisibleIndex(visibleIndex, column.index); 
   var sampleDataCell;
   if(renderedCellVisibleIndex == visibleIndex){
    sampleDataCell = this.GetDataCell(visibleIndex, column.index);
    this.StoreAdaptiveDetailCell(parentElement, column.index, dataCell);
   } else {
    var storedCell = this.GetStoredAdaptiveDetailCell(column.index, renderedCellVisibleIndex);
    sampleDataCell = storedCell.cloneNode(true);
   }
   this.MoveChildrenToElement(sampleDataCell, dataCell);
   columnCount--;
   if(columnCount == 0 || column.isCommandColumn) 
    columnCount = this.adaptiveDetailColumnCount;
   else if(!column.isCommandColumn) {
    var spacerCell = document.createElement("TD");
    spacerCell.className = ASPx.GridViewConsts.AdaptiveDetailSpacerCellCssClass;
    tr.appendChild(spacerCell);
   }
   var helper = this.GetBatchEditHelper();
   if(helper) {
    helper.UpdateItem(this.grid.ConvertVisibleIndexToKey(visibleIndex), [ column.index ], false, false, false);
    helper.UpdateRecordInChangesPreview(visibleIndex);
    helper.ProcessValidationErrors(helper.GetValidationInfo());
   }
  }
 },
 MoveChildrenToElement: function(sourceElement, destinationElement) {
  if(this.grid.IsRowHotTrackEnabled())
   ASPx.GetStateController().ClearElementCacheInContainer(sourceElement);
  ASPx.MoveChildrenToElement(sourceElement, destinationElement);
 },
 CommandColumnHasCaptionForAdaptiveSimpleContent: function(header){
 },
 GetHeaderCellTextNode: function(headerCell) {
  if(this.grid.enableEllipsis) {
   var textContainer = ASPx.GetNodeByClassName(headerCell, ASPx.GridViewConsts.HeaderCellEllipsisContainerCssClass, 0);
   if(textContainer)
    headerCell = textContainer;
  }
  return ASPx.GetNodeByTagName(headerCell, "TD", 0) || headerCell;
 },
 GetColumnCaption: function (column) {
  return this.GetColumnCaptionProvider().GetColumnCaption(column.index);
 },
 GetColumnCaptionProvider: function () {
  return this.grid;
 },
 CreateAdaptiveDetailsDataCell: function(tr, column, dataColSpan){
  var dataCell = document.createElement("TD");
  dataCell.colSpan = dataColSpan;
  dataCell.className = (column.isCommandColumn ? ASPx.GridViewConsts.AdaptiveDetailCommandCellCssClass : ASPx.GridViewConsts.AdaptiveDetailDataCellCssClass);
  dataCell.columnIndex = column.index;
  tr.appendChild(dataCell);
  return dataCell;
 },
 CreateAdaptiveDetailsTitleCell: function(tr, captionHTML){
  var titleCell = document.createElement("TD");
  titleCell.className = ASPx.GridViewConsts.AdaptiveDetailCaptionCellCssClass;
  tr.appendChild(titleCell);
  titleCell.innerHTML = captionHTML;
  return titleCell;
 },
 GetStoredAdaptiveDetailCell: function(columnIndex, visibleIndex){
  var parentElement = this.GetAdaptiveDetailCell(visibleIndex);
  if(!parentElement || !parentElement.adaptiveDetailsCells)
   return null;
  return parentElement.adaptiveDetailsCells[columnIndex];
 },
 StoreAdaptiveDetailCell: function(parentElement, columnIndex, dataCell){
  if(!parentElement.adaptiveDetailsCells)
   parentElement.adaptiveDetailsCells = [];
  parentElement.adaptiveDetailsCells[columnIndex] = dataCell;
 },
 RestoreAdaptiveDetailsContent: function(parentElement, visibleIndex){
  for(var i = 0; i < this.GetColumnCount(); i++) {
   var column = this.GetColumn(i);
   if(!column || !parentElement.adaptiveDetailsCells || !parentElement.adaptiveDetailsCells[column.index]) continue;
   var dataCell = this.GetDataCell(visibleIndex, column.index);
   var storedDataCell = parentElement.adaptiveDetailsCells[column.index];
   if(storedDataCell)
    this.MoveChildrenToElement(storedDataCell, dataCell);
   parentElement.adaptiveDetailsCells[column.index] = null;
   if(this.GetBatchEditHelper())
    this.GetBatchEditHelper().UpdateItemByVI(visibleIndex, [ column.index ], false, false, false);
  }
  if(this.CanClearParentElementOnAdaptiveDetailsContentRestore()) 
   parentElement.innerHTML = "";
 },
 CanClearParentElementOnAdaptiveDetailsContentRestore: function() {
  return true;
 },
 UpdateAdaptivitySelector: function(reset) {
  var visible = this.HasAnyAdaptiveElement() && !reset;
  this.SetAdaptivitySelectorVisible(visible);
 },
 SetAdaptivitySelectorVisible: function(visible) {
  var cssClass = this.GetAdaptivitySelectorEnabledCssClass();
  if(visible) {
   ASPx.AddClassNameToElement(this.GetMainElement(), cssClass);
   ASPx.RemoveClassNameFromElement(this.GetMainElement(), ASPx.GridViewConsts.AdaptivityDisabledCssClass);
  }
  else {
   ASPx.RemoveClassNameFromElement(this.GetMainElement(), cssClass);
   ASPx.AddClassNameToElement(this.GetMainElement(), ASPx.GridViewConsts.AdaptivityDisabledCssClass);
  }
 },
 GetAdaptivitySelectorEnabledCssClass: function() {
 },
 GetFixedGroupPlaceholders: function() {
  var helper = this.GetFixedGroupHelper();
  return helper ? helper.GetPlaceholderCells() : null;
 },
 UpdateAdaptiveToolbarsVisibility: function(show) {
  var helper = this.GetToolbarHelper();
  helper.ForEachAdaptiveToolbar(function(toolbar) {
   if(!show)
    toolbar.CollapseControl();
   else if(toolbar.IsControlCollapsed()) {
    toolbar.ExpandControl();
    toolbar.AdjustControl(true);
   }
  });
 }
});
var GridViewResponsiveModeAdaptivityHelperBase = ASPx.CreateClass(GridViewColumnAdaptivityHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.adaptiveHiddenColumns = [ ];
 },
 CalculateAdaptivityCore: function(forceCalculate) {
  var savedAdaptiveState = this.HasAnyAdaptiveElement();
  GridViewColumnAdaptivityHelper.prototype.CalculateAdaptivityCore.call(this, forceCalculate);
  if(savedAdaptiveState !== this.HasAnyAdaptiveElement())
   this.ProcessDataCellsRightBorder();
 },
 ResetAdaptivity: function() {
  this.ShowAdaptiveColumns();
  GridViewColumnAdaptivityHelper.prototype.ResetAdaptivity.call(this);
 },
 CommandColumnHasCaptionForAdaptiveSimpleContent: function(header) {
  return !ASPx.GetChildByTagName(header, "TABLE"); 
 },
 GetAdaptivitySelectorEnabledCssClass: function() {
  return ASPx.GridViewConsts.AdaptivityEnabledCssClass;
 },
 GetAdaptiveIndent: function() {
 },
 GetLeftIndents: function() {
 },
 CollapseTables: function(tables) {
  var savedStyles = [];
  var cell = this.GetMainElementCell();
  var style = cell.style;
  var savedStyle = { display: style.display, width: style.width, height: style.height, overflow: style.overflow };
  savedStyles.push(savedStyle);
  ASPx.SetStyles(cell, { display: "block", width: "0px", height: "0px", overflow: "hidden" });
  if(this.grid.widthValueSetInPercentage) {
   var mainElement = this.grid.GetMainElement();
   savedStyle = { width: mainElement.style.width };
   mainElement.style.width = this.grid.percentSizeConfig.width;
   savedStyles.push(savedStyle);
  }
  for(var i = 0, table; table = tables[i]; i++) {
   savedStyle = {};
   var collapsedStyle = this.GetCollapsedTableStyle(table, savedStyle);
   savedStyles.push(savedStyle);
   ASPx.SetStyles(table, collapsedStyle);
  }
  this.SetAdaptivitySelectorVisible(true);
  return savedStyles;
 },
 GetCollapsedTableStyle: function(table, savedStyle) {
  savedStyle.width = table.style.width;
  return { width: "1px" };
 },
 ExpandTables: function(tables, savedStyles) {
  var cell = this.GetMainElementCell();
  ASPx.SetStyles(cell, savedStyles[0]);
  var offset = 1;
  if(this.grid.widthValueSetInPercentage) {
   this.grid.GetMainElement().style.width = savedStyles[1].width;
   offset++;
  }
  for(var i = 0, table; table = tables[i]; i++)
   ASPx.SetStyles(table, savedStyles[i + offset]);
 },
 TryGetColumnIndex: function(cell) {
  var rowId = cell.parentNode.id;
  if(rowId.indexOf(ASPx.GridViewConsts.DataRowID) > 0)
   return this.grid.GetColumnIndexByDataCell(cell);
  if(rowId.indexOf(ASPx.GridViewConsts.HeaderRowID) > 0)
   return this.grid.GetColumnIndexByHeaderCell(cell);
  if(rowId.indexOf(ASPx.GridViewConsts.FooterRowID) > 0)
   return this.GetColumnIndexByFooterCell(cell);
  return -1;
 },
 GetColumnIndexByFooterCell: function(cell) {
  if(this.GetLayoutHelper().GetHasFooterRowTemplate())
   return -1;
  var cellIndex = cell.cellIndex;
  var row = cell.parentNode;
  for(var c, i = 0; c = row.cells[i]; i++) {
   if(c == cell) break;
   if(c.colSpan > 1)
    cellIndex += c.colSpan - 1;
  }
  return this.grid.GetLayoutHelper().GetColumnIndex(cellIndex, -1, -1);
 },
 IncreaseCellColSpan: function(cell) {
  if(cell && cell.originalColSpan) {
   if(!cell.decreaseSkipped)
    cell.colSpan++;
   else
    cell.decreaseSkipped = false;
  }
 },
 DecreaseCellColSpan: function(cell){
  if(!cell) return;
  if(!cell.originalColSpan)
   cell.originalColSpan = cell.colSpan;
  if(cell.colSpan > 1)
   this.DecreaseCellColSpanInternal(cell);
  else
   cell.decreaseSkipped = true;
 },
 DecreaseCellColSpanInternal: function(cell) {
  var isSpannedCell = this.grid.GetLayoutHelper().IsSpannedCell(cell);
  if(!isSpannedCell)
   this.DecreaseCellColSpanCore(cell);
  else
   this.DecreaseSpannedCellColSpan(cell);
 },
 DecreaseSpannedCellColSpan: function(cell) {
  var spannedFirstDecreaseSkipped = cell.spannedFirstDecreaseSkipped;
  if(spannedFirstDecreaseSkipped)
   this.DecreaseCellColSpanCore(cell);
  else
   cell.spannedFirstDecreaseSkipped = true;
 },
 DecreaseCellColSpanCore: function(cell) {
  cell.colSpan = cell.colSpan - 1;
 },
 RestoreCellColSpan: function(cell) {
  if(!cell || !cell.originalColSpan)
   return;
  cell.colSpan = cell.originalColSpan;
  if(cell.spannedFirstDecreaseSkipped)
   cell.spannedFirstDecreaseSkipped = false;
 },
 ForEachCell: function(table, method, context){
  context = context || this;
  var shouldBreak = false;
  for(var i = 0; i < table.rows.length; i++){
   for(var j = 0; j < table.rows[i].cells.length; j++){
    var cell = table.rows[i].cells[j];
    shouldBreak = method.call(context, cell);
    if(shouldBreak)
     break;
   }
   if(shouldBreak)
    break;
  }
 },
 GetAdaptiveColumnsOrder: function() {
  return this.grid.adaptiveColumnsOrder;
 },
 ShowAdaptiveColumns: function(){
  this.adaptiveHiddenColumns = [];
  for(var i = 0; i < this.GetAdaptiveColumnsOrder().length; i++)
   this.UpdateAdaptiveColumnVisibility(this.GetAdaptiveColumnsOrder()[i], true);
  this.hasAdaptiveElements = false;
 },
 ShowNextAdaptiveColumn: function() {
  if(this.adaptiveHiddenColumns.length === 0)
   return false;
  var columnIndex = this.adaptiveHiddenColumns.pop();
  this.UpdateAdaptiveColumnVisibility(columnIndex, true);
  this.hasAdaptiveElements = this.adaptiveHiddenColumns.length !== 0;
  this.UpdateAdaptivitySelector();
  return true;
 },
 HideAdaptiveColumns: function(columnsToHide) {
  if(columnsToHide.length === 0)
   return;
  for(var i = 0; i < columnsToHide.length; i++)
   this.UpdateAdaptiveColumnVisibility(columnsToHide[i], false);
  this.hasAdaptiveElements = true;
 },
 HideAllAdaptiveColumns: function() {
  var columnWasHidden = false;
  do {
   columnWasHidden = this.HideNextAdaptiveColumn();
  } while(columnWasHidden);
 },
 HideNextAdaptiveColumn: function() {
  var columnIndex = this.GetNextAdaptiveColumnIndex();
  if(columnIndex === -1)
   return false;
  this.UpdateAdaptiveColumnVisibility(columnIndex, false);
  this.hasAdaptiveElements = true;
  this.UpdateAdaptivitySelector();
  return true;
 },
 GetNextAdaptiveColumnIndex: function() {
  for(var i = 0; i < this.GetAdaptiveColumnsOrder().length - 1; i++) {
   var columnIndex = this.GetAdaptiveColumnsOrder()[i];
   var column = this.GetColumn(columnIndex);
   if(column.adaptiveHidden) continue;
   if(ASPx.Data.ArrayIndexOf(this.GetVisibleColumnIndices(), columnIndex) == -1) continue;
   return columnIndex;
  }
  return -1;
 },
 UpdateAdaptiveColumnVisibility: function(columnIndex, visible) {
  var elementsToHide = this.GetElementsToHide(columnIndex);
  var visibilityChanged = false;
  for(var i = 0; i < elementsToHide.length; i++) {
   visibilityChanged |= ASPx.ElementHasCssClass(elementsToHide[i], ASPx.GridViewConsts.AdaptiveHiddenCssClass) === visible;
   var action = visible ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
   action(elementsToHide[i], ASPx.GridViewConsts.AdaptiveHiddenCssClass);
   this.grid.ChangeCellInitialClass(elementsToHide[i], ASPx.GridViewConsts.AdaptiveHiddenCssClass, !visible);
  }
  var elementsToSpan = this.GetElementsToSpan(columnIndex);
  if(visibilityChanged) {
   for(var i = 0; i < elementsToSpan.length; i++) {
    if(visible) {
     this.IncreaseCellColSpan(elementsToSpan[i]);
    }
    else {
     this.DecreaseCellColSpan(elementsToSpan[i]);
    }
   }
  }
  this.GetColumn(columnIndex).adaptiveHidden = !visible;
  if(visible)
   ASPx.Data.ArrayRemove(this.adaptiveHiddenColumns, columnIndex);
  else
   this.adaptiveHiddenColumns.push(columnIndex);
 },
 GetElementsToHide: function(columnIndex) {
  var result = [
   this.grid.GetFilterCell(columnIndex),
   this.grid.GetFooterCell(columnIndex)
  ].concat(
   this.grid.GetArmatureCells(columnIndex),
   this.grid.GetDataTableAccessibilityHeaderCells(columnIndex),
   this.GetAdaptiveColumnHeaderHideInfo(columnIndex).toHide
  );
  if(this.grid.IsInlineEditMode())
   result.push(this.grid.GetEditingCell(columnIndex));
  var visibleIndices = this.GetVisibleRowsIndicesForAdaptivity();
  for(var i = 0; i < visibleIndices.length; i++) {
   var visibleIndex = visibleIndices[i];
   result.push(this.GetDataCell(visibleIndex, columnIndex));
  }
  var groupFooterVisibleIndices = this.grid.GetGroupFooterVisibleIndices();
  for(var i = 0; i < groupFooterVisibleIndices.length; i++) {
   var visibleIndex = groupFooterVisibleIndices[i];
   result.push(this.GetLayoutHelper().GetGroupFooterCell(visibleIndex, columnIndex));
  }
  var emptyPagerRows = this.GetEmptyPagerRows();
  for(var i = 0; i < emptyPagerRows.length; i++)
   result.push(emptyPagerRows[i].cells[this.grid.GetDataCellIndex(columnIndex)]);
  return result.filter(function(element) {
   return element !== null;
  });
 },
 GetElementsToSpan: function(columnIndex) {
  var result = [
   this.grid.GetEditingErrorCell(),
   this.grid.GetEditFormTableCell(),
   this.grid.GetEmptyDataItemCell()
  ].concat(
   this.GetAdaptiveColumnHeaderHideInfo(columnIndex).toSpan
  ).concat(
   this.GetFixedGroupPlaceholders()
  );
  if(this.IsLeafColumn(columnIndex))
   result.push(this.grid.GetSampleAdaptiveDetailCell());
  var batchEditHelperOwner = this.grid.GetBatchEditHelperOwner();
  result = result.concat(this.grid.GetBatchEditPreviewChangesGroupCells());
  var visibleIndices = this.GetVisibleRowsIndicesForAdaptivity();
  var parentCellsColumnIndices = this.grid.GetColumnHelper().GetParentColumnIndices(columnIndex);
  for(var i = 0; i < visibleIndices.length; i++) {
   var visibleIndex = visibleIndices[i];
   result.push(this.grid.GetGroupCell(visibleIndex));
   result.push(this.grid.GetPreviewCell(visibleIndex));
   result.push(this.grid.GetDetailCell(visibleIndex));
   if(this.IsLeafColumn(columnIndex))
    result.push(this.GetAdaptiveDetailCell(visibleIndex));
   if(batchEditHelperOwner) {
    var errorRow = batchEditHelperOwner.GetRecordErrorByVI(visibleIndex);
    result.push(this.grid.GetEditingErrorCell(errorRow));
   }
   var parentCells = this.GetParentDataCells(parentCellsColumnIndices, visibleIndex);
   var cellsToSpan = parentCells.filter(this.IsColSpanReassignmentRequired.aspxBind(this));
   result = result.concat(cellsToSpan);
  }
  return result;
 },
 GetParentDataCells: function(parentCellsColumnIndices, visibleIndex) {
  return parentCellsColumnIndices.map(function(index) {
   return this.GetDataCell(visibleIndex, index);
  }.bind(this));
 },
 ProcessDataCellsRightBorder: function() {
  var layoutHelper = this.GetLayoutHelper();
  var columnHelper = this.grid.GetColumnHelper();
  var columnIndices = columnHelper.GetVisibleColumnIndices().filter(function(i) { return columnHelper.IsColumnInRightTreeLine(i); });
  var visibleIndices = this.GetVisibleRowsIndicesForAdaptivity();
  var lastColumnIndex = columnIndices[columnIndices.length - 1];
  var rightSideDataCells = visibleIndices.map(function(i) { return layoutHelper.GetCell(i, lastColumnIndex, ASPx.GridViewRowType.Data); });
  var adaptiveIndentCells = visibleIndices.map(function(i) { return ASPx.GetNodeByClassName(this.GetAdaptiveDataRow(i), ASPx.GridViewConsts.AdaptiveIndentCellCssClass); }.bind(this));
  if(layoutHelper.GetShowColumnHeaders()) {
   var rightSideHeaderCells = columnIndices.map(function(i) { return layoutHelper.GetHeaderCell(i); });
   var headerAdaptiveIndentCells = layoutHelper.GetHeaderRows().map(function(row) { return ASPx.GetNodeByClassName(row, ASPx.GridViewConsts.AdaptiveIndentCellCssClass); });
   rightSideDataCells = [ ].concat(rightSideDataCells, rightSideHeaderCells);
   adaptiveIndentCells = [ ].concat(adaptiveIndentCells, headerAdaptiveIndentCells);
  }
  var hasRightBorderAtDataCell = this.HasAnyAdaptiveElement();
  var dataCellAction = hasRightBorderAtDataCell ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
  var adaptiveIndentAction = hasRightBorderAtDataCell ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
  rightSideDataCells.forEach(function(cell) { dataCellAction(cell, ASPx.GridViewConsts.RemoveRightBorderClassName); });
  adaptiveIndentCells.forEach(function(cell) { adaptiveIndentAction(cell, ASPx.GridViewConsts.RemoveRightBorderClassName); });
 }
});
var GridViewAutoTableLayoutAdaptivityHelper = ASPx.CreateClass(GridViewResponsiveModeAdaptivityHelperBase, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
 },
 CreateCalculator: function() {
  return new GridViewAutoTableLayoutAdaptivityCalculator(this);
 },
 GetLeftIndents: function() {
  return [];
 },
 GetAdaptiveIndent: function() {
  var startVisibleIndex = this.grid.GetTopVisibleIndex();
  var rows = this.GetAdaptiveItems(startVisibleIndex);
  if(rows.length === 0)
   return null;
  return ASPx.GetNodeByClassName(rows[0], ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
 },
 CollapseTables: function(tables) {
  var savedStyles = GridViewResponsiveModeAdaptivityHelperBase.prototype.CollapseTables.call(this, tables);
  this.EnsureDetailRowsAdaptiveButtonWidth();
  return savedStyles;
 },
 EnsureDetailRowsAdaptiveButtonWidth: function() {
  var table = this.GetMainTable();
  if(table.detailButtonsEnsured)
   return;
  var width = -1;
  var indices = this.GetVisibleRowsIndicesForAdaptivity();
  for(var i = 0; i < indices.length; i++) { 
   var adaptiveRowButtons = this.GetShowAdaptiveDetailButtons(indices[i]);
   if(adaptiveRowButtons.length > 0) {
    var button = adaptiveRowButtons[0];
    var offsetWidth = button.offsetWidth;
    if(offsetWidth > 0) {
     width = offsetWidth + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(button.parentNode);
     break;
    }
   }
  }
  var strut = null; 
  for(var i = 0; i < indices.length; i++) {
   var detailRow = this.grid.GetDetailRow(indices[i]);
   var indentCell = ASPx.GetChildByClassName(detailRow, ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
   if(!indentCell) continue;
   if(!strut) {
    width -= ASPx.GetLeftRightBordersAndPaddingsSummaryValue(indentCell);
    strut = ASPx.CreateHtmlElement("DIV", { width: width, height: 1, visibility: "hidden" });
   }
   indentCell.appendChild(strut.cloneNode());
  }
  table.detailButtonsEnsured = true;
 }
});
var GridViewFixedTableLayoutAdaptivityHelper = ASPx.CreateClass(GridViewResponsiveModeAdaptivityHelperBase, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
 },
 CreateCalculator: function() {
  return new GridViewFixedTableLayoutAdaptivityCalculator(this);
 },
 GetLeftIndents: function() {
  return Array.prototype.slice.call(this.GetMainTable().rows[0].querySelectorAll("." + this.grid.GetTableHelper().GridGroupIndentClassName + ", ." + this.grid.GetTableHelper().GridDetailIndentClassName + ":not(." + ASPx.GridViewConsts.AdaptiveIndentCellCssClass + ")"));
 },
 GetAdaptiveIndent: function() {
  var mainTable = this.GetMainTable();
  return this.GetArmRowAdaptiveIndent(mainTable);
 },
 GetArmRowAdaptiveIndent: function(table) {
  return ASPx.GetNodeByClassName(table.rows[0], ASPx.GridViewConsts.AdaptiveIndentCellCssClass);
 },
 PrepareForCalculation: function(tables) {
  for(var i = 0, table; table = tables[i]; i++) {
   this.HideCellsWithColSpan(table);
   this.ChangeAdaptiveIndentColumnWidth(table);  
  }
 },
 RestoreAfterCalculation: function(tables) {
  for(var i = 0, table; table = tables[i]; i++) {
   this.RestoreAdaptiveIndentColumnWidth(table);  
   this.RestoreCellsVisibility(table);
  }
 },
 HideCellsWithColSpan: function(table) {
  this.ForEachCell(table, 
   function(cell) { 
    if(cell.colSpan > 1 && this.CanHideCellWithColSpan(cell))
     ASPx.Attr.ChangeStyleAttribute(cell, "display", "none");
   });
 },
 CanHideCellWithColSpan: function(cell) {
  return !ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.HeaderCellCssClass) &&
    (this.GetLayoutHelper().GetHasFooterRowTemplate() || !ASPx.ElementContainsCssClass(cell.parentNode, ASPx.GridViewConsts.FooterRowClass));
 },
 RestoreCellsVisibility: function(table){
  this.ForEachCell(table, 
   function(cell) { 
    ASPx.Attr.RestoreStyleAttribute(cell, "display"); 
   });
 },
 ChangeAdaptiveIndentColumnWidth: function(table) { 
  if(!ASPx.Browser.Edge && !ASPx.Browser.Firefox)
   return;
  var adaptiveIndent = this.GetArmRowAdaptiveIndent(table);
  if(!adaptiveIndent || !ASPx.GetElementDisplay(adaptiveIndent))
   return;
  var isVisibleColumnsHasPercentageWidth = true;
  var columnIndices = this.GetVisibleColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   if(this.GetColumn(columnIndex).adaptiveHidden)
    continue;
   var armCell = this.grid.GetArmatureCells(columnIndex)[0];
   isVisibleColumnsHasPercentageWidth &= ASPx.IsPercentageSize(armCell.style.width);
  }
  if(isVisibleColumnsHasPercentageWidth) {
   this.savedAdaptiveIndentWidth = adaptiveIndent.style.width;
   adaptiveIndent.style.width = "1%";
  }
 },
 RestoreAdaptiveIndentColumnWidth: function(table) {
  if(!ASPx.IsExists(this.savedAdaptiveIndentWidth))
   return;
  var adaptiveIndent = this.GetArmRowAdaptiveIndent(table);
  adaptiveIndent.style.width = this.savedAdaptiveIndentWidth;
  delete this.savedAdaptiveIndentWidth;
 },
 CollapseTables: function(tables) {
  var savedStyles = GridViewResponsiveModeAdaptivityHelperBase.prototype.CollapseTables.call(this, tables);
  this.GetMainElement().style.maxWidth = "";
  return savedStyles;
 },
 GetCollapsedTableStyle: function(table, savedStyle) {
  var collapsedStyle = GridViewResponsiveModeAdaptivityHelperBase.prototype.GetCollapsedTableStyle.call(this, table, savedStyle);
  if(this.GetColumnAdjustor().ShouldAdjustColumns())
   this.GetColumnAdjustor().RestoreTableRenderColumnWidths(table);
  return collapsedStyle;
 },
 GetColumnAdjustor: function () {
  return this.grid.GetColumnAdjustor();
 }
});
var GridViewAdaptiveModeAdaptivityHelper = ASPx.CreateClass(GridViewColumnAdaptivityHelper, {
 constructor: function(grid) {
  this.constructor.prototype.constructor.call(this, grid);
  this.adaptiveLayoutColumnIndices = null;
  this.adaptiveFormlayoutColCount = undefined;
  this.hasAdaptiveDetailsFormLayout = null;
 },
 CreateCalculator: function() {
  return new GridViewAdaptiveModeCalculator(this);
 },
 ResetAdaptivity: function() {
  this.UpdateAdaptiveViewVisibility(false);
  GridViewColumnAdaptivityHelper.prototype.ResetAdaptivity.call(this);
 },
 CanClearParentElementOnAdaptiveDetailsContentRestore: function() {
  return !this.hasAdaptiveDetailsFormLayout;
 },
 ApplySettings: function(data) {
  GridViewColumnAdaptivityHelper.prototype.ApplySettings.call(this, data);
  this.adaptiveLayoutColumnIndices = data.adaptiveLayoutColumnIndices;
  this.adaptiveFormlayoutColCount = 1; 
 },
 GetAdaptiveFormLayoutColCount: function() { return this.adaptiveFormlayoutColCount; },
 CanCreateRowAdaptiveDetailsOnUpdating: function() {
  return this.HasAnyAdaptiveElement();
 },
 UpdateDetailButton: function(visibleIndex, moveFromDataRow) {
  var source = this.grid.GetDetailButtonCell(visibleIndex, !moveFromDataRow);
  var target = this.grid.GetDetailButtonCell(visibleIndex, moveFromDataRow);
  if(source && target)
   ASPx.MoveChildrenToElement(source, target);
 },
 GetAdaptivitySelectorEnabledCssClass: function() {
  return ASPx.GridViewConsts.AdaptivityWithLimitEnabledCssClass;
 },
 UpdateAdaptiveViewVisibility: function(visible) {
  this.UpdateDataRowsVisibility(!visible);
  this.UpdateHeaderPanelVisibility(visible);
  this.UpdateFilterRowVisibility(!visible);
  this.UpdateAdaptiveFoorerPanelVisibility(visible);
 },
 UpdateDataRowsVisibility: function(visible) {
  var indices = this.GetVisibleRowsIndicesForAdaptivity();
  var classNameAction = visible ? ASPx.RemoveClassNameFromElement : ASPx.AddClassNameToElement;
  var changeRowVisibility = function(row) { classNameAction(row, ASPx.GridViewConsts.AdaptiveHiddenCssClass); };
  for(var i = 0; i < indices.length; i++) {
   var index = indices[i];
   var rows = this.GetAdaptiveItems(index);
   rows.forEach(changeRowVisibility);
  }
  for(var i = 0; i < this.GetColumnCount(); i++)
   this.GetColumn(i).adaptiveHidden = !visible;
  this.hasAdaptiveElements = !visible;
 },
 UpdateHeaderPanelVisibility: function(visible) {
  if(visible)
   this.ShowAdaptiveHeaderPanel();
  else
   this.HideAdaptiveHeaderPanel();
 },
 UpdateFilterRowVisibility: function(visible) {
  ASPx.SetElementDisplay(this.grid.GetFilterRow(), visible);
 },
 HideAdaptiveHeaderPanel: function(){
  var adaptivePanel = this.GetAdaptiveHeaderPanel();
  if(adaptivePanel){
   this.MoveHeadersToHeaderRow();
   this.RestoreAdaptiveHeadersHeight();
   ASPx.SetElementDisplay(adaptivePanel, false);
   this.UpdateHeaderRowsVisibility(true);
   }
 },
 ShowAdaptiveHeaderPanel: function(){
  var adaptivePanel = this.GetAdaptiveHeaderPanel();
  if(adaptivePanel){
   this.MoveHeadersToAdaptivePanel();
   ASPx.SetElementDisplay(adaptivePanel, true);
   this.CorrectAdaptiveHeadersHeight();
   this.UpdateHeaderRowsVisibility(false);
  }
 },
 UpdateAdaptiveFoorerPanelVisibility: function(visible){
  ASPx.SetElementDisplay(this.GetAdaptiveFooterPanel(), visible);
  var footerElement = this.grid.GetFooterScrollContainer() || this.grid.GetFooterRow();
  ASPx.SetElementDisplay(footerElement, !visible);
 },
 UpdateHeaderRowsVisibility: function(visible){
  if(!this.grid.showColumnHeaders) 
   return;
  var headerScroll = this.grid.GetHeaderScrollContainer();
  if(headerScroll) {
   ASPx.SetElementDisplay(headerScroll, visible);
   return;
  }
  var headerRowCount = Math.max(this.grid.GetHeaderMatrix().GetRowCount(), 1);
  for(var i = 0; i < headerRowCount; i++) 
   ASPx.SetElementDisplay(this.grid.GetHeaderRow(i), visible);
 },
 GetVisibleHeaderCells: function(){
  var result = [];
  var indices = this.GetVisibleColumnIndices();
  for(var i = 0; i < indices.length; i++){
   var headerCell = this.GetHeader(indices[i]);
   if(headerCell)
    result.push(headerCell);
  }
  return result;
 },
 MoveHeadersToHeaderRow: function(){
  ASPx.Data.ForEach(this.GetVisibleHeaderCells(), function(headerCell){
   this.MoveHeaderToHeaderRow(headerCell);
  }.aspxBind(this));
 },
 MoveHeadersToAdaptivePanel: function(){
  this.SaveHeadersPositionInfo();
  ASPx.Data.ForEach(this.GetVisibleHeaderCells(), function(headerCell){
   this.MoveHeaderToAdaptiveHeaderPanel(headerCell);
  }.aspxBind(this));
 },
 SaveHeadersPositionInfo: function(){
  ASPx.Data.ForEach(this.GetVisibleHeaderCells(), function(headerCell){
   headerCell.savedCellIndex = headerCell.cellIndex;
   headerCell.savedHeaderRow = headerCell.parentElement;
  }.aspxBind(this));
 },
 MoveHeaderToHeaderRow: function(headerCell){
  if(headerCell.savedHeaderRow && headerCell.adaptiveMoved){
   var headerRow = headerCell.savedHeaderRow;
   if(headerCell.savedCellIndex >= 0 && headerCell.savedCellIndex < headerRow.cells.length)
    headerRow.insertBefore(headerCell, headerRow.cells[headerCell.savedCellIndex]);   
   else
    headerRow.appendChild(headerCell);
   ASPx.Attr.RestoreStyleAttribute(headerCell, "width");
   headerCell.adaptiveMoved = false;
  }
 },
 MoveHeaderToAdaptiveHeaderPanel: function(headerCell){
  var container = this.GetAdaptiveHeaderContainer(this.grid.getColumnIndex(headerCell.id), this.GetAdaptiveHeaderPanel());
  ASPx.ChangeElementContainer(headerCell, container);
  ASPx.Attr.ChangeStyleAttribute(headerCell, "width", "");
  headerCell.adaptiveMoved = true;
 },
 CorrectAdaptiveHeadersHeight: function(){
  var cells = this.GetVisibleHeaderCells();
  var maxHeight = 0;
  for(var i = 0; i < cells.length; i++){
   var headerContentHeight = cells[i].clientHeight - ASPx.GetTopBottomPaddings(cells[i]);
   if(maxHeight < headerContentHeight) 
    maxHeight = headerContentHeight;
  }
  for(var i = 0; i < cells.length; i++){
   ASPx.Attr.ChangeStyleAttribute(cells[i], "height", maxHeight + "px");
  }
 },
 RestoreAdaptiveHeadersHeight: function(){
  ASPx.Data.ForEach(this.GetVisibleHeaderCells(), function(headerCell){
   ASPx.Attr.RestoreStyleAttribute(headerCell, "height");
  }.aspxBind(this));
 },
 CreateAdaptiveDetailsContent: function(parentElement, visibleIndex) {
  this.CheckAdaptiveDetailsFormLayout(parentElement);
  if(this.hasAdaptiveDetailsFormLayout)
   this.CreateAdaptiveDetailsFormLayoutContent(parentElement, visibleIndex);
  else
   GridViewColumnAdaptivityHelper.prototype.CreateAdaptiveDetailsContent.call(this, parentElement, visibleIndex);
 },
 CheckAdaptiveDetailsFormLayout: function(parentElement) {
  if(this.hasAdaptiveDetailsFormLayout !== null) return;
  this.hasAdaptiveDetailsFormLayout = this.GetAdaptiveDetailsFormLayout(parentElement) != null;
 },
 GetAdaptiveDetailsFormLayout: function(parentElement) {
  var formLayoutElement = this.GetAdaptiveDetailsFormLayoutElement(parentElement);
  return formLayoutElement ? ASPx.GetControlCollection().Get(formLayoutElement.id) : null;
 },
 GetAdaptiveDetailsFormLayoutElement: function(parentElement) {
  if(!ASPx.FormLayoutConsts) return null;
  return ASPx.GetChildByPartialClassName(parentElement,  ASPx.FormLayoutConsts.FORM_LAYOUT_PARTIAL_CLASS_NAME);
 },
 CreateAdaptiveDetailsFormLayoutContent: function(parentElement, visibleIndex){
  this.CreateAdaptiveDetailsFormLayoutClientObject(parentElement, visibleIndex);
  for(var i = 0; i < this.GetColumnCount(); i++) {
   var column = this.GetColumn(i);
   if(!column || !column.adaptiveHidden) continue;
   var sampleDataCell = this.GetDataCell(visibleIndex, column.index);
   var dataCell = ASPx.GetNodeByClassName(parentElement, ASPx.GridViewConsts.AdaptiveDetailLayoutItemContentCssClass + column.index);
   if(dataCell) {
    if(ASPx.Data.ArrayIndexOf(this.GetVisibleColumnIndices(), column.index) > -1) {
     dataCell.innerHTML = "";
     this.MoveChildrenToElement(sampleDataCell, dataCell);
     this.UpdateAdaptiveDetailsFormLayoutNestedControl(dataCell, visibleIndex);
     dataCell.columnIndex = column.index;
     this.StoreAdaptiveDetailCell(parentElement, column.index, dataCell);
    }
    else{
     var itemElement = this.GetAdaptiveDetailsFormLayoutItemElement(dataCell);
     if(itemElement.tagName === "TABLE")
      itemElement.style.visibility = "hidden";
     else
      itemElement.style.display = "none";
    }
   }
   if(this.GetBatchEditHelper())
    this.GetBatchEditHelper().UpdateItemByVI(visibleIndex, [ column.index ], false, false, false);
  }
 },
 GetAdaptiveDetailsFormLayoutItemElement: function(dataCell) {
  return ASPx.GetParent(dataCell, function(el) { return !!el.id; });
 },
 UpdateAdaptiveDetailsFormLayoutNestedControl: function(dataCell, visibleIndex){
  var itemElement = ASPx.GetParentByPartialClassName(dataCell, ASPx.FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
  if(itemElement) ASPxClientFormLayout.UpdateNestedControlTypeClassName(itemElement, this.grid.IsEditingItem(visibleIndex));
 },
 CreateAdaptiveDetailsFormLayoutClientObject: function(parentElement, visibleIndex){
  if(parentElement.formLayout) return;
  var sampleFormLayout = this.GetAdaptiveDetailsFormLayout(parentElement);
  if(sampleFormLayout) {
   var formLayoutName = sampleFormLayout.name + visibleIndex;
   this.GetAdaptiveDetailsFormLayoutElement(parentElement).id = formLayoutName;
   var formLayout = new ASPxClientFormLayout(formLayoutName);
   formLayout.adaptivityMode = sampleFormLayout.adaptivityMode;
   formLayout.switchToSingleColumnAtWindowInnerWidth = sampleFormLayout.switchToSingleColumnAtWindowInnerWidth;
   formLayout.alignItemCaptionsInAllGroups = sampleFormLayout.alignItemCaptionsInAllGroups;
   formLayout.leftAndRightCaptionsWidth = sampleFormLayout.leftAndRightCaptionsWidth;
   formLayout.showItemCaptionColon = sampleFormLayout.showItemCaptionColon;
   formLayout.AfterCreate();
   formLayout.Initialize();
   formLayout.AfterInitialize();
   formLayout.AdjustControl(true);
   parentElement.formLayout = formLayout;
  }
 },
 GetAdaptiveHeaderPanel: function() { return this.grid.GetAdaptiveHeaderPanel(); }
});
var GridViewColumnAdaptivityCalculatorBase = ASPx.CreateClass(null, {
 constructor: function(layoutHelper) {
  this.grid = layoutHelper.grid;
  this.forceRecalculateAdaptivity = false;
  this.layout = layoutHelper;
 },
 CalculateAdaptivity: function(forceCalculate) {
  if(!forceCalculate && !this.RequireRecalculateAdaptivity())
   return;
  this.layout.ResetAdaptivity();
  this.CalculateAdaptivityCore();
  this.layout.UpdateAdaptivity();
 },
 ApplySettings: function(data) {
 },
 RequireRecalculateAdaptivity: function() {
  return !this.grid.isInitialized || this.forceRecalculateAdaptivity;
 },
 CalculateAdaptivityCore: function() {
 }
});
var GridViewResponsiveModeCalculatorBase = ASPx.CreateClass(GridViewColumnAdaptivityCalculatorBase, {
 constructor: function(layoutHelper) {
  this.constructor.prototype.constructor.call(this, layoutHelper);
  this.gridWidth = -1;
  this.containerWidth = 0;
  this.allowTextTruncationInAdaptiveMode = null;
  this.sizes = [];
  this.calcResultInfo = null;
  this.containerWidth = 0;
  this.bordersWidth = 0;
  this.adaptiveColumnWidth = 0;
  this.leftIndentsWidth = 0;
  this.groupPanelWidth = 0;
  this.utils = this.CreateCalculationUtils();
 },
 CalculateAdaptivity: function(forceCalculate) {
  if(this.ShouldHideAllAdaptiveColumns())
   this.layout.HideAllAdaptiveColumns();
  else
   GridViewColumnAdaptivityCalculatorBase.prototype.CalculateAdaptivity.call(this, forceCalculate);
 },
 RequireRecalculateAdaptivity: function() {
  if(GridViewColumnAdaptivityCalculatorBase.prototype.RequireRecalculateAdaptivity.call(this))
   return true;
  return !this.grid.isInsideHierarchyAdjustment || this.GridWidthChanged();
 },
 CalculateAdaptivityCore: function() {
  var tables = this.layout.GetAllTables();
  this.GetGridViewAdjuster().SaveDocumentScrollPosition();
  this.CalculateAdaptivityInternal(tables);
  this.GetGridViewAdjuster().RestoreDocumentScrollPosition();
 },
 ApplySettings: function(data) {
  this.allowTextTruncationInAdaptiveMode = data.allowTextTruncationInAdaptiveMode;
  GridViewColumnAdaptivityCalculatorBase.prototype.ApplySettings.call(this, data);
 },
 CalculateAdaptivityInternal: function(tables) {
  var savedStyles = this.layout.CollapseTables(tables);
  this.ReadSizes(tables);
  this.CalculateColumns();
  this.layout.ExpandTables(tables, savedStyles);
 },
 ReadSizes: function(tables) {
  var mainTable = this.layout.GetMainTable(),
   mainElement = this.layout.GetMainElement(),
   adaptiveIndent = this.layout.GetAdaptiveIndent();
  this.leftIndentsWidth = this.layout.GetLeftIndents()
             .reduce(function(accumulator, element) {
                return accumulator + element.scrollWidth + ASPx.GetHorizontalBordersWidth(element);
             }, 0);
  var groupPanel = this.layout.GetGroupPanel();
  var groupPanelTable = ASPx.GetChildByTagName(groupPanel, "TABLE");
  if(groupPanel && groupPanelTable) {
   this.groupPanelWidth = groupPanelTable.scrollWidth + groupPanel.scrollWidth;
  }
  this.containerWidth = mainElement.offsetWidth;
  this.bordersWidth = ASPx.GetHorizontalBordersWidth(mainElement) + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainTable);
  this.adaptiveColumnWidth = adaptiveIndent ? (adaptiveIndent.scrollWidth + ASPx.GetHorizontalBordersWidth(adaptiveIndent)) : 0;
  this.sizes = this.GetColumnSizes(tables);
 },
 CalculateColumns: function() {
  this.calcResultInfo = this.CalculateColumnsToBeHidden();
  this.layout.HideAdaptiveColumns(this.calcResultInfo.columnsToHide);
  if(this.calcResultInfo.columnsToHide.length === 0) {
   if(this.groupPanelWidth > this.containerWidth) {
    this.layout.hasAdaptiveGroupPanel = true;
   }
  }
 },
 CalculateColumnsToBeHidden: function() {
 },
 GetColumnSizes: function(tables) {
 },
 GetColumns: function() {
  return this.grid.columns;
 },
 GetDataCellIndex: function(columnIndex) {
  return this.grid.GetDataCellIndex(columnIndex);
 },
 AllowTextTruncationInAdaptiveMode: function(columnIndex) {
  return this.allowTextTruncationInAdaptiveMode[columnIndex];
 },
 CreateCalculationUtils: function() {
  return new GridViewColumnAdaptivityCalculationUtils(this);
 },
 ShouldHideAllAdaptiveColumns: function() {
  return GetGridViewAdaptivityAdjuster().CheckNeedCollapseDetailGrid(this.grid);
 },
 GridWidthChanged: function() {
  var result = false;
  if(this.IsWidthValueSetInPercentage()) {
   var containerWidth = this.grid.percentSizeConfig.markerWidth;
   result = containerWidth !== this.containerWidth;
   this.containerWidth = containerWidth;
  }
  if(!result) {
   var gridWidth = this.layout.GetMainElement().clientWidth;
   result = this.gridWidth !== gridWidth;
   this.gridWidth = gridWidth;
  }
  return result;
 },
 GetGridViewAdjuster: function() {
  return ASPx.GetGridViewAdjuster();
 },
 IsWidthValueSetInPercentage: function() {
  return this.grid.widthValueSetInPercentage;
 }
});
var GridViewAutoTableLayoutAdaptivityCalculator = ASPx.CreateClass(GridViewResponsiveModeCalculatorBase, {
 constructor: function(layoutHelper) {
  this.constructor.prototype.constructor.call(this, layoutHelper);
  this.parentNodeClientWidth = 0;
 },
 CalculateColumnsToBeHidden: function() {
  return this.utils.Auto_CalculateColumnsToBeHidden(this.sizes, this.containerWidth, this.bordersWidth, this.adaptiveColumnWidth, this.leftIndentsWidth);
 },
 GetColumnSizes: function(tables) {
  var sizes = this.GetDataColumnSizes(tables);
  var dataColumnSummaryWidth = this.utils.Auto_GetGridWidth(sizes);
  var restWidth = 0;
  for(var i = 0, table; table = tables[i]; i++) {
   var tableRestWidth = table.clientWidth - dataColumnSummaryWidth;
   if(restWidth < tableRestWidth)
    restWidth = tableRestWidth;
  }
  var indent = this.layout.GetAdaptiveIndent();
  if(indent)
   restWidth -= indent.offsetWidth;
  if(restWidth > 0) {
   var info = {
    index: -3, 
    width: restWidth
   };
   sizes.push(info);
  }
  return sizes;
 },
 GetDataColumnSizes: function(tables) {
  var sizes = [];
  var columns = this.GetColumns();
  for(var i = 0, table; table = tables[i]; i++) {
   if(table.rows.length === 0)
    continue;
   var row = table.rows[0];
   for(var j = 0, column; column = columns[j]; j++) {
    if(!column.visible)
     continue;
    var cellIndex = this.GetDataCellIndex(j);
    if(cellIndex === -1)
     continue;
    var cell = row.cells[cellIndex];
    if(!cell)
     continue;
    var width = cell.offsetWidth;
    var info = {
     index: j,
     width: width
    };
    sizes.push(info);
   }
  }
  return sizes;
 },
 ReadSizes: function(tables) {
  this.parentNodeClientWidth = this.GetParentNodeClientWidth();
  GridViewResponsiveModeCalculatorBase.prototype.ReadSizes.call(this, tables);
 },
 CalculateAdaptivityInternal: function(tables) {
  GridViewResponsiveModeCalculatorBase.prototype.CalculateAdaptivityInternal.call(this, tables);
  if(!this.IsWidthValueSetInPercentage() || this.calcResultInfo.overflow)
   return;
  var parentNodeNewClientWidth = this.GetParentNodeClientWidth();
  if(parentNodeNewClientWidth < this.parentNodeClientWidth) {
   this.layout.ShowAdaptiveColumns();
   var diff = this.parentNodeClientWidth - parentNodeNewClientWidth;
   var percWidthStr = this.GetGridPercentWidthValue();
   var percWidth = ASPx.PercentageToFloat(percWidthStr);
   var containerWidthDiff = percWidth * diff;
   this.containerWidth -= containerWidthDiff;
   this.CalculateColumns();
  }
  this.parentNodeClientWidth = parentNodeNewClientWidth;
 },
 GetGridPercentWidthValue: function() {
  return this.grid.percentSizeConfig.width;
 },
 GetParentNodeClientWidth: function() {
  return this.layout.GetMainElement().parentNode.clientWidth;
 }
});
var GridViewFixedTableLayoutAdaptivityCalculator = ASPx.CreateClass(GridViewResponsiveModeCalculatorBase, {
 constructor: function(layoutHelper) {
  this.constructor.prototype.constructor.call(this, layoutHelper);
  this.allowHideDataCellsByColumnMinWidth = false;
 },
 CalculateAdaptivity: function(forceCalculate) {
  GridViewResponsiveModeCalculatorBase.prototype.CalculateAdaptivity.call(this, forceCalculate);
  if(this.ShouldEnsureAdaptivityBestFit()) {
   var tables = this.layout.GetAllTables();
   this.EnsureAdaptivityBestFit(tables);
  }
 },
 CalculateAdaptivityInternal: function(tables) {
  this.layout.PrepareForCalculation(tables);
  GridViewResponsiveModeCalculatorBase.prototype.CalculateAdaptivityInternal.call(this, tables);
  this.layout.RestoreAfterCalculation(tables);
 },
 ShouldEnsureAdaptivityBestFit: function() {
  return !this.GetColumnAdjustor().HasRestrictions();
 },
 EnsureAdaptivityBestFit: function(tables) {
  var canShowColumns = true,
   canHideColumns = true;
  do {
   if(this.IsColumnsContentCut(tables)) {
    canShowColumns = false;
    if(!this.layout.HideNextAdaptiveColumn())
     canHideColumns = false;
   }
   else {
    canHideColumns = false;
    if(canShowColumns && !this.layout.ShowNextAdaptiveColumn())
     canShowColumns = false;
   }
  } while(canHideColumns || canShowColumns);
 },
 IsColumnsContentCut: function(tables) {
  if(this.GetGridOffsetWidth() > this.containerWidth)
   return true;
  for(var i = 0, table; table = tables[i]; i++) {
   if(this.IsColumnsContentCutCore(table))
    return true;
  }
  return false;
 },
 IsColumnsContentCutCore: function(table) {
  var result = false;
  this.layout.ForEachCell(table, function(cell) { 
   if(!this.NeedCheckCellContentCut(cell)) return;
   if(cell.colSpan == 1 && cell.offsetWidth < cell.scrollWidth) {
    result = true;
    return true;
   }
  }, this);
  return result;
 },
 NeedCheckCellContentCut: function(cell){
  if(ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.AdaptiveHiddenCssClass) || 
   (ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.HeaderCellCssClass) && cell.cellIndex < this.layout.GetIndentColumnCount()) || 
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.CommandColumnCellCssClass) ||
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.InlineEditCellCssClass) ||
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.DetailCellCssClass) ||
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.DetailButtonCellCssClass) ||
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.AdaptiveIndentCellCssClass) ||
   ASPx.ElementContainsCssClass(cell, ASPx.GridViewConsts.IndentCellCssClass) ||
   ASPx.ElementContainsCssClass(cell.parentNode, ASPx.GridViewConsts.GroupRowCssClass)) return false;
  var columnIndex = this.layout.TryGetColumnIndex(cell);
  if(columnIndex > -1 && (this.allowTextTruncationInAdaptiveMode[columnIndex] || this.layout.GetColumn(columnIndex).isCommandColumn))
   return false;
  return true;
 },
 GetGridOffsetWidth: function() {
  return this.layout.GetMainElement().offsetWidth;
 },
 CalculateColumnsToBeHidden: function() {
  var resultInfo = this.utils.Fixed_CalculateColumnsToBeHidden(this.sizes, this.containerWidth, this.bordersWidth, this.adaptiveColumnWidth, this.leftIndentsWidth);
  if(resultInfo.columnsToHide.length === this.sizes.length)
   resultInfo.columnsToHide.pop();
  return resultInfo;
 },
 GetColumnSizes: function(tables) {
  var minContentWidths = this.GetColumnMinContentWidths(tables);
  var sizes = [];
  var armRow = this.layout.GetMainTable().rows[0];
  var columnInfos = this.GetColumnAdjustor().columnInfos;
  for(var columnInfo, i = 0; columnInfo = columnInfos[i]; i++) {
   var cellIndex = this.GetDataCellIndex(columnInfo.column.index);
   var armCell = armRow.cells[cellIndex];
   var ignoreContentWidth = this.ShouldIgnoreColumnContentWidth(columnInfo.column);
   var minContentWidth = 0;
   if(columnInfo.hasFixedWidth || !ignoreContentWidth) {
    minContentWidth = this.allowHideDataCellsByColumnMinWidth && columnInfo.minWidth > 0
     ? columnInfo.minWidth : (minContentWidths[i] || 0);
   }
   var isAlwaysCut = columnInfo.hasFixedWidth && !ignoreContentWidth && armCell.offsetWidth < minContentWidth;
   var info = ASPx.CloneObject(columnInfo);
   info.minContentWidth = minContentWidth;
   info.isAlwaysCut = isAlwaysCut;
   info.violation = null;
   sizes.push(info);
  }
  return sizes;
 },
 GetColumnMinContentWidths: function(tables) {
  var result = { };
  for(var i = 0, table; table = tables[i]; i++)
   this.ReadColumnMinContentWidths(table, result);
  return result;
 },
 ReadColumnMinContentWidths: function(table, widthsObj) {
  this.layout.ForEachCell(table, function(cell) {
   if(!this.NeedCheckCellContentCut(cell))
    return;
   if(cell.colSpan !== 1)
    return;
   var columnIndex = this.layout.TryGetColumnIndex(cell);
   if(columnIndex === -1)
    return;
   var maxWidth = widthsObj[columnIndex] || 0;
   var width = cell.scrollWidth + ASPx.GetHorizontalBordersWidth(cell);
   if(maxWidth < width)
    widthsObj[columnIndex] = width;
  }, this);
 },
 ShouldIgnoreColumnContentWidth: function(column) {  
  return column.isCommandColumn || this.AllowTextTruncationInAdaptiveMode(column.index);
 },
 CalculateColumns: function() {
  GridViewResponsiveModeCalculatorBase.prototype.CalculateColumns.call(this);
  if(this.GetColumnAdjustor().ShouldAdjustColumns()) {
   var displayedColumnInfos = this.GetColumnAdjustor().columnInfos;
   if(this.calcResultInfo.columnsToHide.length > 0) {
    displayedColumnInfos = displayedColumnInfos.filter(function(c) { return !c.column.adaptiveHidden; });
    var indentInfo = this.utils.Fixed_CreateIndentSizeInfo(this.adaptiveColumnWidth + this.leftIndentsWidth);
    displayedColumnInfos.push(indentInfo);
   }
   var gridInnerWidth = this.containerWidth - this.bordersWidth;   
   this.GetColumnAdjustor().AdjustColumnsCore(displayedColumnInfos, gridInnerWidth);
  }
 },
 ReadSizes: function(tables) {
  GridViewResponsiveModeCalculatorBase.prototype.ReadSizes.call(this, tables);
  if(this.grid.HasVertScroll())
   this.bordersWidth += this.grid.GetScrollHelper().GetScrollContainerPadding();
 },
 ApplySettings: function(data) {
  this.allowHideDataCellsByColumnMinWidth = data.allowHideDataCellsByColumnMinWidth;
  GridViewResponsiveModeCalculatorBase.prototype.ApplySettings.call(this, data);
 },
 GetColumnAdjustor: function() {
  return this.grid.GetColumnAdjustor();
 }
});
var GridViewAdaptiveModeCalculator = ASPx.CreateClass(GridViewColumnAdaptivityCalculatorBase, {
 constructor: function(layoutHelper) {
  this.constructor.prototype.constructor.call(this, layoutHelper);
  this.shouldHideDataCellsByWindowInnerWidth = undefined;
  this.hideDataCellsWindowInnerWidth = -1;
 },
 CalculateAdaptivity: function(forceCalculate) {
  this.ResetShouldHideDataCellsByWindowInnerWidth();
  GridViewColumnAdaptivityCalculatorBase.prototype.CalculateAdaptivity.call(this, forceCalculate);
 },
 RequireRecalculateAdaptivity: function() {
  if(GridViewColumnAdaptivityCalculatorBase.prototype.RequireRecalculateAdaptivity.call(this))
   return true;
  return this.layout.HasAnyAdaptiveElement() !== this.GetShouldHideDataCellsByWindowInnerWidth();
 },
 CalculateAdaptivityCore: function() {
  if(this.GetShouldHideDataCellsByWindowInnerWidth())
   this.layout.UpdateAdaptiveViewVisibility(true);
 },
 ApplySettings: function(data) {
  this.hideDataCellsWindowInnerWidth = data.hideDataCellsWindowInnerWidth;
  GridViewColumnAdaptivityCalculatorBase.prototype.ApplySettings.call(this, data);
 },
 ResetShouldHideDataCellsByWindowInnerWidth: function() {
  this.shouldHideDataCellsByWindowInnerWidth = undefined;
 },
 GetShouldHideDataCellsByWindowInnerWidth: function() {
  if(this.shouldHideDataCellsByWindowInnerWidth === undefined)
   this.shouldHideDataCellsByWindowInnerWidth = this.hideDataCellsWindowInnerWidth > 0 && ASPx.GetCurrentDocumentWidth() <= this.hideDataCellsWindowInnerWidth;
  return this.shouldHideDataCellsByWindowInnerWidth;
 }
});
var GridViewColumnAdaptivityCalculationUtils = ASPx.CreateClass(null, {
 constructor: function(helper) {
  this.helper = helper;
  this.layout = helper.layout;
 },
 Auto_CalculateColumnsToBeHidden: function(sizes, containerWidth, bordersWidth, adaptiveColumnIndentWidth, leftIndentsWidth) {
  return this.CalculateColumnsToBeHiddenCore(
   this.Auto_GetGridWidth.aspxBind(this),
   this.Auto_CreateIndentSizeInfo.aspxBind(this),
   this.Auto_HasAnyAlwaysCutColumn.aspxBind(this),
   sizes, containerWidth, bordersWidth, adaptiveColumnIndentWidth, leftIndentsWidth);
 },
 Auto_CreateIndentSizeInfo: function(indentWidth) {
  return {
   index: Constants.SpecColumnIndex.INDENT,
   width: indentWidth
  };
 },
 Auto_GetGridWidth: function(sizes) {
  var result = 0;
  for(var i = 0, info; info = sizes[i]; i++)
   result += info.width;
  return result;
 },
 Auto_HasAnyAlwaysCutColumn: function(sizes) {
  return false;
 },
 Fixed_CalculateColumnsToBeHidden: function(sizes, containerWidth, bordersWidth, adaptiveColumnIndentWidth, leftIndentsWidth) {
  return this.CalculateColumnsToBeHiddenCore(
   this.Fixed_GetCompleteResolvedGridMinWidth.aspxBind(this),
   this.Fixed_CreateIndentSizeInfo.aspxBind(this),
   this.Fixed_HasAnyAlwaysCutColumn.aspxBind(this),
   sizes, containerWidth, bordersWidth, adaptiveColumnIndentWidth, leftIndentsWidth, true);
 },
 Fixed_GetCompleteResolvedGridMinWidth: function(sizes) {
  var adjustor = this.Fixed_GetColumnAdjustor();
  if(!adjustor.HasValidColumnWidths() || !adjustor.CheckHasRestrictions(sizes))
   return this.Fixed_GetGridMinWidthInfo(sizes).gridWidth;
  this.Fixed_GetColumnAdjustor().ResetColumnViolations(sizes);
  var violation = null;
  var minWidthInfo = null;
  var counter = 0;
  do {
   var resolvedColumnInfos = this.Fixed_GetResolvedColumnInfos(sizes);
   var minWidthInfo = this.Fixed_GetGridMinWidthInfo(resolvedColumnInfos);
   violation = this.Fixed_GetColumnAdjustor().GetWidthViolation(minWidthInfo.widthInfos);
   if(violation)
    this.Fixed_GetColumnAdjustor().ResolveViolation(violation);
   if(++counter > Constants.MAX_ITERATION_COUNT)
    throw "GridView column adaptivity calculation error.";
  } while(violation);
  return minWidthInfo.gridWidth;
 },
 Fixed_GetColumnAdjustor: function() {
  return this.helper.GetColumnAdjustor();
 },
 Fixed_CreateColumnInfoObject: function(sourceInfo, widthType, width) {
  var hasFixedWidth = widthType === Constants.WidthType.FIXED;
  var hasPercentageWidth = widthType === Constants.WidthType.PERCENTAGE;
  var result = this.Fixed_GetColumnAdjustor().CreateColumnInfoObject(
   sourceInfo.index, sourceInfo.column, hasPercentageWidth, hasFixedWidth, width, sourceInfo);
  result.minContentWidth = sourceInfo.minContentWidth;
  result.isAlwaysCut = sourceInfo.isAlwaysCut;
  return result;
 },
 Fixed_GetResolvedColumnInfos: function(columnInfos) {
  var groupedInfos = this.Fixed_GroupSizesByWidthType(columnInfos);
  if(!this.Fixed_GetColumnAdjustor().HasRestrictions() || (groupedInfos.violatedSizes.length == 0 && !this.Fixed_IsHideDataCellsByColumnMinWidthAllowed()))
   return columnInfos.slice();
  var autoWidthInfos = groupedInfos.autoWidthSizes,
   percentageWidthInfos = groupedInfos.percentageSizes;
  if(autoWidthInfos.length > 0 && percentageWidthInfos.length > 0)
   return null;
  var result = [];
  var actualPercWidthInfos = [];
  var percWidthSummary = 0;
  for(var info, i = 0; info = columnInfos[i]; i++) {
   if(info.hasFixedWidth || info.violation || this.Fixed_IsHideDataCellsByColumnMinWidthAllowed() && info.minWidth > 0) {
    var width = info.width;
    if(info.violation)
     width = info.violation.violatedWidth;
    else if(!info.hasFixedWidth)
     width = info.minWidth;
    var columnInfo = this.Fixed_CreateColumnInfoObject(info, Constants.WidthType.FIXED, width);
    result.push(columnInfo);
   }
   else if(!info.hasPercentageWidth) {
    var columnInfo = this.Fixed_CreateColumnInfoObject(info, Constants.WidthType.AUTO, info.width);
    result.push(columnInfo);
   }
   else {
    percWidthSummary += info.width;
    actualPercWidthInfos.push(info);
   }
  }
  for(var info, i = 0; info = actualPercWidthInfos[i]; i++) {
   var width = 0;
   if(percWidthSummary > 0)
    width = info.width / percWidthSummary;
   var columnInfo = this.Fixed_CreateColumnInfoObject(info, Constants.WidthType.PERCENTAGE, width);
   result.push(columnInfo);
  }
  result.sort(function(c1, c2) { return c1.index - c2.index; });
  return result;
 },
 Fixed_GetGridMinWidthInfo: function(sizes) {
  var groupedSizes = this.Fixed_GroupSizesByWidthType(sizes);
  var autoWidthSizes = groupedSizes.autoWidthSizes,
   fixedSizes = groupedSizes.fixedSizes,
   percentageSizes = groupedSizes.percentageSizes;
  var autoWidthsInfo = this.Fixed_GetAutoWidthColumnsGridMinWidthInfo(autoWidthSizes);
  var fixedWidthsInfo = this.Fixed_GetFixedColumnsGridMinWidthInfo(fixedSizes);
  var summaryWidth = autoWidthsInfo.gridWidth + fixedWidthsInfo.gridWidth;
  if(autoWidthSizes.length > 0 && percentageSizes.length > 0) {
   var newInfo = this.Fixed_CreatePercentSizeForNonPercentColumns(percentageSizes, summaryWidth);
   if(newInfo) {
    if(newInfo.isAlwaysCut)
     return Constants.INFINITY_WIDTH;
    else
     percentageSizes.push(newInfo);
   }
   summaryWidth = 0;
  }
  var percentageWidthsInfo = this.Fixed_GetPercentageColumnsGridMinWidthInfo(percentageSizes);
  summaryWidth += percentageWidthsInfo.gridWidth;
  var widthInfos = autoWidthsInfo.widthInfos.concat(fixedWidthsInfo.widthInfos.concat(percentageWidthsInfo.widthInfos));
  widthInfos.sort(function(w1, w2) { return w1.columnInfo.index - w2.columnInfo.index; });
  return {
   gridWidth: summaryWidth,
   widthInfos: widthInfos
  };
 },
 Fixed_CreateIndentSizeInfo: function(indentWidth) {
  var result = this.Fixed_GetColumnAdjustor().CreateColumnInfoObject(
   Constants.SpecColumnIndex.INDENT, null, false, true, indentWidth, null);
  result.minContentWidth = indentWidth - 1;
  return result;
 },
 Fixed_HasAnyAlwaysCutColumn: function(sizes) {
  for(var i = 0, info; info = sizes[i]; i++) {
   if(info.isAlwaysCut)
    return true;
  }
  return false;
 },
 Fixed_CreatePercentSizeForNonPercentColumns: function(percentSizes, nonPercentColumnsSummaryWidth) {
  var percentWidthSum = 0;
  for(var i = 0, info; info = percentSizes[i]; i++)
   percentWidthSum += info.width;
  var spaceForNonPercentWidth = 1 - percentWidthSum;
  if(spaceForNonPercentWidth > 0) {
   var result = this.Fixed_GetColumnAdjustor().CreateColumnInfoObject(
    Constants.SpecColumnIndex.NON_PERCENT_SPACE, null, true, false, spaceForNonPercentWidth, null);
   result.minContentWidth = nonPercentColumnsSummaryWidth;
   return result;
  }
  else if(nonPercentColumnsSummaryWidth > 0) {
   return { isAlwaysCut: true };  
  }
  else
   return null;
 },
 Fixed_GetAutoWidthColumnsGridMinWidthInfo: function(autoWidthSizes) {
  var maxMinContentWidth = 0;
  for(var i = 0, info; info = autoWidthSizes[i]; i++) {
   if(maxMinContentWidth < info.minContentWidth)
    maxMinContentWidth = info.minContentWidth;
  }
  var result = {};
  result.gridWidth = maxMinContentWidth * autoWidthSizes.length;
  result.widthInfos = [];
  for(var info, i = 0; info = autoWidthSizes[i]; i++) {
   var widthInfo = this.Fixed_GetColumnAdjustor().CreateWidthInfoObject(maxMinContentWidth, info);
   result.widthInfos.push(widthInfo);
  }
  return result;
 },
 Fixed_GetFixedColumnsGridMinWidthInfo: function(fixedSizes) {
  var result = {
   gridWidth: 0,
   widthInfos: []
  };
  for(var i = 0, info; info = fixedSizes[i]; i++) {
   result.gridWidth += info.width;
   var widthInfo = this.Fixed_GetColumnAdjustor().CreateWidthInfoObject(info.width, info);
   result.widthInfos.push(widthInfo);
  }
  return result;
 },
 Fixed_GetPercentageColumnsGridMinWidthInfo: function(percentageSizes) {
  var result = {
   gridWidth: 0,
   widthInfos: []
  };
  if(percentageSizes.length == 0)
   return result;
  var maxPercentageWidth = 0;
  var maxPercetageIndex = -1;
  for(var i = 0, info; info = percentageSizes[i]; i++) {
   if(maxPercentageWidth < info.width) {
    maxPercentageWidth = info.width;
    maxPercetageIndex = i;
   }
  }
  var maxPercentageWidthInfo = percentageSizes[maxPercetageIndex];
  var maxPercentageWidthColumnMinContentWidth = maxPercentageWidthInfo.minContentWidth > 0 ? maxPercentageWidthInfo.minContentWidth : 1;
  var maxCoefficient = 1;
  for(var i = 0, info; info = percentageSizes[i]; i++) {
   var coefficient = info.minContentWidth / (maxPercentageWidthColumnMinContentWidth * info.width / maxPercentageWidth);
   if(maxCoefficient < coefficient)
    maxCoefficient = coefficient;
  }
  for(var i = 0, info; info = percentageSizes[i]; i++) {
   var width = maxPercentageWidthColumnMinContentWidth * maxCoefficient * info.width / maxPercentageWidth;
   result.gridWidth += width;
   var widthInfo = this.Fixed_GetColumnAdjustor().CreateWidthInfoObject(width, info);
   result.widthInfos.push(widthInfo);
  }
  return result;
 },
 Fixed_GroupSizesByWidthType: function(sizes) {
  var autoWidthSizes = [],
   fixedSizes = [],
   percentageSizes = [],
   violatedSizes = [];
  for(var i = 0, info; info = sizes[i]; i++) {
   if(info.hasFixedWidth)
    fixedSizes.push(info);
   else if(info.hasPercentageWidth)
    percentageSizes.push(info);
   else
    autoWidthSizes.push(info);
   if(info.violation)
    violatedSizes.push(info);
  }
  return {
   autoWidthSizes: autoWidthSizes,
   fixedSizes: fixedSizes,
   percentageSizes: percentageSizes,
   violatedSizes: violatedSizes
  };
 },
 Fixed_IsHideDataCellsByColumnMinWidthAllowed: function() {
  return this.helper.allowHideDataCellsByColumnMinWidth;
 },
 CalculateColumnsToBeHiddenCore: function(getGridWidthFunc, createIndentSizeInfoFunc, hasAnyAlwaysCutColumnFunc, sizes, containerWidth,
   bordersWidth, adaptiveColumnIndentWidth, leftIndentsWidth, allowHideTruncatedColumns) {
  var sizes = sizes.slice(0);
  var indentInfo = createIndentSizeInfoFunc(leftIndentsWidth);
  sizes.push(indentInfo);
  var columnsToHide = [];
  var gridInnerWidth = getGridWidthFunc(sizes);
  var gridWidth = bordersWidth + gridInnerWidth;
  var overflow = gridInnerWidth === Constants.INFINITY_WIDTH || containerWidth < gridWidth;
  if(overflow) {
   var adaptiveColumnsOrder = this.GetAdaptiveColumnsOrder();
   for(var i = 0; i < adaptiveColumnsOrder.length - 1; i++) {
    var columnIndex = adaptiveColumnsOrder[i];
    if(!allowHideTruncatedColumns && this.AllowTextTruncationInAdaptiveMode(columnIndex))
     continue;
    var column = this.GetColumn(columnIndex);
    if(column.adaptiveHidden)
     continue;
    if(!ASPx.Data.ArrayContains(this.GetVisibleColumnIndices(), columnIndex))
     continue;
    if(columnsToHide.length == 0) {
     var indentInfo = createIndentSizeInfoFunc(adaptiveColumnIndentWidth);
     sizes.push(indentInfo);
    }
    columnsToHide.push(columnIndex);
    var infoIndex = ASPx.Data.ArrayIndexOf(sizes, columnIndex, function(info, colIndex) { return info.index === colIndex; });
    ASPx.Data.ArrayRemoveAt(sizes, infoIndex);
    if(hasAnyAlwaysCutColumnFunc(sizes))
     continue;
    gridInnerWidth = getGridWidthFunc(sizes);
    overflow = gridInnerWidth === Constants.INFINITY_WIDTH;
    if(overflow)
     continue;
    gridWidth = bordersWidth + gridInnerWidth;
    overflow = containerWidth < gridWidth;
    if(!overflow)
     break;
   }
  }
  return {
   columnsToHide: columnsToHide,
   overflow: overflow
  };
 },
 GetAdaptiveColumnsOrder: function() {
  return this.layout.GetAdaptiveColumnsOrder();
 },
 AllowTextTruncationInAdaptiveMode: function(columnIndex) {
  return this.helper.AllowTextTruncationInAdaptiveMode(columnIndex);
 },
 GetColumn: function(columnIndex) {
  return this.layout.GetColumn(columnIndex);
 },
 GetVisibleColumnIndices: function() {
  return this.layout.GetVisibleColumnIndices();
 }
});
var GridViewAdaptivityAdjuster = ASPx.CreateClass(null, {
 constructor: function() {
  this.needCollapseMasterGrid = false;
 },
 SetNeedCollapseMasterGrid: function(masterGrid) {
  this.needCollapseMasterGrid = masterGrid.IsResponsiveAdaptivityMode();
 },
 CheckNeedCollapseDetailGrid: function(detailGrid) {
  var masterGrid = this.GetGridViewAdjuster().GetMasterGridForAdjust();
  return masterGrid && masterGrid.IsMasterGridFor(detailGrid);
 },
 CollapseMasterGridIfNeed: function(detailGrid) {
  var masterGrid = this.GetGridViewAdjuster().GetMasterGridForAdjust();
  if(this.needCollapseMasterGrid && masterGrid.IsMasterGridFor(detailGrid)) {
   masterGrid.ResetAdaptivityOnCallback();
   masterGrid.GetAdaptivityHelper().HideAllAdaptiveColumns();
   this.needCollapseMasterGrid = false;
  }
 },
 TryCalculateMasterDetailGridsAdaptivity: function(grid) {
  var calculated = grid.HasAdaptivity();
  this.needCollapseMasterGrid = false;
  this.GetGridViewAdjuster().SetMasterGridForAdjust(null);
  grid.CalculateAdaptivity(true);
  if(grid.hasDetailRows)
   calculated = this.CalculateDetailGridsAdaptivity(grid.GetMainElement()) || calculated;
  grid.RestoreAdaptivityState();
  return calculated;
 },
 CalculateDetailGridsAdaptivity: function(container) {
  var controlCollection = ASPx.GetControlCollection();
  var filter = function(control) {
   return control instanceof ASPxClientGridView && control.IsResponsiveAdaptivityMode();
  };
  var controlTree = new ASPx.ControlTree(controlCollection, container, filter);
  return this.CalculateGridControlsAdaptivityInTree(controlTree.rootNode);
 },
 CalculateGridControlsAdaptivityInTree: function(node) {
  var calculated = false;
  var grid = node.control;
  if(grid) {
   grid.CalculateAdaptivity(true);
   calculated = true;
  }
  for(var childNode, i = 0; childNode = node.children[i]; i++)
   calculated = this.CalculateGridControlsAdaptivityInTree(childNode) || calculated;
  return calculated;
 },
 GetGridViewAdjuster: function() {
  return ASPx.GetGridViewAdjuster();
 }
});
var gridViewAdaptivityAdjuster = new GridViewAdaptivityAdjuster();
function GetGridViewAdaptivityAdjuster() {
 return gridViewAdaptivityAdjuster;
}
ASPx.GridViewColumnAdaptivityCalculatorBase = GridViewColumnAdaptivityCalculatorBase;
ASPx.GridViewResponsiveModeCalculatorBase = GridViewResponsiveModeCalculatorBase;
ASPx.GridViewAutoTableLayoutAdaptivityCalculator = GridViewAutoTableLayoutAdaptivityCalculator;
ASPx.GridViewFixedTableLayoutAdaptivityCalculator = GridViewFixedTableLayoutAdaptivityCalculator;
ASPx.GridViewAdaptiveModeCalculator = GridViewAdaptiveModeCalculator;
ASPx.GridViewColumnAdaptivityCalculationUtils = GridViewColumnAdaptivityCalculationUtils;
ASPx.GridViewAutoTableLayoutAdaptivityHelper = GridViewAutoTableLayoutAdaptivityHelper;
ASPx.GridViewFixedTableLayoutAdaptivityHelper = GridViewFixedTableLayoutAdaptivityHelper;
ASPx.GridViewAdaptiveModeAdaptivityHelper = GridViewAdaptiveModeAdaptivityHelper;
ASPx.GetGridViewAdaptivityAdjuster = GetGridViewAdaptivityAdjuster;
})();

(function() {
 var Constants = {
  ALLOWED_CALC_WIDTH_DIFF: 0.5,
  ALLOWED_RENDER_WIDTH_DIFF: 0.01,
  MAX_ITERATION_COUNT: 1000
 };
 var GridViewColumnAdjustor = ASPx.CreateClass(null, {
  constructor: function(grid) {
   this.grid = grid;
   this.columnInfos = [];
   this.hasRestrictions = false;
   this.hasValidColumnWidths = true;
  },
  Initialize: function() {
   if(!this.IsFixedTableLayout())
    return;
   this.columnInfos = this.GetColumnInfos();
   this.hasRestrictions = this.CheckHasRestrictions(this.columnInfos);
   this.hasValidColumnWidths = this.IsValidGridLayout(this.columnInfos);
  },
  GetColumnInfos: function() {
   var columnInfos = [];
   var armRow = this.GetMainTableArmRow();
   var columns = this.grid.columns;
   for(var i = 0, column; column = columns[i]; i++) {
    if(!column.visible)
     continue;
    var cellIndex = this.grid.GetDataCellIndex(i);
    if(cellIndex === -1)
     continue;
    var armCell = armRow.cells[cellIndex];
    if(!armCell || armCell.colSpan > 1)
     continue;
    var styleWidth = armCell.style.width;
    var hasPercentageWidth = false;
    var hasFixedWidth = false;
    var width = -1;
    if(styleWidth) {
     hasPercentageWidth = ASPx.IsPercentageSize(styleWidth);
     hasFixedWidth = !hasPercentageWidth;
     width = hasPercentageWidth ? ASPx.PercentageToFloat(styleWidth) : ASPx.PxToInt(styleWidth);
    }
    var info = this.CreateColumnInfoObject(i, column, hasPercentageWidth, hasFixedWidth, width);
    columnInfos.push(info);
   }
   return columnInfos;
  },
  CheckHasRestrictions: function(columnInfos) {
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(info.minWidth > 0 || info.maxWidth > 0)
     return true;
   }
   return false;
  },
  HasRestrictions: function() {
   return this.hasRestrictions;
  },
  IsValidGridLayout: function(columnInfos) {
   var hasPercWidths = false,
    hasAutoWidths = false;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(info.hasPercentageWidth) {
     if(hasAutoWidths)
      return false;
     hasPercWidths = true;
    }
    else if(!info.hasFixedWidth) {
     if(hasPercWidths)
      return false;
     hasAutoWidths = true;
    }
   }
   return true;
  },
  HasValidColumnWidths: function() {
   return this.hasValidColumnWidths;
  },
  ShouldAdjustColumns: function() {
   return this.HasRestrictions() && this.HasValidColumnWidths();
  },
  IsColumnAdjustmentAllowed: function() {
   return !this.grid.AllowResizing() && !this.grid.IsResponsiveAdaptivityMode();
  },
  TryAdjustColumns: function() {
   if(!this.ShouldAdjustColumns() || !this.IsColumnAdjustmentAllowed())
    return false;
   var savedStyle = this.CollapseTables();
   var gridWidth = this.GetGridOffsetWidth(); 
   this.AdjustColumnsCore(this.columnInfos, gridWidth);
   this.ExpandTables(savedStyle);
   return true;
  },
  AdjustColumnsCore: function(columnInfos, gridWidth) {
   this.ResetColumnViolations(columnInfos);
   var resolvedGridInfo = this.CalculateCompleteResolvedColumnInfos(columnInfos, gridWidth);
   this.ApplyColumnInfosToRender(resolvedGridInfo.columnInfos, resolvedGridInfo.maxWidth);
  },
  ResetColumnViolations: function(columnInfos) {
   for(var info, i = 0; info = columnInfos[i]; i++)
    info.violation = null;
  },
  GetModifiedColumnInfos: function(newColumnInfos, oldColumnInfos) {
   var result = [];
   for(var newInfo, i = 0; newInfo = newColumnInfos[i]; i++) {
    oldInfo = oldColumnInfos[i];
    if(!this.AreEqualByWidth(newInfo, oldInfo))
     result.push(newInfo);
   }
   return result;
  },
  CalculateCompleteResolvedColumnInfos: function(sourceColumnInfos, gridWidth) {
   var violation = null;
   var resolvedGridInfo = null;
   var counter = 0;
   do {
    resolvedGridInfo = this.CalculateResolvedGridInfo(gridWidth, sourceColumnInfos);
    var resolvedGridWidth = ASPx.IsExists(resolvedGridInfo.resolvedWidth) ? resolvedGridInfo.resolvedWidth : gridWidth;
    var widthInfos = this.CalculateColumnsCurrentWidths(resolvedGridWidth, resolvedGridInfo.columnInfos);
    violation = this.GetWidthViolation(widthInfos);
    if(violation)
     this.ResolveViolation(violation);
    if(++counter > Constants.MAX_ITERATION_COUNT)
     throw "GridView column calculation error.";
   } while(violation);
   return resolvedGridInfo;
  },
  CollapseTables: function() {
   var styles = [];
   var cell = this.GetMainElementCell();
   var style = cell.style;
   var savedStyle = { display: style.display, width: style.width, height: style.height, overflow: style.overflow };
   ASPx.SetStyles(cell, { display: "block", width: "0px", height: "0px", overflow: "hidden", maxWidth: "" });
   styles.push(savedStyle);
   if(this.IsGridWidthValueSetInPercentage()) {
    var mainElement = this.grid.GetMainElement();
    savedStyle = { width: mainElement.style.width };
    mainElement.style.width = this.grid.percentSizeConfig.width;
    styles.push(savedStyle);
   }
   return styles;
  },
  ExpandTables: function(styles) {
   var cell = this.GetMainElementCell();
   ASPx.SetStyles(cell, styles[0]);
   if(this.IsGridWidthValueSetInPercentage())
    this.grid.GetMainElement().style.width = styles[1].width;
  },
  IsGridWidthValueSetInPercentage: function() { return this.grid.widthValueSetInPercentage; },
  RestoreTableRenderColumnWidths: function(table) {
   this.ApplyColumnInfosToTable(table, this.columnInfos);
  },
  ApplyColumnInfosToTable: function(table, columnInfos) {
   var armRow = table.rows[0];
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(!info.column) continue;
    var widthStr = this.GetColumnInfoWidthString(info);
    var columnIndex = info.column.index;
    var cellIndex = this.grid.GetDataCellIndex(columnIndex);
    var armCell = armRow.cells[cellIndex];
    armCell.style.width = widthStr;
   }
  },
  ApplyColumnInfosToRender: function(columnInfos, maxGridWidth) {
   var tables = this.grid.GetLayoutHelper().GetAllTables();
   for(var table, i = 0; table = tables[i]; i++)
    this.ApplyColumnInfosToTable(table, columnInfos);
   if(ASPx.IsExists(maxGridWidth))
    this.grid.GetMainElement().style.maxWidth = maxGridWidth + "px";
  },
  ResolveViolation: function(violation) {
   violation.columnInfo.violation = violation;
  },
  GetWidthViolation: function(widthInfos) {
   var minViolation = null,
    maxViolation = null,
    summaryWidthDiff = 0;
   for(var info, i = 0; info = widthInfos[i]; i++) {
    var columnInfo = info.columnInfo.sourceColumnInfo || info.columnInfo;
    if(columnInfo.minWidth > 0) {
     var widthDiff = columnInfo.minWidth - info.width;
     if(widthDiff > Constants.ALLOWED_CALC_WIDTH_DIFF) {
      summaryWidthDiff += widthDiff;
      if(!minViolation)
       minViolation = this.CreateViolationObject(true, columnInfo, widthDiff, columnInfo.minWidth);
      continue;
     }
    }
    if(columnInfo.maxWidth > 0) {
     var widthDiff = info.width - columnInfo.maxWidth;
     if(widthDiff > Constants.ALLOWED_CALC_WIDTH_DIFF) {
      summaryWidthDiff -= widthDiff;
      if(!maxViolation)
       maxViolation = this.CreateViolationObject(false, columnInfo, -widthDiff, columnInfo.maxWidth);
      continue;
     }
    }
   }
   return summaryWidthDiff >= 0 ? minViolation : maxViolation;
  },
  CreateViolationObject: function(minWidthViolation, columnInfo, widthDiff, violatedWidth) {
   return {
    minWidthViolation: minWidthViolation,
    columnInfo: columnInfo,
    widthDiff: widthDiff,
    violatedWidth: violatedWidth
   };
  },
  CalculateResolvedGridInfo: function(gridWidth, columnInfos) {
   var groupedInfos = this.GroupInfosByWidthType(columnInfos);
   var autoWidthInfos = groupedInfos.autoWidthInfos,
    fixedWidthInfos = groupedInfos.fixedWidthInfos,
    percentageWidthInfos = groupedInfos.percentageWidthInfos;
   if(autoWidthInfos.length > 0 && percentageWidthInfos.length == 0) {
    return this.CalculateResolvedAutoWidthColumnsGridInfo(gridWidth, columnInfos);
   }
   if(autoWidthInfos.length == 0 && fixedWidthInfos.length > 0 && percentageWidthInfos.length == 0) {
    return this.CalculateResolvedFixedWidthColumnsGridInfo(gridWidth, columnInfos);
   }
   if(autoWidthInfos.length == 0 && percentageWidthInfos.length > 0) {
    return this.CalculateResolvedPercentageWidthColumnsGridInfo(gridWidth, columnInfos);
   }
   return null;
  },
  CalculateResolvedPercentageWidthColumnsGridInfo: function(gridWidth, columnInfos) {
   var result = { columnInfos: [] };
   var fixedColumnCount = 0;
   var fixedWidthSummary = 0;
   var percWidthSummary = 0;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(info.hasFixedWidth || info.violation) {
     fixedColumnCount++;
     fixedWidthSummary += info.hasFixedWidth ? info.width : info.violation.violatedWidth;
    }
    else
     percWidthSummary += info.width;
   }
   var percColumnSummaryWidth = gridWidth - fixedWidthSummary;
   var percColumnCount = columnInfos.length - fixedColumnCount;
   if(percColumnSummaryWidth > 0 && percColumnCount == 0)
    result.maxWidth = result.resolvedWidth = fixedWidthSummary;
   if(percWidthSummary == 0)
    percWidthSummary = 1;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    var hasFixedWidth = true;
    var width = info.width;
    if(info.violation)
     width = info.violation.violatedWidth;
    else if(!info.hasFixedWidth) {
     hasFixedWidth = false;
     width = info.width / percWidthSummary;
    }
    var columnInfo = this.CreateColumnInfoObject(info.index, info.column, !hasFixedWidth, hasFixedWidth, width, info);
    result.columnInfos.push(columnInfo);
   }
   return result;
  },
  CalculateResolvedFixedWidthColumnsGridInfo: function(gridWidth, columnInfos) {
   var result = { columnInfos: [] };
   var violatedWidthSummary = 0;
   var violatedColumnCount = 0;
   var normalColumnMinSummaryWidth = 0;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(info.violation) {
     violatedWidthSummary += info.violation.violatedWidth;
     violatedColumnCount++;
    }
    else
     normalColumnMinSummaryWidth += info.width;
   }
   var newMinGridWidth = violatedWidthSummary + normalColumnMinSummaryWidth;
   if(gridWidth <= newMinGridWidth) {
    for(var info, i = 0; info = columnInfos[i]; i++) {
     var columnInfo = this.CreateColumnInfoObject(info.index, info.column, false, true, info.width, info);
     result.columnInfos.push(columnInfo);
    }
    return result;
   }
   else if(violatedColumnCount == columnInfos.length)
    result.maxWidth = result.resolvedWidth = gridWidth = violatedWidthSummary;
   var normalColumnSummaryWidth = gridWidth - violatedWidthSummary;
   var normalColumnSummaryPart = normalColumnSummaryWidth / gridWidth;
   var violatedColumnSummaryPart = 1 - normalColumnSummaryPart;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    var part = info.violation
     ? (info.violation.violatedWidth / violatedWidthSummary) * violatedColumnSummaryPart
     : (info.width / normalColumnMinSummaryWidth) * normalColumnSummaryPart;
    var width = part * gridWidth;
    var columnInfo = this.CreateColumnInfoObject(info.index, info.column, false, true, width, info);
    result.columnInfos.push(columnInfo);
   }
   return result;
  },
  CalculateResolvedAutoWidthColumnsGridInfo: function(gridWidth, columnInfos) {
   var result = { columnInfos: [] };
   var fixedColumnCount = 0;
   var fixedWidthSummary = 0;
   for(var info, i = 0; info = columnInfos[i]; i++) {
    if(info.hasFixedWidth || info.violation) {
     fixedColumnCount++;
     fixedWidthSummary += info.hasFixedWidth ? info.width : info.violation.violatedWidth;
    }
   }
   var autoColumnSummaryWidth = gridWidth - fixedWidthSummary;
   var autoColumnCount = columnInfos.length - fixedColumnCount;
   var autoWidth = 0;
   if(autoColumnSummaryWidth > 0) {
    if(autoColumnCount > 0)
     autoWidth = autoColumnSummaryWidth / autoColumnCount;
    else
     result.maxWidth = result.resolvedWidth = fixedWidthSummary;
   }
   for(var info, i = 0; info = columnInfos[i]; i++) {
    var hasFixedWidth = !!info.violation || info.hasFixedWidth;
    var width = autoWidth;
    if(info.hasFixedWidth)
     width = info.width;
    else if(info.violation)
     width = info.violation.violatedWidth;
    var columnInfo = this.CreateColumnInfoObject(info.index, info.column, false, hasFixedWidth, width, info);
    result.columnInfos.push(columnInfo);
   }
   return result;
  },
  CalculateColumnsCurrentWidths: function(gridWidth, columnInfos) {
   var groupedInfos = this.GroupInfosByWidthType(columnInfos);
   var autoWidthInfos = groupedInfos.autoWidthInfos,
    fixedWidthInfos = groupedInfos.fixedWidthInfos,
    percentageWidthInfos = groupedInfos.percentageWidthInfos;
   var result = [];
   if(percentageWidthInfos.length > 0 && autoWidthInfos.length > 0)
    return null;
   var fixedWidthSum = 0;
   for(var info, i = 0; info = fixedWidthInfos[i]; i++)
    fixedWidthSum += info.width;
   if(fixedWidthInfos.length == columnInfos.length) {
    var coefficient = 1;
    if(fixedWidthSum > 0)
     coefficient = gridWidth / fixedWidthSum;
    if(coefficient < 1)
     coefficient = 1;
    for(var info, i = 0; info = fixedWidthInfos[i]; i++) {
     var width = coefficient * info.width;
     var widthInfo = this.CreateWidthInfoObject(width, info);
     result.push(widthInfo);
    }
   }
   else {
    var flexWidthSum = gridWidth - fixedWidthSum;
    var autoWidthColumnWidth = 0;
    if(autoWidthInfos.length > 0 && flexWidthSum > 0)
     autoWidthColumnWidth = flexWidthSum / autoWidthInfos.length;
    var percWidthColumnSum = 0;
    for(var info, i = 0; info = percentageWidthInfos[i]; i++)
     percWidthColumnSum += info.width;
    if(percWidthColumnSum == 0)
     percWidthColumnSum = 1;
    for(var info, i = 0; info = columnInfos[i]; i++) {
     var width = info.width;
     if(info.hasPercentageWidth)
      width = flexWidthSum * info.width / percWidthColumnSum;
     else if(!info.hasFixedWidth)
      width = autoWidthColumnWidth;
     var widthInfo = this.CreateWidthInfoObject(width, info);
     result.push(widthInfo);
    }
   }
   return result;
  },
  GetColumnInfoWidthString: function(columnInfo) {
   if(columnInfo.hasFixedWidth)
    return columnInfo.width + "px";
   else if(columnInfo.hasPercentageWidth)
    return (columnInfo.width * 100) + "%";
   else
    return "";
  },
  AreEqualByWidth: function(columnInfo1, columnInfo2) {
   return columnInfo1.hasFixedWidth === columnInfo2.hasFixedWidth &&
    columnInfo1.hasPercentageWidth === columnInfo2.hasPercentageWidth &&
    (!columnInfo1.hasFixedWidth && !columnInfo1.hasPercentageWidth ||
     Math.abs(columnInfo1.width - columnInfo2.width) < Constants.ALLOWED_RENDER_WIDTH_DIFF);
  },
  CreateWidthInfoObject: function(width, columnInfo) {
   return {
    width: width,
    columnInfo: columnInfo
   };
  },
  CreateColumnInfoObject: function(index, column, hasPercentageWidth, hasFixedWidth, width, sourceColumnInfo) {
   return {
    index: index,
    column: column,
    hasPercentageWidth: hasPercentageWidth,
    hasFixedWidth: hasFixedWidth,
    width: width,
    minWidth: column ? column.minWidth : 0,
    maxWidth: column ? column.maxWidth : 0,
    sourceColumnInfo: sourceColumnInfo
   };
  },
  GroupInfosByWidthType: function(infos) {
   var autoWidthInfos = [],
    fixedWidthInfos = [],
    percentageWidthInfos = [],
    violatedWidthInfos = [];
   for(var i = 0, info; info = infos[i]; i++) {
    if(info.hasFixedWidth)
     fixedWidthInfos.push(info);
    else if(info.hasPercentageWidth)
     percentageWidthInfos.push(info);
    else
     autoWidthInfos.push(info);
    if(info.violation)
     violatedWidthInfos.push(info);
   }
   return {
    autoWidthInfos: autoWidthInfos,
    fixedWidthInfos: fixedWidthInfos,
    percentageWidthInfos: percentageWidthInfos,
    violatedWidthInfos: violatedWidthInfos
   };
  },
  GetGridOffsetWidth: function() {
   return this.grid.GetMainElement().offsetWidth;
  },
  GetMainTableArmRow: function () {
   return this.grid.GetMainTable().rows[0];
  },
  GetMainElementCell: function() {
   return this.grid.GetLayoutHelper().GetMainElementCell();
  },
  IsFixedTableLayout: function() {
   return this.grid.GetLayoutHelper().IsFixedTableLayout();
  }
 });
 ASPx.GridViewColumnAdjustor = GridViewColumnAdjustor;
})();
(function() {
var GridViewColumnHelper = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
  this.visibleHeaderTree = null;
  this.visibleDataRowTree = null;
  this.headerLayout = null;
  this.dataRowLayout = null;
  this.headerLeafs = null;
  this.dataRowLeafs = null;
  this.headerNodeHash = { };
  this.dataRowNodeHash = { };
  this.sortedVisibleChildColumnsHash = { };
  this.childColumnHash = { };
  this.fixedColumnsHash = null;
  this.visibleColumnIndices = null;
  this.visibleDataColumnIndices = null;
  this.rightTreeLines = null;
  this.cachedGroupColumns = -1;
 },
 GetAllColumns: function() { return this.grid.columns; },
 GetShowGroupedColumns: function() { return this.grid.showGroupedColumns; },
 FindColumn: function(index) {
  index = parseInt(index);
  return this.GetAllColumns().filter(function(c) { return c.index === index; })[0] || null;
 },
 HasColumnChildren: function(index) {
  return this.GetAllColumns().filter(function(c) { return c.parentIndex === index; }).length > 0;
 },
 GetGroupColumns: function() {
  if(this.cachedGroupColumns === -1)
   this.cachedGroupColumns = this.GetAllColumns().filter(function(c) { return c.groupIndex > -1; }).sort(function(c1, c2) { return c1.groupIndex - c2.groupIndex; });
  return this.cachedGroupColumns;
 },
 GetGroupColumnCount: function() { 
  return this.GetGroupColumns().length;
 },
 GetParentColumnIndices: function(columnIndex) {
  var node = this.FindNode(columnIndex);
  if(!node)
   return [ ];
  return this.CreateTreeLine(node, false).map(function(n) { return n.columnIndex; });
 },
 GetParentColumnIndex: function(columnIndex) {
  var parentColumnIndices = this.GetParentColumnIndices(columnIndex);
  return parentColumnIndices.length > 0 ? parentColumnIndices[0] : -1;
 },
 GetIsParentForAllColumns: function(parentColumnIndex, columnIndices) {
  if(columnIndices.length === 0)
   return false;
  return columnIndices.every(function(i) {
   return this.GetParentColumnIndices(i).indexOf(parentColumnIndex) > -1;
  }.bind(this));
 },
 FindColumnLayoutPos: function(layout, columnIndex) {
  for(var i = 0; i < layout.length; i++) {
   var level = layout[i];
   for(var j = 0; j < level.length; j++) {
    if(level[j].columnIndex === columnIndex)
     return { levelIndex: i, cellIndex: j };
   }
  }
  return { levelIndex: -1, cellIndex: -1 };
 },
 FindNode: function(columnIndex, isDataRowTree) {
  this.EnsureTrees();
  var hash = isDataRowTree ? this.dataRowNodeHash : this.headerNodeHash;
  return hash[columnIndex];
 },
 IsColumnFixed: function(columnIndex) {
  this.EnsureFixedColumnsHash();
  return this.fixedColumnsHash[columnIndex];
 },
 EnsureFixedColumnsHash: function() {
  if(this.fixedColumnsHash) 
   return;
  var firstLevelColumnsFixedState = { };
  var firstLevelColumns = this.GetVisibleChildColumns(-1, true);
  for(var i = 0; i < firstLevelColumns.length; i++) {
   var column = firstLevelColumns[i];
   firstLevelColumnsFixedState[column.index] = this.IsColumnFixedRecursive(column);
  }
  this.fixedColumnsHash = { };
  var allColumns = this.GetAllColumns();
  for(var i = 0; i < allColumns.length; i++) {
   var column = allColumns[i];
   var firstLevelColumn = column;
   while(firstLevelColumn.parentIndex >= 0)
    firstLevelColumn = this.FindColumn(firstLevelColumn.parentIndex);
   this.fixedColumnsHash[column.index] = firstLevelColumnsFixedState[firstLevelColumn.index];
  }
 },
 IsColumnFixedRecursive: function(column) {
  if(column.isFixed) return true;
  var childColumns = this.GetVisibleChildColumns(column.index, true);
  for(var i = 0; i < childColumns.length; i++) {
   if(this.IsColumnFixedRecursive(childColumns[i]))
    return true;
  }
  return false;
 },
 IsColumnInRightTreeLine: function(columnIndex, isHeader) {
  this.EnsureRightTreeLines();
  var treeLine = isHeader ? this.rightTreeLines.header : this.rightTreeLines.data;
  return treeLine.filter(function(n) { return n.columnIndex === columnIndex; }).length !== 0;
 },
 EnsureRightTreeLines: function() {
  if(this.rightTreeLines) return;
  this.rightTreeLines = { };
  var headerLeafs = this.GetHeaderLeafs();
  var dataRowLeafs = this.GetDataRowLeafs();
  this.rightTreeLines.header = this.CreateTreeLine(headerLeafs[headerLeafs.length - 1], true);
  this.rightTreeLines.data = this.CreateTreeLine(dataRowLeafs[dataRowLeafs.length - 1], true);
 },
 GetVisibleColumnIndices: function(isDataRowLayout) {
  if(!this.visibleColumnIndices)
   this.visibleColumnIndices = { header: this.CalculateVisibleColumnIndices(false), data: this.CalculateVisibleColumnIndices(true) };
  return isDataRowLayout ? this.visibleColumnIndices.data : this.visibleColumnIndices.header;
 },
 GetVisibleDataColumnIndices: function() {
  if(!this.visibleDataColumnIndices)
   this.visibleDataColumnIndices = this.GetVisibleColumnIndices()
    .filter(function(i) { return this.grid.GetColumn(i).isDataColumn; }.bind(this));
  return this.visibleDataColumnIndices;
 },
 CalculateVisibleColumnIndices: function(isDataRowLayout) {
  var layout = isDataRowLayout ? this.GetDataRowLayout() : this.GetHeaderLayout();
  return ASPx.Data.ArrayFlatten(layout).map(function(n) { return n.columnIndex; });
 },
 GetAdaptiveRowInfo: function() {
  var adaptiveNodes = [ ];
  var tree = this.GetVisibleDataRowTree();
  this.FindAdaptiveNodes(tree, adaptiveNodes, false);
  for(var i = 0; i < adaptiveNodes.length; i++) {
   var node = adaptiveNodes[i];
   ASPx.Data.ArrayRemove(node.parent.children, node);
  }
  var dataRowLayout = [ ];
  this.PopulateRowLayout(tree, dataRowLayout);
  this.Invalidate();
  return { 
   dataRowLayout: dataRowLayout, 
   adaptiveColumnIndices: adaptiveNodes.map(function(n) { return n.columnIndex; }) 
  };
 },
 FindAdaptiveNodes: function(node, adaptiveNodes, isAdaptiveParent) {
  var isColumnAdaptive = node.column && node.column.adaptiveHidden;
  if(isColumnAdaptive || isAdaptiveParent) {
   adaptiveNodes.push(node);
   isAdaptiveParent |= isColumnAdaptive;
  }
  for(var i = 0; i < node.children.length; i++)
   this.FindAdaptiveNodes(node.children[i], adaptiveNodes, isAdaptiveParent);
 },
 EnsureTrees: function() {
  this.GetVisibleHeaderTree();
  this.GetVisibleDataRowTree();
 },
 GetVisibleHeaderTree: function() {
  if(!this.visibleHeaderTree) {
   var root = this.CreateTreeNode(-1, null);
   this.PopulateVisualTreeNode(root, this.GetVisibleChildColumns(-1), false);
   this.PopulateHeaderNodeSpans(root);
   this.visibleHeaderTree = root;
  }
  return this.visibleHeaderTree;
 },
 GetVisibleDataRowTree: function() {
  if(!this.visibleDataRowTree) {
   var root = this.CreateTreeNode(-1, null);
   this.PopulateVisualTreeNode(root, this.GetVisibleChildColumns(-1), true);
   this.PopulateDataRowNodeSpans(root);
   this.visibleDataRowTree = root;
  }
  return this.visibleDataRowTree;
 },
 GetHeaderLayout: function() {
  if(!this.headerLayout) {
   this.headerLayout = [ ];
   this.PopulateRowLayout(this.GetVisibleHeaderTree(), this.headerLayout);
  }
  return this.headerLayout;
 },
 GetDataRowLayout: function() {
  if(!this.dataRowLayout) {
   this.dataRowLayout = [ ];
   this.PopulateRowLayout(this.GetVisibleDataRowTree(), this.dataRowLayout);
  }
  return this.dataRowLayout;
 },
 GetHeaderLeafs: function() { 
  if(!this.headerLeafs) {
   this.headerLeafs = [ ];
   this.PopulateLeafs(this.GetVisibleHeaderTree(), this.headerLeafs);
  }
  return this.headerLeafs;
 },
 GetDataRowLeafs: function() { 
  if(!this.dataRowLeafs) {
   this.dataRowLeafs = [ ];
   this.PopulateLeafs(this.GetVisibleDataRowTree(), this.dataRowLeafs);
  }
  return this.dataRowLeafs;
 },
 PopulateVisualTreeNode: function(node, visibleColumns, isDataRowTree) {
  var nodeHash = isDataRowTree ? this.dataRowNodeHash : this.headerNodeHash;
  for(var i = 0; i < visibleColumns.length; i++) {
   var bandNode = node;
   var column = visibleColumns[i];
   var childColumns = this.GetVisibleChildColumns(column.index);
   if(this.UseColumnInVisualTree(column, childColumns, isDataRowTree)) {
    var child = this.CreateTreeNode(column.index, node);
    node.children.push(child);
    nodeHash[column.index] = child;
    bandNode = child;
   }
   if(childColumns.length > 0)
    this.PopulateVisualTreeNode(bandNode, childColumns, isDataRowTree);
  }
 },
 UseColumnInVisualTree: function(column, childColumns, isDataRowTree) {
  if(column.groupIndex > -1 && !this.GetShowGroupedColumns())
   return false;
  if(isDataRowTree && column.isBand) {
   var childBandColumns = childColumns.filter(function(c) { return c.isBand; });
   if(childBandColumns.length > 0)
    return false;
   var visibleChildrenInTree = childColumns.filter(function(c) { return this.UseColumnInVisualTree(c, this.GetVisibleChildColumns(c.index), isDataRowTree); }.bind(this));
   return visibleChildrenInTree.length === 0;
  }
  return true;
 },
 GetChildColumns: function(columnIndex) {
  if(!this.childColumnHash[columnIndex])
   this.childColumnHash[columnIndex] = this.GetAllColumns().filter(function(c) { return c.parentIndex === columnIndex; });
  return this.childColumnHash[columnIndex];
 },
 GetVisibleChildColumns: function(columnIndex, unsorted) {
  columnIndex = parseInt(columnIndex);
  if(unsorted)
   return this.FindVisibleChildColumns(columnIndex, unsorted);
  if(!this.sortedVisibleChildColumnsHash[columnIndex])
   this.sortedVisibleChildColumnsHash[columnIndex] = this.FindVisibleChildColumns(columnIndex);
  return this.sortedVisibleChildColumnsHash[columnIndex];
 },
 FindVisibleChildColumns: function(columnIndex, unsorted) {
  var columns = this.GetChildColumns(columnIndex).filter(function(c) { return c.visible; }.bind(this));
  if(!unsorted)
   columns.sort(function(c1, c2) {
    var isRootLevel = columnIndex === -1;
    if(isRootLevel && this.IsColumnFixed(c1.index) !== this.IsColumnFixed(c2.index))
     return this.IsColumnFixed(c1.index) ? -1 : 1;
    if(c1.visibleIndex > c2.visibleIndex)
     return 1;
    if(c1.visibleIndex < c2.visibleIndex)
     return -1;
    return c1.collectionIndex - c2.collectionIndex;
   }.aspxBind(this));
  return columns;
 },
 PopulateRowLayout: function(node, layout) {
  for(var i = 0; i < node.children.length; i++) {
   var child = node.children[i];
   var levelIndex = this.FindNodeLayoutLevelIndex(child);
   while(layout.length < levelIndex + 1)
    layout.push([ ]);
   layout[levelIndex].push(child);
   this.PopulateRowLayout(child, layout);
  }
 },
 PopulateLeafs: function(node, leafs) {
  for(var i = 0; i < node.children.length; i++) {
   var child = node.children[i];
   if(child.children.length > 0)
    this.PopulateLeafs(child, leafs);
   else
    leafs.push(child);
  }
 },
 FindNodeLayoutLevelIndex: function(node) {
  var level = 0;
  node = node.parent;
  while(node.parent) {
   level += node.rowSpan;
   node = node.parent;
  }
  return level;
 },
 PopulateDataRowNodeSpans: function(root) {
  this.GetVisibleHeaderTree(); 
  root.rowSpan = root.colSpan = 1;
  var useBandedRowLayout = true; 
  for(var key in this.dataRowNodeHash) {
   if(!this.dataRowNodeHash.hasOwnProperty(key)) continue;
   var dataRowNode = this.dataRowNodeHash[key];
   var headerNode = this.headerNodeHash[key];
   dataRowNode.colSpan = headerNode.colSpan;
   dataRowNode.rowSpan = useBandedRowLayout ? headerNode.rowSpan : 1;
  }
  var bandColumnIndices = [ ];
  for(var key in this.headerNodeHash) {
   if(!this.headerNodeHash.hasOwnProperty(key)) continue;
   var headerNode = this.headerNodeHash[key];
   if(headerNode.column && headerNode.column.isBand)
    bandColumnIndices.push(headerNode.column.index);
  }
  if(bandColumnIndices.length > 0 && useBandedRowLayout)
   this.NormalizeDataRowTreeNodeRowSpans(bandColumnIndices);
 },
 NormalizeDataRowTreeNodeRowSpans: function(bandColumnIndices) {
  var matrix = this.CreateLayoutMatrixInfo(this.GetHeaderLayout()).matrix;
  var height = matrix.length;
  var width = matrix[0].length;
  for(var j = 0; j < width; j++) {
   var lastNotBandColumnIndex = matrix[height - 1][j];
   for(var i = height - 2; i >= 0; i--) {
    var columnIndex = matrix[i][j];
    if(bandColumnIndices.indexOf(columnIndex) > -1)
     matrix[i][j] = lastNotBandColumnIndex;
    else 
     lastNotBandColumnIndex = columnIndex;
   }
  }
  for(var i = height - 1; i > 0; i--) {
   if(this.IsMatrixRowEqual(matrix, i, i - 1))
    matrix.splice(i, 1);
  }
  height = matrix.length;
  var columnRowSpan = { };
  for(var j = 0; j < width; j++) {
   var columnIndices = this.GetColumnIndicesByColInd(height, j, matrix);
   var groupedIndices = columnIndices.reduce(function(r, cI) { (r[cI] = r[cI] || [ ]).push(cI); return r; }, { });
   for(var columnIndex in groupedIndices) {
    if(!groupedIndices.hasOwnProperty(columnIndex)) continue;
    columnRowSpan[columnIndex] = groupedIndices[columnIndex].length;
   }
  }
  for(var columnIndex in columnRowSpan) {
   if(!columnRowSpan.hasOwnProperty(columnIndex)) continue;
   this.dataRowNodeHash[columnIndex].rowSpan = columnRowSpan[columnIndex];
  }
 },
 GetColumnIndicesByColInd: function(height, colInd, matrix) {
  return ASPx.Data.Range(height).map(function(i) { return matrix[i][colInd]; });
 },
 PopulateHeaderNodeSpans: function(root) {
  var leafs = [ ];
  this.PopulateLeafs(root, leafs);
  if(leafs.length === 0)
   return;
  var leafTreeLines = [ ];
  for(var i = 0; i < leafs.length; i++) {
   var treeLine = [ ];
   var current = leafs[i];
   while(current != null) {
    current.colSpan |= 0;
    current.colSpan++;
    current.rowSpan = current.column ? current.column.rowSpan : 1;
    treeLine.push(current);
    current = current.parent;
   }
   leafTreeLines.push(treeLine);
  }
  var normalizeIterationCount = 2;
  for(var i = 0; i < normalizeIterationCount; i++)
   this.NormalizeHeaderNodesRowSpan(leafTreeLines);
 },
 NormalizeHeaderNodesRowSpan: function(leafTreeLines) {
  var height = leafTreeLines.reduce(function(prevValue, treeLine) { return Math.max(prevValue, treeLine.length); }, 0);
  for(var i = 0; i < leafTreeLines.length; i++) {
   var treeLine = leafTreeLines[i];
   var rowSpanHeight = treeLine.reduce(function(prevValue, node) { return prevValue + node.rowSpan; }, 0);
   var diff = height - rowSpanHeight;
   if(diff < 0)
    this.CalculateTreeLineRowSpanProportionally(treeLine, height);
   else
    treeLine[0].rowSpan += diff; 
  }
 },
 CalculateTreeLineRowSpanProportionally: function(treeLine, requiredHeight) {
  var rowSpans = this.CalculateTreeLineRowSpanProportionallyCore(treeLine, requiredHeight);
  for(var i = 0; i < treeLine.length; i++)
   treeLine[i].rowSpan = rowSpans[i];
 },
 CalculateTreeLineRowSpanProportionallyCore: function(treeLine, requiredHeight) {
  var result = [ ];
  var height = treeLine.reduce(function(prevValue, node) { return prevValue + node.rowSpan; }, 0);
  var delta = requiredHeight - height;
  if(delta >= 0) 
   return result;
  delta *= -1;
  var excess = delta;
  for(var i = 0; i < treeLine.length; i++) {
   var node = treeLine[i];
   result[i] = node.rowSpan;
   if(excess <= 0) continue;
   var k = Math.ceil(delta * node.rowSpan / height) + 1;
   if(k >= node.rowSpan)
    k = node.rowSpan - 1;
   excess -= k;
   if(excess < 0)
    k += excess;
   result[i] -= k;
  }
  return result;
 },
 CreateTreeNode: function(columnIndex, parent) {
  if(parent === undefined)
   parent = null;
  return { columnIndex: columnIndex, children: [ ], parent: parent, column: this.FindColumn(columnIndex) };
 },
 CreateTreeLine: function(node, insertCurrent) {
  var result = [ ];
  var current = insertCurrent ? node : node.parent;
  while(current.column !== null) {
   result.push(current);
   current = current.parent;
  }
  return result;
 },
 Invalidate: function() {
  this.visibleHeaderTree = null;
  this.visibleDataRowTree = null;
  this.headerLayout = null;
  this.dataRowLayout = null;
  this.headerLeafs = null;
  this.dataRowLeafs = null;
  this.headerNodeHash = { };
  this.dataRowNodeHash = { };
  this.sortedVisibleChildColumnsHash = { };
  this.childColumnHash = { };
  this.fixedColumnsHash = null;
  this.visibleColumnIndices = null;
  this.visibleDataColumnIndices = null;
  this.rightTreeLines = null;
  this.cachedGroupColumns = -1;
 },
 GetOrderedColumns: function() {
  var columns = this.GetAllColumns();
  columns.sort(function(c1, c2) { return c1.index - c2.index; });
  return columns;
 },
 SerializeColumnVisibleState: function() {
  var state = [ ];
  var columns = this.GetOrderedColumns();
  state.push("clientvis" + columns.length);
  for(var i = 0; i < columns.length; i++) {
   var column = columns[i];
   state.push((column.visible ? "t" : "f") + column.visibleIndex);
  }
  return state.join("|");
 },
 SerializeColumnHierarchyState: function() {
  var state = [ ];
  var columns = this.GetOrderedColumns();
  state.push("clienthierar" + columns.length);
  for(var i = 0; i < columns.length; i++) {
   var column = columns[i];
   state.push(column.index + "|" + column.parentIndex);
  }
  return state.join("|");
 },
 CreateLayoutMatrixInfo: function(layout) {
  var matrix = [ ];
  var inverseMatrix = { };
  for(var i = 0; i < layout.length; i++) {
   var lastFreeIndex = 0;
   var level = layout[i];
   for(var j = 0; j < level.length; j++) {
    var node = level[j];
    lastFreeIndex = this.FindMatrixFreeCellIndex(matrix, i, lastFreeIndex);
    this.FillMatrixBlock(matrix, inverseMatrix, i, lastFreeIndex, node.rowSpan, node.colSpan, node.columnIndex);
    lastFreeIndex += node.colSpan;
   }
  }
  return { matrix: matrix, inverseMatrix: inverseMatrix };
 },
 FindMatrixFreeCellIndex: function(matrix, rowIndex, lastFreeCell) {
  var row = matrix[rowIndex];
  var result = lastFreeCell;
  if(row) {
   while(!isNaN(row[result]))
    result++;
  } 
  return result;
 },
 FillMatrixBlock: function(matrix, inverseMatrix, rowIndex, cellIndex, rowSpan, colSpan, columnIndex) {
  var rect = {
   top: rowIndex,
   bottom: rowIndex + rowSpan - 1,
   left: cellIndex,
   right: cellIndex + colSpan - 1
  };
  for(var i = rect.top; i <= rect.bottom; i++) {
   while(!matrix[i])
    matrix.push([]);
   for(var j = rect.left; j <= rect.right; j++)
    matrix[i][j] = columnIndex;
  }
  inverseMatrix[columnIndex] = rect;
 },
 IsMatrixRowEqual: function(matrix, i1, i2) {
  var row1 = matrix[i1];
  var row2 = matrix[i2];
  for(var j = 0; j < row1.length; j++) {
   if(row1[j] !== row2[j])
    return false;
  }
  return true;
 }
});
ASPx.GridViewColumnHelper = GridViewColumnHelper;
})();
(function() {
var GridViewColumnMovingHelper = ASPx.CreateClass(null, {
 constructor: function(grid) {
  this.grid = grid;
 },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 GetLayoutHelper: function() { return this.grid.GetLayoutHelper(); },
 GetFixedColumnsHelper: function() { return this.grid.GetFixedColumnsHelper(); },
 GetHeaderLayout: function() { return this.GetLayoutHelper().GetHeaderLayout(); },
 GetEtalonDataRowLayout: function() { return this.GetLayoutHelper().GetEtalonDataRowLayout(); },
 GetDataRowLayout: function(visibleIndex) { return this.GetLayoutHelper().GetDataRowLayout(visibleIndex); },
 GetShowColumnHeaders: function() { return this.GetLayoutHelper().GetShowColumnHeaders(); },
 GetShowFilterRow: function() { return this.GetLayoutHelper().GetShowFilterRow(); },
 GetShowFooterRow: function() { return this.GetLayoutHelper().GetShowFooterRow(); },
 GetShowEditingRow: function() { return this.GetLayoutHelper().GetShowEditingRow(); },
 IsBatchEditMode: function() { return this.GetLayoutHelper().IsBatchEditMode(); },
 GetAllowChangeColumnHierarchy: function() { return this.grid.allowChangeColumnHierarchy; },
 HasFixedColumns: function() { return this.GetColumnHelper().GetAllColumns().filter(function(c) { return c.isFixed; }).length > 0; },
 GetTotalIndentCount: function() { return this.GetLayoutHelper().GetTotalIndentCount(); },
 GetDataItemVisibleIndices: function() { return this.GetLayoutHelper().GetDataItemVisibleIndices(true); },
 GetGroupFooterVisibleIndices: function() { return this.GetLayoutHelper().GetGroupFooterVisibleIndices(); },
 GetBatchOtherPagesChangedRecordVisibleIndices: function() { 
  var indices = this.GetLayoutHelper().GetBatchOtherPagesChangedRecordVisibleIndices();
  return indices.filter(function(visibleIndex) { return !!this.GetRow(visibleIndex, 0, ASPx.GridViewRowType.Data); }.bind(this));
 },
 GetColumnMoveState: function() { return this.GetColumnState(); }, 
 GetColumnWidth: function(columnIndex) { return this.GetLayoutHelper().GetColumnWidth(columnIndex); },
 GetRow: function(visibleIndex, levelIndex, rowType) { return this.GetLayoutHelper().GetRow(visibleIndex, levelIndex, rowType); },
 GetCell: function(visibleIndex, columnIndex, rowType) { return this.GetLayoutHelper().GetCell(visibleIndex, columnIndex, rowType); },
 FindColumn: function(columnIndex) { return this.GetColumnHelper().FindColumn(columnIndex); },
 GetVisibleColumnIndices: function(isDataRowLayout) { return this.GetColumnHelper().GetVisibleColumnIndices(isDataRowLayout); },
 GetLayoutHeight: function(isHeader) { return this.GetLayoutHelper().GetLayoutHeight(isHeader); },
 GetHasRowTemplate: function(rowType) { return this.GetLayoutHelper().GetHasRowTemplate(rowType); },
 HasCellMerging: function(rowType) { return this.GetLayoutHelper().HasCellMerging(); },
 IsArmatureRowRequired: function() { return this.GetLayoutHelper().IsArmatureRowRequired(); },
 GetArmatureRows: function() { return this.GetLayoutHelper().GetArmatureRows(); },
 GetColumnLayout: function() {
  var columnHelper = this.GetColumnHelper();
  var visibleColumns = columnHelper.GetVisibleColumnIndices(false).map(function(columnIndex) { return columnHelper.FindColumn(columnIndex); });
  return visibleColumns.map(function(column) { return { column: column, visibleIndex: column.visibleIndex, parentColumn: columnHelper.FindColumn(column.parentIndex) }; });
 },
 SetColumnLayout: function(layout) {
  var newColumnState = {
   parentIndices: ASPx.Data.ArrayToHash(layout, function(layoutInfo) { return layoutInfo.column.index; }, function(layoutInfo) { return layoutInfo.parentColumn ? layoutInfo.parentColumn.index : -1; }),
   visibleIndices: ASPx.Data.ArrayToHash(layout, function(layoutInfo) { return layoutInfo.column.index; }, function(layoutInfo) { return layoutInfo.visibleIndex; })
  };
  var moveInfo = this.CalculateMoveInfoCore(function() { this.ApplyColumnState(newColumnState); }.bind(this));
  this.MoveColumnCore(moveInfo);
 },
 MoveColumn: function(sourceIndex, targetIndex, direction, moveToGroup, moveFromGroup) {
  var source = this.FindColumn(sourceIndex);
  var target = this.FindColumn(targetIndex);
  var moveInfo = this.CalculateMoveInfo(source, target, direction, moveToGroup, moveFromGroup);
  if(moveInfo)
   this.MoveColumnCore(moveInfo);
  return !!moveInfo;
 },
 MoveColumnCore: function(moveInfo) {
  var cellMap = this.GetCellMap();
  this.RemoveBandColumnCells();
  this.ValidateRows(moveInfo.layoutHeight);
  this.RemoveArmatureCells();
  this.ApplyColumnState(moveInfo.stateDiff);
  this.RearrangeCells(cellMap);
  this.UpdateBorders();
  this.RecreateArmatureCells();
  if(this.GetAllowChangeColumnHierarchy()) {
   this.GetLayoutHelper().UpdateStretchedRowsColSpan();
   this.UpdateIndentCellsRowSpan();
  }
 },
 CalculateMoveInfo: function(source, target, direction, toGroup, fromGroup) {
  if(!source || !source.visible || !target || toGroup || fromGroup)
   return null;
  var allowHierarchy = this.GetAllowChangeColumnHierarchy();
  if(!allowHierarchy && (direction === ASPxClientGridColumnMovingTargetPosition.Top || direction === ASPxClientGridColumnMovingTargetPosition.Bottom))
   return null;
  return this.CalculateMoveInfoCore(function() { this.DoUserMoveColumn(source, target, direction, allowHierarchy); }.bind(this));
 },
 CalculateMoveInfoCore: function(moveAction) { 
  this.NormalizeColumnVisibleIndices();
  var oldColumnState = this.GetColumnState();
  var oldHeight = { header: this.GetLayoutHeight(true), data: this.GetLayoutHeight() };
  moveAction();
  this.NormalizeColumnVisibleIndices();
  var columnStateDiff = this.CalcColumnStateDiff(oldColumnState, this.GetColumnState());
  var layoutHeight = { headerOld: oldHeight.header, dataOld: oldHeight.data, headerNew: this.GetLayoutHeight(true), dataNew: this.GetLayoutHeight() };
  this.ApplyColumnState(oldColumnState); 
  return { stateDiff: columnStateDiff, layoutHeight: layoutHeight };
 },
 DoUserMoveColumn: function(source, target, direction, allowHierarchyMove) {
  if(allowHierarchyMove)
   this.MoveColumnHierarchically(source, target, direction);
  if(direction === ASPxClientGridColumnMovingTargetPosition.Left || direction === ASPxClientGridColumnMovingTargetPosition.Right)
   this.MoveColumnHorizontally(source, target, direction);
 },
 MoveColumnHierarchically: function(source, target, direction) {
  var columnHelper = this.GetColumnHelper();
  var sourceChildColumns = columnHelper.GetVisibleChildColumns(source.index);
  sourceChildColumns.forEach(function(column) {
   column.parentIndex = source.parentIndex;
   columnHelper.Invalidate();
   this.MoveColumnHorizontally(column, source, ASPxClientGridColumnMovingTargetPosition.Left);
  }.aspxBind(this));
  if(direction === ASPxClientGridColumnMovingTargetPosition.Bottom) {
   var targetChildColumns = columnHelper.GetVisibleChildColumns(target.index);
   targetChildColumns.forEach(function(c) { c.parentIndex = source.index; });
  }
  source.parentIndex = direction === ASPxClientGridColumnMovingTargetPosition.Bottom ? target.index : target.parentIndex;
  columnHelper.Invalidate();
  if(direction === ASPxClientGridColumnMovingTargetPosition.Top) {
   this.MoveColumnHorizontally(source, target, ASPxClientGridColumnMovingTargetPosition.Left);
   target.parentIndex = source.index;
   columnHelper.Invalidate();
  }
  this.NormalizeColumnVisibleIndices();
 },
 MoveColumnHorizontally: function(source, target, dir) {
  if(source.parentIndex !== target.parentIndex)
   return;
  var columnHelper = this.GetColumnHelper();
  var orderedSiblings = columnHelper.GetVisibleChildColumns(source.parentIndex).filter(function(c) { return c !== source; });
  var info = this.ResolveFixedColumnHorizontalMoveInfo(orderedSiblings, source, target, dir);
  if(info) {
   target = info.target;
   dir = info.dir;
  }
  var targetIndex = orderedSiblings.indexOf(target);
  if(targetIndex < 0) 
   return;
  if(dir === ASPxClientGridColumnMovingTargetPosition.Right)
   targetIndex++;
  orderedSiblings.splice(targetIndex, 0, source);
  orderedSiblings.forEach(function(c, i) { c.visibleIndex = i; });
  columnHelper.Invalidate();
 },
 ResolveFixedColumnHorizontalMoveInfo: function(orderedSiblings, source, target, dir) {
  var columnHelper = this.GetColumnHelper();
  var fixedColumns = orderedSiblings.filter(function(c) { return columnHelper.IsColumnFixed(c.index); }.bind(this));
  var unfixedColumns = orderedSiblings.filter(function(c) { return !columnHelper.IsColumnFixed(c.index); }.bind(this));
  if(fixedColumns.length === 0)
   return null;
  var lastFixedColumn = fixedColumns.length > 0 ? fixedColumns[fixedColumns.length - 1] : null;
  var firstUnfixedColumn = unfixedColumns.length > 0 ? unfixedColumns[0] : null;
  var isSourceFixed = columnHelper.IsColumnFixed(source.index);
  var isTargetFixed = columnHelper.IsColumnFixed(target.index);
  if(isSourceFixed && !isTargetFixed) {
   target = lastFixedColumn;
   dir = ASPxClientGridColumnMovingTargetPosition.Right;
  } else if(!isSourceFixed && isTargetFixed) {
   target = firstUnfixedColumn;
   dir = ASPxClientGridColumnMovingTargetPosition.Left;
  }
  return { target: target, dir: dir };
 },
 NormalizeColumnVisibleIndices: function() {
  var columnHelper = this.GetColumnHelper();
  var indices = this.GetVisibleColumnIndices();
  indices.push(-1); 
  for(var i = 0; i < indices.length; i++)
   columnHelper.GetVisibleChildColumns(indices[i]).forEach(function(c, index) { c.visibleIndex = index; });
  columnHelper.Invalidate();
 },
 GetCellMap: function() {
  var cellMap = { };
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { 
   if(!cellMap[rowType]) cellMap[rowType] = { };
   if(!cellMap[rowType][visibleIndex]) cellMap[rowType][visibleIndex] = { };
   cellMap[rowType][visibleIndex] = this.GetLayoutMap(visibleIndex, rowType);
  }.bind(this));
  return cellMap;
 },
 GetLayoutMap: function(visibleIndex, rowType) {
  var columnIndices = this.GetVisibleColumnIndices(rowType !== ASPx.GridViewRowType.Header);
  return ASPx.Data.ArrayToHash(columnIndices,  function(i) { return i; }, function(i) { return this.GetCell(visibleIndex, i, rowType); }.bind(this));
 },
 ValidateRows: function(layoutHeight) {
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { this.ValidateRowsCore(visibleIndex, rowType, layoutHeight); }.bind(this));
 },
 ValidateRowsCore: function(visibleIndex, rowType, layoutHeight) {
  var oldHeight = rowType === ASPx.GridViewRowType.Header ? layoutHeight.headerOld : layoutHeight.dataOld;
  var newHeight = rowType === ASPx.GridViewRowType.Header ? layoutHeight.headerNew : layoutHeight.dataNew;
  var addCount = newHeight - oldHeight;
  var removeCount = addCount * -1;
  for(var i = 0; i < removeCount; i++) {
   var levelIndex = oldHeight - i - 1;
   ASPx.RemoveElement(this.GetRow(visibleIndex, levelIndex, rowType));
  }
  var firstRow = this.GetRow(visibleIndex, 0, rowType);
  var lastRow = this.GetRow(visibleIndex, oldHeight - 1, rowType);
  var minHeight = Math.min(oldHeight, newHeight);
  var layoutRows = ASPx.Data.Range(minHeight).map(function(i) { return this.GetRow(visibleIndex, i, rowType); }.bind(this));
  var prevRow = lastRow;
  for(var i = 0; i < addCount; i++) {
   var levelIndex = oldHeight + i;
   var row = firstRow.cloneNode();
   this.PrepareClonnedRow(firstRow, row, visibleIndex, levelIndex, rowType);
   ASPx.InsertElementAfter(row, prevRow);
   layoutRows.push(row);
   prevRow = row;
  }
  if(rowType != ASPx.GridViewRowType.Header)
   layoutRows.forEach(function(row, i) { row.id = this.UpdateRowID(row.id, newHeight > 1, i, rowType); }.bind(this));
  this.UpdateBatchEditPreviewChanges(layoutRows);
 },
 PrepareClonnedRow: function(row, cloneRow, visibleIndex, levelIndex, rowType) {
  cloneRow.id = this.UpdateRowID(cloneRow.id, true, levelIndex, rowType);
  this.GetLayoutHelper().CopyIndentCells(row, cloneRow, visibleIndex, levelIndex, rowType);
  if(ASPx.IsExists(row.initialClassName)) 
   cloneRow.initialClassName = row.initialClassName;
  if(!ASPx.IsExists(row.initialCssText))
   cloneRow.initialCssText = row.initialCssText;
 },
 UpdateBatchEditPreviewChanges: function(layoutRows) {
  var grid = this.grid;
  var helper = this.IsBatchEditMode() && grid.GetBatchEditHelper && grid.GetBatchEditHelper(); 
  if(helper)
   helper.UpdateChangesPreviewOnHierarchyChange(layoutRows);
 },
 RearrangeCells: function(cellMap) {
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { this.RearrangeCellsCore(visibleIndex, rowType, cellMap[rowType][visibleIndex]); }.bind(this));
 },
 RearrangeCellsCore: function(visibleIndex, rowType, cellMap) {
  var layout = rowType === ASPx.GridViewRowType.Header ? this.GetHeaderLayout() : this.GetEtalonDataRowLayout();
  if(rowType === ASPx.GridViewRowType.Data)
   layout = this.GetDataRowLayout(visibleIndex);
  var layoutHelper = this.GetLayoutHelper();
  for(var i = 0; i < layout.length; i++) {
   var indentCellCount = layoutHelper.GetIndentCellCount(visibleIndex, i, rowType);
   var row = this.GetRow(visibleIndex, i, rowType);
   var targetElement = row.insertCell(indentCellCount);
   var level = layout[i];
   for(var j = 0; j < level.length; j++) {
    var node = level[j];
    var cell = cellMap[node.columnIndex];
    if(node.column.isBand && !ASPx.IsValidElement(cell))
     cell = this.CreateBandColumnCell();
    if(!this.HasCellMerging() || rowType !== ASPx.GridViewRowType.Data) {
     ASPx.Attr.ChangeCellSpanCount(cell, node.colSpan, true);
     ASPx.Attr.ChangeCellSpanCount(cell, node.rowSpan);
    }
    row.insertBefore(cell, targetElement);
   }
   ASPx.RemoveElement(targetElement);
  }
 },
 RemoveBandColumnCells: function() {
  this.FindBandColumnCells(true).forEach(function(cell) { ASPx.RemoveElement(cell); });
 },
 FindBandColumnCells: function(excludeHeader) {
  var columnIndices = this.GetVisibleColumnIndices(true).filter(function(columnIndex) { return this.FindColumn(columnIndex).isBand; }.bind(this));
  if(columnIndices.length === 0)
   return [ ];
  var cells = [ ];
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { 
   if(rowType !== ASPx.GridViewRowType.Header)
    cells = cells.concat(columnIndices.map(function(columnIndex) { return this.GetCell(visibleIndex, columnIndex, rowType); }.bind(this)));
  }.bind(this));
  return cells;
 },
 CreateBandColumnCell: function() {
  return ASPx.CreateHtmlElement("TD", { className: ASPx.GridViewConsts.GridViewMarkerCssClass });
 },
 UpdateBorders: function() {
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { this.UpdateBordersCore(visibleIndex, rowType); }.bind(this));
  if(this.grid.processBottomBorders)
   this.UpdateBottomBorders();
 },
 UpdateBordersCore: function(visibleIndex, rowType) {
  var columnHelper = this.GetColumnHelper();
  var columnIndices = this.GetVisibleColumnIndices(rowType !== ASPx.GridViewRowType.Header);
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var hasRightBorder = columnHelper.IsColumnInRightTreeLine(columnIndex, rowType === ASPx.GridViewRowType.Header);
   var cell = this.GetCell(visibleIndex, columnIndex, rowType);
   ASPx.RemoveClassNameFromElement(cell, ASPx.GridViewConsts.RemoveRightBorderClassName);
   if(hasRightBorder)
    ASPx.AddClassNameToElement(cell, ASPx.GridViewConsts.RemoveRightBorderClassName);
   this.grid.ChangeCellInitialClass(cell, ASPx.GridViewConsts.RemoveRightBorderClassName, hasRightBorder);
  }
 },
 UpdateBottomBorders: function() {
  var info = this.GetLastVisibleRowInfo();
  if(!info)
   return;
  var columnIndices = this.GetVisibleColumnIndices(true);
  var leafColumnIndices = this.GetColumnHelper().GetDataRowLeafs().map(function(node) { return node.columnIndex; });
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var cell = this.GetCell(info.visibleIndex, columnIndex, info.rowType);
   var borderWidth = leafColumnIndices.indexOf(columnIndex) == -1 ? 1 : 0;
   if(cell)
    ASPx.SetStyles(cell, { borderBottomWidth: borderWidth + "px" });
  }
 },
 GetLastVisibleRowInfo: function() {
  var info = null;
  if(this.GetShowEditingRow())
   info = this.GetLastVisibleRowInfoCore(-1, ASPx.GridViewRowType.InlineEdit);
  if(!info && this.GetShowFooterRow() && !this.GetHasRowTemplate(ASPx.GridViewRowType.Footer))
   info = this.GetLastVisibleRowInfoCore(-1, ASPx.GridViewRowType.Footer);
  if(!info && !this.GetHasRowTemplate(ASPx.GridViewRowType.Data)) {
   var visibleIndices = this.GetDataItemVisibleIndices();
   info = this.GetLastVisibleRowInfoCore(visibleIndices[visibleIndices.length - 1], ASPx.GridViewRowType.Data);
  }
  if(!info && !this.GetHasRowTemplate(ASPx.GridViewRowType.GroupFooter)) {
   var groupFooterVisibleIndices = this.GetGroupFooterVisibleIndices();
   info = this.GetLastVisibleRowInfoCore(groupFooterVisibleIndices[groupFooterVisibleIndices.length - 1], ASPx.GridViewRowType.GroupFooter);
  }
  return info;
 },
 GetLastVisibleRowInfoCore: function(visibleIndex, rowType) {
  var tables = this.GetLayoutHelper().GetAllTables();
  var table = tables[tables.length - 1];
  var layoutLevel = this.GetColumnHelper().GetDataRowLayout().length - 1;
  var row = this.GetRow(visibleIndex, layoutLevel, rowType);
  if(row === table.rows[table.rows.length - 1])
   return { visibleIndex: visibleIndex, rowType: rowType };
  return null;
 },
 UpdateIndentCellsRowSpan: function() {
  this.ExecuteActionForAllNoStretchedRows(function(visibleIndex, rowType) { this.GetLayoutHelper().UpdateIndentCellRowSpan(visibleIndex, rowType); }.bind(this));
 },
 ExecuteActionForAllNoStretchedRows: function(action) {
  if(this.GetShowColumnHeaders())
   action(-1, ASPx.GridViewRowType.Header);
  if(this.GetShowFilterRow() && !this.GetHasRowTemplate(ASPx.GridViewRowType.Filter))
   action(-1, ASPx.GridViewRowType.Filter);
  if(this.GetShowEditingRow())
   action(-1, ASPx.GridViewRowType.InlineEdit);
  if(this.IsBatchEditMode())
   action(-1, ASPx.GridViewRowType.BatchEtalon);
  if(this.GetShowFooterRow() && !this.GetHasRowTemplate(ASPx.GridViewRowType.Footer))
   action(-1, ASPx.GridViewRowType.Footer);
  if(!this.GetHasRowTemplate(ASPx.GridViewRowType.Data)) {
   var visibleIndices = this.GetDataItemVisibleIndices();
   if(this.IsBatchEditMode())
    visibleIndices = visibleIndices.concat(this.GetBatchOtherPagesChangedRecordVisibleIndices());
   for(var i = 0; i < visibleIndices.length; i++)
    action(visibleIndices[i], ASPx.GridViewRowType.Data);
  }
  if(!this.GetHasRowTemplate(ASPx.GridViewRowType.GroupFooter)) {
   var groupFooterVisibleIndices = this.GetGroupFooterVisibleIndices();
   for(var i = 0; i < groupFooterVisibleIndices.length; i++)
    action(groupFooterVisibleIndices[i], ASPx.GridViewRowType.GroupFooter);
  }
 },
 RemoveArmatureCells: function() {
  if(!this.IsArmatureRowRequired()) return;
  var leafs = this.GetColumnHelper().GetHeaderLeafs();
  var removeCellIndices = ASPx.Data.Range(leafs.length, this.GetTotalIndentCount()).reverse();
  this.GetArmatureRows().forEach(function(row) {
   removeCellIndices.forEach(function(cellIndex) { ASPx.RemoveElement(row.cells[cellIndex]); }); 
  });
 },
 RecreateArmatureCells: function() {
  if(!this.IsArmatureRowRequired()) return;
  var leafs = this.GetColumnHelper().GetHeaderLeafs();
  var rows = this.GetArmatureRows();
  for(var i = 0; i < rows.length; i++) {
   var row = rows[i];
   for(var j = 0; j < leafs.length; j++) {
    var leafNode = leafs[j];
    var cellIndex = j + this.GetTotalIndentCount();
    var cell = row.insertCell(cellIndex);
    this.PrepareArmatureCell(cell, leafNode);
   }
  }
 },
 PrepareArmatureCell: function(cell, leafNode) {
  cell.style.width = this.GetColumnWidth(leafNode.columnIndex);
 },
 GetColumnState: function() {
  var allColumns = this.GetColumnHelper().GetAllColumns();
  return {
   parentIndices: ASPx.Data.ArrayToHash(allColumns, function(c) { return c.index; }, function(c) { return c.parentIndex; }),
   visibleIndices: ASPx.Data.ArrayToHash(allColumns, function(c) { return c.index; }, function(c) { return c.visibleIndex; })
  };
 },
 ApplyColumnState: function(moveInfo) {
  for(var columnIndex in moveInfo.parentIndices) {
   if(!moveInfo.parentIndices.hasOwnProperty(columnIndex)) continue;
   this.FindColumn(columnIndex).parentIndex = moveInfo.parentIndices[columnIndex];
  }
  for(var columnIndex in moveInfo.visibleIndices) {
   if(!moveInfo.visibleIndices.hasOwnProperty(columnIndex)) continue;
   this.FindColumn(columnIndex).visibleIndex = moveInfo.visibleIndices[columnIndex];
  }
  this.GetColumnHelper().Invalidate();
 },
 CalcColumnStateDiff: function(oldState, newState) {
  var diffState = { parentIndices: { }, visibleIndices: { } };
  for(var columnIndex in oldState.parentIndices) { 
   if(!oldState.parentIndices.hasOwnProperty(columnIndex)) continue;
   var oldParentIndex = oldState.parentIndices[columnIndex];
   var newParentIndex = newState.parentIndices[columnIndex];
   if(oldParentIndex !== newParentIndex)
    diffState.parentIndices[columnIndex] = newParentIndex;
  }
  for(var columnIndex in oldState.visibleIndices) { 
   if(!oldState.visibleIndices.hasOwnProperty(columnIndex)) continue;
   var oldVisibleIndex = oldState.visibleIndices[columnIndex];
   var newVisibleIndex = newState.visibleIndices[columnIndex];
   if(oldVisibleIndex !== newVisibleIndex)
    diffState.visibleIndices[columnIndex] = newVisibleIndex;
  }
  return diffState;
 },
 UpdateRowID: function(id, hasHierarchy, levelIndex, rowType) {
  var id = this.CutHierarchyPart(id);
  if(!hasHierarchy)
   return id;
  if(rowType == ASPx.GridViewRowType.Header) {
   var oldLevelIndex = this._tryGetNumberFromEndOfString(id).value.toString();
   id = id.substr(0, id.lastIndexOf(oldLevelIndex));
   id += levelIndex;
  }
  else
   id += "_" + levelIndex;
  return id;
 },
 CutHierarchyPart: function(id) {
  var info = this._tryGetNumberFromEndOfString(id);
  if(info.success) {
   var hierarchyPart = "_" + info.value;
   var hierarchyPartIndex = id.lastIndexOf(hierarchyPart);
   var requiredHierarchyPartIndex = id.length - hierarchyPart.length;
   if(hierarchyPartIndex === requiredHierarchyPartIndex)
    id = id.substr(0, hierarchyPartIndex);
  }
  return id;
 },
 _tryGetNumberFromEndOfString: function(str) { 
  var value = -1;
  var success = false;
  var n = str.length - 1;
  while(n >= 0 && !isNaN(parseInt(str.substr(n), 10))) {
   value = parseInt(str.substr(n), 10);
   success = true;
   n--;
  }
  return { success: success, value: value };
 }
});
ASPx.GridViewColumnMovingHelper = GridViewColumnMovingHelper;
})();
(function() {
var GridCustDialogPageType = { Sorting: 0, Grouping: 1, Filtering: 2, FieldChooser: 3 };
var GridCustDialogPageIDs = { 0: "SortingPage", 1: "GroupingPage", 2: "FilteringPage", 3: "FieldChooserPage" };
var GridCustDialogBrickType = { Drag: 0, Caption: 1, Sort: 2, SortOrder: 3, Group: 4, Visibility: 5, Remove: 6, ClearFilter: 7, FilterExpand: 8 };
var GridViewCustDialogHelper = ASPx.CreateClass(null, {
 AnimationViewPortClassName: "dxgvCD_CAWP", 
 AnimationPageContainerClassName: "dxgvCD_CAPC",
 DragAreaClassName: "dxgvCustDialogDragArea",
 ListAreaClassName: "dxgvCustDialogListArea",
 ListAreaItemsWrapperClassName: "dxgvCD_LAIW",
 ColumnItemClassName: "dxgvCustDialogColumnItem",
 DragAreaWrapperClassName: "dxgvCD_DAW",
 DragAreaEmptyTextContainerClassName: "dxgvCD_DAETC",
 DragAreaExpandButtonClassName: "dxgvCD_DAEB",
 DragAreaExpandButtonBlickRippleClassName: "dxgvDAEBBR",
 DragAreaExpandImageClassName: "dxgvCD_DAEI",
 DragAreaCollapseImageClassName: "dxgvCD_DACI",
 FilterRowContainerClassName: "dxgvCD_FR",
 UniqueFilterContainerClassName: "dxgvCD_UF",
 TabSelectorClassName: "dxgvCD_TS",
 TabSelectorLeftShadowElementClassName: "dxgvCD_TSLS",
 TabSelectorRightShadowElementClassName: "dxgvCD_TSRS",
 TabSelectorButtonsWrapperClassName: "dxgvCD_TSBW",
 DialogFilterRowMenuClassName: "dxgvCD_FRM",
 DialogColumnChooserPageSelectedClassName: "dxgvCD_ColumnChooserPage",
 DialogFilterPageSelectedClassName: "dxgvCD_FilterPage",
 DialogSortPageSelectedClassName: "dxgvCD_SortPage",
 DialogGroupPageSelectedClassName: "dxgvCD_GroupPage",
 DialogTabControlID: "DXCDPageControl",
 CustDialogContentID: "DXCDContent",
 CustDialogFilterEditorsContainerID: "DXCDFREC",
 EtalonColumnItemID: "DXCDEtalonColumnItem",
 EtalonFilterItemID: "DXCDEtalonFilterItem",
 DraggingItemClassName: "DXCDDraggingItem",
 UnqiueFilterListBoxVisibleClassName: "dxgvCD_UFLBV",
 ExpandedFilterColumnItemClassName: "dxgvCD_EFCI",
 ColumnItemBrick_ActiveClassName: "dxgvCD_CIPA",
 ColumnItemBrick_DisabledClassName: "dxgvCD_CIPD",
 TabControlColumnChooserTabName: "ColumnChooser",
 TabControlFilterTabName: "Filter",
 TabControlSortTabName: "Sort" ,
 TabControlGroupTabName: "Group",
 DisabledBrickTypes: [ 
  GridCustDialogBrickType.Drag, 
  GridCustDialogBrickType.Sort, 
  GridCustDialogBrickType.Group, 
  GridCustDialogBrickType.Visibility, 
  GridCustDialogBrickType.Remove, 
  GridCustDialogBrickType.ClearFilter, 
  GridCustDialogBrickType.FilterExpand 
 ],
 ActionBrickTypes: [
  GridCustDialogBrickType.Drag, 
  GridCustDialogBrickType.Sort, 
  GridCustDialogBrickType.SortOrder, 
  GridCustDialogBrickType.Group, 
  GridCustDialogBrickType.Visibility, 
  GridCustDialogBrickType.Remove, 
  GridCustDialogBrickType.FilterExpand, 
  GridCustDialogBrickType.ClearFilter 
 ],
 CheckBoxBrickTypes: [
  GridCustDialogBrickType.Sort, 
  GridCustDialogBrickType.SortOrder, 
  GridCustDialogBrickType.Group, 
  GridCustDialogBrickType.Visibility, 
  GridCustDialogBrickType.FilterExpand
 ],
 CheckBoxImageStateOrderedBrickTypes: [ 
  GridCustDialogBrickType.Sort, 
  GridCustDialogBrickType.SortOrder,
  GridCustDialogBrickType.Group,
  GridCustDialogBrickType.Visibility,
  GridCustDialogBrickType.FilterExpand
 ],
 EtalonColumnItemMap: [ 
  GridCustDialogBrickType.Drag, 
  GridCustDialogBrickType.Caption, 
  GridCustDialogBrickType.Sort, 
  GridCustDialogBrickType.SortOrder, 
  GridCustDialogBrickType.Group, 
  GridCustDialogBrickType.Visibility, 
  GridCustDialogBrickType.Remove, 
  GridCustDialogBrickType.FilterExpand, 
  GridCustDialogBrickType.ClearFilter 
 ],
 constructor: function(grid) {
  this.grid = grid;
  this.initialColumnState = null;
  this.checkBoxCollections = { };
  this.pages = [ ];
  this.selectedPageType = this.GetInitialSelectedPageType();
  this.dragHelper = new GridViewCustDialogColumnDragHelper(this);
 },
 GetColumnHelper: function() { return this.grid.GetColumnHelper(); },
 GetFilterHelper: function() { return this.grid.GetFilterHelper(); },
 GetCustDialogWindow: function() { return this.grid.GetCustDialogWindow(); },
 GetFilterRowMenu: function() { return this.grid.GetFilterRowMenu(); },
 GetApplyButton: function() { return this.grid.GetCustDialogApplyButton(); },
 GetCloseButton: function() { return this.grid.GetCustDialogCloseButton(); },
 GetTabControl: function() { return ASPx.GetControlCollection().GetByName(this.grid.name + "_" + ASPx.GridViewConsts.CustDialogWindowID + "_" + this.DialogTabControlID); }, 
 IsDialogVisible: function() { return this.GetCustDialogWindow().IsVisible(); },
 GetAutoFilterEditor: function(columnIndex) { return this.grid.GetAutoFilterEditor(columnIndex); },
 GetAutoFilterEditorValue: function(columnIndex) {
  var editor = this.GetAutoFilterEditor(columnIndex);
  return editor ? editor.GetValue() : null;
 },
 GetDialogProperties: function() { return this.grid.custDialogProp; },
 GetVisiblePageTypes: function() { return this.GetDialogProperties().visiblePageTypes; },
 GetCheckBoxImageProperties: function(brickType) { return this.GetDialogProperties().checkBoxProp[this.CheckBoxImageStateOrderedBrickTypes.indexOf(brickType)]; },
 GetCheckBoxCollection: function(pageType) {
  if(!this.checkBoxCollections[pageType])
   this.checkBoxCollections[pageType] = new ASPx.CheckBoxInternalCollection(this.GetCheckBoxImageProperties(pageType), false, false, new CustDialogCheckableElementHelper()); 
  return this.checkBoxCollections[pageType];
 },
 CanShowFilterRowMenu: function(columnIndex) {
  return this.GetFilterRowMenu() && this.GetDialogProperties().filterRowMenuColumnIndices.indexOf(columnIndex) > -1;
 },
 GetCustDialogChildElement: function(partialID) { return this.grid.GetChildElement(ASPx.GridViewConsts.CustDialogWindowID + "_" + partialID); },
 GetDialogModalElement: function() { return this.GetCustDialogWindow().GetModalWrapperElement(-1); },
 GetDialogScrollableElement: function() { return this.GetDialogModalElement(); },
 GetDialogContentElement: function() { return this.GetCustDialogChildElement(this.CustDialogContentID); },
 GetFilterEditorsContainer: function() { return this.grid.GetChildElement(this.CustDialogFilterEditorsContainerID); },
 GetTabSelector: function() { return ASPx.GetNodeByClassName(this.GetDialogScrollableElement(), this.TabSelectorClassName); },
 GetTabSelectorButtonsWrapper: function() { return ASPx.GetChildByClassName(this.GetTabSelector(), this.TabSelectorButtonsWrapperClassName); },
 GetTabSelectorLeftShadow: function() { return ASPx.GetChildByClassName(this.GetTabSelector(), this.TabSelectorLeftShadowElementClassName); },
 GetTabSelectorRightShadow: function() { return ASPx.GetChildByClassName(this.GetTabSelector(), this.TabSelectorRightShadowElementClassName); },
 GetEtalonColumnItem: function() { return this.GetCustDialogChildElement(this.EtalonColumnItemID); },
 GetEtalonFilterItem: function() { return this.GetCustDialogChildElement(this.EtalonFilterItemID); },
 GetCustDialogPageElement: function(pageType) { 
  var page = this.GetPage(pageType);
  return page ? page.GetMainElement() : null;
 },
 GetColumnState: function(columnIndex, isInitial) { return isInitial ? this.initialColumnState[columnIndex] : this.currentColumnState[columnIndex]; },
 GetAllColumns: function() { return this.GetColumnHelper().GetAllColumns().filter(function(c) { return c.showInCustomizationForm; }); },
 FindColumn: function(columnIndex) { return this.GetColumnHelper().FindColumn(columnIndex); },
 GetAllColumnsState: function() { return this.GetAllColumns().map(function(c) { return this.GetColumnState(c.index); }.bind(this)); },
 GetDataColumnsState: function() { return this.GetAllColumnsState().filter(function(c) { return this.FindColumn(c.columnIndex).isDataColumn; }.bind(this)); },
 GetSortedColumnsState: function() { return this.GetDataColumnsState().filter(function(c) { return c.sortIndex > -1; }); },
 GetGroupedColumnsState: function() { return this.GetDataColumnsState().filter(function(c) { return c.groupIndex > -1; }); },
 GetOrderedAllColumnsState:  function() { return this.GetAllColumnsState().sort(function(c1, c2) { return c1.visibleIndex - c2.visibleIndex; }); },
 GetOrderedDataColumnsState: function() { return this.GetDataColumnsState().sort(function(c1, c2) { return c1.visibleIndex - c2.visibleIndex; }); },
 GetOrderedSortColumnsState: function() { 
  return this.GetSortedColumnsState().sort(function(c1, c2) {
   if(c1.groupIndex > -1 && c2.groupIndex > -1) 
    return c1.groupIndex - c2.groupIndex;
   if(c1.groupIndex > -1)
     return -1;
   if(c2.groupIndex > -1)
     return 1;
   return c1.sortIndex - c2.sortIndex; 
  }); 
 },
 GetOrderedGroupColumnsState: function() { return this.GetGroupedColumnsState().sort(function(c1, c2) { return c1.groupIndex - c2.groupIndex; }); },
 UpdateColumnsSortGroupState: function() {
  this.GetOrderedSortColumnsState().forEach(function(c, i) { c.sortIndex = i; });
  this.GetOrderedGroupColumnsState().forEach(function(c, i) { c.groupIndex = i; });
 },
 GetColumnItemMap: function(key, columnIndex) { return this.GetColumnItemMapCore(key); },
 GetColumnItemMapCore: function(key) {
  if(!this.columnItemMap)
   this.columnItemMap = this.CreateColumnItemMap();
  return this.columnItemMap[key];
 },
 CreateColumnItemMapKey: function(args) { return args.join("_"); },
 CreateEtalonColumnItemMapKey: function() { return this.CreateColumnItemMapKey([ "etalon" ]); },
 CreatePageAreaMapKey: function(pageType, isDragArea) { return this.CreateColumnItemMapKey([ pageType, isDragArea ? "drag" : "list" ]); },
 CreateColumnItemMap: function() {
  var map = { };
  map[this.CreateEtalonColumnItemMapKey() ] =         this.EtalonColumnItemMap;
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.Sorting, true)] =   [ GridCustDialogBrickType.Drag, GridCustDialogBrickType.Caption, GridCustDialogBrickType.SortOrder, GridCustDialogBrickType.Remove ];
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.Sorting, false)] =  [ GridCustDialogBrickType.Caption, GridCustDialogBrickType.Sort ];
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.Grouping, true)] =  [ GridCustDialogBrickType.Drag, GridCustDialogBrickType.Caption, GridCustDialogBrickType.Remove ];
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.Grouping, false)] = [ GridCustDialogBrickType.Caption, GridCustDialogBrickType.Group ];
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.FieldChooser, true)] = [ GridCustDialogBrickType.Drag, GridCustDialogBrickType.Caption, GridCustDialogBrickType.Visibility ];
  map[this.CreatePageAreaMapKey(GridCustDialogPageType.Filtering, false)] =   [ GridCustDialogBrickType.Caption, GridCustDialogBrickType.ClearFilter, GridCustDialogBrickType.FilterExpand ];
  return map;
 },
 GetPage: function(pageType) { return this.pages[pageType]; },
 EvaluateForAllPages: function(evaluateOnPage) {
  this.EnsurePages();
  for(var pageType in this.pages) {
   if(this.pages.hasOwnProperty(pageType))
    evaluateOnPage.call(this, this.pages[pageType]);
  }
 },
 EnsurePages: function() {
  var pageTypes = this.GetVisiblePageTypes();
  for(var i = 0; i < pageTypes.length; i++) {
   var pageType = pageTypes[i];
   if(!this.GetPage(pageType))
    this.pages[pageType] = this.CreatePage(pageType);
  }
 },
 CreatePage: function(pageType) {
  switch(pageType) {
   case GridCustDialogPageType.Sorting:
    return new CustDialogSortingPage(this);
   case GridCustDialogPageType.Grouping:
    return new CustDialogGroupingPage(this);
   case GridCustDialogPageType.FieldChooser:
    return new CustDialogFieldChooserPage(this);
   case GridCustDialogPageType.Filtering:
    return new CustDialogFilteringPage(this);
  }
  return null;
 },
 ShowSelectedPage: function() {
  this.EnsureActiveTab(this.selectedPageType);
  this.UpdateDialogSelectedPageClass(this.selectedPageType);
  this.EvaluateForAllPages(function(p) { this.ChangePageVisibility(p, false); }.bind(this));
  var page = this.GetPage(this.selectedPageType);
  page.ResetMainElement();
  page.Update();
  this.ChangePageVisibility(page, true);
 },
 UpdateCurrentDialogPage: function() { this.UpdateDialogPage(this.selectedPageType); },
 UpdateDialogPage: function(pageType) {
  var page = this.GetPage(pageType);
  if(page) page.Update();
  this.UpdateApplyButtonEnabledState();
 },
 ChangePageVisibility: function(page, visible) { 
  ASPx.SetElementDisplay(page.GetMainElement(), visible);
 },
 ProcessHeaderFilterCallback: function(html, columnIndex) {
  var page = this.GetPage(GridCustDialogPageType.Filtering);
  return page && page.ProcessHeaderFilterCallback(html, columnIndex);
 },
 ProcessFilterChange: function(columnIndex) {
  this.UpdateApplyButtonEnabledState();
  var page = this.GetPage(GridCustDialogPageType.Filtering);
  if(page && ASPx.IsExists(columnIndex))
   page.ProcessFilterChange(columnIndex);
 },
 ClearHeaderFilterAfterLoadValues: function() {
  var page = this.GetPage(GridCustDialogPageType.Filtering);
  if(page) page.ClearHeaderFilterAfterLoadValues();
 },
 GetInitialSelectedPageType: function() {
  var tabControl = this.GetTabControl();
  if(!tabControl) return -1;
  var activeTab = tabControl.GetActiveTab();
  return activeTab ? this.GetPageTypeByTabName(activeTab.name) : this.GetVisiblePageTypes()[0];
 },
 OnInit: function() {
  this.InitializeCustDialogWindow();
 },
 OnAfterCallback: function() {
  this.InitializeCustDialogWindow();
 },
 InitializeCustDialogWindow: function() {
  var popup = this.GetCustDialogWindow();
  if(popup) {
   popup.PopUp.AddHandler(this.OnDialogWindow_PopUp.bind(this));
   popup.CloseUp.AddHandler(this.OnDialogWindow_CloseUp.bind(this));
   popup.StretchVertically();
  }
 },
 OnBrowserWindowResize: function(e) {
  if(this.IsDialogVisible())
   this.AdjustTabSelector();
 },
 OnDialogWindow_PopUp: function(popup) {
  if(this.GetVisiblePageTypes().length === 0) 
   return;
  this.GetFilterHelper().Reset();
  this.initialColumnState = this.LoadColumnState();
  this.currentColumnState = this.LoadColumnState();
  this.EvaluateForAllPages(function(page) { page.OnPopUp(); });
  var filterPage = this.GetPage(GridCustDialogPageType.Filtering);
  if(filterPage) {
   this.InitializeFilterRowMenu(filterPage);
   this.UpdateFilterRowMenuZIndex(true);
   this.FixGridFilterRowHeight();
  }
  this.EvaluateForAllPages(function(page) { page.Update(); });
  this.ShowSelectedPage();
  this.UpdateApplyButtonEnabledState();
  this.InitializeTabSelector();
  this.AdjustTabSelector();
  this.AssingScrollEvent();
  ASPx.SetStyles(this.GetDialogScrollableElement(), { overflowY: "scroll" });
  this.dragHelper.OnPopUp();
 },
 OnDialogWindow_CloseUp: function(popup) {
  this.RemoveCloseButtonRipple();
  this.EvaluateForAllPages(function(page) { page.OnCloseUp(); });
  var filterPage = this.GetPage(GridCustDialogPageType.Filtering);
  if(filterPage) {
   this.UpdateFilterRowMenuZIndex(false);
   this.RestoreGridFilterRowHeight();
  }
  this.GetFilterHelper().Reset();
  this.dragHelper.OnCloseUp();
  this.pages = [ ];
  this.initialColumnState = null;
  this.currentColumnState = null;
  this.checkBoxCollections = { };
 },
 InitializeFilterRowMenu: function(filterPage) {
  var menu = this.GetFilterRowMenu();
  if(menu && !menu.dxgvCustDialogClickHandlerAssigned) {
   menu.ItemClick.AddHandler(function() { window.setTimeout(filterPage.UpdateFilterRowConditionDisplayText(), 0); });
   menu.dxgvCustDialogClickHandlerAssigned = true;
  }
 },
 FixGridFilterRowHeight: function() {
  var filterRow = this.grid.GetFilterRow();
  if(filterRow)
   ASPx.Attr.ChangeStyleAttribute(filterRow, "height", ASPx.GetClearClientHeight(filterRow) + "px"); 
 },
 RestoreGridFilterRowHeight: function() {
  var filterRow = this.grid.GetFilterRow();
  if(filterRow)
   ASPx.Attr.RestoreStyleAttribute(filterRow, "height"); 
 },
 UpdateFilterRowMenuZIndex: function(onShow) {
  var popupMenu = this.GetFilterRowMenu();
  if(!popupMenu) return;
  var popupMenuElement = popupMenu.GetMainElement();
  if(!popupMenu.gvSavedMenuZIndex) {
   popupMenu.gvSavedMenuZIndex = parseInt(ASPx.GetCurrentStyle(popupMenuElement).zIndex);
   popupMenu.gvSavedDialogIndex = parseInt(ASPx.GetCurrentStyle(this.GetDialogModalElement()).zIndex);
  }
  var zIndex = onShow ? popupMenu.gvSavedDialogIndex + 1 : popupMenu.gvSavedMenuZIndex;
  ASPx.SetStyles(popupMenuElement, { zIndex: zIndex });
  var action = onShow ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement; 
  action(popupMenuElement, this.DialogFilterRowMenuClassName);
 },
 LoadColumnState: function() {
  var allColumns = this.GetColumnHelper().GetAllColumns();
  var orderedColumns = allColumns.sort(function(c1, c2) {
   if(c1.visible !== c2.visible)
    return c1.visible ? -1 : 1;
   return c1.visibleIndex - c2.visibleIndex;
  });
  return ASPx.Data.ArrayToHash(
   allColumns,
   function(c) { return c.index; },
   function(c) { 
    return {
     columnIndex: c.index, 
     sortIndex: c.sortIndex, 
     sortOrder: c.sortOrder, 
     groupIndex: c.groupIndex, 
     parentColumnIndex: this.GetColumnHelper().GetParentColumnIndex(c.index),
     visible: c.visible, 
     visibleIndex: orderedColumns.indexOf(c),
     filterEditorValue: this.GetAutoFilterEditorValue(c.index)
    };
   }.bind(this)
  );
 },
 IsStateChanged: function() {
  for(var columnIndex in this.currentColumnState) {
   if(!this.currentColumnState.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   var initialState = this.initialColumnState[columnIndex];
   var currentState = this.currentColumnState[columnIndex];
   if(this.IsFilterStateChanged(columnIndex))
    return true;
   if(initialState.sortIndex !== currentState.sortIndex)
    return true;
   if(initialState.sortOrder !== currentState.sortOrder)
    return true;
   if(initialState.groupIndex !== currentState.groupIndex)
    return true;
   if(initialState.visibleIndex !== currentState.visibleIndex)
    return true;
   if(initialState.visible !== currentState.visible)
    return true;
  }
  return false;
 },
 IsFilterStateChanged: function(columnIndex) {
  var filterHelper = this.GetFilterHelper();
  var page = this.GetPage(GridCustDialogPageType.Filtering);
  if(!filterHelper || !page) 
   return false;
  if(page.GetColumnIndicesToPostponedClearFilter().indexOf(columnIndex) > -1)
   return true;  
  if(page.IsUniqueFilterValuesLoaded(columnIndex) && filterHelper.IsHeaderFilterChanged(columnIndex))
   return true;
  if(filterHelper.IsColumnAutoFilterChanged(columnIndex))
   return true;
  return false;
 },
 ApplyChanges: function() {
  var filterHelper = this.GetFilterHelper();
  var sortState = { };
  var groupState = { };
  var visibleState = { };
  var uniqueFilterState = { };
  var filterPage = this.GetPage(GridCustDialogPageType.Filtering);
  for(var columnIndex in this.currentColumnState) {
   if(!this.currentColumnState.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   var state = this.currentColumnState[columnIndex];
   sortState[columnIndex] = [ state.sortIndex, state.sortOrder ];
   groupState[columnIndex] = state.groupIndex;
   visibleState[columnIndex] = [ state.visibleIndex, state.visible ];
   if(filterHelper.IsHeaderFilterChanged(columnIndex))
    uniqueFilterState[columnIndex] =  ASPx.Json.ToJson(filterHelper.GetHeaderFilterCallbackState(columnIndex)).toString();
  }
  var filterRowState = filterHelper.SerializeChangedAutoFilterValues().map(function(v) { return v.toString(); });
  var state = { sort: sortState, group: groupState, visible: visibleState, filterRow: filterRowState, uniqueFilter: uniqueFilterState, 
   columnIndicesToClearFilter: !!filterPage ? filterPage.GetColumnIndicesToPostponedClearFilter() : [ ]  
  };
  this.grid.GetCallbackHelper().SendRequest([ ASPxClientGridViewCallbackCommand.ApplyCustomizationDialogChanges, ASPx.Json.ToJson(state) ]);
  this.GetCustDialogWindow().Hide();
 },
 CancelChanges: function() {
  if(!this.initialColumnState) return;
  var filterPage = this.GetPage(GridCustDialogPageType.Filtering);
  if(filterPage) {
   var columnIndices = filterPage.GetListAreaColumnIndices();
   for(var i = 0; i < columnIndices.length; i++) {
    var columnIndex = columnIndices[i];
    var filterEditor = this.GetAutoFilterEditor(columnIndex);
    var initialFilterValue = this.GetColumnState(columnIndex, true).filterEditorValue;
    if(filterEditor)
     filterEditor.SetValue(initialFilterValue);
   }
  }
  this.GetFilterHelper().OnChange();
  this.GetCustDialogWindow().Hide();
 },
 InitializeTabSelector: function() {
  var tabSelector = this.GetTabSelector();
  if(!tabSelector.initialized) {
   this.InitializeTabSelectorMouseScroll();
   this.InitializeTabControl();
   this.InitializeTebSelectorShadowEvents();
   tabSelector.initialized = true;
  }
 },
 InitializeTabSelectorMouseScroll: function() {
  var getScrollElement = this.GetTabSelectorButtonsWrapper.bind(this);
  ASPx.MouseScroller.Create(getScrollElement, getScrollElement, getScrollElement, function() { return this.requirePreventTabSelectorMouseScroll; }.bind(this));
 },
 InitializeTebSelectorShadowEvents: function() {
  ASPx.Evt.AttachEventToElement(this.GetTabSelectorLeftShadow(), "click", this.OnTabSelectorShadowClick.bind(this));
  ASPx.Evt.AttachEventToElement(this.GetTabSelectorRightShadow(), "click", this.OnTabSelectorShadowClick.bind(this));
 },
 OnTabSelectorShadowClick: function(e) {
  var x = ASPx.Evt.GetEventX(e);
  var y = ASPx.Evt.GetEventY(e);
  var tabControl = this.GetTabControl();
  var count = tabControl.GetTabCount();
  for(var i = 0; i < count; i++) {
   var r = tabControl.GetTabElement(i).getBoundingClientRect();
   if((x >= r.left) && (x <= r.right) && (y >= r.top) && (y <= r.bottom)) {
    tabControl.SetActiveTabIndex(i);
    return;
   }
  }
 },
 AdjustTabSelector: function() {
  var tabSelector = this.GetTabSelector();
  ASPx.SetStyles(tabSelector, { width: 1 });
  ASPx.SetStyles(tabSelector, { width: tabSelector.parentNode.offsetWidth });
  var wrapper = this.GetTabSelectorButtonsWrapper();
  var tabControlElement = this.GetTabControl().GetMainElement();
  var tabControlWidth = ASPx.GetClearClientWidth(tabControlElement) - ASPx.GetLeftRightMargins(this.GetActiveTabElement());
  var containerWidth = ASPx.GetClearClientWidth(wrapper);
  var excess = containerWidth - tabControlWidth;
  var padding = excess > 0 ? Math.floor(excess / 2) : 0;
  var styles = this.grid.rtl ? { paddingRight: padding } : { paddingLeft: padding };
  ASPx.SetStyles(tabControlElement, styles);
  this.requirePreventTabSelectorMouseScroll = excess > 0;
 },
 InitializeTabControl: function() {
  var tabControl = this.GetTabControl();
  tabControl.AdjustControl();
  tabControl.ActiveTabChanged.AddHandler(this.OnActiveTabChanged, this);
 },
 GetActiveTabElement: function() {
  var tabControl = this.GetTabControl();
  return tabControl.GetTabElement(tabControl.GetActiveTabIndex(), true);
 },
 OnActiveTabChanged: function(s, e) {
  this.SlideToShowPage(this.GetPageTypeByTabName(e.tab.name));
 },
 GetPageTypeByTabName: function(name) {
  switch(name) {
   case this.TabControlColumnChooserTabName : return GridCustDialogPageType.FieldChooser;
   case this.TabControlFilterTabName : return GridCustDialogPageType.Filtering;
   case this.TabControlSortTabName : return GridCustDialogPageType.Sorting;
   case this.TabControlGroupTabName : return GridCustDialogPageType.Grouping;
  }
  return -1;
 },
 GetTabNameByPageType: function(pageType) {
  switch(pageType) {
   case GridCustDialogPageType.FieldChooser : return this.TabControlColumnChooserTabName;
   case GridCustDialogPageType.Filtering : return this.TabControlFilterTabName;
   case GridCustDialogPageType.Sorting : return this.TabControlSortTabName;
   case GridCustDialogPageType.Grouping : return this.TabControlGroupTabName;
  }
  return "";
 },
 SlideToShowPage: function(newSelectedPageType) {
  this.CancelSlideAnimation(); 
  var page = this.GetPage(newSelectedPageType);
  if(page) {
   page.ResetMainElement();
  }
  this.UpdateDialogPage(newSelectedPageType);
  this.PreparePagesToSlideAnimation(newSelectedPageType);
  this.UpdateDialogSelectedPageClass(newSelectedPageType);  
  this.StartSlideAnimation(newSelectedPageType);
  this.selectedPageType = newSelectedPageType;
 },
 CancelSlideAnimation: function() {
  var pageContainer = this.GetDialogContentElement().animationPageContainer;
  if(!pageContainer) return;
  ASPx.AnimationHelper.cancelAnimation(pageContainer);
  this.ClearSlideAnimationElements();
 },
 StartSlideAnimation: function(newSelectedPageType) {
  var to = this.GetSlideAnimationDirection(newSelectedPageType) * this.GetCurrentContentWidth();  
  var options = { to: to, onComplete: function() {  this.OnSlideAnimationComplete(); }.bind(this) };
  ASPx.AnimationHelper.slideTo(this.GetDialogContentElement().animationPageContainer, options);
 },
 EnsureSlideAnimationElements: function() {
  var content = this.GetDialogContentElement();
  if(content.animationViewPot) return;
  var viewPort = document.createElement("DIV");
  viewPort.className = this.AnimationViewPortClassName;
  content.insertBefore(viewPort, content.firstChild);
  var pageContainer = document.createElement("DIV");
  pageContainer.className = this.AnimationPageContainerClassName;
  viewPort.appendChild(pageContainer);
  content.animationViewPot = viewPort;
  content.animationPageContainer = pageContainer;
 },
 PreparePagesToSlideAnimation: function(newSelectedPageType) {
  this.EnsureSlideAnimationElements();
  var content = this.GetDialogContentElement();
  var pageContainer = content.animationPageContainer;
  var viewPort = content.animationViewPot;
  var currentPageElement = this.GetCustDialogPageElement(this.selectedPageType);
  var newPageElement = this.GetCustDialogPageElement(newSelectedPageType);
  var direction = this.GetSlideAnimationDirection(newSelectedPageType);
  var pageElements = direction === -1 ? [currentPageElement, newPageElement] : [newPageElement, currentPageElement];
  var currentWidth = this.GetCurrentContentWidth();
  for(var i = 0; i < pageElements.length; i++) {
   var pageElement = pageElements[i];
   pageContainer.appendChild(pageElement);
   var pageLeft = i * currentWidth;
   var pageWidth = currentWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(pageElement);
   ASPx.SetStyles(pageElement, { display: "", left: pageLeft, width: pageWidth });
  }
  var pageContainerLeft = direction === 1 ? -currentWidth : 0;
  ASPx.SetStyles(pageContainer, { left: pageContainerLeft});
  ASPx.SetElementDisplay(viewPort, true);
  var maxHeight = Math.max(pageElements[0].offsetHeight, pageElements[1].offsetHeight);
  ASPx.SetStyles(viewPort, { height: maxHeight });
 },
 GetSlideAnimationDirection: function(newSelectedPageType) { return newSelectedPageType > this.selectedPageType ? -1 : 1; },
 GetCurrentContentWidth: function() { return this.GetDialogContentElement().offsetWidth; },
 OnSlideAnimationComplete: function() {
  this.ClearSlideAnimationElements();    
  ASPx.SetElementDisplay(this.GetCustDialogPageElement(this.selectedPageType), true);
  this.EnsureTabVisible(this.selectedPageType);
 },
 ClearSlideAnimationElements: function() {
  var content = this.GetDialogContentElement();
  var pageContainer = content.animationPageContainer;
  if(!pageContainer) return;
  for(var i = 0; i < pageContainer.childNodes.length; i++)
   ASPx.SetStyles(pageContainer.childNodes[i], { display: "none", left: "", width: "" });
  ASPx.MoveChildrenToElement(pageContainer, content);
  ASPx.SetElementDisplay(content.animationViewPot, false);
  ASPx.AnimationUtils.SetTransformValue(pageContainer, 0);
 },
 EnsureTabVisible: function(pageType) {
  var wrapper = this.GetTabSelectorButtonsWrapper();
  var tab = this.GetActiveTabElement();
  if(!tab) return;
  var wrapperPadding = ASPx.GetLeftRightPaddings(wrapper) / 2;
  var wrapperX = ASPx.GetAbsoluteX(wrapper);
  var wrapperLeft = wrapperX + wrapperPadding;
  var wrapperRight = wrapperX + wrapper.offsetWidth - wrapperPadding;
  var tabX = ASPx.GetAbsoluteX(tab);
  var tabMargin = ASPx.GetLeftRightMargins(tab);
  var tabLeft = tabX - tabMargin;
  var tabRight = tabX + tab.offsetWidth + tabMargin;
  var leftDiff = wrapperLeft - tabLeft;
  var rightDiff = tabRight - wrapperRight;
  if(leftDiff > 0)
   wrapper.scrollLeft -= leftDiff;
  else if(rightDiff > 0)
   wrapper.scrollLeft += rightDiff;
 },
 AssingScrollEvent: function() {
  var scrollElement = this.GetDialogScrollableElement();
  if(!scrollElement.dxgvOnScrollAssigned) {
   ASPx.Evt.AttachEventToElement(scrollElement, "scroll", this.OnScroll.bind(this));
   scrollElement.dxgvOnScrollAssigned = true;
  }
  this.AttachTouchScrollEvents();
 },
 OnScroll: function() {
  var pageElement = this.GetCustDialogPageElement(this.selectedPageType);
  if(pageElement.dragAreaExpandButton && ASPx.GetElementDisplay(pageElement.dragAreaExpandButton)) {
   var firstDraggableColumnItem = ASPx.GetChildByPartialClassName(pageElement.dragArea, this.ColumnItemClassName);
   var topDragPanelElement = firstDraggableColumnItem || pageElement.dragArea;
   var elementY = ASPx.GetAbsoluteY(topDragPanelElement);
   var viewPortY = ASPx.GetAbsoluteY(this.GetDialogScrollableElement());
   if(elementY > viewPortY) {
    ASPx.Timer.ClearTimer(this.expandTimeoutID);
    this.expandTimeoutID = window.setTimeout(function() { this.ChangeDragPanelFixation(false); }.bind(this), 100);
   }
  }
 },
 AttachTouchScrollEvents: function() {  
  if(!ASPx.Browser.WebKitTouchUI) return;
  var scrollElement = this.GetDialogScrollableElement();
  if(!scrollElement.dxgvTouchScrollEventsAssigned) {
   ASPx.Evt.AttachEventToElement(scrollElement, "touchstart", this.OnTouchStart.bind(this));
   ASPx.Evt.AttachEventToElement(scrollElement, "touchmove", this.OnTouchMove.bind(this));
   scrollElement.dxgvTouchScrollEventsAssigned = true;
  }
 },
 OnTouchStart: function(evt) {
  if(evt.touches.length === 1)
   this.touchStartY = ASPx.Evt.GetEventY(evt);
 },
 OnTouchMove: function(evt) {
  if(evt.touches.length > 1)
   return;
  var distanceY = ASPx.Evt.GetEventY(evt) - this.touchStartY;
  var scrollElement = this.GetDialogScrollableElement();
  var isScrolledToBottom = scrollElement.scrollHeight - scrollElement.scrollTop <= scrollElement.clientHeight;
  var needPreventScroll = (scrollElement.scrollTop === 0 && distanceY > 0) || (isScrolledToBottom && distanceY < 0);
  if(needPreventScroll)
   ASPx.Evt.PreventEvent(evt);  
 },
 UpdateApplyButtonEnabledState: function() {
  var applyButton = this.GetApplyButton();
  if(applyButton)
   applyButton.SetEnabled(this.IsStateChanged());
 },
 EnsureActiveTab: function(pageType) {
  var tabControl = this.GetTabControl();
  var requiredActiveTabName = this.GetTabNameByPageType(pageType);
  var actualActiveTab = tabControl.GetActiveTab();
  if(!actualActiveTab || requiredActiveTabName !== actualActiveTab.name) {
   var tab = tabControl.GetTabByName(requiredActiveTabName);
   tabControl.SetActiveTab(tab);
  }
 },
 UpdateDialogSelectedPageClass: function(pageType) { 
  var contentElement = this.GetCustDialogWindow().GetWindowContentElement(-1);
  ASPx.RemoveClassNameFromElement(contentElement, this.DialogColumnChooserPageSelectedClassName);
  ASPx.RemoveClassNameFromElement(contentElement, this.DialogFilterPageSelectedClassName);
  ASPx.RemoveClassNameFromElement(contentElement, this.DialogSortPageSelectedClassName);
  ASPx.RemoveClassNameFromElement(contentElement, this.DialogGroupPageSelectedClassName);
  var className = this.GetDialogSelectedPageClassName(pageType);
  ASPx.AddClassNameToElement(contentElement, className);
 },
 GetDialogSelectedPageClassName: function(pageType) {
  if(pageType === GridCustDialogPageType.FieldChooser)
   return this.DialogColumnChooserPageSelectedClassName;
  if(pageType === GridCustDialogPageType.Filtering)
   return this.DialogFilterPageSelectedClassName;
  if(pageType === GridCustDialogPageType.Sorting)
   return this.DialogSortPageSelectedClassName;
  if(pageType === GridCustDialogPageType.Grouping)
   return this.DialogGroupPageSelectedClassName;
 },
 RemoveCloseButtonRipple: function() {
  var closeButton = this.GetCloseButton();
  if(closeButton)
   ASPx.RippleHelper.RemoveRippleContainer(closeButton.GetMainElement());
 },
 ChangeDragPanelFixation: function(fixate, prevColumnCount, newColumnCount) { 
  var pageElement = this.GetCustDialogPageElement(this.selectedPageType);  
  if(!this.CanChangeDragPanelFixation(pageElement, fixate, newColumnCount))
   return;
  var button = pageElement.dragAreaExpandButton;
  var expandButtonVisible = ASPx.GetElementDisplay(button);
  var requireChangeFixation = fixate !== expandButtonVisible;
  if(requireChangeFixation) {
   if(fixate) {   
    this.FixateDragPanel(pageElement);
    if(!button.fixedColumnCount)
     button.fixedColumnCount = prevColumnCount;
   } else   
    this.UnfixateDragPanel(pageElement);
  } else if(expandButtonVisible) {
   if(button.fixedColumnCount === newColumnCount) {
    this.ClearDragPanelHeight(pageElement);
    this.HideExpandButton(pageElement);    
   } else
    this.FireExpandButtonRipple(pageElement);
  }
 },
 FixateDragPanel: function(pageElement) {
  var areaWrapper = pageElement.dragAreaWrapper;
  var button = pageElement.dragAreaExpandButton;
  var wrapperHeight = ASPx.GetClearClientHeight(areaWrapper);
  ASPx.SetStyles(areaWrapper, { height: wrapperHeight, overflowY: "hidden" });
  ASPx.SetStyles(pageElement.dragArea, { height: wrapperHeight });
  this.UpdateDragAreaExpandImagesVisibility();
  ASPx.AnimationHelper.setOpacity(button, 0);
  ASPx.SetElementDisplay(button, true);
  ASPx.AnimationHelper.fadeIn(button);
 },
 UnfixateDragPanel: function(pageElement) {
  var dragArea = pageElement.dragArea;
  var areaWrapper = pageElement.dragAreaWrapper;
  var wrapperHeight = ASPx.GetClearClientHeight(areaWrapper);
  ASPx.SetStyles(dragArea, { height: "" });
  var areaHeight = dragArea.offsetHeight;
  if(areaHeight < wrapperHeight)
   ASPx.SetStyles(dragArea, { height: wrapperHeight });
  var transition = ASPx.AnimationHelper.createAnimationTransition(areaWrapper, { 
   property: "height", 
   unit: "px", 
   onComplete: function() { this.ClearDragPanelHeight(pageElement); }.bind(this)
  });
  transition.Start(wrapperHeight, areaHeight);
  this.HideExpandButton(pageElement);
 },
 ClearDragPanelHeight: function(pageElement) {
  ASPx.SetStyles(pageElement.dragAreaWrapper, { height: "", overflowY: "visible" }); 
  ASPx.SetStyles(pageElement.dragArea, { height: "" });
 },
 CanChangeDragPanelFixation: function(pageElement, fixate, newColumnCount) {
  var button = pageElement.dragAreaExpandButton;
  if(!button) return false;
  var fixedColumnCount = button.fixedColumnCount || 0;
  if(fixate && fixedColumnCount === 0 && newColumnCount === 1)
   return false;  
  return true;
 }, 
 HideExpandButton: function(pageElement) {
  var button = pageElement && pageElement.dragAreaExpandButton;
  if(!button) return;
  ASPx.AnimationHelper.fadeOut(button, function() { 
   ASPx.SetElementDisplay(button, false); 
   delete button.fixedColumnCount;
  });  
 },
 FireExpandButtonRipple: function(pageElement) {
  var target = pageElement.dragAreaExpandButton;  
  var helper = ASPx.RippleHelper;
  if(!helper || !target) return;
  var rippleCenterX = ASPx.GetAbsoluteX(target);
  var rippleCenterY = ASPx.GetAbsoluteY(target) + target.offsetHeight / 2;
  ASPx.AddClassNameToElement(target, this.DragAreaExpandButtonBlickRippleClassName);
  var info = helper.createTargetInfo(target);
  helper.processRipple(info, { x: rippleCenterX, y: rippleCenterY });
  window.setTimeout(function() { ASPx.RemoveClassNameFromElement(target, this.DragAreaExpandButtonBlickRippleClassName); }.bind(this), helper.getDuration(info));
 },
 UpdateDragAreaExpandImagesVisibility: function() {
  window.setTimeout(this.UpdateDragAreaExpandImagesVisibilityCore.bind(this), 0);
 },
 UpdateDragAreaExpandImagesVisibilityCore: function() { 
  var pageElement = this.GetCustDialogPageElement(this.selectedPageType);
  if(pageElement && pageElement.dragAreaExpandButton) {
   var showExpandImage = false;
   var columnItems = ASPx.GetChildNodesByTagName(pageElement.dragArea, "DIV");
   var lastColumnItem = columnItems[columnItems.length - 1];
   if(lastColumnItem) {
    var itemBottomPos = ASPx.GetAbsoluteY(lastColumnItem) + lastColumnItem.offsetHeight;
    var buttonTopPos = ASPx.GetAbsoluteY(pageElement.dragAreaExpandButton);
    showExpandImage = itemBottomPos > buttonTopPos;
   }
   ASPx.SetElementDisplay(pageElement.dragAreaExpandImage, showExpandImage);
   ASPx.SetElementDisplay(pageElement.dragAreaCollapseImage, !showExpandImage);
  }
 },
 GetBrickDragImage: function(brickElement) {
  return ASPx.GetNodesByTagName(brickElement, "IMG")[0];
 },
 ApplyColumnItemStateEnabled: function(brickElement, isDisabled) {
  ASPx.RemoveClassNameFromElement(brickElement, this.ColumnItemBrick_ActiveClassName);
  ASPx.RemoveClassNameFromElement(brickElement, this.ColumnItemBrick_DisabledClassName);
  var className = isDisabled ? this.ColumnItemBrick_DisabledClassName : this.ColumnItemBrick_ActiveClassName;
  ASPx.AddClassNameToElement(brickElement, className);
 },
 FindCheckBoxElement: function(brickElement) {
  return brickElement.querySelector("INPUT");
 },
 PrepareCaptionElement: function(captionElement, brickElements, mapKey, columnIndex) {
  captionElement.innerHTML = this.GetColumnCaption(columnIndex);
 },
 GetColumnItemCheckBoxID: function(mapKey, columnIndex, brickType) { return this.GetColumnItemID(columnIndex, mapKey) + "Chk" + brickType; },
 GetColumnItemID: function(columnIndex, mapKey) { return this.grid.name + "_" + mapKey + "_C" + columnIndex; },
 PrepareCheckBoxBrickAttributes: function(checkBoxBrickElement, mapKey, columnIndex, brickType) {
  checkBoxBrickElement.id = this.GetColumnItemCheckBoxID(mapKey, columnIndex, brickType);
 },
 GetCheckBoxInvokeClick: function(collection, checkBox) {
  return function() { collection.helper.InvokeClick(checkBox, { }); };
 },
 CreateCheckBoxClientObject: function(collection, columnIndex, brickType, element, onChange){
  var checkBox = collection.Add(element.id, element);
  checkBox.SetValue(ASPx.CheckBoxInputKey.Unchecked); 
  checkBox.stateController.UpdateInternalCheckBoxDecoration(checkBox.mainElement, checkBox.GetValue(), true); 
  return checkBox;
 },
 GetCheckBoxState: function(checkBox) { return checkBox.GetCurrentCheckState(); },
 SetCheckBoxValue: function(checkBox, value) { checkBox.SetValue(value); },
 GetColumnCaption: function(columnIndex) {
  return this.grid.GetColumnCaption(columnIndex);
 },
 PrepareUniqueFilterContainer: function(container, columnIndex){ }
});
var CustDialogPage = ASPx.CreateClass(null, {
 constructor: function(dialogHelper) {
  this.dialogHelper = dialogHelper;
 },
 GetBrickTypeUniqueKey: function(brickType) { return "columnItemBrick_" + brickType; },
 GetBrickElement: function(columnItem, brickType) { return columnItem[this.GetBrickTypeUniqueKey(brickType)]; },
 CreatePageAreaMapKey: function(isDragArea) { return this.dialogHelper.CreatePageAreaMapKey(this.GetPageType(), isDragArea);  },
 GetColumnItem: function(columnIndex, isDragArea) {  return this.GetColumnItemCore(columnIndex, this.CreatePageAreaMapKey(isDragArea)); },
 GetColumnItemCore: function(columnIndex, mapKey) { return document.getElementById(this.dialogHelper.GetColumnItemID(columnIndex, mapKey)); },
 GetColumnState: function(columnIndex, isInitial) { return this.dialogHelper.GetColumnState(columnIndex, isInitial); },
 GetDialogProperties: function() { return this.dialogHelper.GetDialogProperties(); },
 GetEtalonColumnItem: function() { return this.dialogHelper.GetEtalonColumnItem(); },
 IsCheckBoxBrickType: function(brickType) { return this.dialogHelper.CheckBoxBrickTypes.indexOf(brickType) > -1; },
 GetPageType: function() { return null; },
 GetMainElement: function() { 
  var pageID = GridCustDialogPageIDs[this.GetPageType()];
  if(!pageID) return;
  var pageElement = this.dialogHelper.GetCustDialogChildElement(pageID);
  if(pageElement && !pageElement.etalonPageElement)
   pageElement.etalonPageElement = pageElement.cloneNode(true);
  return pageElement;
 },
 ResetMainElement: function() {
  var mainElement = this.GetMainElement();
  if(mainElement && mainElement.etalonPageElement) {
   var newMainElement = mainElement.etalonPageElement.cloneNode(true);
   mainElement.parentNode.insertBefore(newMainElement, mainElement);
   ASPx.RemoveElement(mainElement);
  }
 },
 OnPopUp: function() { },
 OnCloseUp: function() {
  this.ResetMainElement();
 },
 HasDragArea: function() { return false; },
 HasListArea: function() { return false; },
 GetDragAreaColumnState: function() { return this.dialogHelper.GetOrderedAllColumnsState(); },
 GetListAreaColumnState: function() { return this.dialogHelper.GetOrderedDataColumnsState(); },
 GetDragAreaColumnIndices: function() { return this.GetDragAreaColumnState().map(function(c) { return c.columnIndex; }); },
 GetListAreaColumnIndices: function() { return this.GetListAreaColumnState().map(function(c) { return c.columnIndex; }); },
 GetDragAreaItemsContainer: function() { return this.GetMainElement().dragArea; },
 GetListAreaItemsContainer: function() { return this.GetMainElement().listAreaItemsWrapper; },
 OnInsertColumnItemToContainer: function(columnItem, columnIndex) { },
 IsSingleVisibleColumnWithData: function(column, columnState) {
  var visibleDataColumnIndices = this.GetVisibleDataColumnIndices();
  if(visibleDataColumnIndices.length === 1 && visibleDataColumnIndices[0] === columnState.columnIndex)
   return true;
  if(column.isBand && this.dialogHelper.GetColumnHelper().GetIsParentForAllColumns(columnState.columnIndex, visibleDataColumnIndices))
   return true;
  return false;
 },
 IsColumnStateVisible: function(columnState) {
  var result = false;
  if(columnState.visible && columnState.groupIndex === -1) {
   var parentColumnState = this.GetParentColumnState(columnState);
   result = parentColumnState === null || this.IsColumnStateVisible(parentColumnState);
  }
  return result;
 },
 GetParentColumnState: function(columnState) {
  if(columnState.parentColumnIndex !== -1)
   return this.dialogHelper.GetColumnState(columnState.parentColumnIndex);
  return null;
 },
 GetVisibleDataColumnIndices: function() {
  return this.GetListAreaColumnState()
   .filter(function(c) { return this.IsColumnStateVisible(c); }.bind(this))
   .map(function(c) { return c.columnIndex; });
 },
 GetGroupColumnCount: function() { return this.GetListAreaColumnState().filter(function(c) { return c.groupIndex > -1; }).length; },
 Update: function() {
  if(this.HasDragArea()) {
   this.InitDragPanelElements();
   var dragColumnState = this.GetDragAreaColumnState();
   this.UpdateColumnItems(this.CreatePageAreaMapKey(true), dragColumnState, this.GetDragAreaItemsContainer());
   this.UpdateDragAreaEmptyTextContainerVisibility(dragColumnState.length === 0);
  }
  if(this.HasListArea())
   this.UpdateColumnItems(this.CreatePageAreaMapKey(false), this.GetListAreaColumnState(), this.GetListAreaItemsContainer());
 },
 InitDragPanelElements: function() {
  var pageElement = this.GetMainElement();
  if(pageElement.dragArea) return;
  pageElement.dragArea = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.DragAreaClassName)[0];
  pageElement.dragAreaEmptyTextContainer = ASPx.GetChildByClassName(pageElement.dragArea, this.dialogHelper.DragAreaEmptyTextContainerClassName);
  pageElement.listArea = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.ListAreaClassName)[0];
  pageElement.listAreaItemsWrapper = ASPx.GetChildByClassName(pageElement.listArea, this.dialogHelper.ListAreaItemsWrapperClassName);
  pageElement.dragAreaWrapper = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.DragAreaWrapperClassName)[0];
  pageElement.dragAreaExpandButton = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.DragAreaExpandButtonClassName)[0];
  pageElement.dragAreaExpandImage = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.DragAreaExpandImageClassName)[0];
  pageElement.dragAreaCollapseImage = ASPx.GetNodesByPartialClassName(pageElement, this.dialogHelper.DragAreaCollapseImageClassName)[0];
  if(pageElement.dragAreaExpandButton)
   ASPx.Evt.AttachEventToElement(pageElement.dragAreaExpandButton, "click", function() { this.dialogHelper.ChangeDragPanelFixation(false); }.bind(this));
 },
 UpdateColumnItems: function(mapKey, columnsState, container) {
  var columnsInfo = columnsState.map(function(c) { return { columnIndex: c.columnIndex, disabledBrickTypes: this.GetColumnDisabledBrickTypes(c) }; }.bind(this));
  for(var i = 0; i < columnsInfo.length; i++)
   this.UpdateColumnItem(mapKey, columnsInfo[i], container);
 },
 UpdateColumnItem: function(mapKey, columnInfo, container) { 
  var columnIndex = columnInfo.columnIndex;
  var columnItem = this.GetColumnItemCore(columnIndex, mapKey);
  if(!columnItem) {
   columnItem = this.CreateColumnItem(mapKey, columnIndex);
   container.appendChild(columnItem);
   this.OnInsertColumnItemToContainer(columnItem, columnIndex);
  }
  this.ApplyColumnItemState(columnItem, columnInfo);
 },
 CreateColumnItem: function(mapKey, columnIndex) {
  var etalonMap = this.dialogHelper.GetColumnItemMap(this.dialogHelper.CreateEtalonColumnItemMapKey());
  var itemMap = this.dialogHelper.GetColumnItemMap(mapKey, columnIndex);
  var columnItem = this.GetEtalonColumnItem().cloneNode(true);
  this.GetColumnItemBricks(columnItem).filter(function(d, i) { return itemMap.indexOf(etalonMap[i]) < 0; }).forEach(function(c) { ASPx.RemoveElement(c); }); 
  var brickElements = this.GetColumnItemBricks(columnItem);
  for(var i = 0; i < itemMap.length; i++)
   this.PrepareColumnItemBrick(columnItem, columnIndex, brickElements[i], itemMap[i], mapKey);
  columnItem.id = this.dialogHelper.GetColumnItemID(columnIndex, mapKey);
  columnItem.dxgvColumnIndex = columnIndex;
  ASPx.SetElementDisplay(columnItem, true);
  return columnItem;
 },
 GetColumnItemBricks: function(columnItem) {
  return ASPx.GetChildNodesByTagName(columnItem, "DIV");
 },
 PrepareColumnItemBrick: function(columnItem, columnIndex, brickElement, brickType, mapKey) {
  if(this.IsCheckBoxBrickType(brickType))
   this.PrepareCheckBoxBrick(brickElement, brickType, columnIndex, mapKey);
  if(brickType === GridCustDialogBrickType.Caption)
   this.dialogHelper.PrepareCaptionElement(brickElement, this.GetColumnItemBricks(columnItem), mapKey, columnIndex);
  if(brickType === GridCustDialogBrickType.Remove) {
   this.PreventImageDragging(brickElement);
   ASPx.Evt.AttachEventToElement(brickElement, "click", this.OnRemoveBrickElementClick.bind(this));
  }
  if(brickType === GridCustDialogBrickType.Drag) { 
   this.PreventImageDragging(brickElement);
   var img = this.dialogHelper.GetBrickDragImage(brickElement);
   if(img) {
    brickElement.dxgvDragPart = img.dxgvDragPart = brickElement;
    ASPx.Evt.AttachEventToElement(img, "mouseDown", ASPx.Evt.PreventEvent); 
   }
  }
  columnItem[this.GetBrickTypeUniqueKey(brickType)] = brickElement;
 },
 PrepareCheckBoxBrick: function(brickElement, brickType, columnIndex, mapKey) {
  var element = this.dialogHelper.FindCheckBoxElement(brickElement);
  this.dialogHelper.PrepareCheckBoxBrickAttributes(element, mapKey, columnIndex, brickType);
  var collection = this.dialogHelper.GetCheckBoxCollection(brickType);
  var checkBox = this.dialogHelper.CreateCheckBoxClientObject(collection, columnIndex, brickType, element);
  brickElement.dxCheckBox = checkBox;
  checkBox.CheckedChanged.AddHandler(this.OnCheckBoxCheckedChanged.bind(this, checkBox, columnIndex, brickType));
  checkBox.InvokeClick = this.dialogHelper.GetCheckBoxInvokeClick(collection, checkBox);
  var parentForClick = brickElement; 
  if(brickType === GridCustDialogBrickType.FilterExpand) {
   parentForClick = this.GetColumnItemByBrick(brickElement);
   parentForClick.style.cursor = "pointer"; 
  }
  ASPx.Evt.AttachEventToElement(parentForClick, "click", function(e) {
   var src = ASPx.Evt.GetEventSource(e);
   if(!ASPx.GetIsParent(checkBox.mainElement, src) && this.RequireProcessCheckBoxBrickElementClick(brickType, columnIndex, src))
    checkBox.InvokeClick();
  }.bind(this));
 },
 OnRemoveBrickElementClick: function(e) {
  var brickElement = e.currentTarget;
  if(ASPx.ElementHasCssClass(brickElement, this.dialogHelper.ColumnItemBrick_DisabledClassName))
   return;
  var columnItem = this.GetColumnItemByBrick(brickElement);
  var columnIndex = columnItem.dxgvColumnIndex;
  this.ProcessColumnItemRemoveBrickClick(columnIndex);
  ASPx.RemoveElement(columnItem);
  this.dialogHelper.ChangeDragPanelFixation(false);
  this.dialogHelper.UpdateCurrentDialogPage();
 },
 GetColumnItemByBrick: function(brickElement) {
  return brickElement.parentNode;
 },
 ProcessColumnItemRemoveBrickClick: function(columnIndex) { },
 RequireProcessCheckBoxBrickElementClick: function(brickType, columnIndex, src) { return true; },
 PreventImageDragging: function(brickElement) { ASPx.Attr.SetAttribute(brickElement, "ondragstart", "return false;"); },
 ApplyColumnItemState: function(columnItem, columnInfo) {
  var state = this.GetColumnState(columnInfo.columnIndex);
  var disabledBrickTypes = columnInfo.disabledBrickTypes;
  for(var i = 0; i < this.dialogHelper.ActionBrickTypes.length; i++) {
   var brickType = this.dialogHelper.ActionBrickTypes[i];
   var brickElement = this.GetBrickElement(columnItem, brickType);
   if(!brickElement) 
    continue;
   var isDisabled = disabledBrickTypes.indexOf(brickType) > -1;
   if(this.IsCheckBoxBrickType(brickType) && brickElement.dxCheckBox) {
    brickElement.dxCheckBox.SetEnabled(!isDisabled);
    this.dialogHelper.SetCheckBoxValue(brickElement.dxCheckBox, this.GetCheckBoxValueByColumnState(state, brickType));
   }
   this.dialogHelper.ApplyColumnItemStateEnabled(brickElement, isDisabled);
  }
 },
 OnCheckBoxCheckedChanged: function(checkBox, columnIndex, brickType) {
  this.OnCheckBoxCheckedChangedCore(this.dialogHelper.GetCheckBoxState(checkBox), this.GetColumnState(columnIndex), brickType);
  this.dialogHelper.UpdateCurrentDialogPage();
 },
 OnCheckBoxCheckedChangedCore: function(checkState, columnState, brickType) {
  var pageType = this.GetPageType();
  if(pageType !== GridCustDialogPageType.Sorting && pageType !== GridCustDialogPageType.Grouping) 
   return;
  var prevColumnCount = this.GetDragAreaColumnIndices().length;
  var newColumnState = this.GetNewColumnStateByCheckState(checkState, brickType, columnState);
  if(ASPx.IsExists(newColumnState.sortIndex))
   columnState.sortIndex = newColumnState.sortIndex;
  if(ASPx.IsExists(newColumnState.sortOrder))
   columnState.sortOrder = newColumnState.sortOrder;
  if(ASPx.IsExists(newColumnState.groupIndex))
   columnState.groupIndex = newColumnState.groupIndex;
  this.dialogHelper.UpdateColumnsSortGroupState();
  if(brickType === GridCustDialogBrickType.Sort || brickType === GridCustDialogBrickType.Group) {
   var newColumnCount = this.GetDragAreaColumnIndices().length;
   if(newColumnCount !== prevColumnCount)
    this.dialogHelper.ChangeDragPanelFixation(true, prevColumnCount, newColumnCount);
   if(newColumnState.sortIndex === -1 || newColumnState.groupIndex === -1) 
    ASPx.RemoveElement(this.GetColumnItem(columnState.columnIndex, true));
  }
 },
 GetColumnDisabledBrickTypes: function(columnState) {
  return this.dialogHelper.DisabledBrickTypes.filter(function(brickType) { return this.RequireDisableColumnItemBrick(columnState, brickType); }.bind(this));
 },
 RequireDisableColumnItemBrick: function(columnState, brickType) {
  var column = this.dialogHelper.GetColumnHelper().FindColumn(columnState.columnIndex);
  return this.RequireDisableColumnItemBrickCore(column, columnState, brickType);
 },
 RequireDisableColumnItemBrickCore: function(column, columnState, brickType) { return false; },
 GetCheckBoxValueByColumnState: function(columnState, brickType) { return null; },
 GetNewColumnStateByCheckState: function(checkState, brickType, oldColumnState) { return null; },
 UpdateDragAreaEmptyTextContainerVisibility: function(visible) {
  ASPx.SetElementDisplay(this.GetMainElement().dragAreaEmptyTextContainer, visible);
 },
});
var CustDialogSortingPage = ASPx.CreateClass(CustDialogPage, {
 constructor: function(dialogHelper) {
  this.constructor.prototype.constructor.call(this, dialogHelper);
 },
 GetPageType: function() { return GridCustDialogPageType.Sorting; },
 HasDragArea: function() { return true; },
 HasListArea: function() { return true; },
 GetDragAreaColumnState: function() { return this.dialogHelper.GetOrderedSortColumnsState(); },
 RequireDisableColumnItemBrickCore: function(column, columnState, brickType) {
  if(brickType === GridCustDialogBrickType.Drag)
   return columnState.groupIndex > -1;
  if(brickType === GridCustDialogBrickType.Remove)
   return columnState.groupIndex > -1;
  if(brickType === GridCustDialogBrickType.Sort) {
   if(columnState.groupIndex > -1)
    return true;
   return !column.allowSort;
  }
  return false;
 },
 ProcessColumnItemRemoveBrickClick: function(columnIndex) { 
  var state = this.GetColumnState(columnIndex);
  state.sortIndex = -1;
  state.sortOrder = ASPx.GridSortOrder.None;
 },
 GetCheckBoxValueByColumnState: function(columnState, brickType) { 
  if(brickType == GridCustDialogBrickType.Sort)
   return columnState.sortIndex > -1 ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked;
  if(brickType == GridCustDialogBrickType.SortOrder)
   return columnState.sortOrder === ASPx.GridSortOrder.Ascending ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked;
  return null;
 },
 GetNewColumnStateByCheckState: function(checkState, brickType, oldColumnState) { 
  if(brickType === GridCustDialogBrickType.SortOrder) {
   var sortOrder = checkState === ASPx.CheckBoxCheckState.Checked ? ASPx.GridSortOrder.Ascending : ASPx.GridSortOrder.Descending;
   return { sortOrder: sortOrder };
  }
  if(brickType === GridCustDialogBrickType.Sort) {
   var sortedColumnCount = this.GetDragAreaColumnIndices().length;
   var sortIndex = checkState === ASPx.CheckBoxCheckState.Checked ? sortedColumnCount : -1;
   var sortOrder = checkState === ASPx.CheckBoxCheckState.Checked ? ASPx.GridSortOrder.Ascending : ASPx.GridSortOrder.None;
   return { sortIndex: sortIndex, sortOrder: sortOrder };
  }
  return null;
 },
});
var CustDialogGroupingPage = ASPx.CreateClass(CustDialogPage, {
 constructor: function(dialogHelper) {
  this.constructor.prototype.constructor.call(this, dialogHelper);
 },
 GetPageType: function() { return GridCustDialogPageType.Grouping; },
 HasDragArea: function() { return true; },
 HasListArea: function() { return true; },
 GetDragAreaColumnState: function() { return this.dialogHelper.GetOrderedGroupColumnsState(); },
 RequireDisableColumnItemBrickCore: function(column, columnState, brickType) {
  if(brickType === GridCustDialogBrickType.Group)
   return !this.canGroupByColumn(column, columnState);
  if(brickType === GridCustDialogBrickType.Drag)
   return !column.allowGroup;
  if(brickType === GridCustDialogBrickType.Remove)
   return !column.allowGroup;
  return false;
 },
 canGroupByColumn: function(column, columnState) {
  return column.allowGroup && this.GetVisibleDataColumnIndices().length > 0 && !this.IsSingleVisibleColumnWithData(column, columnState);
 },
 ProcessColumnItemRemoveBrickClick: function(columnIndex) { 
  var state = this.GetColumnState(columnIndex);
  state.groupIndex = -1;
  state.sortIndex = -1;
  state.sortOrder = ASPx.GridSortOrder.None;
 },
 GetCheckBoxValueByColumnState: function(columnState, brickType) { 
  if(brickType == GridCustDialogBrickType.Group)
   return columnState.groupIndex > -1 ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked;
  return null;
 },
 GetNewColumnStateByCheckState: function(checkState, brickType, oldColumnState) { 
  if(brickType === GridCustDialogBrickType.Group) {
   var groupedColumnCount = this.GetDragAreaColumnIndices().length;
   var groupIndex = checkState === ASPx.CheckBoxCheckState.Checked ? groupedColumnCount : -1;
   var sortIndex = groupIndex;
   var sortOrder = ASPx.GridSortOrder.None;
   if(groupIndex > -1) {
    var prevSortOrder = oldColumnState.sortOrder;
    sortOrder = prevSortOrder !== ASPx.GridSortOrder.None ? prevSortOrder : ASPx.GridSortOrder.Ascending;
   }
   return { groupIndex: groupIndex, sortIndex: sortIndex, sortOrder: sortOrder };
  }
  return null;
 },
});
var CustDialogFieldChooserPage = ASPx.CreateClass(CustDialogPage, {
 constructor: function(dialogHelper) {
  this.constructor.prototype.constructor.call(this, dialogHelper);
 },
 GetPageType: function() { return GridCustDialogPageType.FieldChooser; },
 HasDragArea: function() { return true; },
 RequireDisableColumnItemBrickCore: function(column, columnState, brickType) {
  if(brickType === GridCustDialogBrickType.Drag)
   return !column.allowDrag || this.dialogHelper.GetColumnHelper().GetHeaderLayout().length > 1;
  if(brickType === GridCustDialogBrickType.Visibility)
   return !this.canHideColumn(column, columnState);
  return false;
 },
 canHideColumn: function(column, columnState) {
  return column.allowDrag && (!this.IsSingleVisibleColumnWithData(column, columnState) || this.GetGroupColumnCount() === 0);
 },
 OnCheckBoxCheckedChangedCore: function(checkState, columnState, brickType) {
  var newColumnState = this.GetNewColumnStateByCheckState(checkState, brickType, columnState);
  if(ASPx.IsExists(newColumnState.visible))
   columnState.visible = newColumnState.visible;
 },
 GetCheckBoxValueByColumnState: function(columnState, brickType) { 
  if(brickType == GridCustDialogBrickType.Visibility)
   return columnState.visible ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked;
  return null;
 },
 GetNewColumnStateByCheckState: function(checkState, brickType, oldColumnState) { 
  if(brickType === GridCustDialogBrickType.Visibility)
   return { visible: checkState === ASPx.CheckBoxCheckState.Checked };
  return null;
 }
});
var CustDialogFilteringPage = ASPx.CreateClass(CustDialogPage, {
 constructor: function(dialogHelper) {
  this.constructor.prototype.constructor.call(this, dialogHelper);
  this.filterItemExpandState = { };
  this.columnIndicesToPostponedClearFilter = [ ];
 },
 GetPageType: function() { return GridCustDialogPageType.Filtering; },
 GetFilterHelper: function() { return this.dialogHelper.GetFilterHelper(); },
 GetAutoFilterEditor: function(columnIndex) { return this.dialogHelper.GetAutoFilterEditor(columnIndex); },
 GetEtalonFilterItem: function() { return this.dialogHelper.GetEtalonFilterItem(); },
 GetFilterEditorsContainer: function() { return this.dialogHelper.GetFilterEditorsContainer(); },
 CanShowFilterRowMenu: function(columnIndex) { return this.dialogHelper.CanShowFilterRowMenu(columnIndex); },
 GetFilterItemID: function(columnIndex) { return this.dialogHelper.GetColumnItemID(columnIndex, this.CreatePageAreaMapKey(this.GetPageType())) + "FI"; },
 GetFilterItem: function(columnIndex) { return document.getElementById(this.GetFilterItemID(columnIndex)); },
 GetFilterItemExpandState: function(columnIndex) { return this.filterItemExpandState[columnIndex]; },
 SetFilterItemExpandState: function(columnIndex, value) { this.filterItemExpandState[columnIndex] = value; },
 GetColumnIndicesToPostponedClearFilter: function() { return this.columnIndicesToPostponedClearFilter; },
 GetCheckBoxValueByColumnState: function(columnState, brickType) { 
  if(brickType == GridCustDialogBrickType.FilterExpand)
   return this.GetFilterItemExpandState(columnState.columnIndex) ? ASPx.CheckBoxInputKey.Checked : ASPx.CheckBoxInputKey.Unchecked;
  return null;
 },
 IsColumnFiltered: function(columnIndex) { return this.GetDialogProperties().filteredColumnIndices.indexOf(columnIndex) > -1; },
 HasUniqueColumnFilter: function(columnIndex) { return this.GetDialogProperties().headerFilterColumnIndices.indexOf(columnIndex) > -1; },
 IsUniqueFilterValuesLoaded: function(columnIndex) { 
  var filterItem = this.GetFilterItem(columnIndex);
  return filterItem && filterItem.uniqueFilter && ASPx.ElementHasCssClass(filterItem.uniqueFilter, this.dialogHelper.UnqiueFilterListBoxVisibleClassName);
 },
 GetUniqueFilterColumnIndices: function() { return this.GetListAreaColumnIndices().filter(this.HasUniqueColumnFilter.bind(this)); },
 GetFilterRowConditionDisplayText: function(columnIndex) {
  var condition = this.dialogHelper.grid.filterRowConditions[columnIndex];
  if(ASPx.IsExists(condition))
   return this.GetDialogProperties().filterRowConditionsText[condition];
  return "";
 },
 HasListArea: function() { return true; },
 GetListAreaColumnState: function() { return CustDialogPage.prototype.GetListAreaColumnState.call(this).filter(this.RequireShowFilterItem.bind(this)); },
 GetListAreaItemsContainer: function() { return this.GetMainElement(); },
 RequireShowFilterItem: function(columnState) { return this.HasUniqueColumnFilter(columnState.columnIndex) || this.GetAutoFilterEditor(columnState.columnIndex); },
 OnPopUp: function() { 
  CustDialogPage.prototype.OnPopUp.call(this);
  this.filterItemExpandState = ASPx.Data.ArrayToHash(this.GetListAreaColumnIndices(), function(index) { return index; }, this.IsColumnFiltered.bind(this));
 },
 OnCloseUp: function() { 
  CustDialogPage.prototype.OnCloseUp.call(this);
  this.ClearUniqueFilterContainerCache();
  this.filterItemExpandState = { };
  this.columnIndicesToPostponedClearFilter = [ ];
 },
 ResetMainElement: function() {
  this.MoveAutoFilterEditorsToFilterCell();
  this.MoveUniqueFilterEditorsToUniqueFilterContainer();
  CustDialogPage.prototype.ResetMainElement.call(this);
 },
 PrepareColumnItemBrick: function(columnItem, columnIndex, brickElement, brickType, mapKey) {
  CustDialogPage.prototype.PrepareColumnItemBrick.call(this, columnItem, columnIndex, brickElement, brickType, mapKey);
  if(brickType === GridCustDialogBrickType.ClearFilter) {
   this.PreventImageDragging(brickElement);
   ASPx.Evt.AttachEventToElement(brickElement, "click", this.OnClearFilterBrickElementClick.bind(this));
   ASPx.SetElementDisplay(brickElement, this.IsColumnFiltered(columnIndex));
  }
 },
 OnClearFilterBrickElementClick: function(e) {
  var brickElement = e.currentTarget;
  if(ASPx.ElementHasCssClass(brickElement, this.dialogHelper.ColumnItemBrick_DisabledClassName))
   return;
  var columnIndex = this.GetColumnItemByBrick(brickElement).dxgvColumnIndex;
  this.ClearColumnFilter(columnIndex);
  ASPx.SetElementDisplay(brickElement, false);
  ASPx.Evt.PreventEventAndBubble(e);
 },
 ClearColumnFilter: function(columnIndex) {
  this.GetFilterHelper().ClearColumnFilter(columnIndex);
  this.UpdateFilterRowConditionDisplayTextCore(columnIndex);
  if(this.HasUniqueColumnFilter(columnIndex) && !this.IsUniqueFilterValuesLoaded(columnIndex) && !ASPx.Data.ArrayContains(this.columnIndicesToPostponedClearFilter, columnIndex))
   this.columnIndicesToPostponedClearFilter.push(columnIndex);
 },
 RequireProcessCheckBoxBrickElementClick: function(brickType, columnIndex, src) { 
  var clearFilterBrick = this.GetBrickElement(this.GetColumnItem(columnIndex), GridCustDialogBrickType.ClearFilter);
  return !ASPx.GetIsParent(clearFilterBrick, src);
 },
 OnCheckBoxCheckedChangedCore: function(checkState, columnState, brickType) {
  if(brickType === GridCustDialogBrickType.FilterExpand) {
   var columnIndex = columnState.columnIndex;
   var expanded = checkState === ASPx.CheckBoxCheckState.Checked;
   this.SetFilterItemExpandState(columnIndex, expanded);
   var columnItem = this.GetColumnItem(columnIndex);
   var action = expanded ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
   action(columnItem, this.dialogHelper.ExpandedFilterColumnItemClassName);
  }
 },
 OnInsertColumnItemToContainer: function(columnItem, columnIndex) {
  var filterItem = this.CreateFilterItem(columnItem, columnIndex);
  this.GetMainElement().appendChild(filterItem);
  if(this.GetFilterItemExpandState(columnIndex)) {
   var brickElement = this.GetBrickElement(columnItem, GridCustDialogBrickType.FilterExpand);
   if(brickElement && brickElement.dxCheckBox)
    brickElement.dxCheckBox.InvokeClick();
  }
 },
 CreateFilterItem: function(columnItem, columnIndex) {
  var filterItem = this.GetEtalonFilterItem().cloneNode(true);
  filterItem.id = this.GetFilterItemID(columnIndex);
  this.PrepareFilterRow(filterItem, columnIndex);
  this.PrepareUniqueFilter(filterItem, columnIndex);
  ASPx.SetElementDisplay(filterItem, true);
  return filterItem;
 },
 PrepareFilterRow: function(filterItem, columnIndex) {
  var filterRow = ASPx.GetChildByClassName(filterItem, this.dialogHelper.FilterRowContainerClassName);
  var editor = this.GetAutoFilterEditor(columnIndex);
  var showFilterRow = !!(editor && editor.GetMainElement());
  if(showFilterRow)
   this.PrepareFilterRowCore(filterItem, filterRow, editor, columnIndex);
  else
   ASPx.RemoveElement(filterRow);
 },
 PrepareFilterRowCore: function(filterItem, filterRow, editor, columnIndex) {
  filterItem.filterRow = filterRow;
  filterItem.conditionLink = ASPx.GetChildByTagName(filterRow, "A");
  filterItem.conditionLabel = ASPx.GetChildByTagName(filterRow, "SPAN");
  filterItem.editorContainer = ASPx.GetChildByTagName(filterRow, "DIV");
  if(editor.GetInputElement())
   ASPx.Attr.RestoreAttribute(editor.GetInputElement(), "tabindex");
  if(!editor.filterCell)
   editor.filterCell = editor.GetMainElement().parentNode;
  ASPx.MoveChildrenToElement(editor.filterCell, filterItem.editorContainer);
  this.UpdateFilterRowConditionDisplayTextCore(columnIndex, filterItem);
  var hasFilterRowMenu = this.CanShowFilterRowMenu(columnIndex);
  if(hasFilterRowMenu)
   ASPx.Evt.AttachEventToElement(filterItem.conditionLink, "click", function() {
    this.dialogHelper.GetFilterHelper().FilterRowMenuButtonClick(columnIndex, filterItem.conditionLink);
   }.bind(this));
  ASPx.SetElementDisplay(filterItem.conditionLink, hasFilterRowMenu);
  ASPx.SetElementDisplay(filterItem.conditionLabel, !hasFilterRowMenu);
 },
 PrepareUniqueFilter: function(filterItem, columnIndex) {
  var uniqueFilter = ASPx.GetChildByClassName(filterItem, this.dialogHelper.UniqueFilterContainerClassName);
  var showUniqueFilter = this.HasUniqueColumnFilter(columnIndex);
  if(showUniqueFilter)
   this.PrepareUniqueFilterCore(filterItem, uniqueFilter, columnIndex);
  else
   ASPx.RemoveElement(uniqueFilter);
 },
 PrepareUniqueFilterCore: function(filterItem, uniqueFilter, columnIndex) {
  filterItem.uniqueFilter = uniqueFilter;
  filterItem.loadLink = ASPx.GetChildByTagName(uniqueFilter, "A");
  filterItem.scrollContainer = ASPx.GetChildByTagName(uniqueFilter, "DIV");
  this.dialogHelper.PrepareUniqueFilterContainer(filterItem.scrollContainer, columnIndex);
  var containerCache = this.GetFilterEditorsContainer().uniqueFilterContainerCache;
  var uniqueFilterContainer = containerCache && containerCache[columnIndex]; 
  if(uniqueFilterContainer) {
   ASPx.MoveChildrenToElement(uniqueFilterContainer, filterItem.scrollContainer);
   ASPx.AddClassNameToElement(filterItem.uniqueFilter, this.dialogHelper.UnqiueFilterListBoxVisibleClassName);
   ASPx.RemoveElement(filterItem.loadLink);
  } else {
   ASPx.Evt.AttachEventToElement(filterItem.loadLink, "click", function() { 
    this.dialogHelper.GetFilterHelper().SendHeaderFilterCallback(columnIndex);
    ASPx.AddClassNameToElement(filterItem.uniqueFilter, this.dialogHelper.UnqiueFilterListBoxVisibleClassName);
    this.dialogHelper.grid.CreateLoadingPanelWithoutBordersInsideContainer(filterItem.scrollContainer); 
   }.bind(this));
  }
 },
 UpdateFilterRowConditionDisplayText: function() {
  this.GetListAreaColumnIndices().forEach(function(i) { this.UpdateFilterRowConditionDisplayTextCore(i); }.bind(this));
 },
 UpdateFilterRowConditionDisplayTextCore: function(columnIndex, filterItem) {
  var filterItem = filterItem || this.GetFilterItem(columnIndex);
  if(!filterItem || !filterItem.filterRow) return;
  var hasFilterRowMenu = this.CanShowFilterRowMenu(columnIndex);
  var conditionControl = hasFilterRowMenu ? filterItem.conditionLink : filterItem.conditionLabel;
  conditionControl.innerHTML = this.GetFilterRowConditionDisplayText(columnIndex);
 },
 MoveAutoFilterEditorsToFilterCell: function() {
  var columnIndices = this.GetListAreaColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var filterItem = this.GetFilterItem(columnIndex);
   var editor = this.GetAutoFilterEditor(columnIndex);
   if(editor && editor.filterCell && filterItem)
    ASPx.MoveChildrenToElement(filterItem.editorContainer, editor.filterCell);
  }
 },
 MoveUniqueFilterEditorsToUniqueFilterContainer: function() {
  var columnIndices = this.GetUniqueFilterColumnIndices();
  var container = this.GetFilterEditorsContainer();
  container.uniqueFilterContainerCache = container.uniqueFilterContainerCache || { };
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var filterItem = this.GetFilterItem(columnIndex);
   if(!filterItem.scrollContainer.children.length)
    continue;
   var uniqueFilterContainer = container.uniqueFilterContainerCache[columnIndex];
   if(!uniqueFilterContainer) {
    uniqueFilterContainer = ASPx.CreateHtmlElement("DIV");
    container.appendChild(uniqueFilterContainer);
    container.uniqueFilterContainerCache[columnIndex] = uniqueFilterContainer;
   }
   ASPx.MoveChildrenToElement(filterItem.scrollContainer, uniqueFilterContainer);
  }
 },
 ClearUniqueFilterContainerCache: function() {
  var uniqueFilterCache = this.GetFilterEditorsContainer().uniqueFilterContainerCache; 
  if(uniqueFilterCache) {
   Object.keys(uniqueFilterCache).forEach(function(columnIndex) { ASPx.RemoveElement(uniqueFilterCache[columnIndex]); });
   this.GetFilterEditorsContainer().uniqueFilterContainerCache = null;
  }
 },
 ProcessHeaderFilterCallback: function(html, columnIndex) {
  var filterItem = this.GetFilterItem(columnIndex);
  if(filterItem) {
   filterItem.scrollContainer.innerHTML = html;
   return true;
  }
  return false;
 },
 ProcessFilterChange: function(columnIndex) {
  var columnItem = this.GetColumnItem(columnIndex);
  var clearBrickElement = this.GetBrickElement(columnItem, GridCustDialogBrickType.ClearFilter);
  if(clearBrickElement) {
   var visible = this.GetFilterHelper().HasFilter(columnIndex);
   if(!ASPx.GetElementDisplay(clearBrickElement) && visible)
    ASPx.Data.ArrayRemove(this.columnIndicesToPostponedClearFilter, columnIndex);
   ASPx.SetElementDisplay(clearBrickElement, visible);
  }
 },
 ClearHeaderFilterAfterLoadValues: function() {
  var loadedIndices = this.columnIndicesToPostponedClearFilter.filter(this.IsUniqueFilterValuesLoaded.bind(this));
  for(var i = 0; i < loadedIndices.length; i++) { 
   var columnIndex = loadedIndices[i];   
   this.GetFilterHelper().ClearColumnFilter(columnIndex);
   ASPx.Data.ArrayRemove(this.columnIndicesToPostponedClearFilter, columnIndex);
  } 
 }
});
var GridViewCustDialogColumnDragHelper = ASPx.CreateClass(null, {
 constructor: function(dialogHelper) {
  this.dialogHelper = dialogHelper;
  this.hugePos = 1000000;
  this.customScrollTimeout = 1;
  this.customScrollTimer = -1;
  this.minScrollVelocity = 0.100; 
  this.maxScrollVelocity = 0.400;
  this.scrollAreaHeightMultiplicator = 1.5;
 },
 GetPage: function() { return this.dialogHelper.GetPage(this.dialogHelper.selectedPageType); },
 GetColumnItem: function(columnIndex) { return this.GetPage().GetColumnItem(columnIndex, true); },
 GetScrollableControl: function() { return this.dialogHelper.GetDialogScrollableElement(); },
 GetColumnState: function(columnIndex) { return this.dialogHelper.GetColumnState(columnIndex); },
 GetDraggableColumnIndices: function() {
  var result = [ ];
  var page = this.GetPage();
  var columnsState = page.GetDragAreaColumnState();
  var firstDraggableColumnState = null;
  for(var i = 0; i < columnsState.length; i++) {
   var state = columnsState[i];
   var disabledBrickTypes = page.GetColumnDisabledBrickTypes(state);
   if(!firstDraggableColumnState && disabledBrickTypes.indexOf(GridCustDialogBrickType.Drag) === -1)
    firstDraggableColumnState = state;
   if(firstDraggableColumnState)
    result.push(state.columnIndex);
  }
  return result;
 },
 OnPopUp: function() {
  this.AttachEvents();
 },
 OnCloseUp: function() {
  this.DetachEvents();
 },
 TranslateYPos: function(y, fromRelative) {
  var dir = fromRelative ? 1 : -1;
  return y + dir * ASPx.GetDocumentScrollTop();
 },
 GetEventY: function(e) { return this.TranslateYPos(ASPx.Evt.GetEventY(e)); },
 GetYDiff: function(eventY) { return eventY - this.dragInfo.initialY; },
 OnMouseDown: function(evt) {
  var src = ASPx.Evt.GetEventSource(evt);
  var dragPart = src.dxgvDragPart;
  if(!dragPart || ASPx.ElementHasCssClass(dragPart, this.dialogHelper.ColumnItemBrick_DisabledClassName)) 
   return;
  var columnIndices = this.GetDraggableColumnIndices();
  if(columnIndices.length < 1)
   return;
  var columnItem = this.GetPage().GetColumnItemByBrick(dragPart);
  this.dragInfo = this.CalcDragInfo(columnItem, columnIndices, this.GetEventY(evt));
  ASPx.AddClassNameToElement(columnItem, this.dialogHelper.DraggingItemClassName);
  this.SetTransformTransition(columnItem, true);
  this.ChangeColumnItemTransform(columnItem, 0);
  this.dialogHelper.ChangeDragPanelFixation(false);
  ASPx.Selection.Clear();
 },
 OnMouseMove: function(evt) {
  if(!this.dragInfo) return;
  var eventY = this.GetEventY(evt);
  this.ReorderColumnItems(eventY);
  if(this.IsPositionInScrollableArea(eventY)) {
   if(this.customScrollInfo)
    this.DoCustomScroll();
   this.customScrollInfo = this.CalcCustomScrollInfo(eventY);
   this.StartCustomScroll();
  } else
   this.CancelCustomScroll();
  ASPx.Evt.PreventEvent(evt); 
 },
 OnMouseUp: function(evt) {
  if(!this.dragInfo) return;
  this.CancelCustomScroll();
  var yDiff = this.GetEventY(evt) - this.dragInfo.initialY;
  var newColumnIndices = this.ReOrderColumnIndices(yDiff);
  this.ApplyChanges(newColumnIndices);
  var offset = this.CalcColumnOffsetOnEndDrag(newColumnIndices);
  ASPx.RemoveClassNameFromElement(this.dragInfo.draggableColumnItem, this.dialogHelper.DraggingItemClassName);
  this.ChangeColumnItemTransform(this.dragInfo.draggableColumnItem, offset);
  this.prevYDiff = null;
  this.dragInfo = null;
  window.setTimeout(function() {
   newColumnIndices.forEach(function(i) { ASPx.RemoveElement(this.GetColumnItem(i)); }.bind(this));
   this.dialogHelper.UpdateCurrentDialogPage();
  }.bind(this), 200);
 },
 PreventEventOnDrag: function(evt) {
  if(this.dragInfo)
   ASPx.Evt.PreventEvent(evt);
 },
 CalcDragInfo: function(columnItem, columnIndices, y) {
  var columnIndex = columnItem.dxgvColumnIndex;
  var columnItems = ASPx.Data.ArrayToHash(columnIndices, function(i) { return i; }, function(i) { return this.GetColumnItem(i); }.bind(this));
  var columnHeights = ASPx.Data.ArrayToHash(columnIndices, function(i) { return i; }, function(i) { return this.GetColumnItem(i).offsetHeight; }.bind(this));
  var separatorHeight = ASPx.PxToInt(ASPx.GetCurrentStyle(this.GetColumnItem(columnIndices[0])).marginBottom);
  return { 
   initialY: y,
   columnIndex: columnIndex,
   columnIndices: columnIndices,
   columnItems: columnItems,
   columnHeights: columnHeights,
   draggableColumnItem: columnItem,
   draggableColumnHeight: columnHeights[columnIndex],
   separatorHeight: separatorHeight,
   columnBounds: this.CalcColumnBounds(columnIndices, columnHeights, separatorHeight, columnIndex),
   scrollBounds: this.CalcCustomScrollBounds(columnIndex, columnItem, columnHeights, columnIndices, separatorHeight, y)
  };
 },
 CalcCustomScrollBounds: function(columnIndex, columnItem, columnHeights, columnIndices, separatorHeight, y) {
  var maxColumnHeight = ASPx.Data.Max(Object.keys(columnHeights), function(key) { return columnHeights[key]; });
  var scrollAreaHeight = maxColumnHeight * this.scrollAreaHeightMultiplicator;
  var leftOffset = y - this.TranslateYPos(ASPx.GetAbsoluteY(columnItem));
  var rightOffset = columnHeights[columnIndex] - leftOffset; 
  var windowHeight = ASPx.GetDocumentClientHeight();
  var left = scrollAreaHeight + leftOffset;
  var right = windowHeight - scrollAreaHeight - rightOffset;
  var notDragColumnIndices = columnIndices.filter(function(i) { return i !== columnIndex; });
  var leftIndices = [ columnIndex ].concat(notDragColumnIndices);
  var rightIndices = notDragColumnIndices.concat([ columnIndex ]);
  var leftOffset = this.CalcColumnOffsetOnEndDragCore(columnIndex, columnIndices, leftIndices, columnHeights, separatorHeight);
  var rightOffset = this.CalcColumnOffsetOnEndDragCore(columnIndex, columnIndices, rightIndices, columnHeights, separatorHeight);
  var leftStopOffset = leftOffset - maxColumnHeight / 2;
  var rightStopOffset = rightOffset + maxColumnHeight / 2;
  return { 
   left: left,
   right: right,
   stopLeft: leftStopOffset,
   stopRight: rightStopOffset,
   maxColumnHeight: maxColumnHeight,
   scrollAreaHeight: scrollAreaHeight
  };
 },
 IsPositionInScrollableArea: function(y) { 
  return y < this.dragInfo.scrollBounds.left || y > this.dragInfo.scrollBounds.right; 
 },
 CalcCustomScrollInfo: function(y) {
  var scrollTop = this.GetScrollableControl().scrollTop;
  var bounds = this.dragInfo.scrollBounds;
  var requireScrollTop = y < bounds.left;
  var bound = requireScrollTop ? bounds.left : bounds.right;
  var distanceToBound = Math.min(Math.abs(y - bound), bounds.scrollAreaHeight);
  var velocity = this.CalcCustomScrollVelocity(this.minScrollVelocity, this.maxScrollVelocity, bounds.scrollAreaHeight, distanceToBound, requireScrollTop ? -1 : 1);
  return {
   y: y,
   velocity: velocity,
   scrollTop: scrollTop,
   initialY: this.dragInfo.initialY,
   startTimer: new Date()
  };
 },
 CalcCustomScrollVelocity: function(minVelocity, maxVelocity, scrollAreaHeight, distanceToBound, sign) {
  var value = (maxVelocity - minVelocity) * distanceToBound / scrollAreaHeight + minVelocity;
  return value * sign;
 },
 StartCustomScroll: function() {
  if(this.customScrollTimer === -1)
   this.customScrollTimer = window.setInterval(this.DoCustomScroll.bind(this), this.customScrollTimeout);
 },
 CancelCustomScroll: function() {
  this.customScrollTimer = ASPx.Timer.ClearTimer(this.customScrollTimer);
  this.customScrollInfo = null;
 },
 DoCustomScroll: function() {
  var info = this.customScrollInfo;
  if(this.IsScrolledOutOfBounds(info.y)) {
   this.CancelCustomScroll();
   return;
  }
  var timeStamp = new Date() - info.startTimer;
  var scrollInc = Math.round(info.velocity * timeStamp);
  if(scrollInc === 0)
   return;
  var scrollableControl = this.GetScrollableControl();
  scrollableControl.scrollTop = info.scrollTop + scrollInc;
  this.dragInfo.initialY = info.initialY - scrollInc;
  this.ReorderColumnItems(info.y);
 },
 IsScrolledOutOfBounds: function(y) {
  var yDiff = this.GetYDiff(y);
  var scrollBounds = this.dragInfo.scrollBounds;
  return yDiff > scrollBounds.stopRight || yDiff < scrollBounds.stopLeft;
 },
 ReorderColumnItems: function(eventY) {
  var yDiff = this.GetYDiff(eventY);
  if(yDiff === this.prevYDiff)
   return;
  this.MoveColumnItems(yDiff);
  this.prevYDiff = yDiff;
  ASPx.Selection.Clear();
 },
 MoveColumnItems: function(yDiff) {
  var columnItems = this.dragInfo.columnItems;
  var columnOffsets = this.CalcColumnOffsets(yDiff);
  for(var columnIndex in columnOffsets) {
   if(!columnOffsets.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   this.ChangeColumnItemTransform(columnItems[columnIndex], columnOffsets[columnIndex]);
  }
 },
 ApplyChanges: function(columnIndices) {
  var pageType = this.GetPage().GetPageType();
  if(pageType === GridCustDialogPageType.Sorting)
   columnIndices.forEach(function(columnIndex, i) { this.GetColumnState(columnIndex).sortIndex = i; }.bind(this));
  if(pageType === GridCustDialogPageType.Grouping)
   columnIndices.forEach(function(columnIndex, i) { this.GetColumnState(columnIndex).groupIndex = i; }.bind(this));
  if(pageType === GridCustDialogPageType.FieldChooser)
   columnIndices.forEach(function(columnIndex, i) { this.GetColumnState(columnIndex).visibleIndex = i; }.bind(this));
 },
 CalcColumnOffsetOnEndDrag: function(newColumnIndices) {
  return this.CalcColumnOffsetOnEndDragCore(this.dragInfo.columnIndex, this.dragInfo.columnIndices, newColumnIndices, this.dragInfo.columnHeights, this.dragInfo.separatorHeight);
 },
 CalcColumnOffsetOnEndDragCore: function(columnIndex, columnIndices, newColumnIndices, columnHeights, separatorHeight) { 
  var visibleIndex = columnIndices.indexOf(columnIndex);
  var newVisibleIndex = newColumnIndices.indexOf(columnIndex);
  if(visibleIndex === newVisibleIndex) 
   return 0;
  var moveToTop = newVisibleIndex < visibleIndex;
  var betweenColumnIndices = [ ];
  if(moveToTop)
   betweenColumnIndices = columnIndices.slice(newVisibleIndex, visibleIndex);
  else
   betweenColumnIndices = newColumnIndices.slice(visibleIndex, newVisibleIndex);
  var height = ASPx.Data.Sum(betweenColumnIndices, function(i) { return columnHeights[i]; });
  var offset = height + separatorHeight * betweenColumnIndices.length;
  if(moveToTop)
   offset *= -1;
  return offset;
 },
 CalcColumnOffsets: function(yDiff) { 
  var newColumnIndices = this.ReOrderColumnIndices(yDiff);
  return this.CalcColumnOffsetsCore(this.dragInfo.columnIndices, newColumnIndices, this.dragInfo.draggableColumnHeight, this.dragInfo.separatorHeight, this.dragInfo.columnIndex, yDiff);
 },
 CalcColumnOffsetsCore: function(columnIndices, newColumnIndices, draggableColumnHeight, separatorHeight, draggableColumnIndex, yDiff) {
  var result = { };
  for(var visibleIndex = 0; visibleIndex < columnIndices.length; visibleIndex++) {
   var columnIndex = columnIndices[visibleIndex];
   var newVisibleIndex = newColumnIndices.indexOf(columnIndex);
   var offset = 0;
   if(columnIndex === draggableColumnIndex) {
    offset = yDiff;
   } else if(newVisibleIndex !== visibleIndex) {
    offset = draggableColumnHeight + separatorHeight;
    if(newVisibleIndex < visibleIndex)
     offset *= -1;
   }
   result[columnIndex] = offset;
  }
  return result;
 },
 ReOrderColumnIndices: function(yDiff) {
  return this.ReOrderColumnIndicesCore(this.dragInfo.columnIndices, this.dragInfo.columnBounds, this.dragInfo.columnIndex, yDiff);
 },
 ReOrderColumnIndicesCore: function(columnIndices, columnBounds, columnIndex, yDiff) {
  var visibleIndex = columnIndices.indexOf(columnIndex);
  var newVisibleIndex = this.CalcNewColumnPosition(columnIndices, columnBounds, yDiff);
  if(visibleIndex === newVisibleIndex)
   return columnIndices;
  var result = columnIndices.slice();
  ASPx.Data.ArrayRemoveAt(result, visibleIndex);
  ASPx.Data.ArrayInsert(result, columnIndex, newVisibleIndex);
  return result;
 },
 CalcNewColumnPosition: function(columnIndices, columnBounds, yDiff) {
  for(var columnIndex in columnBounds) {
   if(!columnBounds.hasOwnProperty(columnIndex)) continue;
   columnIndex = parseInt(columnIndex);
   var bounds = columnBounds[columnIndex];
   if(yDiff >= bounds.left && yDiff <= bounds.right)
    return columnIndices.indexOf(columnIndex);
  }
  return -1;
 },
 CalcColumnBounds: function(columnIndices, columnHeights, separatorHeight, draggableColumnIndex) {
  var draggableColumnVisibleIndex = columnIndices.indexOf(draggableColumnIndex);
  var topColumnIndices = draggableColumnVisibleIndex === 0 ? [ ] : columnIndices.slice(0, draggableColumnVisibleIndex);
  topColumnIndices.reverse();
  var bottomColumnIndices = (draggableColumnVisibleIndex === columnIndices.length - 1) ? [ ] : columnIndices.slice(draggableColumnVisibleIndex + 1);
  var topColumnBounds = this.CalcColumnBoundsCore(topColumnIndices, columnHeights, separatorHeight);
  var bottomColumnBounds = this.CalcColumnBoundsCore(bottomColumnIndices, columnHeights, separatorHeight);
  var result = { };
  for(var columnIndex in topColumnBounds) {
   if(!topColumnBounds.hasOwnProperty(columnIndex)) continue;
   var bounds = topColumnBounds[columnIndex];
   var left = bounds.left;
   var right = !isNaN(bounds.right) ? bounds.right : this.hugePos;
   result[columnIndex] = { left: right * -1, right: left * -1 };
  }
  for(var columnIndex in bottomColumnBounds) {
   if(!bottomColumnBounds.hasOwnProperty(columnIndex)) continue;
   var bounds = bottomColumnBounds[columnIndex];
   var left = bounds.left;
   var right = !isNaN(bounds.right) ? bounds.right : this.hugePos;
   result[columnIndex] = { left: left, right: right };
  }
  var firstTopColumnIndex = topColumnIndices.length > 0 ? topColumnIndices[0] : -1;
  var firstBottomColumnIndex = bottomColumnIndices.length > 0 ? bottomColumnIndices[0] : -1;
  var draggableColumnLeft = firstTopColumnIndex > -1 ? result[firstTopColumnIndex].right + 1 : this.hugePos * -1;
  var draggableColumnRight = firstBottomColumnIndex > -1 ? result[firstBottomColumnIndex].left - 1 : this.hugePos;
  result[draggableColumnIndex] = { left: draggableColumnLeft, right: draggableColumnRight };
  return result;
 },
 CalcColumnBoundsCore: function(columnIndices, columnHeights, separatorHeight) { 
  if(columnIndices.length === 0)
   return { };
  var middlePositions = { };
  var totalHeight = 0;
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var height = columnHeights[columnIndex];
   totalHeight += separatorHeight;
   middlePositions[columnIndex] = totalHeight + Math.floor(height / 2);
   totalHeight += height;
  }
  var result = { };
  for(var i = 0; i < columnIndices.length; i++) {
   var columnIndex = columnIndices[i];
   var isLastColumn = i === columnIndices.length - 1;
   var nextColumnIndex = !isLastColumn ? columnIndices[i + 1] : -1;
   result[columnIndex] = { 
    left: middlePositions[columnIndex] + 1,
    right: nextColumnIndex > -1 ? middlePositions[nextColumnIndex] : NaN
   };
  }
  return result;
 },
 ChangeColumnItemTransform: function(columnItem, value) { 
  if(columnItem.assignedTransform === value)
   return;
  var translateValue = "translate(0, " + value + "px)";
  var style = { };
  style.transform = translateValue;
  style.msTransform = translateValue;
  style.webkitTransform = translateValue;
  ASPx.SetStyles(columnItem, style);
  columnItem.assignedTransform = value;
 },
 SetTransformTransition: function(element, resetAfterTimeout) { 
  var value = resetAfterTimeout ? "transform 0.2s" : "";
  ASPx.SetStyles(element, { transition: value, msTransition: value, webkitTransition: value });
  if(resetAfterTimeout)
   window.setTimeout(function() { this.SetTransformTransition(element, false); }.bind(this), 200);
 },
 AttachEvents: function() {
  this.mouseDownHandler = this.OnMouseDown.bind(this);
  this.mouseMoveHandler = this.OnMouseMove.bind(this);
  this.mouseUpHandler = this.OnMouseUp.bind(this);
  this.mouseWheelHandler = this.PreventEventOnDrag.bind(this);
  this.contextMenuHandler = this.PreventEventOnDrag.bind(this);
  ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, this.mouseDownHandler);
  ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
  ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
  ASPx.Evt.AttachEventToDocument(ASPx.Evt.GetMouseWheelEventName(), this.mouseWheelHandler);
  ASPx.Evt.AttachEventToDocument("contextmenu", this.contextMenuHandler);
 },
 DetachEvents: function() {
  ASPx.Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseDownEventName, this.mouseDownHandler);
  ASPx.Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseMoveEventName, this.mouseMoveHandler);
  ASPx.Evt.DetachEventFromDocument(ASPx.TouchUIHelper.touchMouseUpEventName, this.mouseUpHandler);
  ASPx.Evt.DetachEventFromDocument(ASPx.Evt.GetMouseWheelEventName(), this.mouseWheelHandler);
  ASPx.Evt.DetachEventFromDocument("contextmenu", this.contextMenuHandler);
 }
});
var CustDialogCheckableElementHelper = ASPx.CreateClass(ASPx.CheckableElementHelper, {
 InternalCheckBoxInitialize: function(internalCheckBox) {
  this.AttachToMainElement(internalCheckBox);
 },
 InvokeClick: function(internalCheckBox, evt) {
  ASPx.CheckableElementHelper.prototype.InvokeClick.call(this, internalCheckBox, evt);
 },
 RequirePreventFocus: function() { return ASPx.Browser.MacOSMobilePlatform; }
});
ASPx.GridViewCustDialogColumnDragHelper = GridViewCustDialogColumnDragHelper;
ASPx.GridViewCustDialogHelper = GridViewCustDialogHelper;
})();

(function () {
var compositeKeyNameSeparator = ";";
var compositeKeyValueSeparator = "|";
var MVCxGridAdapter = ASPx.CreateClass(null, {
 constructor: function(grid){
  this.grid = grid;
 },
 AssignCallbackRoutes: function(){
  var grid = this.grid;
  if(grid.callbackUrl)
   grid.callBack = function(arg){ MVCx.PerformControlCallback(grid.name, grid.callbackUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); };
  if(grid.deleteSelectedItemsUrl)
   grid.deleteSelectedItemsCallBack = function(arg){ MVCx.PerformControlCallback(grid.name, grid.deleteSelectedItemsUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); };
  if(grid.addNewItemUrl)
   grid.addNewItemCallBack = function (arg) { MVCx.PerformControlCallback(grid.name, grid.addNewItemUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); };
  if(grid.updateItemUrl)
   grid.updateItemCallBack = function (arg) { MVCx.PerformControlCallback(grid.name, grid.updateItemUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); };
  if(grid.deleteItemUrl)
   grid.deleteItemCallBack = function (arg) { MVCx.PerformControlCallback(grid.name, grid.deleteItemUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); };
  if(grid.allowBatchEditing && grid.batchUpdateUrl)
   grid.batchUpdateCallBack = function(arg) { MVCx.PerformControlCallback(grid.name, grid.batchUpdateUrl, arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); }; 
  for(var command in grid.callbackActionUrlCollection)
   if(grid.callbackActionUrlCollection.hasOwnProperty(command))
    (function(command) {
     grid.callbackMethods[command] = function(arg) {
      MVCx.PerformControlCallback(grid.name, grid.callbackActionUrlCollection[command], arg, grid.GetCallbackParams(arg), grid.callbackCustomArgs); 
     };
    }).call(this, command);
 },
 ValidateEditorsByJQuery: function(){
  var isValid = true;
  var jQValidation = MVCx.JQueryValidation;
  if(jQValidation.IsEnabled(this.grid)){
   this.PrepareUnobtrusiveValidation();
   $.each(this.GetEditorsToValidate(), function(i, editor){
    isValid &= jQValidation.Validate(editor);
   });
   if(jQValidation.HasPendingRequests(this.grid)){
    jQValidation.SetOnStopRequestHandler(this.grid, this.grid.UpdateEdit.aspxBind(this.grid));
    isValid = false;
   }
  }
  return isValid;
 },
 PrepareUnobtrusiveValidation: function(){
  MVCx.JQueryValidation.PrepareUVRules(this.grid, function() { this.ResolveRemoteValidation(); }.aspxBind(this));
 },
 ResolveRemoteValidation: function(){
  var context = this;
  var fieldsMapMarker = "data-val-remote-dxfieldsmap";
  var editors = this.GetEditorsToValidate();
  for(var i = 0; i < editors.length; i++){
   $input = $(MVCx.GetValueInputElement(editors[i]));
   if($input.attr("data-val-remote-additionalfields") && !$input.attr(fieldsMapMarker))
    $input.attr(fieldsMapMarker, JSON.stringify(context.GetFieldsMap()));
  }
 },
 GetFieldsMap: function(){
  var fieldsMap = {};
  var columns = this.grid.columns;
  for(var i = 0; i < columns.length; i++){
   var editor = this.grid.GetEditor(columns[i]);
   if(editor)
    fieldsMap[columns[i].fieldName] = editor.name;
  }
  return fieldsMap;
 },
 GetEditorsToValidate: function(){
  var editors = this.grid._getEditors() || [];
  var container = this.grid.GetMainElement();
  var controlCollection = ASPx.GetControlCollection();
  $.each(this.grid.columns, function(i, column){
   var control = controlCollection.Get(column.fieldName);
   if(control && ASPx.Ident.IsASPxClientEdit(control) && controlCollection.IsControlInContainer(container, control))
    editors.push(control);
  });
  return editors;
 },
 GetCallbackMethod: function(command){
  var grid = this.grid;
  if(command == "FUNCTION")
   return grid.funcCallbackMethod || grid.callBack;
  if(command == ASPxClientGridViewCallbackCommand.DeleteRow)
   return grid.deleteItemCallBack;
  if(command == ASPxClientGridViewCallbackCommand.UpdateEdit && grid.allowBatchEditing)
   return grid.batchUpdateCallBack;
  if(command == ASPxClientGridViewCallbackCommand.UpdateEdit)
   return grid.IsNewItemEditing() ? grid.addNewItemCallBack : grid.updateItemCallBack;
  if(grid.deleteSelectedItemsOnPage)
   return grid.deleteSelectedItemsCallBack;
  return grid.callbackMethods[command] || grid.callBack;
 },
 GetCallbackParams: function(arg){
  var params = {};
  var predicate = this.GetRequireAddEditorParamPredicate(arg);
  MVCx.AddCallbackParam(params, this.grid.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.grid.GetMainElement(), predicate);
  this.AddEditingCallbackParams(params, predicate);
  this.AddSelectedKeysParams(params);
  return params;
 },
 GetRequireAddEditorParamPredicate: function(arg) {
  if(!arg || arg.indexOf(ASPxClientGridViewCallbackCommand.StartEdit) === -1 && arg.indexOf(ASPxClientGridViewCallbackCommand.AddNewRow) === -1)
   return null;
  var formCell = this.grid.GetEditFormTableCell && this.grid.GetEditFormTableCell();
  if(!formCell)
   return null;
  return function(input, clientEditor) { return this.RequireAddEditorParam(formCell, input, clientEditor); }.bind(this);
 },
 RequireAddEditorParam: function(container, input, clientEditor) {
  var element = input || clientEditor.GetMainElement();
  return !ASPx.GetIsParent(container, element);
 },
 AddEditingCallbackParams: function(params, addEditorValuePredicate){
  if(this.grid.IsEditing() || this.grid.deleteKeyValue)
   this.AddEditorsCallbackParams(params, addEditorValuePredicate);
  if(this.grid.allowBatchEditing)
   this.AddBatchEditingCallbackParams(params);
 },
 AddEditorsCallbackParams: function(params, addEditorValuePredicate){
  var grid = this.grid;
  var editFields = [];
  var editors = grid._getEditors();
  for(var i = 0; i < editors.length; i++){
   if(addEditorValuePredicate && !addEditorValuePredicate(null, editors[i]))
    continue;
   var editorIndex = grid.GetEditorIndex(editors[i].name);
   var column = grid.GetColumn(editorIndex);
   params[column.fieldName] = ASPx.Json.ToJson(MVCx.GetEditorValueByControl(editors[i]));
   editFields.push(column.fieldName);
  }
  this.AddKeyValueParams(params, editFields);
  if(editFields.length > 0)
   params["DXMVCGridEditFields"] = ASPx.Json.ToJson(editFields);
  MVCx.AddDXEditorValuesInContainer(params, grid.GetMainElement(), addEditorValuePredicate);
 },
 AddKeyValueParams: function(params, editFields){
  var grid = this.grid;
  var keyFields = this.GetKeyFieldNames();
  if(keyFields.length == 0)
   return;
  var keyValues;
  if(grid.deleteKeyValue)
   keyValues = grid.deleteKeyValue;
  else if(!grid.IsNewItemEditing() && grid.editingItemVisibleIndex > -1)
   keyValues = grid.GetItemKey(grid.editingItemVisibleIndex);
  if(keyValues){
   keyValues = this.IsCompositeKey() ? keyValues.split(compositeKeyValueSeparator) : [ keyValues ];
   var keyCount = Math.min(keyFields.length, keyValues.length);
   for(var i = 0; i < keyCount; i++){
    var keyName = keyFields[i];
    params[keyName] = ASPx.Json.ToJson(keyValues[i]);
    if(editFields.indexOf(keyName) < 0)
     editFields.push(keyName);
   }
  }
 },
 IsCompositeKey: function() {
  return this.grid.keyName.indexOf(compositeKeyNameSeparator) > -1;
 },
 GetKeyFieldNames: function(){
  if(!this.grid.keyName)
   return [ ];
  if(this.IsCompositeKey())
   return this.grid.keyName.split(compositeKeyNameSeparator);
  return [ this.grid.keyName ];
 },
 AddBatchEditingCallbackParams: function(params){
  params["DXMVCBatchEditingValuesRequestKey"] = this.grid.uniqueID;
  params["DXMVCBatchEditingKeyFieldName"] = this.grid.keyName;
 },
 AddSelectedKeysParams: function(params){
  if(this.grid.deleteSelectedItemsOnPage)
   params["DXMVCGridSelectedKeys"] = ASPx.Json.ToJson(this.grid.GetSelectedKeysOnPage());
 },
 GridCallBack: function(args) {
  if(args[0] === ASPxClientGridViewCallbackCommand.Sort)
   this.grid.callbackCustomArgs["reset"] = args[4];
  else if(args[0] === ASPxClientGridViewCallbackCommand.Toolbar && args[1] === "DeleteSelectedVisible")
   this.grid.deleteSelectedItemsOnPage = true;
 },
 OnAfterCallback: function() {
  delete this.grid.deleteSelectedItemsOnPage;
  MVCx.JQueryValidation.ResetUVRules(this.grid);
 },
 ExportTo: function(format) {
  this.GridPerformExportCallback([ASPxClientGridViewCallbackCommand.Export, format]);
 },
 GetExportCallbackArgs: function(args) {
  var grid = this.grid,
   callbackHelper = grid.GetCallbackHelper();
  return callbackHelper.SerializeCallbackArgs(args);
 },
 GridPerformExportCallback: function(args) {
  var grid = this.grid,
   form = grid.GetParentForm();
  if(form) {
   grid.RaiseBeginCallback(ASPxClientGridViewCallbackCommand.Export);
   var exportCallbackArgs = this.GetExportCallbackArgs(args);
   MVCx.PerformExportCallback(form, grid.name, grid.callbackUrl, exportCallbackArgs, grid.callbackCustomArgs, function() {
    grid.callbackCustomArgs = {};
    grid.RaiseEndCallback();
   }.aspxBind(this));
  }
  else
   ASPx.ShowErrorMessage('The form is not found. Make sure that the extension is located inside the <form> tag to make exporting work properly.');
 },
 DoGridCallbackError: function(errorMessage) {
  var grid = this.grid;
  ASPxClientGridBase.prototype.DoCallbackError.call(grid, errorMessage);
  grid.SetAfterCallbackRequired();
  grid.DoEndCallback();
 }
});
var BatchEditHelperAdapter = ASPx.CreateClass(null, {
 constructor: function(owner) {
  this.owner = owner;
 },
 GetOwnerControl: function() { return this.owner.GetOwnerControl(); },
 GetEditColumnIndices: function() { return this.owner.GetEditColumnIndices(); },
 PrepareUnobtrusiveValidation: function() { this.owner.PrepareUnobtrusiveValidation(); },
 GetEditor: function(columnIndex) { return this.owner.GetEditor(columnIndex); },
 GetColumnIndex: function(fieldName) { return this.owner.GetColumnIndex(fieldName); },
 GetIsJQueryValidationEnabled: function() { return MVCx.JQueryValidation.IsEnabled(this.GetOwnerControl()); },
 PrepareEditorsValidation: function(){
  if(!this.GetIsJQueryValidationEnabled())
   return;
  this.owner.PrepareUnobtrusiveValidation();
  var columnIndices = this.GetEditColumnIndices();
  for(var i = 0; i < columnIndices.length; i++) {
   var editor = this.GetEditor(columnIndices[i]);
   if(editor) {
    editor.GotFocus.AddHandler(function(s){ $.validator.prototype.lastElement = s.GetInputElement(); });
    editor.LostFocus.AddHandler(function(s) { $.validator.lastElement = null; });
   }
  }
 },
 SafeCallValidateItem: function(validateItemFunc) {
  var oldValidateInvisibleEditors = MVCx.validateInvisibleEditors;
  try {
   MVCx.validateInvisibleEditors = true;
   return validateItemFunc();
  } finally{
   MVCx.validateInvisibleEditors = oldValidateInvisibleEditors;
  }
 },
 ValidateEditor: function(editor){
  if(this.GetIsJQueryValidationEnabled()) {
   var jQValidation = MVCx.JQueryValidation;
   jQValidation.Validate(editor);
   if(jQValidation.HasPendingRequests(this.GetOwnerControl()))
    this.SetHandlerAtEndingRequest(editor);
  }
 },
 SetHandlerAtEndingRequest : function(editor) {
  var helper = this.owner;
  var key = helper.editingRecordKey;
  MVCx.JQueryValidation.SetOnStopRequestHandler(this.GetOwnerControl(), function() {
   if(editor.GetValue() !== helper.GetCellValue(key, columnIndex)) return;
   if(!editor.GetIsValid()) {
    helper.ApplyCellValidationError(key, columnIndex, MVCx.JQueryValidation.GetValidationErrorMessage(editor));
    editor.SetIsValid(true);
   } else
    helper.ResetCellValidationError(key, columnIndex);
  }.bind(this));
 },
 GetUVRemoteAdditionalColumnIndices: function(columnIndices) {
  var indices = [ ].concat(columnIndices);
  for(var i = 0; i < columnIndices.length; i++) {
   var editor = this.GetEditor(columnIndices[i]);
   var fields = editor && editor.uvRemoteAdditionalFields;
   if(!fields) continue;
   for(var j = 0; j < fields.length; j++) {
    var index = this.GetColumnIndex(fields[j]);
    if(ASPx.IsExists(index) && indices.indexOf(index) === -1)
     indices.push(index);
   }
  }
  return indices;
 }
});
var GridToolbarHelperAdapter = ASPx.CreateClass(null, {
 constructor: function() {
  this.toolbarHelper = null;
 },
 Init: function(toolbarHelper) {
  this.toolbarHelper = toolbarHelper;
 },
 SendExportCommand: function(toolbarIndex, indexPath, exportFormat) {
  var grid = this.toolbarHelper.grid;
  grid.gridAdapter.GridPerformExportCallback([ASPxClientGridViewCallbackCommand.Toolbar, ASPxClientGridViewCallbackCommand.Export, toolbarIndex, indexPath, exportFormat]);
 }
});
function InitUnobtrusiveRules(name, rules){
 var editor = ASPx.GetControlCollection().Get(name);
 MVCx.JQueryValidation.SetUVAttributes(editor, rules);
}
MVCx.GridAdapter = MVCxGridAdapter;
MVCx.BatchEditHelperAdapter = BatchEditHelperAdapter;
MVCx.GridToolbarHelperAdapter = GridToolbarHelperAdapter;
MVCx.InitUnobtrusiveRules = InitUnobtrusiveRules;
})();

(function () {
var MVCxGridBatchEditHelper = ASPx.CreateClass(ASPx.GridBatchEditHelper, {
 constructor: function(owner) { 
  this.constructor.prototype.constructor.call(this, owner);
  this.adapter = new MVCx.BatchEditHelperAdapter(this);
 },
 PrepareUnobtrusiveValidation: function() { this.grid.gridAdapter.PrepareUnobtrusiveValidation(); },
 GetColumnIndex: function(fieldName) { return this.grid._getColumnIndexByColumnArgs(fieldName); },
 Init: function(){
  ASPx.GridBatchEditHelper.prototype.Init.call(this);
  this.adapter.PrepareEditorsValidation();
 },
 OnAfterCallback: function(){
  ASPx.GridBatchEditHelper.prototype.OnAfterCallback.call(this);
  this.adapter.PrepareEditorsValidation();
 },
 SetEditorValues: function(itemValues, columnIndices) {
  columnIndices = this.adapter.GetUVRemoteAdditionalColumnIndices(columnIndices);
  ASPx.GridBatchEditHelper.prototype.SetEditorValues.call(this, itemValues, columnIndices);
 },
 ValidateItem: function(key, itemValues, validateNotModified) {
  return this.adapter.SafeCallValidateItem(
   function(){ return ASPx.GridBatchEditHelper.prototype.ValidateItem.call(this, key, itemValues, validateNotModified); }.bind(this)
  );
 },
 ValidateEditor: function(editor){
  ASPx.GridBatchEditHelper.prototype.ValidateEditor.call(this, editor);
  if(editor.GetIsValid())
   this.adapter.ValidateEditor(editor);
 }
});
MVCx.MVCxGridBatchEditHelper = MVCxGridBatchEditHelper;
})();

(function() {
var MVCxClientGridView = ASPx.CreateClass(ASPxClientGridView, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.customActionUrl = "";
  this.addNewItemUrl = "";
  this.updateItemUrl = "";
  this.deleteItemUrl = "";
  this.batchUpdateUrl = "";
  this.callbackCustomArgs = {};
  this.callbackActionUrlCollection = {};
  this.deleteSelectedItemsCallBack = undefined;
  this.customActionCallBack = undefined;
  this.addNewItemCallBack = undefined;
  this.updateItemCallBack = undefined;
  this.deleteItemCallBack = undefined;
  this.batchUpdateCallBack = undefined;
  this.callbackMethods = {};
  this.funcCallbackMethod = undefined;
  this.deleteKeyValue = undefined;
  this.gridAdapter = new MVCx.GridAdapter(this);
 },
 PerformCallback: function(data, onSuccess){
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientGridView.prototype.PerformCallback.call(this, data, onSuccess);
 },
 GetValuesOnCustomCallback: function(data, onCallback) {
  this.funcCallbackMethod = this.callbackMethods[ASPxClientGridViewCallbackCommand.CustomValues];
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientGridView.prototype.GetValuesOnCustomCallback.call(this, data, onCallback);
 },
 InlineInitialize: function(){
  this.gridAdapter.AssignCallbackRoutes();
  ASPxClientGridView.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command){
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetSortingCallbackParamsMethod: function(arg){
  var param = this.GetCallbackParams(arg);
  return param;
 },
 GetCallbackParams: function(arg) {
  return this.gridAdapter.GetCallbackParams(arg);
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientGridView.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientGridView.prototype.EvalCallbackResult.call(this, resultString);
 },
 CreateCallbackCore: function(arg, command, callbackID){
  if(this.callbackCustomArgs != {})
   window.setTimeout(function(){ this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  if(this.funcCallbackMethod)
   window.setTimeout(function() { this.funcCallbackMethod = null; }.aspxBind(this), 0);
  ASPxClientGridView.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 GetCallbackMethod: function(command) {
  return this.gridAdapter.GetCallbackMethod(command);
 },
 DeleteItemByKey: function(key) {
  this.deleteKeyValue = key;
  ASPxClientGridView.prototype.DeleteItemByKey.call(this, key);
 },
 gridCallBack: function(args, handler) {
  this.gridAdapter.GridCallBack(args);
  ASPxClientGridView.prototype.gridCallBack.call(this, args, handler);
 },
 OnAfterCallback: function() {
  delete this.deleteKeyValue;
  this.gridAdapter.OnAfterCallback();
  ASPxClientGridView.prototype.OnAfterCallback.call(this);
 },
 DoCallbackError: function(errorMessage) {
  this.gridAdapter.DoGridCallbackError(errorMessage);  
 },
 ShowCallbackErrorCore: function(displayIn, errorText) {
  ASPxClientGridView.prototype.ShowCallbackErrorCore.call(this, displayIn, errorText);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 },
 ExportTo: function(format) {
  this.gridAdapter.ExportTo(format);
 },
 CreateToolbarHelper: function() {
  this.InitializeToolbarHelperClass();
  return new MVCxClientGridViewToolbarHelper(this, new MVCx.GridToolbarHelperAdapter());
 },
 InitializeToolbarHelperClass: function() {
  if(typeof(MVCxClientGridViewToolbarHelper) != 'undefined') return;
  MVCxClientGridViewToolbarHelper = ASPx.CreateClass(ASPx.GridViewToolbarHelper, {
   constructor: function(grid, toolbarHelperAdapter) { 
    this.constructor.prototype.constructor.call(this, grid);
    this.toolbarHelperAdapter = toolbarHelperAdapter;
    this.toolbarHelperAdapter.Init(this);
   },
   SendExportCommand: function(toolbarIndex, indexPath, exportFormat) {
    this.toolbarHelperAdapter.SendExportCommand(toolbarIndex, indexPath, exportFormat);
   }
  });
 },
 CreateContextMenuHelper: function() {
  this.InitializeContextMenuHelperClass();
  return new MVCxClientGridViewContextMenuHelper(this);
 },
 InitializeContextMenuHelperClass: function() {
  if(typeof(MVCxClientGridViewContextMenuHelper) != 'undefined') return;
  MVCxClientGridViewContextMenuHelper = ASPx.CreateClass(ASPx.GridViewContextMenuHelper, {
   SendExportCommand: function(menuType, itemPath, elementIndex, exportFormat) {
    var gridAdapter = this.grid.gridAdapter;
    gridAdapter.GridPerformExportCallback([ASPxClientGridViewCallbackCommand.ContextMenu, ASPxClientGridViewCallbackCommand.Export, menuType, itemPath, elementIndex, exportFormat]);
   }
  });
 },
 _validateEditors: function () {
  var isValid = ASPxClientGridView.prototype._validateEditors.call(this);
  if(isValid)
   isValid = this.gridAdapter.ValidateEditorsByJQuery();
  return isValid;
 },
 CreateBatchEditHelper: function(owner){ return new MVCx.MVCxGridBatchEditHelper(owner); }
});
MVCxClientGridView.Cast = ASPxClientControl.Cast;
window.MVCxClientGridView = MVCxClientGridView;
})();
(function() {
 var ASPxClientImageControlBase = ASPx.CreateClass(null, {
  constructor: function(control) {
   this.control = control;
   this.Initialize();
   this.CreateControlHierarchy();
   this.PrepareControlHierarchy();
   if(this.IsEnabled())
    this.InitializeHandlers();
  },
  Initialize: function() {
  },
  CreateControlHierarchy: function() {
  },
  PrepareControlHierarchy: function() {
  },
  AdjustControl: function() {
  },
  InitializeHandlers: function() {
  },
  IsEnabled: function() {
   return this.control.enabled;
  }
 });
 var ImageSizeModeEnum = {
  ActualSizeOrFit: 0,
  FitProportional: 1,
  FitAndCrop: 2
 };
 var RenderMode = {
  Image: 0,
  Canvas: 1
 };
 var Utils = {
  versions: {},
  GetKey: function(image) {
   return image.id + image.className;
  },
  RemoveLoadingGif: function(element) {
   ASPx.SetStyles(element, { backgroundImage: "url(" + ASPx.EmptyImageUrl + ")" });
  },
  IsImageLoaded: function(image) {
   return image.complete && image.naturalWidth !== undefined;
  },
  IsEmptyImageSource: function(image) {
   return !ASPx.Attr.GetAttribute(image, "src");
  },
  IsNotEmptyImageSize: function(image) {
   return image.naturalWidth && image.naturalHeight || image.width && image.height ? true : false;
  },
  TryGetImageSize: function(image, onComplete) {
   var fakeImage = new Image();
   ASPx.Evt.AttachEventToElement(fakeImage, "load", function(evt) {
    image.width = fakeImage.width;
    image.height = fakeImage.height;
    image.naturalWidth = fakeImage.width;
    image.naturalHeight = fakeImage.height;
    onComplete();
   });
   fakeImage.src = image.src;
  },
  ChangeImageSource: function(image, src, onComplete, onError) {
   var keyVersion = Utils.GetKey(image);
   Utils.versions[keyVersion] = (Utils.versions[keyVersion] + 1) || 0;
   var currentVersion = Utils.versions[keyVersion];
   var newImage = document.createElement("IMG");
   newImage.id = image.id;
   newImage.className = image.className;
   newImage.alt = image.alt;
   ASPx.Evt.AttachEventToElement(newImage, "load", function(evt) {
    if(Utils.versions[keyVersion] == currentVersion) {
     image.parentNode.appendChild(newImage);
     ASPx.RemoveElement(image);
     onComplete();
    }
   });
   if(onError)
    ASPx.Evt.AttachEventToElement(newImage, "error", function(evt) { onError(); });
   newImage.src = src;
  }
 };
 var ResizeUtils = {
  ResizeImage: function(image, options) {
   if(!Utils.IsNotEmptyImageSize(image)) 
    Utils.TryGetImageSize(image, function() { ResizeUtils.ResizeImageCore(image, options); });
   else
    ResizeUtils.ResizeImageCore(image, options);
  },
  ResizeImageCore: function(image, options) {
   var parent = image.parentNode;
   var canvas = ResizeUtils.GetCanvas(parent);
   var sizeMode = options.sizeMode == undefined ? ImageSizeModeEnum.ActualSizeOrFit : options.sizeMode;
   var properties = ResizeUtils.GetImageProperties(image.naturalWidth || image.width, image.naturalHeight || image.height, options.width, options.height, sizeMode);
   var useCanvas = properties.renderMode == RenderMode.Canvas && (options.canUseCanvas == undefined ? true : options.canUseCanvas);
   if(useCanvas) {
    if(canvas) {
     canvas.width = options.width;
     canvas.height = options.height;
     ResizeUtils.DrawImage(canvas, image, properties);
    }
    else {
     canvas = ResizeUtils.CreateCanvas(parent, options.width, options.height, image, properties);
     ASPx.RemoveElement(image);
    }
   }
   else {
    if(canvas)
     ASPx.RemoveElement(canvas);
    ResizeUtils.SetImageProperties(image, properties, options.rtl);
   }
   if(options.onEndResize)
    options.onEndResize(canvas || image, useCanvas);
  },
  SetImageProperties: function(image, properties, rtl) {
   var style = {
    marginTop: properties.y, display: ""
   };
   if(rtl)
    style.marginRight = properties.x;
   else
    style.marginLeft = properties.x;
   image.width = properties.w;
   image.height = properties.h;
   ASPx.SetStyles(image, style);
  },
  GetImageProperties: function(naturalWidth, naturalHeight, width, height, sizeMode) {
   var properties = {};
   switch (sizeMode) {
    case ImageSizeModeEnum.FitAndCrop:
     properties = ResizeUtils.GetFitAndCropImageProperties(naturalWidth, naturalHeight, width, height);
     break;
    case ImageSizeModeEnum.FitProportional:
     properties = ResizeUtils.GetFitProportionalImageProperties(naturalWidth, naturalHeight, width, height);
     break;
    case ImageSizeModeEnum.ActualSizeOrFit:
     properties = ResizeUtils.GetActualSizeOrFitImageProperties(naturalWidth, naturalHeight, width, height);
     break;
   }
   properties.renderMode = RenderMode.Image;
   if(window.HTMLCanvasElement && (naturalWidth > width * 2 || naturalHeight > height * 2)) {
    if(ASPx.Browser.MacOSMobilePlatform && (naturalWidth > 2200 || naturalHeight > 2200)) 
     properties.renderMode = RenderMode.Image;
    else
     properties.renderMode = RenderMode.Canvas;
   }
   return properties;
  },
  GetFitAndCropImageProperties: function(naturalWidth, naturalHeight, width, height) {
   var ratio = naturalWidth / naturalHeight;
   naturalWidth = width;
   naturalHeight = naturalWidth / ratio;
   if(naturalHeight < height) {
    naturalHeight = height;
    naturalWidth = naturalHeight * ratio;
   }
   var left = -(naturalWidth - width) / 2;
   var top = -(naturalHeight - height) / 2;
   return ResizeUtils.CreateImagePropertiesObject(naturalWidth, naturalHeight, left, top);
  },
  GetFitProportionalImageProperties: function(naturalWidth, naturalHeight, width, height) {
   var ratio = naturalWidth / naturalHeight;
   naturalWidth = width;
   naturalHeight = naturalWidth / ratio;
   if(naturalHeight > height) {
    naturalHeight = height;
    naturalWidth = naturalHeight * ratio;
   }
   var left = (width - naturalWidth) / 2;
   var top = (height - naturalHeight) / 2;
   return ResizeUtils.CreateImagePropertiesObject(naturalWidth, naturalHeight, left, top);
  },
  GetActualSizeOrFitImageProperties: function(naturalWidth, naturalHeight, width, height) {
   if(naturalWidth > width || naturalHeight > height)
    return ResizeUtils.GetFitProportionalImageProperties(naturalWidth, naturalHeight, width, height);
   return ResizeUtils.CreateImagePropertiesObject(naturalWidth, naturalHeight, (width - naturalWidth) / 2, (height - naturalHeight) / 2);
  },
  CreateImagePropertiesObject: function(w, h, x, y) {
   var obj = { w: w, h: h, x: x, y: y };
   obj.w = Math.round(obj.w);
   obj.h = Math.round(obj.h);
   obj.x = Math.round(obj.x);
   obj.y = Math.round(obj.y);
   return obj;
  },
  GetCanvas: function (container) {
   return ASPx.GetChildByTagName(container, "CANVAS");
  },
  CreateCanvas: function(container, width, height, image, properties) {
   var canvas = document.createElement("CANVAS");
   canvas.width = width;
   canvas.height = height;
   container.appendChild(canvas);
   if(image && properties)
    ResizeUtils.DrawImage(canvas, image, properties);
   return canvas;
  },
  DrawImage: function(canvas, image, properties) {
   var context = canvas.getContext("2d");
   context.drawImage(image, properties.x, properties.y, properties.w, properties.h);
  }
 };
 ASPx.ImageControlUtils = {};
 ASPx.ImageControlUtils.ResizeImage = ResizeUtils.ResizeImage;
 ASPx.ImageControlUtils.RemoveLoadingGif = Utils.RemoveLoadingGif;
 ASPx.ImageControlUtils.IsImageLoaded = Utils.IsImageLoaded;
 ASPx.ImageControlUtils.IsEmptyImageSource = Utils.IsEmptyImageSource;
 ASPx.ImageControlUtils.IsNotEmptyImageSize = Utils.IsNotEmptyImageSize;
 ASPx.ImageControlUtils.ChangeImageSource = Utils.ChangeImageSource;
 ASPx.ImageControlUtils.TryGetImageSize = Utils.TryGetImageSize;
 ASPx.ImageControlUtils.ImageSizeModeEnum = ImageSizeModeEnum;
 window.ASPxClientImageControlBase = ASPxClientImageControlBase;
})();

(function() {
 var Constants = {};
 Constants.Hash = "#dxig";
 Constants.InitialOpacityValue = 0;
 Constants.InitialFadedOpacityValue = 0.2;
 Constants.EmptyHash = " ";
 Constants.SlideAnimationDuration = 300;
 Constants.FadeAnimationDuration = 200;
 Constants.VirtualPagingCallbackCommand = "VIRTUALPAGING";
 var CssClassesConstants = {};
 CssClassesConstants.Prefix = "dxig-";
 CssClassesConstants.ThumbnailTextAreaClassName = CssClassesConstants.Prefix + "thumbnailTextArea";
 CssClassesConstants.ThumbnailBorderClassName = CssClassesConstants.Prefix + "thumbnailBorder";
 CssClassesConstants.ThumbnailWrapperClassName = CssClassesConstants.Prefix + "thumbnailWrapper";
 CssClassesConstants.ImageSliderWrapperClassName = CssClassesConstants.Prefix + "imageSliderWrapper";
 CssClassesConstants.BottomPanelClassName = CssClassesConstants.Prefix + "bottomPanel";
 CssClassesConstants.PrevButtonAreaClassName = CssClassesConstants.Prefix + "prevButtonArea";
 CssClassesConstants.NextButtonAreaClassName = CssClassesConstants.Prefix + "nextButtonArea";
 CssClassesConstants.NavigationBarMarkerClassName = CssClassesConstants.Prefix + "navigationBarMarker";
 CssClassesConstants.OverflowPanelClassName = CssClassesConstants.Prefix + "overflowPanel";
 CssClassesConstants.PlayPauseButtonWrapperClassName = CssClassesConstants.Prefix + "playPauseButtonWrapper";
 CssClassesConstants.FullscreenViewerTextAreaClassName = CssClassesConstants.Prefix + "fullscreenViewerTextArea";
 CssClassesConstants.ExpandedText = " dxigExpandedText";
 var ControlIDConstants = {
  FVContainerID: "_FVCell",
  NextNavButton: "_nextBtn",
  PrevNavButton: "_prevBtn",
  Popup: "_Popup",
  Slider: "_Slider",
  CloseButton: "_ClsBtn",
  NavigationBar: "_NavigationBar"
 };
 CallbackPrefixes = {
  Gallery: "g",
  FullscreenViewer: "f"
 };
 ElementVisibilityModeEnum = {
  None: 0,
  Faded: 1,
  OnMouseOver: 2,
  Always: 3
 };
 var LayoutModeEnum = {
  Table: 0,
  Flow: 1,
  Breakpoints: 2
 };
 var NavigationButton = ASPx.CreateClass(null, {
  constructor: function(owner, id, cssClassName, isNext, isEnabledEvalFunc) {
   this.owner = owner;
   this.id = owner.popup.name + id;
   this.isEnabledEvalFunc = isEnabledEvalFunc;
   this.cssClassName = cssClassName;
   this.isNext = isNext;
   this.button = null;
   this.relatedButton = null;
   this.buttonDisabled = false;
  },
  adjust: function() {
   var button = this.getButtonArea();
   var textArea = this.owner.getFullscreenViewerTextArea();
   var bottomPanelHeight = 0;
   if(textArea)
    bottomPanelHeight = textArea.offsetHeight;
   if(this.owner.isAlwaysVisibleNavBar)
    bottomPanelHeight += this.owner.getNavigationBarHeight();
   ASPx.SetStyles(button, { height: "100%" });
   ASPx.SetStyles(button, { height: button.offsetHeight - bottomPanelHeight });
  },
  prepare: function() {
   var style = { className: this.cssClassName },
    buttonArea = this.getButtonArea();
   if(this.owner.canHandleMouseOverForButtons)
    style.opacity = this.owner.initialOpacity;
   ASPx.SetStyles(buttonArea, style);
   ASPx.Selection.SetElementSelectionEnabled(buttonArea, false);
   this.assignHandlers();
  },
  getButton: function() {
   if(!this.button)
    this.button = ASPx.GetElementById(this.id);
   return this.button;
  },
  getButtonArea: function() {
   var button = this.getButton();
   return button ? button.parentNode : null;
  },
  assignHandlers: function() {
   if(this.owner.enabled) {
    var isNext = this.isNext;
    ASPx.Evt.AttachEventToElement(this.getButtonArea(), this.owner.clickEventName, function(evt) {
     if(!this.canPreventMouseDownEvent())
      this.onNavigationButtonMouseDown(evt, isNext);
    }.aspxBind(this.owner));
   }
  },
  updateEnabled: function(force, skipRtl) {
   if(this.owner.rtl && !skipRtl)
    this.relatedButton.updateEnabled(force, true);
   var stateController = typeof (ASPx.GetStateController) != "undefined" ? ASPx.GetStateController() : null;
   if(stateController) {
    var buttonDisabled = this.isEnabledEvalFunc();
    if(force || this.buttonDisabled != buttonDisabled)
     stateController.SetElementEnabled(this.getButton(), buttonDisabled);
    this.buttonDisabled = buttonDisabled;
   }
  }
 });
 var FullscreenViewer = ASPx.CreateClass(null, {
  constructor: function(owner) {
   this.hasFVTextTemplate = owner.hasFVTextTemplate;
   this.hasItemFVTextTemplate = owner.hasItemFVTextTemplate;
   this.disappearElementsTimerId = -1;
   this.lastActiveItemIndex = owner.lastActiveItemIndex;
   this.elementsVisible = false;
   this.owner = owner;
   this.rtl = owner.rtl;
   this.enabled = owner.enabled;
   this.useHash = owner.useHash;
   this.isVisibleNavigationButtons = owner.navBtnVisibility != ElementVisibilityModeEnum.None;
   this.canHandleMouseOverForButtons = this.isVisibleNavigationButtons && owner.navBtnVisibility != ElementVisibilityModeEnum.Always;
   this.canHandleMouseOverForBottomPanel = owner.navBarVisibility == ElementVisibilityModeEnum.OnMouseOver;
   this.clickEventName = ASPx.Browser.MobileUI ? ASPx.TouchUIHelper.touchMouseUpEventName : "click";
   this.initialOpacity = ASPx.Browser.MobileUI ? Constants.InitialOpacityValue : Constants.InitialFadedOpacityValue;
   this.isAlwaysVisibleNavBar = owner.navBarVisibility == ElementVisibilityModeEnum.Always;
   this.enablePagingByClick = owner.enablePagingByClick;
   this.keyboardSupport = owner.keyboardSupport;
   this.popup = null;
   this.slider = null;
   this.navigationBar = null;
   this.imageSliderWrapper = null;
   this.bottomPanel = null;
   this.navigationBarMarker = null;
   this.fulscreenViewerTextArea = null;
   this.nextNavigationButton = null;
   this.prevNavigationButton = null;
   this.closeButtonWrapper = null;
   this.playPauseButtonWrapper = null;
   this.items = owner.fvitems || {};
   this.itemsPerRequest = owner.fvItemsPerRequest || 0;
   this.lastMouseX = 0;
   this.lastMouseY = 0;
   this.contentPaddings = null;
   this.itemIndexToShow = -1;
  },
  initialize: function() {
   this.reset();
   this.prepare();
   var index = this.useHash ? this.owner.getIndexFromString(window.location) : -1;
   if(index === -1) {
    index = this.itemIndexToShow;
    this.itemIndexToShow = -1;
   }
   if(index != -1)
    this.show(index);
  },
  canPreventMouseDownEvent: function() {
   return ASPx.Browser.MobileUI && this.canHandleMouseOverForButtons && !this.elementsVisible;
  },
  prepare: function() {
   if(this.isDOMInitialized()) {
    this.ensureControlsCreated();
    this.initVirtualPagingHandlers();
    this.preparePlayPauseButton();
    this.prepareCloseButtonWrapper();
    this.prepareNavigationButtons();
    this.prepareImagePanel();
    this.prepareBottomPanel();
    if(this.enabled) {
     this.assignHandlersToPopup();
     this.assignHandlersToImagePanel();
     this.assignHandlersToBottomPanel();
    }
    this.popup.fadeAnimationDuration = Constants.FadeAnimationDuration;
   }
  },
  ensureControlsCreated: function() {
   this.popup = this.getPopup();
   this.slider = this.getSlider();
   if(this.isVisibleNavigationButtons) {
    this.nextNavigationButton = new NavigationButton(this, ControlIDConstants.NextNavButton, CssClassesConstants.NextButtonAreaClassName, !this.rtl,
     function() {
      return this.getActiveItemIndex() != this.getItemCount() - 1;
     }.aspxBind(this));
    this.prevNavigationButton = new NavigationButton(this, ControlIDConstants.PrevNavButton, CssClassesConstants.PrevButtonAreaClassName, this.rtl,
     function(evt) {
      return this.getActiveItemIndex() != 0;
     }.aspxBind(this));
    this.nextNavigationButton.relatedButton = this.prevNavigationButton;
    this.prevNavigationButton.relatedButton = this.nextNavigationButton;
   }
  },
  initVirtualPagingHandlers: function() {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.OnLoadItemsViaCallback.AddHandler(this.loadItems.aspxBind(this));
   this.slider.OnLoadItemsViaCallback.AddHandler(this.loadItems.aspxBind(this));
  },
  getPopup: function() {
   return ASPx.GetControlCollection().Get(this.owner.name + ControlIDConstants.Popup);
  },
  getSlider: function() {
   return ASPx.GetControlCollection().Get(this.popup.name + ControlIDConstants.Slider);
  },
  isDOMInitialized: function() {
   return !!this.getPopup() && this.getPopup().IsDOMInitialized();
  },
  reset: function() {
   this.popup = null;
   this.slider = null;
   this.navigationBar = null;
   this.imageSliderWrapper = null;
   this.bottomPanel = null;
   this.navigationBarMarker = null;
   this.fulscreenViewerTextArea = null;
   this.closeButtonWrapper = null;
   this.playPauseButtonWrapper = null;
   this.nextNavigationButton = null;
   this.prevNavigationButton = null;
  },
  show: function(index, skipEvent) {
   if(!skipEvent && this.owner.raiseFullscreenViewerShowing(index))
    return;
   if(!this.popup) {
    this.itemIndexToShow = index;
    return;
   }
   this.popup.Show();
   this.setActiveItemIndex(index, true, true);
   if(this.canHandleMouseOverForBottomPanel)
    this.slideOutNavigationBar(true, true);
   window.setTimeout(function() {
    this.adjustImagePanel();
   }.aspxBind(this), 0);
  },
  hide: function() {
   this.popup.Hide();
   this.clearHash();
   this.pauseSlideShow();
   this.hideElements(); 
  },
  updateFullscreenViewerText: function() {
   var textArea = this.getFullscreenViewerTextArea();
   if(textArea) {
    var activeItemIndex = this.getActiveItemIndex();
    if(this.hasItemFVTextTemplate) {
     var templateWrapper = textArea.children[0];
     var activeItemTextTemplate = this.getItemFVTextTemplate(activeItemIndex);
     if(!activeItemTextTemplate) {
      ASPx.SetStyles(templateWrapper, { display: "" });
      return;
     }
     templateWrapper.innerHTML = activeItemTextTemplate;
     ASPx.SetStyles(templateWrapper, { display: "block" });
     this.lastActiveItemIndex = activeItemIndex;
    } else if(!this.hasFVTextTemplate)
     textArea.innerHTML = this.getItemFVText(activeItemIndex) || "";
   }
  },
  getItemFVTextTemplate: function(index) {
   var item = this.items[index];
   return item ? this.items[index].itt : null;
  },
  getItemFVText: function(index) {
   var item = this.items[index];
   return item ? this.items[index].t : null;
  },
  getActiveItemIndex: function() {
   return this.slider ? this.slider.GetActiveItemIndex() : null;
  },
  setActiveItemIndex: function(index, preventAnimation, forced) {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.SetActiveItemIndex(index, preventAnimation, true);
   this.slider.SetActiveItemIndex(index, preventAnimation, true);
   this.slider.Focus();
   this.updateFullscreenViewerElements(forced);
  },
  setPlayPauseButtonState: function(play) {
   if(this.getPlayPauseButtonWrapper()) {
    ASPx.SetElementDisplay(this.getPlayPauseButtonWrapper().children[0], play);
    ASPx.SetElementDisplay(this.getPlayPauseButtonWrapper().children[1], !play);
   }
  },
  isVisible: function() {
   return !!this.popup && this.popup.IsVisible();
  },
  changeElementsVisibility: function() {
   if(this.canHandleMouseOverForButtons || this.canHandleMouseOverForBottomPanel) {
    this.elementsVisible = !this.elementsVisible;
    var opacity = this.elementsVisible ? 1 : this.initialOpacity;
    if(this.canHandleMouseOverForButtons) {
     if(this.getCloseButtonWrapper())
      ASPx.AnimationHelper.fadeTo(this.getCloseButtonWrapper(), { to: opacity });
     if(this.getPlayPauseButtonWrapper())
      ASPx.AnimationHelper.fadeTo(this.getPlayPauseButtonWrapper(), { to: opacity });
     if(this.prevNavigationButton)
      ASPx.AnimationHelper.fadeTo(this.prevNavigationButton.getButtonArea(), { to: opacity });
     if(this.nextNavigationButton)
      ASPx.AnimationHelper.fadeTo(this.nextNavigationButton.getButtonArea(), { to: opacity });
    }
    if(ASPx.Browser.MobileUI && this.canHandleMouseOverForBottomPanel) {
     if(this.elementsVisible)
      this.onBottomPanelMouseIn();
     else
      this.onBottomPanelMouseOut();
    }
   }
  },
  hideElements: function() {
   if(ASPx.Browser.MobileUI && (this.canHandleMouseOverForButtons || this.canHandleMouseOverForBottomPanel)) {
    if(this.canHandleMouseOverForButtons) {
     if(this.getCloseButtonWrapper())
      ASPx.SetElementOpacity(this.getCloseButtonWrapper(), this.initialOpacity);
     if(this.getPlayPauseButtonWrapper())
      ASPx.SetElementOpacity(this.getPlayPauseButtonWrapper(), this.initialOpacity);
     ASPx.SetElementOpacity(this.prevNavigationButton.getButtonArea(), this.initialOpacity);
     ASPx.SetElementOpacity(this.nextNavigationButton.getButtonArea(), this.initialOpacity);
    }
    if(this.canHandleMouseOverForBottomPanel)
     this.onBottomPanelMouseOut(true);
    this.elementsVisible = false;
   }
  },
  fadeInTextArea: function() {
   var textArea = this.getFullscreenViewerTextArea();
   if(textArea && this.canHandleMouseOverForBottomPanel)
    ASPx.AnimationHelper.fadeTo(textArea, { to: 1 });
  },
  doSetPrevItemIndex: function() {
   var index = this.getActiveItemIndex() - 1;
   if(index >= 0)
    this.setActiveItemIndex(index);
  },
  doSetNextItemIndex: function() {
   var index = this.getActiveItemIndex() + 1;
   if(index < this.getItemCount())
    this.setActiveItemIndex(index);
  },
  playSlideShow: function() {
   this.slider.Play();
   this.setPlayPauseButtonState(false);
  },
  pauseSlideShow: function() {
   this.slider.Pause();
   this.setPlayPauseButtonState(true);
  },
  animateElements: function() {
   if(ASPx.Browser.MobileUI || !this.canHandleMouseOverForButtons)
    return;
   if(!this.elementsVisible)
    this.changeElementsVisibility();
   ASPx.Timer.ClearTimer(this.disappearElementsTimerId);
   this.disappearElementsTimerId = window.setTimeout(function() {
    this.changeElementsVisibility();
   }.aspxBind(this), 2000);
  },
  fadeOutTextArea: function(preventAnimation) {
   var textArea = this.getFullscreenViewerTextArea();
   if(textArea && this.canHandleMouseOverForBottomPanel) {
    if(preventAnimation)
     ASPx.SetElementOpacity(textArea, Constants.InitialFadedOpacityValue);
    else
     ASPx.AnimationHelper.fadeTo(textArea, { to: Constants.InitialFadedOpacityValue });
   }
  },
  updateHash: function() {
   if(this.useHash) {
    var newHash = Constants.Hash + this.getActiveItemIndex();
    if(window.location.hash != newHash) {
     var newUrl = location.pathname + location.search + newHash;
     if(history.replaceState)
      history.replaceState("", "", newUrl);
     else
      location.replace(newUrl);
    }
   }
  },
  clearHash: function() {
   if(this.useHash) {
    if(history.replaceState)
     history.replaceState("", "", location.pathname + location.search);
    else
     location.replace(location.pathname + location.search + "#");
   }
  },
  updateNavigationButtonsState: function(force) {
   if(this.nextNavigationButton)
    this.nextNavigationButton.updateEnabled(force);
   if(this.prevNavigationButton)
    this.prevNavigationButton.updateEnabled(force);
  },
  getItemCount: function() {
   return this.slider.GetItemCount();
  },
  setNavigationBarMarkerVisibility: function(value) {
   var marker = this.getNavigationBarMarker();
   if(marker)
    ASPx.SetElementDisplay(marker, value);
  },
  slideInNavigationBar: function(preventAnimation) {
   if(this.canHandleMouseOverForBottomPanel) {
    this.setNavigationBarMarkerVisibility(false);
    ASPx.AnimationHelper.slideTo(this.getNavigationBar().GetMainElement(), {
     to: 0,
     direction: ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
     duration: Constants.SlideAnimationDuration
    });
   }
  },
  slideOutNavigationBar: function(preventAnimation, preventMarker) {
   if(this.canHandleMouseOverForBottomPanel) {
    if(!preventMarker)
     this.setNavigationBarMarkerVisibility(true);
    var element = this.getNavigationBar().GetMainElement();
    if(preventAnimation)
     ASPx.AnimationUtils.SetTransformValue(element, this.getNavigationBarHeight(), true);
    else
     ASPx.AnimationHelper.slideTo(element, {
      to: this.getNavigationBarHeight(),
      direction: ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
      duration: Constants.SlideAnimationDuration
     });
   }
  },
  getNavigationBarHeight: function() {
   return this.getNavigationBar().GetMainElement().offsetHeight;
  },
  prepareImagePanel: function() {
   var element = this.getImageSliderWrapper();
   var style = ASPx.GetCurrentStyle(element);
   this.contentPaddings = {
    paddingLeft: ASPx.PxToInt(style.paddingLeft),
    paddingTop: ASPx.PxToInt(style.paddingTop),
    paddingRight: ASPx.PxToInt(style.paddingRight),
    paddingBottom: ASPx.PxToInt(style.paddingBottom)
   };
   ASPx.SetStyles(element, { padding: 0 });
  },
  prepareBottomPanel: function() {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.disableSelectedStateAnimation = true;
   if(this.getNavigationBarMarker()) {
    this.getOverflowPanel().className += " dxigOPWM";
    ASPx.SetStyles(navigationBar.GetMainElement(), { zIndex: "1" });
   }
   this.fadeOutTextArea(true);
  },
  prepareNavigationButtons: function() {
   if(this.nextNavigationButton)
    this.nextNavigationButton.prepare();
   if(this.prevNavigationButton)
    this.prevNavigationButton.prepare();
  },
  preparePlayPauseButton: function() {
   var playPauseWrapper = this.getPlayPauseButtonWrapper();
   if(playPauseWrapper) {
    if(this.canHandleMouseOverForButtons)
     ASPx.SetElementOpacity(playPauseWrapper, this.initialOpacity);
    this.setPlayPauseButtonState(true);
   }
  },
  prepareCloseButtonWrapper: function() {
   var closeButtonWrapper = this.getCloseButtonWrapper();
   if(closeButtonWrapper && this.canHandleMouseOverForButtons)
    ASPx.SetElementOpacity(closeButtonWrapper, this.initialOpacity);
  },
  extendItemsPerRequest: function(indexes) {
   var itemsCount = this.getItemCount(),
    navigationBar = this.getNavigationBar(),
    shownIndexes = navigationBar
     ? navigationBar.GetNavigationBarStrategy().GetShownItemIndexes(false)
     : [this.slider.GetActiveItemIndex()];
   return ASPxClientImageSlider.ExtendItemsPerRequest(indexes, this.itemsPerRequest, shownIndexes, itemsCount, function(i) {
    return !this.items[i];
   }.bind(this));
  },
  loadItems: function(slider, pendingItemsQueue) {
   var indexes = this.extendItemsPerRequest(pendingItemsQueue),
    queue = indexes.filter(function(i) {
    if(!this.items[i])
     this.items[i] = {};
    var item = this.items[i];
    if(item.virtScrLock)
     return false;
    item.virtScrLock = true;
    return true;
   }.aspxBind(this));
   if(queue.length > 0)
    this.owner.DoLoadFullscreenViewerItemsViaCallback(queue);
  },
  processCreatedItems: function(items) {
   this.processFVCreatedItems(items);
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.ProcessCreatedItems(items);
   if(this.slider)
    this.slider.ProcessCreatedItems(items);
  },
  processFVCreatedItems: function(items) {
   var activeItemIndex = this.getActiveItemIndex();
   var processFVCreatedItemProperty = function(item, propName, move) {
    if(!items[key][propName])
     return;
    item[propName] = items[key][propName];
    if(move)
     delete items[key][propName];
   };
   for(var key in items) {
    if(!items.hasOwnProperty(key)) continue;
    var item = this.items[key] || (this.items[key] = {});
    processFVCreatedItemProperty(item, "itt", true);
    processFVCreatedItemProperty(item, "t");
    if(key == activeItemIndex)
     this.updateFullscreenViewerText();
   }
  },
  getPlayPauseButtonWrapper: function() {
   if(!this.playPauseButtonWrapper)
    this.playPauseButtonWrapper = this.getElementByClassName(CssClassesConstants.PlayPauseButtonWrapperClassName);
   return this.playPauseButtonWrapper;
  },
  getCloseButtonWrapper: function() {
   if(!this.closeButtonWrapper) {
    var closeButton = this.getCloseButton();
    if(closeButton)
     this.closeButtonWrapper = closeButton.parentNode;
   }
   return this.closeButtonWrapper;
  },
  getCloseButton: function() {
   return ASPx.GetElementById(this.popup.name + ControlIDConstants.CloseButton);
  },
  getImageSliderWrapper: function() {
   if(!this.imageSliderWrapper)
    this.imageSliderWrapper = this.getElementByClassName(CssClassesConstants.ImageSliderWrapperClassName);
   return this.imageSliderWrapper;
  },
  getBottomPanel: function() {
   if(!this.bottomPanel)
    this.bottomPanel = this.getElementByClassName(CssClassesConstants.BottomPanelClassName);
   return this.bottomPanel;
  },
  getOverflowPanel: function() {
   if(!this.overflowPanel)
    this.overflowPanel = this.getElementByClassName(CssClassesConstants.OverflowPanelClassName);
   return this.overflowPanel;
  },
  getNavigationBar: function() {
   if(!this.navigationBar && this.popup)
    this.navigationBar = ASPx.GetControlCollection().Get(this.popup.name + ControlIDConstants.NavigationBar);
   return this.navigationBar;
  },
  getNavigationBarMarker: function() {
   if(!ASPx.Browser.MobileUI && !this.navigationBarMarker)
    this.navigationBarMarker = this.getElementByClassName(CssClassesConstants.NavigationBarMarkerClassName);
   return this.navigationBarMarker;
  },
  getFullscreenViewerTextArea: function() {
   if(!this.fulscreenViewerTextArea)
    this.fulscreenViewerTextArea = this.getElementByClassName(CssClassesConstants.FullscreenViewerTextAreaClassName);
   return this.fulscreenViewerTextArea;
  },
  adjustImagePanel: function() {
   this.adjustPopupContent();
   this.adjustNavigationButtons();
   this.slider.AdjustControl();
  },
  adjustBottomPanel: function() {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.AdjustControl();
  },
  adjustPopupContent: function() {
   var wrapper = this.getImageSliderWrapper();
   var popupContentElement = wrapper.parentNode.parentNode;
   var navBarHeight = this.isAlwaysVisibleNavBar ? this.getNavigationBarHeight() : 0;
   var style = {
    width: popupContentElement.clientWidth - this.contentPaddings.paddingLeft - this.contentPaddings.paddingRight,
    height: popupContentElement.clientHeight - this.contentPaddings.paddingTop - this.contentPaddings.paddingBottom - navBarHeight,
    marginTop: this.contentPaddings.paddingTop
   };
   if(this.rtl)
    style.marginRight = this.contentPaddings.paddingLeft;
   else
    style.marginLeft = this.contentPaddings.paddingLeft;
   ASPx.SetStyles(wrapper, style);
   ASPx.SetStyles(this.getBottomPanel(), { width: "", height: "" });
  },
  adjustNavigationButtons: function() {
   if(this.prevNavigationButton)
    this.prevNavigationButton.adjust();
   if(this.nextNavigationButton)
    this.nextNavigationButton.adjust();
  },
  assignHandlersToPopup: function() {
   var popup = this.popup;
   if(popup) {
    if(!ASPx.Browser.MobileUI) {
     ASPx.Evt.AttachEventToElement(popup.GetWindowElement(-1), "mousemove", function(evt) { this.onPopupElementMouseMove(evt); }.aspxBind(this));
     if(this.keyboardSupport) {
      popup.Shown.AddHandler(function() { this.slider.Focus(); }.aspxBind(this));
      popup.Closing.AddHandler(function() {
       this.clearHash();
       this.pauseSlideShow();
      }.aspxBind(this));
     }
    }
    if(ASPx.Browser.MacOSMobilePlatform) {
     popup.Shown.AddHandler(function(s, e) { s.preventParentOverlowOnIos(-1); }.aspxBind(this));
     popup.CloseUp.AddHandler(function(s, e) { s.restoreParentOverflowOnIos(-1); }.aspxBind(this));
    }
    popup.BeforeResizing.AddHandler(function() {
     ASPx.SetStyles(this.getImageSliderWrapper(), { width: 1, height: 1 });
     if(this.prevNavigationButton)
      ASPx.SetStyles(this.prevNavigationButton.getButtonArea(), { height: 1 });
     if(this.nextNavigationButton)
      ASPx.SetStyles(this.nextNavigationButton.getButtonArea(), { height: 1 });
     ASPx.SetStyles(this.getBottomPanel(), { width: 1, height: 1 });
    }.aspxBind(this));
    popup.AfterResizing.AddHandler(function() {
     this.adjustImagePanel();
     this.adjustBottomPanel();
    }.aspxBind(this));
   }
  },
  assignHandlersToImagePanel: function() {
   this.assignHandlersToImageSlider();
   this.assignHandlersToPlayPauseButton();
   this.assignHandlersToCloseButtonWrapper();
  },
  assignHandlersToBottomPanel: function() {
   if(!ASPx.Browser.MobileUI && this.canHandleMouseOverForBottomPanel) {
    ASPx.Evt.AttachMouseEnterToElement(this.getElementByClassName(CssClassesConstants.BottomPanelClassName),
     function() { this.onBottomPanelMouseIn(); }.aspxBind(this),
     function() { this.onBottomPanelMouseOut(); }.aspxBind(this)
    );
   }
   this.assignHandlersToNavigationBar();
  },
  assignHandlersToNavigationBar: function() {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.ActiveItemChanged.AddHandler(function(s, e) {
     this.slider.SetActiveItemIndex(e.item.index, false, true);
     this.updateFullscreenViewerElements();
    }.aspxBind(this));
  },
  assignHandlersToImageSlider: function() {
   this.slider.ActiveItemChanged.AddHandler(function(s, e) { this.onImageSliderActiveItemChanged(s, e); }.aspxBind(this));
   ASPx.Evt.AttachEventToElement(this.slider.GetPassePartoutElement(), this.clickEventName, this.onImageSliderMouseUp.aspxBind(this));
  },
  assignHandlersToPlayPauseButton: function() {
   var playPauseButtonWrapper = this.getPlayPauseButtonWrapper();
   if(playPauseButtonWrapper)
    ASPx.Evt.AttachEventToElement(playPauseButtonWrapper, this.clickEventName, function(evt) {
     if(!this.canPreventMouseDownEvent())
      this.onPlayPauseButtonMouseDown(evt);
    }.aspxBind(this));
  },
  assignHandlersToCloseButtonWrapper: function() {
   var closeButtonWrapper = this.getCloseButtonWrapper();
   if(closeButtonWrapper)
    ASPx.Evt.AttachEventToElement(closeButtonWrapper, this.clickEventName, function(evt) {
     if(!this.canPreventMouseDownEvent())
      this.onCloseButtonMouseDown(evt);
    }.aspxBind(this));
  },
  onPopupElementMouseMove: function(evt) {
   if(!this.isVisible())
    return;
   this.animateElements();
  },
  onHashChange: function() {
   if(!this.enabled || !this.isVisible())
    return;
   var index = this.owner.getIndexFromString(window.location);
   if(index != -1)
    this.setActiveItemIndex(index);
  },
  onPlayPauseButtonMouseDown: function(evt) {
   this.animateElements();
   if(this.slider.IsSlideShowPlaying())
    this.pauseSlideShow();
   else
    this.playSlideShow();
   ASPx.Evt.PreventEvent(evt);
  },
  onCloseButtonMouseDown: function(evt) {
   this.hide();
   ASPx.Evt.PreventEvent(evt);
  },
  onNavigationButtonMouseDown: function(evt, isNext) {
   this.animateElements();
   if(isNext)
    this.doSetNextItemIndex();
   else
    this.doSetPrevItemIndex();
   ASPx.Evt.PreventEvent(evt);
  },
  onImageSliderActiveItemChanged: function(s, e) {
   var navigationBar = this.getNavigationBar();
   if(navigationBar)
    navigationBar.SetActiveItemIndex(e.item.index, false, true);
   this.updateFullscreenViewerElements();
  },
  updateFullscreenViewerElements: function(forced) {
   this.updateHash();
   this.updateFullscreenViewerText();
   this.updateNavigationButtonsState(forced);
   this.owner.raiseFullscreenViewerActiveItemIndexChanged();
  },
  onImageSliderMouseUp: function(evt) {
   if(ASPx.Browser.MobileUI)
    this.changeElementsVisibility();
   else if(this.enablePagingByClick) {
    var container = this.slider.GetPassePartoutElement();
    var leftLimitPos = container.offsetWidth * 0.35;
    var rightLimitPos = container.offsetWidth * 0.65;
    var mousePosInElement = ASPx.Evt.GetEventX(evt) - ASPx.GetAbsolutePositionX(container);
    if(mousePosInElement < leftLimitPos)
     this.doSetPrevItemIndex();
    else if(mousePosInElement > rightLimitPos)
     this.doSetNextItemIndex();
   }
  },
  onBottomPanelMouseIn: function() {
   if(this.slider.IsAdjusted()) {
    this.slideInNavigationBar();
    this.fadeInTextArea();
   }
  },
  onBottomPanelMouseOut: function(preventAnimation) {
   this.slideOutNavigationBar(preventAnimation);
   this.fadeOutTextArea(preventAnimation);
  },
  getElementByClassName: function(className) {
   var elements = ASPx.GetNodesByClassName(this.owner.GetMainElement(), className);
   return elements.length > 0 ? elements[0] : null;
  }
 });
 var DataContainer = ASPx.CreateClass(null, {
  constructor: function(owner) {
   this.owner = owner;
   this.dataItems = [];
  },
  clearDataItems: function() {
   this.dataItems = [];
  },
  hasSliderItems: function() {
   var fullscreenViewer = this.owner.fullscreenViewer;
   return fullscreenViewer && fullscreenViewer.slider && fullscreenViewer.slider.IsDOMInitialized();
  },
  getSliderItems: function() {
   var fullscreenViewer = this.owner.fullscreenViewer;
   return this.hasSliderItems() ? fullscreenViewer.slider.items : null;
  },
  createDataItems: function() {
   var galleryData = this.owner.items;
   var sliderData = this.getSliderItems();
   var result = [];
   for(var i = 0; i < galleryData.length; i++) {
    var galleryItem = galleryData[i];
    var sliderItem = sliderData ? sliderData[galleryItem.i] : {};
    var existItem = this.dataItems[i];
    result[i] = {
     index: galleryItem.i,
     name: galleryItem.n || sliderItem.n,
     isProcessed: existItem && existItem.index == galleryItem.i
    };
   }
   this.dataItems = result;
  },
  getDataItems: function() {
   return this.dataItems; 
  },
  getItemName: function(index) {
   if(this.hasSliderItems()) {
    var items = this.getSliderItems();
    var item = items[index];
    if(item)
     return item.n;
   }
   else {
    var items = this.getDataItems();
    for(var i = 0; i < items.length; i++) {
     var item = items[i];
     if(item.index === index)
      return item.name;
    }
   }
   return null;
  },
  getItemCount: function() {
   return this.dataItems.length;
  },
  isItemProcessed: function(index) {
   var item = this.dataItems[index];
   var tmp = item.isProcessed;
   item.isProcessed = true;
   return tmp;
  }
 });
 var LayoutItemProcessorBase = ASPx.CreateClass(null, {
  constructor: function(owner) {
   this.owner = owner;
   this.items = this.getItems();
   this.longTouchTimeout = 1000;
  },
  isBreakpointsLayoutMode: function() {
   return false;
  },
  getItems: function() {
  },
  createItem: function(index, itemIndex) {
   var item = this.items[index];
   var hyperLink = ASPx.GetNodeByTagName(this.items[index], "A", 0);
   var textElement = ASPx.GetNodeByClassName(this.items[index], CssClassesConstants.ThumbnailTextAreaClassName);
   var width = ASPx.PxToInt(item.style.width);
   var height = ASPx.PxToInt(item.style.height);
   var image = ASPx.GetNodeByClassName(this.items[index], "dxig-img");
   var onPrepareImgEndFunc = function() {
    image.style.visibility = "visible";
    ASPx.ImageControlUtils.RemoveLoadingGif(item);
   };
   var prepareImgFunc = function() {
    if(this.isBreakpointsLayoutMode()) {
     onPrepareImgEndFunc();
     return;
    }
    ASPx.ImageControlUtils.ResizeImage(image, {
     width: width,
     height: height,
     sizeMode: this.owner.thumbImgSizeMode,
     onEndResize: function(element, isCanvas) {
      if(!isCanvas)
       element.onload = null;
      onPrepareImgEndFunc();
     }
    });
   }.aspxBind(this);
   if(ASPx.ImageControlUtils.IsImageLoaded(image))
    prepareImgFunc();
   else
    image.onload = prepareImgFunc;
   var borderElement = ASPx.GetNodeByClassName(item, CssClassesConstants.ThumbnailBorderClassName);
   ASPx.SetStyles(borderElement, { width: width, height: height, display: "block" });
   if(this.isBreakpointsLayoutMode()) {
    var borderHeight = Math.round(borderElement.offsetHeight / 2),
     borderWidth = Math.round(borderElement.offsetWidth / 2);
    ASPx.SetStyles(borderElement, { top: -borderHeight, left: -borderWidth });
    ASPx.SetStyles(item, {
     marginTop: ASPx.PxToInt(item.style.marginTop) + borderHeight,
     marginLeft: ASPx.PxToInt(item.style.marginLeft) + borderWidth,
     marginBottom: ASPx.PxToInt(item.style.marginBottom) + borderHeight,
     marginRight: ASPx.PxToInt(item.style.marginRight) + borderWidth
    });
    ASPx.Attr.RemoveStyleAttribute(borderElement, "width");
    ASPx.Attr.RemoveStyleAttribute(borderElement, "height");
   }
   else
    ASPx.SetStyles(borderElement, { width: width - (borderElement.offsetWidth - width), height: height - (borderElement.offsetHeight - height) });
   if(hyperLink.parentNode.className == CssClassesConstants.ThumbnailWrapperClassName)
    ASPx.SetStyles(hyperLink.parentNode, { width: width, height: height });
   this.prepareTextElement(textElement, this.owner.thumbTxtVisibility, this.owner.allowExpandText);
   if(this.owner.enabled) {
    this.assignHandlersToHyperLink(hyperLink, itemIndex, this.owner.thumbTxtVisibility, this.owner.useHash);
    this.assignHandlersToTextElement(textElement, item, this.owner.thumbTxtVisibility, this.owner.allowExpandText);
   }
  },
  assignHandlersToHyperLink: function(hyperLink, index, elementVisibility, useHash) {
   if(!!ASPx.Attr.GetAttribute(hyperLink, "href"))
    return;
   var showViewer = function(evt) {
    if(useHash)
     this.onHyperLinkClick(evt);
    else
     this.ShowFullscreenViewer(index);
   }.aspxBind(this.owner);
   if(useHash) {
    ASPx.Attr.SetAttribute(hyperLink, "href", Constants.Hash + index);
    if(!ASPx.Browser.MobileUI)
     ASPx.Evt.AttachEventToElement(hyperLink, ASPx.TouchUIHelper.touchMouseDownEventName, function(evt) {
      this.onHyperLinkMouseDown(evt);
     }.aspxBind(this.owner));
    ASPx.Attr.SetAttribute(hyperLink, "target", "_blank");
    ASPx.Attr.SetAttribute(hyperLink, "rel", "noopener noreferrer");
   } else
    ASPx.SetStyles(hyperLink, { cursor: "pointer" });
   ASPx.Evt.AttachEventToElement(hyperLink, "click", showViewer);
   this.assignTouchHandlers(hyperLink, showViewer, function() {
    this.toggleTextElementsVisibility(elementVisibility);
   }.aspxBind(this));
  },
  assignHandlersToTextElement: function(textElement, item, elementVisibility, allowExpandText) {
   if(textElement) {
    if(elementVisibility != ElementVisibilityModeEnum.Always) {
     ASPx.Evt.AttachMouseEnterToElement(item,
      function(element) { this.showTextElement(textElement); }.aspxBind(this),
      function(element) { this.hideTextElement(textElement, elementVisibility, false); }.aspxBind(this)
     );
    }
    if(allowExpandText)
     ASPx.Evt.AttachEventToElement(textElement, "click", function() {
      if(textElement.dxIsExpanded)
       textElement.className = textElement.className.replace(CssClassesConstants.ExpandedText, "");
      else
       textElement.className += CssClassesConstants.ExpandedText;
      textElement.dxIsExpanded = !textElement.dxIsExpanded;
     }.aspxBind(this));
   }
  },
  assignTouchHandlers: function(element, shortTouchHandler, longTouchHandler) {
   if(!ASPx.Browser.MobileUI)
    return;
   var preventHandlerApply = false;
   ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseDownEventName, function(e) {
    preventHandlerApply = false;
    setTimeout(function() {
     if(!preventHandlerApply) {
      preventHandlerApply = true;
      longTouchHandler.apply(this, [e]);
     }
    }.aspxBind(this), this.longTouchTimeout);
   }.aspxBind(this));
   ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseMoveEventName, function(e) { preventHandlerApply = true; });
   ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseUpEventName, function(e) {
    ASPx.Evt.PreventEventAndBubble(e);
    if(!preventHandlerApply) {
     preventHandlerApply = true;
     shortTouchHandler.apply(this, [e]);
    }
   }.aspxBind(this));
  },
  getOpacityValue: function(elementVisibility) {
   var opacity = Constants.InitialOpacityValue;
   if(elementVisibility == ElementVisibilityModeEnum.Faded)
    opacity = Constants.InitialFadedOpacityValue;
   return opacity;
  },
  showTextElement: function(textElement) {
   ASPx.AnimationHelper.fadeTo(textElement, { to: 1 });
  },
  hideTextElement: function(textElement, elementVisibility, forceHide) {
   if(!this.owner.allTemplatesShowed || forceHide) {
    var opacity = this.getOpacityValue(elementVisibility);
    ASPx.AnimationHelper.fadeTo(textElement, { to: opacity });
   }
  },
  toggleTextElementsVisibility: function(elementVisibility) {
   if(elementVisibility == ElementVisibilityModeEnum.Always || elementVisibility == ElementVisibilityModeEnum.None)
    return;
   var items = this.getItems();
   for(var i = 0; i < items.length; i++) {
    var textElement = ASPx.GetNodeByClassName(items[i], CssClassesConstants.ThumbnailTextAreaClassName);
    if(textElement) {
     if(this.owner.allTemplatesShowed)
      this.hideTextElement(textElement, elementVisibility, true);
     else
      this.showTextElement(textElement);
    }
   }
   this.owner.allTemplatesShowed = !this.owner.allTemplatesShowed;
  },
  prepareTextElement: function(textElement, elementVisibility, allowExpandText) {
   if(textElement) {
    var style = { display: "block" };
    if(allowExpandText)
     style.cursor = "default";
    if(elementVisibility != ElementVisibilityModeEnum.Always && !this.owner.allTemplatesShowed)
     style.opacity = this.getOpacityValue(elementVisibility);
    ASPx.SetStyles(textElement, style);
   }
  }
 });
 var FlowLayoutItemProcessor = ASPx.CreateClass(LayoutItemProcessorBase, {
  constructor: function(owner) {
   this.constructor.prototype.constructor.call(this, owner);
  },
  getItems: function() {
   var table = ASPx.GetNodeByTagName(this.owner.GetItemsCell(), "table", 0);
   var tbody = ASPx.GetNodeByTagName(table, "tbody", 0);
   var tr = ASPx.GetNodeByTagName(tbody, "tr", 0);
   return ASPx.GetNodeByTagName(tr, "td", 0).childNodes;
  }
 });
 var BreakpointsLayoutItemProcessor = ASPx.CreateClass(LayoutItemProcessorBase, {
  constructor: function(owner) {
   this.constructor.prototype.constructor.call(this, owner);
  },
  isBreakpointsLayoutMode: function() {
   return true;
  },
  getItems: function() {
   var table = ASPx.GetNodeByTagName(this.owner.GetItemsCell(), "table", 0);
   var tbody = ASPx.GetNodeByTagName(table, "tbody", 0);
   var tr = ASPx.GetNodeByTagName(tbody, "tr", 0);
   var containers = ASPx.GetNodeByTagName(tr, "td", 0).childNodes;
   var items = [];
   for(var i = 0; i < containers.length; i++)
    items.push(ASPx.GetNodeByTagName(containers[i], "div", 0));
   return items;
  }
 });
 var TableLayoutItemProcessor = ASPx.CreateClass(LayoutItemProcessorBase, {
  constructor: function(owner) {
   this.constructor.prototype.constructor.call(this, owner);
  },
  getItems: function() {
   var items = ASPx.GetNodesByClassName(this.owner.GetItemsCell(), CssClassesConstants.ThumbnailWrapperClassName);
   for(var i = 0; i < items.length; i++)
    items[i] = items[i].parentNode;
   return items;
  }
 });
 var ASPxClientImageGallery = ASPx.CreateClass(ASPxClientDataView, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.keyboardSupport = true;
   this.enablePagingByClick = true;
   this.useHash = true;
   this.navBarVisibility = 2;
   this.navBtnVisibility = 2;
   this.thumbTxtVisibility = 2;
   this.thumbImgSizeMode = 2;
   this.allowExpandText = true;
   this.items = [];
   this.hasFVTextTemplate = false;
   this.hasItemFVTextTemplate = false;
   this.allTemplatesShowed = false;
   this.lastActiveItemIndex = 0;
   this.isLeftButtonPressed = false;
   this.layoutMode = LayoutModeEnum.Table;
   this.needUpdateFullscreenViewer = false;
   this.fullscreenViewer = null;
   this.dataContainer = null;
   this.FullscreenViewerShowing = new ASPxClientEvent();
   this.FullscreenViewerActiveItemIndexChanged = new ASPxClientEvent();
  },
  InlineInitialize: function() {
   ASPxClientDataView.prototype.InlineInitialize.call(this);
   this.fullscreenViewer = new FullscreenViewer(this);
   this.createImages();
  },
  Initialize: function() {
   ASPxClientDataView.prototype.Initialize.call(this);
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.initialize();
  },
  canUseFullscreenViewer: function() {
   return !!ASPx.GetControlCollection().Get(this.name + ControlIDConstants.Popup);
  },
  createItemProcessor: function() {
   switch(this.layoutMode) {
    case LayoutModeEnum.Flow:
     return new FlowLayoutItemProcessor(this);
    case LayoutModeEnum.Breakpoints:
     return new BreakpointsLayoutItemProcessor(this);
    default:
     return new TableLayoutItemProcessor(this);
   }
  },
  createImages: function() {
   var dataContainer = this.getDataContainer();
   dataContainer.createDataItems();
   var length = dataContainer.getItemCount();
   if(length == 0)
    return;
   var itemProcessor = this.createItemProcessor();
   for(var i = 0; i < length; i++) {
    if(!dataContainer.isItemProcessed(i) && dataContainer.dataItems[i])
     itemProcessor.createItem(i, dataContainer.dataItems[i].index);
   }
  },
  getDataContainer: function() {
   if(!this.dataContainer)
    this.dataContainer = new DataContainer(this);
   return this.dataContainer;
  },
  raiseFullscreenViewerActiveItemIndexChanged: function() {
   if(!this.FullscreenViewerActiveItemIndexChanged.IsEmpty()) {
    var index = this.GetFullscreenViewerActiveItemIndex();
    var args = new ASPxClientImageGalleryFullscreenViewerEventArgs(index, this.getDataContainer().getItemName(index));
    this.FullscreenViewerActiveItemIndexChanged.FireEvent(this, args);
   }
  },
  raiseFullscreenViewerShowing: function(index) {
   var cancel = false;
   if(!this.FullscreenViewerShowing.IsEmpty()) {
    if(index == undefined)
     index = this.GetFullscreenViewerActiveItemIndex();
    var args = new ASPxClientImageGalleryCancelEventArgs(index, this.getDataContainer().getItemName(index));
    this.FullscreenViewerShowing.FireEvent(this, args);
    cancel = args.cancel;
   }
   return cancel;
  },
  DoLoadFullscreenViewerItemsViaCallback: function(indexArray) {
   var preparedArgs = this.PrepareCallbackArgs(ASPx.Json.ToJson(indexArray), false, true);
   this.CreateCallback(preparedArgs, Constants.VirtualPagingCallbackCommand);
   this.HideLoadingPanel();
  },
  DoProcessFullscreenViewerItems: function(items) {
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.processCreatedItems(items);
  },
  ShowFullscreenViewer: function(index) {
   if(!this.raiseFullscreenViewerShowing(index) && this.canUseFullscreenViewer())
    this.fullscreenViewer.show(index, true);
  },
  HideFullscreenViewer: function() {
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.hide();
  },
  SetFullscreenViewerActiveItemIndex: function(index, preventAnimation) {
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.setActiveItemIndex(index, preventAnimation);
  },
  GetFullscreenViewerItemCount: function() {
   if(this.canUseFullscreenViewer())
    return this.fullscreenViewer.getItemCount();
   return 0;
  },
  GetFullscreenViewerActiveItemIndex: function() {
   if(this.canUseFullscreenViewer())
    return this.fullscreenViewer.getActiveItemIndex();
   return 0;
  },
  PlaySlideShow: function() {
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.playSlideShow();
  },
  PauseSlideShow: function() {
   if(this.canUseFullscreenViewer())
    this.fullscreenViewer.pauseSlideShow();
  },
  PrepareCallbackArgs: function(args, isCustomCallback, isFullscreenViewerCallback) {
   return isFullscreenViewerCallback
    ? CallbackPrefixes.FullscreenViewer + args
    : CallbackPrefixes.Gallery + ASPxClientDataView.prototype.PrepareCallbackArgs.call(this, args, isCustomCallback);
  },
  OnCallback: function(result) {
   this.fvitems = result.fvitems;
   if(result.type == CallbackPrefixes.FullscreenViewer)
    return;
   var areStatesEqual = this.GetPageIndex() == result.index && this.GetPageSize() == result.size;
   var isEndlessPagingCallback = result.epHtml != undefined;
   ASPxClientDataView.prototype.OnCallback.call(this, result);
   if(ASPx.IsExists(result.fv)) {
    this.needUpdateFullscreenViewer = true;
    ASPx.SetInnerHtml(this.GetChildElement(ControlIDConstants.FVContainerID), result.fv);
   }
   if(result.items) {
    if(this.UseEndlessPaging() && isEndlessPagingCallback) {
     if(!areStatesEqual)
      this.items = ASPx.Data.CollectionsUnionToArray(this.items, result.items);
    } else {
     this.items = result.items;
     this.getDataContainer().clearDataItems();
    }
   }
  },
  DoEndCallback: function() {
   if(this.needUpdateFullscreenViewer) {
    this.fullscreenViewer.reset();
    this.fullscreenViewer.prepare();
    if(this.fullscreenViewer.isVisible())
     this.fullscreenViewer.show(this.fullscreenViewer.getActiveItemIndex(), true);
    this.needUpdateFullscreenViewer = false;
   }
   if(this.fvitems)
    this.DoProcessFullscreenViewerItems(this.fvitems);
   this.createImages();
   ASPxClientDataView.prototype.DoEndCallback.call(this);
  },
  getIndexFromString: function(str) {
   var hash = (new RegExp(Constants.Hash + '[0-9]+')).exec(str);
   if(!hash)
    return -1;
   return parseInt(hash[0].replace(new RegExp(Constants.Hash), ""));
  },
  onHyperLinkMouseDown: function(evt) {
   this.isLeftButtonPressed = ASPx.Evt.IsLeftButtonPressed(evt);
   ASPx.Evt.PreventEvent(evt);
  },
  onHyperLinkClick: function(evt) {
   if(ASPx.Browser.MobileUI || this.isLeftButtonPressed) {
    var hyperLink = ASPx.Evt.GetEventSource(evt).parentNode;
    this.ShowFullscreenViewer(this.getIndexFromString(ASPx.Attr.GetAttribute(hyperLink, "href")));
    ASPx.Evt.PreventEvent(evt);
   }
   this.isLeftButtonPressed = false;
  }
 });
 ASPxClientImageGallery.Cast = ASPxClientDataView.Cast;
 ASPxClientImageGalleryCancelEventArgs = ASPx.CreateClass(ASPxClientCancelEventArgs, {
  constructor: function(index, name) {
   this.constructor.prototype.constructor.call(this);
   this.index = index;
   this.name = name;
  }
 });
 ASPxClientImageGalleryFullscreenViewerEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(index, name) {
   this.constructor.prototype.constructor.call(this);
   this.index = index;
   this.name = name;
  }
 });
 ASPxClientImageGallery.DataContainer = DataContainer;
 window.ASPxClientImageGallery = ASPxClientImageGallery;
 window.ASPxClientImageGalleryCancelEventArgs = ASPxClientImageGalleryCancelEventArgs;
 window.ASPxClientImageGalleryFullscreenViewerEventArgs = ASPxClientImageGalleryFullscreenViewerEventArgs;
 ASPx.Evt.AttachEventToElement(window, "hashchange", function() {
  ASPx.GetControlCollection().ForEachControl(function(control) {
   if(control.onHashChange)
    control.onHashChange();
  });
 });
})();

(function() {
var MVCxClientImageGallery = ASPx.CreateClass(ASPxClientImageGallery, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.customActionUrl = "";
  this.callbackCustomArgs = {};
  this.customActionCallBack = null;
 },
 PerformCallback: function(data, onSuccess) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientImageGallery.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function() {
  if(this.callbackUrl != "") {
   this.callBack = function(arg) {
    MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs);
   };
  }
  if(this.customActionUrl != "") {
   this.customActionCallBack = function(arg) {
    MVCx.PerformControlCallback(this.name, this.customActionUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs);
   };
  }
  ASPxClientImageGallery.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(arg) {
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 EvalCallbackResult: function(resultString) {
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2) {
   var resultObj = ASPxClientImageGallery.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientImageGallery.prototype.EvalCallbackResult.call(this, resultString);
 },
 CreateCallbackCore: function(arg, command, callbackID) {
  if(this.callbackCustomArgs != {})
   window.setTimeout(function() { this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientImageGallery.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 GetCallbackMethod: function(command) {
  return MVCx.IsCustomCallback(command) ? MVCx.GetCustomActionCallBackMethod(this) : this.callBack;
 }
});
MVCxClientImageGallery.Cast = ASPxClientControl.Cast;
window.MVCxClientImageGallery = MVCxClientImageGallery;
})();

(function () {
 var CssClassesConstants = {};
 CssClassesConstants.Prefix = "dxis-";
 CssClassesConstants.OverlayElementCssClass = CssClassesConstants.Prefix + "overlayElement";
 CssClassesConstants.TextAreaCssClassName = CssClassesConstants.Prefix + "itemTextArea";
 CssClassesConstants.ImageAreaSlidePanelCssClassName = CssClassesConstants.Prefix + "slidePanel";
 CssClassesConstants.NavigationBarHoverStateElementCssClassName = CssClassesConstants.Prefix + "nbHoverItem";
 CssClassesConstants.NavigationBarSelectedStateCssClassName = " " + CssClassesConstants.Prefix + "selected";
 CssClassesConstants.NavigationBarHoverStateCssClassName = CssClassesConstants.Prefix + "hover";
 CssClassesConstants.NavigationBarSlidePanelCssClassName = CssClassesConstants.Prefix + "nbSlidePanel";
 CssClassesConstants.NavigationBarSlidePanelWrapperCssClassName = CssClassesConstants.Prefix + "nbSlidePanelWrapper";
 CssClassesConstants.PassePartoutCssClassName = CssClassesConstants.Prefix + "passePartout";
 CssClassesConstants.ItemHyperLinkCssClassName = CssClassesConstants.Prefix + "hl";
 CssClassesConstants.PlayPauseWrapperCssClassName = CssClassesConstants.Prefix + "playPauseBtnWrapper";
 CssClassesConstants.NavigationButtonUpWrapperCssClassName = CssClassesConstants.Prefix + "prevBtnVertWrapper";
 CssClassesConstants.NavigationButtonDownWrapperCssClassName = CssClassesConstants.Prefix + "nextBtnVertWrapper";
 CssClassesConstants.NavigationButtonBackwardWrapperCssClassName = CssClassesConstants.Prefix + "prevBtnHorWrapper";
 CssClassesConstants.NavigationButtonForwardWrapperCssClassName = CssClassesConstants.Prefix + "nextBtnHorWrapper";
 CssClassesConstants.NavigationButtonUpOutsideWrapperCssClassName = CssClassesConstants.Prefix + "prevBtnVertOutsideWrapper";
 CssClassesConstants.NavigationButtonDownOutsideWrapperCssClassName = CssClassesConstants.Prefix + "nextBtnVertOutsideWrapper";
 CssClassesConstants.NavigationButtonBackwardOutsideWrapperCssClassName = CssClassesConstants.Prefix + "prevBtnHorOutsideWrapper";
 CssClassesConstants.NavigationButtonForwardOutsideWrapperCssClassName = CssClassesConstants.Prefix + "nextBtnHorOutsideWrapper";
 CssClassesConstants.NavigationButtonWrapperHoverCssClassPostfix = "Hover";
 CssClassesConstants.NavigationButtonWrapperPressedCssClassPostfix = "Pressed";
 CssClassesConstants.NavigationButtonWrapperDisabledCssClassPostfix = "Disabled";
 CssClassesConstants.ImageZoomNavigatorCssClassName = CssClassesConstants.Prefix + "zoomNavigator";
 CssClassesConstants.LoadingElement = "dx-is-loading";
 var LoadModeEnum = {
  AllImages: 0,
  DynamicLoadAndCache: 1,
  DynamicLoad: 2
 };
 var AnimationTypeEnum = {
  Slide: 0,
  Fade: 1,
  None: 2
 };
 var AnimationDirectionEnum = {
  Horizontal: 0,
  Vertical: 1
 };
 var NavigationBarPositionEnum = {
  Bottom: 0,
  Top: 1,
  Left: 2,
  Right: 3
 };
 var NavigationBarModeEnum = {
  Thumbnails: 0,
  Dots: 1
 };
 var ElementVisibilityModeEnum = {
  None: 0,
  Faded: 1,
  OnMouseOver: 2,
  Always: 3
 };
 var NavigationBarPagingModeEnum = {
  Page: 0,
  Single: 1
 };
 var ExtremeItemClickModeEnum = {
  SelectAndSlide: 0,
  Select: 1
 };
 var NavigationBarButtonPositionEnum = {
  Inside: 0,
  Outside: 1
 };
 var ActiveItemChangeActionEnum = {
  Click: 0,
  Hover: 1
 };
 var NavigationButtonVisibilityModeEnum = {
  Auto: 0,
  Always: 1
 };
 var FadedDefaultOpacity = 0.3;
 var SizeUtils = {
  GetClientWidth: function (element, clear) {
   return clear ? ASPx.GetClearClientWidth(element) : element.offsetWidth;
  },
  GetClientHeight: function (element, clear) {
   return clear ? ASPx.GetClearClientHeight(element) : element.offsetHeight;
  }
 };
 var MouseEnterHelper = {
  data: [],
  AddHandler: function (element, mouseOver, mouseOut) {
   var dataItem = this.GetDataItem(element);
   if(!dataItem)
    dataItem = this.CreateDataItem(element, mouseOver, mouseOut);
   dataItem.mouseOverHandlers.push(mouseOver);
   dataItem.mouseOutHandlers.push(mouseOut);
  },
  GetDataItem: function (element) {
   for(var i = 0; i < this.data.length; i++) {
    var dataItem = this.data[i];
    if(dataItem && dataItem.element == element)
     return dataItem;
   }
   return null;
  },
  CreateDataItem: function (element, mouseOver, mouseOut) {
   var dataItem = { element: element, mouseOverHandlers: [mouseOver], mouseOutHandlers: [mouseOut] };
   this.data.push(dataItem);
   ASPx.Evt.AttachMouseEnterToElement(element, MouseEnterHelper.OnMouseOverHandler, MouseEnterHelper.OnMouseOutHandler);
   return dataItem;
  },
  OnMouseOverHandler: function (element) {
   MouseEnterHelper.PerformHandlers(MouseEnterHelper.GetDataItem(element).mouseOverHandlers);
  },
  OnMouseOutHandler: function (element) {
   MouseEnterHelper.PerformHandlers(MouseEnterHelper.GetDataItem(element).mouseOutHandlers);
  },
  PerformHandlers: function (array) {
   for(var i = 0; i < array.length; i++)
    array[i]();
  }
 };
 var ControlBase = ASPx.CreateClass(ASPxClientImageControlBase, {
  constructor: function (imageSlider) {
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  AdjustControl: function () {
   this.CalculateSize();
  },
  ResetControlStyle: function () {
  },
  CalculateSize: function () {
  },
  InitializeHandlers: function () {
  },
  IsAdjustedSize: function () {
   return this.GetImageSlider().IsAdjusted();
  },
  GetImageSlider: function () {
   return this.control;
  },
  GetClientControlName: function () {
   return this.GetImageSlider().name;
  },
  IsHorizontalNavigation: function () {
   return this.GetImageSlider().navDirection == AnimationDirectionEnum.Horizontal;
  },
  GetAnimationType: function () {
   return this.GetImageSlider().GetAnimationType();
  },
  IsRtl: function (withoutHorizontalNavigation) {
   var value = !!this.GetImageSlider().rtl;
   if(!withoutHorizontalNavigation)
    value = value && this.IsHorizontalNavigation();
   return value;
  },
  CreateDiv: function () {
   return document.createElement("DIV");
  },
  GetStateController: function () {
   return typeof (ASPx.GetStateController) != "undefined" ? ASPx.GetStateController() : null;
  },
  PatchElementForMSTouch: function (element) {
   if(ASPx.Browser.MSTouchUI)
    element.className += " " + ASPx.TouchUIHelper.msTouchDraggableClassName;
  }
 });
 var ButtonBase = ASPx.CreateClass(ControlBase, {
  constructor: function (itemsOwner) {
   this.itemsOwner = itemsOwner;
   this.defaultOpacity = 0;
   this.isLeftButtonPressed = false;
   this.visibility = true;
   this.constructor.prototype.constructor.call(this, itemsOwner.GetImageSlider());
  },
  Initialize: function () {
   if(this.GetVisibilityMode() == ElementVisibilityModeEnum.Faded)
    this.defaultOpacity = FadedDefaultOpacity;
  },
  GetOwner: function () {
   return this.itemsOwner;
  },
  GetContainer: function () {
   return this.GetOwner().GetButtonsContainer();
  },
  GetMouseUpElement: function () {
   return this.GetContainer();
  },
  GetVisibilityMode: function () {
   return 0;
  },
  CanHandle: function () {
   return this.GetOwner().CanHandleButtons();
  },
  PrepareControlHierarchy: function () {
   if(this.GetVisibilityMode() == ElementVisibilityModeEnum.Always)
    return;
   var elements = this.GetAnimationElements();
   for(var i = 0; i < elements.length; i++) {
    ASPx.SetStyles(elements[i], { opacity: this.defaultOpacity });
    this.PatchElementForMSTouch(elements[i]);
   }
  },
  InitializeHandlers: function () {
   ASPx.Evt.AttachEventToElement(this.GetMouseUpElement(), ASPx.TouchUIHelper.touchMouseDownEventName, function (evt) {
    this.isLeftButtonPressed = ASPx.Evt.IsLeftButtonPressed(evt);
   }.aspxBind(this));
   ASPx.Evt.AttachEventToElement(this.GetMouseUpElement(), ASPx.Browser.TouchUI ? ASPx.TouchUIHelper.touchMouseUpEventName : "click", function (evt) {
    if(this.visibility && this.isLeftButtonPressed && this.CanHandle())
     this.OnMouseUp(evt);
   }.aspxBind(this));
   if(!ASPx.Browser.TouchUI && this.GetVisibilityMode() != ElementVisibilityModeEnum.Always)
    MouseEnterHelper.AddHandler(this.GetContainer(), function () { this.Appear(); }.aspxBind(this), function () { this.Disappear(); }.aspxBind(this));
  },
  OnMouseUp: function (evt) {
  },
  Appear: function () {
   this.Animate(1);
  },
  Disappear: function () {
   this.Animate(this.defaultOpacity);
  },
  GetAnimationElements: function () {
   return [];
  },
  Animate: function (value) {
   var elements = this.GetAnimationElements();
   var hasAnimation = this.GetAnimationType() != AnimationTypeEnum.None;
   for(var i = 0; i < elements.length; i++) {
    if(hasAnimation)
     ASPx.AnimationHelper.fadeTo(elements[i], { to: value });
    else
     ASPx.SetStyles(elements[i], { opacity: value });
   }
  },
  SetInnerHtml: function (element, html) {
   element.innerHTML = html;
  }
 });
 var SlideShowButton = ASPx.CreateClass(ButtonBase, {
  constructor: function (itemsOwner) {
   this.wrapperElement = null;
   this.playButton = null;
   this.pauseButton = null;
   this.itemsOwner = itemsOwner;
   this.constructor.prototype.constructor.call(this, itemsOwner);
  },
  GetMouseUpElement: function () {
   return this.wrapperElement;
  },
  GetAnimationElements: function () {
   return [this.wrapperElement];
  },
  GetVisibilityMode: function () {
   return this.GetImageSlider().playPauseBtnVbl;
  },
  CreateControlHierarchy: function () {
   var slider = this.GetImageSlider();
   this.wrapperElement = this.CreateDiv();
   this.wrapperElement.innerHTML = slider.playBH + slider.pauseBH;
   this.playButton = this.wrapperElement.children[0];
   this.pauseButton = this.wrapperElement.children[1];
   this.GetContainer().appendChild(this.wrapperElement);
  },
  PrepareControlHierarchy: function () {
   ButtonBase.prototype.PrepareControlHierarchy.call(this);
   this.wrapperElement.className = CssClassesConstants.PlayPauseWrapperCssClassName;
   this.SetButtonState(true);
  },
  IsPlaying: function () {
   return this.GetImageSlider().IsSlideShowPlaying();
  },
  OnMouseUp: function (evt) {
   var slider = this.GetImageSlider();
   if(this.IsPlaying())
    slider.Pause();
   else
    slider.Play();
  },
  SetButtonState: function (play) {
   ASPx.SetElementDisplay(this.playButton, play);
   ASPx.SetElementDisplay(this.pauseButton, !play);
  }
 });
 var NavigationButtons = ASPx.CreateClass(ButtonBase, {
  constructor: function (itemsOwner) {
   this.prevButtonEnable = true;
   this.nextButtonEnable = true;
   this.prevButton = null;
   this.nextButton = null;
   this.prevButtonWrapper = null;
   this.nextButtonWrapper = null;
   this.constructor.prototype.constructor.call(this, itemsOwner);
  },
  GetUniqueId: function () {
   return this.GetOwner().GetUniqueId();
  },
  IsEnablePagingByClick: function () {
   return this.GetOwner().IsEnablePagingByClick();
  },
  IsHorizontal: function () {
   return this.GetOwner().IsHorizontalNavigation();
  },
  GetVisibilityMode: function () {
   return this.GetOwner().GetNavigationBtnsVisibilityMode();
  },
  OnPrevButtonMouseUp: function (evt) {
   if(this.prevButtonEnable)
    this.GetOwner().PerformBackward();
   return ASPx.Evt.PreventEvent(evt);
  },
  OnNextButtonMouseUp: function (evt) {
   if(this.nextButtonEnable)
    this.GetOwner().PerformForward();
   return ASPx.Evt.PreventEvent(evt);
  },
  CreateControlHierarchy: function () {
   this.prevButtonWrapper = this.CreateDiv();
   this.nextButtonWrapper = this.CreateDiv();
   this.SetInnerHtml(this.prevButtonWrapper, this.GetOwner().GetPrevButtonHtml());
   this.SetInnerHtml(this.nextButtonWrapper, this.GetOwner().GetNextButtonHtml());
   this.prevButton = this.prevButtonWrapper.firstChild;
   this.nextButton = this.nextButtonWrapper.firstChild;
   var container = this.GetContainer();
   container.appendChild(this.prevButtonWrapper);
   container.appendChild(this.nextButtonWrapper);
  },
  PrepareControlHierarchy: function () {
   ButtonBase.prototype.PrepareControlHierarchy.call(this);
   this.SetId(this.prevButtonWrapper, "nbwb");
   this.SetId(this.nextButtonWrapper, "nbwf");
   this.PrepareButtonWrapper(this.prevButtonWrapper, this.GetPrevButtonWrapperCssClassName());
   this.PrepareButtonWrapper(this.nextButtonWrapper, this.GetNextButtonWrapperCssClassName());
  },
  GetPrevButtonWrapperCssClassName: function () {
   return this.IsHorizontal() ?
    CssClassesConstants.NavigationButtonBackwardWrapperCssClassName : CssClassesConstants.NavigationButtonUpWrapperCssClassName;
  },
  GetNextButtonWrapperCssClassName: function () {
   return this.IsHorizontal() ?
     CssClassesConstants.NavigationButtonForwardWrapperCssClassName : CssClassesConstants.NavigationButtonDownWrapperCssClassName;
  },
  PrepareButtonWrapper: function (wrapper, className) {
   wrapper.className = className;
   var stateController = this.GetStateController();
   if(stateController) {
    if(this.IsEnabled()) {
     stateController.AddHoverItem(wrapper.id, [className + CssClassesConstants.NavigationButtonWrapperHoverCssClassPostfix], [""], [""], null, null, false);
     stateController.AddPressedItem(wrapper.id, [className + CssClassesConstants.NavigationButtonWrapperPressedCssClassPostfix], [""], [""], null, null, false);
    }
    stateController.AddDisabledItem(wrapper.id, [className + CssClassesConstants.NavigationButtonWrapperDisabledCssClassPostfix], [""], [""], null, null, false);
   }
  },
  SetId: function (element, id) {
   element.id = this.GetClientControlName() + this.GetOwner().GetUniqueId() + id;
  },
  OnMouseUp: function (evt) {
   var value = true;
   var container = this.GetContainer();
   var source = ASPx.Evt.GetEventSource(evt);
   if(this.IsEnablePagingByClick() && !this.IsSlideShowButton(source) && !ASPx.IsInteractiveControl(source)) {
    var containerSize = this.IsHorizontal() ? container.offsetWidth : container.offsetHeight;
    var leftLimitPos = containerSize * 0.35,
     rightLimitPos = containerSize * 0.65;
    var mousePosInElement = this.IsHorizontal() ? ASPx.Evt.GetEventX(evt) - ASPx.GetAbsolutePositionX(container) : ASPx.Evt.GetEventY(evt) - ASPx.GetAbsolutePositionY(container);
    if(mousePosInElement < leftLimitPos)
     value = this.OnPrevButtonMouseUp(evt);
    else if(mousePosInElement > rightLimitPos)
     value = this.OnNextButtonMouseUp(evt);
   }
   else {
    if(source == this.prevButtonWrapper || source == this.prevButton)
     value = this.OnPrevButtonMouseUp(evt);
    else if(source == this.nextButtonWrapper || source == this.nextButton)
     value = this.OnNextButtonMouseUp(evt);
   }
   return value;
  },
  IsSlideShowButton: function (element) {
   var className = CssClassesConstants.PlayPauseWrapperCssClassName;
   return element.className == className || element.parentNode.className == className;
  },
  SetEnablePrevButton: function (enable) {
   this.prevButtonEnable = enable;
   var stateController = this.GetStateController();
   if(stateController) {
    stateController.SetElementEnabled(this.prevButtonWrapper, enable);
    stateController.SetElementEnabled(this.prevButton, enable);
   }
  },
  SetEnableNextButton: function (enable) {
   this.nextButtonEnable = enable;
   var stateController = this.GetStateController();
   if(stateController) {
    stateController.SetElementEnabled(this.nextButtonWrapper, enable);
    stateController.SetElementEnabled(this.nextButton, enable);
   }
  },
  SetVisibilityButtons: function (visible) {
   if(this.visibility == visible)
    return;
   this.visibility = visible;
   ASPx.SetElementDisplay(this.prevButtonWrapper, this.visibility);
   ASPx.SetElementDisplay(this.nextButtonWrapper, this.visibility);
  },
  GetVisibilityButtons: function () {
   return this.visibility;
  },
  GetAnimationElements: function () {
   return [this.prevButtonWrapper, this.nextButtonWrapper];
  },
  GetPrevButtonWrapperSize: function () {
   return this.GetButtonSize(this.prevButtonWrapper);
  },
  GetNextButtonWrapperSize: function () {
   return this.GetButtonSize(this.nextButtonWrapper);
  },
  GetButtonSize: function (element) {
   return { width: element.offsetWidth, height: element.offsetHeight };
  }
 });
 var OutsideNavigationButtons = ASPx.CreateClass(NavigationButtons, {
  constructor: function (itemsOwner) {
   this.constructor.prototype.constructor.call(this, itemsOwner);
  },
  GetAnimationElements: function () {
   return [];
  },
  GetPrevButtonWrapperCssClassName: function () {
   return this.IsHorizontal() ?
    CssClassesConstants.NavigationButtonBackwardOutsideWrapperCssClassName : CssClassesConstants.NavigationButtonUpOutsideWrapperCssClassName;
  },
  GetNextButtonWrapperCssClassName: function () {
   return this.IsHorizontal() ?
     CssClassesConstants.NavigationButtonForwardOutsideWrapperCssClassName : CssClassesConstants.NavigationButtonDownOutsideWrapperCssClassName;
  }
 });
 var ItemsOwnerBase = ASPx.CreateClass(ControlBase, {
  constructor: function (imageSlider) {
   this.activeItemIndex = 0;
   this.prevItemIndex = -1;
   this.fullItemWidth = 0;
   this.fullItemHeight = 0;
   this.clearItemWidth = 0;
   this.clearItemHeight = 0;
   this.itemElementsManager = null; 
   this.navigationButtons = null; 
   this.slidePanelElement = null;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  Initialize: function () {
   this.activeItemIndex = this.GetRtlIndex(this.GetImageSlider().activeItemIndex);
   if(this.IsRtl())
    this.prevItemIndex = this.activeItemIndex + 1;
  },
  GetRtlIndex: function (index) {
   if(this.IsRtl())
    return this.GetItemCount() - 1 - index;
   return index;
  },
  ForEachItem: function (func) {
   var count = this.GetItemCount();
   if(!this.IsRtl()) {
    for(var i = 0; i < count ; i++)
     func.call(this, i);
   }
   else {
    for(var i = count - 1; i >= 0; i--)
     func.call(this, i);
   }
  },
  GetUniqueId: function () {
   return "";
  },
  IsAccessibilityCompliant: function () {
   return this.GetImageSlider().accessibilityCompliant;
  },
  GetItemElementsManager: function () {
   if(!this.itemElementsManager)
    this.itemElementsManager = this.CreateItemElementsManager();
   return this.itemElementsManager;
  },
  CreateItemElementsManager: function () {
   return new ItemElementsManagerBase(this);
  },
  GetTemplate: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItem(index).tpl : null;
  },
  GetNavigateUrl: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItem(index).u : null;
  },
  GetImageSrc: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItem(index).s : null;
  },
  GetItemAlternateText: function (index) {
   if(this.IsValidItemIndex(index)) {
    var item = this.GetItem(index);
    return item.t || item.at || "";
   }
   return "";
  },
  GetItem: function (index) {
   return this.GetImageSlider().GetItemInternal(this.GetRtlIndex(index));
  },
  GetItemCount: function () {
   return this.GetImageSlider().GetItemCount();
  },
  SetActiveItemIndex: function (index, preventAnimation) {
   if(!this.IsEnabled() || !this.IsValidItemIndex(index) || index == this.GetActiveItemIndex())
    return;
   this.prevItemIndex = this.GetActiveItemIndex();
   this.activeItemIndex = index;
   this.SetActiveItemIndexInternal(index, preventAnimation);
   this.EnsureShownItemsLoaded();
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   this.UpdateNavigationButtonsState();
  },
  GetActiveItemIndex: function () {
   return this.activeItemIndex;
  },
  GetPrevItemIndex: function () {
   return this.prevItemIndex;
  },
  EnsureShownItemsLoaded: function() {
   this.GetImageSlider().EnsureShownItemsLoaded();
  },
  GetItemElement: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItemElementsManager().GetCollection()[index] : null;
  },
  GetImageElement: function (index) {
   return ASPx.GetChildByTagName(this.GetItemElement(index), "IMG");
  },
  GetCanvasElement: function (index) {
   return ASPx.GetChildByTagName(this.GetItemElement(index), "CANVAS");
  },
  GetHyperLinkElement: function (index) {
   return ASPx.GetChildByClassName(this.GetItemElement(index), CssClassesConstants.ItemHyperLinkCssClassName);
  },
  GetImageContainerElement: function (index) {
   return this.GetHyperLinkElement(index) || this.GetItemElement(index);
  },
  GetItemElementSize: function (clear) {
   return this.IsHorizontalNavigation() ? this.GetItemElementWidth(clear) : this.GetItemElementHeight(clear);
  },
  GetItemElementWidth: function (clear) {
   return clear ? this.clearItemWidth : this.fullItemWidth;
  },
  GetItemElementHeight: function (clear) {
   return clear ? this.clearItemHeight : this.fullItemHeight;
  },
  GetSlidePanelElement: function () {
   return this.slidePanelElement;
  },
  GetItemsContainer: function () {
   return null;
  },
  StopPlayingWhenPaging: function () {
   this.GetImageSlider().StopPlayingWhenPaging();
  },
  CanCreateNavigationButtons: function () {
   return true;
  },
  CreateNavigationButtons: function () {
   if(this.GetNavigationBtnsVisibilityMode() == ElementVisibilityModeEnum.None)
    return null;
   return new NavigationButtons(this);
  },
  GetNavigationBtnsVisibilityMode: function () {
   return this.GetImageSlider().navBtnsVbl;
  },
  UpdateNavigationButtonsState: function () {
   return false;
  },
  GetButtonsContainer: function () {
   return null;
  },
  GetPrevButtonHtml: function () {
   return "";
  },
  GetNextButtonHtml: function () {
   return "";
  },
  CanHandleButtons: function () {
   return !this.IsExecutedGesture();
  },
  IsExecutedGesture: function () {
   return ASPx.GesturesHelper.IsExecutedGesture();
  },
  IsEnablePagingByClick: function () {
   return false;
  },
  SetEnablePrevButton: function (enabled) {
   if(this.navigationButtons)
    this.navigationButtons.SetEnablePrevButton(enabled);
  },
  SetEnableNextButton: function (enabled) {
   if(this.navigationButtons)
    this.navigationButtons.SetEnableNextButton(enabled);
  },
  SetVisibilityButtons: function (visible) {
   if(this.navigationButtons)
    this.navigationButtons.SetVisibilityButtons(visible);
  },
  PerformBackward: function () {
  },
  PerformForward: function () {
  },
  PerformRollBack: function () {
  },
  GetEnableLoopNavigation: function () {
   return false;
  },
  GetImageLoadMode: function () {
   return this.GetImageSlider().imageLoadMode;
  },
  UpdateItemElementsIfRequired: function () {
   this.GetItemElementsManager().UpdateHierarchyIfRequired();
  },
  UpdateItemElementsAfterDelayIfRequired: function () {
   this.GetItemElementsManager().UpdateHierarchyAfterDelayIfRequired();
  },
  IsNeedCreateHyperLink: function () {
   return true;
  },
  GetTarget: function () {
   return this.GetImageSlider().target;
  },
  CreateTemplates: function () {
   this.ForEachItem(function (i) {
    this.CreateTemplate(i);
   });
  },
  CreateTemplate: function(index) {
   var template = this.GetTemplate(index);
   if(template) {
    var itemElement = this.GetItemElement(index);
    if(!itemElement)
     return;
    var child = itemElement.firstChild ? itemElement.firstChild.cloneNode(true) : null;
    itemElement.innerHTML = template;
    if(child)
     itemElement.appendChild(child);
    ASPx.ImageControlUtils.RemoveLoadingGif(itemElement);
   }
  },
  CreateControlHierarchy: function () {
   this.CreateControlHierarchyInternal();
   if(this.CanCreateNavigationButtons())
    this.navigationButtons = this.CreateNavigationButtons();
   this.GetItemElementsManager().CreateItemsIfRequired();
  },
  CreateControlHierarchyInternal: function () {
  },
  CreateItemElements: function () {
   this.ForEachItem(function (i) {
    this.GetItemsContainer().appendChild(this.CreateItemElement(i));
   });
  },
  CreateItemElement: function (index) {
   var itemElement = this.CreateDiv();
   if(!this.GetTemplate(index)) {
    var hyperLinkElement = this.CreateHyperLinkElement(index);
    if(hyperLinkElement)
     itemElement.appendChild(hyperLinkElement);
   }
   return itemElement;
  },
  CreateImageElement: function (index) {
   var image = new Image();
   ASPx.SetElementDisplay(image, false);
   this.AttachLoadEvent(image);
   this.GetImageContainerElement(index).appendChild(image);
   image.dxIndex = index;
   image.dxImageSlider = this;
   image.src = this.GetImageSrc(index);
   image.alt = this.IsAccessibilityCompliant() ? this.GetItemAlternateText(index) : "";
   return image;
  },
  CreateHyperLinkElement: function (index) {
   var url = this.GetNavigateUrl(index);
   if(!this.IsNeedCreateHyperLink() || !url)
    return null;
   var element = document.createElement("A");
   element.target = this.GetTarget();
   element.className = CssClassesConstants.ItemHyperLinkCssClassName;
   element.href = url;
   return element;
  },
  PrepareControlHierarchy: function () {
   this.GetItemElementsManager().PrepareItemsIfRequired();
  },
  PrepareItemElements: function () {
   this.ForEachItem(function (i) {
    this.PrepareItemElement(i);
   });
  },
  PrepareItemElement: function (index) {
   var itemElement = this.GetItemElement(index);
   ASPx.SetStyles(itemElement, {
    className: this.GetItemElementCssClass(),
    cssText: this.GetItemElementStyle()
   });
   if(this.GetTemplate(index))
    ASPx.ImageControlUtils.RemoveLoadingGif(itemElement);
  },
  AdjustControl: function () {
   ControlBase.prototype.AdjustControl.call(this);
   if(this.navigationButtons)
    this.navigationButtons.AdjustControl();
   this.AdjustControlInternal();
   this.SetActiveItemIndexInternal(this.GetActiveItemIndex(), true);
  },
  AdjustControlInternal: function () {
   this.AdjustItemElements();
  },
  AdjustItemElements: function () {
   this.GetItemElementsManager().AdjustItemsIfRequired();
  },
  CalculateSize: function () {
   var fakeElement = this.CreateDiv();
   ASPx.SetStyles(fakeElement, {
    className: this.GetItemElementCssClass(),
    cssText: this.GetItemElementStyle()
   });
   this.CalculateItemElementSize(fakeElement);
   ASPx.RemoveElement(fakeElement);
  },
  CalculateItemElementSize: function (element) {
  },
  AdjustItemElement: function (index) {
   ASPx.SetStyles(this.GetItemElement(index), {
    width: this.GetItemElementWidth(true),
    height: this.GetItemElementHeight(true)
   });
  },
  AdjustImageElement: function (index) {
   if(this.GetTemplate(index) || !this.GetImageSrc(index))
    return;
   var image = this.GetImageElement(index);
   if(!image)
    image = this.CreateImageElement(index);
   else if(ASPx.ImageControlUtils.IsImageLoaded(image))
    this.ResizeImage(image, index);
  },
  UpdateItemElement: function(index) {
   if(this.GetImageContainerElement(index))
    this.AdjustImageElement(index);
   if(this.GetImageSlider().HasTemplates())
    this.CreateTemplate(index);
  },
  GetItemElementCssClass: function () {
   return "";
  },
  GetItemElementStyle: function () {
   return "";
  },
  ResizeImage: function (image, index) {
   ASPx.ImageControlUtils.ResizeImage(image, {
    width: this.GetItemElementWidth(true),
    height: this.GetItemElementHeight(true),
    sizeMode: this.GetImageSizeMode(),
    rtl: this.IsRtl(true),
    onEndResize: function(element, isCanvas) {
     if(isCanvas)
      this.PrepareCanvasElement(index);
    }.aspxBind(this),
    canUseCanvas: !this.IsAccessibilityCompliant()
   });
  },
  PrepareCanvasElement: function (index) {
  },
  GetImageSizeMode: function () {
   return this.GetImageSlider().imageSizeMode;
  },
  GetSwipeGestureElement: function () {
   return this.GetSlidePanelElement();
  },
  CanCreateSwipeGestureHandler: function () {
   return false;
  },
  CreateSwipeGestureHandler: function () {
   ASPx.GesturesHelper.AddSwipeSlideGestureHandler(
    this.GetClientControlName() + this.GetUniqueId(),
    function () { return this.GetSwipeGestureElement(); }.aspxBind(this),
    this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
    function (evt) { return this.CanHandleSwipeGesture(evt); }.aspxBind(this),
    function () { this.PerformBackward(); }.aspxBind(this),
    function () { this.PerformForward(); }.aspxBind(this),
    function () { this.PerformRollBack(); }.aspxBind(this)
   );
  },
  CanHandleSwipeGesture: function (evt) {
   return !!ASPx.GetIsParent(this.GetSwipeGestureElement(), ASPx.Evt.GetEventSource(evt));
  },
  InitializeHandlers: function () {
   if(this.GetImageSlider().allowMouseWheel && !(ASPx.Browser.Edge && ASPx.Browser.MSTouchUI))
    ASPx.Evt.AttachEventToElement(this.GetItemsContainer(), ASPx.Evt.GetMouseWheelEventName(), function (evt) { this.OnMouseWheel(evt); }.aspxBind(this));
   if(this.CanCreateSwipeGestureHandler() && this.GetImageSlider().enablePagingGestures)
    this.CreateSwipeGestureHandler();
  },
  AttachLoadEvent: function (image) {
   ASPx.Evt.AttachEventToElement(image, "load", _onImageLoad);
  },
  DetachLoadEvents: function (image) {
   ASPx.Evt.DetachEventFromElement(image, "load", _onImageLoad);
  },
  OnMouseWheel: function (evt) {
   if(!this.IsFocused())
    return;
   if(ASPx.Evt.GetWheelDelta(evt) > 0)
    this.PerformBackward();
   else
    this.PerformForward();
   return ASPx.Evt.PreventEvent(evt);
  },
  OnImageLoad: function (image) {
   this.InitializeImage(image);
   this.ResizeImage(image, image.dxIndex);
   ASPx.ImageControlUtils.RemoveLoadingGif(this.GetItemElement(image.dxIndex));
  },
  InitializeImage: function (image) {
   if(image.naturalWidth && image.naturalHeight)
    return;
   image.naturalWidth = image.width;
   image.naturalHeight = image.height;
  },
  GetElementTransformPosition: function (element) {
   return ASPx.AnimationUtils.GetTransformValue(element, !this.IsHorizontalNavigation());
  },
  SetElementTransformPosition: function (element, position) {
   ASPx.AnimationUtils.SetTransformValue(element, position, !this.IsHorizontalNavigation());
  },
  GetWidth: function () {
   return 0;
  },
  GetHeight: function () {
   return 0;
  },
  IsFocused: function () {
   return this.GetImageSlider().IsFocused();
  },
  CreateDocumentFragment: function () {
   var fragment = null;
   if(document.createDocumentFragment)
    fragment = document.createDocumentFragment();
   return fragment;
  },
  IsValidItemIndex: function (index) {
   if(index >= 0 && index < this.GetItemCount())
    return true;
   return false;
  }
 });
 function _onImageLoad(evt) {
  var image = evt.srcElement || this;
  if(!image.dxImageSlider)
   return;
  var imageSlider = image.dxImageSlider;
  imageSlider.DetachLoadEvents(image);
  if(!image.parentNode) return;
  imageSlider.OnImageLoad(image);
 }
 var ImageAreaStrategy = ASPx.CreateClass(ItemsOwnerBase, {
  constructor: function (imageSlider) {
   this.currentItemTextElementOpacity = 0;
   this.defaultItemTextElementOpacity = 0;
   this.touchDeviceElementsVisible = false;
   this.imageAreaStyleSize = { width: "", height: "" };
   this.imageAreaElement = null;
   this.slideShowButton = null; 
   this.overlayLinkElement = null;
   this.overlayImageElement = null;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  Initialize: function () {
   ItemsOwnerBase.prototype.Initialize.call(this);
   if(this.GetItemTextVisibilityMode() == ElementVisibilityModeEnum.Faded)
    this.defaultItemTextElementOpacity = FadedDefaultOpacity;
   else if(ASPx.Browser.Firefox)
    this.defaultItemTextElementOpacity = 0.01; 
   this.currentItemTextElementOpacity = this.defaultItemTextElementOpacity;
  },
  GetUniqueId: function () {
   return "_ia_";
  },
  CreateItemElementsManager: function () {
   return new ImageAreaItemElementsManager(this);
  },
  GetTextTemplate: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItem(index).ttpl : null;
  },
  GetItemText: function (index) {
   return this.IsValidItemIndex(index) ? this.GetItem(index).t : null;
  },
  SetSlideShowButtonState: function (play) {
   if(this.slideShowButton)
    this.slideShowButton.SetButtonState(play);
  },
  IsEnablePagingByClick: function () {
   return this.GetImageSlider().enablePagingByClick;
  },
  GetButtonsContainer: function () {
   return this.GetImageSlider().GetPassePartoutElement();
  },
  GetPrevButtonHtml: function () {
   return this.GetImageSlider().pbh;
  },
  GetNextButtonHtml: function () {
   return this.GetImageSlider().nbh;
  },
  UpdateNavigationButtonsState: function () {
   if(this.navigationButtons) {
    if(this.GetItemCount() == 1)
     this.SetVisibilityButtons(false);
    else {
     var currentItemIndex = this.GetActiveItemIndex();
     this.SetEnablePrevButton(currentItemIndex != 0);
     this.SetEnableNextButton(currentItemIndex != this.GetItemCount() - 1);
    }
   }
   return false;
  },
  PerformBackward: function () {
   this.StopPlayingWhenPaging();
   var index = this.GetActiveItemIndex();
   index--;
   if(index < 0 && this.GetEnableLoopNavigation())
    index = this.GetItemCount() - 1;
   this.GetImageSlider().SetActiveItemIndexInternal(index);
  },
  PerformForward: function () {
   this.StopPlayingWhenPaging();
   var index = this.GetActiveItemIndex();
   index++;
   if(index == this.GetItemCount() && this.GetEnableLoopNavigation())
    index = 0;
   this.GetImageSlider().SetActiveItemIndexInternal(index);
  },
  PerformRollBack: function () {
   this.SetActiveItemIndexInternal(this.GetActiveItemIndex(), false);
  },
  CreateControlHierarchy: function () {
   ItemsOwnerBase.prototype.CreateControlHierarchy.call(this);
   this.CreateOverlayElements();
  },
  CreateTemplate: function(index) {
   ItemsOwnerBase.prototype.CreateTemplate.call(this, index);
   var template = this.GetTextTemplate(index);
   if(template) {
    var itemTextElement = this.GetItemTextElement(index);
    if(itemTextElement)
     itemTextElement.innerHTML = template;
   }
  },
  CreateControlHierarchyInternal: function () {
   ItemsOwnerBase.prototype.CreateControlHierarchyInternal.call(this);
   this.CreateImageAreaElement();
   this.CreateSlideShowButton();
  },
  CreateImageAreaElement: function () {
   this.imageAreaElement = document.createElement("DIV");
   this.GetImageSlider().GetPassePartoutElement().appendChild(this.imageAreaElement);
  },
  CreateSlideShowButton: function () {
   if(this.GetImageSlider().playPauseBtnVbl != ElementVisibilityModeEnum.None)
    this.slideShowButton = new SlideShowButton(this);
  },
  CreateOverlayElements: function () {
   var itemsContainer = this.GetItemsContainer();
   if(!itemsContainer)
    return;
   if(this.GetImageSlider().HasNavigateUrls()) {
    this.overlayLinkElement = document.createElement("A");
    itemsContainer.insertBefore(this.overlayLinkElement, itemsContainer.firstChild);
    this.overlayLinkElement.className = CssClassesConstants.OverlayElementCssClass;
    this.overlayLinkElement.target = this.GetTarget();
   }
   this.overlayImageElement = document.createElement("IMG");
   this.overlayImageElement.src = ASPx.EmptyImageUrl;
   this.overlayImageElement.alt = "";
   if(this.overlayLinkElement)
    this.overlayLinkElement.appendChild(this.overlayImageElement);
   else {
    this.overlayImageElement.className = CssClassesConstants.OverlayElementCssClass;
    itemsContainer.insertBefore(this.overlayImageElement, itemsContainer.firstChild);
   }
  },
  UpdateOverlayParameters: function () {
   var activeItemIndex = this.GetActiveItemIndex();
   var currentItem = this.GetItem(activeItemIndex);
   if(this.overlayLinkElement) {
    if(!currentItem.u)
     this.overlayLinkElement.removeAttribute("href");
    else if(this.overlayLinkElement.href != currentItem.u)
     this.overlayLinkElement.href = currentItem.u;
   }
   if(this.overlayImageElement) {
    if(currentItem.s)
     this.overlayImageElement.src = currentItem.s;
    if(currentItem.tpl)
     this.overlayImageElement.style.display = "none";
    else {
     this.overlayImageElement.style.display = "";
     this.overlayImageElement.alt = this.IsAccessibilityCompliant() ? this.GetItemAlternateText(activeItemIndex) : "";
    }
   }
  },
  PrepareControlHierarchy: function () {
   ItemsOwnerBase.prototype.PrepareControlHierarchy.call(this);
   this.UpdateOverlayParameters();
   var imageAreaElement = this.GetImageAreaElement();
   ASPx.SetStyles(imageAreaElement, {
    className: this.GetImageSlider().imgAreaCssCl,
    cssText: this.GetImageSlider().imgAreaStyle
   });
   this.imageAreaStyleSize = {
    width: imageAreaElement.style.width,
    height: imageAreaElement.style.height
   };
   this.GetItemsContainer().style.zIndex = "0";
  },
  AdjustControl: function (width, height) {
   this.AdjustImageAreaElement(width, height);
   ItemsOwnerBase.prototype.AdjustControl.call(this);
  },
  AdjustImageAreaElement: function (width, height) {
   var imageAreaElement = this.GetImageAreaElement();
   if(!imageAreaElement.style.width) {
    ASPx.SetStyles(imageAreaElement, { width: width });
    if(imageAreaElement.offsetWidth > width)
     ASPx.SetStyles(imageAreaElement, { width: width - (imageAreaElement.offsetWidth - width) });
   }
   if(!imageAreaElement.style.height) {
    ASPx.SetStyles(imageAreaElement, { height: height });
    if(imageAreaElement.offsetHeight > height)
     ASPx.SetStyles(imageAreaElement, { height: height - (imageAreaElement.offsetHeight - height) });
   }
   if(imageAreaElement.offsetHeight < height)
    ASPx.SetStyles(imageAreaElement, { top: (height - imageAreaElement.offsetHeight) / 2 });
  },
  ResetControlStyle: function () {
   var imageAreaElement = this.GetImageAreaElement();
   ASPx.SetStyles(imageAreaElement, this.imageAreaStyleSize);
   ASPx.SetStyles(imageAreaElement, { top: 0 });
  },
  IsNeedCreateHyperLink: function () {
   return false;
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   ItemsOwnerBase.prototype.SetActiveItemIndexInternal.call(this, index, preventAnimation);
   this.UpdateOverlayParameters();
  },
  CalculateItemElementSize: function (fakeElement) {
   var imageArea = this.GetImageAreaElement();
   imageArea.appendChild(fakeElement);
   this.fullItemWidth = SizeUtils.GetClientWidth(imageArea, true);
   this.fullItemHeight = SizeUtils.GetClientHeight(imageArea, true);
   ASPx.SetStyles(fakeElement, {
    width: this.fullItemWidth,
    height: this.fullItemHeight
   });
   this.clearItemWidth = this.fullItemWidth - (SizeUtils.GetClientWidth(fakeElement) - this.fullItemWidth);
   this.clearItemHeight = this.fullItemHeight - (SizeUtils.GetClientHeight(fakeElement) - this.fullItemHeight);
  },
  CreateItemElement: function (index) {
   var itemElement = ItemsOwnerBase.prototype.CreateItemElement.call(this, index);
   var textElement = this.CreateItemTextElement(index);
   if(!textElement)
    return itemElement;
   itemElement.appendChild(textElement);
   return itemElement;
  },
  CreateItemTextElement: function (index) {
   var text = this.GetItemText(index);
   var textTemplate = this.GetTextTemplate(index);
   if(this.GetItemTextVisibilityMode() == ElementVisibilityModeEnum.None || (!text && !textTemplate))
    return null;
   var itemTextElement = this.CreateDiv();
   if(!textTemplate)
    itemTextElement.innerHTML = text;
   ASPx.SetStyles(itemTextElement, { className: this.GetImageSlider().itemTxtCssCl });
   return itemTextElement;
  },
  PrepareItemTextElement: function (index) {
   var itemTextElement = this.GetItemTextElement(index);
   if(itemTextElement) {
    var style = { cssText: this.GetImageSlider().itemTxtStyle, zIndex: 2, className: itemTextElement.className + " dx-wbv" };
    if(this.GetItemTextVisibilityMode() != ElementVisibilityModeEnum.Always)
     style.opacity = this.currentItemTextElementOpacity;
    ASPx.SetStyles(itemTextElement, style);
   }
  },
  PrepareItemElement: function (index) {
   ItemsOwnerBase.prototype.PrepareItemElement.call(this, index);
   this.PrepareItemTextElement(index);
  },
  UpdateItemElement: function(index) {
   var textElement = this.CreateItemTextElement(index);
   var imageContainer = this.GetImageContainerElement(index);
   if(textElement && imageContainer) {
    imageContainer.appendChild(textElement);
    this.PrepareItemTextElement(index);
   }
   ItemsOwnerBase.prototype.UpdateItemElement.call(this, index);
   if(this.GetActiveItemIndex() == index)
    this.UpdateOverlayParameters();
  },
  GetItemElementCssClass: function () {
   return this.GetImageSlider().itemCssCl;
  },
  GetItemElementStyle: function () {
   return this.GetImageSlider().itemStyle;
  },
  PrepareCanvasElement: function (index) {
   var canvas = this.GetCanvasElement(index);
   canvas.style.position = "absolute";
   canvas.style.zIndex = "0";
  },
  GetItemTextElement: function (index) {
   var itemElement = this.GetItemElement(index);
   return itemElement ? ASPx.GetChildByClassName(itemElement, CssClassesConstants.TextAreaCssClassName) : null;
  },
  GetImageAreaElement: function () {
   return this.imageAreaElement;
  },
  GetItemTextVisibilityMode: function () {
   return this.GetImageSlider().itemTxtVbl;
  },
  GetNavigationBarStrategy: function () {
   return this.GetImageSlider().GetNavigationBarStrategy();
  },
  HasMouseOverForTouchDevice: function () {
   if(!ASPx.Browser.TouchUI)
    return false;
   return this.HasMouseOverImageAreaNavigationButtons() || this.HasMouseOverNavigationBarNavigationButtons() || this.HasMouseOverTextArea() || this.HasMouseOverSlideShowButton();
  },
  HasMouseOverImageAreaNavigationButtons: function () {
   return this.IsMouseOverOrFaded(this.GetNavigationBtnsVisibilityMode());
  },
  HasMouseOverNavigationBarNavigationButtons: function () {
   var navigationBar = this.GetNavigationBarStrategy();
   if(!navigationBar)
    return false;
   return this.IsMouseOverOrFaded(navigationBar.GetNavigationBtnsVisibilityMode());
  },
  HasMouseOverTextArea: function () {
   return this.IsMouseOverOrFaded(this.GetItemTextVisibilityMode());
  },
  HasMouseOverSlideShowButton: function () {
   return this.IsMouseOverOrFaded(this.GetImageSlider().playPauseBtnVbl);
  },
  IsMouseOverOrFaded: function (visibility) {
   return visibility == ElementVisibilityModeEnum.Faded || visibility == ElementVisibilityModeEnum.OnMouseOver;
  },
  InitializeHandlers: function () {
   ItemsOwnerBase.prototype.InitializeHandlers.call(this);
   var imageSlider = this.GetImageSlider();
   imageSlider.StrategiesCreated.AddHandler(function () {
    if(this.CanHandleClickEvent())
     ASPx.Evt.AttachEventToElement(this.GetImageAreaElement(), ASPx.Browser.TouchUI ? ASPx.TouchUIHelper.touchMouseUpEventName : "click", function (evt) { this.OnImageAreaClick(evt); }.aspxBind(this));
   }.aspxBind(this));
   if(!ASPx.Browser.TouchUI && this.IsMouseOverOrFaded(this.GetItemTextVisibilityMode()))
    MouseEnterHelper.AddHandler(
     imageSlider.GetPassePartoutElement(),
     function () { this.AppearTextElements(); }.aspxBind(this),
     function () { this.DisappearTextElements(); }.aspxBind(this)
    );
  },
  CanHandleClickEvent: function () {
   var imageSlider = this.GetImageSlider();
   return !imageSlider.ItemClick.IsEmpty() || imageSlider.HasNavigateUrls() || this.HasMouseOverForTouchDevice();
  },
  OnImageAreaClick: function (evt) {
   this.GetImageSlider().RaiseItemClick();
   if(!this.HasMouseOverForTouchDevice())
    return;
   if(this.touchDeviceElementsVisible) {
    if(this.HasMouseOverTextArea())
     this.DisappearTextElements();
    if(this.HasMouseOverImageAreaNavigationButtons())
     this.navigationButtons.Disappear();
    if(this.HasMouseOverNavigationBarNavigationButtons())
     this.GetNavigationBarStrategy().navigationButtons.Disappear();
    if(this.HasMouseOverSlideShowButton())
     this.slideShowButton.Disappear();
   }
   else {
    if(this.HasMouseOverTextArea())
     this.AppearTextElements();
    if(this.HasMouseOverImageAreaNavigationButtons())
     this.navigationButtons.Appear();
    if(this.HasMouseOverNavigationBarNavigationButtons())
     this.GetNavigationBarStrategy().navigationButtons.Appear();
    if(this.HasMouseOverSlideShowButton())
     this.slideShowButton.Appear();
   }
   this.touchDeviceElementsVisible = !this.touchDeviceElementsVisible;
  },
  AppearTextElements: function () {
   this.FadeItemTextElements(1);
  },
  DisappearTextElements: function () {
   this.FadeItemTextElements(this.defaultItemTextElementOpacity);
  },
  FadeItemTextElements: function (value) {
   this.currentItemTextElementOpacity = value;
   var activeItemIndex = this.GetActiveItemIndex();
   this.ForEachItem(function (i) {
    var preventAnimation = true;
    if(i == activeItemIndex && this.GetAnimationType() != AnimationTypeEnum.None)
     preventAnimation = false;
    this.FadeItemTextElement(i, preventAnimation);
   });
  },
  FadeItemTextElement: function (index, preventAnimation) {
   var textElement = this.GetItemTextElement(index);
   if(!textElement) 
    return;
   if(preventAnimation)
    ASPx.SetStyles(textElement, { opacity: this.currentItemTextElementOpacity });
   else
    ASPx.AnimationHelper.fadeTo(textElement, { to: this.currentItemTextElementOpacity });
  },
  GetWidth: function () {
   return SizeUtils.GetClientWidth(this.GetImageAreaElement());
  },
  GetHeight: function () {
   return SizeUtils.GetClientHeight(this.GetImageAreaElement());
  }
 });
 var SlideImageAreaStrategy = ASPx.CreateClass(ImageAreaStrategy, {
  constructor: function (imageSlider) {
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   ImageAreaStrategy.prototype.SetActiveItemIndexInternal.call(this, index, preventAnimation);
   this.UpdateItemElementsAfterDelayIfRequired();
   var position = this.GetItemElementPosition(index);
   if(preventAnimation) {
    this.SetElementTransformPosition(this.GetSlidePanelElement(), position);
    this.UpdateItemElementsIfRequired();
   }
   else
    ASPx.AnimationHelper.slideTo(this.GetSlidePanelElement(), {
     to: position, duration: this.GetImageSlider().animationDuration,
     direction: this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
     onComplete: function () { this.UpdateItemElementsIfRequired(); }.aspxBind(this)
    });
  },
  PerformRollBack: function () {
   this.SetActiveItemIndexInternal(this.GetActiveItemIndex(), false);
  },
  CreateControlHierarchyInternal: function () {
   ImageAreaStrategy.prototype.CreateControlHierarchyInternal.call(this);
   this.slidePanelElement = this.CreateDiv();
   this.GetImageAreaElement().appendChild(this.slidePanelElement);
  },
  PrepareControlHierarchy: function () {
   ImageAreaStrategy.prototype.PrepareControlHierarchy.call(this);
   var slideElement = this.GetSlidePanelElement();
   slideElement.className = CssClassesConstants.ImageAreaSlidePanelCssClassName;
   this.PatchElementForMSTouch(slideElement);
  },
  AdjustControlInternal: function () {
   ImageAreaStrategy.prototype.AdjustControlInternal.call(this);
   var horizontal = this.IsHorizontalNavigation();
   var width = horizontal ? this.GetItemCount() * this.GetItemElementWidth() : this.GetItemElementWidth();
   var height = !horizontal ? this.GetItemCount() * this.GetItemElementHeight() : this.GetItemElementHeight();
   ASPx.SetStyles(this.GetSlidePanelElement(), {
    width: width,
    height: height
   });
  },
  AdjustItemElement: function (index) {
   ImageAreaStrategy.prototype.AdjustItemElement.call(this, index);
   var itemElement = this.GetItemElement(index);
   var position = this.IsHorizontalNavigation() ? this.GetItemElementWidth() * index : this.GetItemElementHeight() * index;
   if(this.IsHorizontalNavigation())
    ASPx.SetStyles(itemElement, { left: position });
   else
    ASPx.SetStyles(itemElement, { top: position });
  },
  GetItemsContainer: function () {
   return this.GetSlidePanelElement();
  },
  CanCreateSwipeGestureHandler: function () {
   return true;
  },
  IsEnablePagingByClick: function () {
   var imageSlider = this.GetImageSlider();
   return imageSlider.ItemClick.IsEmpty() && !imageSlider.HasNavigateUrls() && ImageAreaStrategy.prototype.IsEnablePagingByClick.call(this);
  },
  OnImageAreaClick: function (evt) {
   if(this.IsExecutedGesture())
    return ASPx.Evt.PreventEventAndBubble(evt);
   else
    ImageAreaStrategy.prototype.OnImageAreaClick.call(this, evt);
  },
  GetItemElementPosition: function (index) {
   return this.IsHorizontalNavigation() ? -(index * this.GetItemElementWidth()) : -(index * this.GetItemElementHeight());
  }
 });
 var SlideLoopNavigationImageAreaStrategy = ASPx.CreateClass(SlideImageAreaStrategy, {
  constructor: function (imageSlider) {
   this.simpleTransition = null;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  CreateItemElementsManager: function () {
   return new LoopImageAreaItemElementsManager(this);
  },
  GetEnableLoopNavigation: function () {
   return true;
  },
  StartSlideSimpleTransition: function (from, to, preventAnimation) {
   this.UpdateItemsPosition(to - from, preventAnimation);
   if(!preventAnimation) {
    this.simpleTransition = ASPx.AnimationHelper.createSimpleAnimationTransition({
     duration: this.GetImageSlider().animationDuration,
     onUpdate: function (value) {
      this.UpdateItemsPosition(value, true);
     }.aspxBind(this)
    });
    this.simpleTransition.Start(from, to);
   }
  },
  StopSimpleTransition: function () {
   if(this.simpleTransition) {
    this.simpleTransition.Cancel();
    this.simpleTransition = null;
   }
  },
  UpdateItemsPosition: function (value, needApplyPositions) {
   this.ForEachItem(function (i) {
    var element = this.GetItemElement(i);
    if(element) {
     element.dxPosition = element.dxPosition + value;
     if(needApplyPositions)
      this.SetItemPosition(element);
    }
   });
  },
  OnMouseMoveUpdatePosition: function (position) {
   this.StopSimpleTransition();
   var itemSize = this.GetItemElementSize();
   this.ForEachItem(function (i) {
    var element = this.GetItemElement(i);
    if(element)
     element.dxPosition = element.dxPosition + position;
   });
   this.ForEachItem(function (i) {
    var element = this.GetItemElement(i);
    if(!element)
     return;
    this.SetItemPosition(element);
    if(element.dxPosition < 0 && ((element.dxPosition + itemSize) > 0)) {
     var index = i + 1;
     if(index == this.GetItemCount())
      index = 0;
     var nextItem = this.GetItemElement(index);
     if(nextItem) {
      nextItem.dxPosition = element.dxPosition + itemSize;
      this.SetItemPosition(nextItem);
     }
    }
    if(element.dxPosition < itemSize && ((element.dxPosition + itemSize) > itemSize)) {
     var index = i - 1;
     if(index < 0)
      index = this.GetItemCount() - 1;
     var nextItem = this.GetItemElement(index);
     if(nextItem) {
      nextItem.dxPosition = element.dxPosition - itemSize;
      this.SetItemPosition(nextItem);
     }
    }
   });
  },
  SetItemPosition: function (itemElement) {
   this.SetElementTransformPosition(itemElement, itemElement.dxPosition);
  },
  SetActiveItemIndexInternal: function (index, preventAnimation, isRollback) {
   ImageAreaStrategy.prototype.SetActiveItemIndexInternal.call(this, index, preventAnimation);
   this.StopSimpleTransition();
   this.UpdateItemElementsIfRequired();
   var currentIndex = this.GetPrevItemIndex();
   if(currentIndex == -1 || this.IsRtl() && currentIndex == this.GetItemCount())
    currentIndex = index;
   if(!isRollback) {
    var isLeft = currentIndex > index;
    if(currentIndex == 0 && index == this.GetItemCount() - 1)
     isLeft = true;
    if(currentIndex == this.GetItemCount() - 1 && index == 0)
     isLeft = false;
    var prevItem = this.GetItemElement(currentIndex);
    var nextIndex = isLeft ? currentIndex - 1 : currentIndex + 1;
    for(var i = 1; i < this.GetItemCount() ; i++) {
     if(isLeft && nextIndex < 0)
      nextIndex = this.GetItemCount() - 1;
     else if(nextIndex == this.GetItemCount())
      nextIndex = 0;
     var nextItem = this.GetItemElement(nextIndex);
     if(nextItem) {
      nextItem.dxPosition = (isLeft ? -1 : 1) * (this.GetItemElementSize() * i) + prevItem.dxPosition;
      this.SetItemPosition(nextItem);
     }
     nextIndex = isLeft ? nextIndex - 1 : nextIndex + 1;
    }
   }
   var offset = this.GetItemElement(index).dxPosition;
   this.StartSlideSimpleTransition(offset, 0, preventAnimation);
  },
  PerformRollBack: function () {
   this.SetActiveItemIndexInternal(this.GetActiveItemIndex(), false, true);
  },
  CreateControlHierarchyInternal: function () {
   ImageAreaStrategy.prototype.CreateControlHierarchyInternal.call(this);
  },
  PrepareControlHierarchy: function () {
   ImageAreaStrategy.prototype.PrepareControlHierarchy.call(this);
   this.PatchElementForMSTouch(this.GetImageAreaElement());
  },
  AdjustControlInternal: function () {
   ImageAreaStrategy.prototype.AdjustControlInternal.call(this);
  },
  AdjustItemElement: function (index) {
   ImageAreaStrategy.prototype.AdjustItemElement.call(this, index);
   var itemElement = this.GetItemElement(index);
   itemElement.dxPosition = this.IsHorizontalNavigation() ? this.GetItemElementWidth() * index : this.GetItemElementHeight() * index;
   this.SetItemPosition(itemElement);
  },
  CreateSwipeGestureHandler: function () {
   ASPx.GesturesHelper.AddSwipeSlideGestureHandler(
    this.GetClientControlName() + this.GetUniqueId(),
    function () { return this.GetSwipeGestureElement(); }.aspxBind(this),
    this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
    function (evt) { return this.CanHandleSwipeGesture(evt); }.aspxBind(this),
    function () { this.PerformBackward(); }.aspxBind(this),
    function () { this.PerformForward(); }.aspxBind(this),
    function () { this.PerformRollBack(); }.aspxBind(this),
    function (position) { this.OnMouseMoveUpdatePosition(position); }.aspxBind(this)
   );
  },
  UpdateOverlayParameters: function () {
   SlideImageAreaStrategy.prototype.UpdateOverlayParameters.call(this);
   if(this.overlayImageElement) {
    var textElement = this.GetItemTextElement(this.GetActiveItemIndex());
    if(textElement)
     this.overlayImageElement.style.height = (this.GetImageAreaElement().offsetHeight - textElement.offsetHeight) + "px";
   }
  },
  GetSwipeGestureElement: function () {
   return this.GetImageAreaElement();
  },
  GetItemsContainer: function () {
   return this.GetImageAreaElement();
  },
  UpdateNavigationButtonsState: function () {
   return false;
  }
 });
 FadeImageAreaStrategy = ASPx.CreateClass(ImageAreaStrategy, {
  constructor: function (imageSlider) {
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   ImageAreaStrategy.prototype.SetActiveItemIndexInternal.call(this, index, preventAnimation);
   this.UpdateItemElementsIfRequired();
   var appearItem = this.GetItemElement(index);
   var disapperItem = this.GetItemElement(this.GetPrevItemIndex());
   if(preventAnimation) {
    this.SetVisible(appearItem);
    if(disapperItem)
     this.SetInvisible(disapperItem);
   }
   else {
    var duration = this.GetImageSlider().animationDuration;
    ASPx.SetElementDisplay(appearItem, true);
    ASPx.AnimationHelper.fadeTo(disapperItem, {
     to: 0, duration: duration,
     onComplete: function (el) { ASPx.SetElementDisplay(el, false); }
    });
    ASPx.AnimationHelper.fadeTo(appearItem, {
     to: 1, duration: duration
    });
   }
  },
  UpdateNavigationButtonsState: function () {
   if(!this.GetEnableLoopNavigation())
    return ImageAreaStrategy.prototype.UpdateNavigationButtonsState.call(this);
   return false;
  },
  AdjustItemElement: function (index) {
   ImageAreaStrategy.prototype.AdjustItemElement.call(this, index);
   this.SetInvisible(this.GetItemElement(index));
  },
  GetEnableLoopNavigation: function () {
   return this.GetImageSlider().enableLoopNavigation;
  },
  CanCreateSwipeGestureHandler: function () {
   return true;
  },
  GetSwipeGestureElement: function () {
   return this.GetImageAreaElement();
  },
  OnImageAreaClick: function (evt) {
   if(this.IsExecutedGesture())
    return ASPx.Evt.PreventEventAndBubble(evt);
   else
    ImageAreaStrategy.prototype.OnImageAreaClick.call(this, evt);
  },
  CreateSwipeGestureHandler: function () {
   ASPx.GesturesHelper.AddSwipeSlideGestureHandler(
    this.GetClientControlName() + this.GetUniqueId(),
    function () { return this.GetSwipeGestureElement(); }.aspxBind(this),
    this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
    function (evt) { return this.CanHandleSwipeGesture(evt); }.aspxBind(this),
    function () { this.PerformBackward(); }.aspxBind(this),
    function () { this.PerformForward(); }.aspxBind(this),
    function () { },
    function () { }
   );
  },
  GetItemsContainer: function () {
   return this.GetImageAreaElement();
  },
  SetVisible: function (element) {
   ASPx.SetStyles(element, {
    display: "",
    opacity: 1
   });
  },
  SetInvisible: function (element) {
   ASPx.SetStyles(element, {
    display: "none",
    opacity: 0
   });
  }
 });
 var NoneImageAreaStrategy = ASPx.CreateClass(FadeImageAreaStrategy, {
  constructor: function (imageSlider) {
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   FadeImageAreaStrategy.prototype.SetActiveItemIndexInternal.call(this, index, true);
  }
 });
 var NavigationBarStrategy = ASPx.CreateClass(ItemsOwnerBase, {
  constructor: function (imageSlider) {
   this.navigationBarElement = null;
   this.slidePanelWrapperElement = null;
   this.lastSlideItemsPortionDate = new Date();
   this.slideElementPosition = 0;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  GetUniqueId: function () {
   return "_nb_";
  },
  IsHorizontalNavigation: function () {
   var position = this.GetPositionMode();
   return position == NavigationBarPositionEnum.Top || position == NavigationBarPositionEnum.Bottom;
  },
  IsNeedCreateHyperLink: function () {
   return false;
  },
  GetLoadingElement: function (index) {
   return null;
  },
  CreateItemElementsManager: function () {
   return new NavigationBarItemElementsManager(this);
  },
  GetTemplate: function (index) {
   return this.GetItem(index).tmtpl;
  },
  GetImageSrc: function (index) {
   var thumbnailImageSrc = this.GetItem(index).ts;
   if(thumbnailImageSrc)
    return thumbnailImageSrc;
   return this.GetItem(index).s;
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   var snapToLeft = this.IsSnapToLeft(index);
   var nextIndex = snapToLeft ? index - 1 : index + 1;
   if(this.GetImageSlider().extremeItemClickMode == ExtremeItemClickModeEnum.Select || !this.IsValidItemIndex(nextIndex))
    nextIndex = index;
   if(!this.IsVisibleItemElement(nextIndex, true))
    this.SlideToItem(nextIndex, snapToLeft, preventAnimation);
   this.SetActiveItemVisually(index, preventAnimation);
  },
  IsVisibleItemElement: function (index, considerSize) {
   var slideWrapperElementSize = this.GetElementSize(this.GetSlidePanelWrapperElement());
   var itemPosition = (this.GetItemElementSize() + this.GetItemSpacing()) * index;
   var itemPositionInSlideWrapper = this.ConvertItemPositionToSlideWrapperPosition(itemPosition);
   if(considerSize)
    return itemPositionInSlideWrapper >= 0 && itemPositionInSlideWrapper + this.GetItemElementSize() <= slideWrapperElementSize;
   return itemPositionInSlideWrapper + this.GetItemElementSize() >= 0 && itemPositionInSlideWrapper <= slideWrapperElementSize;
  },
  IsSnapToLeft: function (index) {
   var slideWrapperElementSize = this.GetElementSize(this.GetSlidePanelWrapperElement());
   var itemPosition = (this.GetItemElementSize() + this.GetItemSpacing()) * index;
   var lastItemSize = this.GetItemElementSize() + (index != this.GetItemCount() - 1 ? this.GetItemSpacing() : 0);
   return this.ConvertItemPositionToSlideWrapperPosition(itemPosition + lastItemSize) < (slideWrapperElementSize / 2);
  },
  ConvertItemPositionToSlideWrapperPosition: function (itemPosition) {
   return this.GetElementTransformPosition(this.GetSlidePanelElement()) + itemPosition;
  },
  SlideToItem: function (index, snapToLeft, preventAnimation) {
   this.UpdateItemElementsAfterDelayIfRequired();
   this.CalculateSlideElementPosition(index, snapToLeft);
   this.PerformSlideAction(preventAnimation);
  },
  CalculateSlideElementPosition: function (index, snapToLeft) {
   var slideWrapperElementSize = this.GetElementSize(this.GetSlidePanelWrapperElement());
   var itemPosition = (this.GetItemElementSize() + this.GetItemSpacing()) * index;
   if(snapToLeft) {
    this.slideElementPosition = -itemPosition;
    var limitPosition = -(this.GetElementSize(this.GetSlidePanelElement()) - this.GetElementSize(this.GetSlidePanelWrapperElement()));
    var next = this.GetElementTransformPosition(this.GetSlidePanelElement()) > this.slideElementPosition;
    if(this.slideElementPosition < limitPosition || next && Math.abs(-limitPosition + this.slideElementPosition) < this.GetItemElementSize())
     this.slideElementPosition = limitPosition;
   }
   else {
    this.slideElementPosition = slideWrapperElementSize - (itemPosition + this.GetItemElementSize());
    var prev = this.GetElementTransformPosition(this.GetSlidePanelElement()) < this.slideElementPosition;
    if(this.slideElementPosition > 0 || prev && this.slideElementPosition > -this.GetItemElementSize())
     this.slideElementPosition = 0;
   }
  },
  PerformSlideAction: function (preventAnimation) {
   this.UpdateNavigationButtonsState(); 
   if(preventAnimation) {
    this.SetElementTransformPosition(this.GetSlidePanelElement(), this.slideElementPosition);
    this.PerformSlideActionComplete();
   }
   else {
    ASPx.AnimationHelper.slideTo(this.GetSlidePanelElement(), {
     to: this.slideElementPosition, callBack: function () { this.UpdateItemElementsIfRequired(); }.aspxBind(this),
     duration: this.IsSinglePagingMode() ? 300 : ASPx.AnimationConstants.Durations.Default,
     direction: this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION,
     onComplete: function() { this.PerformSlideActionComplete(); }.aspxBind(this)
    });
   }
  },
  PerformSlideActionComplete: function() {
  },
  SetActiveItemVisually: function (index, preventAnimation) {
  },
  GetNavigationBtnsVisibilityMode: function () {
   return this.GetImageSlider().thumbNavBtnsVbl;
  },
  GetButtonsContainer: function () {
   return this.GetNavigationBarElement();
  },
  GetPrevButtonHtml: function () {
   return this.GetImageSlider().nbpbh;
  },
  GetNextButtonHtml: function () {
   return this.GetImageSlider().nbnbh;
  },
  UpdateNavigationButtonsState: function () {
   if(this.navigationButtons) {
    var oldButtonsVisibility = this.navigationButtons.GetVisibilityButtons();
    if(this.IsWrapperOverlapsItemCollection())
     this.SetVisibilityButtons(false);
    else {
     this.SetVisibilityButtons(true);
     var minOffset = -(this.GetElementSize(this.GetSlidePanelElement(), false) - this.GetElementSize(this.GetSlidePanelWrapperElement(), true)), maxOffset = 0;
     this.SetEnablePrevButton(this.slideElementPosition != maxOffset);
     this.SetEnableNextButton(this.slideElementPosition != minOffset);
    }
    return oldButtonsVisibility != this.navigationButtons.GetVisibilityButtons();
   }
   return false;
  },
  PerformBackward: function () {
   if(this.IsSinglePagingMode())
    this.SlideItemsPortionSingleMode(true);
   else
    this.SlideItemsPortionPageMode(true);
  },
  PerformForward: function () {
   if(this.IsSinglePagingMode())
    this.SlideItemsPortionSingleMode(false);
   else
    this.SlideItemsPortionPageMode(false);
  },
  PerformRollBack: function () {
   var position = this.GetElementTransformPosition(this.GetSlidePanelElement());
   var slidePanelElementSize = this.GetElementSize(this.GetSlidePanelElement());
   var slidePanelWrapperElementSize = this.GetElementSize(this.GetSlidePanelWrapperElement());
   var minPosition = slidePanelWrapperElementSize - slidePanelElementSize;
   if(this.IsWrapperOverlapsItemCollection())
    this.slideElementPosition = (slidePanelWrapperElementSize - slidePanelElementSize) / 2;
   else if(position > 0)
    this.slideElementPosition = 0;
   else if(position < minPosition)
    this.slideElementPosition = minPosition;
   this.PerformSlideAction();
  },
  SlideItemsPortionPageMode: function (backward) {
   var index = backward ? 0 : this.GetItemCount() - 1;
   var lastIndex = backward ? this.GetItemCount() - 1 : 0;
   var previousInvisibleIndex = index;
   while(index != lastIndex) {
    if(this.IsVisibleItemElement(index, true)) {
     this.SlideToItem(previousInvisibleIndex, !backward);
     break;
    }
    previousInvisibleIndex = index;
    index += backward ? 1 : -1;
   }
  },
  SlideItemsPortionSingleMode: function (backward) {
   var index = backward ? 0 : this.GetItemCount() - 1;
   var lastIndex = backward ? this.GetItemCount() - 1 : 0;
   var previousInvisibleIndex = index;
   var considerSize = new Date() - this.lastSlideItemsPortionDate < 350 ? false : true;
   while(index != lastIndex) {
    if(this.IsVisibleItemElement(index, considerSize)) {
     this.SlideToItem(previousInvisibleIndex, backward);
     break;
    }
    previousInvisibleIndex = index;
    index += backward ? 1 : -1;
   }
   this.lastSlideItemsPortionDate = new Date();
  },
  CreateControlHierarchyInternal: function () {
   ItemsOwnerBase.prototype.CreateControlHierarchyInternal.call(this);
   var mainElement = this.GetMainElement();
   this.navigationBarElement = this.CreateDiv();
   this.slidePanelWrapperElement = this.CreateDiv();
   var positionMode = this.GetPositionMode();
   var passePartour = this.GetImageSlider().GetPassePartoutElement();
   if((positionMode == NavigationBarPositionEnum.Top || positionMode == NavigationBarPositionEnum.Left) && passePartour)
    mainElement.insertBefore(this.navigationBarElement, passePartour);
   else
    mainElement.appendChild(this.navigationBarElement);
   this.slidePanelElement = this.CreateDiv();
   this.slidePanelWrapperElement.appendChild(this.slidePanelElement);
   this.navigationBarElement.appendChild(this.slidePanelWrapperElement);
  },
  GetItemsContainer: function () {
   return this.GetSlidePanelElement();
  },
  PrepareControlHierarchy: function () {
   ItemsOwnerBase.prototype.PrepareControlHierarchy.call(this);
   this.PrepareNavigationBarElement();
   this.PrepareSlidePanelElement();
  },
  PrepareNavigationBarElement: function () {
   var navigationBarElement = this.GetNavigationBarElement();
   ASPx.SetStyles(navigationBarElement, {
    className: this.GetImageSlider().navBarCssCl,
    cssText: this.GetImageSlider().navBarStyle
   });
  },
  PrepareSlidePanelElement: function () {
   var slideElement = this.GetSlidePanelElement();
   slideElement.className = CssClassesConstants.NavigationBarSlidePanelCssClassName;
   this.GetSlidePanelWrapperElement().className = CssClassesConstants.NavigationBarSlidePanelWrapperCssClassName;
   this.PatchElementForMSTouch(slideElement);
  },
  AdjustControlInternal: function () {
   ItemsOwnerBase.prototype.AdjustControlInternal.call(this);
   this.AdjustNavigationBarElement();
   this.AdjustSlidePanelElement();
   this.UpdateItemElementsIfRequired();
   if(this.UpdateNavigationButtonsState())
    this.AdjustNavigationBarElement();
  },
  AdjustItemElements: function () {
   if(!this.IsAdjustedSize()) {
    ItemsOwnerBase.prototype.AdjustItemElements.call(this);
    var horizontal = this.IsHorizontalNavigation();
    var width = horizontal ? this.GetItemCount() * this.GetItemWidthWithSpacing() - this.GetItemSpacing() : this.GetItemElementWidth();
    var height = horizontal ? this.GetItemElementHeight() : this.GetItemCount() * this.GetItemHeightWithSpacing() - this.GetItemSpacing();
    ASPx.SetStyles(this.GetSlidePanelElement(), { width: width, height: height });
   }
  },
  AdjustNavigationBarElement: function () {
   var styles = this.GetNavigationBarElementsStyles();
   ASPx.SetStyles(this.GetNavigationBarElement(), styles.navBarStyle);
   ASPx.SetStyles(this.GetSlidePanelWrapperElement(), styles.wrapperStyle);
  },
  GetNavigationBarElementsStyles: function () {
   var isHorizontal = this.IsHorizontalNavigation();
   var styles = {};
   if(this.CanUseVisibleItemCount())
    styles = {
     width: isHorizontal ? this.GetItemWidthWithSpacing() * this.GetVisibleItemCount() - this.GetItemSpacing() : this.GetItemElementWidth(),
     height: isHorizontal ? this.GetItemElementHeight() : this.GetItemHeightWithSpacing() * this.GetVisibleItemCount() - this.GetItemSpacing()
    };
   else {
    var navigationBar = this.GetNavigationBarElement();
    var mainElementWidth = SizeUtils.GetClientWidth(this.GetMainElement(), true);
    var mainElementHeight = SizeUtils.GetClientHeight(this.GetMainElement(), true);
    styles = {
     width: this.IsHorizontalNavigation() ? mainElementWidth : this.GetItemElementWidth(),
     height: this.IsHorizontalNavigation() ? this.GetItemElementHeight() : mainElementHeight
    };
    ASPx.SetStyles(navigationBar, styles);
    styles.width = this.IsHorizontalNavigation() ? mainElementWidth - (navigationBar.offsetWidth - mainElementWidth) : this.GetItemElementWidth();
    styles.height = this.IsHorizontalNavigation() ? this.GetItemElementHeight() : mainElementHeight - (navigationBar.offsetHeight - mainElementHeight);
   }
   return {
    navBarStyle: {
     width: styles.width,
     height: styles.height
    },
    wrapperStyle: {
     width: styles.width,
     height: styles.height
    }
   };
  },
  CanUseVisibleItemCount: function () {
   return !this.GetImageSlider().showImageArea && this.GetVisibleItemCount() > 0;
  },
  AdjustSlidePanelElement: function () {
   this.slideElementPosition = this.GetPostDataOffset();
   if(this.IsWrapperOverlapsItemCollection())
    this.slideElementPosition = (this.GetElementSize(this.GetSlidePanelWrapperElement()) - this.GetElementSize(this.GetSlidePanelElement())) / 2;
   else if(this.slideElementPosition > 0 && !this.IsRtl())
    this.slideElementPosition = 0;
   this.SetElementTransformPosition(this.GetSlidePanelElement(), this.slideElementPosition);
  },
  IsWrapperOverlapsItemCollection: function() {
   return this.GetElementSize(this.GetSlidePanelWrapperElement()) > this.GetElementSize(this.GetSlidePanelElement());
  },
  GetPostDataOffset: function () {
   var offset = this.IsAdjustedSize() ? 0 : this.GetImageSlider().navBarOffset;
   if(offset == 0 && this.IsRtl())
    offset = this.GetElementSize(this.GetSlidePanelWrapperElement()) - this.GetElementSize(this.GetSlidePanelElement());
   return offset;
  },
  PrepareItemElement: function (index) {
   ItemsOwnerBase.prototype.PrepareItemElement.call(this, index);
   this.GetItemElement(index).itemIndex = index;
  },
  AdjustItemElement: function (index) {
   ItemsOwnerBase.prototype.AdjustItemElement.call(this, index);
   ASPx.SetStyles(this.GetItemElement(index), this.IsHorizontalNavigation() ? { left: this.GetItemWidthWithSpacing() * index } : { top: this.GetItemHeightWithSpacing() * index });
  },
  CalculateSize: function () {
   if(!this.IsAdjustedSize())
    ItemsOwnerBase.prototype.CalculateSize.call(this);
  },
  CalculateItemElementSize: function (fakeElement) {
   this.GetNavigationBarElement().appendChild(fakeElement);
   this.fullItemWidth = SizeUtils.GetClientWidth(fakeElement);
   this.fullItemHeight = SizeUtils.GetClientHeight(fakeElement);
   this.clearItemWidth = SizeUtils.GetClientWidth(fakeElement, true);
   this.clearItemHeight = SizeUtils.GetClientHeight(fakeElement, true);
  },
  ResetControlStyle: function () {
   ASPx.SetStyles(this.GetNavigationBarElement(), { width: 0, height: 0 });
  },
  GetShownItemIndexes: function(getUncroppedItems) { return []; },
  CanCreateSwipeGestureHandler: function () {
   return true;
  },
  CanHandleSwipeGesture: function(evt) {
   return !this.IsWrapperOverlapsItemCollection() && ItemsOwnerBase.prototype.CanHandleSwipeGesture.call(this, evt);
  },
  InitializeHandlers: function () {
   ItemsOwnerBase.prototype.InitializeHandlers.call(this);
   ASPx.Evt.AttachEventToElement(this.GetSlidePanelElement(), this.GetMouseUpEventName(), function (evt) { this.OnNavigationBarMouseUp(evt); }.aspxBind(this)); 
  },
  OnNavigationBarMouseUp: function (evt) {
   if(this.CanCandleMouseUpEvent(evt)) {
    var index = this.GetItemIndexFromEvent(evt);
    if(index != -1) {
     this.GetImageSlider().SetActiveItemIndexInternal(index);
     this.StopPlayingWhenPaging();
     this.GetImageSlider().RaiseThumbnailItemClick();
    }
   }
  },
  GetMouseUpEventName: function () {
   return ASPx.TouchUIHelper.touchMouseUpEventName;
  },
  CanCandleMouseUpEvent: function (evt) {
   return !this.IsExecutedGesture() && ASPx.Evt.IsLeftButtonPressed(evt);
  },
  GetItemIndexFromEvent: function (evt) {
   var itemElement = ASPx.GetParentByClassName(ASPx.Evt.GetEventSource(evt),this.GetItemElementCssClass());
   return itemElement ? itemElement.itemIndex : -1;
  },
  GetImageSizeMode: function () {
   return this.GetImageSlider().thumbImageSizeMode;
  },
  GetMainElement: function () {
   return this.GetImageSlider().GetMainElement();
  },
  GetSlidePanelWrapperElement: function () {
   return this.slidePanelWrapperElement;
  },
  GetNavigationBarElement: function () {
   return this.navigationBarElement;
  },
  GetElementSize: function (element, clear) {
   return this.IsHorizontalNavigation() ? SizeUtils.GetClientWidth(element, clear) : SizeUtils.GetClientHeight(element, clear);
  },
  GetItemWidthWithSpacing: function () {
   return this.GetItemElementWidth() + this.GetItemSpacing();
  },
  GetItemHeightWithSpacing: function () {
   return this.GetItemElementHeight() + this.GetItemSpacing();
  },
  GetPositionMode: function () {
   return this.GetImageSlider().GetNavigationBarPosition();
  },
  GetItemSpacing: function () {
   return this.GetImageSlider().itemSpacing;
  },
  IsSinglePagingMode: function () {
   return this.GetImageSlider().navBarPagingMode == NavigationBarPagingModeEnum.Single;
  },
  GetVisibleItemCount: function () {
   return this.GetImageSlider().visibleItemsCount;
  },
  GetSlideElementPosition: function () {
   return Math.round(this.slideElementPosition);
  },
  GetWidth: function () {
   var navigationBarElement = this.GetNavigationBarElement();
   var currentStyle = ASPx.GetCurrentStyle(navigationBarElement);
   var width = SizeUtils.GetClientWidth(navigationBarElement) + ASPx.PxToInt(currentStyle.marginLeft) + ASPx.PxToInt(currentStyle.marginRight);
   return width > 0 ? width : 0;
  },
  GetHeight: function () {
   var navigationBarElement = this.GetNavigationBarElement();
   var currentStyle = ASPx.GetCurrentStyle(navigationBarElement);
   var height = SizeUtils.GetClientHeight(navigationBarElement) + ASPx.PxToInt(currentStyle.marginTop) + ASPx.PxToInt(currentStyle.marginBottom);
   return height > 0 ? height : 0;
  }
 });
 var NavigationBarThumbnailStrategy = ASPx.CreateClass(NavigationBarStrategy, {
  constructor: function (imageSlider) {
   this.selectedStateElement = null;
   this.hoverStateElementSize = {};
   this.innerHoverStateElementSize = {};
   this.loadingElenentSize = {};
   this.setActiveIndexCounter = 0;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  BeginSetActiveIndex: function () {
   this.setActiveIndexCounter++;
  },
  EndSetActiveIndex: function () {
   this.setActiveIndexCounter--;
  },
  NeedOffsetCorrection: function () {
   return this.setActiveIndexCounter > 0 && this.GetImageSlider().extremeItemClickMode == ExtremeItemClickModeEnum.SelectAndSlide;
  },
  GetNavigationButtonsPosition: function () {
   return this.GetImageSlider().thumbNavBtnsPos;
  },
  GetItemIndexFromEvent: function(evt) {
   var result = NavigationBarStrategy.prototype.GetItemIndexFromEvent.call(this, evt);
   if(result == -1) {
    var eventSource = ASPx.Evt.GetEventSource(evt);
    var selectedItem = this.GetSelectedStateElement();
    if (eventSource.parentNode == selectedItem || eventSource == selectedItem)
     result = this.GetRtlIndex(this.GetImageSlider().GetActiveItemIndex());
   }
   return result;
  },
  SetActiveItemIndexInternal: function (index, preventAnimation) {
   this.BeginSetActiveIndex();
   NavigationBarStrategy.prototype.SetActiveItemIndexInternal.call(this, index, preventAnimation);
   this.EndSetActiveIndex();
  },
  SetActiveItemVisually: function (index, preventAnimation) {
   this.SelectItemElement(index);
   this.MoveSelectedItem(index, preventAnimation);
  },
  SelectItemElement: function (index) {
   var currentItemElement = this.GetItemElement(index);
   var prevItemElement = this.GetItemElement(this.GetPrevItemIndex());
   if(prevItemElement)
    prevItemElement.className = prevItemElement.className.replace(CssClassesConstants.NavigationBarSelectedStateCssClassName, "");
   if(currentItemElement && !ASPx.ElementContainsCssClass(currentItemElement, CssClassesConstants.NavigationBarSelectedStateCssClassName))
    currentItemElement.className += CssClassesConstants.NavigationBarSelectedStateCssClassName;
  },
  MoveSelectedItem: function (index, preventAnimation) {
   var selectedStateElement = this.GetSelectedStateElement();
   var position = (this.GetItemElementSize() + this.GetItemSpacing()) * index;
   preventAnimation = this.GetImageSlider().disableSelectedStateAnimation || preventAnimation; 
   if(preventAnimation)
    this.SetElementTransformPosition(selectedStateElement, position);
   else
    ASPx.AnimationHelper.slideTo(selectedStateElement, {
     to: position,
     direction: this.IsHorizontalNavigation() ? ASPx.AnimationHelper.SLIDE_HORIZONTAL_DIRECTION : ASPx.AnimationHelper.SLIDE_VERTICAL_DIRECTION
    });
  },
  PerformSlideActionComplete: function() {
   this.EnsureShownItemsLoaded();
  },
  SlideItemsPortionPageMode: function (backward) {
   this.PerformSlideToExtremeInvisibleElement(backward, true, !backward);
  },
  PerformRollBack: function () {
   NavigationBarStrategy.prototype.PerformRollBack.call(this);
  },
  UpdateItemElementsIfRequired: function () {
   NavigationBarStrategy.prototype.UpdateItemElementsIfRequired.call(this);
   if(this.GetImageLoadMode() != LoadModeEnum.AllImages)
    this.SelectItemElement(this.GetActiveItemIndex());
  },
  CanCreateNavigationButtons: function () {
   if(!this.CanUseVisibleItemCount())
    return true;
   return this.GetVisibleItemCount() < this.GetItemCount();
  },
  CreateNavigationButtons: function () {
   if(this.GetNavigationBtnsVisibilityMode() == ElementVisibilityModeEnum.None)
    return null;
   if(this.GetNavigationButtonsPosition() == NavigationBarButtonPositionEnum.Outside)
    return new OutsideNavigationButtons(this);
   return new NavigationButtons(this);
  },
  CreateControlHierarchy: function () {
   NavigationBarStrategy.prototype.CreateControlHierarchy.call(this);
   this.CreateSelectedStateElement();
  },
  CreateTemplate: function(index) {
   ItemsOwnerBase.prototype.CreateTemplate.call(this, index);
   var template = this.GetTemplate(index);
   if(template)
    this.HideLoadingElement(index);
  },
  CreateItemElement: function (index) {
   var itemElement = NavigationBarStrategy.prototype.CreateItemElement.call(this, index);
   itemElement.appendChild(this.CreateLoadingElement());
   if(this.IsEnabled() && !ASPx.Browser.TouchUI)
    itemElement.appendChild(this.CreateHoverStateElement());
   return itemElement;
  },
  CreateLoadingElement: function(itemElement) {
   var element = this.CreateDiv();
   element.className = CssClassesConstants.LoadingElement;
   return element;
  },
  CreateHoverStateElement: function (itemElement) {
   var element = this.CreateDiv();
   element.className = CssClassesConstants.NavigationBarHoverStateElementCssClassName;
   element.appendChild(this.CreateDiv());
   return element;
  },
  CreateSelectedStateElement: function () {
   this.selectedStateElement = this.CreateDiv();
   this.selectedStateElement.appendChild(this.CreateDiv()); 
   this.GetSlidePanelElement().appendChild(this.selectedStateElement);
  },
  PrepareControlHierarchy: function () {
   NavigationBarStrategy.prototype.PrepareControlHierarchy.call(this);
   ASPx.SetStyles(this.GetSelectedStateElement(), {
    className: this.GetImageSlider().thSelCssCl,
    cssText: this.GetImageSlider().thSelStyle
   });
  },
  PrepareItemElement: function (index) {
   NavigationBarStrategy.prototype.PrepareItemElement.call(this, index);
   var stateController = this.GetStateController();
   if(this.IsEnabled() && !ASPx.Browser.TouchUI && stateController && this.GetEnableItemHoverState()) {
    var itemElement = this.GetItemElement(index);
    itemElement.id = this.GetClientControlName() + "_nb_" + index;
    stateController.AddHoverItem(itemElement.id, [CssClassesConstants.NavigationBarHoverStateCssClassName], [""], [""], null, null, false);
   }
  },
  GetEnableItemHoverState: function () {
   return true;
  },
  CalculateItemElementSize: function (fakeElement) {
   NavigationBarStrategy.prototype.CalculateItemElementSize.call(this, fakeElement);
   if(this.IsEnabled() && !ASPx.Browser.TouchUI)
    this.CalculateHoverStateElement(fakeElement);
   this.CalculateLoadingElement(fakeElement);
  },
  CalculateHoverStateElement: function (fakeElement) { 
   var hoverStateElement = this.CreateHoverStateElement();
   fakeElement.appendChild(hoverStateElement);
   ASPx.SetStyles(hoverStateElement, { display: "block" });
   this.hoverStateElementSize = this.GetBorderBoxSize(hoverStateElement, this.GetItemElementWidth(), this.GetItemElementHeight());
   var innerDiv = this.GetFirstChild(hoverStateElement);
   this.innerHoverStateElementSize = this.GetBorderBoxSize(innerDiv, this.hoverStateElementSize.width, this.hoverStateElementSize.height);
  },
  CalculateLoadingElement: function(fakeElement) {
   var loadingElement = this.CreateLoadingElement();
   fakeElement.appendChild(loadingElement);
   this.loadingElenentSize.width = loadingElement.offsetWidth;
   this.loadingElenentSize.height = loadingElement.offsetHeight;
  },
  AdjustControlInternal: function () {
   NavigationBarStrategy.prototype.AdjustControlInternal.call(this);
   this.AdjustSelectedStateElement();
  },
  AdjustItemElement: function (index) {
   NavigationBarStrategy.prototype.AdjustItemElement.call(this, index);
   if(this.IsEnabled() && !ASPx.Browser.TouchUI)
    this.AdjustHoverStateElement(index);
   this.AdjustLoadingElement(index);
  },
  AdjustLoadingElement: function(index) {
   var loadingElement = this.GetLoadingElement(index);
   loadingElement.style.left = (this.GetItemElementWidth() - this.loadingElenentSize.width) / 2 + "px";
   loadingElement.style.top = (this.GetItemElementHeight() - this.loadingElenentSize.height) / 2 + "px";
  },
  AdjustHoverStateElement: function (index) {
   var hoverStateElement = this.GetHoverStateElement(index);
   ASPx.SetStyles(hoverStateElement, this.hoverStateElementSize);
   ASPx.SetStyles(this.GetFirstChild(hoverStateElement), this.innerHoverStateElementSize);
  },
  AdjustSelectedStateElement: function () {
   var selectedStateElement = this.GetSelectedStateElement();
   var size = this.GetBorderBoxSize(selectedStateElement, this.GetItemElementWidth(), this.GetItemElementHeight());
   ASPx.SetStyles(selectedStateElement, size);
   var innerDiv = this.GetFirstChild(selectedStateElement);
   size = this.GetBorderBoxSize(selectedStateElement, size.width, size.height);
   ASPx.SetStyles(innerDiv, size);
  },
  GetHoverStateElement: function (index) {
   return ASPx.GetChildByClassName(this.GetItemElement(index), CssClassesConstants.NavigationBarHoverStateElementCssClassName);
  },
  GetLoadingElement: function (index) {
   return ASPx.GetChildByClassName(this.GetItemElement(index), CssClassesConstants.LoadingElement);
  },
  HideLoadingElement: function(index) {
   var element = this.GetLoadingElement(index);
   if(element)
    element.style.display = "none";
  },
  GetSelectedStateElement: function () {
   return this.selectedStateElement;
  },
  GetItemElementCssClass: function () {
   return this.GetImageSlider().thCssCl;
  },
  GetItemElementStyle: function () {
   return this.GetImageSlider().thStyle;
  },
  CalculateSlideElementPosition: function (index, snapToLeft) {
   var prevSlideElementPosition = this.slideElementPosition;
   NavigationBarStrategy.prototype.CalculateSlideElementPosition.call(this, index, snapToLeft);
   this.slideElementPosition = this.CorrectSelectAndSlideOffsetPosition(index, prevSlideElementPosition, this.slideElementPosition);
  },
  IsSnapToLeft: function (index) {
   var shownItemIndexes = this.GetShownItemIndexes(true);
   for(var i = 0; i < shownItemIndexes.length; i++)
    if(shownItemIndexes[i] == index)
     return i < shownItemIndexes.length / 2;
   return index < shownItemIndexes[0];
  },
  SlideItemsPortionSingleMode: function (backward) {
   var considerSize = new Date() - this.lastSlideItemsPortionDate >= 350;
   this.PerformSlideToExtremeInvisibleElement(backward, considerSize, backward);
   this.lastSlideItemsPortionDate = new Date();
  },
  PerformSlideToExtremeInvisibleElement: function (backward, considerSize, preventAnimation) {
   var shownItemIndexes = this.GetShownItemIndexes(false);
   var lastIndex = backward ? -1 : this.GetItemCount();
   var incValue = backward ? -1 : 1;
   for(var index = shownItemIndexes[backward ? 0 : shownItemIndexes.length - 1]; index != lastIndex; index += incValue)
    if(!this.IsVisibleItemElement(index, considerSize)) {
     this.SlideToItem(index, preventAnimation);
     break;
    }
  },
  GetShownItemIndexes: function (getUncroppedItems) {
   var result = [];
   var itemSize = this.GetItemElementSize();
   var constOffset = this.GetElementTransformPosition(this.GetSlidePanelElement());
   var itemFullSize = itemSize + this.GetItemSpacing();
   var minValue = getUncroppedItems ? -1 : -itemSize;
   var maxValue = getUncroppedItems ? this.GetSlidePanelWrapperSize() - itemSize + 1 : this.GetSlidePanelWrapperSize();
   var tempValue = null;
   for(var index = 0; index < this.GetItemCount() ; index++) {
    tempValue = constOffset + itemFullSize * index;
    if(tempValue > minValue && tempValue < maxValue)
     result.push(index);
   }
   return result;
  },
  OnImageLoad: function (image) {
   NavigationBarStrategy.prototype.OnImageLoad.call(this, image);
   this.HideLoadingElement(image.dxIndex);
  },
  CorrectSelectAndSlideOffsetPosition: function (nextItemIndex, prevPos, nextPos) {
   var index = this.GetActiveItemIndex();
   if(!this.NeedOffsetCorrection() || nextItemIndex == index)
    return nextPos;
   var itemElementSize = this.GetItemElementSize();
   var sliderWrapperSize = this.GetSlidePanelWrapperSize();
   if(sliderWrapperSize < (itemElementSize * 3)) {
    var offsetDelta = Math.abs(Math.abs(nextPos) - Math.abs(prevPos));
    var itemSpacing = this.GetItemSpacing();
    var itemPosition = (itemElementSize + itemSpacing) * index;
    var itemPositionInSlideWrapper = this.ConvertItemPositionToSlideWrapperPosition(itemPosition) +
     (nextItemIndex < index ? offsetDelta : -offsetDelta);
    nextPos += (sliderWrapperSize - itemElementSize) / 2 - itemPositionInSlideWrapper;
   }
   return nextPos;
  },
  GetBorderBoxSize: function (element, width, height) {
   ASPx.SetStyles(element, { width: width, height: height });
   if(element.offsetWidth > width)
    width -= element.offsetWidth - width;
   if(element.offsetHeight > height)
    height -= element.offsetHeight - height;
   return { width: width, height: height };
  },
  GetFirstChild: function (parent) {
   return parent.children[0];
  },
  GetSlidePanelWrapperSize: function () {
   return this.GetElementSize(this.GetSlidePanelWrapperElement());
  },
  GetNavigationBarElementsStyles: function () {
   var styles = NavigationBarStrategy.prototype.GetNavigationBarElementsStyles.call(this);
   if(this.GetNavigationButtonsPosition() == NavigationBarButtonPositionEnum.Outside && this.navigationButtons) {
    var prevButtonSize = this.navigationButtons.GetPrevButtonWrapperSize();
    var nextButtonSize = this.navigationButtons.GetNextButtonWrapperSize();
    var isHorizontal = this.IsHorizontalNavigation();
    var styleName = isHorizontal ? "width" : "height";
    if(this.CanUseVisibleItemCount())
     styles.navBarStyle[styleName] += prevButtonSize[styleName] + nextButtonSize[styleName];
    else
     styles.wrapperStyle[styleName] -= prevButtonSize[styleName] + nextButtonSize[styleName];
    styles.wrapperStyle[isHorizontal ? "left" : "top"] = prevButtonSize[styleName];
   }
   return styles;
  }
 });
 var NavigationBarDotsStrategy = ASPx.CreateClass(NavigationBarStrategy, {
  constructor: function (imageSlider) {
   this.cloneElement = null;
   this.constructor.prototype.constructor.call(this, imageSlider);
  },
  Initialize: function () {
   NavigationBarStrategy.prototype.Initialize.call(this);
   this.cloneElement = ASPx.CreateHtmlElementFromString(this.GetImageSlider().dbh);
  },
  SetActiveItemVisually: function (index, preventAnimation) {
   var stateController = this.GetStateController();
   if(stateController) {
    if(this.GetPrevItemIndex() != -1)
     stateController.DeselectElementBySrcElement(this.GetItemElement(this.GetPrevItemIndex()));
    stateController.SelectElementBySrcElement(this.GetItemElement(index));
   }
  },
  GetImageLoadMode: function () {
   return LoadModeEnum.AllImages;
  },
  OnNavigationBarMouseUp: function (evt) {
   ASPx.ClearHoverState();
   NavigationBarStrategy.prototype.OnNavigationBarMouseUp.call(this, evt);
  },
  GetMouseUpEventName: function () {
   return ASPx.TouchUIHelper.touchMouseUpEventName; 
  },
  GetNavigationBtnsVisibilityMode: function () {
   return ElementVisibilityModeEnum.None;
  },
  CreateItemElement: function (index) {
   var itemElement = this.CreateDiv();
   itemElement.id = this.GetItemElementId(index);
   return itemElement;
  },
  PrepareControlHierarchy: function () {
   NavigationBarStrategy.prototype.PrepareControlHierarchy.call(this);
   var imageSlider = this.GetImageSlider();
   var stateController = this.GetStateController();
   if(!stateController)
    return;
   this.ForEachItem(function (i) {
    if(this.IsEnabled()) {
     stateController.AddHoverItem(this.GetItemElementId(i), [imageSlider.dotHCssCl], [imageSlider.dotHStyle],
      null, [imageSlider.dotHSprt], [""], false);
     stateController.AddPressedItem(this.GetItemElementId(i), [imageSlider.dotPCssCl], [imageSlider.dotPStyle],
      null, [imageSlider.dotPSprt], [""], false);
    }
    stateController.AddSelectedItem(this.GetItemElementId(i), [imageSlider.dotSCssCl], [imageSlider.dotSStyle],
     null, [imageSlider.dotSSprt], [""], false);
   });
  },
  AdjustImageElement: function (index) {
  },
  GetItemElementCssClass: function () {
   return this.cloneElement.className;
  },
  GetItemElementStyle: function () {
   return this.cloneElement.style.cssText;
  },
  GetItemElementId: function (index) {
   return this.GetClientControlName() + "_dot_" + index;
  }
 });
 var ItemElementsManagerBase = ASPx.CreateClass(null, {
  constructor: function (itemsOwner) {
   this.itemsOwner = itemsOwner;
   this.timerId = -1;
   this.itemCollection = [];
  },
  GetOwner: function () {
   return this.itemsOwner;
  },
  GetCollection: function () {
   if(this.IsEnablePartialLoading())
    return this.itemCollection;
   return ASPx.GetChildNodesByTagName(this.GetOwner().GetItemsContainer(), "DIV");
  },
  HasItem: function (index) {
   return !!this.GetCollection()[index];
  },
  SaveItem: function (index, item) {
   if(this.IsEnablePartialLoading())
    this.itemCollection[index] = item;
  },
  GetImageLoadMode: function () {
   return this.GetOwner().GetImageLoadMode();
  },
  IsEnablePartialLoading: function () {
   return this.GetImageLoadMode() != LoadModeEnum.AllImages;
  },
  CreateItemsIfRequired: function () {
   if(this.GetImageLoadMode() == LoadModeEnum.AllImages)
    this.GetOwner().CreateItemElements();
  },
  PrepareItemsIfRequired: function () {
   if(this.GetImageLoadMode() == LoadModeEnum.AllImages)
    this.GetOwner().PrepareItemElements();
  },
  AdjustItemsIfRequired: function () {
   var owner = this.GetOwner();
   for(var i = 0; i < owner.GetItemCount() ; i++) {
    if(this.IsEnablePartialLoading() && !this.HasItem(i))
     continue;
    this.GetOwner().AdjustItemElement(i);
    this.GetOwner().AdjustImageElement(i);
   }
  },
  UpdateHierarchyIfRequired: function () {
   if(this.IsEnablePartialLoading()) {
    this.timerId = ASPx.Timer.ClearTimer(this.timerId);
    this.UpdateHierarchyCore();
   }
  },
  CreateItemAndAppend: function (index, parent) {
   var owner = this.GetOwner();
   var element = owner.CreateItemElement(index);
   this.SaveItem(index, element);
   parent.appendChild(element);
   owner.PrepareItemElement(index);
   owner.AdjustItemElement(index);
   owner.AdjustImageElement(index);
   if(owner.GetImageSlider().HasTemplates())
    owner.CreateTemplate(index);
  },
  RemoveItem: function (index) {
   if(this.GetImageLoadMode() == LoadModeEnum.DynamicLoadAndCache)
    return;
   var owner = this.GetOwner();
   var element = owner.GetItemElement(index);
   if(element) {
    var image = owner.GetImageElement(index);
    if(image)
     owner.DetachLoadEvents(image);
    this.itemCollection[index] = undefined;
    ASPx.RemoveElement(element);
   }
  },
  UpdateHierarchyCore: function () {
  },
  GetDelay: function () {
   return 450;
  },
  UpdateHierarchyAfterDelayIfRequired: function () {
   if(this.IsEnablePartialLoading() && this.timerId == -1)
    this.timerId = window.setTimeout(function () { this.UpdateHierarchyIfRequired(); }.aspxBind(this), this.GetDelay());
  }
 });
 var ImageAreaItemElementsManager = ASPx.CreateClass(ItemElementsManagerBase, {
  constructor: function (imageAreaStrategy) {
   this.constructor.prototype.constructor.call(this, imageAreaStrategy);
  },
  GetDelay: function () {
   return this.GetOwner().GetImageSlider().animationDuration + 50;
  },
  UpdateHierarchyCore: function () {
   var owner = this.GetOwner();
   var activeItemIndex = owner.GetActiveItemIndex();
   var prevItemIndex = owner.GetPrevItemIndex();
   if(prevItemIndex == -1) 
    prevItemIndex = 0;
   var isForwardDirection = (activeItemIndex - prevItemIndex) >= 0;
   var fragment = owner.CreateDocumentFragment();
   var itemsContainer = owner.GetItemsContainer();
   if(!this.HasItem(activeItemIndex))
    this.CreateItemAndAppend(activeItemIndex, fragment || itemsContainer);
   if(this.CanUpdateItemElements(isForwardDirection, isForwardDirection ? activeItemIndex + 1 : activeItemIndex - 1)) {
    for(var i = 0; i < owner.GetItemCount() ; i++) {
     if(this.CanRemoveItem(i, activeItemIndex, prevItemIndex, isForwardDirection))
      this.RemoveItem(i);
     else if(!this.HasItem(i))
      this.CreateItemAndAppend(i, fragment || itemsContainer);
    }
   }
   if(fragment)
    itemsContainer.appendChild(fragment);
  },
  CanRemoveItem: function (index, activeItemIndex, prevItemIndex, forwardDirection) {
   var visibleItemCount = 6;
   var result = forwardDirection ? (index < activeItemIndex || index > (activeItemIndex + visibleItemCount)) :
     (index > activeItemIndex || index < (activeItemIndex - visibleItemCount));
   return result && prevItemIndex != index; 
  },
  CanUpdateItemElements: function (forwardDirection, followingItemIndex) {
   return forwardDirection ? followingItemIndex < this.GetOwner().GetItemCount() && !this.HasItem(followingItemIndex) :
    followingItemIndex > 0 && !this.HasItem(followingItemIndex);
  }
 });
 var LoopImageAreaItemElementsManager = ASPx.CreateClass(ItemElementsManagerBase, {
  constructor: function (imageAreaStrategy) {
   this.constructor.prototype.constructor.call(this, imageAreaStrategy);
  },
  UpdateHierarchyCore: function () {
   var owner = this.GetOwner();
   var activeIndex = owner.GetActiveItemIndex();
   var fragment = owner.CreateDocumentFragment();
   var itemsContainer = owner.GetItemsContainer();
   if(!this.HasItem(activeIndex))
    this.CreateItemAndAppend(activeIndex, fragment || itemsContainer);
   var activeItem = owner.GetItemElement(activeIndex);
   var nextIndex = activeIndex + 1;
   if(nextIndex == owner.GetItemCount())
    nextIndex = 0;
   if(!this.HasItem(nextIndex)) {
    this.CreateItemAndAppend(nextIndex, fragment || itemsContainer);
    var item = owner.GetItemElement(nextIndex);
    item.dxPosition = activeItem.dxPosition + owner.GetItemElementSize();
    owner.SetItemPosition(item);
   }
   var prevIndex = activeIndex - 1;
   var prevIndex = activeIndex - 1;
   if(prevIndex < 0)
    prevIndex = owner.GetItemCount() - 1;
   if(!this.HasItem(prevIndex)) {
    this.CreateItemAndAppend(prevIndex, fragment || itemsContainer);
    var item = owner.GetItemElement(prevIndex);
    item.dxPosition = activeItem.dxPosition - owner.GetItemElementSize();
    owner.SetItemPosition(item);
   }
   for(var i = 0; i < owner.GetItemCount() ; i++)
    if(i != activeIndex && i != prevIndex && i != nextIndex && owner.GetPrevItemIndex() != i && owner.GetItemElement(i))
     this.RemoveItem(i);
   if(fragment)
    itemsContainer.appendChild(fragment);
  }
 });
 var NavigationBarItemElementsManager = ASPx.CreateClass(ItemElementsManagerBase, {
  constructor: function (navigationBarStrategy) {
   this.constructor.prototype.constructor.call(this, navigationBarStrategy);
  },
  CreateDummyItem: function (index, parent) {
   if(!this.HasItem(index))
    this.CreateAndPrepareItemElement(index, parent);
   else if(this.GetImageLoadMode() != LoadModeEnum.DynamicLoadAndCache) {
    var owner = this.GetOwner();
    var element = owner.GetItemElement(index);
    if(element) {
     element.style.backgroundImage = "";
     var image = owner.GetImageElement(index);
     if(image)
      owner.DetachLoadEvents(image);
     ASPx.RemoveElement(image);
     ASPx.RemoveElement(owner.GetCanvasElement(index));
     var el = owner.GetLoadingElement(index);
     if(el) el.style.display = "";
    }
    this.SetDummyFlagToElement(index, true);
   }
  },
  SetDummyFlagToElement: function (index, isDummy) {
   var element = this.GetOwner().GetItemElement(index);
   if(element)
    element.isDummy = isDummy;
  },
  IsElementDummy: function (index) {
   var element = this.GetOwner().GetItemElement(index);
   if(element)
    return !!element.isDummy;
   return false;
  },
  CreateItemAndAppend: function (index, parent) {
   if(!this.HasItem(index))
    this.CreateAndPrepareItemElement(index, parent);
   if(this.IsElementDummy(index)) {
    this.SetDummyFlagToElement(index, false);
    this.GetOwner().UpdateItemElement(index);
   }
  },
  CreateAndPrepareItemElement: function (index, parent) {
   var owner = this.GetOwner();
   var element = owner.CreateItemElement(index);
   this.SaveItem(index, element);
   parent.appendChild(element);
   owner.PrepareItemElement(index);
   owner.AdjustItemElement(index);
   this.SetDummyFlagToElement(index, true);
  },
  UpdateHierarchyCore: function () {
   var owner = this.GetOwner();
   var navigationBarSize = owner.GetElementSize(owner.GetSlidePanelWrapperElement()),
    slidePanelPosition = owner.GetElementTransformPosition(owner.GetSlidePanelElement());
   var fragment = owner.CreateDocumentFragment();
   var itemsContainer = owner.GetItemsContainer();
   var itemFullSize = owner.GetItemElementSize() + owner.GetItemSpacing();
   var lPos = Math.min(-navigationBarSize * 0.3, -itemFullSize);
   var rPos = Math.max(navigationBarSize * 1.3, navigationBarSize + itemFullSize);
   var lDummyPos = lPos - navigationBarSize;
   var rDummyPos = rPos + navigationBarSize;
   var itemPos = 0;
   for(var i = 0; i < owner.GetItemCount() ; i++) {
    itemPos = slidePanelPosition + itemFullSize * i;
    if(itemPos > lDummyPos && itemPos < rDummyPos && (itemPos < lPos || itemPos > rPos))
     this.CreateDummyItem(i, fragment || itemsContainer);
    else {
     if(itemPos <= lDummyPos || itemPos >= rDummyPos)
      this.RemoveItem(i);
     else
      this.CreateItemAndAppend(i, fragment || itemsContainer);
    }
   }
   if(fragment)
    itemsContainer.appendChild(fragment);
  }
 });
 var ASPxClientImageSlider = ASPx.CreateClass(ASPxClientControl, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
   this.activeItemIndex = 0;
   this.imageAreaStrategy = null; 
   this.navigationBarStrategy = null; 
   this.passePartoutElement = null;
   this.hiddenField = null;
   this.pendingItemsTimerID = -1;
   this.slideShowEnabled = false;
   this.templateCreated = false;
   this.timerID = -1;
   this.defaultControlSize = { width: "", height: "" };
   this.showImageArea = true;
   this.showNavBar = true;
   this.seoFriendlyItems = {};
   this.items = {}; 
   this.itemsPerRequest = 0;
   this.enableLoopNavigation = false;
   this.enableKeyboardSupport = true;
   this.enablePagingByClick = true;
   this.enablePagingGestures = true;
   this.extremeItemClickMode = 0;
   this.animationDuration = 400;
   this.allowMouseWheel = false;
   this.imageLoadMode = 1;
   this.imageSizeMode = ASPx.ImageControlUtils.ImageSizeModeEnum.ActualSizeOrFit;
   this.thumbImageSizeMode = ASPx.ImageControlUtils.ImageSizeModeEnum.FitAndCrop;
   this.animationType = 0;
   this.navDirection = 0;
   this.itemSpacing = 5;
   this.target = "";
   this.hasNavigateUrls = false;
   this.hasTemplates = false;
   this.navBtnsVbl = 2;
   this.itemTxtVbl = 3;
   this.interval = 5000;
   this.autoPlay = false;
   this.stopPlayingWhenPaging = false;
   this.stopPlayingWhenPagingExecuted = false;
   this.pausePlayingWhenMouseOver = false;
   this.playPauseBtnVbl = 0;
   this.visibleStartIndex = 0;
   this.visibleItemsCount = 0;
   this.navBarPos = 0;
   this.navBarPagingMode = 0;
   this.thumbNavBtnsVbl = 2;
   this.thumbNavBtnsPos = 0;
   this.navBarOffset = 0;
   this.passePartoutStyle = "";
   this.imgAreaCssCl = "";
   this.imgAreaStyle = "";
   this.itemCssCl = "";
   this.itemStyle = "";
   this.navBarCssCl = "";
   this.navBarStyle = "";
   this.thCssCl = "";
   this.thStyle = "";
   this.thSelCssCl = "";
   this.thSelStyle = "";
   this.itemTxtCssCl = "";
   this.itemTxtStyle = "";
   this.dotHSprt = null;
   this.dotHCssCl = "";
   this.dotHStyle = "";
   this.dotPSprt = null;
   this.dotPCssCl = "";
   this.dotPStyle = "";
   this.dotSSprt = null;
   this.dotSCssCl = "";
   this.dotSStyle = "";
   this.dbh = "";
   this.playBH = "";
   this.pauseBH = "";
   this.pbh = "";
   this.nbh = "";
   this.nbpbh = "";
   this.nbnbh = "";
   this.sizingConfig.adjustControl = true;
   this.disableSelectedStateAnimation = false;
   this.ActiveItemChanged = new ASPxClientEvent();
   this.ItemClick = new ASPxClientEvent();
   this.ThumbnailItemClick = new ASPxClientEvent();
   this.ItemLoadedOnCallback = new ASPxClientEvent();
   this.StrategiesCreated = new ASPxClientEvent();
  },
  InlineInitialize: function () {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   this.PopulateItemsSeoMode();
  },
  Initialize: function () {
   ASPxClientControl.prototype.Initialize.call(this);
   if(this.hasTemplates)
    for(var key in this.seoFriendlyItems) {
     if(!this.seoFriendlyItems.hasOwnProperty(key)) continue;
     if(!this.items[key])
      this.items[key] = {};
     var item = this.items[key],
      seoFriendlyItem = this.seoFriendlyItems[key];
     item.s = seoFriendlyItem.s;
     item.ts = seoFriendlyItem.ts;
     item.t = seoFriendlyItem.t;
     item.u = seoFriendlyItem.u;
    }
   this.seoFriendlyItems = null;
   this.CreateControlHierarchy();
   this.PrepareControlHierarchy();
   this.InitializeElementsSize();
  },
  PopulateItemsSeoMode: function () {
   var elements = ASPx.GetNodesByTagName(this.GetMainElement(), "IMG");
   if(elements.length > 0)
    this.populateItemCollection(elements, this.hasTemplates ? this.seoFriendlyItems : this.items);
  },
  populateItemCollection: function(imageCollection, itemsCollection, image) {
   var index = this.visibleStartIndex;
   while(image = imageCollection[0]) {
    var collectionItem = (itemsCollection[index] || (itemsCollection[index] = {}));
    collectionItem.s = ASPx.Attr.GetAttribute(image, "src");
    collectionItem.t = ASPx.Attr.GetAttribute(image, "alt");
    if(image.parentNode.tagName == "A") {
     collectionItem.u = ASPx.Attr.GetAttribute(image.parentNode, "href");
     ASPx.RemoveElement(image.parentNode);
    } else 
     ASPx.RemoveElement(image);
    index++;
   }
  },
  InitializeElementsSize: function () {
   var mainElement = this.GetMainElement();
   this.defaultControlSize = {
    width: mainElement.style.width,
    height: mainElement.style.height
   };
  },
  AfterInitialize: function () {
   ASPxClientControl.prototype.AfterInitialize.call(this);
   this.InitializeHandlers();
   this.EnsureShownItemsLoaded();
  },
  InitializeHandlers: function () {
   if(ASPx.Browser.TouchUI)
    return;
   if(this.enableKeyboardSupport) {
    var element = this.GetMainElement();
    ASPx.Evt.AttachEventToElement(element, "keydown", function (evt) { this.OnKeyDown(evt); }.aspxBind(this));
    ASPx.Evt.AttachEventToElement(element, "mousedown", function(evt) {
     if(!ASPx.Ident.IsFocusableElementRegardlessTabIndex(ASPx.Evt.GetEventSource(evt)))
      this.Focus();
    }.aspxBind(this));
   }
   if(this.pausePlayingWhenMouseOver)
    MouseEnterHelper.AddHandler(this.GetMainElement(), function () {
     if(this.slideShowEnabled)
      this.PauseInternal();
    }.aspxBind(this), function () {
     if(this.slideShowEnabled && !this.stopPlayingWhenPagingExecuted)
      this.PlayInternal();
    }.aspxBind(this));
  },
  GetNavigationBarOffset: function(){
   var offset = 0;
   var navigationBar = this.GetNavigationBarStrategy();
   if(navigationBar) 
    offset = navigationBar.GetSlideElementPosition();
   return isNaN(offset) ? 0 : offset;
  },
  UpdateStateObject: function(){
   this.UpdateStateObjectWithObject({ activeItemIndex: this.GetActiveItemIndex(), navigationBarOffset: this.GetNavigationBarOffset() });
  },
  CreateTemplates: function () {
   var imageArea = this.GetImageAreaStrategy();
   if(imageArea)
    imageArea.CreateTemplates();
   var navigationBar = this.GetNavigationBarStrategy();
   if(navigationBar)
    navigationBar.CreateTemplates();
   ASPx.ProcessScriptsAndLinks(this.name);
   this.templateCreated = true;
  },
  AdjustControlCore: function () {
   this.AdjustControlCoreInternal();
   if(this.HasTemplates() && !this.templateCreated)
    window.setTimeout(function () { this.CreateTemplates(); }.aspxBind(this), 0);
  },
  SetSizeCore: function(sizePropertyName, size, getFunctionName, corrected) {
   this.defaultControlSize[sizePropertyName] = size;
   ASPxClientControl.prototype.SetSizeCore.call(this, sizePropertyName, size, getFunctionName, corrected);
  },
  AdjustControlCoreInternal: function () {
   this.AllowRubberLayout();
   var mainElementStyle = {
    width: SizeUtils.GetClientWidth(this.GetMainElement(), true),
    height: SizeUtils.GetClientHeight(this.GetMainElement(), true)
   };
   var passePartourStyle = {
    width: mainElementStyle.width,
    height: mainElementStyle.height
   };
   this.AdjustNavigationBar(mainElementStyle, passePartourStyle);
   this.AdjustImageArea(mainElementStyle, passePartourStyle);
   this.ensureSizesAreValid(mainElementStyle);
   ASPx.SetStyles(this.GetMainElement(), mainElementStyle);
   if(this.showImageArea)
    ASPx.SetStyles(this.GetPassePartoutElement(), passePartourStyle);
   this.DenyRubberLayout();
  },
  AdjustNavigationBar: function (mainElementStyle, passePartourStyle) {
   var navigationBar = this.GetNavigationBarStrategy();
   if(navigationBar) {
    navigationBar.AdjustControl();
    var width = navigationBar.GetWidth();
    var height = navigationBar.GetHeight();
    if(this.showImageArea) {
     switch (this.GetNavigationBarPosition()) {
      case NavigationBarPositionEnum.Right:
      case NavigationBarPositionEnum.Left:
       passePartourStyle.float = "left";
       passePartourStyle.width -= width;
       break;
      case NavigationBarPositionEnum.Bottom:
      case NavigationBarPositionEnum.Top:
       passePartourStyle.height -= height;
       break;
     }
    }
    else {
     mainElementStyle.width = width;
     mainElementStyle.height = height;
    }
   }
  },
  AdjustImageArea: function (mainElementStyle, passePartourStyle) {
   var imageAreaStrategy = this.GetImageAreaStrategy();
   if(imageAreaStrategy) {
    imageAreaStrategy.AdjustControl(passePartourStyle.width, passePartourStyle.height);
    var imageAreaWidth = imageAreaStrategy.GetWidth();
    var imageAreaHeight = imageAreaStrategy.GetHeight();
    var navigationBar = this.GetNavigationBarStrategy();
    var navigationBarWidth = navigationBar ? navigationBar.GetWidth() : 0;
    var navigationBarHeight = navigationBar ? navigationBar.GetHeight() : 0;
    var useHorizLayout = this.GetNavigationBarPosition() == NavigationBarPositionEnum.Left
     || this.GetNavigationBarPosition() == NavigationBarPositionEnum.Right;
    if(imageAreaWidth > passePartourStyle.width) {
     var widthCorrection = useHorizLayout ? navigationBarWidth : 0;
     passePartourStyle.width = imageAreaWidth;
     mainElementStyle.width = imageAreaWidth + widthCorrection;
    }
    if(imageAreaHeight > passePartourStyle.height) {
     var heightCorrection = !useHorizLayout ? navigationBarHeight : 0;
     passePartourStyle.height = imageAreaHeight;
     mainElementStyle.height = imageAreaHeight + heightCorrection;
    }
   }
  },
  AllowRubberLayout: function () {
   this.ResetControlStyle();
   ASPx.SetStyles(this.GetMainElement(), {
    borderSpacing: 0,
    overflow: "hidden",
    display: "table" 
   });
   if(this.showImageArea)
    ASPx.SetStyles(this.GetPassePartoutElement(), { width: "", height: "" });
  },
  DenyRubberLayout: function () {
   ASPx.SetStyles(this.GetMainElement(), {
    display: "",
    overflow: "",
    borderSpacing: ""
   });
   if(this.showImageArea)
    ASPx.SetStyles(this.GetPassePartoutElement(), { display: "" });
  },
  ResetControlStyle: function () {
   ASPx.SetStyles(this.GetMainElement(), this.defaultControlSize);
   var navigationBar = this.GetNavigationBarStrategy();
   if(navigationBar)
    navigationBar.ResetControlStyle();
   var imageAreaStrategy = this.GetImageAreaStrategy();
   if(imageAreaStrategy)
    imageAreaStrategy.ResetControlStyle();
  },
  ensureSizesAreValid: function(style) {
   if(style.width <= 0)
    style.width = 1;
   if(style.height <= 0)
    style.height = 1;
  },
  CreateControlHierarchy: function () {
   if(this.showImageArea) {
    this.passePartoutElement = document.createElement("DIV");
    this.GetMainElement().appendChild(this.passePartoutElement);
    this.imageAreaStrategy = this.CreateImageAreaStrategy();
   }
   if(this.showNavBar)
    this.navigationBarStrategy = this.CreateNavigationBarStrategy();
   this.RaiseStrategiesCreated();
  },
  CreateImageAreaStrategy: function () {
   switch (this.GetAnimationType()) {
    case AnimationTypeEnum.Slide:
     return this.CreateSlideImageAreaStrategy();
    case AnimationTypeEnum.Fade:
     return new FadeImageAreaStrategy(this);
    case AnimationTypeEnum.None:
     return new NoneImageAreaStrategy(this);
   }
  },
  CreateSlideImageAreaStrategy: function () {
   return this.enableLoopNavigation ? new SlideLoopNavigationImageAreaStrategy(this) : new SlideImageAreaStrategy(this);
  },
  CreateNavigationBarStrategy: function () {
   switch (this.GetNavigationBarMode()) {
    case NavigationBarModeEnum.Thumbnails:
     return new NavigationBarThumbnailStrategy(this);
    case NavigationBarModeEnum.Dots:
     return new NavigationBarDotsStrategy(this);
   }
  },
  PrepareControlHierarchy: function () {
   this.PrepareMainElement();
   if(this.showImageArea)
    this.PreparePassePartoutElement();
   if(this.autoPlay)
    this.Play();
  },
  PrepareMainElement: function () {
   var mainElement = this.GetMainElement();
   mainElement.tabIndex = Math.max(mainElement.tabIndex, 0);
   ASPx.SetElementDisplay(mainElement, true);
  },
  PreparePassePartoutElement: function () {
   ASPx.SetStyles(this.GetPassePartoutElement(), {
    cssText: this.passePartoutStyle,
    className: CssClassesConstants.PassePartoutCssClassName
   });
  },
  OnBrowserWindowResize: function(e) {
   this.AdjustControl();
  },
  OnKeyDown: function(evt) {
   if(!this.IsFocused())
    return;
   var keyCode = ASPx.Evt.GetKeyCode(evt);
   switch(keyCode) {
    case ASPx.Key.Left:
     var index = this.rtl ? this.GetActiveItemIndex() + 1 : this.GetActiveItemIndex() - 1;
     this.SetActiveItemIndex(index);
     return ASPx.Evt.PreventEvent(evt);
    case ASPx.Key.Up:
     this.SetActiveItemIndex(this.GetActiveItemIndex() - 1);
     return ASPx.Evt.PreventEvent(evt);
    case ASPx.Key.Right:
     var index = this.rtl ? this.GetActiveItemIndex() - 1 : this.GetActiveItemIndex() + 1;
     this.SetActiveItemIndex(index);
     return ASPx.Evt.PreventEvent(evt);
    case ASPx.Key.Down:
     this.SetActiveItemIndex(this.GetActiveItemIndex() + 1);
     return ASPx.Evt.PreventEvent(evt);
    case ASPx.Key.Home:
     this.SetActiveItemIndex(0);
     return ASPx.Evt.PreventEvent(evt);
    case ASPx.Key.End:
     this.SetActiveItemIndex(this.GetItemCount() - 1);
     return ASPx.Evt.PreventEvent(evt);
   }
  },
  OnCallback: function(result) {
   if(result.items)
    this.ProcessCreatedItems(result.items);
  },
  GetImageAreaStrategy: function () {
   return this.imageAreaStrategy;
  },
  GetNavigationBarStrategy: function () {
   return this.navigationBarStrategy;
  },
  GetPassePartoutElement: function () {
   return this.passePartoutElement;
  },
  GetItem: function(index, forceLoad) {
   var item = this.GetItemInternal(index);
   if(item) {
    var isLoaded = !item.skipped && !item.pending;
    if(forceLoad && !isLoaded)
     this.LoadItemsViaCallback([index]);
    return new ASPxClientImageSliderItem(this, index, item.n, item.s, item.t, isLoaded);
   }
   return null;
  },
  GetItemByName: function(name, forceLoad) {
   for(var i = 0; i < this.GetItemCount(); i++) {
    if(this.GetItemInternal(i).n == name)
     return this.GetItem(i, forceLoad);
   }
   if(forceLoad)
    this.DoLoadItemsViaCallback(null, [name]);
   return null;
  },
  GetActiveItemIndex: function () {
   return this.GetRtlIndex(this.GetActiveItemIndexInternal());
  },
  SetActiveItemIndex: function (index, preventAnimation, isAPICall) {
   this.SetActiveItemIndexInternal(this.GetRtlIndex(index), preventAnimation, isAPICall);
  },
  GetActiveItem: function () {
   return this.GetItem(this.GetActiveItemIndex());
  },
  SetActiveItem: function (item, preventAnimation) {
   this.SetActiveItemIndex(item.index, preventAnimation);
  },
  GetItemCount: function () {
   return this.itemsCount;
  },
  GetLoadedItems: function() {
   var itemsCount = this.GetItemCount(),
    result = [];
   for(var i = 0; i < itemsCount; i++) {
    var item = this.GetItem(i);
    if(item.loaded)
     result.push(item);
   }
   return result;
  },
  Focus: function () {
   if(!ASPx.Browser.TouchUI && this.enableKeyboardSupport)
    ASPx.SetFocus(this.GetMainElement());
  },
  Play: function () {
   if(this.enabled) {
    this.PlayInternal();
    this.slideShowEnabled = true;
   }
  },
  Pause: function () {
   if(this.enabled) {
    this.PauseInternal();
    this.slideShowEnabled = false;
   }
  },
  IsSlideShowPlaying: function () {
   return this.timerID != -1;
  },
  IsFocused: function () {
   return ASPx.GetActiveElement() == this.GetMainElement();
  },
  PlayInternal: function () {
   if(this.IsSlideShowPlaying())
    return;
   this.timerID = window.setInterval(function () { this.DoSeActivetNextItem(); }.aspxBind(this), this.interval);
   this.stopPlayingWhenPagingExecuted = false;
   if(this.GetImageAreaStrategy())
    this.GetImageAreaStrategy().SetSlideShowButtonState(false);
  },
  PauseInternal: function () {
   this.timerID = ASPx.Timer.ClearInterval(this.timerID);
   if(this.GetImageAreaStrategy())
    this.GetImageAreaStrategy().SetSlideShowButtonState(true);
  },
  ResetSlideShowTimer: function () {
   if(this.IsSlideShowPlaying()) {
    this.timerID = ASPx.Timer.ClearInterval(this.timerID);
    this.timerID = window.setInterval(function () { this.DoSeActivetNextItem(); }.aspxBind(this), this.interval);
   }
  },
  StopPlayingWhenPaging: function () {
   if(this.stopPlayingWhenPaging) {
    this.Pause();
    this.stopPlayingWhenPagingExecuted = true;
   }
  },
  DoSeActivetNextItem: function () {
   var activeIndex = this.GetActiveItemIndex() + 1;
   if(activeIndex >= this.GetItemCount())
    activeIndex = 0;
   this.SetActiveItemIndex(activeIndex);
  },
  RaiseStrategiesCreated: function () {
   if(!this.StrategiesCreated.IsEmpty())
    this.StrategiesCreated.FireEvent(this, null);
  },
  RaiseActiveItemChanged: function () {
   this.RaiseItemEvent(this.ActiveItemChanged);
  },
  RaiseItemClick: function () {
   this.RaiseItemEvent(this.ItemClick);
  },
  RaiseThumbnailItemClick: function () {
   this.RaiseItemEvent(this.ThumbnailItemClick);
  },
  RaiseItemLoadedOnCallback: function(item) {
   this.RaiseItemEvent(this.ItemLoadedOnCallback, item);
  },
  RaiseItemEvent: function(event, item) {
   if(!event.IsEmpty()) {
    var args = new ASPxClientImageSliderItemEventArgs(item || this.GetActiveItem());
    event.FireEvent(this, args);
   }
  },
  SetActiveItemIndexInternal: function (index, preventAnimation, isAPICall) {
   if(index >= 0 && index < this.GetItemCount() && index != this.GetActiveItemIndexInternal()) {
    if(this.GetImageAreaStrategy())
     this.GetImageAreaStrategy().SetActiveItemIndex(index, preventAnimation);
    if(this.GetNavigationBarStrategy())
     this.GetNavigationBarStrategy().SetActiveItemIndex(index, preventAnimation);
    this.ResetSlideShowTimer();
    if(!isAPICall)
     this.RaiseActiveItemChanged();
   }
  },
  GetActiveItemIndexInternal: function() {
   var strategy = this.GetImageAreaStrategy() || this.GetNavigationBarStrategy();
   if(strategy)
    return strategy.GetActiveItemIndex();
   return 0;
  },
  GetItemInternal: function (index) {
   if(index < 0 || index >= this.GetItemCount())
    return null;
   return this.items[index] || { skipped: true };
  },
  GetRtlIndex: function (index) {
   if(this.rtl)
    return this.GetItemCount() - 1 - index;
   return index;
  },
  IsSkippedItem: function(index) {
   var item = this.GetItemInternal(index);
   return item ? !!item.skipped : false;
  },
  IsPendingItem: function(index) {
   var item = this.GetItemInternal(index);
   return item ? !!item.pending : false;
  },
  IsAllowItemCallback: function(index) {
   return this.IsSkippedItem(index) && !this.IsPendingItem(index);
  },
  EnsureShownItemsLoaded: function() {
   this.pendingItemsTimerID = ASPx.Timer.ClearTimer(this.pendingItemsTimerID);
   this.pendingItemsTimerID = window.setTimeout(function() {
    var navigationBar = this.GetNavigationBarStrategy();
    var indexes = navigationBar ? navigationBar.GetShownItemIndexes(false) : [];
    for(var i = 0; i < indexes.length; i++)
     indexes[i] = this.GetRtlIndex(indexes[i]);
    var activeItemIndex = this.GetActiveItemIndex(),
     shownIndexes = navigationBar ? indexes : [activeItemIndex];
    indexes.push(activeItemIndex);
    indexes = ASPxClientImageSlider.ExtendItemsPerRequest(indexes, this.itemsPerRequest, shownIndexes, this.GetItemCount(), this.IsAllowItemCallback.bind(this));
    this.LoadItemsViaCallback(indexes);
   }.aspxBind(this), 1000);
  },
  LoadItemsViaCallback: function(indexArray) {
   var pendingItemsQueue = [];
   for(var i = 0; i < indexArray.length; i++) {
    var index = indexArray[i];
    if(this.IsAllowItemCallback(index)) {
     this.items[index] = { pending: true };
     pendingItemsQueue.push(index);
    }
   }
   if(pendingItemsQueue.length > 0)
    this.DoLoadItemsViaCallback(pendingItemsQueue);
  },
  DoLoadItemsViaCallback: function(indexArray, nameArray) {
   var args = {};
   if(indexArray)
    args.i = indexArray;
   if(nameArray)
    args.n = nameArray;
   var preparedArgs = ASPx.Json.ToJson(args);
   this.CreateCallback(preparedArgs);
   this.HideLoadingPanel();
  },
  ProcessCreatedItems: function(items) {
   var navigationBar = this.GetNavigationBarStrategy();
   var imageArea = this.GetImageAreaStrategy();
   for(var key in items) {
    if(!items.hasOwnProperty(key)) continue;
    this.items[key] = items[key];
    this.RaiseItemLoadedOnCallback(this.GetItem(key));
    var index = this.GetRtlIndex(key);
    if(navigationBar)
     navigationBar.UpdateItemElement(index);
    if(imageArea)
     imageArea.UpdateItemElement(index);
   }
   if(this.HasTemplates())
    ASPx.ProcessScriptsAndLinks(this.name);
  },
  GetAnimationType: function () {
   return this.animationType;
  },
  HasNavigateUrls: function () {
   return this.hasNavigateUrls;
  },
  HasTemplates: function () {
   return this.hasTemplates;
  },
  GetNavigationBarPosition: function () {
   return this.navBarPos;
  },
  GetNavigationBarMode: function () {
   return this.dotHCssCl != "" ? 1 : 0;
  }
 });
 ASPxClientImageSlider.ExtendItemsPerRequest = function(indexes, itemsPerRequest, shownIndexes, itemsCount, allowFunc) {
  var result = indexes.filter(function(i) { return allowFunc(i); }.aspxBind(this)),
   extendedItemsCount = itemsPerRequest - result.length;
  if(result.length === 0 || extendedItemsCount < 1)
   return result;
  var index = shownIndexes[Math.floor(shownIndexes.length / 2)],
   count = itemsCount,
   i = 0;
  while(i < count && extendedItemsCount > 0) {
   index = (i % 2 === 0) ? index + i : index - i;
   if(index < 0 || index >= count)
    count++;
   else if(!ASPx.Data.ArrayContains(indexes, index) && allowFunc(index)) {
    result.push(index);
    extendedItemsCount--;
   }
   i++;
  }
  return result;
 };
 ASPxClientImageSlider.Cast = ASPxClientControl.Cast;
 var ASPxClientImageSliderItemEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function (item) {
   this.constructor.prototype.constructor.call(this);
   this.item = item;
  }
 });
 var ASPxClientImageSliderItem = ASPx.CreateClass(null, {
  constructor: function (imageSlider, index, name, imageUrl, text, loaded) {
   this.imageSlider = imageSlider;
   this.index = index;
   this.name = name;
   this.imageUrl = imageUrl;
   this.text = text;
   this.loaded = loaded;
  }
 });
 var ASPxClientImageZoomNavigator = ASPx.CreateClass(ASPxClientImageSlider, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
   this.disableSelectedStateAnimation = true;
   this.imageZoomName = "";
   this.changeAction = 0;
   this.buttonVisibilityMode = 0;
  },
  Initialize: function () {
   ASPxClientImageSlider.prototype.Initialize.call(this);
   this.ActiveItemChanged.AddHandler(function () {
    this.OnActiveItemChanged();
   }.aspxBind(this));
  },
  CreateNavigationBarStrategy: function () {
   return new ImageZoomNavigationBarStrategy(this);
  },
  PrepareControlHierarchy: function () {
   ASPxClientImageSlider.prototype.PrepareControlHierarchy.call(this);
   ASPx.AddClassNameToElement(this.GetMainElement(), CssClassesConstants.ImageZoomNavigatorCssClassName);
  },
  OnActiveItemChanged: function () {
   this.UpdateImageZoomImages();
  },
  ProcessCreatedItems: function(items) {
   ASPxClientImageSlider.prototype.ProcessCreatedItems.call(this, items);
   this.UpdateImageZoomImages();
  },
  UpdateImageZoomImages: function() {
   var activeItemIndex = this.GetActiveItemIndex();
   if(this.IsSkippedItem(activeItemIndex))
    return;
   var imageZoom = this.GetImageZoom();
   if(imageZoom) {
    var item = this.GetItemInternal(activeItemIndex);
    imageZoom.SetImageProperties(item.s, item.liu || item.s, item.zt, item.et, item.zt || item.at);
   }
  },
  GetImageZoom: function() {
   return this.imageZoomName ? ASPx.GetControlCollection().Get(this.imageZoomName) : null;
  }
 });
 var ImageZoomNavigationBarStrategy = ASPx.CreateClass(NavigationBarThumbnailStrategy, {
  constructor: function (imageZoomNavigator) {
   this.visibleItemCount = 0;
   this.constructor.prototype.constructor.call(this, imageZoomNavigator);
  },
  InitializeHandlers: function () {
   if(this.GetImageSlider().changeAction == ActiveItemChangeActionEnum.Hover) {
    ItemsOwnerBase.prototype.InitializeHandlers.call(this);
    ASPx.Evt.AttachEventToElement(this.GetSlidePanelElement(), "mouseover", function (evt) { this.OnNavigationBarMouseOver(evt); }.aspxBind(this));
   }
   else
    NavigationBarThumbnailStrategy.prototype.InitializeHandlers.call(this);
  },
  OnNavigationBarMouseOver: function (evt) {
   if(!this.IsExecutedGesture()) {
    var index = this.GetItemIndexFromEvent(evt);
    if(index != -1)
     this.GetImageSlider().SetActiveItemIndexInternal(index);
   }
  },
  GetEnableItemHoverState: function () {
   return this.GetImageSlider().changeAction == ActiveItemChangeActionEnum.Click;
  },
  GetItemAlternateText: function (index) {
   if(this.IsValidItemIndex(index)) {
    var item = this.GetItem(index);
    return item.zt || item.at || "";
   }
   return "";
  },
  CalculateSize: function() {
   NavigationBarThumbnailStrategy.prototype.CalculateSize.call(this);
   if(!this.CanUseVisibleItemCount()) {
    var isHorizontal = this.IsHorizontalNavigation();
    var size = {
     width: isHorizontal ? this.GetItemWidthWithSpacing() * this.GetItemCount() - this.GetItemSpacing() : this.GetItemElementWidth(),
     height: isHorizontal ? this.GetItemElementHeight() : this.GetItemHeightWithSpacing() * this.GetItemCount() - this.GetItemSpacing()
    };
    var mainElementWidth = SizeUtils.GetClientWidth(this.GetMainElement(), true);
    var mainElementHeight = SizeUtils.GetClientHeight(this.GetMainElement(), true);
    if(isHorizontal && size.width < mainElementWidth || !isHorizontal && size.height < mainElementHeight) {
     this.visibleItemCount = this.GetItemCount();
     if(this.GetImageSlider().buttonVisibilityMode == NavigationButtonVisibilityModeEnum.Auto)
      this.SetVisibilityButtons(false);
    }
   }
  },
  UpdateNavigationButtonsState: function () {
   if(this.GetVisibleItemCount() != this.GetItemCount() || this.GetImageSlider().buttonVisibilityMode != NavigationButtonVisibilityModeEnum.Auto)
    return NavigationBarThumbnailStrategy.prototype.UpdateNavigationButtonsState.call(this);
   return false;
  },
  CanCreateNavigationButtons: function() {
   if(this.GetImageSlider().buttonVisibilityMode == NavigationButtonVisibilityModeEnum.Always)
    return true;
   return NavigationBarThumbnailStrategy.prototype.CanCreateNavigationButtons.call(this);
  },
  GetVisibleItemCount: function() {
   return this.GetImageSlider().visibleItemsCount || this.visibleItemCount;
  }
 });
 var ClientGalleryImageSlider = ASPx.CreateClass(ASPxClientImageSlider, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.OnLoadItemsViaCallback = new ASPxClientEvent();
  },
  ExtendItemsPerRequest: function(indexes, startIndex, itemsCount, allowFunc) {
   return indexes;
  },
  DoLoadItemsViaCallback: function(indexArray) {
   this.RaiseLoadItemsViaCallback(indexArray);
  },
  RaiseLoadItemsViaCallback: function(pendingQueue) {
   if(!this.OnLoadItemsViaCallback.IsEmpty() && pendingQueue.length > 0)
    this.OnLoadItemsViaCallback.FireEvent(this, pendingQueue);
  }
 });
 ASPx.ClientGalleryImageSlider = ClientGalleryImageSlider;
 window.ASPxClientImageSlider = ASPxClientImageSlider;
 window.ASPxClientImageSliderItemEventArgs = ASPxClientImageSliderItemEventArgs;
 window.ASPxClientImageSliderItem = ASPxClientImageSliderItem;
 window.ASPxClientImageZoomNavigator = ASPxClientImageZoomNavigator;
})();

(function() {
var MVCxClientImageSlider = ASPx.CreateClass(ASPxClientImageSlider, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
 },
 InlineInitialize: function() {
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), null); }; 
  ASPxClientImageSlider.prototype.InlineInitialize.call(this);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(arg) {
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 GetCallbackMethod: function(command) {
  return this.callBack;
 }
});
window.MVCxClientImageSlider = MVCxClientImageSlider;
})();
(function() {
 var CssClassesConstants = {};
 CssClassesConstants.Prefix = "dxiz-";
 CssClassesConstants.Lens = CssClassesConstants.Prefix + "lens";
 CssClassesConstants.ClipPanel = CssClassesConstants.Prefix + "clipPanel";
 CssClassesConstants.Hint = CssClassesConstants.Prefix + "hint";
 CssClassesConstants.Wrapper = CssClassesConstants.Prefix + "wrapper";
 CssClassesConstants.EmptyImage = CssClassesConstants.Prefix + "emptyImage";
 CssClassesConstants.ZoomWindowImage = CssClassesConstants.Prefix + "zwImage";
 CssClassesConstants.ExpandWindowImage = CssClassesConstants.Prefix + "ewImage";
 var Constants = {};
 Constants.ZoomWindowID = "_ZW";
 Constants.ExpandWindowID = "_EW";
 Constants.ZoomWindowImageID = "_ZW_Image";
 Constants.ExpandWindowImageID = "_EW_Image";
 Constants.ExpandWindowPadding = 10;
 Constants.AnimationDuration = 200;
 Constants.ContentBoxClassName = "dx-contentBox";
 var MouseBoxOpacityModeEnum = {
  Inside: 0,
  Outside: 1
 };
 var LargeImageLoadModeEnum = {
  AtOnce: 0,
  AfterInitialize: 1,
  OnAction: 2
 };
 var ZoomWindowPosition = {
  Inside: 0,
  Outside: 1
 };
 var ASPxClientImageZoom = ASPx.CreateClass(ASPxClientControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.image = null;
   this.hint = null;
   this.action = null;
   this.zoomWindow = null;
   this.secondaryZoomWindow = null;
   this.expandWindow = null;
   this.wrapperElement = null;
   this.emptyImage = null;
   this.showHint = true;
   this.showZoomWindow = true;
   this.showExpandWindow = true;
   this.hasDefaultSize = false;
   this.largeImageLoadingLockCount = 0;
   this.width = 0;
   this.height = 0;
   this.zoomWindowWidth = "150%";
   this.zoomWindowHeight = "150%";
   this.zoomWindowPosition = ZoomWindowPosition.Outside;
   this.currentZoomWindowPosition = this.zoomWindowPosition;
   this.previousParentNodeOfClipPanel = null;
   this.mouseBoxOpacityMode = MouseBoxOpacityModeEnum.Inside;
   this.largeImageLoadMode = LargeImageLoadModeEnum.AtOnce;
   this.largeImageUrl = "";
   this.navigator = null;
   this.imageZoomNavigatorName = "";
  },
  InlineInitialize: function() {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   var mainElement = this.GetMainElement();
   if(mainElement.style.width && mainElement.style.height) {
    this.width = ASPx.PxToInt(mainElement.style.width);
    this.height = ASPx.PxToInt(mainElement.style.height);
    this.hasDefaultSize = true;
   }
  },
  Initialize: function() {
   ASPxClientControl.prototype.Initialize.call(this);
   var mainElement = this.GetMainElement();
   mainElement.className += " " + Constants.ContentBoxClassName; 
   if(this.GetVisible())
    mainElement.style.display = "";
   var image = this.GetImage();
   var navigator = this.GetNavigator();
   if(navigator) {
    this.Create();
    if(navigator.GetMainElement())
     window.setTimeout(this.BindNavigator.bind(this), 0);
    else
     this.ShowEmptyImage();
   }
   else {
    if(ASPx.ImageControlUtils.IsImageLoaded(image))
     this.Create();
    else
     ASPx.Evt.AttachEventToElement(image, "load", function () { this.Create(); }.bind(this));
   }
  },
  BindNavigator: function() {
   var navigator = this.GetNavigator();
   navigator.imageZoomName = this.name;
   navigator.UpdateImageZoomImages();
  },
  Create: function() {
   this.ApplyImageSize();
   this.CreateControlHierarchy();
   this.ChangeLoadingPanelLocation();
  },
  ApplyImageSize: function() {
   this.ApplyImageSizeInternal(this.GetImage());
  },
  ApplyImageSizeInternal: function(image) {
   if(this.hasDefaultSize)
    ASPx.ImageControlUtils.ResizeImage(image, {
     width: this.width, height: this.height, canUseCanvas: false
    });
   else {
    this.width = image.naturalWidth || image.width;
    this.height = image.naturalHeight || image.height;
    ASPx.SetStyles(this.GetMainElement(), {
     width: this.width,
     height: this.height
    });
   }
  },
  CreateControlHierarchy: function() {
   if(this.showHint)
    this.hint = new HintControl(this);
   if(this.enabled) {
    if(ASPx.Browser.MSTouchUI)
     this.GetWrapperElement().style["touch-action"] = "none";
    this.action = ASPx.Browser.MobileUI ? new TouchAction(this) : new DesktopAction(this);
    if(this.showZoomWindow)
     this.zoomWindow = this.zoomWindowPosition == ZoomWindowPosition.Outside ? new OutsideZoomWindowControl(this) : new ZoomWindowControl(this);
    if(this.showExpandWindow)
     this.expandWindow = new ExpandWindowControl(this);
   }
  },
  ChangeLoadingPanelLocation: function() {
   var loadingPanel = this.GetLoadingPanelElement();
   if(loadingPanel) {
    if(loadingPanel.tagName == "DIV") { 
     var table = loadingPanel.children[0];
     table.id = loadingPanel.id;
     table.style.zIndex = loadingPanel.style.zIndex;
     table.style.display = loadingPanel.style.display;
     this.GetWrapperElement().appendChild(table.cloneNode(true));
    }
    else
     this.GetWrapperElement().appendChild(loadingPanel.cloneNode(true));
    ASPx.RemoveElement(loadingPanel);
   }
  },
  ShowLoadingPanel: function() {
   this.HideHint();
   this.action.StopHandle();
   var loadingPanel = this.GetLoadingPanelElement();
   ASPx.SetElementDisplay(loadingPanel, true);
   ASPx.SetStyles(loadingPanel, {
    top: (this.GetMainElement().offsetHeight - loadingPanel.offsetHeight) / 2,
    left: (this.GetMainElement().offsetWidth - loadingPanel.offsetWidth) / 2
   });
   this.GetMainElement().style.overflow = "hidden";
  },
  HideLoadingPanel: function() {
   this.ShowHint();
   this.action.StartHandle();
   ASPx.SetElementDisplay(this.GetLoadingPanelElement(), false);
   this.GetMainElement().style.overflow = "";
  },
  TryHideLoadingPanel: function() {
   var count = this.zoomWindow && this.expandWindow ? 2 : 1;
   if(this.largeImageLoadingLockCount == count) {
    this.largeImageLoadingLockCount = 0;
    this.HideLoadingPanel();
   }
  },
  ShowHint: function() {
   if(this.hint)
    this.hint.Show();
  },
  HideHint: function() {
   if(this.hint)
    this.hint.Hide();
  },
  OnBrowserWindowResize: function(e) {
   this.expandWindow.AdjustControl();
  },
  BrowserWindowResizeSubscriber: function() {
   return this.expandWindow && this.expandWindow.IsVisible();
  },
  SwapZoomWindows: function() {
   var tempZoomWindow = this.zoomWindow;
   this.zoomWindow = this.secondaryZoomWindow;
   this.secondaryZoomWindow = tempZoomWindow;
  },
  ChangeZoomWindowPosition: function(newPosition) {
   var clipPanel = this.zoomWindow.GetClipPanel();
   var insideClassName = CssClassesConstants.Prefix + "inside";
   if(!this.secondaryZoomWindow)
    this.secondaryZoomWindow = newPosition == ZoomWindowPosition.Outside ? new OutsideZoomWindowControl(this) : new ZoomWindowControl(this);
   this.SwapZoomWindows();
   if(this.currentZoomWindowPosition == ZoomWindowPosition.Outside) {
    ASPx.AddClassNameToElement(clipPanel, insideClassName);
    this.previousParentNodeOfClipPanel = clipPanel.parentNode;
    this.GetWrapperElement().appendChild(clipPanel);
   }
   else {
    ASPx.RemoveClassNameFromElement(clipPanel, insideClassName);
    this.previousParentNodeOfClipPanel.appendChild(clipPanel);
   }
   this.currentZoomWindowPosition = newPosition;
   this.zoomWindow.UpdateAppearance();
  },
  IsAccessibilityCompliant: function () {
   return this.accessibilityCompliant;
  },
  SetImageProperties: function (imageUrl, largeImageUrl, zoomWindowText, expandWindowText, alternateText) {
   alternateText = alternateText || "";
   this.ShowLoadingPanel();
   ASPx.ImageControlUtils.ChangeImageSource(this.GetImage(), imageUrl, function () {
    this.HideEmptyImage();
    this.ResetImage();
    this.ApplyImageSize();
    this.GetImage().alt = alternateText;
    if(!(this.zoomWindow || this.expandWindow))
     this.HideLoadingPanel();
    else {
     if(this.zoomWindow) {
      this.zoomWindow.SetText(zoomWindowText || "");
      if(this.secondaryZoomWindow)
       this.secondaryZoomWindow.SetText(zoomWindowText || "");
      ASPx.ImageControlUtils.ChangeImageSource(this.zoomWindow.GetImage(), largeImageUrl, function () {
       this.zoomWindow.ResetImage();
       this.zoomWindow.UpdateAppearance();
       this.zoomWindow.GetImage().alt = alternateText;
       this.largeImageLoadingLockCount++;
       this.TryHideLoadingPanel();
       if(this.secondaryZoomWindow)
        this.secondaryZoomWindow.ResetImage();
      }.aspxBind(this));
     }
     if(this.expandWindow) {
      this.expandWindow.SetText(expandWindowText || "");
      ASPx.ImageControlUtils.ChangeImageSource(this.expandWindow.GetImage(), largeImageUrl, function () {
       this.expandWindow.ResetImage();
       this.expandWindow.UpdateAppearance();
       this.expandWindow.GetImage().alt = alternateText;
       this.largeImageLoadingLockCount++;
       this.TryHideLoadingPanel();
      }.aspxBind(this));
     }
    }
   }.bind(this), this.ShowEmptyImage.bind(this));
  },
  ShowEmptyImage: function() {
   var emptyImage = this.GetEmptyImage();
   if(emptyImage){ 
    ASPx.SetElementDisplay(this.GetImage(), false);
    ASPx.SetElementDisplay(emptyImage, true);
    this.ApplyImageSizeInternal(emptyImage);
   }
   this.HideLoadingPanel();
   this.action.StopHandle();
   this.zoomWindow.Hide();
   this.HideHint();
  },
  HideEmptyImage: function() {
   var emptyImage = this.GetEmptyImage();
   if(emptyImage) {
    ASPx.SetElementDisplay(emptyImage, false);
    ASPx.SetElementDisplay(this.GetImage(), true);
   }
   this.action.StartHandle();
  },
  GetImage: function() {
   if(!this.image)
    this.image = this.GetChildElement("I");
   return this.image;
  },
  ResetImage: function() {
   this.image = null;
  },
  GetEmptyImage: function() {
   if(!this.emptyImage)
    this.emptyImage = ASPx.GetNodeByClassName(this.GetMainElement(), CssClassesConstants.EmptyImage);
   return this.emptyImage;
  },
  GetWrapperElement: function() {
   if(!this.wrapperElement)
    this.wrapperElement = ASPx.GetNodeByClassName(this.GetMainElement(), CssClassesConstants.Wrapper);
   return this.wrapperElement;
  },
  GetNavigator: function() {
   if (!this.navigator)
    this.navigator = ASPx.GetControlCollection().GetByName(this.imageZoomNavigatorName);
   return this.navigator;
  }
 });
 var DesktopAction = ASPx.CreateClass(ASPxClientImageControlBase, {
  constructor: function(imageZoom) {
   this.imageZoom = imageZoom;
   this.zoomWindowLockCount = 0;
   this.mouseX = 0;
   this.mouseY = 0;
   this.zoomOffsetX = 0;
   this.zoomOffsetY = 0;
   this.canHandle = true;
   this.constructor.prototype.constructor.call(this, imageZoom);
  },
  GetImageZoom: function() {
   return this.control;
  },
  GetZoomWindow: function() {
   return this.GetImageZoom().zoomWindow;
  },
  GetExpandWindow: function() {
   return this.GetImageZoom().expandWindow;
  },
  LockZoomWindow: function() {
   this.zoomWindowLockCount++;
  },
  UnlockZoomWindow: function() {
   this.zoomWindowLockCount--;
  },
  IsZoomWindowLocked: function() {
   return this.zoomWindowLockCount > 0;
  },
  StartHandle: function() {
   this.canHandle = true;
  },
  StopHandle: function() {
   this.canHandle = false;
  },
  IsMouseEntered: function() {
   return this.isMouseEntered;
  },
  InitializeHandlers: function() {
   var element = this.GetImageZoom().GetWrapperElement();
   if(this.HasMouseMoveHandler())
    ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseMoveEventName, function(evt) {
     this.OnMouseMove(evt);
    }.aspxBind(this));
   if(this.HasMouseEnterHandler())
    ASPx.Evt.AttachMouseEnterToElement(element,
     function() { this.OnMouseIn(); }.aspxBind(this),
     function() { this.OnMouseOut(); }.aspxBind(this)
    );
   if(this.HasMouseUpHandler()) {
    if(ASPx.Browser.MSTouchUI)
     ASPx.TouchUIHelper.msTouchCreateGesturesWrapper(element, function(evt) {
      this.OnMouseUp(evt);
     }.aspxBind(this));
    else
     ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseUpEventName, function(evt) {
      this.OnMouseUp(evt);
     }.aspxBind(this));
   }
   if(this.HasMouseDownHandler())
    ASPx.Evt.AttachEventToElement(element, ASPx.TouchUIHelper.touchMouseDownEventName, function(evt) {
     this.OnMouseDown(evt);
    }.aspxBind(this));
  },
  OnMouseDown: function(evt) {
  },
  OnMouseUp: function(evt) {
   if(!this.canHandle)
    return;
   if(ASPx.Evt.IsLeftButtonPressed(evt) || evt.type == "MSGestureTap") {
    var zoomWindow = this.GetZoomWindow();
    if(zoomWindow && zoomWindow.IsVisible())
     zoomWindow.Hide(true);
    this.GetExpandWindow().Show();
   }
  },
  OnMouseMove: function(evt) {
   if(!this.canHandle)
    return;
   if(!this.IsZoomWindowLocked()) {
    this.mouseX = ASPx.Evt.GetEventX(evt) - this.zoomOffsetX;
    this.mouseY = ASPx.Evt.GetEventY(evt) - this.zoomOffsetY;
    this.GetZoomWindow().SetPosition(this.mouseX, this.mouseY);
   }
  },
  OnMouseIn: function() {
   this.isMouseEntered = true;
   if(!this.canHandle)
    return;
   if(!this.IsZoomWindowLocked()) {
    this.FillZoomOffsets();
    if(this.imageZoom.zoomWindowPosition == ZoomWindowPosition.Outside) {
     var outsideZoomWindowPopup = this.imageZoom.currentZoomWindowPosition == ZoomWindowPosition.Inside ? this.imageZoom.secondaryZoomWindow.GetPopup() :
      this.GetZoomWindow().GetPopup();
     var intersectRect = ImageZoomUtils.GetIntersectRect(ImageZoomUtils.GetElementRect(this.imageZoom.GetMainElement()),
        ImageZoomUtils.GetPopupRect(outsideZoomWindowPopup));
     if(intersectRect && this.imageZoom.currentZoomWindowPosition == ZoomWindowPosition.Outside)
      this.imageZoom.ChangeZoomWindowPosition(ZoomWindowPosition.Inside);
     else if(!intersectRect && this.imageZoom.currentZoomWindowPosition == ZoomWindowPosition.Inside)
      this.imageZoom.ChangeZoomWindowPosition(ZoomWindowPosition.Outside);
    }
    this.GetZoomWindow().Show();
   }
  },
  OnMouseOut: function() {
   this.isMouseEntered = false;
   if(!this.canHandle)
    return;
   if(!this.IsZoomWindowLocked())
    this.GetZoomWindow().Hide();
  },
  HasMouseMoveHandler: function() {
   return this.imageZoom.showZoomWindow;
  },
  HasMouseDownHandler: function() {
   return false;
  },
  HasMouseUpHandler: function() {
   return this.imageZoom.showExpandWindow;
  },
  HasMouseEnterHandler: function() {
   return this.imageZoom.showZoomWindow;
  },
  FillZoomOffsets: function() {
   var mainElement = this.GetImageZoom().GetMainElement();
   this.zoomOffsetX = ASPx.GetAbsoluteX(mainElement);
   this.zoomOffsetY = ASPx.GetAbsoluteY(mainElement);
  }
 });
 var TouchAction = ASPx.CreateClass(DesktopAction, {
  constructor: function(imageZoom) {
   this.constructor.prototype.constructor.call(this, imageZoom);
  },
  HasMouseDownHandler: function() {
   return this.imageZoom.showExpandWindow || this.imageZoom.showZoomWindow;
  },
  HasMouseUpHandler: function() {
   return this.imageZoom.showExpandWindow || this.imageZoom.showZoomWindow;
  },
  HasMouseEnterHandler: function() {
   return false;
  },
  OnMouseMove: function(evt) {
   if(!this.canHandle)
    return;
   if(!this.IsZoomWindowLocked()) {
    DesktopAction.prototype.OnMouseMove.call(this, evt);
    if(!this.GetZoomWindow().IsVisible()) {
     this.FillZoomOffsets();
     this.GetZoomWindow().Show();
    }
    ASPx.Evt.PreventEvent(evt);
   }
  },
  OnMouseDown: function(evt) {
   if(!this.canHandle)
    return;
   ASPx.Evt.PreventEvent(evt);
  },
  OnMouseUp: function(evt) {
   if(!this.canHandle)
    return;
   var zoomWindow = this.GetZoomWindow();
   var expandWindow = this.GetExpandWindow();
   if(expandWindow && zoomWindow && !zoomWindow.IsVisible())
    expandWindow.Show();
   else if(zoomWindow)
    zoomWindow.Hide();
  }
 });
 var HintControl = ASPx.CreateClass(null, {
  constructor: function(imageZoom) {
   this.imageZoom = imageZoom;
   this.hintElement = null;
   this.visible = true;
  },
  Show: function() {
   if(!this.visible) {
    this.visible = true;
    this.GetHintElement().style.display = "";
   }
  },
  Hide: function() {
   if(this.visible) {
    this.visible = false;
    this.GetHintElement().style.display = "none";
   }
  },
  GetHintElement: function() {
   if(!this.hintElement)
    this.hintElement = ASPx.GetNodeByClassName(this.imageZoom.GetMainElement(), CssClassesConstants.Hint);
   return this.hintElement;
  }
 });
 var WindowControlBase = ASPx.CreateClass(ASPxClientImageControlBase, {
  constructor: function(imageZoom) {
   this.popup = null;
   this.image = null;
   this.visible = false;
   this.loadImageStarted = false;
   this.imageLoaded = !imageZoom.largeImageUrl;
   this.constructor.prototype.constructor.call(this, imageZoom);
  },
  GetImageZoom: function() {
   return this.control;
  },
  Initialize: function() {
   if(this.GetImageZoom().largeImageLoadMode == LargeImageLoadModeEnum.AfterInitialize)
    this.StartLoadImage();
   else if(this.imageLoaded)
    this.UpdateAppearance();
  },
  UpdateAppearance: function() {
  },
  GetImage: function() {
   if(!this.image) {
    this.image = ASPx.GetNodeByClassName(this.GetImageZoom().GetMainElement(), this.GetImageClassName());
    this.image.id = this.GetImageID();
   }
   return this.image;
  },
  GetImageClassName: function() {
   return "";
  },
  GetImageIDPostfix: function() {
   return "";
  },
  GetImageID: function() {
   return this.GetImageZoom().name + this.GetImageIDPostfix();
  },
  ResetImage: function() {
   this.image = null;
  },
  GetPopup: function() {
   if(!this.popup)
    this.popup = ASPx.GetControlCollection().Get(this.GetImageZoom().name + this.GetPopupID());
   return this.popup;
  },
  GetPopupID: function() {
   return "";
  },
  StartLoadImage: function() {
   this.GetImageZoom().ShowLoadingPanel();
   var image = this.GetImage();
   ASPx.Evt.AttachEventToElement(image, "load", function() {
    this.OnImageLoad();
   }.aspxBind(this));
   image.src = this.GetImageZoom().largeImageUrl;
   this.loadImageStarted = true;
  },
  OnImageLoad: function() {
   var imageZoom = this.GetImageZoom();
   this.imageLoaded = true;
   this.UpdateAppearance();
   imageZoom.HideLoadingPanel();
   if(imageZoom.largeImageLoadMode == LargeImageLoadModeEnum.OnAction && imageZoom.action.IsMouseEntered())
    this.Show();
  },
  Show: function() {
   if(this.GetImageZoom().largeImageLoadMode == LargeImageLoadModeEnum.OnAction && !this.imageLoaded && !this.loadImageStarted)
    this.StartLoadImage();
   else if(this.imageLoaded) {
    this.visible = true;
    this.ShowCore();
    this.GetImageZoom().HideHint();
   }
  },
  ShowCore: function() {
  },
  Hide: function(preventAnimation) {
   if(this.imageLoaded) {
    this.visible = false;
    this.HideCore(preventAnimation);
    this.GetImageZoom().ShowHint();
   }
  },
  HideCore: function(preventAnimation) {
  },
  SetText: function (text) {
   var popup = this.GetPopup();
   popup.SetFooterText(text);
   popup.SetWindowFooterVisible(-1, !!text);
  },
  IsVisible: function() {
   return this.visible;
  }
 });
 var ExpandWindowControl = ASPx.CreateClass(WindowControlBase, {
  constructor: function(imageZoom) {
   this.imageWidth = 0;
   this.imageHeight = 0;
   this.imageRatio = 0;
   this.constructor.prototype.constructor.call(this, imageZoom);
  },
  Initialize: function() {
   WindowControlBase.prototype.Initialize.call(this);
   this.SetVisibilityPointerCursor(true);
   this.GetPopup().fadeAnimationDuration = Constants.AnimationDuration;
  },
  InitializeHandlers: function() {
   var popup = this.GetPopup();
   popup.Closing.AddHandler(function() {
    this.OnClosing();
   }.aspxBind(this));
   popup.PopUp.AddHandler(function() {
    this.OnPopup();
   }.aspxBind(this));
   ASPx.Evt.AttachEventToElement(this.GetImage().parentNode, "click", function(evt) {
    this.Hide();
   }.aspxBind(this));
  },
  UpdateAppearance: function() {
   var image = this.GetImage();
   this.imageWidth = image.naturalWidth || image.width;
   this.imageHeight = image.naturalHeight || image.height;
   this.imageRatio = this.imageWidth / this.imageHeight;
  },
  OnClosing: function() {
   this.GetImageZoom().ShowHint();
   this.GetImageZoom().action.UnlockZoomWindow();
   this.SetVisibilityPointerCursor(true);
  },
  OnPopup: function() {
   this.AdjustControl();
   this.GetImageZoom().action.LockZoomWindow();
   this.SetVisibilityPointerCursor(false);
  },
  ShowCore: function() {
   this.GetPopup().Show();
  },
  HideCore: function() {
   this.GetPopup().Hide();
  },
  GetImageClassName: function() {
   return CssClassesConstants.ExpandWindowImage;
  },
  GetImageIDPostfix: function() {
   return Constants.ExpandWindowImageID;
  },
  GetPopupID: function() {
   return Constants.ExpandWindowID;
  },
  SetVisibilityPointerCursor: function(visible) {
   this.GetImageZoom().GetWrapperElement().style.cursor = visible ? ASPx.GetPointerCursor() : "";
  },
  AdjustControl: function() {
   var popup = this.GetPopup();
   var image = this.GetImage();
   var popupWidth = this.imageWidth;
   var popupHeight = this.imageHeight;
   var popupMaxWidth = ASPx.GetDocumentClientWidth() - Constants.ExpandWindowPadding;
   var popupMaxHeight = ASPx.GetDocumentClientHeight() - Constants.ExpandWindowPadding;
   var ratioWidth =  popupMaxWidth / this.imageWidth;
   var ratioHeight = popupMaxHeight / this.imageHeight;
   if(ratioWidth < 1 || ratioHeight < 1) {
    if(ratioWidth < ratioHeight) {
     popupWidth = popupMaxWidth;
     popupHeight = popupWidth / this.imageRatio;
    }
    else {
     popupHeight = popupMaxHeight;
     popupWidth = popupHeight * this.imageRatio;
    }
   }
   ASPx.SetStyles(image, {
    width: popupWidth,
    height: "100%"
   });
   popup.SetSize(popupWidth, popupHeight); 
   if(popup.IsVisible())
    popup.UpdatePosition();
  }
 });
 var ZoomWindowControl = ASPx.CreateClass(WindowControlBase, {
  constructor: function(imageZoom) {
   this.clipPanel = null;
   this.imageWidth = 0;
   this.imageHeight = 0;
   this.largeImageWidth = 0;
   this.largeImageHeight = 0;
   this.offsetX = 0;
   this.offsetY = 0;
   this.zoomWindowWidth = 0;
   this.zoomWindowHeight = 0;
   this.widthRatio = 0;
   this.heightRatio = 0;
   this.constructor.prototype.constructor.call(this, imageZoom);
  },  
  GetClipPanel: function() {
   if(!this.clipPanel)
    this.clipPanel = ASPx.GetNodeByClassName(this.GetImageZoom().GetMainElement(), CssClassesConstants.ClipPanel);
   return this.clipPanel;
  },
  GetImageClassName: function() {
   return CssClassesConstants.ZoomWindowImage;
  },
  GetImageIDPostfix: function() {
   return Constants.ZoomWindowImageID;
  },
  UpdateAppearance: function() {
   var largeImage = this.GetImage();
   if(!ASPx.ImageControlUtils.IsEmptyImageSource(largeImage)) { 
    if(!ASPx.ImageControlUtils.IsNotEmptyImageSize(largeImage)) 
     ASPx.ImageControlUtils.TryGetImageSize(largeImage, function() { this.UpdateAppearanceCore(); }.aspxBind(this));
    else
     this.UpdateAppearanceCore();
   }
  },
  UpdateAppearanceCore: function() {
   var largeImage = this.GetImage();
   this.largeImageWidth = largeImage.naturalWidth || largeImage.width;
   this.largeImageHeight = largeImage.naturalHeight || largeImage.height;
   var image = this.GetImageZoom().GetImage();
   if(ASPx.Browser.Chrome || ASPx.Browser.Safari) 
    var dummy = image.offsetParent;
   this.imageWidth = image.width || image.naturalWidth; 
   this.imageHeight = image.height || image.naturalHeight; 
   this.widthRatio = this.largeImageWidth / this.imageWidth;
   this.heightRatio = this.largeImageHeight / this.imageHeight;
   var controlWidth = this.GetImageZoom().width;
   var controlHeight = this.GetImageZoom().height;
   this.offsetX = controlWidth > this.imageWidth ? (controlWidth - this.imageWidth) / 2 : 0;
   this.offsetY = controlHeight > this.imageHeight ? (controlHeight - this.imageHeight) / 2 : 0;
   this.InitializeZoomWindowDimensions();
   ASPx.SetStyles(this.GetClipPanel(), this.GetClipPanelStyle());
  },
  InitializeZoomWindowDimensions: function() {
   this.zoomWindowHeight = this.imageHeight;
   this.zoomWindowWidth = this.imageWidth;
  },
  GetClipPanelStyle: function() {
   var image = this.GetImageZoom().GetImage();
   return {
    width: this.zoomWindowWidth,
    height: this.zoomWindowHeight,
    marginTop: image.style.marginTop,
    marginLeft: image.style.marginLeft
   };
  },
  ShowCore: function() {
   ASPx.AnimationHelper.fadeIn(this.GetClipPanel(), null, Constants.AnimationDuration);
  },
  HideCore: function(preventAnimation) {
   if(preventAnimation)
    ASPx.SetElementOpacity(this.GetClipPanel(), 0);
   else
    ASPx.AnimationHelper.fadeOut(this.GetClipPanel(), null, Constants.AnimationDuration);
  },
  SetText: function() {
  },
  SetPosition: function(x, y) {
   x = x - this.offsetX;
   y = y - this.offsetY;
   var lensWidth = this.zoomWindowWidth / this.widthRatio;
   var lensHeight = this.zoomWindowHeight / this.heightRatio;
   var borderX = this.imageWidth - lensWidth;
   var borderY = this.imageHeight - lensHeight;
   x = x - lensWidth / 2;
   y = y - lensHeight / 2;
   if(x < 0)
    x = 0;
   else if(x > borderX)
    x = borderX;
   if(y < 0)
    y = 0;
   else if(y > borderY)
    y = borderY;
   ASPx.SetStyles(this.GetImage(), {
    left: -x * this.widthRatio,
    top: -y * this.heightRatio
   });
  }
 });
 var OutsideZoomWindowControl = ASPx.CreateClass(ZoomWindowControl, {
  constructor: function(imageZoom) {
   this.lensControl = null;
   this.constructor.prototype.constructor.call(this, imageZoom);
  },
  Initialize: function() {
   this.lensControl = new LensControl(this);
   var popup = this.GetPopup();
   popup.fadeAnimationDuration = Constants.AnimationDuration;
   popup.AddPopupElement(this.GetImageZoom().GetWrapperElement());
   ZoomWindowControl.prototype.Initialize.call(this);
  },
  UpdateAppearance: function() {
   ZoomWindowControl.prototype.UpdateAppearance.call(this);
   this.GetPopup().SetSize(this.zoomWindowWidth, this.zoomWindowHeight);
   this.lensControl.UpdateAppearance();
  },
  InitializeZoomWindowDimensions: function() {
   this.zoomWindowHeight = typeof (this.GetImageZoom().zoomWindowHeight) == "string" ? this.imageHeight * ASPx.PercentageToFloat(this.GetImageZoom().zoomWindowHeight) : this.GetImageZoom().zoomWindowHeight;
   this.zoomWindowWidth = typeof (this.GetImageZoom().zoomWindowWidth) == "string" ? this.imageWidth * ASPx.PercentageToFloat(this.GetImageZoom().zoomWindowWidth) : this.GetImageZoom().zoomWindowWidth;
   if(this.zoomWindowHeight > this.largeImageHeight)
    this.zoomWindowHeight = this.largeImageHeight;
   if(this.zoomWindowWidth > this.largeImageWidth)
    this.zoomWindowWidth = this.largeImageWidth;
  },
  GetClipPanelStyle: function() {
   return {
    width: this.zoomWindowWidth,
    height: this.zoomWindowHeight,
    marginTop: "",
    marginLeft: "",
    opacity: ""
   };
  },
  GetPopupID: function() {
   return Constants.ZoomWindowID;
  },
  SetPosition: function(x, y) {
   ZoomWindowControl.prototype.SetPosition.call(this, x, y);
   this.lensControl.SetPosition(x, y);
  },
  ShowCore: function() {
   this.lensControl.Show();
   this.GetPopup().Show();
  },
  HideCore: function(preventAnimation) {
   this.lensControl.Hide(preventAnimation);
   var popup = this.GetPopup();
   if(preventAnimation)
    popup.closeAnimationType = "none";
   popup.Hide();
   if(preventAnimation)
    popup.closeAnimationType = "fade";
  },
  SetText: function(text) {
   WindowControlBase.prototype.SetText.call(this, text);
  }
 });
 var LensControl = ASPx.CreateClass(ASPxClientImageControlBase, {
  constructor: function(zoomWindow) {
   this.zoomWindow = zoomWindow;
   this.mainElement = null;
   this.panels = null;
   this.topPanel = null;
   this.bottomPanel = null;
   this.leftPanel = null;
   this.rightPanel = null;
   this.centralPanel = null;
   this.lensWidth = 0;
   this.lensHeight = 0;
   this.lensCenterX = 0;
   this.lensCenterY = 0;
   this.constructor.prototype.constructor.call(this, zoomWindow.GetImageZoom());
  },
  GetImageZoom: function() {
   return this.control;
  },
  GetZoomWindow: function() {
   return this.zoomWindow;
  },
  CreateControlHierarchy: function() {
   this.mainElement = this.CreateDiv(CssClassesConstants.Lens + (this.GetImageZoom().mouseBoxOpacityMode == MouseBoxOpacityModeEnum.Outside ? " outside" : ""));
   this.GetImageZoom().GetWrapperElement().appendChild(this.mainElement);
   this.panels = this.CreateDiv(CssClassesConstants.Prefix + "pc");
   this.mainElement.appendChild(this.panels);
   this.topPanel = this.CreateDiv(CssClassesConstants.Prefix + "ltp");
   this.bottomPanel = this.CreateDiv(CssClassesConstants.Prefix + "lbp");
   this.leftPanel = this.CreateDiv(CssClassesConstants.Prefix + "llp");
   this.rightPanel = this.CreateDiv(CssClassesConstants.Prefix + "lrp");
   this.centralPanel = this.CreateDiv(CssClassesConstants.Prefix + "lcp");
   this.panels.appendChild(this.leftPanel);
   this.panels.appendChild(this.rightPanel);
   this.panels.appendChild(this.topPanel);
   this.panels.appendChild(this.bottomPanel);
   this.panels.appendChild(this.centralPanel);
  },
  CreateDiv: function(className) {
   return ASPx.CreateHtmlElement("DIV", { className: className });
  },
  UpdateAppearance: function() {
   var imageWidth = this.GetZoomWindow().imageWidth;
   var imageHeight = this.GetZoomWindow().imageHeight;
   ASPx.SetStyles(this.mainElement, {
    left: this.GetZoomWindow().offsetX, top: this.GetZoomWindow().offsetY,
    width: imageWidth, height: imageHeight
   });
   this.lensWidth = this.GetZoomWindow().zoomWindowWidth / this.GetZoomWindow().widthRatio;
   this.lensHeight = this.GetZoomWindow().zoomWindowHeight / this.GetZoomWindow().heightRatio;
   this.lensCenterX = imageWidth - this.lensWidth / 2;
   this.lensCenterY = imageHeight - this.lensHeight / 2;
   ASPx.SetStyles(this.panels, {
    width: imageWidth * 2 - this.lensWidth, height: imageHeight * 2 - this.lensHeight
   });
   this.AdjustPanel(this.topPanel, 0, this.GetZoomWindow().imageWidth - this.lensWidth, this.lensWidth, this.GetZoomWindow().imageHeight - this.lensHeight);
   this.AdjustPanel(this.bottomPanel, this.GetZoomWindow().imageHeight, this.GetZoomWindow().imageWidth - this.lensWidth, this.lensWidth, this.GetZoomWindow().imageHeight - this.lensHeight);
   this.AdjustPanel(this.leftPanel, 0, 0, this.GetZoomWindow().imageWidth - this.lensWidth, this.GetZoomWindow().imageHeight * 2 - this.lensHeight);
   this.AdjustPanel(this.rightPanel, 0, this.GetZoomWindow().imageWidth, this.GetZoomWindow().imageWidth - this.lensWidth, this.GetZoomWindow().imageHeight * 2 - this.lensHeight);
   this.AdjustPanel(this.centralPanel, this.GetZoomWindow().imageHeight - this.lensHeight, this.GetZoomWindow().imageWidth - this.lensWidth, this.lensWidth, this.lensHeight);
  },
  AdjustPanel: function(element, top, left, width, height) {
   ASPx.SetStyles(element, {
    top: top,
    left: left,
    width: width,
    height: height
   });
  },
  Show: function() {
   ASPx.AnimationHelper.fadeIn(this.panels, null, Constants.AnimationDuration);
  },
  Hide: function(preventAnimation) {
   if(preventAnimation)
    ASPx.SetElementOpacity(this.panels, 0);
   else
    ASPx.AnimationHelper.fadeOut(this.panels, null, Constants.AnimationDuration);
  },
  SetPosition: function(x, y) {
   ASPx.SetStyles(this.panels, {
    left: this.GetCorrectedX(x),
    top: this.GetCorrectedY(y)
   });
  },
  GetCorrectedX: function(value) {
   value = value - this.lensCenterX - this.GetZoomWindow().offsetX;
   if(value >= 0)
    value = 0;
   else if(value <= -(this.GetZoomWindow().imageWidth - this.lensWidth))
    value = -(this.GetZoomWindow().imageWidth - this.lensWidth);
   return value;
  },
  GetCorrectedY: function(value) {
   value = value - this.lensCenterY - this.GetZoomWindow().offsetY;
   if(value >= 0)
    value = 0;
   else if(value <= -(this.GetZoomWindow().imageHeight - this.lensHeight))
    value = -(this.GetZoomWindow().imageHeight - this.lensHeight);
   return value;
  }
 });
 var ImageZoomUtils = {
  GetElementRect: function(element) {
   return element.getBoundingClientRect();
  },
  GetPopupRect: function(popup) {
   var currentPopupAnimationType = popup.popupAnimationType;
   var currentCloseAnimationType = popup.closeAnimationType;
   popup.popupAnimationType = "none";
   popup.closeAnimationType = "none";
   popup.Show();
   var result = ImageZoomUtils.GetElementRect(popup.GetWindowElement(-1));
   popup.Hide();
   popup.popupAnimationType = currentPopupAnimationType;
   popup.closeAnimationType = currentCloseAnimationType;
   return result;
  },
  GetIntersectRect: function(rectA, rectB) {
   var left = Math.max(rectA.left, rectB.left);
   var right = Math.min(rectA.right, rectB.right);
   var top = Math.max(rectA.top, rectB.top);
   var bottom = Math.min(rectA.bottom, rectB.bottom);
   if(right >= left && bottom >= top) {
    return {
     top: top,
     left: left,
     right: right,
     bottom: bottom
    };
   }
   return null;
  }
 };
 window.ASPxClientImageZoom = ASPxClientImageZoom;
})();

(function() {
 var MVCxClientImageZoom = ASPx.CreateClass(ASPxClientImageZoom, {
  Initialize: function () {
   ASPxClientImageZoom.prototype.Initialize.call(this);
  }
});
window.MVCxClientImageZoom = MVCxClientImageZoom;
})();
(function() {
var MVCxClientImageZoomNavigator = ASPx.CreateClass(ASPxClientImageZoomNavigator, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
 },
 InlineInitialize: function() {
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), null); }; 
  ASPxClientImageZoomNavigator.prototype.InlineInitialize.call(this);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(arg) {
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 GetCallbackMethod: function(command) {
  return this.callBack;
 }
});
window.MVCxClientImageZoomNavigator = MVCxClientImageZoomNavigator;
})();
(function () {
 FormLayoutConsts = {
  FORM_LAYOUT_PARTIAL_CLASS_NAME: "dxflFormLayout",
  ITEM_SYSTEM_CLASS_NAME: "dxflItemSys",
  CAPTION_CELL_SYSTEM_CLASS_NAME: "dxflCaptionCellSys",
  ALIGNED_GROUP_SYSTEM_CLASS_NAME: "dxflAGSys",
  FULL_HEIGHT_CELL_SYSTEM_CLASS_NAME: "dxflFullHeightItemCellSys",
  FULL_HEIGHT_NESTED_CONTROL_SYSTEM_CLASS_NAME: "dxflFullHeightNestedControlSys",
  HEADING_LINE_GROUP_BOX_WITH_CAPTION_SYSTEM_CLASS_NAME: "dxflWithCaptionSys",
  NESTED_CONTROL_CELL_PARTIAL_CLASS_NAME: "dxflNestedControlCell",
  HEADING_LINE_GROUP_BOX_SYSTEM_CLASS_NAME: "dxflHeadingLineGroupBoxSys",
  TABBED_GROUP_PAGE_CONTROL_SYSTEM_CLASS_NAME: "dxflPCSys",
  PAGE_CONTROL_ID_PREFIX: "PC_",
  ITEM_PATH_SEPARATOR: "_",
  NOT_FLOATED_ELEMENT_SYSTEM_CLASS_NAME: "dxflNotFloatedElSys",
  ELEMENT_CONTAINER_SYSTEM_CLASS_NAME: "dxflElConSys",
  ELEMENT_IN_ADAPTIVE_VIEW: "dxflElInAdaptiveView",
  ITEM_IN_ADAPTIVE_VIEW: "dxflItemInAdaptiveView",
  GROUP_CHILD_ITEM_IN_FIRST_ROW_SYSTEM_CLASS_NAME: "dxflChildInFirstRowSys",
  GROUP_FIRST_CHILD_ITEM_SYSTEM_CLASS_NAME: "dxflFirstChildSys",
  GROUP_CHILD_ITEM_IN_LAST_ROW_SYSTEM_CLASS_NAME: "dxflChildInLastRowSys",
  GROUP_LAST_CHILD_ITEM_SYSTEM_CLASS_NAME: "dxflLastChildSys",
  GROUP_SYSTEM_CLASS_NAME: "dxflGroupSys",
  GROUP_BOX_SYSTEM_CLASS_NAME: "dxflGroupBoxSys",
  TABBED_GROUP_SYSTEM_CLASS_NAME: "dxflPCContainerSys",
  EMPTY_ITEM_CLASS_NAME: "dxflEmptyItem",
  GROUP_FIRST_CHILD_IN_ROW_SYSTEM_CLASS_NAME: "dxflFirstChildInRowSys",
  GROUP_LAST_CHILD_IN_ROW_SYSTEM_CLASS_NAME: "dxflLastChildInRowSys",
  GROUP_WITHOUT_PADDINGS_SYSTEM_CLASS_NAME: "dxflNoDefaultPaddings",
  GROUP_CELL_PARTIAL_CLASS_NAME: "dxflGroupCell",
  LAYOUT_ITEM_CAPTION_PARTIAL_CLASS_NAME: "dxflCaption",
  GROUP_BOX_CAPTION_PARTIAL_CLASS_NAME: "dxflGroupBoxCaption",
  VIEW_FORM_LAYOUT_SYSTEM_CLASS_NAME: "dxflViewFormLayoutSys",
  EDIT_FORM_ITEM_SYSTEM_CLASS_NAME: "dxflEditFormItemSys",
  TEXT_ITEM_SYSTEM_CLASS_NAME: "dxflTextItemSys",
  GROUP_CONTAINER_SYSTEM_CLASS_NAME: "dxflGroupContainerSys",
  SINGLE_COLUMN_BREAKPOINT_NAME: "dxSC",
  OFFSET_ERROR: 5
 };
 FormLayoutHorizontalCaptionsCssClasses = [ "dxflCLLSys", "dxflCLRSys" ];
 FormLayoutVerticalCaptionsCssClasses = [ "dxflCLTSys", "dxflCLBSys" ];
 FormLayoutHorizontalHelpTextsCssClasses = [ "dxflLHelpTextSys", "dxflRHelpTextSys" ];
 FormLayoutVerticalHelpTextsCssClasses = [ "dxflTHelpTextSys", "dxflBHelpTextSys" ];
 var NestedControlToItemClassNamesMap = [
  { controlClassName: "dxeTextBoxSys", itemClassName: "dxflTextEditItemSys" },
  { controlClassName: "dxeButtonEditSys", itemClassName: "dxflTextEditItemSys" },
  { controlClassName: "dxeMemoSys", itemClassName: "dxflMemoItemSys" },
  { controlClassName: "dxeBase", itemClassName: "dxflCheckBoxItemSys" }
 ];
 var LayoutChangeType = {
  None: "N",
  SingleColumn: "S",
  Breakpoint: "B"
 };
 var FormLayoutAdaptivityMode = {
  Off: 0,
  SingleColumnWindowLimit: 1,
  Breakpoints: 2
 };
 var EdgeKeys = {
  top: "top",
  bottom: "bottom",
  left: "left",
  right: "right"
 };
 var errorCellVisibilityChangedProcessingDelay = 50;
 ASPxClientLayoutItem = ASPx.CreateClass(null, {
  constructor: function (formLayout, name, path, parent) {
   this.formLayout = formLayout;
   this.name = name;
   this.path = path;
   this.parent = parent;
   this.visible = true;
   this.clientVisible = true;
   this.isTabbedGroup = false;
   this.needAdjustContentOnShowing = true;
   this.items = [];
  },
  CreateItems: function (itemsProperties) {
   for(var i = 0; i < itemsProperties.length; i++){
    var item = this.CreateItemInstance(itemsProperties[i].name, itemsProperties[i].path);
    item.ConfigureByProperties(itemsProperties[i]);
    this.items.push(item);
   }
  },
  CreateItemInstance: function (name, path) {
   return new ASPxClientLayoutItem(this.formLayout, name, path, this);
  },
  ConfigureByProperties: function(itemProperties){
   if(ASPx.IsExists(itemProperties.visible))
    this.visible = itemProperties.visible;
   if(ASPx.IsExists(itemProperties.clientVisible))
    this.clientVisible = itemProperties.clientVisible;
   if(ASPx.IsExists(itemProperties.isTabbedGroup))
    this.isTabbedGroup = itemProperties.isTabbedGroup;
   if(ASPx.IsExists(itemProperties.items))
    this.CreateItems(itemProperties.items);
   if(ASPx.IsExists(itemProperties.columnProperties)) {
    this.columnProperties = {};
    this.columnProperties.name = itemProperties.columnProperties.name;
    this.columnProperties.fieldName = itemProperties.columnProperties.fieldName;
   }
  },
  GetItemByName: function(name) {
   return this.getItemByPredicate(function(item) { return item.name == name; });
  },
  getItemByPredicate: function(predicate) {
   for(var i = 0; i < this.items.length; i++)
    if(predicate(this.items[i])) return this.items[i];
   for(var i = 0; i < this.items.length; i++) {
    var item = this.items[i].getItemByPredicate(predicate);
    if(item != null) return item;
   }
   return null;
  },
  GetItemByPath: function (path) {
   var pathIndexes = path.split(FormLayoutConsts.ITEM_PATH_SEPARATOR);
   var currentIndex = pathIndexes[0];
   pathIndexes.shift();
   if(currentIndex > this.items.length - 1)
    return null;
   if(pathIndexes.length > 0 && this.items[currentIndex].items.length > 0) {
    var newPath = pathIndexes.join(FormLayoutConsts.ITEM_PATH_SEPARATOR);
    var result = this.items[currentIndex].GetItemByPath(newPath);
    if(result != null)
     return result;
   }
   else
    return pathIndexes.length > 0 ? null : this.items[currentIndex];
   return null;
  },
  GetVisible: function () {
   return this.visible && this.clientVisible;
  },
  SetVisible: function (value) {
   if(this.clientVisible != value) {
    this.clientVisible = value;
    this.formLayout.SetItemVisible(this, value, false);
   }
  },
  SetCaption: function(caption) {
   if(!this.visible)
    return;
   this.formLayout.SetItemCaption(this, caption);
  },
  GetCaption: function() {
   if(this.visible)
    return this.formLayout.GetItemCaption(this);
   return "";
  },
  InitializeNeedAdjustContentOnShowing: function () {
   if(this.visible) {
    this.needAdjustContentOnShowing = !this.IsVisibleOnClient();
    for(var i = 0; i < this.items.length; i++)
     this.items[i].InitializeNeedAdjustContentOnShowing();
   }
  },
  IsVisibleOnClient: function () {
   var currentItem = this;
   while(currentItem != null) {
    if(!currentItem.clientVisible)
     return false;
    currentItem = currentItem.parent;
   }
   return true;
  },
  ResetNeedAdjustContentOnShowing: function () {
   this.needAdjustContentOnShowing = false;
  }
 });
 var ApplyEdgeClassHelper = ASPx.CreateClass(null, {
  constructor: function() {
   this.edgeClasses = {
    top: FormLayoutConsts.GROUP_CHILD_ITEM_IN_FIRST_ROW_SYSTEM_CLASS_NAME,
    right: FormLayoutConsts.GROUP_LAST_CHILD_IN_ROW_SYSTEM_CLASS_NAME,
    bottom: FormLayoutConsts.GROUP_CHILD_ITEM_IN_LAST_ROW_SYSTEM_CLASS_NAME,
    left: FormLayoutConsts.GROUP_FIRST_CHILD_IN_ROW_SYSTEM_CLASS_NAME
   };
   this.cells = null;
  },
  RemoveElementClassNames: function(cellContainer) {
   ASPx.RemoveClassNamesFromElement(cellContainer, [
    FormLayoutConsts.NOT_FLOATED_ELEMENT_SYSTEM_CLASS_NAME,
    FormLayoutConsts.GROUP_CHILD_ITEM_IN_FIRST_ROW_SYSTEM_CLASS_NAME,
    FormLayoutConsts.GROUP_CHILD_ITEM_IN_LAST_ROW_SYSTEM_CLASS_NAME,
    FormLayoutConsts.GROUP_FIRST_CHILD_IN_ROW_SYSTEM_CLASS_NAME,
    FormLayoutConsts.GROUP_LAST_CHILD_IN_ROW_SYSTEM_CLASS_NAME,
    FormLayoutConsts.GROUP_LAST_CHILD_ITEM_SYSTEM_CLASS_NAME
   ]);
  },
  ApplyEdgeClasses: function(cells, cellsRects, edgeKey) {
   this.cells = null;
   if(!cells)
    return;
   this.cells = cells;
   var edgeCells = cells;
   if(edgeCells.length > 1)
    edgeCells = this.GetEdgeElements(cellsRects, edgeKey);
   for(var i = 0; i < edgeCells.length; i++)
    ASPx.AddClassNameToElement(edgeCells[i], this.edgeClasses[edgeKey]);
  },
  ApplyEdgeTopClass: function(cells, cellsRects) {
   this.ApplyEdgeClasses(cells, cellsRects, EdgeKeys.top);
  },
  ApplyEdgeBottomClass: function(cells, cellsRects) {
   this.ApplyEdgeClasses(cells, cellsRects, EdgeKeys.bottom);
  },
  ApplyEdgeLeftClass: function(cells, cellsRects) {
   this.ApplyEdgeClasses(cells, cellsRects, EdgeKeys.left);
  },
  ApplyEdgeRightClass: function(cells, cellsRects) {
   this.ApplyEdgeClasses(cells, cellsRects, EdgeKeys.right);
  },
  ApplyLastGroupItemClass: function(cells) {
   var lastCell = cells[cells.length - 1];
   ASPx.AddClassNameToElement(lastCell, FormLayoutConsts.GROUP_LAST_CHILD_ITEM_SYSTEM_CLASS_NAME);
  },
  GetEdgeElements: function(cellsRects, edgeKey) {
   var result = [];
   var edgeOffset = this.GetEdgeOffset(cellsRects, edgeKey);
   for(var i = 0; i < this.cells.length; i++) {
    var cell = this.cells[i];
    var offset = cellsRects[i][edgeKey];
    if(Math.abs(offset - edgeOffset) < FormLayoutConsts.OFFSET_ERROR)
     result.push(cell);
   }
   return result;
  },
  GetEdgeOffset: function(cellsRects, edgeKey) {
   var offsets = this.GetOffsets(cellsRects, edgeKey);
   return this.GetEdgeOffsetCore(edgeKey, offsets);
  },
  GetOffsets: function(cellsRects, edgeKey) {
   var offsets = [];
   for(var i = 0; i < cellsRects.length; i++)
    offsets.push(cellsRects[i][edgeKey]);
   return offsets;
  },
  GetEdgeOffsetCore: function(edgeKey, offsets) {
   var result = -1;
   if(edgeKey === EdgeKeys.bottom || edgeKey === EdgeKeys.right)
    result = Math.max.apply(null, offsets);
   else
    result = Math.min.apply(null, offsets);
   return result;
  }
 });
 var FullHeightTableItemHelper = ASPx.CreateClass(null, {
  constructor: function(mainElement) {
   this.mainElement = mainElement;
   this.cells = null;
   this.rows = [];
  },
  SetCellsFullHeight: function(cellsInfo) {
   this.prepareHelperState(cellsInfo);
   for(var i = 0; i < this.cells.length; i++)
    this.SetCellsFullHeightCore(i, this.cells[i]);
  },
  SetCellsFullHeightCore: function(index, container) {
   this.ensureNestedControlCellHeight(container);
   this.ensureGroupBoxCellHeight(container);
  },
  prepareHelperState: function(cellsInfo) {
   this.resetHelperState();
   if(!this.needInitializeHelperState(cellsInfo))
    return;
   this.initializeHelperState(cellsInfo);
  },
  initializeHelperState: function(cellsInfo) {
   this.cells = cellsInfo.cells;
   this.rows = cellsInfo.rows;
  },
  resetHelperState: function() {
   this.cells = null;
   this.rows = [];
  },
  needInitializeHelperState: function(cellsInfo) {
   return cellsInfo.cells && cellsInfo.rows;
  },
  ensureGroupBoxCellHeight: function(container) {
   var groupBoxCell = ASPxClientFormLayoutUtils.getContainerElementNodesByClassName(container, FormLayoutConsts.GROUP_BOX_SYSTEM_CLASS_NAME, container)[0];
   if(!groupBoxCell || groupBoxCell.style.height !== "100%")
    return;
   groupBoxCell.style.height = this.getGroupBoxCellHeight(groupBoxCell);
  },
  getGroupBoxCellHeight: function(groupBoxCell) {
   var itemCell = groupBoxCell.parentNode;
   var indents = ASPx.GetTopBottomMargins(groupBoxCell);
    return itemCell.offsetHeight - indents + "px";
  },
  ensureNestedControlCellHeight: function(container, isReset) {
   var itemCell = ASPxClientFormLayoutUtils.getContainerElementNodesByClassName(container, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME, container)[0];
   var nestedControlCell = ASPxClientFormLayoutUtils.getContainerElementNodesByPartialClassName(container, FormLayoutConsts.NESTED_CONTROL_CELL_PARTIAL_CLASS_NAME, container)[0];
   if(!itemCell || !nestedControlCell)
    return;
   var captionCell = ASPxClientFormLayoutUtils.getContainerElementNodesByClassName(container, FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME, container)[0];
   var helpTextCell = ASPxClientFormLayoutUtils.getContainerElementNodesByPartialClassName(container, "HelpTextSys", container)[0];
   var isComplexItemRenderer = captionCell || helpTextCell;
   var hasFullHeightNestedControl = ASPx.ElementHasCssClass(nestedControlCell, FormLayoutConsts.FULL_HEIGHT_NESTED_CONTROL_SYSTEM_CLASS_NAME);
   if(!isComplexItemRenderer && !hasFullHeightNestedControl)
    return;
   var correctingHeightCell = this.getCorrectingHeightCell(container, nestedControlCell);
   correctingHeightCell.style.height = this.getNestedControlCellHeight(container, itemCell, hasFullHeightNestedControl, isReset);
  },
  getNestedControlCellHeight: function(container, itemCell, hasFullHeightNestedControl, isReset) {
   var height = "";
   if(isReset)
    return height;
   if(hasFullHeightNestedControl) {
    if(this.haveAllRowNestedControlsFloatHeight(container))
     height = "100%";
    else {
     var cellHeight = this.getNestedControlCellHeightCore(container, itemCell);
     if(cellHeight)
      height = cellHeight + "px";
    }
   }
   return height;
  },
  getNestedControlCellHeightCore: function(container, itemCell) {
   var verticalCaptionCellHeight = this.getVerticalCaptionCellHeight(container);
   var containerPaddings = this.getContainerPaddings(container, itemCell);
   var containerOffsetHeight = this.getContainerOffsetHeight(container);
   var result = containerOffsetHeight - verticalCaptionCellHeight - containerPaddings;
   return result;
  },
  haveAllRowNestedControlsFloatHeight: function(container) {
   var currentRow = this.getRowByCellContainer(container);
   var currentRowCellContainers = currentRow.cells;
   var result = true;
   for(var i = 0; i < currentRowCellContainers.length; i++) {
    var cellContainer = currentRowCellContainers[i];
    var nestedControlCell = ASPxClientFormLayoutUtils.getContainerElementNodesByPartialClassName(cellContainer, FormLayoutConsts.NESTED_CONTROL_CELL_PARTIAL_CLASS_NAME, cellContainer)[0];
    var hasFullHeightNestedControl = ASPx.ElementHasCssClass(nestedControlCell, FormLayoutConsts.FULL_HEIGHT_NESTED_CONTROL_SYSTEM_CLASS_NAME);
    if(!hasFullHeightNestedControl) {
     result = false;
     break;
    }
   }
   return result;
  },
  getRowByCellContainer: function(container) {
   var result = null;
   for(var i = 0; i < this.rows.length; i++) {
    var row = this.rows[i];
    if(ASPx.GetIsParent(row, container)) {
     result = row;
     break;
    }
   }
   return result;
  },
  getVerticalCaptionCellHeight: function(container) {
   var captionCell = this.getVerticalCaptionCell(container);
   var result = 0;
   if(captionCell) {
    if(ASPx.Browser.Firefox)
     result = captionCell.firstElementChild.offsetHeight + ASPx.GetTopBottomPaddings(captionCell);
    else
     result = captionCell.offsetHeight;
   }
   return result;
  },
  getVerticalCaptionCell: function(container) {
   var result = null;
   var verticalCaptionContainer = ASPxClientFormLayoutUtils.getVerticalCaptionContainer(container);
   if(verticalCaptionContainer)
    result = ASPxClientFormLayoutUtils.getContainerElementNodesByClassName(verticalCaptionContainer, FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME, container)[0];
   return result;
  },
  getVerticalHelpTextCellHeight: function(container) {
   var verticalHelpTextCell = this.getVerticalHelpTextCell(container);
   return verticalHelpTextCell ? verticalHelpTextCell.offsetHeight : 0;
  },
  getVerticalHelpTextCell: function(container) {
   var result = ASPxClientFormLayoutUtils.getContainerElementNodesByPredicate(container, function(element) {
    return ASPx.ElementContainsCssClass(element, FormLayoutVerticalHelpTextsCssClasses[0])
     || ASPx.ElementContainsCssClass(element, FormLayoutVerticalHelpTextsCssClasses[1]);
   }, container)[0];
   return result;
  },
  getContainerPaddings: function(container, itemCell) {
   var containerChildElement = ASPx.GetChildByTagName(container, "DIV", 0) || ASPx.GetChildByTagName(container, "TABLE", 0);
   var containerPaddings = ASPx.GetTopBottomPaddings(containerChildElement);
   if(containerChildElement !== itemCell)
    containerPaddings += ASPx.GetTopBottomPaddings(itemCell);
   return containerPaddings;
  },
  getContainerOffsetHeight: function(container) {
   var parentNode = ASPx.GetParentByPartialClassName(container, FormLayoutConsts.GROUP_CELL_PARTIAL_CLASS_NAME);
   return ASPx.GetClearClientHeight(parentNode);
  },
  getCorrectingHeightCell: function(container, controlCell) {
   return controlCell;
  }
 });
 var FullHeightAdaptiveItemHelper = ASPx.CreateClass(FullHeightTableItemHelper, {
  constructor: function(mainElement) {
   this.constructor.prototype.constructor.call(this, mainElement);
   this.rowHeights = [];
   this.breakpointKey = "";
   this.rowLastCellIndices = [];
   this.isSingleColumnLayout = false;
  },
  initializeHelperState: function(cellsInfo) {
   FullHeightTableItemHelper.prototype.initializeHelperState.call(this, cellsInfo);
   this.rowLastCellIndices = cellsInfo.rowLastCellIndices;
   this.breakpointKey = cellsInfo.breakpointKey;
   this.isSingleColumnLayout = cellsInfo.cells.length === cellsInfo.rows.length;
  },
  resetHelperState: function() {
   FullHeightTableItemHelper.prototype.resetHelperState.call(this);
   this.breakpointKey = "";
   this.rowLastCellIndices = [];
   this.rowHeights = [];
   this.isSingleColumnLayout = false;
  },
  SetCellsFullHeightCore: function(index, container) {
   if(container.style.width !== "100%")
    this.setCellFullHeight(index);
   FullHeightTableItemHelper.prototype.SetCellsFullHeightCore.call(this, index, container);
  },
  setCellFullHeight: function(index) {
   var container = this.cells[index];
   var rowSpan = this.getCellRowSpan(container);
   var rowHeight = this.getRowHeightByCellIndex(index);
   var height = rowHeight;
   if(rowSpan > 1) {
    var nextRowsHeight = this.getNextRowsHeight(index, rowSpan - 1);
    height += nextRowsHeight;
    var marginBottom = Math.max(container.offsetHeight *(1 - 1/rowSpan), nextRowsHeight);
    container.style.marginBottom = -marginBottom + "px";
   }
   var heightAttribute = height + "px";
   if(height === 0)
    heightAttribute = "";
   container.style.height = heightAttribute;
  },
  getRowHeightByCellIndex: function(index) {
   var rowIndex = this.getRowIndexByCellIndex(index);
   return this.getRowHeight(rowIndex);
  },
  getNextRowsHeight: function(index, count) {
   var rowIndex = this.getRowIndexByCellIndex(index);
   var result = 0;
   for(var i = 0; i < count; i++)
    result += this.getRowHeight(rowIndex + 1 + i);
   return result;
  },
  getPreviousRowHeights: function(rowIndex, count) {
   var result = 0;
   for(var i = 0; i < count; i++)
    result += this.getCachedRowHeight(rowIndex - 1 - i);
   return result;
  },
  getRowHeight: function(rowIndex) {
   if(!this.rows[rowIndex])
    return 0;
   var result = this.getCachedRowHeight(rowIndex);
   if(result !== 0)
    return result;
   var heights = [];
   for(var i = 0; i <= rowIndex; i++) {
    var row = this.rows[i];
    for(var j = 0; j < row.length; j++) {
     var height = this.getRowHeightCore(i, row[j], rowIndex);
     if(height !== 0)
      heights.push(height);
    }
   }
   result = Math.max.apply(null, heights);
   this.rowHeights[rowIndex] = result;
   return result;
  },
  getRowHeightCore: function(rowIndex, cellElement, currentRowIndex) {
   var rowSpan = this.getCellRowSpan(cellElement);
   var unoccupiedRowSpan = rowIndex + rowSpan - currentRowIndex;
   if(unoccupiedRowSpan <= 0)
    return 0;
   var previousRowHeights = this.getPreviousRowHeights(currentRowIndex, rowSpan - unoccupiedRowSpan);
   var extraCellHeightOverPreviousRow = cellElement.offsetHeight - previousRowHeights;
   var unoccupiedElementHeight = extraCellHeightOverPreviousRow > 0 ? extraCellHeightOverPreviousRow : 0;
   return unoccupiedElementHeight / unoccupiedRowSpan;
  },
  getCachedRowHeight: function(rowIndex) {
   var rowHeight = this.rowHeights[rowIndex];
   if(isNaN(rowHeight))
    rowHeight = 0;
   return rowHeight;
  },
  getCorrectingHeightCell: function(container, controlCell) {
   var verticalHelpTextCell = this.getVerticalHelpTextCell(container);
   if(!verticalHelpTextCell)
    return controlCell;
   var internalTable = ASPxClientFormLayoutUtils.getContainerElementNodesByPartialClassName(container, "dxflInternalEditorTable", container)[0];
   return ASPx.RetrieveByPredicate(ASPx.GetChildNodesByTagName(internalTable, "DIV"),
           function (element) { return element != verticalHelpTextCell; }
             )[0];
  },
  resetInlineMargins: function(cellContainer) {
   if(cellContainer.style.marginLeft)
    cellContainer.style.marginLeft = "";
   if(cellContainer.style.marginBottom)
    cellContainer.style.marginBottom = "";
  },
  resetInlineHeight: function(cellContainer) {
   this.ensureNestedControlCellHeight(cellContainer, true);
   if(cellContainer.style.height)
    cellContainer.style.height = "";
  },
  resetInlineWidth: function(cellContainer) {
   if(cellContainer.style.width)
    cellContainer.style.width = "";
  },
  getRowIndexByCellIndex: function(index) {
   return ASPxClientFormLayoutUtils.getRowIndexByCellIndex(index, this.rowLastCellIndices);
  },
  needInitializeHelperState: function(cellsInfo) {
   return FullHeightTableItemHelper.prototype.needInitializeHelperState.call(this, cellsInfo) && cellsInfo.rowLastCellIndices;
  },
  getNestedControlCellHeightCore: function(container, itemCell) {
   var result = FullHeightTableItemHelper.prototype.getNestedControlCellHeightCore.call(this, container, itemCell);
   var verticalHelpTextCellHeight = this.getVerticalHelpTextCellHeight(container);
   result = result - verticalHelpTextCellHeight;
   return result;
  },
  haveAllRowNestedControlsFloatHeight: function() {
   return false;
  },
  getContainerOffsetHeight: function(container) {
   var rowIndex = this.getContainerRowIndex(container);
   var otherRowsHeight = this.getRowsHeight(rowIndex);
   return Math.max(container.offsetHeight, ASPx.GetClearClientHeight(container.parentNode) - otherRowsHeight);
  },
  getContainerRowIndex: function(container) {
   var result = 0;
   for(var i = 0, row; row = this.rows[i]; i++) {
    if(row == container || ASPx.Data.ArrayContains(row, container)) {
     result = i;
     break;
    }
   }
   return result;
  },
  getRowsHeight: function(excludedRowIndex) {
   var result = 0;
   for(var i = 0, row; row = this.rows[i]; i++) {
    if(i == excludedRowIndex)
     continue;
    var rowHeight = 0;
    for(var j = 0, cell; cell = row[j]; j++) {
     var cellOffsetHeight = cell.offsetHeight;
     if(cellOffsetHeight > rowHeight)
      rowHeight = cellOffsetHeight;
    }
    result += rowHeight;
   }
   return result;
  },
  getCellRowSpan: function(cell) {
   var rowSpan = 1;
   if(!this.isSingleColumnLayout)
    rowSpan = ASPxClientFormLayoutUtils.getCellRowSpan(cell, this.breakpointKey);
   return rowSpan;
  },
  ensureGroupBoxCellHeight: function() { }
 });
 var TableGroupLayoutHelper = ASPx.CreateClass(null, {
  constructor: function(formLayout) {
   this.formLayout = formLayout;
   this.areGroupsAligned = false;
   this.groupElementClassName = FormLayoutConsts.GROUP_SYSTEM_CLASS_NAME;
  },
  RecalculateLayout: function() {
   this.ensureGroupsLayout();
   this.ensureCaptionsAlignment();
  },
  ensureCaptionsAlignment: function() {
   if(this.AreCaptionsAligned())
    return;
   var mainElement = this.formLayout.GetMainElement();
   this.formLayout.alignGroupsInContainer(mainElement);
  },
  ensureGroupsLayout: function() {
   var groups = this.getSortedVisibleGroups();
   for(var i = 0; i < groups.length; i++) {
    var groupInfo = this.getGroupInfo(groups[i]);
    var resizingHandler = this.getResizingHandler(groupInfo);
    this.areGroupsAligned = resizingHandler.EnsureCellsLayout(groupInfo) && this.areGroupsAligned;
   }
  },
  getSortedVisibleGroups: function() {
   var result = this.getVisibleGroups();
   return result.sort(function(a, b) {
    var predicate = function(node) { return node.id; };
    var aContainer = ASPx.GetParent(a, predicate);
    var bContainer = ASPx.GetParent(b, predicate);
    var aDepth = aContainer.id.split(FormLayoutConsts.ITEM_PATH_SEPARATOR).length;
    var bDepth = bContainer.id.split(FormLayoutConsts.ITEM_PATH_SEPARATOR).length;
    return bDepth - aDepth;
   });
  },
  getVisibleGroups: function() {
   var mainElement = this.formLayout.GetMainElement();
   var groups = ASPxClientFormLayoutUtils.getElementNodesByClassName(mainElement, this.groupElementClassName, mainElement);
   return groups.filter(function(groupElement) { return ASPx.IsElementVisible(groupElement); });
  },
  getGroupInfo: function(group) {
   return { group: group };
  },
  getResizingHandler: function(groupInfo) {
   return new TableResizingHandler(this, this.formLayout.GetMainElement());
  },
  AreCaptionsAligned: function() { return this.areGroupsAligned; }
 });
 var AdaptiveGroupLayoutHelper = ASPx.CreateClass(TableGroupLayoutHelper, {
  constructor: function(formLayout) {
   this.constructor.prototype.constructor.call(this, formLayout);
   this.formLayoutOffsetWidth = 0;
   this.areGroupsAligned = true;
   this.isSingleColumnLayout = null;
   this.groupElementClassName = FormLayoutConsts.GROUP_CONTAINER_SYSTEM_CLASS_NAME;
  },
  RecalculateLayout: function(force) {
   this.prepareHelperState(force);
   TableGroupLayoutHelper.prototype.RecalculateLayout.call(this);
  },
  prepareHelperState: function(force) {
   this.formLayoutOffsetWidth = this.formLayout.GetMainElement().offsetWidth;
   this.force = force;
   this.isSingleColumnLayout = null;
   this.areGroupsAligned = true;
  },
  getResizingHandler: function(groupInfo) {
   var layoutChangeType = this.getLayoutChangeType(groupInfo);
   var mainElement = this.formLayout.GetMainElement();
   switch(layoutChangeType) {
    case LayoutChangeType.SingleColumn:
     return new SingleColumnResizingHandler(this, mainElement);
    case LayoutChangeType.Breakpoint:
     return new BreakpointResizingHandler(this, mainElement);
    default:
     return new RegularResizingHandler(this, mainElement);
   }
  },
  getLayoutChangeType: function(groupInfo) {
   var result = LayoutChangeType.None;
   if(this.force || this.isBreakpointChanged(groupInfo)) {
    if(this.IsSingleColumnLayout())
     result = LayoutChangeType.SingleColumn;
    else
     result = LayoutChangeType.Breakpoint;
   }
   return result;
  },
  getSortedVisibleGroups: function() {
   var result = this.getVisibleGroups();
   return result.sort(function(a, b) {
    var aDepth = a.id.split(FormLayoutConsts.ITEM_PATH_SEPARATOR).length;
    var bDepth = b.id.split(FormLayoutConsts.ITEM_PATH_SEPARATOR).length;
    return bDepth - aDepth;
   });
  },
  getGroupInfo: function(group) {
   var breakpointInfo = ASPxClientFormLayoutUtils.getBreakpointInfo(group, this.formLayoutOffsetWidth);
   var requiredColumnCount = this.getRequiredColumnCount(group, breakpointInfo);
   return {
    group: group,
    breakpointInfo: breakpointInfo,
    requiredColumnCount: requiredColumnCount
   };
  },
  isBreakpointChanged: function(groupInfo) {
   var currentBreakpoint = ASPxClientFormLayoutUtils.getCurrentBreakpoint(groupInfo.group);
   if(this.IsSingleColumnLayout() && currentBreakpoint == FormLayoutConsts.SINGLE_COLUMN_BREAKPOINT_NAME)
    return false;
   return currentBreakpoint !== this.getRequiredBreakpoint(groupInfo);
  },
  getRequiredBreakpoint: function(groupInfo) {
   if(this.IsSingleColumnLayout())
    return FormLayoutConsts.SINGLE_COLUMN_BREAKPOINT_NAME;
   return groupInfo.breakpointInfo.breakpointKey;
  },
  IsSingleColumnLayout: function() {
   if(this.isSingleColumnLayout === null)
    this.isSingleColumnLayout = ASPx.GetCurrentDocumentWidth() <= this.formLayout.switchToSingleColumnAtWindowInnerWidth;
   return this.isSingleColumnLayout;
  },
  getRequiredColumnCount: function(group, breakpointInfo) {
   var result = 1;
   if(this.IsSingleColumnLayout())
    return result;
   if(breakpointInfo.breakpoint) {
    var colCountIndex = 2;
    result = breakpointInfo.breakpoint[colCountIndex];
   } else
    result = ASPxClientFormLayoutUtils.getGroupCurrentColCount(group);
   return result;
  }
 });
 var TableResizingHandler = ASPx.CreateClass(null, {
  constructor: function(groupHelper, mainElement) {
   this.heightHelper = null;
   this.groupHelper = groupHelper;
   this.classHelper = new ApplyEdgeClassHelper();
   this.mainElement = mainElement;
   this.group = null;
   this.groupCells = null;
   this.areGroupsAligned = false;
  },
  EnsureCellsLayout: function(groupInfo) {
   this.prepareHelperState(groupInfo);
   this.ensureCaptionLocation();
   this.adjustCellContainers();
   return this.areGroupsAligned;
  },
  prepareHelperState: function(groupInfo) {
   this.group = groupInfo.group;
   this.groupCells = this.getGroupCells();
   this.requiredColumnCount = groupInfo.requiredColumnCount;
  },
  getGroupCells: function() {
   var result = [];
   for(var i = 0, row; row = this.group.rows[i]; i++)
    result = result.concat(Array.prototype.slice.call(row.cells));
   return result;
  },
  adjustCellContainers: function() {
   if(!this.groupCells)
    return;
   this.groupCells = this.groupCells.filter(function(cell) {
    return ASPx.GetElementDisplay(cell);
   });
   this.adjustCellContainersCore(this.groupCells.length);
   this.applyEdgeClassesAndFullHeight();
  },
  applyEdgeClassesAndFullHeight: function() {
   var cellsRects = [];
   if(this.groupCells.length > 1)
    cellsRects = this.getCellsClientRects();
   this.classHelper.ApplyEdgeTopClass(this.groupCells, cellsRects);
   this.classHelper.ApplyEdgeLeftClass(this.groupCells, cellsRects);
   this.classHelper.ApplyEdgeRightClass(this.groupCells, cellsRects);
   this.classHelper.ApplyLastGroupItemClass(this.groupCells);
   this.applyEdgeBottomClassAndFullHeight(cellsRects);
  },
  applyEdgeBottomClassAndFullHeight: function(cellsRects) {
   this.classHelper.ApplyEdgeBottomClass(this.groupCells, cellsRects);
   this.SetCellsFullHeight();
  },
  SetCellsFullHeight: function() {
   this.getHeightHelper().SetCellsFullHeight(this.getCellsInfo());
  },
  getCellsClientRects: function() {
   var result = [];
   for(var i = 0; i < this.groupCells.length; i++) {
    var groupCell = this.groupCells[i];
    var clientRect = groupCell.getBoundingClientRect();
    result.push(clientRect);
    ASPx.Attr.SetAttribute(groupCell, "data-left", clientRect.left);
   }
   return result;
  },
  getCellsInfo: function() {
   return {
    cells: this.groupCells,
    rows: this.group.rows
   };
  },
  getHeightHelper: function() {
   if(!this.heightHelper)
    this.heightHelper = this.getHeightHelperCore();
   return this.heightHelper;
  },
  getHeightHelperCore: function() {
   return new FullHeightTableItemHelper(this.mainElement);
  },
  adjustCellContainersCore: function() {
   var groupCellsLength = this.groupCells.length;
   for(var i = 0; i < groupCellsLength; i++)
    this.removeElementClassNames(this.groupCells[i]);
  },
  removeElementClassNames: function(cellContainer) {
   this.classHelper.RemoveElementClassNames(cellContainer);
  },
  ensureCaptionLocation: function() { }
 });
 var RegularResizingHandler = ASPx.CreateClass(TableResizingHandler, {
  constructor: function(groupHelper, mainElement) {
   this.constructor.prototype.constructor.call(this, groupHelper, mainElement);
   this.breakpointInfo = ASPxClientFormLayoutUtils.getDefaultBreakpointInfo();
   this.rows = [];
   this.cellsWidth = [];
   this.rowLastCellIndices = [];
   this.busyWidthIntervals = [];
   this.isStretchLastItem = null;
   this.requiredColumnCount = 0;
   this.areGroupsAligned = true;
  },
  EnsureCellsLayout: function(groupInfo) {
   this.areGroupsAligned = TableResizingHandler.prototype.EnsureCellsLayout.call(this, groupInfo) && this.areGroupsAligned;
   this.setCurrentBreakpoint();
   return this.areGroupsAligned;
  },
  prepareHelperState: function(groupInfo) {
   this.isStretchLastItem = null;
   this.breakpointInfo = groupInfo.breakpointInfo;
   TableResizingHandler.prototype.prepareHelperState.call(this, groupInfo);
  },
  ensureCaptionLocation: function() {
   var verticalCaptionPositionWidth = this.GetVerticalCaptionPositionWidth();
   var isSingleColumnLayout = this.groupHelper.IsSingleColumnLayout();
   var isVerticalCaptionsCurrentState = this.IsVerticalCaptionsCurrentState();
   var formLayoutWidth = this.groupHelper.formLayoutOffsetWidth;
   var isVerticalPositionRequired = formLayoutWidth < verticalCaptionPositionWidth;
   if((isVerticalPositionRequired || isSingleColumnLayout) && !isVerticalCaptionsCurrentState)
    this.SetVerticalItemCaptionsState(true);
   else if((!isVerticalPositionRequired && !isSingleColumnLayout) && isVerticalCaptionsCurrentState)
    this.SetVerticalItemCaptionsState(false);
  },
  GetVerticalCaptionPositionWidth: function() {
   var result = parseInt(ASPx.Attr.GetAttribute(this.group, "data-wrapCaption"));
   if(isNaN(result))
    result = -1;
   return result;
  },
  IsVerticalCaptionsCurrentState: function() {
   var groupContainer = this.GetGroupContainer();
   if(groupContainer)
    return !!ASPx.Attr.GetAttribute(groupContainer, "data-itemVertCaptions");
  },
  IsStretchLastItem: function() {
   if(this.isStretchLastItem === null)
    this.isStretchLastItem = !!ASPx.Attr.GetAttribute(this.group, "data-stretchLastItem");
   return this.isStretchLastItem;
  },
  setCurrentBreakpoint: function() {
   var attribute = this.breakpointInfo.breakpointKey;
   if(this.groupHelper.IsSingleColumnLayout())
    attribute = FormLayoutConsts.SINGLE_COLUMN_BREAKPOINT_NAME;
   if(attribute != ASPxClientFormLayoutUtils.getCurrentBreakpoint(this.group))
    ASPx.Attr.SetAttribute(this.group, "data-currentBreakpoint", attribute);
  },
  adjustCellContainersCore: function(count) {
   for(var i = 0; i < count; i++)
    this.adjustCellContainer(i);
  },
  applyEdgeClassesAndFullHeight: function() {
   this.SetCellsFullHeight();
  },
  getCellsInfo: function() {
   return {
    breakpointKey: this.breakpointInfo.breakpointKey,
    cells: this.groupCells,
    rowLastCellIndices: this.rowLastCellIndices,
    rows: this.rows
   };
  },
  adjustCellContainer: function(index) {
   var cellContainer = this.groupCells[index];
   this.removeElementClassNames(cellContainer);
   this.getHeightHelper().resetInlineHeight(cellContainer);
   if(!this.groupHelper.IsSingleColumnLayout())
    this.adjustCellContainerCore(index);
   else 
    this.prepareSingleColumnCellsInfo();
  },
  removeElementClassNames: function(cellContainer) { },
  prepareSingleColumnCellsInfo: function() {
   this.rows = this.groupCells.map(function(cell) { return [cell]; });
   for(var i = 0; i < this.groupCells.length; i++)
    this.rowLastCellIndices.push(i);
  },
  adjustCellContainerCore: function(index) {
   var cellContainer = this.groupCells[index];
   if(this.IsFirstCellInRow(index))
    this.onPrepareFirstCellInRow(cellContainer);
   this.onSetGroupCellWidth(index);
   if(this.IsLastCellInRow(index))
    this.onPrepareLastCellInRow(index);
  },
  onPrepareLastCellInRow: function(index) {
   this.rowLastCellIndices.push(index);
  },
  onSetGroupCellWidth: function(index) {
   var cellContainer = this.groupCells[index];
   var cellWidth = this.getGroupCellWidth(index);
   var marginLeft = this.getMarginLeft(index, cellWidth);
   this.setCellStyleProperties(cellContainer, cellWidth, marginLeft);
   this.CacheCellInfo(cellContainer, cellWidth + marginLeft);
   this.prepareBusyWidthIntervals(index, cellWidth, marginLeft);
  },
  setCellStyleProperties: function(cellContainer, cellWidth, marginLeft) { },
  prepareBusyWidthIntervals: function(index, cellWidth, marginLeft) {
   var cellContainer = this.groupCells[index];
   var rowSpan = ASPxClientFormLayoutUtils.getCellRowSpan(cellContainer, this.breakpointInfo.breakpointKey);
   if(rowSpan > 1) {
    var rowWidth = this.GetRowWidth(index - 1) + marginLeft;
    this.addBusyWidthInterval(index, rowSpan, rowWidth, cellWidth);
   }
  },
  getMarginLeft: function(index, cellWidth) {
   var result = 0;
   var busyWidthIntervals = this.getbusyWidthIntervals(index);
   if(!busyWidthIntervals)
    return result;
   var rowWidth = this.GetRowWidth(index);
   for(var i = 0; i < busyWidthIntervals.length; i++) {
    var busyWidthInterval = busyWidthIntervals[i];
    result = this.getMarginLeftCore(busyWidthInterval, rowWidth, cellWidth, result);
   }
   return result;
  },
  getMarginLeftCore: function(busyWidthInterval, rowWidth, cellWidth, result) {
   var beginCellWidth = rowWidth;
   var endCellWidth = beginCellWidth + cellWidth;
   var beginBusyWidth = busyWidthInterval[0];
   var endBusyWidth = beginBusyWidth + busyWidthInterval[1];
   while(beginCellWidth + result <= beginBusyWidth && endCellWidth + result > beginBusyWidth ||
      beginCellWidth + result >= beginBusyWidth && endCellWidth + result <= endBusyWidth ||
      beginCellWidth + result < endBusyWidth && endCellWidth + result > endBusyWidth)
    result = endBusyWidth - rowWidth;
   return result;
  },
  getGroupCellWidth: function(index) {
   if(this.cellsWidth[index] !== undefined)
    return this.cellsWidth[index];
   var cellContainer = this.groupCells[index];
   var colSpan = ASPxClientFormLayoutUtils.getCellColSpan(cellContainer, this.breakpointInfo.breakpointKey);
   if(colSpan > this.requiredColumnCount)
    colSpan = this.requiredColumnCount;
   var result = colSpan * 100 / this.requiredColumnCount;
   if(this.IsLastCellInGroup(index) && colSpan == 1 && this.IsStretchLastItem())
    result = this.GetStretchedLastItemWidth();
   return result;
  },
  addBusyWidthInterval: function(index, rowSpan, rowWidth, width) {
   var rowIndex = this.getRowIndexByCellIndex(index);
   for(var i = rowIndex + 1; i < rowIndex + rowSpan; i++) {
    var busyWidthInterval = [rowWidth, width];
    var currentRowIndex = i.toString();
    if(!this.busyWidthIntervals[currentRowIndex])
     this.busyWidthIntervals[currentRowIndex] = [];
    this.busyWidthIntervals[currentRowIndex].push(busyWidthInterval);
   }
  },
  IsFirstCellInRow: function(index) {
   return index === this.GetRowLastCellIndex(index) + 1;
  },
  IsLastCellInRow: function(index) {
   if(this.IsLastCellInGroup(index))
    return true;
   var currentRowWidth = this.GetRowWidth(index);
   var nextItemWidth = this.getGroupCellWidth(index + 1);
   var fullNextItemWidth = nextItemWidth + this.getMarginLeft(index + 1, nextItemWidth, true);
   return Math.floor(currentRowWidth + fullNextItemWidth) > 100;
  },
  IsLastCellInGroup: function(index) {
   return index == this.groupCells.length - 1;
  },
  GetRowWidth: function(index) {
   var result = 0;
   var lastEndRowCellIndex = this.GetRowLastCellIndex(index);
   for(var i = index; i > lastEndRowCellIndex; i--)
    if(this.cellsWidth[i])
     result += this.cellsWidth[i];
   return result;
  },
  GetRowLastCellIndex: function(index) {
   var lastEndRowCellIndex = -1;
   for(var i = this.rowLastCellIndices.length - 1; i >= 0; i--) {
    var lastCellIndex = this.rowLastCellIndices[i];
    if(index >= lastCellIndex) {
     lastEndRowCellIndex = lastCellIndex;
     break;
    }
   }
   return lastEndRowCellIndex;
  },
  GetStretchedLastItemWidth: function() {
   var cellIndex = this.groupCells.length - 1;
   var previousItemWidth = this.GetRowWidth(cellIndex);
   var endWidth = 100;
   var busyWidthIntervals = this.getbusyWidthIntervals(cellIndex);
   if(busyWidthIntervals) {
    for(var i = 0; i < busyWidthIntervals.length; i++) {
     var busyWidthInterval = busyWidthIntervals[i];
     var beginBusyWidth = busyWidthInterval[0];
     var endBusyWidth = busyWidthInterval[0] + busyWidthInterval[1];
     if(endWidth > beginBusyWidth && previousItemWidth < beginBusyWidth)
      endWidth = beginBusyWidth;
     if(previousItemWidth >= beginBusyWidth && previousItemWidth < endBusyWidth)
      previousItemWidth = endBusyWidth;
    }
   }
   return endWidth - previousItemWidth % 100;
  },
  getbusyWidthIntervals: function(cellIndex) {
   var rowIndex = this.getRowIndexByCellIndex(cellIndex);
   var busyWidthIntervals = this.busyWidthIntervals[rowIndex];
   return busyWidthIntervals && busyWidthIntervals.sort(function(a, b) {
    return a[0] - b[0];
   });
  },
  onPrepareFirstCellInRow: function(cellContainer) {
   this.rows.push([]);
   ASPx.AddClassNameToElement(cellContainer, FormLayoutConsts.NOT_FLOATED_ELEMENT_SYSTEM_CLASS_NAME);
  },
  CacheCellInfo: function(cellContainer, width) {
   this.cellsWidth.push(width);
   this.rows[this.rows.length - 1].push(cellContainer);
  },
  SetVerticalItemCaptionsState: function(enabled) {
   var groupContainer = this.GetGroupContainer();
   this.groupHelper.formLayout.UpdateItemsCssClasses(enabled);
   if(!groupContainer)
    return;
   if(enabled)
    ASPx.Attr.SetAttribute(groupContainer, "data-itemVertCaptions", true);
   else
    ASPx.Attr.RemoveAttribute(groupContainer, "data-itemVertCaptions");
   var changeClassNameMethod = enabled ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
   var groupChildLayoutItemElements = this.GetGroupChildLayoutItemElements();
   for(var i = 0; i < groupChildLayoutItemElements.length; i++)
    changeClassNameMethod(groupChildLayoutItemElements[i], FormLayoutConsts.ITEM_IN_ADAPTIVE_VIEW);
   this.updateItemCaptionsClassNames(enabled, groupChildLayoutItemElements);
   this.updateHelpTextClassNames(enabled);
   this.areGroupsAligned = false;
  },
  getGroupCells: function() {
   var result = null;
   var groupContainer = this.GetGroupContainer();
   if(groupContainer)
    result = ASPx.GetChildNodesByTagName(groupContainer, "DIV");
   return result;
  },
  GetGroupContainer: function() {
   var isRootGroup = ASPx.Attr.GetAttribute(this.group, "data-groupID");
   return isRootGroup ? this.group : this.GetGroupContainerCore();
  },
  GetGroupContainerCore: function() {
   var nestedGroups = Array.prototype.slice.call(this.group.querySelectorAll("[data-groupID]"));
   var mainElement = this.group;
   return nestedGroups.filter(function(el) { 
    return !ASPxClientFormLayoutUtils.isElementContainedInNestedItem(el, mainElement);
   })[0];
  },
  GetGroupChildLayoutItemElements: function() {
   if(!this.groupToChildLayoutItemElementsMap)
    this.groupToChildLayoutItemElementsMap = {};
   if(!ASPx.IsExists(this.groupToChildLayoutItemElementsMap[ASPx.Attr.GetAttribute(this.group, "data-groupID")])) {
    var layoutItemElementsWithHorizontalCaptions = this.groupHelper.formLayout.GetLayoutItemElementsWithHorizontalCaptions();
    var groupChildLayoutItemElementsWithHorizontalCaptions = [];
    for(var i = 0; i < layoutItemElementsWithHorizontalCaptions.length; i++) {
     var layoutItemWithHorCaption = layoutItemElementsWithHorizontalCaptions[i];
     if(ASPx.GetParentByClassName(layoutItemWithHorCaption, FormLayoutConsts.GROUP_CONTAINER_SYSTEM_CLASS_NAME) == this.group
      && !ASPx.Attr.GetAttribute(layoutItemWithHorCaption, "data-fixedCaptionLocation"))
      groupChildLayoutItemElementsWithHorizontalCaptions.push(layoutItemWithHorCaption);
    }
    this.groupToChildLayoutItemElementsMap[ASPx.Attr.GetAttribute(this.group, "data-groupID")] = groupChildLayoutItemElementsWithHorizontalCaptions;
   }
   return this.groupToChildLayoutItemElementsMap[ASPx.Attr.GetAttribute(this.group, "data-groupID")];
  },
  getRowIndexByCellIndex: function(index) {
   return ASPxClientFormLayoutUtils.getRowIndexByCellIndex(index, this.rowLastCellIndices);
  },
  getHeightHelperCore: function() {
   return new FullHeightAdaptiveItemHelper(this.mainElement);
  },
  updateItemCaptionsClassNames: function(fromHorizontalToVertical, itemElements) {
   var targetItemElements = itemElements || this.groupHelper.formLayout.GetLayoutItemElementsWithHorizontalCaptions();
   var oldClasses = fromHorizontalToVertical ? FormLayoutHorizontalCaptionsCssClasses : FormLayoutVerticalCaptionsCssClasses;
   var newClasses = fromHorizontalToVertical ? FormLayoutVerticalCaptionsCssClasses : FormLayoutHorizontalCaptionsCssClasses;
   this.updateElementsCssClasses(targetItemElements, oldClasses, newClasses);
  },
  updateHelpTextClassNames: function(fromHorizontalToVertical) {
   var targetItemElements = this.groupHelper.formLayout.GetHorizontalHelpTextElements();
   var oldClasses = fromHorizontalToVertical ? FormLayoutHorizontalHelpTextsCssClasses : FormLayoutVerticalHelpTextsCssClasses;
   var newClasses = fromHorizontalToVertical ? FormLayoutVerticalHelpTextsCssClasses : FormLayoutHorizontalHelpTextsCssClasses;
   this.updateElementsCssClasses(targetItemElements, oldClasses, newClasses);
  },
  updateElementsCssClasses: function (elements, oldCssClasses, newCssClasses) {
   for(var i = 0; i < elements.length; i++) {
    for(var j = 0; j < oldCssClasses.length; j++)
     elements[i].className = elements[i].className.replace(oldCssClasses[j], newCssClasses[j]);
   }
  }
 });
 var SingleColumnResizingHandler = ASPx.CreateClass(RegularResizingHandler, {
  constructor: function(groupHelper, mainElement) {
   this.constructor.prototype.constructor.call(this, groupHelper, mainElement);
   this.areGroupsAligned = false;
  },
  applyEdgeClassesAndFullHeight: function() {
   TableResizingHandler.prototype.applyEdgeClassesAndFullHeight.call(this);
  },
  adjustCellContainer: function(index) {
   var cellContainer = this.groupCells[index];
   this.getHeightHelper().resetInlineMargins(cellContainer);
   this.resetCellInlineWidth(cellContainer);
   RegularResizingHandler.prototype.adjustCellContainer.call(this, index);
  },
  removeElementClassNames: function(cellContainer) {
   TableResizingHandler.prototype.removeElementClassNames.call(this, cellContainer);
  },
  resetCellInlineWidth: function(cellContainer) {
   this.getHeightHelper().resetInlineWidth(cellContainer);
  }
 });
 var BreakpointResizingHandler = ASPx.CreateClass(SingleColumnResizingHandler, {
  constructor: function(groupHelper, mainElement) {
   this.constructor.prototype.constructor.call(this, groupHelper, mainElement);
  },
  setCellStyleProperties: function(cellContainer, cellWidth, marginLeft) {
   cellContainer.style.width = cellWidth + "%";
   cellContainer.style.marginLeft = marginLeft + "%";
  },
  resetCellInlineWidth: function(cellContainer) { },
  applyEdgeBottomClassAndFullHeight: function() {
   RegularResizingHandler.prototype.applyEdgeClassesAndFullHeight.call(this);
   this.classHelper.ApplyEdgeBottomClass(this.groupCells, this.getCellsClientRects());
  },
  getMarginLeft: function(index, cellWidth, isNextCell) {
   var result = SingleColumnResizingHandler.prototype.getMarginLeft.call(this, index, cellWidth);
   var isWrongLayout = !isNextCell && Math.floor(result + cellWidth) > 100;
   if(isWrongLayout) {
    try {
     this.tryCorrectWrongLayout(index);
     result = this.getMarginLeft(index, cellWidth, isNextCell);
    }
    catch(e) {
     var errorMessage = "A FormLayout's item has an incorrect RowSpan property value that cannot be corrected automatically. For detailed information, refer to http://www.devexpress.com/bcid=BC4454.";
     throw new Error(errorMessage);
    }
   }
   return result;
  },
  recalculateCellsLayout: function(count) {
   this.rows = [];
   this.cellsWidth = [];
   this.rowLastCellIndices = [];
   this.busyWidthIntervals = [];
   this.adjustCellContainersCore(count);
   this.rows.push([]);
  },
  tryCorrectWrongLayout: function(index) {
   this.decreaseRowSpan(index);
   this.recalculateCellsLayout(index);
  },
  decreaseRowSpan: function(index) {
   var currentRowIndex = ASPxClientFormLayoutUtils.getRowIndexByCellIndex(index, this.rowLastCellIndices);
   for(var i = 0; i < index; i++) {
    var container = this.groupCells[i];
    var rowSpan = ASPxClientFormLayoutUtils.getCellRowSpan(container, this.breakpointInfo.breakpointKey);
    var rowIndex = ASPxClientFormLayoutUtils.getRowIndexByCellIndex(i, this.rowLastCellIndices);
    var occupiedRowSpan = rowIndex + rowSpan - currentRowIndex;
    if(rowIndex !== currentRowIndex && occupiedRowSpan > 0)
     this.decreaseRowSpanCore(container);
   }
  },
  decreaseRowSpanCore: function(cellContainer) {
   var spanRules = ASPxClientFormLayoutUtils.getCellSpanRules(cellContainer);
   var key = this.breakpointInfo.breakpointKey;
   var areSpanRulesExist = spanRules && spanRules[key];
   if(areSpanRulesExist) {
    spanRules[key][1]--;
    ASPx.Attr.SetAttribute(cellContainer, "data-spanRules", JSON.stringify(spanRules));
   } else {
    var currentRowSpan = ASPxClientFormLayoutUtils.getCellRowSpan(cellContainer);
    ASPx.Attr.SetAttribute(cellContainer, "data-rowSpan", currentRowSpan - 1);
   }
  }
 });
 var AlignCaptionBaseStrategy = ASPx.CreateClass(null, {
  constructor: function(formLayout) {
   this.formLayout = formLayout;
   this.leftAndRightCaptionsWidth = formLayout.leftAndRightCaptionsWidth;
   this.alignItemCaptionsInAllGroups = formLayout.alignItemCaptionsInAllGroups;
   this.rtl = formLayout.rtl;
   this.firstCaptionElement = null;
   this.firstCaptionElementOffsetWidth = 0;
  },
  AlignGroups: function(groupContainer) {
   if(this.leftAndRightCaptionsWidth === 0) {
    var groupElements = this.getGroupElements(groupContainer);
    if(this.alignItemCaptionsInAllGroups)
     this.alignGroupsTogether(groupElements);
    else
     this.alignGroupsSeparately(groupElements);
   }
   else
    this.alignLeftAndRightCaptionsIdentically(groupContainer);
  },
  getGroupElements: function(parent) {
   return ASPxClientFormLayoutUtils.getElementNodesByClassName(parent,
    FormLayoutConsts.ALIGNED_GROUP_SYSTEM_CLASS_NAME,
    this.formLayout.GetMainElement());
  },
  alignLeftAndRightCaptionsIdentically: function(groupContainer) {
   var captionCells = ASPxClientFormLayoutUtils.getElementNodesByClassName(groupContainer,
    FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME,
    this.formLayout.GetMainElement());
   for(var i = 0; i < captionCells.length; i++)
    if(this.isLeftOrRigthCaption(captionCells[i]))
     this.setCaptionCellWidth(captionCells[i], this.leftAndRightCaptionsWidth);
  },
  isLeftOrRigthCaption: function(captionCell) {
   var itemElement = ASPx.GetParentByClassName(captionCell, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
   return this.formLayout.itemHasHorizontalCaption(itemElement);
  },
  setCaptionCellWidth: function(captionCellElement, width) {
   var captionCellPaddings = ASPx.GetLeftRightBordersAndPaddingsSummaryValue(captionCellElement);
   ASPx.SetOffsetWidth(captionCellElement, width + captionCellPaddings);
   captionCellElement.style.minWidth = this.getCaptionMinWidth(captionCellElement, width) + "px";
   if(!this.formLayout.isFinallyInitialized && !ASPx.IsExists(this.firstCaptionElementOffsetWidth)) {
    var firstCaptionElement = ASPx.GetChildByPartialClassName(captionCellElement, FormLayoutConsts.LAYOUT_ITEM_CAPTION_PARTIAL_CLASS_NAME);
    if(firstCaptionElement) {
     this.firstCaptionElementOffsetWidth = firstCaptionElement.offsetWidth;
     this.firstCaptionElement = firstCaptionElement;
    }
   }
  },
  getCaptionMinWidth: function(captionCell, width) {
   var result = width;
   var groupElement = this.getParentGroupElement(captionCell);
   var isVerticalCaptions = ASPx.Attr.GetAttribute(groupElement, "data-itemVertCaptions");
   if(isVerticalCaptions) {
    var itemElement = ASPx.GetParentByClassName(captionCell, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
    var isFixedCaptionLocation = ASPx.Attr.GetAttribute(itemElement, "data-fixedCaptionLocation");
    if(!isFixedCaptionLocation)
     result = 0;
   }
   return result;
  },
  getParentGroupElement: function(element) {
   return ASPx.GetParentByClassName(element, FormLayoutConsts.GROUP_SYSTEM_CLASS_NAME);
  },
  alignGroupsSeparately: function(groupElements) {
   for(var i = 0; i < groupElements.length; i++)
    this.alignGroup(groupElements[i]);
  },
  alignGroupColumnCaptionCellWidths: function(cellElements) {
   var maxCaptionCellWidth = this.getGroupCellsMaxWidth(cellElements);
   this.setGroupCellsWidth(cellElements, maxCaptionCellWidth);
  },
  getGroupCellsMaxWidth: function(cellElements) {
   var maxCaptionWidth = 0;
   var captionCellWithMaxCaption = null;
   for(var i = 0; i < cellElements.length; i++) {
    var captionInfo = this.getGroupCellCaptionInfo(cellElements[i]);
    if(captionInfo && maxCaptionWidth < captionInfo.captionWidth) {
     maxCaptionWidth = captionInfo.captionWidth;
     captionCellWithMaxCaption = captionInfo.captionCell;
    }
   }
   if(captionCellWithMaxCaption) {
    this.setCaptionCellWidth(captionCellWithMaxCaption, maxCaptionWidth);
    var captionCellWidth = ASPx.GetClearClientWidth(captionCellWithMaxCaption);
    return Math.max(captionCellWidth, maxCaptionWidth);
   }
   return maxCaptionWidth;
  },
  getGroupCellCaptionInfo: function(groupCellElement) {
   if(groupCellElement) {
    var captionCellElement = this.getGroupCellCaptionElement(groupCellElement);
    if(captionCellElement)
     return {
      captionCell: captionCellElement,
      captionWidth: this.getCaptionCellChildrenWidth(captionCellElement)
     };
   }
   return null;
  },
  getGroupCellCaptionElement: function(groupCellElement) {
   var itemElement = this.getChildItemElement(groupCellElement);
   if(itemElement == null)
    return null;
   return this.getFormLayoutElementNodeByClassName(itemElement, FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME);
  },
  getChildItemElement: function(groupCellElement) {
   var childTabbedGroupElement = null;
   if(this.alignItemCaptionsInAllGroups)
    childTabbedGroupElement = ASPx.GetChildByClassName(groupCellElement, FormLayoutConsts.TABBED_GROUP_SYSTEM_CLASS_NAME);
   return childTabbedGroupElement ? this.formLayout.findTabbedGroupChildItemElement(childTabbedGroupElement) :
    ASPx.GetChildByClassName(groupCellElement, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
  },
  setGroupCellsWidth: function(cellElements, captionCellWidth) {
   for(var i = 0; i < cellElements.length; i++)
    this.setGroupCellCaptionElementWidth(cellElements[i], captionCellWidth);
  },
  setGroupCellCaptionElementWidth: function(groupCellElement, width) {
   if(groupCellElement) {
    var captionCellElement = this.getGroupCellCaptionElement(groupCellElement);
    if(captionCellElement)
     this.setCaptionCellWidth(captionCellElement, width);
   }
  },
  getFormLayoutElementNodeByClassName: function(parent, className, index) {
   var mainElement =  this.formLayout.GetMainElement();
   var nodes = ASPxClientFormLayoutUtils.getElementNodesByClassName(parent, className, mainElement);
   if(!index) index = 0;
   return nodes.length > index ? nodes[index] : null;
  },
  getCaptionCellChildrenWidth: function(captionCellElement) {
   var result = 0;
   for(var i = 0; i < captionCellElement.childNodes.length; i++)
    if(captionCellElement.childNodes[i].offsetWidth)
     result += captionCellElement.childNodes[i].offsetWidth;
   if(result)
    return result;
  },
  needAlignCaptionCells: function() {
   return this.firstCaptionElement && this.firstCaptionElement.offsetWidth !== this.firstCaptionElementOffsetWidth;
  }
 });
 var AlignCaptionByOffsetStrategy = ASPx.CreateClass(AlignCaptionBaseStrategy, {
  constructor: function(formLayout) {
   this.constructor.prototype.constructor.call(this, formLayout);
  },
  alignGroupsTogether: function(groupElements) {
   var containerElements = [];
   for(var i = 0; i < groupElements.length; i++) {
    var elementsToAlign = this.getElementsToAlign(groupElements[i]);
    containerElements = containerElements.concat(elementsToAlign);
   } 
   this.alignElements(containerElements, null);
  },
  alignGroup: function(groupElement) {
   var containerElements = this.getElementsToAlign(groupElement);
   this.alignElements(containerElements);
  },
  alignElements: function(elements) {
   var columnStartOffsets = this.getUniqueStartOffsets(elements);
   var sameColumnElements = [];
   for(var i = 0; i < columnStartOffsets.length; i++)
    sameColumnElements.push(this.getSameColumnElements(elements, columnStartOffsets[i]));
   for(var i = 0; i < sameColumnElements.length; i++)
    this.alignGroupColumnCaptionCellWidths(sameColumnElements[i]);
  },
  getElementsToAlign: function(groupElement) {
   var isVerticalCaptionLocation = ASPx.Attr.GetAttribute(groupElement, "data-itemVertCaptions");
   var groupChildElements = this.getGroupChildElements(groupElement);
   var result = [];
   if(isVerticalCaptionLocation) {
    for(var i = 0; i < groupChildElements.length; i++) {
     var groupChildElement = groupChildElements[i];
     var container = ASPxClientFormLayoutUtils.getChildDivAtNestedLevel(groupChildElement, 2);
     if(container && ASPx.Attr.GetAttribute(container, "data-fixedCaptionLocation"))
      result.push(groupChildElement);
    }
   } else
    result = groupChildElements.filter(function(c) { 
     return !ASPxClientFormLayoutUtils.getVerticalCaptionContainer(c); 
    });
   return result;
  },
  getGroupChildElements: function(groupElement) {
   return ASPx.GetChildNodesByTagName(groupElement, "DIV");
  },
  getSameColumnElements: function(elements, columnOffsetLeft) {
   var result = [];
   for(var i = 0; i < elements.length; i++) {
    var container = elements[i];
    var containerOffset = this.getItemElementStartOffset(container);
    var isSameColumn = Math.abs(columnOffsetLeft - containerOffset) < FormLayoutConsts.OFFSET_ERROR;
    if(isSameColumn) {
     var groupCellElement = this.getGroupCellElement(container);
     result.push(groupCellElement);
    }
   }
   return result;
  },
  getItemElementStartOffset: function(element) {
   var offset = ASPxClientFormLayoutUtils.getClientLeft(element);
   var parentGroupElement = this.getParentGroupElement(element);
   if(this.rtl)
    offset += ASPx.GetElementOffsetWidth(element) + this.getGroupItemRightIndents(parentGroupElement);
   else
    offset -= this.getGroupItemLeftIndents(parentGroupElement);
   return offset;
  },
  getGroupCellElement: function(container) {
   return ASPx.GetNodeByTagName(container, "DIV");
  },
  getGroupElementsTreeLine: function(groupElement) {
   var groupItems = [];
   var parent = groupElement;
   var mainElement = this.formLayout.GetMainElement();
   while(parent !== mainElement) {
    groupItems.push(parent);
    parent = parent.parentNode;
   }
   return groupItems;
  },
  getGroupItemLeftIndents: function(groupElement) {
   var result = 0;
   var parentGroups = this.getGroupElementsTreeLine(groupElement);
   for(var i = 0; i < parentGroups.length; i++) {
    var currentStyle = ASPx.GetCurrentStyle(parentGroups[i]);
    result += ASPx.PxToInt(currentStyle.paddingLeft) +
     ASPx.PxToInt(currentStyle.marginLeft) +
     ASPx.PxToInt(currentStyle.borderLeftWidth);
   }
   return result;
  },
  getGroupItemRightIndents: function(groupElement) {
   var result = 0;
   var parentGroups = this.getGroupElementsTreeLine(groupElement);
   for(var i = 0; i < parentGroups.length; i++) {
    var currentStyle = ASPx.GetCurrentStyle(parentGroups[i]);
    result += ASPx.PxToInt(currentStyle.paddingRight) +
     ASPx.PxToInt(currentStyle.marginRight) +
     ASPx.PxToInt(currentStyle.borderRightWidth);
   }
   return result;
  },
  getUniqueStartOffsets: function(elements) {
   var offsets = [];
   for(var i = 0; i < elements.length; i++)
    offsets.push(this.getItemElementStartOffset(elements[i]));
   function uniqueOffsets(value, index, self) { 
    var unique = true;
    for(var i = 0; i < index; i++) {
     var isSameColumn = Math.abs(self[i] - value) < FormLayoutConsts.OFFSET_ERROR;
     if(isSameColumn) {
      unique = false;
      break;
     }
    }
    return unique;
   }
   return offsets.filter(uniqueOffsets);
  }
 });
 var AlignTableLayoutCaptionByOffsetStrategy = ASPx.CreateClass(AlignCaptionByOffsetStrategy, {
  constructor: function(formLayout) {
   this.constructor.prototype.constructor.call(this, formLayout);
  },
  getGroupCellElement: function (container) {
   return container;
  },
  getGroupChildElements: function(groupElement) {
   var result = [];
   for(var i = 0; i < groupElement.rows.length; i++) {
    var cells = ASPx.GetChildNodesByTagName(groupElement.rows[i], "TD");
    result = result.concat(cells);
   }
   return result;
  }
 });
 var ASPxClientFormLayout = ASPx.CreateClass(ASPxClientControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.rootItem = null;
   this.needAdjust = true;
   this.forceAdjustOnShow = true;
   this.isFinallyInitialized = false;
   this.mainElementWidth = 0;
   this.updateLock = false;
   this.alignItemCaptionsInAllGroups = false;
   this.leftAndRightCaptionsWidth = 0;
   this.adaptivityMode = FormLayoutAdaptivityMode.Off;
   this.switchToSingleColumnAtWindowInnerWidth = 0;
   this.showItemCaptionColon = true;
   this.captionAssociatingItems = [];
   this.alignCaptionHelper = null;
   this.layoutHelper = null;
  },
  UpdateItemsCssClasses: function() { },
  SetData: function(data){
   if(data.items)
    this.CreateItems(data.items);
   if(this.accessibilityCompliant && data.captionAssociatingItems)
    this.captionAssociatingItems = data.captionAssociatingItems;
  },
  InlineInitialize: function() {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   this.InitializeEvents();
   this.EnsureCustomFontSizeClassName();
   this.InitializeNeedAdjustItemsContentOnShowing();
   this.UpdateHeadingLineGroupBoxElements();
   if(this.enabled)
    this.addHandlersToActiveTabChangedEvents();
   if(this.switchToSingleColumnAtWindowInnerWidth > 0)
    this.CreateAdaptivityCssRules();
   this.adjustTabbedGroupPageControls();
  },
  Initialize: function () {
   ASPxClientControl.prototype.Initialize.call(this);
   this.isFinallyInitialized = true;
   this.prepareNestedControls();
  },
  InitializeEvents: function() {
   if(this.adaptivityMode === FormLayoutAdaptivityMode.Breakpoints)
    this.InitializeResizeEvent();
  },
  AfterInitialize: function() {
   if(this.accessibilityCompliant && this.captionAssociatingItems)
    this.SetAccessibilityCaptionAssociating(this.captionAssociatingItems);
   ASPxClientControl.prototype.AfterInitialize.call(this);
  },
  prepareNestedControls: function(container) {
   this.getLayoutItemElements(container).forEach(function(itemElement) {
    var predicate = function(control) { return !!control.applyFormLayoutItemSettings || !!control.errorCellVisibilityChanged; };
    var nestedControls = this.getNestedControls(itemElement, predicate);
    nestedControls.forEach(function(control) { this.prepareNestedControl(control, itemElement); }.bind(this));
   }.bind(this));
  },
  prepareNestedControl: function(nestedControl, itemElement) {
   if(nestedControl.applyFormLayoutItemSettings) {
    var captionElement = this.getLayoutItemCaptionElement(itemElement);
    var helpTextElement = this.getLayoutItemHelpTextElement(itemElement);
    var caption = captionElement ? this.getItemCaptionInternal(captionElement) : "";
    nestedControl.applyFormLayoutItemSettings({
     caption: caption,
     helpText: helpTextElement ? ASPx.GetInnerText(helpTextElement) : null
    });
   }
   if(this.IsFlowRender() && nestedControl.errorCellVisibilityChanged) {
    var eventHandler = this.getErrorCellVisibilityChangedEventHandler();
    nestedControl.errorCellVisibilityChanged.AddHandler(eventHandler);
   }
  },
  getErrorCellVisibilityChangedEventHandler: function() {
   if(!this.errorCellVisibilityChangedEventHandler)
    this.errorCellVisibilityChangedEventHandler = function() {
     if(this.isErrorCellVisibilityChangedProcessingLocked)
      return;
     this.isErrorCellVisibilityChangedProcessingLocked = true;
     setTimeout(function() {
      this.AdjustControl();
      this.isErrorCellVisibilityChangedProcessingLocked = false;
     }.bind(this), errorCellVisibilityChangedProcessingDelay);
    }.bind(this);
   return this.errorCellVisibilityChangedEventHandler;
  },
  getNestedControls: function(layoutItemElement, predicate) {
   var controlTree = new ASPx.ControlTree(ASPx.GetControlCollection(), layoutItemElement,
    function(control) { return predicate(control); });
   return controlTree.rootNode.children.map(function(child) { return child.control; });
  },
  getNestedControlCell: function(layoutItem) { 
   var itemElementContainer = this.getItemElementContainer(layoutItem);
   if(this.IsFlowRender() && !itemElementContainer.id) 
    itemElementContainer = itemElementContainer.parentNode;
   return ASPxClientFormLayoutUtils.getItemNestedControlCell(itemElementContainer);
  },
  getLayoutItemElements: function(container) {
   var mainElement = this.GetMainElement();
   var itemsContainer = container || mainElement;
   return Array.prototype.slice.call(itemsContainer.querySelectorAll("." + FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME))
    .map(function(element) { return ASPx.GetParent(element, function(el) { return !!el.id; }); })
    .filter(function(element) {
     return !ASPxClientFormLayoutUtils.isElementContainedInNestedFormLayout(element, mainElement);
    });
  },
  GetAlignCaptionHelper: function() {
   if(!this.alignCaptionHelper)
    this.alignCaptionHelper = this.IsFlowRender() ? new AlignCaptionByOffsetStrategy(this) : new AlignTableLayoutCaptionByOffsetStrategy(this);
   return this.alignCaptionHelper;
  },
  InitializeResizeEvent: function() {
   var resizeInterval = 50;
   this.mainElementWidth = this.GetMainElement().getBoundingClientRect().width;
   ASPx.Timer.SetControlBoundInterval(function() {
    var currentWidth = this.GetMainElement().getBoundingClientRect().width;
    if(currentWidth !== this.mainElementWidth) {
     this.mainElementWidth = currentWidth;
     this.AdjustControlInternal();
    }
   }.aspxBind(this), this, resizeInterval);
  },
  EnsureCustomFontSizeClassName: function() {
   var mainElement = this.GetMainElement();
   if(mainElement.style.fontSize !== "")
    ASPx.AddClassNameToElement(mainElement, "dxflCustomFontSizeSys");
  },
  GetGroupLayoutHelper: function() {
   if(!this.layoutHelper)
    this.layoutHelper = this.GetGroupLayoutHelperCore();
   return this.layoutHelper;
  },
  GetGroupLayoutHelperCore: function() {
   if(this.adaptivityMode == FormLayoutAdaptivityMode.Off)
    return new TableGroupLayoutHelper(this);
   else
    return new AdaptiveGroupLayoutHelper(this);
  },
  IsFlowRender: function() {
   return this.adaptivityMode !== FormLayoutAdaptivityMode.Off;
  },
  CreateAdaptivityCssRules: function() {
   var styleSheet = ASPx.GetCurrentStyleSheet();
   if(!styleSheet || !styleSheet.insertRule) return;
   var rule = "@media all and (max-width: " + this.switchToSingleColumnAtWindowInnerWidth + "px) { " +
    this.getAdaptiveSelectorForContainer() + this.getAdaptiveContainerStyles() +
    this.getAdaptiveSelectorForCaptionCell() + this.getAdaptiveCaptionCellStyles() +
    "}";
   styleSheet.insertRule(rule, styleSheet.cssRules.length);
  },
  getAdaptiveSelectorForContainer: function () {
   return "#" + this.name + " ." + FormLayoutConsts.ELEMENT_CONTAINER_SYSTEM_CLASS_NAME + ":not[data-fixedCaptionLocation=\"True\"]" + " > div";
  },
  getAdaptiveSelectorForCaptionCell: function () {
   return "#" + this.name + " ." + FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME;
  },
  getAdaptiveContainerStyles: function () {
   return "{ width: 100%!important; min-width: 0!important; float: left; }";
  },
  getAdaptiveCaptionCellStyles: function () {
   return "{ height: auto !important; }";
  },
  OnBrowserWindowResize: function(e) {
   this.AdjustControl();
  },
  BrowserWindowResizeSubscriber: function() {
   return this.adaptivityMode == FormLayoutAdaptivityMode.SingleColumnWindowLimit;
  },
  GetLayoutItemElementsWithHorizontalCaptions: function() {
   if(!this.itemsWithHorizontalCaptions) {
    var mainElement = this.GetMainElement();
    this.itemsWithHorizontalCaptions = ASPxClientFormLayoutUtils.getElementNodesByPredicate(mainElement,
     function(element) { return this.itemHasHorizontalCaption(element); }.aspxBind(this),
     mainElement);
   }
   return this.itemsWithHorizontalCaptions;
  },
  GetHorizontalHelpTextElements: function() {
   if(!this.horizontalHelpTextElements) {
    var mainElement = this.GetMainElement();
    this.horizontalHelpTextElements = ASPxClientFormLayoutUtils.getElementNodesByPredicate(mainElement,
     function(element) { return this.isHorizontalHelpTextElement(element); }.aspxBind(this),
     mainElement);
   }
   return this.horizontalHelpTextElements;
  },
  AddCssClassToElements: function(elements, className) {
   for(var i = 0; i < elements.length; i++)
    ASPx.AddClassNameToElement(elements[i], className);
  },
  InitializeNeedAdjustItemsContentOnShowing: function () {
   if(this.rootItem == null) return;
   for(var i = 0; i < this.rootItem.items.length; i++)
    this.rootItem.items[i].InitializeNeedAdjustContentOnShowing();
  },
  CreateItems: function (itemsProperties) {
   this.rootItem = this.CreateRootItem();
   this.rootItem.CreateItems(itemsProperties);
  },
  CreateRootItem: function(){
   return new ASPxClientLayoutItem(this, "", "", null);
  },
  SetAccessibilityCaptionAssociating: function(captionAssociatingItems) {
   var itemsCount = captionAssociatingItems.length;
   for(var i = 0; i < itemsCount; i++) {
    var captionElement = ASPx.GetElementById(captionAssociatingItems[i][0]);
    var control = ASPx.GetControlCollection().Get(captionAssociatingItems[i][1]);
    if(ASPx.IsExists(captionElement) && ASPx.IsExists(control) && control.isASPxClientEdit)
     ASPx.EditAccessibilityExplanatoryTextManager.SetLabelAssociating(control, control.GetAccessibilityFirstActiveElement(), captionElement);
    if(ASPx.IsExists(captionAssociatingItems[i][2]))
     this.SetAccessibilityCaptionAssociating(captionAssociatingItems[i][2]);
   }
  },
  GetItemByName: function (name) {
   return this.rootItem != null ? this.rootItem.GetItemByName(name) : null;
  },
  getItemByPredicate: function(predicate) {
   return this.rootItem != null ? this.rootItem.getItemByPredicate(predicate) : null;
  },
  GetItemByPath: function (path) {
   return this.rootItem != null ? this.rootItem.GetItemByPath(path) : null;
  },
  getElementToAlignGroups: function(elementToChangeState, item) {
   if(this.alignItemCaptionsInAllGroups)
    return this.GetMainElement();
   else {
    if(item.items.length > 0)
     return elementToChangeState;
    else
     return this.GetHTMLElementByItem(item.parent);
   }
  },
  SetItemVisible: function (item, visible, initialization) {
   if(visible && initialization) return;
   if(!item.visible) return;
   var tab = this.findItemParentTab(item);
   if(tab)
    tab.SetVisible(visible);
   else
    this.SetItemVisibleCore(item, visible);
   this.adjustTabbedGroupPageControls();
  },
  SetItemVisibleCore: function(item, visible) {
   var element = this.GetHTMLElementByItem(item);
   if(!element)
    return;
   this.setElementDisplay(element, visible);
   if(this.IsVisible() && this.isLayoutPrepared())
    this.alignGroupsAfterItemStateChanged(element, item);
   if(visible && item.needAdjustContentOnShowing) {
    ASPx.GetControlCollection().AdjustControls(element);
    item.ResetNeedAdjustContentOnShowing();
   }
   this.AdjustControlInternal(true);
  },
  setElementDisplay: function(element, visible) {
   ASPx.SetElementDisplay(element, visible);
  },
  getItemCaptionElement: function(item, itemParentTab) {
   var itemElementContainer = this.getItemElementContainer(item, itemParentTab);
   return this.getCaptionElementByItemContainer(itemElementContainer);
  },
  getItemCaptionInternal: function(captionElement) {
   var captionText = this.getItemCaptionElementText(captionElement);
   captionText = ASPx.Str.Trim(captionText);
   if(captionText !== "" && captionText[captionText.length - 1] == ":")
    captionText = captionText.substring(0, captionText.length - 1);
   return captionText;
  },
  GetItemCaption: function(item) {
   var itemParentTab = this.findItemParentTab(item);
   if(itemParentTab)
    return itemParentTab.GetText();
   var captionElement = this.getItemCaptionElement(item);
   if(captionElement)
    return this.getItemCaptionInternal(captionElement);
   return "";
  },
  SetItemCaption: function(item, caption) {
   var itemParentTab = this.findItemParentTab(item);
   var captionElement = this.getItemCaptionElement(item, itemParentTab);
   if(itemParentTab)
    itemParentTab.SetText(caption);
   if(captionElement)
    this.setItemCaptionInternal(captionElement, caption);
   if(this.isLayoutItemCaptionElement(captionElement)) {
    this.alignGroupsAfterItemStateChanged(captionElement, item);
   }
   this.adjustTabbedGroupPageControls();
  },
  isLayoutItemCaptionElement: function(captionElement) {
   return ASPx.ElementContainsCssClass(captionElement, FormLayoutConsts.LAYOUT_ITEM_CAPTION_PARTIAL_CLASS_NAME);
  },
  alignGroupsAfterItemStateChanged: function(element, item) {
   var elementToAlignGroups = this.getElementToAlignGroups(element, item);
   if(elementToAlignGroups)
    this.alignGroupsInContainer(elementToAlignGroups);
  },
  needToAddItemCaptionColon: function(captionElement, caption) {
   if(caption === "")
    return false;
   var captionEndsWithColon = caption[caption.length - 1] == ":";
   return this.showItemCaptionColon && this.isLayoutItemCaptionElement(captionElement) && !captionEndsWithColon;
  },
  setItemCaptionInternal: function(captionElement, rawCaption) {
   var captionTextNode = ASPx.GetNormalizedTextNode(captionElement);
   if(!captionTextNode) {
    captionTextNode = document.createTextNode("");
    captionElement.appendChild(captionTextNode);
   }
   captionTextNode.nodeValue = this.getPreparedCaption(rawCaption, captionElement);
  },
  getPreparedCaption: function(rawCaption, captionElement) {
   var result = ASPx.Str.Trim(rawCaption);
   if(this.needToAddItemCaptionColon(captionElement, result))
    result += ":";
   return result;
  },
  findItemParentTab: function(item) {
   if(!item.parent.isTabbedGroup)
    return null;
   var pageControlObject = this.getPageControlObjectByItem(item.parent);
   if(pageControlObject) {
    var tabName = item.name || item.path;
    return pageControlObject.GetTabByName(tabName);
   }
   return null;
  },
  getItemElementContainer: function(item, itemParentTab) {
   if(itemParentTab)
    return itemParentTab.tabControl.GetContentHolder(itemParentTab.index);
   var container = this.GetHTMLElementByItem(item);
   if(!this.IsFlowRender())
    return container;
   return ASPxClientFormLayoutUtils.getGroupCell(container);
  },
  getPageControlObjectByItem: function(tabbedGroup) {
   var pageControlName = this.GetPageControlName(tabbedGroup);
   return ASPx.GetControlCollection().Get(pageControlName);
  },
  getPageControlObjectByContainer: function(pageControlContainer) {
   var pageControlElement = ASPx.GetChildByClassName(pageControlContainer, FormLayoutConsts.TABBED_GROUP_PAGE_CONTROL_SYSTEM_CLASS_NAME, 0);
   if(pageControlElement == null)
    return null;
   return ASPx.GetControlCollection().Get(pageControlElement.id);
  },
  getCaptionElementByItemContainer: function(container) {
   var captionElement = null;
   var layoutItemElement = ASPx.GetChildByClassName(container, this.getItemCaptionContainerClassName());
   if(layoutItemElement)
    captionElement = this.getLayoutItemCaptionElement(layoutItemElement);
   else {
    var groupBoxElement = ASPx.GetChildByClassName(container, this.getGroupBoxCaptionContainerClassName());
    if(groupBoxElement)
     captionElement = this.getGroupBoxCaptionElement(groupBoxElement);
   }
   return captionElement;
  },
  getLayoutItemCaptionElement: function(itemElement) {
   var captionCell = ASPxClientFormLayoutUtils.getElementNodesByClassName(itemElement, FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME, this.GetMainElement())[0];
   return ASPx.GetChildByPartialClassName(captionCell, FormLayoutConsts.LAYOUT_ITEM_CAPTION_PARTIAL_CLASS_NAME);
  },
  getLayoutItemHelpTextElement: function(itemElement) {
   var classes = FormLayoutHorizontalHelpTextsCssClasses.concat(FormLayoutVerticalHelpTextsCssClasses)
    .map(function(c) { return "." + c; })
    .join(",");
   return Array.prototype.slice.call(itemElement.querySelectorAll(classes))
    .filter(function(element) {
     return !ASPxClientFormLayoutUtils.isElementContainedInNestedItem(element, itemElement);
    })[0];
  },
  getGroupBoxCaptionElement: function(groupBoxElement) {
   return ASPx.GetChildByPartialClassName(groupBoxElement, FormLayoutConsts.GROUP_BOX_CAPTION_PARTIAL_CLASS_NAME);
  },
  GetPageControlName: function (tabbedGroup) {
   return this.GetItemElementIDPrefix(tabbedGroup) + FormLayoutConsts.PAGE_CONTROL_ID_PREFIX + tabbedGroup.path;
  },
  GetHTMLElementByItem: function(item) {
   if(item === this.rootItem)
    return this.GetMainElement();
   var itemParentTab = this.findItemParentTab(item);
   if(itemParentTab)
    return itemParentTab.tabControl.GetContentHolder(itemParentTab.index);
   return ASPx.GetElementById(this.GetItemElementID(item));
  },
  GetItemElementID: function (item) {
   return this.GetItemElementIDPrefix(item) + item.path;
  },
  GetItemElementIDPrefix: function (item) {
   var result = "";
   var currentParent = item.parent;
   while(currentParent != null) {
    if(currentParent.isTabbedGroup)
     result = FormLayoutConsts.PAGE_CONTROL_ID_PREFIX + currentParent.path + "_" + result;
    currentParent = currentParent.parent;
   }
   return this.name + "_" + result;
  },
  UpdateHeadingLineGroupBoxElements: function () {
   var mainElement = this.GetMainElement();
   if(ASPx.IsExistsElement(mainElement)) {
    var groupBoxElements = this.getGroupBoxElements(mainElement);
    for(var i = 0; i < groupBoxElements.length; i++) {
     var groupBoxElement = groupBoxElements[i];
     var isHeadingLineGroupBox = groupBoxElement.className.indexOf(FormLayoutConsts.HEADING_LINE_GROUP_BOX_SYSTEM_CLASS_NAME) !== -1;
     if(isHeadingLineGroupBox) {
      var hasGroupBoxCaption = ASPx.GetChildNodesByTagName(groupBoxElement, "SPAN").length === 1;
      if(hasGroupBoxCaption)
       groupBoxElement.className += " " + FormLayoutConsts.HEADING_LINE_GROUP_BOX_WITH_CAPTION_SYSTEM_CLASS_NAME;
     }
    }
   }
  },
  AdjustControlCore: function() {
   this.AdjustControlInternal();
  },
  AdjustControlInternal: function(force) {
   if(!this.isLayoutPrepared())
    return;
   var isForce = force || this.forceAdjustOnShow;
   if(!this.IsFlowRender() && !isForce)
    return;
   var mainElement = this.GetMainElement();
   if(ASPx.IsExists(mainElement)) {
    if(ASPx.IsElementVisible(mainElement)) {
     this.GetGroupLayoutHelper().RecalculateLayout(isForce);
     this.forceAdjustOnShow = false;
    }  else
     this.forceAdjustOnShow = isForce;
   }
  },
  BeginUpdate: function() {
   this.updateLock = true;
  },
  EndUpdate: function() {
   this.updateLock = false;
   this.AdjustControlInternal(true);
  },
  getTabbedGroupPageControlObjects: function() {
   var mainElement = this.GetMainElement();
   var pageControlElements = ASPxClientFormLayoutUtils.getElementNodesByClassName(mainElement, FormLayoutConsts.TABBED_GROUP_PAGE_CONTROL_SYSTEM_CLASS_NAME, mainElement);
   var result = [];
   ASPx.Data.ForEach(pageControlElements, function(element) {
    if(!element.id)
     return;
    var pageControlObject = ASPx.GetControlCollection().Get(element.id);
    if(pageControlObject)
     result.push(pageControlObject);
   });
   return result;
  },
  adjustTabbedGroupPageControls: function() { 
   var pageControls = this.getTabbedGroupPageControlObjects();
   ASPx.Data.ForEach(pageControls, function(control) {
    control.AdjustControl();
   });
  },
  addHandlersToActiveTabChangedEvents: function () {
   var mainElement = this.GetMainElement();
   var pageControls = ASPxClientFormLayoutUtils.getElementNodesByClassName(mainElement,
    FormLayoutConsts.TABBED_GROUP_PAGE_CONTROL_SYSTEM_CLASS_NAME,
    mainElement);
   for(var i = 0; i < pageControls.length; i++) {
    var pageControlObject = ASPx.GetControlCollection().Get(pageControls[i].id);
    if(!pageControlObject)
     continue;
    pageControlObject.ActiveTabChanged.AddHandler(function (s, e) {
     this.onPageControlTabChanged();
     this.AdjustControlInternal(true);
    }.aspxBind(this));
    pageControlObject.EndCallback.AddHandler(function (s, e) {
     var tabContentElement = s.GetContentElement(s.GetActiveTabIndex());
     this.prepareNestedControls(tabContentElement);
    }.aspxBind(this));
   }
  },
  onPageControlTabChanged: function () { },
  alignGroupsInContainer: function (groupContainer) {
   if(ASPx.IsExistsElement(groupContainer))
    this.GetAlignCaptionHelper().AlignGroups(groupContainer);
  },
  itemHasHorizontalCaption: function(itemElement) {
   for(var i = 0; i < FormLayoutHorizontalCaptionsCssClasses.length; i++)
    if(ASPx.ElementContainsCssClass(itemElement, FormLayoutHorizontalCaptionsCssClasses[i]))
     return true;
   return false;
  },
  isHorizontalHelpTextElement: function(element) {
   for(var i = 0; i < FormLayoutHorizontalHelpTextsCssClasses.length; i++)
    if(ASPx.ElementContainsCssClass(element, FormLayoutHorizontalHelpTextsCssClasses[i]))
     return true;
   return false;
  },
  findTabbedGroupChildItemElement: function(tabbedGroupElement) {
   var pageControlObject = this.getPageControlObjectByContainer(tabbedGroupElement);
   if(pageControlObject == null)
    return null;
   var tabContentHolder = pageControlObject.GetContentHolder(pageControlObject.GetActiveTabIndex());
   var itemElement = ASPx.GetChildByClassName(tabContentHolder, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME);
   if(itemElement)
    return itemElement;
   var childTabbedGroupElement = ASPx.GetChildByClassName(tabContentHolder, FormLayoutConsts.TABBED_GROUP_SYSTEM_CLASS_NAME);
   return childTabbedGroupElement ? this.findTabbedGroupChildItemElement(childTabbedGroupElement) : null;
  },
  getGroupBoxElements: function(parent) {
   return ASPxClientFormLayoutUtils.getElementNodesByClassName(parent,
    FormLayoutConsts.HEADING_LINE_GROUP_BOX_SYSTEM_CLASS_NAME,
    this.GetMainElement());
  },
  isLayoutPrepared: function() {
   return !this.updateLock;
  },
  getItemCaptionContainerClassName: function() {
   return FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME;
  },
  getGroupBoxCaptionContainerClassName: function() {
   return FormLayoutConsts.GROUP_BOX_SYSTEM_CLASS_NAME;
  },
  getItemCaptionElementText: function(captionElement) {
   return ASPx.GetInnerText(captionElement);
  }
 });
 ASPxClientFormLayout.Cast = ASPxClientControl.Cast;
 var ASPxClientFormLayoutUtils = { };
 ASPxClientFormLayoutUtils.getCellColSpan = function (cellContainer, breakpointKey) {
  return this.getCellSpanCore(cellContainer, breakpointKey, true);
 };
 ASPxClientFormLayoutUtils.getCellRowSpan = function (cellContainer, breakpointKey) {
  return this.getCellSpanCore(cellContainer, breakpointKey, false);
 };
 ASPxClientFormLayoutUtils.getCellSpanCore = function(cellContainer, breakpointKey, isColumnSpan) {
  var spanRules = this.getCellSpanRules(cellContainer);
  var defaultSpan = this.getDefaultCellSpanCore(cellContainer, isColumnSpan);
  if(!spanRules)
   return defaultSpan;
  var rulesValue = spanRules[breakpointKey];
  var ruleSpanIndex = isColumnSpan ? 0 : 1;
  return rulesValue === undefined ? defaultSpan : rulesValue[ruleSpanIndex];
 };
 ASPxClientFormLayoutUtils.getCellSpanRules = function(cellElement) {
  return JSON.parse(ASPx.Attr.GetAttribute(cellElement, "data-spanRules"));
 };
 ASPxClientFormLayoutUtils.getDefaultCellSpanCore = function(cellContainer, isColumnSpan) {
  var result = 1;
  var attributeName = isColumnSpan ? "data-colSpan" : "data-rowSpan";
  var spanAttribute = ASPx.Attr.GetAttribute(cellContainer, attributeName);
  if(spanAttribute) {
   var invariantCultureSpanAttribute = spanAttribute.replace(/,/g, '.');
   var parsedValue = parseFloat(invariantCultureSpanAttribute);
   if(!isNaN(parsedValue))
    result = parsedValue;
  }
  return result;
 };
 ASPxClientFormLayoutUtils.getGroupCell = function(container) {
  return ASPx.GetChildByPartialClassName(container, FormLayoutConsts.GROUP_CELL_PARTIAL_CLASS_NAME);
 };
 ASPxClientFormLayoutUtils.getCellContent = function(groupCell) {
  return ASPx.GetChildNodes(groupCell, this.isFormLayoutElement)[0];
 };
 ASPxClientFormLayoutUtils.isFormLayoutElement = function(element) {
  return ASPx.ElementHasCssClass(element, FormLayoutConsts.TABBED_GROUP_SYSTEM_CLASS_NAME) ||
   ASPx.ElementHasCssClass(element, FormLayoutConsts.GROUP_BOX_SYSTEM_CLASS_NAME) ||
   ASPx.ElementHasCssClass(element, FormLayoutConsts.ITEM_SYSTEM_CLASS_NAME) ||
   ASPx.ElementHasCssClass(element, FormLayoutConsts.GROUP_SYSTEM_CLASS_NAME) ||
   ASPx.ElementContainsCssClass(element, FormLayoutConsts.EMPTY_ITEM_CLASS_NAME);
 };
 ASPxClientFormLayoutUtils.isRootFlowLayoutGroup = function(groupBox) {
  return this.getFlowLayoutGroupLevel(groupBox) == 1;
 };
 ASPxClientFormLayoutUtils.getFlowLayoutGroupLevel = function(groupBox) {
  var result = -1;
  var groupIDAttribute = ASPx.Attr.GetAttribute(groupBox, "data-groupid");
  if(groupIDAttribute)
   result = groupIDAttribute.split(FormLayoutConsts.ITEM_PATH_SEPARATOR)
          .filter(function(pathPart) { return pathPart !== ""; })
          .length;
  return result;
 };
 ASPxClientFormLayoutUtils.getChildDivAtNestedLevel = function(element, level) {
  var result = element;
  for(var i = 0; i < level; i++) {
   result = ASPx.GetChildNodesByTagName(result, "DIV")[0];
   if(!result)
    break;
  }
  return result;
 };
 ASPxClientFormLayoutUtils.getRowIndexByCellIndex = function(index, rowLastCellIndices) {
  var rowIndex = 0;
  if(rowLastCellIndices.length == 0)
   return rowIndex;
  if(index > rowLastCellIndices[rowLastCellIndices.length - 1])
   return rowLastCellIndices.length;
  for(var i = rowLastCellIndices.length - 1; i >= 0; i--) {
   var lastCellIndex = rowLastCellIndices[i];
   var previousLastCellIndex = rowLastCellIndices[i - 1];
   if(index <= lastCellIndex && (i == 0 || index > previousLastCellIndex)) {
    rowIndex = i;
    break;
   } 
  }
  return rowIndex;
 };
 ASPxClientFormLayoutUtils.getDefaultBreakpointInfo = function() {
  return {
   breakpoint: "",
   breakpointKey: ""
  };
 };
 ASPxClientFormLayoutUtils.getBreakpointInfo = function(group, flOffsetWidth) {
  var result = this.getDefaultBreakpointInfo();
  var breakpoints = this.getBreakpoints(group);
  if(!breakpoints)
   return result;
  for(var key in breakpoints) {
   if(breakpoints.hasOwnProperty(key)) {
    var breakpoint = breakpoints[key];
    var minWidth = breakpoint[0];
    var maxWidth = breakpoint[1];
    if(flOffsetWidth >= minWidth && flOffsetWidth <= maxWidth) {
     result.breakpoint = breakpoints[key];
     result.breakpointKey = key;
     break;
    }
   }
  }
  return result;
 };
 ASPxClientFormLayoutUtils.getBreakpoints = function(group) {
  var breakpointsAttribute = ASPx.Attr.GetAttribute(group, "data-breakpoints");
  return JSON.parse(breakpointsAttribute);
 };
 ASPxClientFormLayoutUtils.getCurrentBreakpoint = function(group) {
  return ASPx.Attr.GetAttribute(group, "data-currentBreakpoint") || "";
 };
 ASPxClientFormLayoutUtils.getGroupCurrentColCount = function(group) {
  var colCountAttribute = ASPx.Attr.GetAttribute(group, "data-colCount");
  return (colCountAttribute && parseInt(colCountAttribute)) || 1;
 };
 ASPxClientFormLayoutUtils.getClientLeft = function(container) {
  var clientLeftAttr = ASPx.Attr.GetAttribute(container, "data-left");
  return (clientLeftAttr && parseInt(clientLeftAttr)) || ASPx.GetAbsoluteX(container);
 };
 ASPxClientFormLayoutUtils.getVerticalCaptionContainer = function(container) {
  return this.getContainerElementNodesByPredicate(container, function(element) {
   return ASPx.ElementContainsCssClass(element, FormLayoutVerticalCaptionsCssClasses[0])
    || ASPx.ElementContainsCssClass(element, FormLayoutVerticalCaptionsCssClasses[1]);
  }, container)[0];
 };
 ASPxClientFormLayoutUtils.isElementContainedInNestedFormLayout = function(element, mainElement) {
  var parentFormLayout = ASPx.GetParentByPartialClassName(element, FormLayoutConsts.FORM_LAYOUT_PARTIAL_CLASS_NAME);
  return parentFormLayout !== mainElement;
 };
 ASPxClientFormLayoutUtils.isElementContainedInNestedItem = function(element, mainElement) {
  var parentContainer = ASPx.GetParent(element, function(el) { return !!el.id; });
  return mainElement.id !== parentContainer.id;
 };
 ASPxClientFormLayoutUtils.getElementNodesByPredicate = function(parent, predicate, mainElement) {
  return ASPx.GetNodes(parent, function(element) {
   return !this.isElementContainedInNestedFormLayout(element, mainElement) && (!predicate || predicate(element));
  }.aspxBind(this));
 };
 ASPxClientFormLayoutUtils.getContainerElementNodesByPredicate = function(parent, predicate, mainElement) {
  return ASPx.GetNodes(parent, function(element) {
   return !this.isElementContainedInNestedItem(element, mainElement) && (!predicate || predicate(element));
  }.aspxBind(this));
 };
 ASPxClientFormLayoutUtils.getElementNodesByClassName = function(parent, className, mainElement) {
  var result = [];
  ASPx.Data.ForEach(ASPx.GetNodesByClassName(parent, className), function(element) {
   if(!this.isElementContainedInNestedFormLayout(element, mainElement))
    result.push(element);
  }.aspxBind(this));
  return result;
 };
 ASPxClientFormLayoutUtils.getContainerElementNodesByClassName = function(parent, className, mainElement) {
  var result = [];
  ASPx.Data.ForEach(ASPx.GetNodesByClassName(parent, className), function(element) {
   if(!this.isElementContainedInNestedItem(element, mainElement))
    result.push(element);
  }.aspxBind(this));
  return result;
 };
 ASPxClientFormLayoutUtils.getElementNodesByPartialClassName = function(parent, className, mainElement) {
  var result = [];
  ASPx.Data.ForEach(ASPx.GetNodesByPartialClassName(parent, className), function(element) {
   if(!this.isElementContainedInNestedFormLayout(element, mainElement))
    result.push(element);
  }.aspxBind(this));
  return result;
 };
 ASPxClientFormLayoutUtils.getContainerElementNodesByPartialClassName = function(parent, className, mainElement) {
  var result = [];
  ASPx.Data.ForEach(ASPx.GetNodesByPartialClassName(parent, className), function(element) {
   if(!this.isElementContainedInNestedItem(element, mainElement))
    result.push(element);
  }.aspxBind(this));
  return result;
 };
 ASPxClientFormLayoutUtils.getItemNestedControlCell = function(itemElementContainer) {
  return this.getContainerElementNodesByPartialClassName(itemElementContainer, FormLayoutConsts.NESTED_CONTROL_CELL_PARTIAL_CLASS_NAME, itemElementContainer)[0];
 };
 ASPxClientFormLayout.UpdateNestedControlTypeClassName = function(itemElement, isEditingItem) {
  var getActualEditorTypeClassName = function(itemElement) {
   for(var i = 0; i < NestedControlToItemClassNamesMap.length; i++)
    if(ASPx.ElementHasCssClass(itemElement, NestedControlToItemClassNamesMap[i].itemClassName))
     return NestedControlToItemClassNamesMap[i].itemClassName;   
   return "";
  };
  var getRequiredEditorTypeClassName = function(itemElement) {
   var nestedControlElement = getNestedControlElement(itemElement);
   if(ASPx.IsExists(nestedControlElement)) {
    for(var i = 0; i < NestedControlToItemClassNamesMap.length; i++)
     if(ASPx.ElementContainsCssClass(nestedControlElement, NestedControlToItemClassNamesMap[i].controlClassName))
      return NestedControlToItemClassNamesMap[i].itemClassName;    
   }
   return "";
  };
  var getNestedControlElement = function(itemElement) {
   var nestedControlCell = ASPx.GetNodesByPartialClassName(itemElement, FormLayoutConsts.NESTED_CONTROL_CELL_PARTIAL_CLASS_NAME)[0];
   if(!nestedControlCell) return null; 
   var nestedControlElements = ASPx.GetNodes(nestedControlCell, function(element) {
    var nestedControlObject = element.id && ASPx.GetControlCollection().Get(element.id);
    return !!nestedControlObject;
   });
   return nestedControlElements.length > 0 ? nestedControlElements[0] : null;
  };
  if(isEditingItem) {
   var editorClassName = getRequiredEditorTypeClassName(itemElement);
   if(editorClassName) {
    ASPx.AddClassNameToElement(itemElement, ASPx.FormLayoutConsts.EDIT_FORM_ITEM_SYSTEM_CLASS_NAME);
    ASPx.RemoveClassNameFromElement(itemElement, FormLayoutConsts.TEXT_ITEM_SYSTEM_CLASS_NAME);
    ASPx.AddClassNameToElement(itemElement, editorClassName);
   }
  }
  else {
   ASPx.RemoveClassNameFromElement(itemElement, ASPx.FormLayoutConsts.EDIT_FORM_ITEM_SYSTEM_CLASS_NAME);
   ASPx.RemoveClassNameFromElement(itemElement, getActualEditorTypeClassName(itemElement));
   ASPx.AddClassNameToElement(itemElement, FormLayoutConsts.TEXT_ITEM_SYSTEM_CLASS_NAME);
  }
 };
 ASPx.CreateDialogLayoutBaseClass = function (parentClass, properties) {
  var extendentClass = ASPx.CreateClass(parentClass, {
   constructor: function (name) {
    this.constructor.prototype.constructor.call(this, name);
    this.oneColumnItemPriorityTable = {};
    this.itemVisibilityDependencies = {};
    this.triggerInfoCollection = [];
    this.controlNameIdMapping = {};
    this.externalUpdateInvokesCounter = 0;
    this.allowAdjust = true;
   },
   processFieldValueChangedOnServer: function (parentCallbackPanelName) {
    var callbackPanel = ASPxClientControl.GetControlCollection().GetByName(parentCallbackPanelName);
    if (this.externalUpdateInvokesCounter == 0) {
     this.externalUpdateInvokesCounter++;
     callbackPanel.PerformCallback();
    }
   },
   CreateItems: function (itemsProperties) {
    parentClass.prototype.CreateItems.call(this, itemsProperties);
    if (this.rootItem) {
     this.beginUpdate();
     this.initializeOneColumnItemPriorities();
     this.initializeDependencies();
     this.initializeTriggers();
     this.endUpdate();
    }
   },
   initializeTriggers: function () {
    this.triggerInfoCollection.forEach(this.createTrigger.aspxBind(this));
   },
   createTrigger: function (triggerInfo) {
    if (!triggerInfo.trigger || !triggerInfo.method)
     return;
    var targetGetter = null;
    var target = triggerInfo.target;
    if (target) {
     if (target.control)
      targetGetter = function () { return ASPxClientControl.GetControlCollection().GetByName(target.control); };
     else if (target.object) {
      targetGetter = function () {
       return target.object.split('.')
        .reduce(function (obj, n) {
         return (obj[n] || (obj[n] = {}));
        }, window);
      };
     }
    } else
     targetGetter = function () { return window; };
    triggerInfo.trigger.forEach(function (trigger) {
     this.attachMethodInvokationOnEvent(trigger, targetGetter, triggerInfo.method);
    }.aspxBind(this));
   },
   attachMethodInvokationOnEvent: function (trigger, targetGetter, methodInfo) {
    var event = this.getControlEvent(trigger);
    if (event) {
     event.AddHandler(function (s, e) {
      var target = targetGetter();
      if (target) {
       var method = target[methodInfo.name];
       if (method)
        method.apply(target, methodInfo.args || []);
      }
     });
    }
   },
   getControlEvent: function (trigger) {
    var field = this.getField(trigger.name);
    if (!field)
     return null;
    var control = field.getControl();
    return control ? (control[trigger.event] || control.UserInput || control.ValueChanged) : null;
   },
   initializeOneColumnItemPriorities: function () {
    for (var orderIndex in this.oneColumnItemPriorityTable) {
     if (this.oneColumnItemPriorityTable.hasOwnProperty(orderIndex)) {
      var itemName = this.oneColumnItemPriorityTable[orderIndex];
      var items = this.getItemsByName(itemName);
      for (var j = 0; j < items.length; j++) {
       var itemElement = this.getItemElementContainer(items[j]).parentNode;
       if (itemElement)
        itemElement.style.order = orderIndex;
      }
     }
    }
   },
   initializeDependencies: function (suppressEventAssign) {
    this.iterateDependencies(this.itemVisibilityDependencies, function (key, dependency) {
     this.getItemsByName(key).forEach(function (item) {
      this.createDependency(dependency, this.getItemVisibleChangeDelegate(item), suppressEventAssign);
     }.aspxBind(this));
    }.aspxBind(this));
    this.iterateDependencies(this.editorVisibilityDependencies, function (key, dependency) {
     var editor = this.getField(key).getControl();
     if (editor)
      this.createDependency(dependency, this.getEditorVisibleChangeDelegate(editor), suppressEventAssign);
    }.aspxBind(this));
    this.iterateDependencies(this.editorEnabledDependencies, function (key, dependency) {
     var editor = this.getField(key).getControl();
     if (editor)
      this.createDependency(dependency, editor.SetEnabled.aspxBind(editor), suppressEventAssign);
    }.aspxBind(this));
   },
   getItemVisibleChangeDelegate: function (item) {
    return function (newValue) {
     var container = this.GetMainElement();
     var stateClasses = this.getFieldStateCssClasses(item);
     if (stateClasses) {
      ASPx.RemoveClassNameFromElement(container, stateClasses.hidden);
      ASPx.RemoveClassNameFromElement(container, stateClasses.visible);
      ASPx.AddClassNameToElement(container, newValue ? stateClasses.visible : stateClasses.hidden);
     }
     item.SetVisible(newValue);
    }.aspxBind(this);
   },
   getFieldStateCssClasses: function (item) {
    return {
     visible: "dialog-item-" + item.name + "-visible",
     hidden: "dialog-item-" + item.name + "-hidden"
    };
   },
   getEditorVisibleChangeDelegate: function (editor) {
    return function (newValue) {
     if (newValue != editor.GetVisible()) {
      var container = ASPx.GetParentByClassName(editor.GetMainElement(), "dialog-linc");
      var count = container.className.match(/(?:dialog-linc-c)(\d)/)[1];
      ASPx.RemoveClassNameFromElement(container, "dialog-linc-c" + count);
      ASPx.AddClassNameToElement(container, "dialog-linc-c" + (newValue ? ++count : --count));
      ASPx.SetElementDisplay(ASPx.GetParentByClassName(editor.GetMainElement(), "dialog-control-wrapper"), newValue);
     }
     editor.SetVisible(newValue);
    };
   },
   createDependency: function (dependency, propertySetter, suppressEventAssign) {
    var control = this.getField(dependency.fieldName).getControl();
    if (control) {
     propertySetter(this.hasSameValue(control, dependency));
     if (!suppressEventAssign) {
      control.ValueChanged.removeHandlerByControlName(this.name);
      control.ValueChanged.AddHandler(function (s, e) {
       this.beginUpdate();
       propertySetter(this.hasSameValue(control, dependency));
       this.initializeDependencies(true);
       this.endUpdate();
       this.AdjustControlInternal(true);
      }.aspxBind(this), this);
     }
    } else if (!dependency.fieldName)
     propertySetter(dependency.value.toString().toLowerCase() == "true");
   },
   hasSameValue: function (control, dependency) {
    return this.getValueToCompare(control.GetValue()) == this.getValueToCompare(dependency.value);
   },
   getValueToCompare: function (value) {
    return ASPx.IsExists(value) ? value.toString().toLowerCase() : "";
   },
   iterateDependencies: function (dependencies, callback) {
    for (var key in dependencies) {
     if (dependencies.hasOwnProperty(key)) {
      var dependencyTable = dependencies[key];
      for (var i = 0; i < dependencyTable.length; i++) {
       var dependency = dependencyTable[i];
       callback(key, dependency);
      }
     }
    }
   },
   getItemsByName: function (name, result, currentItem) {
    result = result || [];
    currentItem = currentItem || this.rootItem;
    if (currentItem) {
     if (currentItem.name == name)
      result.push(currentItem);
     for (var i = 0; i < currentItem.items.length; i++)
      this.getItemsByName(name, result, currentItem.items[i]);
    }
    return result;
   },
   getField: function (name) {
    return new DialogLayoutField(name, this);
   },
   beginUpdate: function() {
    this.allowAdjust = false;
   },
   endUpdate: function() {
    this.allowAdjust = true;
   },
   layoutUpdating: function() {
    return !this.allowAdjust;
   }
  });
  return ASPx.CreateClass(extendentClass, properties);
 };
 ASPx.CreateDialogLayoutClass = function (parentClass, properties) {
  var extendentClass = ASPx.CreateDialogLayoutBaseClass(parentClass, {
   constructor: function (name) {
    this.constructor.prototype.constructor.call(this, name);
    this.layoutPrepared = false;
    this.canModifyEnviroment = false;
   },
   getPreparingCssClass: function () {
    return "dialog-preparing";
   },
   getSingleColumnCssClass: function () {
    return "dialog-singlecolumn";
   },
   InlineInitialize: function () {
    this.switchToSingleColumnAtWindowInnerWidth = this.calculateSwitchToSingleColumnAtWindowInnerWidth();
    this.columnMinWidth = this.calculateColumnMinWidth();
    ASPxClientFormLayout.prototype.InlineInitialize.call(this);
   },
   Initialize: function () {
    this.beginUpdate();
    ASPxClientFormLayout.prototype.Initialize.call(this);
    this.canModifyEnviroment = true;
    this.endUpdate();
   },
   onPageControlTabChanged: function () {
    this.adjustLogicalRows();
   },
   SetItemVisible: function () {
    ASPxClientFormLayout.prototype.SetItemVisible.apply(this, arguments);
   },
   AdjustControlCore: function () {
    if(this.layoutUpdating())
     return;
    if (this.canModifyEnviroment && !this.layoutPrepared) {
     this.removePopupInvisibleProperties();
     this.prepareMinLayoutSize();
     this.prepareDialogPopupIfNeeded();
     this.adjustLogicalRows();
     this.restorePopupInvisibleProperties();
     ASPx.RemoveClassNameFromElement(this.GetMainElement(), this.getPreparingCssClass());
     this.layoutPrepared = true;
    }
    this.AdjustControlInternal(true);
   },
   AdjustControlInternal: function(force) {
    if(this.layoutUpdating())
     return;
    ASPxClientFormLayout.prototype.AdjustControlInternal.call(this, force);
   },
   removePopupInvisibleProperties: function () {
    var mainElement = this.GetMainElement();
    var w = ASPx.GetParentByClassName(mainElement, "dialog-window");
    if(w && !ASPx.IsElementVisible(w)) {
     var winOuter = w.parentNode;
     this.savedWindowStyles = { display: winOuter.style.display, visibility: winOuter.style.visibility, overflow: "", height: "", width: "" };
     ASPx.SetStyles(winOuter, { display: "block", visibility: "visible", overflow: "hidden", height: 0, width: 0 });
     if (winOuter.parentNode.className.indexOf("dxmodalSys") > -1) {
      this.savedModalStyles = { display: "", overflow: "", height: "", width: "" };
      ASPx.SetStyles(winOuter.parentNode, { display: "block", overflow: "hidden", height: 0, width: 0 });
     }
    }
   },
   restorePopupInvisibleProperties: function () {
    if (this.savedWindowStyles) {
     var mainElement = this.GetMainElement();
     var w = ASPx.GetParentByClassName(mainElement, "dialog-window").parentNode;
     ASPx.SetStyles(w, this.savedWindowStyles);
     delete this.savedWindowStyles;
     if (this.savedModalStyles) {
      ASPx.SetStyles(w.parentNode, this.savedModalStyles);
      delete this.savedModalStyles;
     }
    }
   },
   prepareDialogPopupIfNeeded: function () {
    var mainElement = this.GetMainElement();
    if (!!ASPx.GetParentByClassName(mainElement, "dialog-window")) {
     var popup = this.findParentByType(ASPxClientPopupControl);
     var win = popup.GetWindowElement(-1);
     var newMaxWidth = mainElement.offsetWidth + ASPx.GetLeftRightBordersAndPaddingsSummaryValue(win);
     var oldMaxWidth = ASPx.PxToInt(ASPx.GetCurrentStyle(win).maxWidth);
     if (oldMaxWidth > 0 && oldMaxWidth < newMaxWidth)
      popup.SetAdaptiveMaxWidth(newMaxWidth);
    }
   },
   prepareMinLayoutSize: function () {
    var mainElement = this.GetMainElement();
    var buttonGroups = mainElement.querySelectorAll(".dialog-linc.buttons");
    var layoutMinWidth = 0;
    for (var i = 0; i < buttonGroups.length; i++) {
     var buttonGroup = buttonGroups[i];
     var minWidth = 0;
     var separators = buttonGroup.querySelectorAll(".dialog-separator");
     for (var j = 0; j < separators.length; j++)
      minWidth += separators[j].offsetWidth;
     var maxButtonWidth = 0;
     var buttons = buttonGroup.querySelectorAll(".dialog-btn");
     for (var j = 0; j < buttons.length; j++) {
      maxButtonWidth = Math.max(buttons[j].offsetWidth, maxButtonWidth);
      minWidth += ASPx.GetLeftRightMargins(buttons[j]);
     }
     minWidth += maxButtonWidth * buttons.length;
     var buttonWrappers = buttonGroup.querySelectorAll(".dialog-control-wrapper");
     for (var j = 0; j < buttonWrappers.length; j++) {
      ASPx.SetStyles(buttonWrappers[j], { width: maxButtonWidth });
      minWidth += ASPx.GetLeftRightMargins(buttonWrappers[j]);
     }
     ASPx.SetStyles(buttonGroup, { minWidth: minWidth });
     while ((buttonGroup = buttonGroup.parentNode) != mainElement)
      minWidth += ASPx.GetLeftRightBordersAndPaddingsSummaryValue(buttonGroup);
     layoutMinWidth = Math.max(layoutMinWidth, minWidth);
    }
    ASPx.SetStyles(mainElement, { minWidth: layoutMinWidth });
   },
   adjustLogicalRows: function () {
    var rowNumber = 1;
    var mainElement = this.GetMainElement();
    var rowCells = [];
    while ((rowCells = mainElement.querySelectorAll(".d-row-" + rowNumber)).length) {
     var parent = rowCells[0].parentNode;
     var tmpRowCells = [];
     for (var i = 0; i < rowCells.length; i++) {
      if (rowCells[i].parentNode == parent) {
       tmpRowCells.push(rowCells[i]);
      } else {
       if (tmpRowCells.length > 1)
        this.adjustHeightWithinSameRow(tmpRowCells);
       tmpRowCells = [rowCells[i]];
       parent = rowCells[i].parentNode;
      }
     }
     if (tmpRowCells.length > 1)
      this.adjustHeightWithinSameRow(tmpRowCells);
     rowNumber++;
    }
    this.AdjustControlInternal(true);
   },
   adjustHeightWithinSameRow: function (cells) {
    var maxHeight = 0;
    for(var i = 0; i < cells.length; i++) {
     cells[i].style.height = "";
    }
    for (var i = 0; i < cells.length; i++) {
     if (this.getRowSpan(cells[i]) == 1)
      maxHeight = Math.max(cells[i].offsetHeight, maxHeight);
    }
    for (var i = 0; i < cells.length; i++) {
     var cell = cells[i];
     var rowSpan = this.getRowSpan(cell);
     ASPx.SetStyles(cell, { height: maxHeight * rowSpan, marginBottom: -1 * (rowSpan - 1) * maxHeight });
     ASPxClientControl.AdjustControls(cell, true);
    }
   },
   getRowSpan: function (cell) {
    if(!ASPx.IsExists(cell.dataset.rowSpan))
     cell.dataset.rowSpan = cell.className.match(/(?:d-rowspan-)(\d)/)[1];
    return cell.dataset.rowSpan;
   },
   UpdateItemsCssClasses: function (fromHorizontalToVertical) {
    ASPxClientFormLayout.prototype.UpdateItemsCssClasses.call(this, fromHorizontalToVertical);
    if (fromHorizontalToVertical)
     ASPx.AddClassNameToElement(this.GetMainElement(), this.getSingleColumnCssClass());
    else
     ASPx.RemoveClassNameFromElement(this.GetMainElement(), this.getSingleColumnCssClass());
   },
   GetLayoutItemElementsWithHorizontalCaptions: function () {
    return ASPxClientFormLayout.prototype.GetLayoutItemElementsWithHorizontalCaptions.call(this)
     .filter(function (element) {
      return !ASPx.GetParentByClassName(element, "dx-noAdaptive");
     });
   },
   getAdaptiveSelector: function () {
    return "#" + this.name + " .dialog-lg:not(.dx-noAdaptive) > div";
   },
   getAdaptiveSelectorForContainer: function () {
    return this.getAdaptiveSelector() + ", " +
     this.getAdaptiveSelector() + " > .dialog-lgc > .dialog-li > .dialog-linc";
   },
   getAdaptiveSelectorForCaptionCell: function () {
    return this.getAdaptiveSelector() + " > .dialog-lgc > .dialog-li > .dxflCaptionCellSys";
   },
   getAdaptiveContainerStyles: function () {
    return "{ width: 100%!important; float: left; }";
   },
   getAdaptiveCaptionCellStyles: function () {
    return "{ width: 100%!important; float: left;height: auto !important; }";
   },
   calculateSwitchToSingleColumnAtWindowInnerWidth: function () {
    var singleColumnCssClass = this.getSingleColumnCssClass();
    var mainElement = this.GetMainElement();
    var isSingleColumn = ASPx.ElementHasCssClass(mainElement, singleColumnCssClass);
    if (!isSingleColumn)
     ASPx.AddClassNameToElement(mainElement, singleColumnCssClass);
    ASPx.Attr.RemoveStyleAttribute(mainElement, "max-width");
    var singleColumnMaxWidthPx = ASPx.GetCurrentStyle(mainElement).maxWidth;
    ASPx.SetStyles(mainElement, { maxWidth: "none" });
    if (!isSingleColumn)
     ASPx.RemoveClassNameFromElement(mainElement, singleColumnCssClass);
    return ASPx.PxToInt(singleColumnMaxWidthPx) || this.getDefaultSwitchToSingleColumnAtWindowInnerWidth();
   },
   getDefaultSwitchToSingleColumnAtWindowInnerWidth: function () {
    return 700;
   },
   calculateColumnMinWidth: function () {
    return 0;
   },
   isLayoutPrepared: function () {
    return this.layoutPrepared;
   }
  });
  return ASPx.CreateClass(extendentClass, properties);
 };
 ASPx.ClientDialogFormLayout = ASPx.CreateDialogLayoutClass(ASPxClientFormLayout, {});
 var DialogLayoutField = ASPx.CreateClass(null, {
  constructor: function (name, dialogLayout) {
   this.name = name;
   this.dialogLayout = dialogLayout;
  },
  getItem: function () {
   return this.dialogLayout.GetItemByName(this.name);
  },
  getControl: function () {
   return this.getControlWithFallbackStrategy([this.getControlByMapping, this.getDialogLayoutInnerControl, this.getControlByItemId]);
  },
  getControlByMapping: function () {
   return ASPxClientControl.GetControlCollection().Get(this.dialogLayout.controlNameIdMapping[this.name]);
  },
  getDialogLayoutInnerControl: function () {
   return this.dialogLayout.getInnerControl("_" + this.name);
  },
  getControlByItemId: function () {
   var item, control;
   if (item = this.getItem()) {
    var containerId = this.dialogLayout.GetItemElementID(item);
    containerId = containerId.substring(0, containerId.length - item.path.length) + this.name;
    control = window[containerId];
    if (control && !ASPx.Ident.IsASPxClientControl(control) && control.nodeType == 1)
     control = ASPxClientControl.GetControlCollection().Get(containerId);
   }
   return control;
  },
  getControlWithFallbackStrategy: function (gettersArray) {
   var control = null;
   while (gettersArray.length && !(control = gettersArray.shift().call(this))) { }
   return control;
  },
  isEnabled: function () {
   var control = this.getControl();
   return !!control && control.GetEnabled();
  },
  getValue: function () {
   var control = this.getControl();
   return control && control.GetValue();
  }
 });
 ASPx.DialogLayoutField = DialogLayoutField;
ASPx.FormLayoutConsts = FormLayoutConsts;
window.ASPxClientLayoutItem = ASPxClientLayoutItem;
window.ASPxClientFormLayout = ASPxClientFormLayout;
window.ASPxClientFormLayoutUtils = ASPxClientFormLayoutUtils;
})();

(function() {
var MVCxClientFormLayout = ASPx.CreateClass(ASPxClientFormLayout, {
 CreateRootItem: function(){
  return new MVCxClientLayoutItem(this, "", "", null);
 }
});
var MVCxClientLayoutItem = ASPx.CreateClass(ASPxClientLayoutItem, {
 CreateItemInstance: function (name, path) {
  return new MVCxClientLayoutItem(this.formLayout, name, path, this);
 },
 ConfigureByProperties: function(itemProperties){
  ASPxClientLayoutItem.prototype.ConfigureByProperties.call(this, itemProperties);
  var associatedControlName = itemProperties.associatedNestedExtensionName;
  if(ASPx.IsExists(associatedControlName))
   this.EnsureLabelAssociatedElementId(associatedControlName);
 },
 EnsureLabelAssociatedElementId: function(associatedControlName) {
  var labelElement = this.GetLabelElement();
  if(!labelElement) return;
  var associatedControl = ASPx.GetControlCollection().GetByName(associatedControlName);
  var inputElement = associatedControl && associatedControl.GetInputElement && associatedControl.GetInputElement() || ASPx.GetElementById(associatedControlName);
  if(inputElement)
   $(labelElement).attr("for", inputElement.id);
 },
 GetLabelElement: function(){
  var itemElement = this.formLayout.GetHTMLElementByItem(this);
  if (!itemElement)
   return;
  var captionCells = ASPx.GetNodesByClassName(itemElement, ASPx.FormLayoutConsts.CAPTION_CELL_SYSTEM_CLASS_NAME);
  if(!captionCells || captionCells.length == 0)
   return;
  return ASPx.GetNodeByTagName(captionCells[0], "label", 0);
 }
});
window.MVCxClientFormLayout = MVCxClientFormLayout;
window.MVCxClientLayoutItem = MVCxClientLayoutItem;
})();
(function () {
var ASPxClientLoadingPanel = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.containerElementID = "";
  this.containerElement = null;
  this.horizontalOffset = 0;
  this.verticalOffset = 0;
  this.isTextEmpty = false;
  this.showImage = true;
  this.shown = false;
  this.currentoffsetElement = null;
  this.currentX = null;
  this.currentY = null;
 },
 Initialize: function () {
  if(this.containerElementID != "")
   this.containerElement = ASPx.GetElementById(this.containerElementID);
  ASPxClientControl.prototype.Initialize.call(this);
 },
 SetCurrentShowArguments: function (offsetElement, x, y) {
  if(offsetElement == null)
   offsetElement = this.containerElement;
  if(offsetElement && !ASPx.IsValidElement(offsetElement))
   offsetElement = ASPx.GetElementById(offsetElement.id);
  if(offsetElement == null)
   offsetElement = document.body;
  this.SetCurrentoffsetElement(offsetElement);
  this.currentX = x;
  this.currentY = y;
 },
 SetCurrentoffsetElement: function(offsetElement) {
  this.ChangeTabIndexesBehindLoadingDiv(true);
  this.currentoffsetElement = offsetElement;
  delete ASPxClientControl.documentDropDownMouseDownLocked;
 },
 GetCurrentoffsetElement: function() {
  return this.currentoffsetElement;
 },
 ResetCurrentShowArguments: function () {
  this.SetCurrentoffsetElement(null);
  this.currentX = null;
  this.currentY = null;
 },
 SetLoadingPanelPosAndSize: function () {
  var element = this.GetMainElement();
  this.SetLoadingPanelLocation(this.GetCurrentoffsetElement(), element, this.currentX, this.currentY, this.horizontalOffset, this.verticalOffset);
 },
 SetLoadingDivPosAndSize: function () {
  var element = this.GetLoadingDiv();
  if(element != null) {
   ASPx.SetElementDisplay(element, true);
   var offsetElement = this.GetCurrentoffsetElement();
   this.SetLoadingDivBounds(offsetElement, element);
   var activeElement = document.activeElement;
   if(offsetElement.contains(activeElement) && !!activeElement.blur) {
    activeElement.blur();
    if(element.tabIndex === -1)
     element.tabIndex = 0;
   }
   this.ChangeTabIndexesBehindLoadingDiv(false);
   if(offsetElement === document.body)
    ASPxClientControl.documentDropDownMouseDownLocked = true;
  }
 },
 ShowInternal: function (offsetElement, x, y) {
  this.SetCurrentShowArguments(offsetElement, x, y);
  var element = this.GetMainElement();
  ASPx.SetElementDisplay(element, true);
  this.SetLoadingPanelPosAndSize();
  this.SetLoadingDivPosAndSize();
  ASPx.GetControlCollection().AdjustControls(element);
  this.shown = true;
 },
 Show: function () {
  this.ShowInternal(null);
 },
 ShowInElement: function (htmlElement) {
  if(htmlElement)
   this.ShowInternal(htmlElement);
 },
 ShowInElementByID: function (id) {
  var htmlElement = ASPx.GetElementById(id);
  this.ShowInElement(htmlElement);
 },
 ShowAtPos: function (x, y) {
  this.ShowInternal(null, x, y);
 },
 SetText: function (text) {
  this.isTextEmpty = (text == null || text == "");
  var textLabel = this.GetTextLabel();
  if(textLabel)
   textLabel.innerHTML = this.isTextEmpty ? "&nbsp;" : text;
 },
 GetText: function () {
  return this.isTextEmpty ? "" : this.GetTextLabel().innerHTML;
 },
 Hide: function () {
  var element = this.GetMainElement();
  ASPx.SetElementDisplay(element, false);
  element = this.GetLoadingDiv();
  if(element != null) {
   ASPx.SetStyles(element, { width: 1, height: 1 });
   ASPx.SetElementDisplay(element, false);
   element.tabIndex = -1;
  }
  this.ResetCurrentShowArguments();
  this.shown = false;
 },
 GetTextLabel: function () {
  return this.GetChildElement("TL");
 },
 GetVisible: function () {
  return ASPx.GetElementDisplay(this.GetMainElement());
 },
 SetVisible: function (visible) {
  if(visible && !this.IsVisible())
   this.Show();
  else if(!visible && this.IsVisible())
   this.Hide();
 },
 BrowserWindowResizeSubscriber: function () {
  return true;
 },
 OnBrowserWindowResize: function () {
  if(this.shown) {
   this.SetLoadingPanelPosAndSize();
   this.SetLoadingDivPosAndSize();
  }
 },
 ChangeTabIndexesBehindLoadingDiv: function(restore) {
  var offsetElement = this.GetCurrentoffsetElement();
  if(!this.GetLoadingDiv() || !offsetElement) return;
  var elements = restore ? this.elementsToRestoreTabIndex : ASPx.GetCanBeActiveElementsInContainer(offsetElement);
  this.elementsToRestoreTabIndex = [];
  ASPx.Data.ForEach(elements, function(element) {
   var manager = ASPx.ControlTabIndexManager.getInstance();
   if(restore)
    manager.restoreTabIndexAttribute(element, this.GetMainElement().id);
   else {
    this.elementsToRestoreTabIndex.push(element);
    manager.changeTabIndexAttribute(element, this.GetMainElement().id);
   }
  }.aspxBind(this));
 }
});
ASPxClientLoadingPanel.Cast = ASPxClientControl.Cast;
window.ASPxClientLoadingPanel = ASPxClientLoadingPanel;
})();

(function(){
 var MVCxClientMenu = ASPx.CreateClass(ASPxClientMenu, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.callbackUrl = "";
  },
  InlineInitialize: function() {
   if(this.callbackUrl != "")
    this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), null); }; 
   ASPxClientMenu.prototype.InlineInitialize.call(this);
  },
  CreateCallbackByInfo: function(arg, command, callbackInfo) {
   this.CreateCallbackInternal(arg, command, true, callbackInfo);
  },
  GetCallbackParams: function(){
   var params = {};
   MVCx.AddCallbackParam(params, this.GetStateHiddenField());
   return params;
  },
  OnCallbackGeneralError: function(errorMessage) {
   ASPxClientMenu.prototype.OnCallbackGeneralError.call(this, errorMessage);
   if(!this.serverExceptionOnLastCallback)
    MVCx.ThrowExceptionOnCallback();
  }
 });
 window.MVCxClientMenu = MVCxClientMenu;
})();

(function(){
 var MVCxClientPopupMenu = ASPx.CreateClass(ASPxClientPopupMenu, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.callbackUrl = "";
  },
  InlineInitialize: function() {
   if(this.callbackUrl != "")
    this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), null); }; 
   ASPxClientPopupMenu.prototype.InlineInitialize.call(this);
  },
  CreateCallbackByInfo: function(arg, command, callbackInfo) {
   this.CreateCallbackInternal(arg, command, true, callbackInfo);
  },
  GetCallbackParams: function(){
   var params = {};
   MVCx.AddCallbackParam(params, this.GetStateHiddenField());
   return params;
  },
  OnCallbackGeneralError: function(errorMessage) {
   ASPxClientPopupMenu.prototype.OnCallbackGeneralError.call(this, errorMessage);
   if(!this.serverExceptionOnLastCallback)
    MVCx.ThrowExceptionOnCallback();
  }
 });
 window.MVCxClientPopupMenu = MVCxClientPopupMenu;
})();

(function () {
var NavBarCssClasses = {};
NavBarCssClasses.Prefix = "dxnb-";
NavBarCssClasses.Disabled = "dxnbLiteDisabled";
NavBarCssClasses.Group = NavBarCssClasses.Prefix + "gr";
NavBarCssClasses.GroupHeader = NavBarCssClasses.Prefix + "header";
NavBarCssClasses.GroupHeaderCollapsed = NavBarCssClasses.Prefix + "headerCollapsed";
NavBarCssClasses.GroupHeaderText = NavBarCssClasses.Prefix + "ghtext";
NavBarCssClasses.GroupContent = NavBarCssClasses.Prefix + "content";
NavBarCssClasses.Template = NavBarCssClasses.Prefix + "tmpl";
NavBarCssClasses.Link = NavBarCssClasses.Prefix + "link";
NavBarCssClasses.Image = NavBarCssClasses.Prefix + "img";
NavBarCssClasses.LastItem = NavBarCssClasses.Prefix + "last";
var NavBarRenderHelper = ASPx.CreateClass(null, {
 constructor: function(navBar) {
  this.navBar = navBar;
  this.itemLinkModes = {};
 },
 InlineInitializeElements: function() {
  this.AssignElementsAttributes();
 },
 AssignElementsAttributes: function () {
  var mainElement = this.navBar.GetMainElement();
  if(mainElement.style.width && !ASPx.IsPercentageSize(mainElement.style.width)) {
   mainElement.style.width = ASPx.PxToInt(mainElement.style.width) -
    ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainElement) + 'px';
  }
  if(!ASPx.ElementContainsCssClass(mainElement, NavBarCssClasses.Disabled)) {
   var groupElements = this.GetGroupElements(mainElement);
   var groupIndex = 0;
   for(var i = 0; i < groupElements.length; i++) {
    while(!this.navBar.groups[groupIndex].visible)
     groupIndex++;
    this.AssignGroupAttributes(groupElements[i], groupIndex);
    groupIndex++;
   }
  }
 },
 AssignGroupAttributes: function (groupElement, groupIndex) {
  if(groupElement.className.indexOf("dxnb-ti") > 1)
   this.itemLinkModes[groupIndex] = "TextAndImage";
  else if(groupElement.className.indexOf("dxnb-t") > -1)
   this.itemLinkModes[groupIndex] = "TextOnly";
  else
   this.itemLinkModes[groupIndex] = "ContentBounds";
  groupElement.id = this.PrepareElementID(this.navBar.GetGroupRowElementID(groupIndex));
  var headerElements = this.GetGroupHeaderElements(groupElement);
  for(var i = 0; i < headerElements.length; i++) 
   this.AssignGroupHeaderAttributes(headerElements[i], groupIndex);
  var contentElement = this.GetGroupContentElement(groupElement);
  this.AssignGroupContentAttributes(contentElement, groupIndex);
 },
 AssignGroupHeaderAttributes: function (headerElement, groupIndex) {
  if(!headerElement) return;
  headerElement.id = this.PrepareElementID(this.navBar.GetGroupHeaderElementID(groupIndex, !this.IsGroupHeaderCollapsed(headerElement)));
  var navBarName = this.navBar.name;
  if(this.navBar.mouseOverExpand)
   ASPx.Evt.AttachEventToElement(headerElement, "mouseover", function(event) { ASPx.NBHMMove(event, navBarName, groupIndex); });
  else if(this.navBar.autoPostBack && !this.navBar.IsClientSideEventsAssigned())
   ASPx.Evt.AttachEventToElement(headerElement, "click", function() { this.SendPostBack("HEADERCLICK:" + groupIndex); }.aspxBind(this.navBar));
  else
   ASPx.Evt.AttachEventToElement(headerElement, "click", function(event) { ASPx.NBHClick(event, navBarName, groupIndex); });
  if(this.navBar.IsStateControllerEnabled())
   ASPx.AssignAccessibilityEventsToChildrenLinks(headerElement, true);
 },
 AssignGroupContentAttributes: function (contentElement, groupIndex) {
  if(!contentElement) return;
  contentElement.id = this.PrepareElementID(this.navBar.GetGroupContentElementID(groupIndex));
  if(!this.HasContentTemplate(contentElement)) {
   var itemElements = this.GetItemElements(contentElement);
   var itemIndex = 0;
   var group = this.navBar.groups[groupIndex];
   for(var i = 0; i < itemElements.length; i++) {
    while(!group.items[itemIndex].visible)
     itemIndex++;
    this.AssignItemAttributes(itemElements[i], groupIndex, itemIndex);
    itemIndex++;
   }
  }
 },
 AssignItemAttributes: function (itemElement, groupIndex, itemIndex) {
  var indexPath = this.navBar.GetIndexPath(groupIndex, itemIndex);
  itemElement.id = this.PrepareElementID(this.navBar.GetItemElementID(indexPath));
  if(this.navBar.IsStateControllerEnabled())
   ASPx.AssignAccessibilityEventsToChildrenLinks(itemElement, true);
  if(this.HasItemTemplate(itemElement)) return;
  if(!this.IsItemDisabled(itemElement))
   this.AssignItemOnClick(itemElement, groupIndex, itemIndex);
  var itemLink = this.GetItemLinkElement(itemElement);
  if(itemLink)
   itemLink.id = this.PrepareElementID(this.navBar.GetItemLinkID(indexPath));
  var itemImg = this.GetItemImageElement(itemElement);
  if(itemImg)
   itemImg.id = this.PrepareElementID(this.navBar.GetItemImageID(indexPath));
 },
 AssignItemOnClick: function(itemElement, groupIndex, itemIndex) {
  var onclick = this.GetItemOnClick(this.navBar.name, itemElement, groupIndex, itemIndex);
  this.AssignItemOnClickToElement(itemElement, this.itemLinkModes[groupIndex], onclick);
 },
 AssignItemOnClickToElement: function(element, itemLinkMode, method) {
  switch(itemLinkMode){
   case "ContentBounds":
    ASPx.Evt.AttachEventToElement(element, "click", method);
    break;
   case "TextOnly":
    var textElement = ASPx.GetNodeByTagName(element, "A");
    if(!textElement)
     textElement = ASPx.GetNodeByTagName(element, "SPAN");
    if(textElement)
     ASPx.Evt.AttachEventToElement(textElement, "click", method);
    break;
   case "TextAndImage":
    var linkElement = ASPx.GetNodeByTagName(element, "A");
    if(linkElement)
     ASPx.Evt.AttachEventToElement(linkElement, "click", method);
    else{
     var textElement = ASPx.GetNodeByTagName(element, "SPAN");
     if(textElement)
      ASPx.Evt.AttachEventToElement(textElement, "click", method);
     var imageElement = ASPx.GetNodeByTagName(element, "IMG");
     if(imageElement)
      ASPx.Evt.AttachEventToElement(imageElement, "click", method);
    }
    break;
  }
 },
 GetItemOnClick: function(name, itemElement, groupIndex, itemIndex) {
  var navBar = this.navBar;
  var sendPostBackHandler = function() {
   navBar.SendPostBack("CLICK:" + navBar.GetIndexPath(groupIndex, itemIndex));
  };
  var itemClickHandler = function(e) {
   ASPx.NBIClick(e, name, groupIndex, itemIndex);
  };
  var itemLink = ASPx.GetNodeByTagName(itemElement, "A");
  var handler = navBar.autoPostBack && !navBar.IsClientSideEventsAssigned() && (!itemLink || itemLink.href === "")
   ? sendPostBackHandler
   : itemClickHandler;
  return function(e) {
   if(!itemElement.clientDisabled)
    handler(e);
  };
 },
 HasContentTemplate: function (contentElement) {
  return false;
 },
 HasItemTemplate: function (itemElement) {
  return ASPx.ElementContainsCssClass(itemElement, NavBarCssClasses.Template);
 },
 IsItemDisabled: function (itemElement) {
  return ASPx.ElementContainsCssClass(itemElement, NavBarCssClasses.Disabled);
 },
 GetGroupElements: function(mainElement) {
  return ASPx.GetChildElementNodes(mainElement);
 },
 GetGroupHeaderElements: function(groupElement) {
  return ASPx.GetChildNodesByPartialClassName(groupElement, NavBarCssClasses.GroupHeader);
 },
 IsGroupHeaderCollapsed: function(headerElement) {
  return headerElement.className.indexOf("Collapsed") > -1;
 },
 GetGroupContentElement: function(groupElement) {
  return ASPx.GetNodesByPartialClassName(groupElement, NavBarCssClasses.GroupContent)[0];
 },
 GetItemElements: function(contentElement) {
  return ASPx.GetChildNodesByTagName(contentElement, "LI");
 },
 GetItemLinkElement: function(itemElement) {
  return ASPx.GetNodesByPartialClassName(itemElement, NavBarCssClasses.Link)[0];
 },
 GetItemImageElement: function(itemElement) {
  return ASPx.GetNodesByPartialClassName(itemElement, NavBarCssClasses.Image)[0];
 },
 PrepareElementID: function (id) {
  return this.navBar.name + id;
 }
});
var ASPxClientNavBar = ASPx.CreateClass(ASPxClientControl, {
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.animationDuration = 200;
  this.autoCollapse = false;
  this.allowExpanding = true;
  this.allowSelectItem = false;
  this.cookieName = "";
  this.groupCount = 0;
  this.enableAnimation = false;
  this.groups = [];
  this.groupsExpanding = [];
  this.groupsExpandingRequest = [];
  this.selectedItemIndexPath = "";
  this.renderHelper = this.CreateRenderHelper();
  this.mouseOverExpand = false;
  this.mouseOverActionDelay = 300;
  this.mouseOverActionTimerID = -1;
  this.ItemClick = new ASPxClientEvent();
  this.ExpandedChanged = new ASPxClientEvent();
  this.ExpandedChanging = new ASPxClientEvent();
  this.HeaderClick = new ASPxClientEvent();
 },
 SetData: function(data){
  if(data.groups)
   this.CreateGroups(data.groups);
 },
 InlineInitialize: function () {
  ASPxClientControl.prototype.InlineInitialize.call(this);
  this.renderHelper.InlineInitializeElements();
  this.InitializeSelectedItem();
  this.InitializeEnabledAndVisible();
  this.UpdateLastGroupClassName();
 },
 UpdateLastGroupClassName: function () {
  var visibleItems = [];
  for (var i = 0; i < this.groups.length; i++) {
   if (this.groups[i].GetVisible())
    visibleItems.push(this.groups[i]);
   var element = this.GetGroupRow(this.groups[i].index);
   ASPx.RemoveClassNameFromElement(element, NavBarCssClasses.LastItem);
  }
  var lastGroup = visibleItems[visibleItems.length - 1];
  if (lastGroup)
   ASPx.AddClassNameToElement(this.GetGroupRow(lastGroup.index), NavBarCssClasses.LastItem);
 },
 InitializeEnabledAndVisible: function () {
  for(var i = 0; i < this.groups.length; i++) {
   this.SetGroupVisible(i, this.groups[i].clientVisible, true);
   this.InitializeGroupItemsEnabledAndVisible(i);
  }
 },
 InitializeGroupItemsEnabledAndVisible: function (groupIndex) {
  var group = this.groups[groupIndex];
  for(var j = 0; j < group.items.length; j++) {
   this.SetItemEnabled(groupIndex, j, group.items[j].clientEnabled, true);
   this.SetItemVisible(groupIndex, j, group.items[j].clientVisible, true);
  }
 },
 InitializeSelectedItem: function () {
  if(!this.allowSelectItem) return;
  this.SelectItem(this.GetSelectedItemIndexPath());
 },
 InitializeCallBackData: function () {
  for(var i = 0; i < this.GetGroupCountCore() ; i++) {
   if(this.groupsExpanding[i]) {
    var element = this.GetGroupContentElement(i);
    if(element != null) element.loaded = true;
   }
  }
 },
 CreateRenderHelper: function() {
  return new NavBarRenderHelper(this);
 },
 IsClientSideEventsAssigned: function() {
  return !this.ItemClick.IsEmpty()
   || !this.ExpandedChanged.IsEmpty()
   || !this.ExpandedChanging.IsEmpty()
   || !this.HeaderClick.IsEmpty()
   || !this.Init.IsEmpty();
 },
 applyAccessibilityAttributes: function() {
  this.applyHeaderItemsAccessibilityAttributes();
  this.applyContentItemsAccessibilityAttributes();
 },
 applyHeaderItemsAccessibilityAttributes: function() {
  this.setAriaDescription("");
  this.setAriaDescription("groupHeaderContainer");
  this.setAriaDescription("groupHeaderItem");
 },
 applyContentItemsAccessibilityAttributes: function() {
  this.setAriaDescription("contentItemsContainer");
  this.setAriaDescription("contentItemContainer");
  this.setAriaDescription("contentItem");
  this.setAriaDescription("presentationElements");
 },
 AdjustControlCore: function () {
  this.CorrectGroupHeaderText();
  this.ShrinkWrappedText(this.GetGroupHeaderElements, "Headers");
  this.ShrinkWrappedText(this.GetItemLinkElements, "Items");
  this.CorrectWrappedText(this.GetGroupHeaderElements, "Headers");
  this.CorrectWrappedText(this.GetItemLinkElements, "Items");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetGroupHeaderElements, "Headers", true);
 },
 CorrectGroupHeaderText: function () {
  var elements = ASPx.CacheHelper.GetCachedElements(this, "headerElementsCache", this.GetGroupHeaderElements);
  var hasHeaderButtonOnLeft;
  var textElementMargin;
  for(var i = 0; i < elements.length; i++) {
   if(elements[i].textCorrected || elements[i].offsetWidth == 0) continue;
   this.CorrectGroupHeaderTextElement(elements[i]);
   if(!elements[i].needExpandButtonReplacement) {
    elements[i].textCorrected = true;
    if(!textElementMargin) {
     var btnElement = this.GetGroupHeaderButton(elements[i]);
     if(btnElement) {
      hasHeaderButtonOnLeft = ASPx.GetElementFloat(btnElement) == "left";
      textElementMargin = this.GetGroupHeaderTextElementMargin(btnElement);
     }
    }
   }
  }
  for(var i = 0; i < elements.length; i++) {
   if(!elements[i].textCorrected && elements[i].needExpandButtonReplacement) {
    if(textElementMargin) {
     var textElementStyle = {};
     textElementStyle[hasHeaderButtonOnLeft ? "marginLeft" : "marginRight"] = textElementMargin;
     this.CorrectGroupHeaderTextElementStyle(elements[i], textElementStyle);
     elements[i].textCorrected = true;
    }
   }
  }
 },
 CorrectGroupHeaderTextElement: function (element) {
  var btnElement = this.GetGroupHeaderButton(element);
  if(btnElement) {
   if(!ASPx.IsElementRightToLeft(this.GetMainElement()))
    this.CorrectGroupHeaderTextElementStyle(element, { marginRight: this.GetGroupHeaderTextElementMargin(btnElement) });
  }
  else
   element.needExpandButtonReplacement = true;
 },
 CorrectGroupHeaderTextElementStyle: function (element, textElementStyle) {
  var textElements = ASPx.GetChildNodesByClassName(element, NavBarCssClasses.GroupHeaderText);
  if(textElements.length > 0)
   ASPx.SetStyles(textElements[0], textElementStyle, true);
 },
 GetGroupHeaderButton: function (element) {
  var btnElements = ASPx.GetChildNodesByClassName(element, "dxnb-btn");
  if(btnElements.length == 0)
   btnElements = ASPx.GetChildNodesByClassName(element, "dxnb-btnLeft");
  return btnElements.length > 0 ? btnElements[0] : null;
 },
 GetGroupHeaderTextElementMargin: function (btnElement) {
  return btnElement ? btnElement.offsetWidth + ASPx.GetLeftRightMargins(btnElement) : 0;
 },
 GetGroupHeaderElementID: function (index, expanded) {
  return "_GH" + (expanded ? "E" : "C") + index;
 },
 GetClickableGroupHeaderElement: function (index) {
  var isDisplayed = false;
  var element = this.GetGroupHeaderExpandedElement(index);
  if(element != null) isDisplayed = !ASPx.GetElementDisplay(element) || !this.allowExpanding;
  if(!isDisplayed)
   element = this.GetGroupHeaderCollapsedElement(index);
  return element;
 },
 GetGroupContentElementID: function (index) {
  return "_GC" + index;
 },
 GetGroupRowElementID: function(index) {
  return "_GR" + index;
 },
 GetItemElementID: function (indexPath) {
  return "_I" + indexPath + "_";
 },
 GetItemLinkID: function (indexPath) {
  return this.GetItemElementID(indexPath) + "T";
 },
 GetItemImageID: function (indexPath) {
  return this.GetItemElementID(indexPath) + "Img";
 },
 GetGroupHeaderExpandedElement: function (index) {
  return this.GetGroupHeaderElement(index, true);
 },
 GetGroupHeaderCollapsedElement: function (index) {
  return this.GetGroupHeaderElement(index, false);
 },
 GetGroupHeaderElement: function(index, expanded) {
  return this.GetChildElement(this.GetGroupHeaderElementID(index, expanded));
 },
 GetGroupHeaderElements: function () {
  var elements = [];
  elements = elements.concat(ASPx.GetNodesByClassName(this.GetMainElement(), NavBarCssClasses.GroupHeader));
  elements = elements.concat(ASPx.GetNodesByClassName(this.GetMainElement(), NavBarCssClasses.GroupHeaderCollapsed));
  return elements;
 },
 GetGroupHeaderTextElements: function(index) {
  var groupRow = this.GetGroupRow(index);
  return groupRow ? ASPx.GetNodesByClassName(groupRow, NavBarCssClasses.GroupHeaderText) : null;
 },
 GetItemLinkElements: function () {
  return ASPx.GetNodesByClassName(this.GetMainElement(), NavBarCssClasses.Link);
 },
 GetGroupContentElement: function (index) {
  return this.GetChildElement(this.GetGroupContentElementID(index));
 },
 GetGroupContentAnimationElement: function (index) {
  return this.GetGroupContentElement(index);
 },
 GetItemElement: function (groupIndex, itemIndex) {
  return this.GetItemElementByIndexPath(this.GetIndexPath(groupIndex, itemIndex));
 },
 GetMarkedLastItemElement: function(groupIndex) {
  var groupContent = this.GetGroupContentElement(groupIndex);
  return ASPx.GetChildByClassName(groupContent, NavBarCssClasses.LastItem);
 },
 GetLastVisibleItemElement: function(groupIndex) {
  var group = this.GetGroup(groupIndex),
   items = group.items;
  for(var i = items.length - 1; i >= 0; i--) {
   var item = items[i];
   if(item.GetVisible())
    return this.GetItemElement(groupIndex, item.index);
  }
 },
 GetItemSeparatorElement: function (groupIndex, itemIndex) {
  return this.GetChildElement("I" + this.GetIndexPath(groupIndex, itemIndex) + "S");
 },
 GetItemElementByIndexPath: function (indexPath) {
  return this.GetChildElement(this.GetItemElementID(indexPath));
 },
 GetItemTextElementByIndexPath: function (indexPath) {
  return this.GetChildElement(this.GetItemElementID(indexPath) + "T");
 },
 GetItemImageElementByIndexPath: function (indexPath) {
  return this.GetChildElement(this.GetItemElementID(indexPath) + "I");
 },
 GetGroupRow: function (groupIndex) {
  return this.GetChildElement(this.GetGroupRowElementID(groupIndex));
 },
 GetGroupSeparatorRow: function (groupIndex) {
  return this.GetChildElement("GSR" + groupIndex);
 },
 DoItemClick: function (groupIndex, itemIndex, hasItemLink, htmlEvent) {
  var processOnServer = this.RaiseItemClick(groupIndex, itemIndex, htmlEvent);
  if(processOnServer && !hasItemLink)
   this.SendPostBack("CLICK:" + this.GetIndexPath(groupIndex, itemIndex));
 },
 GetAutoCollapseCoGroupIndex: function (groupIndex) {
  if(this.autoCollapse) {
   for(var i = 0; i < this.GetGroupCountCore() ; i++) {
    if(!this.groups[i].GetVisible()) continue;
    if(i != groupIndex && this.groupsExpanding[i])
     return i;
   }
  }
  return -1;
 },
 SetExpandedInternal: function (groupIndex, expanded) {
  if(expanded == this.groupsExpanding[groupIndex] || !this.GetGroupHeaderElement(groupIndex, expanded))
   return;
  var processingMode = this.RaiseExpandedChanging(groupIndex);
  if(processingMode == "Client") {
   if(expanded || !this.autoCollapse)
    this.ChangeExpanding(groupIndex, expanded);
  }
  else if(processingMode == "Server")
   this.SendPostBack("EXPAND:" + groupIndex);
 },
 ChangeExpanding: function (groupIndex, expanded) {
  var element = this.GetGroupContentElement(groupIndex);
  var autoCollapseCoGroupIndex = this.GetAutoCollapseCoGroupIndex(groupIndex);
  if(expanded && ASPx.IsFunction(this.callBack) && element != null && !element.loaded) {
   this.DoChangeExpanding(groupIndex, autoCollapseCoGroupIndex, expanded, false, false, true);
   if(!element.loading) {
    element.loading = true;
    this.groupsExpandingRequest.push(groupIndex);
    this.ShowLoadingPanelInGroup(groupIndex);
    this.CreateCallback(groupIndex);
   }
  }
  else
   this.DoChangeExpanding(groupIndex, autoCollapseCoGroupIndex, expanded, this.enableAnimation, true, true);
  if(this.accessibilityCompliant)
   this.changeExpandingAccessible(groupIndex, expanded);
 },
 changeExpandingAccessible: function(groupIndex, expanded) {
  var headerElement = this.GetGroupHeaderElement(groupIndex, expanded);
  var link = ASPx.GetNodeByTagName(headerElement, "A", 0);
  if(link) {
   ASPx.Attr.SetAttribute(link, "aria-expanded", expanded ? "true" : "false");
   link.focus();
  }
 },
 DoChangeExpanding: function (groupIndex, autoCollapseCoGroupIndex, expanded, doAnimation, raiseChangedEvent, raiseCoGroupChangedEvent) {
  this.ChangeGroupExpandState(groupIndex, expanded);
  if(autoCollapseCoGroupIndex > -1)
   this.ChangeGroupExpandState(autoCollapseCoGroupIndex, !expanded);
  if(doAnimation)
   this.DoChangeExpandingWithAnimation(groupIndex, autoCollapseCoGroupIndex, expanded);
  else
   this.DoChangeExpandingWithoutAnimation(groupIndex, autoCollapseCoGroupIndex, expanded, raiseChangedEvent, raiseCoGroupChangedEvent);
 },
 DoChangeExpandingWithoutAnimation: function (groupIndex, autoCollapseCoGroupIndex, expanded, raiseChangedEvent, raiseCoGroupChangedEvent) {
  this.ChangeGroupElementsExpandState(groupIndex, expanded);
  if(autoCollapseCoGroupIndex > -1)
   this.ChangeGroupElementsExpandState(autoCollapseCoGroupIndex, !expanded);
  if(raiseCoGroupChangedEvent && autoCollapseCoGroupIndex > -1)
   this.RaiseExpandedChanged(autoCollapseCoGroupIndex);
  if(raiseChangedEvent)
   this.RaiseExpandedChanged(groupIndex);
 },
 DoChangeExpandingWithAnimation: function (groupIndex, autoCollapseCoGroupIndex, expanded) {
  var controlHeight = this.GetMainElement().offsetHeight, endHeight = 0;
  var element = this.GetGroupContentAnimationElement(groupIndex);
  if(element != null) {
   element.expanding = expanded;
   endHeight = this.GetGroupContentEndHeight(element, expanded);
   this.PrepareGroupElementsForAnimation(groupIndex, expanded, 0);
  }
  if(autoCollapseCoGroupIndex > -1)
   this.PrepareGroupElementsForAnimation(autoCollapseCoGroupIndex, !expanded, controlHeight - this.GetMainElement().offsetHeight);
  if(element != null)
   this.StartAnimation(element, this.GetGroupContentStartHeight(element, expanded), endHeight, function (element) { this.OnAnimationComplete(groupIndex); }.aspxBind(this));
  if(autoCollapseCoGroupIndex > -1) {
   var groupContentElement = this.GetGroupContentAnimationElement(autoCollapseCoGroupIndex);
   if(groupContentElement)
    this.StartAnimation(groupContentElement, groupContentElement.offsetHeight, 0, function (element) { this.OnAnimationCompleteAutoCollapseGroup(autoCollapseCoGroupIndex); }.aspxBind(this));
  }
 },
 StartAnimation: function (element, from, to, onComplete) {
  var transition = ASPx.AnimationHelper.createAnimationTransition(element, {
   property: "height", unit: "px",
   duration: this.animationDuration,
   onComplete: onComplete
  });
  transition.Start(from, to);
 },
 OnAnimationCompleteAutoCollapseGroup: function (groupIndex) {
  this.ChangeGroupElementsExpandState(groupIndex, false);
  var element = this.GetGroupContentAnimationElement(groupIndex);
  if(element)
   ASPx.SetStyles(element, { height: "" });
  this.RaiseExpandedChanged(groupIndex);
 },
 OnAnimationComplete: function (groupIndex) {
  var element = this.GetGroupContentAnimationElement(groupIndex);
  if(element) {
   this.ChangeGroupElementsExpandState(groupIndex, element.expanding);
   ASPx.SetStyles(element, { overflow: "", height: "", width: "" });
   this.RaiseExpandedChanged(groupIndex);
  }
 },
 PrepareGroupElementsForAnimation: function (groupIndex, expanding, heightCorrection) {
  var element = this.GetGroupContentAnimationElement(groupIndex);
  var contentElement = this.GetGroupContentElement(groupIndex);
  if(!element || !contentElement)
   return;
  element.style.overflow = "hidden";
  if(expanding) {
   element.style.height = "0px";
   this.SetGroupElementDisplay(contentElement, true);
  }
  else {
   var height = element.offsetHeight + heightCorrection;
   if(height >= 0)
    ASPx.SetOffsetHeight(element, height);
  }
 },
 GetGroupContentEndHeight: function (element, expanding) {
  if(!expanding)
   return 0;
  var container = element;
  var display = ASPx.GetElementDisplay(container);
  ASPx.SetElementDisplay(container, true);
  var height = ASPx.GetClearClientHeight(element);
  ASPx.SetElementDisplay(container, display);
  return height;
 },
 GetGroupContentStartHeight: function (element, expanding) {
  return expanding ? 0 : element.offsetHeight;
 },
 ChangeGroupExpandState: function (groupIndex, expanded) {
  this.groupsExpanding[groupIndex] = expanded;
  this.UpdateGroupStateCookie();
 },
 ChangeGroupElementsExpandState: function (groupIndex, expanded) {
  this.SetGroupElementDisplay(this.GetGroupContentElement(groupIndex), expanded);
  this.SetGroupElementDisplay(this.GetGroupHeaderExpandedElement(groupIndex), expanded);
  this.SetGroupElementDisplay(this.GetGroupHeaderCollapsedElement(groupIndex), !expanded);
  if(expanded)
   ASPx.GetControlCollection().AdjustControls(this.GetGroupContentElement(groupIndex), true);
  this.CorrectGroupHeaderText();
  this.ShrinkWrappedText(this.GetGroupHeaderElements, "Headers");
  this.ShrinkWrappedText(this.GetItemLinkElements, "Items");
  this.CorrectWrappedText(this.GetGroupHeaderElements, "Headers");
  this.CorrectWrappedText(this.GetItemLinkElements, "Items");
  this.CorrectVerticalAlignment(ASPx.AdjustVerticalMarginsInContainer, this.GetGroupHeaderElements, "Headers");
 },
 SetGroupElementDisplay: function (groupElement, value) {
  if(groupElement != null)
   ASPx.SetElementDisplay(groupElement, value);
 },
 GetGroupCountCore: function () {
  return (this.groups.length > 0) ? this.groups.length : this.groupCount;
 },
 GetIndexPath: function (groupIndex, itemIndex) {
  return (groupIndex != -1 && itemIndex != -1) ? groupIndex + ASPx.ItemIndexSeparator + itemIndex : "";
 },
 GetGroupIndex: function (indexPath) {
  var indexes = indexPath.split(ASPx.ItemIndexSeparator);
  return (indexes.length > 0) ? indexes[0] : -1;
 },
 GetItemIndex: function (indexPath) {
  var indexes = indexPath.split(ASPx.ItemIndexSeparator);
  return (indexes.length > 1) ? indexes[1] : -1;
 },
 GetGroupState: function () {
  var state = "";
  for(var i = 0; i < this.GetGroupCountCore() ; i++) {
   state += this.groupsExpanding[i] ? "1" : "0";
   if(i < this.GetGroupCountCore() - 1) state += ";";
  }
  return state;
 },
 UpdateGroupStateCookie: function () {
  if(this.cookieName == "") return;
  ASPx.Cookie.DelCookie(this.cookieName);
  ASPx.Cookie.SetCookie(this.cookieName, this.GetGroupState());
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ selectedItemIndexPath: this.selectedItemIndexPath, groupsExpanding: this.GetGroupState() });
 },
 SelectItem: function (indexPath) {
  if(!this.IsStateControllerEnabled()) return;
  var element = this.GetSelectingItemElement(indexPath);
  if(element != null) ASPx.GetStateController().SelectElementBySrcElement(element);
 },
 DeselectItem: function (indexPath) {
  if(!this.IsStateControllerEnabled()) return;
  var element = this.GetSelectingItemElement(indexPath);
  if(element != null) ASPx.GetStateController().DeselectElementBySrcElement(element);
 },
 GetSelectingItemElement: function (indexPath) {
  return this.GetItemElementByIndexPath(indexPath);
 },
 GetSelectedItemIndexPath: function () {
  return this.selectedItemIndexPath;
 },
 SetSelectedItemInternal: function (groupIndex, itemIndex) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  if(this.allowSelectItem) {
   this.DeselectItem(this.selectedItemIndexPath);
   this.selectedItemIndexPath = indexPath;
   var group = this.GetGroup(groupIndex);
   var item = group ? group.GetItem(itemIndex) : null;
   if(item == null || item.GetEnabled())
    this.SelectItem(this.selectedItemIndexPath);
  }
 },
 OnHeaderClick: function (groupIndex, evt) {
  this.ClearMouseMoverTimer();
  var processingMode = this.RaiseHeaderClick(groupIndex, evt);
  var linkElement = (evt != null) ? ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(evt), "A") : null;
  if(linkElement == null || linkElement.href == ASPx.AccessibilityEmptyUrl) {
   if(processingMode == "Client" && this.allowExpanding) {
    var expanded = this.groupsExpanding[groupIndex];
    this.SetExpandedInternal(groupIndex, !expanded);
    if(evt != null && this.IsStateControllerEnabled())
     ASPx.UpdateHoverState(evt);
   }
   else if(processingMode == "Server")
    this.SendPostBack("HEADERCLICK:" + groupIndex);
  }
 },
 OnHeaderMouseMove: function (groupIndex, evt) {
  if(MouseOverActiveNavBar != this || MouseOverActiveGroupIndex != groupIndex) {
   MouseOverActiveNavBar = this;
   MouseOverActiveGroupIndex = groupIndex;
   this.ClearMouseMoverTimer();
   this.mouseOverActionTimerID = window.setTimeout(function() {
    this.OnHeaderMouseMoveTimer(groupIndex);
   }.aspxBind(this), this.mouseOverActionDelay);
  }
 },
 OnHeaderMouseMoveTimer: function (groupIndex) {
  this.ClearMouseMoverTimer();
  if(MouseOverActiveNavBar == this || MouseOverActiveGroupIndex == groupIndex)
   this.OnHeaderClick(groupIndex, null);
 },
 ClearMouseMoverTimer: function () {
  if(this.mouseOverActionTimerID > -1) {
   ASPx.Timer.ClearTimer(this.mouseOverActionTimerID);
   this.mouseOverActionTimerID = -1;
  }
 },
 OnItemClick: function (groupIndex, itemIndex, evt) {
  var element = this.GetItemElement(groupIndex, itemIndex);
  var clickedLinkElement = ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(evt), "A");
  var isLinkClicked = (clickedLinkElement != null && clickedLinkElement.href != ASPx.AccessibilityEmptyUrl);
  var linkElement = (element != null) ? (element.tagName === "A" ? element : ASPx.GetNodeByTagName(element, "A", 0)) : null;
  if(linkElement != null && linkElement.href == ASPx.AccessibilityEmptyUrl)
   linkElement = null;
  if(this.IsStateControllerEnabled())
   ASPx.ClearHoverState();
  this.SetSelectedItemInternal(groupIndex, itemIndex);
  if(this.IsStateControllerEnabled())
   ASPx.UpdateHoverState(evt);
  this.DoItemClick(groupIndex, itemIndex, isLinkClicked || (linkElement != null), evt);
  if(!isLinkClicked && linkElement != null)
   ASPx.Url.NavigateByLink(linkElement);
 },
 OnCallback: function (result) {
  this.OnCallbackInternal(result.html, result.index, false);
 },
 OnCallbackError: function (result, data) {
  this.OnCallbackInternal(result, data, true);
 },
 OnCallbackInternal: function (html, index, isError) {
  this.SetCallbackContent(html, index, isError);
  ASPx.Data.ArrayRemoveAt(this.groupsExpandingRequest, 0);
  if(this.enableCallbackAnimation)
   ASPx.AnimationHelper.fadeIn(this.GetGroupContentElement(index), function () { this.OnCallbackFinish(index, isError); }.aspxBind(this));
  else
   this.OnCallbackFinish(index, isError);
 },
 OnCallbackFinish: function (index, isError) {
  if(!isError) {
   this.InitializeGroupItemsEnabledAndVisible(index);
   this.ClearWrappedTextContainersCache();
   this.ShrinkWrappedText(this.GetItemLinkElements, "Items");
   this.CorrectWrappedText(this.GetItemLinkElements, "Items");
   if(this.accessibilityCompliant)
    this.applyContentItemsAccessibilityAttributes();
   this.RaiseExpandedChanged(index);
  }
 },
 OnCallbackGeneralError: function (result) {
  var callbackGroupIndex = (this.groupsExpandingRequest.length > 0) ? this.groupsExpandingRequest[0] : 0;
  this.SetCallbackContent(result, callbackGroupIndex, true);
  ASPx.Data.ArrayRemoveAt(this.groupsExpandingRequest, 0);
 },
 ShowLoadingPanelInGroup: function (groupIndex) {
  if(this.lpDelay > 0)
   window.setTimeout(function () { this.ShowLoadingPanelInGroupCore(groupIndex); }.aspxBind(this), this.lpDelay);
  else
   this.ShowLoadingPanelInGroupCore(groupIndex);
 },
 ShowLoadingPanelInGroupCore: function (groupIndex) {
  if(ASPx.Data.ArrayIndexOf(this.groupsExpandingRequest, groupIndex) < 0) return;
  var element = this.GetGroupContentElement(groupIndex);
  this.CreateLoadingPanelInline(element);
 },
 ShouldHideExistingLoadingElements: function () {
  return false;
 },
 SetCallbackContent: function(html, index, isError) {
  var element = this.GetGroupContentElement(index);
  if(!!element) {
   if(this.enableAnimation && !this.enableCallbackAnimation && !isError) {
    ASPx.SetInnerHtml(element, html);
    var endHeight = this.GetGroupContentEndHeight(element, true);
    this.PrepareGroupElementsForAnimation(index, false, 0);
    element.expanding = true;
    element.loading = false;
    element.loaded = true;
    this.StartAnimation(element, this.GetGroupContentStartHeight(element, true),
         endHeight,
         function(element) { this.OnAnimationComplete(index); }.aspxBind(this));
   }
   else {
    element.loading = false;
    ASPx.SetInnerHtml(element, html);
    element.loaded = true;
   }
   this.renderHelper.AssignGroupContentAttributes(element, index);
  }
 },
 CreateGroups: function(groupsProperties) {
  var groupType = this.GetClientGroupType();
  for(var i = 0; i < groupsProperties.length; i++) {
   var groupName = groupsProperties[i][0] || "";
   var group = new groupType(this, i, groupName);
   if(ASPx.IsExists(groupsProperties[i][1]))
    group.enabled = groupsProperties[i][1];
   if(ASPx.IsExists(groupsProperties[i][2]))
    group.visible = groupsProperties[i][2];
   if(ASPx.IsExists(groupsProperties[i][3]))
    group.clientVisible = groupsProperties[i][3];
   this.groups.push(group);
   group.CreateItems(groupsProperties[i][4]);
  }
 },
 GetClientGroupType: function() {
  return ASPxClientNavBarGroup;
 },
 CreateItemClickEventArgs: function(processOnServer, item, htmlElement, htmlEvent) {
  return new ASPxClientNavBarItemEventArgs(processOnServer, item, htmlElement, htmlEvent);
 },
 CreateGroupEventArgs: function(group) {
  return new ASPxClientNavBarGroupEventArgs(group);
 },
 CreateGroupCancelEventArgs: function(processOnServer, group) {
  return new ASPxClientNavBarGroupCancelEventArgs(processOnServer, group);
 },
 CreateGroupClickEventArgs: function(processOnServer, group, htmlElement, htmlEvent) {
  return new ASPxClientNavBarGroupClickEventArgs(processOnServer, group, htmlElement, htmlEvent);
 },
 RaiseItemClick: function(groupIndex, itemIndex, htmlEvent) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned("ItemClick");
  if(!this.ItemClick.IsEmpty()) {
   var htmlElement = this.GetItemElement(groupIndex, itemIndex);
   var args = this.CreateItemClickEventArgs(processOnServer, this.GetGroup(groupIndex).GetItem(itemIndex), htmlElement, htmlEvent);
   this.ItemClick.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 RaiseExpandedChanged: function (groupIndex) {
  if(!this.ExpandedChanged.IsEmpty()) {
   var args = this.CreateGroupEventArgs(this.GetGroup(groupIndex));
   this.ExpandedChanged.FireEvent(this, args);
  }
 },
 RaiseExpandedChanging: function(groupIndex) {
  var processingMode = this.autoPostBack ? "Server" : "Client";
  if(!this.ExpandedChanging.IsEmpty()) {
   var args = this.CreateGroupCancelEventArgs(processingMode == "Server", this.GetGroup(groupIndex));
   this.ExpandedChanging.FireEvent(this, args);
   if(args.cancel)
    processingMode = "Handled";
   else
    processingMode = args.processOnServer ? "Server" : "Client";
  }
  return processingMode;
 },
 RaiseHeaderClick: function (groupIndex, htmlEvent) {
  var processingMode = this.autoPostBack || this.IsServerEventAssigned("HeaderClick") ? "Server" : "Client";
  if(!this.HeaderClick.IsEmpty()) {
   var htmlElement = this.GetClickableGroupHeaderElement(groupIndex);
   var args = this.CreateGroupClickEventArgs(processingMode == "Server", this.GetGroup(groupIndex), htmlElement, htmlEvent);
   this.HeaderClick.FireEvent(this, args);
   if(args.cancel)
    processingMode = "Handled";
   else
    processingMode = args.processOnServer ? "Server" : "Client";
  }
  return processingMode;
 },
 SetEnabled: function (enabled) {
  for(var i = this.GetGroupCount() - 1; i >= 0; i--) {
   var group = this.GetGroup(i);
   for(var j = group.GetItemCount() - 1; j >= 0; j--) {
    var item = group.GetItem(j);
    item.SetEnabled(enabled);
   }
  }
 },
 GetGroupCount: function () {
  return this.groups.length;
 },
 GetGroup: function (index) {
  return (0 <= index && index < this.groups.length) ? this.groups[index] : null;
 },
 GetGroupByName: function (name) {
  for(var i = 0; i < this.groups.length; i++)
   if(this.groups[i].name == name) return this.groups[i];
  return null;
 },
 GetActiveGroup: function () {
  if(this.autoCollapse) {
   for(var i = 0; i < this.groups.length; i++) {
    if(this.groups[i].GetVisible() && this.groups[i].GetExpanded())
     return this.groups[i];
   }
  }
  return null;
 },
 SetActiveGroup: function (group) {
  if(this.autoCollapse && group != null && group.GetVisible())
   group.SetExpanded(true);
 },
 GetItemByName: function (name) {
  for(var i = 0; i < this.groups.length; i++) {
   var item = this.groups[i].GetItemByName(name);
   if(item != null) return item;
  }
  return null;
 },
 GetSelectedItem: function () {
  var indexPath = this.GetSelectedItemIndexPath();
  if(indexPath != "") {
   var groupIndex = this.GetGroupIndex(indexPath);
   var itemIndex = this.GetItemIndex(indexPath);
   if(groupIndex > -1 && itemIndex > -1)
    return this.GetGroup(groupIndex).GetItem(itemIndex);
  }
  return null;
 },
 SetSelectedItem: function (item) {
  var groupIndex = (item != null) ? item.group.index : -1;
  var itemIndex = (item != null) ? item.index : -1;
  if(this.IsStateControllerEnabled())
   ASPx.ClearHoverState();
  this.SetSelectedItemInternal(groupIndex, itemIndex);
 },
 CollapseAll: function () {
  for(var i = 0; i < this.groupsExpanding.length; i++) {
   if(this.groupsExpanding[i])
    this.SetExpandedInternal(i, false);
  }
 },
 ExpandAll: function () {
  for(var i = 0; i < this.groupsExpanding.length; i++) {
   if(!this.groupsExpanding[i])
    this.SetExpandedInternal(i, true);
  }
 },
 ChangeItemElementsEnabledAttributes: function (groupIndex, itemIndex, enabled) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var itemElement = this.GetItemElement(groupIndex, itemIndex);
  if(!itemElement) return;
  itemElement.clientDisabled = !enabled;
  var method = ASPx.Attr.ChangeAttributesMethod(enabled);
  var styleMethod = ASPx.Attr.ChangeStyleAttributesMethod(enabled);
  var imageElement = this.GetItemImageElementByIndexPath(indexPath);
  if(imageElement) {
   styleMethod(imageElement, "cursor");
   var link = this.GetInternalHyperlinkElement(imageElement, 0);
   if(link != null)
    this.ChangeItemLinkEnabledAttributes(link, enabled, method, styleMethod);
  }
  var textElement = this.GetItemTextElementByIndexPath(indexPath);
  if(textElement) {
   this.ChangeItemLinkEnabledAttributes(textElement, enabled, method, styleMethod);
   var link = this.GetInternalHyperlinkElement(textElement, 0);
   if(link != null) {
    this.ChangeItemLinkEnabledAttributes(link, enabled, method, styleMethod);
    link = this.GetInternalHyperlinkElement(textElement, 1);
    if(link != null)
     this.ChangeItemLinkEnabledAttributes(link, enabled, method, styleMethod);
   }
  }
  if(imageElement == null && textElement == null) {
   styleMethod(itemElement, "cursor");
   var link = this.GetInternalHyperlinkElement(itemElement, 0);
   if(link != null)
    this.ChangeItemLinkEnabledAttributes(link, enabled, method, styleMethod);
  }
 },
 ChangeItemLinkEnabledAttributes: function (link, enabled, method, styleMethod) {
  method(link, "href");
  styleMethod(link, "cursor");
 },
 SetItemEnabled: function (groupIndex, itemIndex, enabled, initialization) {
  if(!this.groups[groupIndex].items[itemIndex].enabled) return;
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  if(!enabled) {
   if(this.GetSelectedItemIndexPath() == indexPath)
    this.DeselectItem(indexPath);
  }
  if(!initialization || !enabled)
   this.ChangeItemEnabledStateItems(groupIndex, itemIndex, enabled);
  this.ChangeItemEnabledAttributes(groupIndex, itemIndex, enabled);
  if(enabled) {
   if(this.GetSelectedItemIndexPath() == indexPath)
    this.SelectItem(indexPath);
  }
 },
 ChangeItemEnabledAttributes: function (groupIndex, itemIndex, enabled) {
  this.ChangeItemElementsEnabledAttributes(groupIndex, itemIndex, enabled);
  if(this.accessibilityCompliant)
   this.changeItemEnabledAccessibilityAttributes(groupIndex, itemIndex, enabled);
 },
 changeItemEnabledAccessibilityAttributes: function(groupIndex, itemIndex, enabled) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var link = this.GetChildElement(this.GetItemLinkID(indexPath));
  if(link) {
   var changeAttributeAction = enabled ? ASPx.Attr.RemoveAttribute : ASPx.Attr.SetAttribute;
   changeAttributeAction(link, "aria-disabled", "true");
   var item = this.GetGroup(groupIndex).GetItem(itemIndex);
   if(!enabled && item.enabled)
    link.href = ASPx.AccessibilityEmptyUrl;
  }
 },
 ChangeItemEnabledStateItems: function (groupIndex, itemIndex, enabled) {
  if(!this.IsStateControllerEnabled()) return;
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var element = this.GetItemTextElementByIndexPath(indexPath);
  if(element == null)
   element = this.GetItemImageElementByIndexPath(indexPath);
  if(element == null)
   element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null)
   ASPx.GetStateController().SetElementEnabled(element, enabled);
 },
 GetItemImageUrl: function (groupIndex, itemIndex) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var element = this.GetItemImageContainer(indexPath);
  if(element != null) {
   var img = ASPx.GetNodeByTagName(element, "IMG", 0);
   if(img != null)
    return img.src;
  }
  element = this.GetItemTextElementByIndexPath(indexPath);
  if(element != null) {
   var img = ASPx.GetNodeByTagName(element, "IMG", 0);
   if(img != null)
    return img.src;
  }
  return "";
 },
 SetItemImageUrl: function (groupIndex, itemIndex, url) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var element = this.GetItemImageContainer(indexPath);
  if(element != null) {
   var img = ASPx.GetNodeByTagName(element, "IMG", 0);
   if(img != null)
    img.src = url;
  }
  element = this.GetItemTextElementByIndexPath(indexPath);
  if(element != null) {
   var itemImageElementID = this.name + this.GetItemImageID(indexPath);
   var img = ASPx.GetChildById(element, itemImageElementID);
   if(img != null)
    img.src = url;
  }
 },
 GetItemImageContainer: function (indexPath) {
  return this.GetItemElementByIndexPath(indexPath);
 },
 GetItemNavigateUrl: function (groupIndex, itemIndex) {
  var element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null) {
   var link = ASPx.GetNodeByTagName(element, "A", 0);
   if(link != null)
    return link.href || ASPx.Attr.GetAttribute(link, "savedhref");
  }
  return "";
 },
 SetItemNavigateUrl: function (groupIndex, itemIndex, url) {
  var element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null) {
   var setUrl = function(link) {
    if(link != null) {
     if(ASPx.Attr.IsExistsAttribute(link, "savedhref"))
      ASPx.Attr.SetAttribute(link, "savedhref", url);
     else if(ASPx.Attr.IsExistsAttribute(link, "href"))
      link.href = url;
    }
   };
   setUrl(ASPx.GetNodeByTagName(element, "A", 0));
   setUrl(ASPx.GetNodeByTagName(element, "A", 1));
  }
 },
 GetItemText: function(groupIndex, itemIndex) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var element = this.GetItemTextElementByIndexPath(indexPath);
  if(element == null)
   element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null) {
   var textNode = ASPx.GetNormalizedTextNode(element);
   if(textNode != null)
    return textNode.nodeValue;
  }
  return "";
 },
 SetItemText: function (groupIndex, itemIndex, text) {
  var indexPath = this.GetIndexPath(groupIndex, itemIndex);
  var element = this.GetItemTextElementByIndexPath(indexPath);
  if(element == null)
   element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null) {
   var textNode = ASPx.GetNormalizedTextNode(element);
   if(textNode != null)
    textNode.nodeValue = text;
  }
 },
 SetItemVisible: function (groupIndex, itemIndex, visible, initialization) {
  if(!this.groups[groupIndex].items[itemIndex].visible) return;
  if(visible && initialization) return;
  var element = this.GetItemElement(groupIndex, itemIndex);
  if(element != null) ASPx.SetElementDisplay(element, visible);
  this.UpdateMarkedLastItem(groupIndex);
  this.SetItemSeparatorsVisiblility(groupIndex);
 },
 UpdateMarkedLastItem: function(groupIndex) {
  ASPx.RemoveClassNameFromElement(this.GetMarkedLastItemElement(groupIndex), NavBarCssClasses.LastItem);
  ASPx.AddClassNameToElement(this.GetLastVisibleItemElement(groupIndex), NavBarCssClasses.LastItem);
 },
 SetItemSeparatorsVisiblility: function (groupIndex) {
  var group = this.groups[groupIndex];
  for(var i = 0; i < group.items.length; i++) {
   var separatorVisible = group.items[i].GetVisible() && this.HasNextVisibleItems(group, i);
   var separatorElement = this.GetItemSeparatorElement(groupIndex, i);
   if(separatorElement != null) ASPx.SetElementDisplay(separatorElement, separatorVisible);
  }
 },
 HasNextVisibleItems: function (group, index) {
  for(var i = index + 1; i < group.items.length; i++) {
   if(group.items[i].GetVisible())
    return true;
  }
  return false;
 },
 SetGroupVisible: function (groupIndex, visible, initialization) {
  if(!this.groups[groupIndex].visible) return;
  if(visible && initialization) return;
  var element = this.GetGroupRow(groupIndex);
  if(element != null) ASPx.SetElementDisplay(element, visible);
  this.SetGroupSeparatorsVisiblility();
 },
 GetGroupText: function (groupIndex) {
  var groupTextElements = this.GetGroupHeaderTextElements(groupIndex);
  if(!groupTextElements || groupTextElements.length == 0)
   return;
  return ASPx.GetInnerText(groupTextElements[0]);
 },
 SetGroupText: function (groupIndex, text) {
  var groupTextElements = this.GetGroupHeaderTextElements(groupIndex);
  if(!groupTextElements || groupTextElements.length == 0)
   return;
  for(var i = 0; i < groupTextElements.length; i++) {
   var textNode = ASPx.GetNormalizedTextNode(groupTextElements[i]);
   if(textNode != null)
    textNode.nodeValue = text;
  }
 },
 SetGroupSeparatorsVisiblility: function () {
  for(var i = 0; i < this.groups.length; i++) {
   var separatorVisible = this.groups[i].GetVisible() && this.HasNextVisibleGroups(i);
   var separatorElement = this.GetGroupSeparatorRow(i);
   if(separatorElement != null) ASPx.SetElementDisplay(separatorElement, separatorVisible);
  }
 },
 HasNextVisibleGroups: function (index) {
  for(var i = index + 1; i < this.groups.length; i++) {
   if(this.groups[i].GetVisible())
    return true;
  }
  return false;
 }
});
ASPxClientNavBar.Cast = ASPxClientControl.Cast;
var ASPxClientNavBarGroup = ASPx.CreateClass(null, {
 constructor: function (navBar, index, name) {
  this.navBar = navBar;
  this.index = index;
  this.name = name;
  this.enabled = true;
  this.visible = true;
  this.clientVisible = true;
  this.items = [];
 },
 CreateItems: function(itemsProperties) {
  var itemType = this.GetClientItemType();
  for(var i = 0; i < itemsProperties.length; i++) {
   var itemName = itemsProperties[i][0] || "";
   var item = new itemType(this.navBar, this, i, itemName);
   if(ASPx.IsExists(itemsProperties[i][1]))
    item.enabled = itemsProperties[i][1];
   if(ASPx.IsExists(itemsProperties[i][2]))
    item.clientEnabled = itemsProperties[i][2];
   if(ASPx.IsExists(itemsProperties[i][3]))
    item.visible = itemsProperties[i][3];
   if(ASPx.IsExists(itemsProperties[i][4]))
    item.clientVisible = itemsProperties[i][4];
   this.items.push(item);
  }
 },
 GetClientItemType: function() {
  return ASPxClientNavBarItem;
 },
 GetEnabled: function () {
  return this.enabled;
 },
 GetExpanded: function () {
  return this.navBar.groupsExpanding[this.index];
 },
 SetExpanded: function (value) {
  this.navBar.SetExpandedInternal(this.index, value);
 },
 GetVisible: function () {
  return this.visible && this.clientVisible;
 },
 GetText: function () {
  return this.navBar.GetGroupText(this.index);
 },
 SetText: function (text) {
  this.navBar.SetGroupText(this.index, text);
 },
 SetVisible: function (value) {
  if(this.clientVisible != value) {
   this.clientVisible = value;
   this.navBar.SetGroupVisible(this.index, value, false);
   this.navBar.UpdateLastGroupClassName();
  }
 },
 GetItemCount: function (groupIndex) {
  return this.items.length;
 },
 GetItem: function (index) {
  return (0 <= index && index < this.items.length) ? this.items[index] : null;
 },
 GetItemByName: function (name) {
  for(var i = 0; i < this.items.length; i++)
   if(this.items[i].name == name) return this.items[i];
  return null;
 }
});
var ASPxClientNavBarItem = ASPx.CreateClass(null, {
 constructor: function (navBar, group, index, name) {
  this.navBar = navBar;
  this.group = group;
  this.index = index;
  this.name = name;
  this.enabled = true;
  this.clientEnabled = true;
  this.visible = true;
  this.clientVisible = true;
 },
 GetEnabled: function () {
  return this.enabled && this.clientEnabled;
 },
 SetEnabled: function (value) {
  if(this.clientEnabled != value) {
   this.clientEnabled = value;
   this.navBar.SetItemEnabled(this.group.index, this.index, value, false);
  }
 },
 GetImageUrl: function () {
  return this.navBar.GetItemImageUrl(this.group.index, this.index);
 },
 SetImageUrl: function (value) {
  this.navBar.SetItemImageUrl(this.group.index, this.index, value);
 },
 GetNavigateUrl: function () {
  return this.navBar.GetItemNavigateUrl(this.group.index, this.index);
 },
 SetNavigateUrl: function (value) {
  this.navBar.SetItemNavigateUrl(this.group.index, this.index, value);
 },
 GetText: function () {
  return this.navBar.GetItemText(this.group.index, this.index);
 },
 SetText: function (value) {
  this.navBar.SetItemText(this.group.index, this.index, value);
 },
 GetVisible: function () {
  return this.visible && this.clientVisible;
 },
 SetVisible: function (value) {
  if(this.clientVisible != value) {
   this.clientVisible = value;
   this.navBar.SetItemVisible(this.group.index, this.index, value, false);
  }
 }
});
var ASPxClientNavBarItemEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function (processOnServer, item, htmlElement, htmlEvent) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.item = item;
  this.htmlElement = htmlElement;
  this.htmlEvent = htmlEvent;
 }
});
var ASPxClientNavBarGroupEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (group) {
  this.group = group;
 }
});
var ASPxClientNavBarGroupCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
 constructor: function (processOnServer, group) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.group = group;
 }
});
var ASPxClientNavBarGroupClickEventArgs = ASPx.CreateClass(ASPxClientNavBarGroupCancelEventArgs, {
 constructor: function (processOnServer, group, htmlElement, htmlEvent) {
  this.constructor.prototype.constructor.call(this, processOnServer, group);
  this.htmlElement = htmlElement;
  this.htmlEvent = htmlEvent;
 }
});
ASPx.NBHClick = function(evt, name, groupIndex) {
 var nb = ASPx.GetControlCollection().Get(name);
 if(nb != null) nb.OnHeaderClick(groupIndex, evt);
};
ASPx.NBHMMove = function(evt, name, groupIndex) {
 var nb = ASPx.GetControlCollection().Get(name);
 if(nb != null) nb.OnHeaderMouseMove(groupIndex, evt);
};
ASPx.NBIClick = function(evt, name, groupIndex, itemIndex) {
 var nb = ASPx.GetControlCollection().Get(name);
 if(nb != null) nb.OnItemClick(groupIndex, itemIndex, evt);
};
var MouseOverActiveNavBar = null;
var MouseOverActiveGroupIndex = -1;
var DocMouseMoveHandler = function (evt) {
 if(MouseOverActiveNavBar != null && MouseOverActiveGroupIndex != -1) {
  var srcElement = ASPx.Evt.GetEventSource(evt);
  var headerElement = MouseOverActiveNavBar.GetGroupHeaderExpandedElement(MouseOverActiveGroupIndex);
  if(headerElement == null || (srcElement != headerElement && !ASPx.GetIsParent(headerElement, srcElement))) {
   headerElement = MouseOverActiveNavBar.GetGroupHeaderCollapsedElement(MouseOverActiveGroupIndex);
   if(headerElement == null || (srcElement != headerElement && !ASPx.GetIsParent(headerElement, srcElement))) {
    MouseOverActiveNavBar = null;
    MouseOverActiveGroupIndex = -1;
   }
  }
 }
};
ASPx.Evt.AttachEventToDocument("mousemove", DocMouseMoveHandler);
ASPx.NavBarRenderHelper = NavBarRenderHelper;
window.ASPxClientNavBar = ASPxClientNavBar;
window.ASPxClientNavBarGroup = ASPxClientNavBarGroup;
window.ASPxClientNavBarItem = ASPxClientNavBarItem;
window.ASPxClientNavBarItemEventArgs = ASPxClientNavBarItemEventArgs;
window.ASPxClientNavBarGroupEventArgs = ASPxClientNavBarGroupEventArgs;
window.ASPxClientNavBarGroupCancelEventArgs = ASPxClientNavBarGroupCancelEventArgs;
window.ASPxClientNavBarGroupClickEventArgs = ASPxClientNavBarGroupClickEventArgs;
})();

(function() {
var MVCxClientNavBar = ASPx.CreateClass(ASPxClientNavBar, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), this.callbackCustomArgs); };
  ASPxClientNavBar.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  this.callbackCustomArgs = args.customArgs;
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 GetCallbackParams: function(){
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientNavBar.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientNavBar.prototype.EvalCallbackResult.call(this, resultString);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientNavBar.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientNavBar.Cast = ASPxClientControl.Cast;
window.MVCxClientNavBar = MVCxClientNavBar;
})();

(function() {
 var constants = {
  TABCONTROL_POSTFIX: "_TC",
  GROUPCOLLAPSEPOPUP_POSTFIX: "_GPC",
  TABMINIMIZEPOPUP_POSTFIX: "_MPC",
  TAB_CONTENTCONTROL_POSTFIX: "_T",
  TABSCONTAINER_POSTFIX: "_RTC",
  KEYTIP_POSTFIX: "_KT",
  KEYTIPSCONTAINER_POSTFIX: "_KTC",
  GROUP_POSTFIX: "G",
  GROUPDIALOGBOXLAUNCHER_POSTFIX: "_DBL",
  POPUP_MENU_POSTFIX: "_PM",
  POPUP_CONTROL_POSTFIX: "_IPC",
  COMBOBOX_POSTFIX: "_CMB",
  CHECKBOX_POSTFIX: "_CB",
  SPINEDIT_POSTFIX: "_SE",
  TEXTBOX_POSTFIX: "_TB",
  TRACKBAR_POSTFIX: "_TB",
  DROPDOWNEDIT_POSTFIX: "_DDE",
  DATEEDIT_POSTFIX: "_DE",
  POPUP_GALLERY_POSTFIX: "_PG",
  MINIMIZEBUTTON_POSTFIX: "_TPTCL_MinBtn",
  MINIMIZEBUTTONIMAGE_POSTFIX: "_TPTCL_MinBtnI",
  PINBUTTONIMAGE_POSTFIX: "_TPTCL_PinBtnI",
  INACTIVETAB_NAME: "DXR_INACTIVE",
  FILETAB_NAME: "DXR_FILE",
  COLORTABLE_POSTFIX: "_IPC_CT",
  COLORINDICATOR_POSTFIX: "_CI",
  MENU_INDEXPATH_SEPARATOR: "i",
  COLORITEM_CLIENTSTATE_SEPARATOR: "|",
  CLASSNAMES: {
   LARGEITEM: "dxr-largeSize",
   ITEMLABEL: "dxr-label",
   ITEMPOPOUT: "dxr-popOut",
   ITEMDDIMAGECONTAINER: "dxr-ddImageContainer",
   GROUPLIST: "dxr-groupList",
   BLOCK: "dxr-block",
   TAB_HOVER: "dxtc-tabHover", 
   BLOCK_REGULAR_ITEMS: "dxr-blRegItems",
   BLOCK_REGULAR_ITEMS_REDUCED: "dxr-blRegItems dxr-blReduced",
   BLOCK_LARGE_ITEMS: "dxr-blLrgItems",
   BLOCK_SEPARATE_ITEMS: "dxr-blSepItems",
   BLOCK_HORIZONTAL_ITEMS: "dxr-blHorItems",
   BLOCK_HORIZONTAL_ITEMS_REDUCED: "dxr-blHorItems dxr-blReduced",
   BLOCK_HORIZONTAL_ITEMS_HIDE: "dxr-blHorItems dxr-blHide",
   BlOCK_HIDE: "dxr-blHide",
   GROUP_COLLAPSED: "dxr-group dxr-grCollapsed",
   GROUP_EXPAND: "dxr-grExpBtn",
   GROUP_DIALOG_BOX: "dxr-grDialogBoxLauncher",
   GROUP: "dxr-group",
   ONE_LINE_MODE_GROUP_EXPAND: "dxr-olmGrExpBtn",
   ONE_LINE_MODE_GROUP_EXPAND_VISIBLE: "dxr-olmGrExpBtn dxr-olmGrExpBtnVisible",
   GROUP_LABEL: "dxr-groupLabel",
   GROUP_CONTENT: "dxr-groupContent",
   GROUP_SCROLL_CONTAINER: "dxr-gscroll",
   GROUP_SCROLL_LEFT_DIV: "dxr-lbutton",
   GROUP_SCROLL_RIGHT_DIV: "dxr-rbutton",
   BUTTONITEM: "dxr-buttonItem",
   ITEM: "dxr-item",
   IMAGE16: "dxr-img16",
   IMAGE32: "dxr-img32",
   LABELTEXT: "dxr-lblText",
   LABELCONTENT: "dxr-lblContent",
   TABWRAPPER: "dxr-tabWrapper",
   GALLERY_ITEM: "dxr-glrItem",
   GALLERY_MAIN_DIV: "dxr-glrMainDiv",
   GALLERY_BAR_CONTAINER: "dxr-glrBarContainer",
   GALLERY_POPOUT: "dxr-glrPopout",
   GALLERY_BAR_DIV: "dxr-glrBarDiv",
   GALLERY_GROUP_DIV: "dxr-glrGroup",
   GALLERY_ITEM_CONTENT: "dxr-glrItemContent",
   GALLERY_ITEM_TEXT: "dxr-glrItemText"
  },
  ITEMTYPES: {
   BUTTON: 0,
   TEMPLATE: 1,
   DROPDOWNSPLIT: 2,
   DROPDOWNMENU: 3,
   TOGGLE: 4,
   OPTION: 5,
   SPINEDIT: 6,
   COLOR: 7,
   TEXTBOX: 8,
   DATEEDIT: 9,
   COMBOBOX: 10,
   CHECKBOX: 11,
   DROPDOWNTOGGLEBUTTON: 12,
   GALLERYDROPDOWN: 13,
   GALLERYBAR: 14,
   BUTTONEDIT: 15,
   TRACKBAR: 16
  }
 };
 var ASPxClientRibbonItem = ASPx.CreateClass(null, {
  constructor: function(itemInfo) {
   this.group = itemInfo.group;
   this.index = itemInfo.index;
   this.name = itemInfo.name || "";
   this.ribbon = itemInfo.ribbon;
   this.groupName = itemInfo.subGroup;
   this.type = itemInfo.type;
   this.text = itemInfo.text;
   this.id = this.getId();
   this.enabled = !itemInfo.clientDisabled;
   this.visible = itemInfo.type !== undefined;
   this.clientDisabledLocked = itemInfo.clientDisabled;
   this.accessKey = itemInfo.accessKey;
   this.keyTipElement = null;
  },
  GetEnabled: function() {
   return this.getEnabledCore();
  },
  SetEnabled: function(enabled) {
   if(!this.getControlEnabled(true)) return;
   this.clientDisabledLocked = !enabled;
   this.setEnabledCore(enabled, false);
  },
  GetValue: function() {
   return this.getValueCore();
  },
  SetValue: function(value) {
   this.setValueCore(value);
  },
  GetVisible: function() {
   return this.visible;
  },
  execCommand: function(value) {
   this.ribbon.onBarItemExecCommand(this, value);
  },
  changeClientState: function(state) {
   var key = getItemID(this, true);
   if(state === undefined)
    this.ribbon.clearBarItemClientState(key);
   else
    this.ribbon.updateBarItemClientState(key, state);
  },
  getItemsFactory: function() {
   return this.ribbon.getBarItemsFactory();
  },
  forEachBarItem: function(func) {
   this.ribbon.forEachBarItem(func);
  },
  getControlEnabled: function(clientEnabled) {
   return this.ribbon.getControlEnabled(clientEnabled);
  },
  hasKeyboardSupport: function() {
   return this.ribbon.getBarItemsKeyboardSupport();
  },
  getPopupMenuHelper: function() {
   return this.ribbon.getBarItemPopupHelper();
  },
  getId: function() {
   return getItemID(this);
  },
  initialize: function() { },
  onClick: function(evt) { },
  setEnabledCore: function(enabled, initialization) {
   enabled = enabled && (!initialization || this.enabled);
   if(enabled && this.clientDisabledLocked)
    return;
   this.enabled = enabled;
   if(this.keyTipElement) {
    ASPx.GetStateController().SetElementEnabled(this.keyTipElement, enabled);
   }
   ASPx.GetStateController().SetElementEnabled(this.getElement(), enabled);
  },
  getEnabledCore: function() {
   return this.enabled;
  },
  getValueCore: function() {
   return null;
  },
  setValueCore: function() { },
  getElement: function() {
   if(!this.element)
    this.element = document.getElementById(this.id);
   return this.element;
  },
  getLabelElement: function() {
   if(!this.labelElement)
    this.labelElement = ASPx.GetNodeByClassName(this.getElement(), constants.CLASSNAMES.ITEMLABEL);
   return this.labelElement;
  },
  getLabelContentElement: function() {
   if(!this.labelContentElement) {
    var labelElement = this.getLabelElement();
    if(labelElement)
     this.labelContentElement = ASPx.GetNodeByClassName(labelElement, constants.CLASSNAMES.LABELCONTENT);
   }
   return this.labelContentElement;
  },
  getLabelTextElement: function() {
   if(!this.labelTextElement) {
    var labelElement = this.getLabelElement();
    if(labelElement)
     this.labelTextElement = ASPx.GetNodeByClassName(labelElement, constants.CLASSNAMES.LABELTEXT);
   }
   return this.labelTextElement;
  },
  getBlockElement: function() {
   if(!this.blockElement)
    this.blockElement = this.getElement().parentNode;
   return this.blockElement;
  },
  getAccessKeyPopupElement: function() {
   return this.getElement();
  },
  getGroupIndexPath: function() {
   return this.group.getIndexPath();
  },
  getFullIndexPath: function() {
   return this.getGroupIndexPath() + ASPx.ItemIndexSeparator + this.index;
  },
  adjust: function() { },
  accessKeyClick: function() {
   if(!this.getEnabledCore()) return;
   ASPx.Evt.EmulateMouseClick(this.getElement());
  },
  getLineIndex: function() {
   var itemHeight = this.getElement().offsetHeight;
   var groupHeight = this.group.getElement().offsetHeight;
   if(groupHeight - itemHeight <= itemHeight)
    return -1;
   var top = this.getElement().offsetTop - this.getBlockElement().offsetTop;
   var lineIndex = top / itemHeight;
   return lineIndex;
  },
  getAccessKeyPosition: function() {
   var lineIndex = this.getLineIndex();
   switch(lineIndex) {
    case -1:
     return "Below";
    case 0:
     return "AboveRight";
    case 1:
     return "Right";
    case 2:
     return "BelowRight";
    default:
     return "Below";
   }
  }
 });
 var ASPxClientRibbonButtonItem = ASPx.CreateClass(ASPxClientRibbonItem, {
  constructor: function(itemInfo, navigateUrl) {
   this.constructor.prototype.constructor.call(this, itemInfo);
   this.navigateUrl = navigateUrl;
  },
  initialize: function() {
   if(this.getControlEnabled()) {
    ASPx.Evt.AttachEventToElement(this.getElement(), "click", function(evt) {
     this.onClick(evt);
    }.aspxBind(this));
   }
   var element = this.getElement();
   var label = this.getLabelTextElement();
   if(label && ASPx.ElementHasCssClass(this.getBlockElement(), constants.CLASSNAMES.BLOCK_LARGE_ITEMS) && !element.style.width) {
    var className = ASPx.CreateImportantStyleRule(null, "width: " + this.getLargeItemWidth() + "px;", undefined, "." + constants.CLASSNAMES.BLOCK_LARGE_ITEMS);
    ASPx.AddClassNameToElement(element, className);
   }
  },
  getLargeItemWidth: function() {
   return getLargeItemWidth(this.getLabelTextElement(), ASPx.GetLeftRightMargins(this.getLabelContentElement()));
  },
  onClick: function(evt) {
   if(!this.getEnabledCore()) return;
   this.execute();
  },
  execute: function() {
   this.execCommand(null);
  },
  setEnabledCore: function(enabled, initialization) {
   ASPxClientRibbonItem.prototype.setEnabledCore.call(this, enabled, initialization);
   var element = this.getElement();
   if(!element)
    return;
   if(this.navigateUrl) {
    if(!this.enabled && element.href) {
     ASPx.Attr.SetAttribute(element, "savedhref", element.href);
     ASPx.Attr.RemoveAttribute(element, "href");
    }
    else if(this.enabled && ASPx.Attr.GetAttribute(element, "savedhref")) {
     ASPx.Attr.SetAttribute(element, "href", ASPx.Attr.GetAttribute(element, "savedhref"));
     ASPx.Attr.RemoveAttribute(element, "savedhref");
    }
   }
  },
  adjust: function() {
   var block = this.getBlockElement();
   var label = this.getLabelElement();
   var image = this.getImageElement(constants.CLASSNAMES.IMAGE16);
   if(label && !image && ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS) && !ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED)) {
    this.ribbon.CorrectVerticalAlignment && this.ribbon.CorrectVerticalAlignment(ASPx.AdjustVerticalMargins, function() { return label; });
   }
  },
  getImageElement: function(className) {
   if(this.imageElement === undefined)
    this.imageElement = ASPx.GetNodeByClassName(this.getElement(), className) || null;
   return this.imageElement;
  },
  getAccessKeyPopupElement: function() {
   var image = this.getImageElement(constants.CLASSNAMES.IMAGE16);
   if(image && ASPx.IsElementVisible(image, true))
    return image;
   return this.getElement();
  },
  accessKeyClick: function() {
   this.onClick();
   if(this.navigateUrl)
    ASPx.Url.NavigateByLink(this.getElement());
  }
 });
 var ASPxClientRibbonDropDownMenuItem = ASPx.CreateClass(ASPxClientRibbonButtonItem, {
  constructor: function(itemInfo, items, navigateUrl, rawInfo) {
   this.constructor.prototype.constructor.call(this, itemInfo, navigateUrl);
   this.parent = null;
   if(items !== undefined) {
    this.items = [];
    var itemsFactory = this.getItemsFactory();
    for(var i = 0, subItemInfo; subItemInfo = items[i]; i++) {
     var info = new ASPxClientRibbonItemInfo(itemInfo.ribbon, itemInfo.group, i, subItemInfo);
     info.hasParent = true;
     var subItem = itemsFactory.createItem(info);
     subItem.parent = this;
     subItem.id = getItemID(subItem);
     if(subItem.checked)
      subItem.setCheckedState();
     this.items.push(subItem);
    }
   }
   if(rawInfo) {
    this.target = rawInfo.ta || "";
    this.tooltip = rawInfo.tt || "";
    this.dropDownMode = !!rawInfo.ddm;
    this.beginGroup = !!rawInfo.bg;
    this.largeImage = rawInfo.li || null;
    this.smallImage = rawInfo.si || null;
    this.largeImageHottrackSrc = rawInfo.lih || null;
    this.smallImageHottrackSrc = rawInfo.sih || null;
    this.className = rawInfo.cl || "";
    this.textTemplate = rawInfo.ttem || null;
    this.styles = rawInfo.st || "";
    this.isSvg = rawInfo.isSvg || false;
   }
   if(!itemInfo.hasParent)
    this.initPopupMenu();
  },
  initPopupMenu: function() {
   var popup = this.getOwnItemPopup();
   if(popup)
    this.getPopupMenuHelper().initializeEventsCore(popup, this);
  },
  getId: function() {
   return !this.parent ? ASPxClientRibbonButtonItem.prototype.getId.call(this) :
    this.group.tab.getRibbonID() + constants.POPUP_MENU_POSTFIX + "_DXI" + this.getIndexPath() + "_";
  },
  getLargeItemWidth: function() {
   var popOut = this.getPopOutElement();
   return getLargeItemWidth(this.getLabelTextElement(), ASPx.GetLeftRightMargins(this.getLabelContentElement()), popOut.offsetWidth + ASPx.GetLeftRightMargins(popOut));
  },
  getOwnItemPopup: function() {
   return ASPx.GetControlCollection().Get(getItemID(this) + constants.POPUP_MENU_POSTFIX);
  },
  getElement: function() {
   return !this.parent || this.isPopupMenuVisible() ? document.getElementById(this.getId()) : null;
  },
  getPopup: function() {
   return this.getOwnItemPopup() || this.getPopupMenuHelper().getPopupMenu();
  },
  isPopupMenuVisible: function() {
   var popup = this.getPopup();
   return !!popup && popup.IsVisible();
  },
  getPopupElement: function() {
   var popup = this.getPopup();
   if(popup)
    return popup.GetMainElement();
  },
  getPopOutElement: function() {
   if(!this.popOutElement)
    this.popOutElement = ASPx.GetNodeByClassName(this.getLabelElement(), constants.CLASSNAMES.ITEMPOPOUT);
   return this.popOutElement;
  },
  onClick: function(evt) {
   if(!this.getEnabledCore()) return;
   setTimeout(function() { this.showPopup(); }.aspxBind(this), 0);
  },
  preparePopupBeforeShow: function() {
   if(!this.getOwnItemPopup())
    this.getPopupMenuHelper().populatePopupMenuWithItems(this);
  },
  afterPopupShown: function() {
   var pm = this.getPopup();
   if(this.hasKeyboardSupport() && pm.Focus)
    pm.Focus();
  },
  showPopup: function() {
   if(!this.getEnabledCore()) return;
   var pm = this.getPopup();
   if(pm) {
    if(pm.IsVisible())
     pm.Hide();
    else if(this.getPopupMenuHelper().popupWasNotShownForThisItem(this)) {
     this.preparePopupBeforeShow();
     pm.ShowAtElement(this.getElement());
     this.afterPopupShown();
    }
   }
  },
  hidePopup: function() {
   var pm = this.getPopup();
   if(pm)
    pm.Hide();
  },
  onMenuItemClick: function(menuItem) {
   var indexPath = menuItem.indexPath.split(constants.MENU_INDEXPATH_SEPARATOR);
   var item = this.findItem(indexPath);
   if(item.type !== constants.ITEMTYPES.DROPDOWNMENU)
    item.execute();
  },
  findItem: function(indexPath) {
   var item = this.items[indexPath.shift()];
   return indexPath.length ? item.findItem(indexPath) : item;
  },
  setEnabledCore: function(enabled, initialization) {
   if(!this.parent)
    ASPxClientRibbonButtonItem.prototype.setEnabledCore.call(this, enabled, initialization);
   else {
    var indexPath = this.getIndexPath();
    var popup = this.getPopup();
    if(getItemID(this, true).indexOf(popup.cpRibbonItemID) === 0) {
     popup.GetItemByIndexPath(indexPath).SetEnabled(enabled);
    }
    ASPxClientRibbonButtonItem.prototype.setEnabledCore.call(this, enabled, initialization);
   }
   if(this.items) {
    for(var item, i = 0; item = this.items[i]; i++)
     item.setEnabledCore(item.enabled, initialization);
   }
  },
  getIndexPath: function(includeLastParent) {
   if(!this.parent) return includeLastParent ? this.index : "";
   var parentPath = this.parent.getIndexPath(includeLastParent);
   return "" + (parentPath === "" ? this.index : (parentPath + constants.MENU_INDEXPATH_SEPARATOR + this.index));
  },
  getFullIndexPath: function() {
   return this.getGroupIndexPath() + ASPx.ItemIndexSeparator + this.getIndexPath(true);
  },
  getItemByName: function(name) {
   if(this.items) {
    var subItem = null;
    for(var i = 0; i < this.items.length; i++) {
     var item = this.items[i];
     if(item.name === name)
      return item;
     if(!subItem && item.getItemByName)
      subItem = item.getItemByName(name);
    }
    return subItem;
   }
   return null;
  },
  adjust: function() { },
  accessKeyClick: function() {
   this.showPopup();
  }
 });
 var ASPxClientRibbonDropDownSplitItem = ASPx.CreateClass(ASPxClientRibbonDropDownMenuItem, {
  initialize: function() {
   ASPxClientRibbonDropDownMenuItem.prototype.initialize.call(this);
   this.correctDropDownElementPosition();
  },
  onClick: function(evt) {
   if(!this.getEnabledCore()) return;
   var pm = this.getPopup();
   var source = ASPx.Evt.GetEventSource(evt);
   var itemElement = this.getElement();
   var isLargeItem = ASPx.ElementHasCssClass(itemElement.parentNode, constants.CLASSNAMES.BLOCK_LARGE_ITEMS);
   var popoutContainer = isLargeItem ? this.getLabelElement() : this.getPopOutElement();
   var imgContainer = ASPx.GetNodeByClassName(itemElement, constants.CLASSNAMES.ITEMDDIMAGECONTAINER);
   var itemPopupContainer = ASPx.GetNodeByClassName(itemElement, constants.CLASSNAMES.ITEMPOPOUT);
   if(ASPx.GetIsParent(popoutContainer, source) || this.isClickByPopout(isLargeItem, imgContainer, itemPopupContainer, evt))
    setTimeout(function() { this.showPopup(); }.aspxBind(this), 0);
   else if(!pm || !ASPx.GetIsParent(pm.GetMainElement(), source))
    this.execute();
  },
  isClickByPopout: function(isLargeItem, imgContainer, itemPopupContainer, evt) {
   if(isLargeItem) {
    var offsetY = evt.offsetY == undefined ? evt.layerY : evt.offsetY;
    return imgContainer && offsetY > imgContainer.offsetHeight + ASPx.GetTopBottomBordersAndPaddingsSummaryValue(imgContainer)
     + ASPx.GetTopBottomMargins(imgContainer);
   } else {
    var offsetX = evt.offsetX == undefined ? evt.layerX : evt.offsetX;
    return itemPopupContainer && offsetX > itemPopupContainer.offsetLeft;
   }
  },
  getPopOutElement: function() {
   var itemElement = this.getElement();
   return ASPx.GetNodeByClassName(itemElement, constants.CLASSNAMES.ITEMPOPOUT);
  },
  correctDropDownElementPosition: function() {
   var itemElement = this.getElement();
   var textElement = this.getLabelTextElement();
   var dropDownElement = ASPx.GetNodeByClassName(itemElement, constants.CLASSNAMES.ITEMPOPOUT);
   var imgContainer = ASPx.GetNodeByClassName(itemElement, constants.CLASSNAMES.ITEMDDIMAGECONTAINER);
   var getElementRightCoordinate = function(element) {
    return ASPx.GetAbsolutePositionX(element) + element.offsetWidth + ASPx.PxToInt(ASPx.GetCurrentStyle(element).marginRight);
   };
   var getElementFullWidth = function(element) {
    if(element)
     return element.offsetWidth + ASPx.GetLeftRightMargins(element);
    return 0;
   };
   var difference = getElementRightCoordinate(itemElement) - getElementRightCoordinate(this.getBlockElement());
   if(difference > 0)
    itemElement.style.maxWidth = ASPx.GetClearClientWidth(itemElement) - difference + "px";
   var width = ASPx.GetClearClientWidth(itemElement) - getElementFullWidth(imgContainer) - getElementFullWidth(textElement) - getElementFullWidth(dropDownElement);
   if(width <= 0)
    return;
   var correctionElement = textElement || imgContainer;
   correctionElement.style.marginRight = ASPx.PxToInt(correctionElement.style.marginRight) + width + "px";
  }
 });
 var ASPxClientRibbonDropDownToggleButtonItem = ASPx.CreateClass(ASPxClientRibbonDropDownSplitItem, {
  constructor: function(itemInfo, items, navigateUrl, rawInfo) {
   this.constructor.prototype.constructor.call(this, itemInfo, items, navigateUrl, rawInfo);
   if(!!rawInfo)
    this.checked = !!rawInfo.chk;
  },
  initialize: function() {
   ASPxClientRibbonDropDownSplitItem.prototype.initialize.call(this);
   if(this.checked) {
    ASPx.GetStateController().SelectElementBySrcElement(this.getElement());
   }
  },
  getValueCore: function() {
   return !!this.checked;
  },
  setValueCore: function(value) {
   value = !!value;
   if(this.getValueCore() == value)
    return;
   this.checked = value;
   if(!this.parent) {
    var element = this.getElement();
    if(this.checked)
     ASPx.GetStateController().SelectElementBySrcElement(element);
    else
     ASPx.GetStateController().DeselectElementBySrcElement(element);
   } else {
    var indexPath = this.getIndexPath();
    var popup = this.getPopup();
    if(getItemID(this, true).indexOf(popup.cpRibbonItemID) === 0)
     popup.GetItemByIndexPath(indexPath).SetChecked(value);
   }
   this.setCheckedState();
  },
  execute: function() {
   this.setValueCore(!this.checked);
   this.execCommand(this.checked);
  },
  setCheckedState: function() {
   this.changeClientState(this.checked);
  }
 });
 var ASPxClientRibbonColorButtonItem = ASPx.CreateClass(ASPxClientRibbonDropDownSplitItem, {
  constructor: function(itemInfo, color, isAutomaticColor, dropDownMode) {
   this.constructor.prototype.constructor.call(this, itemInfo);
   this.dropDownMode = !!dropDownMode;
   if(this.getControlEnabled()) {
    if(color || isAutomaticColor)
     this.setValueCore(color, isAutomaticColor);
    this.updateIndicator();
   }
  },
  initPopupMenu: function() {
   var popup = this.getPopup();
   if(!popup) return;
   popup.PopUp.AddHandler(function(s, e) {
    this.onPopupPopUp();
   }.bind(this));
   this.getPopupMenuHelper().initializeEventsCore(popup, this);
   var colorTable = this.getColorTable();
   colorTable.ShouldBeClosed.AddHandler(function(s, e) {
    this.onCNCShouldBeClosed(e.cancelButtonClicked);
   }.bind(this));
   colorTable.ShouldBeClosed.AddHandler(function(s, e) {
    this.onCNCShouldBeClosed(e.cancelButtonClicked);
   }.bind(this));
   colorTable.CustomColorTableUpdated.AddHandler(function(s, e) {
    this.updateClientState();
   }.bind(this));
   colorTable.ColorChanged.AddHandler(function(s, e) {
    this.onColorChanged();
   }.bind(this));
  },
  onColorChanged: function() {
   this.hidePopup();
   this.updateIndicator();
   this.updateClientState();
   this.execute();
  },
  onCNCShouldBeClosed: function(cancelButtonClicked) {
   if(this.getPopup().IsVisible()) {
    this.getPopup().Hide();
    if(!cancelButtonClicked)
     this.execute();
   }
  },
  onPopupPopUp: function() {
   var colorTable = this.getColorTable();
   var properties = this.getOwnProperties();
   colorTable.SetOwnerProperties(properties);
   colorTable.SetColorSelectorDisplay(false);
   colorTable.SetColorTablesDisplay(true);
   if(this.hasKeyboardSupport())
    colorTable.Focus();
   var popup = this.getPopup();
   popup.SetWidth(0);
   popup.SetHeight(0);
   popup.UpdatePositionAtElement(this.getElement());
  },
  getOwnProperties: function() {
   var link = this.GetFocusableElement();
   var properties = {
    ribbonButton: this,
    popup: this.getPopup(),
    alignElement: this.getElement(),
    focusableElement: link
   };
   return properties;
  },
  execute: function() {
   this.execCommand(this.getValueCore());
  },
  getPopup: function() {
   return ASPx.GetControlCollection().Get(getItemID(this) + constants.POPUP_CONTROL_POSTFIX);
  },
  getPopupElement: function() {
   var popup = this.getPopup();
   if(popup)
    return popup.GetContentContainer(-1);
  },
  getColorTable: function() {
   return ASPx.GetControlCollection().Get(this.id + constants.COLORTABLE_POSTFIX);
  },
  getValueCore: function() {
   return this.getColorTable().GetValue();
  },
  getColor: function() {
   return this.getColorTable().GetColor();
  },
  setValueCore: function(color, isAutomaticColor) {
   this.getColorTable().SetColor(color, isAutomaticColor);
   this.updateIndicator();
  },
  getIndicatorElement: function() {
   if(!this.indicatorElement)
    this.indicatorElement = document.getElementById(this.id + constants.COLORINDICATOR_POSTFIX);
   return this.indicatorElement;
  },
  updateIndicator: function() {
   var indicator = this.getIndicatorElement();
   indicator.style.backgroundColor = this.getColor();
  },
  getState: function() {
   var colorTable = this.getColorTable();
   return (colorTable.GetCustomColorTableControl() ? colorTable.GetState() : "") + constants.COLORITEM_CLIENTSTATE_SEPARATOR + this.getColor() +
    constants.COLORITEM_CLIENTSTATE_SEPARATOR + this.getColorTable().IsAutomaticColorSelected();
  },
  updateClientState: function() {
   this.changeClientState(this.getState());
  },
  onClick: function(evt) {
   if(this.dropDownMode) {
    ASPxClientRibbonDropDownSplitItem.prototype.onClick.call(this, evt);
   }
   else {
    if(!this.getEnabledCore()) return;
    setTimeout(function() { this.showPopup(); }.aspxBind(this), 0);
   }
  },
  preparePopupBeforeShow: function() {
  },
  GetFocusableElement: function() {
   return ASPx.GetNodeByTagName(this.getElement(), "A", 0);
  }
 });
 var ASPxClientRibbonTemplateItem = ASPx.CreateClass(ASPxClientRibbonItem, {
  constructor: function(itemInfo) {
   this.constructor.prototype.constructor.call(this, itemInfo);
   if(this.hasKeyboardSupport())
    this.getElement().tabIndex = "-1";
  },
  setEnabledCore: function(enabled, initialization) {
   ASPxClientRibbonItem.prototype.setEnabledCore.call(this, enabled, initialization);
   enabled = this.GetEnabled();
   if(!initialization || !enabled) {
    ASPx.GetControlCollection().ProcessControlsInContainer(this.getElement(), function(control) {
     if(ASPx.IsFunction(control.SetEnabled))
      control.SetEnabled(enabled);
    });
   }
  },
  accessKeyClick: function() {
   setTimeout(function() {
    this.getElement().focus();
   }.aspxBind(this), 0);
  }
 });
 var ASPxClientRibbonToggleItem = ASPx.CreateClass(ASPxClientRibbonButtonItem, {
  constructor: function(ribbonItemInfo, checked) {
   this.constructor.prototype.constructor.call(this, ribbonItemInfo);
   this.checked = !!checked;
  },
  initialize: function() {
   ASPxClientRibbonButtonItem.prototype.initialize.call(this);
   if(this.checked)
    ASPx.GetStateController().SelectElementBySrcElement(this.getElement());
  },
  getValueCore: function() {
   return !!this.checked;
  },
  setValueCore: function(value) {
   value = !!value;
   if(this.getValueCore() == value)
    return;
   var element = this.getElement();
   this.checked = value;
   if(this.checked)
    ASPx.GetStateController().SelectElementBySrcElement(element);
   else
    ASPx.GetStateController().DeselectElementBySrcElement(element);
   this.setCheckedState();
  },
  onClick: function(evt) {
   if(!this.getEnabledCore()) return;
   this.setValueCore(!this.checked);
   this.execCommand(this.checked);
  },
  setCheckedState: function() {
   this.changeClientState(this.checked);
  }
 });
 var ASPxClientRibbonOptionItem = ASPx.CreateClass(ASPxClientRibbonToggleItem, {
  constructor: function(itemInfo, checked, optionGroup) {
   this.constructor.prototype.constructor.call(this, itemInfo, checked);
   this.optionGroup = optionGroup;
  },
  setValueCore: function(value) {
   ASPxClientRibbonToggleItem.prototype.setValueCore.call(this, value);
   if(this.checked && this.optionGroup) {
    this.forEachBarItem(function(item) {
     if(item !== this && item instanceof ASPxClientRibbonOptionItem && item.optionGroup === this.optionGroup)
      item.setValueCore(false);
    }.bind(this));
   }
  },
  setCheckedState: function() {
   if(this.checked)
    this.changeClientState(this.checked);
   else
    this.changeClientState();
  }
 });
 var ASPxClientRibbonEditorItem = ASPx.CreateClass(ASPxClientRibbonItem, {
  initialize: function() {
   ASPxClientRibbonItem.prototype.initialize.call(this);
   if(this.getControlEnabled())
    this.getEditor().ValueChanged.AddHandler(this.onValueChanged.bind(this));
  },
  onValueChanged: function() {
   this.execCommand(this.getEditor().GetValue());
  },
  getValueCore: function() {
   if(this.getControlEnabled())
    return this.getEditor().GetValue();
  },
  setValueCore: function(value) {
   if(this.getControlEnabled())
    this.getEditor().SetValue(value);
  },
  setEnabledCore: function(enabled, initialization) {
   ASPxClientRibbonItem.prototype.setEnabledCore.call(this, enabled, initialization);
   if(this.getControlEnabled())
    this.getEditor().SetEnabled(this.enabled);
  },
  getEditor: function() {
   return ASPx.GetControlCollection().Get(getItemID(this) + this.getEditorPostfix());
  },
  getEditorPostfix: function() {
  }
 });
 var ASPxClientRibbonCheckBoxItem = ASPx.CreateClass(ASPxClientRibbonEditorItem, {
  getEditorPostfix: function() {
   return constants.CHECKBOX_POSTFIX;
  },
  accessKeyClick: function() {
   this.getEditor().OnClick();
  }
 });
 var ASPxClientRibbonComboBoxItem = ASPx.CreateClass(ASPxClientRibbonEditorItem, {
  getEditorPostfix: function() {
   return constants.COMBOBOX_POSTFIX;
  },
  accessKeyClick: function() {
   this.getEditor().OnDropDownCore();
  }
 });
 var ASPxClientRibbonDateEditItem = ASPx.CreateClass(ASPxClientRibbonEditorItem, {
  getEditorPostfix: function() {
   return constants.DATEEDIT_POSTFIX;
  },
  accessKeyClick: function() {
   this.getEditor().OnDropDownCore();
  }
 });
 var ASPxClientRibbonSpinEditItem = ASPx.CreateClass(ASPxClientRibbonEditorItem, {
  getEditorPostfix: function() {
   return constants.SPINEDIT_POSTFIX;
  },
  accessKeyClick: function() {
   this.getEditor().Focus();
  }
 });
 var ASPxClientRibbonTextBoxItem = ASPx.CreateClass(ASPxClientRibbonEditorItem, {
  getEditorPostfix: function() {
   return constants.TEXTBOX_POSTFIX;
  },
  accessKeyClick: function() {
   this.getEditor().Focus();
  }
 });
 var ASPxClientRibbonGroup = ASPx.CreateClass(null, {
  constructor: function(ribbon, tab, index, groupInfo) {
   this.ribbon = ribbon;
   this.tab = tab;
   this.index = index;
   this.name = groupInfo.n;
   this.items = [];
   this.accessKey = groupInfo.ak || "";
   this.subElements = [];
  },
  GetVisible: function() {
   return !!this.getElement();
  },
  initialize: function() {
   var items = this.items;
   for(var item, i = 0; item = items[i]; i++)
    item.initialize();
  },
  getElement: function() {
   if(!this.element)
    this.element = document.getElementById(this.tab.getRibbonID() + constants.TAB_CONTENTCONTROL_POSTFIX +
     this.tab.index + constants.GROUP_POSTFIX + this.index);
   return this.element;
  },
  getSubElements: function() {
   if(this.subElements.length === 0) {
    var element = this.getElement();
    this.subElements.push(ASPx.GetNodeByClassName(element, constants.CLASSNAMES.GROUP_CONTENT));
    var groupLabel = ASPx.GetNodeByClassName(element, constants.CLASSNAMES.GROUP_LABEL);
    groupLabel && this.subElements.push(groupLabel);
   }
   return this.subElements;
  },
  getIndexPath: function() {
   return this.tab.index + ASPx.ItemIndexSeparator + this.index;
  },
  accessKeyClick: function() {
   this.onExpandButtonClick();
  }
 });
 var ASPxClientRibbonTab = ASPx.CreateClass(null, {
  constructor: function(ribbon, index, tabInfo) {
   this.ribbon = ribbon;
   this.index = index;
   this.name = tabInfo.n || "";
   this.visible = tabInfo.v ? true : false;
   this.groups = [];
   this.isContext = tabInfo.c || false;
   this.categoryName = tabInfo.cn || "";
   this.tabElement = null;
   this.listElement = null;
   this.initialized = false;
   this.accessKey = tabInfo.ak || "";
  },
  GetText: function() {
   return this.hasTabs() ? this.getTabControlTab().GetText() : "";
  },
  SetEnabled: function(enabled) {
   if(this.hasTabs())
    this.getTabControlTab().SetEnabled(enabled);
  },
  GetEnabled: function() {
   if(this.hasTabs())
    return this.getTabControlTab().GetEnabled();
   return true;
  },
  GetVisible: function() {
   if(this.isContext)
    return this.visible;
   else
    return !!this.getTabContentElement();
  },
  hasTabs: function() {
   return this.ribbon.isBarItemsTabVisible(this);
  },
  initialize: function(forced) {
   if(this.initialized) return;
   this.initializeCore(forced);
  },
  initializeCore: function(forced) {
   var groups = this.groups;
   for(var group, i = groups.length - 1; group = groups[i]; i--) {
    group.initialize();
   }
   this.initialized = true;
  },
  getRibbonID: function() {
   return this.ribbon.getBarItemsIDPrefix();
  },
  deleteModifications: function() { },
  recalculateModifications: function() { },
  adjustItems: function() {
   for(var i = 0, group; group = this.groups[i]; i++) {
    for(var j = 0, item; item = group.items[j]; j++) {
     item.adjust();
    }
   }
  },
  getTabControlTab: function() {
   return this.ribbon.getBarItemTabControlTab(this.index);
  },
  getTabContentElement: function() {
   if(!this.tabElement)
    this.tabElement = document.getElementById(this.getRibbonID() + constants.TAB_CONTENTCONTROL_POSTFIX + this.index);
   return this.tabElement;
  },
  getWrapperElement: function() {
   if(this.wrapperElement === undefined)
    this.wrapperElement = ASPx.GetNodeByClassName(this.getTabContentElement(), constants.CLASSNAMES.TABWRAPPER);
   return this.wrapperElement;
  },
  getListElement: function() {
   if(!this.listElement)
    this.listElement = ASPx.GetNodeByClassName(this.getTabContentElement(), constants.CLASSNAMES.GROUPLIST);
   return this.listElement;
  },
  setVisible: function(visible) { },
  accessKeyClick: function() { }
 });
 var ASPxClientRibbonItemInfo = ASPx.CreateClass(null, {
  constructor: function(ribbon, group, index, itemInfo) {
   this.ribbon = ribbon;
   this.group = group;
   this.index = index;
   this.name = itemInfo.c;
   this.type = itemInfo.t;
   this.subGroup = itemInfo.sg;
   this.clientDisabled = itemInfo.cdi;
   this.text = itemInfo.txt || "";
   this.rawInfo = itemInfo;
   this.accessKey = itemInfo.ak || "";
  }
 });
 var ASPxRibbonPopupMenuHelper = ASPx.CreateClass(ASPx.KbdHelper, {
  constructor: function(name, items) {
   this.name = name;
   this.items = items;
   this.lastShownPopup = null;
   this.currentDropDownItem = null;
  },
  getPopupMenu: function() {
   return ASPx.GetControlCollection().Get(this.name + constants.POPUP_MENU_POSTFIX);
  },
  popupWasNotShownForThisItem: function(item) {
   return !this.lastShownPopup || getItemID(item, true) !== this.lastShownPopup.cpRibbonItemID;
  },
  onItemPopupPopUp: function(itemID, popup) {
   this.currentDropDownItem = this.items[itemID];
   this.lastShownPopup = popup;
  },
  onItemPopupCloseUp: function(itemID, popup) {
   var element = this.currentDropDownItem.getElement();
   if(this.currentDropDownItem.hoverItem) {
    this.currentDropDownItem.hoverItem.Cancel(element);
    this.currentDropDownItem.hoverItem = null;
   }
   this.currentDropDownItem.col = this.currentDropDownItem.previousCol;
   this.currentDropDownItem = null;
   setTimeout(function() {
    if(this.lastShownPopup === popup)
     this.lastShownPopup = undefined;
   }.aspxBind(this), 100);
  },
  initializeEvents: function() {
   var popupMenu = this.getPopupMenu();
   if(popupMenu)
    this.initializeEventsCore(popupMenu, null);
  },
  initializeEventsCore: function(popup, item) {
   if(popup.ItemClick) {
    popup.ItemClick.AddHandler(function(s, e) {
     this.onMenuItemClick(item || s.cpRibbonItemID, e.item);
    }.bind(this));
   }
   popup.CloseUp.AddHandler(function(s, e) {
    if(e.item && e.item.parent) return;
    var itemID = s.cpRibbonItemID;
    this.onItemPopupCloseUp(itemID, popup);
   }.bind(this));
   popup.PopUp.AddHandler(function(s, e) {
    if(e.item && e.item.parent) return;
    var itemID = s.cpRibbonItemID;
    this.onItemPopupPopUp(itemID, popup);
   }.bind(this));
  },
  onMenuItemClick: function(item, menuItem) {
   if(typeof item === "string")
    item = this.items[item];
   item.onMenuItemClick(menuItem);
  },
  populatePopupMenuWithItems: function(ribbonItem) {
   var popupMenu = this.getPopupMenu();
   popupMenu.ClearItems();
   popupMenu.cpRibbonItemID = getItemID(ribbonItem, true);
   if(!ribbonItem.items) return;
   var menuItems = this.populateMenuItems(ribbonItem.items);
   popupMenu.CreateItems(menuItems);
  },
  populateMenuItems: function(items) {
   var resultItems = [];
   ASPx.Data.ForEach(items, function(ribbonMenuItem) {
    childItems = ribbonMenuItem.items ? this.populateMenuItems(ribbonMenuItem.items) : null;
    var popupMenuItem = {
     imageUrl: ribbonMenuItem.smallImage ? ribbonMenuItem.smallImage : ribbonMenuItem.largeImage ? ribbonMenuItem.largeImage : null,
     imageHottrackSrc: ribbonMenuItem.smallImageHottrackSrc ? ribbonMenuItem.smallImageHottrackSrc : ribbonMenuItem.largeImageHottrackSrc ? ribbonMenuItem.largeImageHottrackSrc : null,
     imageClassName: ribbonMenuItem.className,
     clientEnabled: ribbonMenuItem.enabled,
     clientVisible: ribbonMenuItem.GetVisible(),
     dropDownMode: ribbonMenuItem.dropDownMode,
     text: ribbonMenuItem.text,
     tooltip: ribbonMenuItem.tooltip,
     navigateUrl: ribbonMenuItem.navigateUrl,
     target: ribbonMenuItem.target,
     beginGroup: ribbonMenuItem.beginGroup,
     textTemplate: ribbonMenuItem.textTemplate,
     styles: ribbonMenuItem.styles,
     items: childItems,
     isSvg: ribbonMenuItem.isSvg
    };
    if(ribbonMenuItem instanceof ASPx.ASPxClientRibbonDropDownToggleButtonItem) {
     popupMenuItem.groupName = getItemID(ribbonMenuItem, true);
     popupMenuItem.checked = ribbonMenuItem.checked;
    }
    resultItems.push(popupMenuItem);
   }.aspxBind(this));
   return resultItems;
  },
  tryApplyHoverState: function(hoverItem) {
   if(hoverItem.name === this.currentDropDownItem.id) {
    var element = this.currentDropDownItem.getElement();
    var newHoverItem = hoverItem.Clone();
    this.currentDropDownItem.hoverItem = newHoverItem;
    newHoverItem.Apply(element);
   }
  }
 });
 function getGroupID(group) {
  return "T" + group.tab.index + "G" + group.index;
 }
 function getItemID(item, excludeRibbon) {
  var id = getGroupID(item.group) + "I";
  id = excludeRibbon ? id : (item.group.tab.getRibbonID() + "_" + id);
  if(item.type === constants.ITEMTYPES.DROPDOWNTOGGLEBUTTON || item.type === constants.ITEMTYPES.DROPDOWNSPLIT) {
   id += item.getIndexPath(true);
  } else {
   id += item.index;
  }
  return id;
 }
 function getLargeItemWidth(textContainer, marginWidth, popOutWidth) {
  popOutWidth = popOutWidth === undefined ? 0 : popOutWidth;
  marginWidth = marginWidth === undefined ? 0 : marginWidth;
  var html = textContainer.innerHTML;
  var words = ASPx.GetInnerText(textContainer).split(' ');
  var wordsWidths = [];
  textContainer.style.visibility = "hidden";
  textContainer.innerHTML = "&nbsp;";
  var spaceWidth = getElementOffsetWidth(textContainer);
  var commonWidth = spaceWidth;
  for(var i = 0; i < words.length; i++) {
   var word = words[i];
   textContainer.innerHTML = word;
   var width = getElementOffsetWidth(textContainer);
   commonWidth += width;
   if(i > 0)
    commonWidth += spaceWidth;
   wordsWidths.push(width);
  }
  var labelWidth = getLargeItemLabelWidth(commonWidth, popOutWidth, spaceWidth, wordsWidths);
  textContainer.innerHTML = html;
  textContainer.style.visibility = "";
  return labelWidth + marginWidth;
 }
 function getLargeItemLabelWidth(firstRowWidth, secondRowWidth, spaceWidth, wordsWidths) {
  var result = Math.max(firstRowWidth, secondRowWidth);
  for(var i = wordsWidths.length - 1; i > 0; i--) {
   if(firstRowWidth - secondRowWidth > 0) {
    secondRowWidth += (secondRowWidth ? spaceWidth : 0) + wordsWidths[i];
    firstRowWidth -= wordsWidths[i] + spaceWidth;
    if(Math.max(firstRowWidth, secondRowWidth) >= result)
     return result;
    result = Math.ceil(Math.max(firstRowWidth, secondRowWidth));
   }
  }
  return result;
 }
 function getElementOffsetWidth(element) {
  return element.getBoundingClientRect().width;
 }
 var ASPxRibbonItemsFactory = ASPx.CreateClass(null, {
  create: function(control, tabsInfo, tabs, items) {
   for(var i = 0, tabInfo; tabInfo = tabsInfo[i]; i++) {
    var tab = this.createTab(control, i, tabInfo);
    tabs.push(tab);
    var tabServerVisible = !!tab.getTabContentElement();
    if(!tabServerVisible)
     continue;
    for(var j = 0, groupInfo; groupInfo = tabInfo.g[j]; j++) {
     var group = this.createGroup(control, tab, j, groupInfo);
     tab.groups.push(group);
     if(!group.GetVisible())
      continue;
     for(var k = 0, itemInfo; itemInfo = groupInfo.i[k]; k++) {
      var ribbonItemInfo = new ASPx.ASPxClientRibbonItemInfo(control, group, k, itemInfo);
      var item = this.createItem(ribbonItemInfo);
      group.items.push(item);
      items[getItemID(item, true)] = item;
     }
    }
   }
  },
  createTab: function(control, index, tabInfo) {
   return new ASPxClientRibbonTab(control, index, tabInfo);
  },
  createGroup: function(control, tab, index, groupInfo) {
   return new ASPxClientRibbonGroup(control, tab, index, groupInfo);
  },
  createItem: function(ribbonItemInfo) {
   var rawInfo = ribbonItemInfo.rawInfo;
   switch(ribbonItemInfo.type) {
    case constants.ITEMTYPES.BUTTON:
     return new ASPxClientRibbonButtonItem(ribbonItemInfo, rawInfo.nu);
    case constants.ITEMTYPES.DROPDOWNMENU:
     return new ASPxClientRibbonDropDownMenuItem(ribbonItemInfo, rawInfo.i, rawInfo.nu, rawInfo);
    case constants.ITEMTYPES.DROPDOWNSPLIT:
     return new ASPxClientRibbonDropDownSplitItem(ribbonItemInfo, rawInfo.i, rawInfo.nu, rawInfo);
    case constants.ITEMTYPES.DROPDOWNTOGGLEBUTTON:
     return new ASPxClientRibbonDropDownToggleButtonItem(ribbonItemInfo, rawInfo.i, rawInfo.nu, rawInfo);
    case constants.ITEMTYPES.CHECKBOX:
     return new ASPxClientRibbonCheckBoxItem(ribbonItemInfo);
    case constants.ITEMTYPES.COMBOBOX:
     return new ASPxClientRibbonComboBoxItem(ribbonItemInfo);
    case constants.ITEMTYPES.TEXTBOX:
     return new ASPxClientRibbonTextBoxItem(ribbonItemInfo);
    case constants.ITEMTYPES.SPINEDIT:
     return new ASPxClientRibbonSpinEditItem(ribbonItemInfo);
    case constants.ITEMTYPES.DATEEDIT:
     return new ASPxClientRibbonDateEditItem(ribbonItemInfo);
    case constants.ITEMTYPES.TOGGLE:
     return new ASPxClientRibbonToggleItem(ribbonItemInfo, rawInfo.chk);
    case constants.ITEMTYPES.COLOR:
     return new ASPxClientRibbonColorButtonItem(ribbonItemInfo, rawInfo.color, rawInfo.iac, rawInfo.ddm);
    case constants.ITEMTYPES.TEMPLATE:
     return new ASPxClientRibbonTemplateItem(ribbonItemInfo);
    case constants.ITEMTYPES.OPTION:
     return new ASPxClientRibbonOptionItem(ribbonItemInfo, rawInfo.chk, rawInfo.og);
    default:
     return new ASPxClientRibbonItem(ribbonItemInfo);
   }
  }
 });
 ASPxClientRibbonItem.constants = constants;
 ASPxClientRibbonItem.getItemID = getItemID;
 ASPxClientRibbonItem.getLargeItemWidth = getLargeItemWidth;
 ASPx.ASPxClientRibbonDropDownToggleButtonItem = ASPxClientRibbonDropDownToggleButtonItem;
 ASPx.ASPxClientRibbonComboBoxItem = ASPxClientRibbonComboBoxItem;
 ASPx.ASPxClientRibbonItemInfo = ASPxClientRibbonItemInfo;
 ASPx.ASPxClientRibbonEditorItem = ASPxClientRibbonEditorItem;
 ASPx.ASPxRibbonPopupMenuHelper = ASPxRibbonPopupMenuHelper;
 ASPx.ASPxRibbonItemsFactory = ASPxRibbonItemsFactory;
 ASPx.ASPxClientRibbonDropDownMenuItem = ASPxClientRibbonDropDownMenuItem;
 window.ASPxClientRibbonItem = ASPxClientRibbonItem;
 window.ASPxClientRibbonItemInfo = ASPxClientRibbonItemInfo;
 window.ASPxClientRibbonItemInfo.getItemID = getItemID;
 window.ASPxClientRibbonGroup = ASPxClientRibbonGroup;
 window.ASPxClientRibbonTab = ASPxClientRibbonTab;
})();
(function() {
 var constants = ASPxClientRibbonItem.constants;
 var getItemID = ASPxClientRibbonItem.getItemID;
 var getLargeItemWidth = ASPxClientRibbonItem.getLargeItemWidth;
 ASPxClientRibbonCollection = {
  ribbons: {},
  register: function(ribbon) {
   ASPxClientRibbonCollection.ribbons[ribbon.name] = ribbon;
  },
  find: function(id) {
   var ribbons = ASPxClientRibbonCollection.ribbons;
   for(var name in ribbons) {
    if(!ribbons.hasOwnProperty(name)) continue;
    if(id.indexOf(name) == 0)
     return ASPxClientRibbonCollection.get(name);
   }
   return null;
  },
  get: function(name) {
   return ASPxClientRibbonCollection.ribbons[name];
  },
  onMouseDown: function(evt) {
   for(var name in ASPxClientRibbonCollection.ribbons) {
    if(!ASPxClientRibbonCollection.ribbons.hasOwnProperty(name)) continue;
    var ribbon = ASPxClientRibbonCollection.get(name);
    if(ASPx.IsExists(ribbon.GetMainElement()))
     ribbon.onMouseDown(evt);
   }
  }
 };
 ASPx.Evt.AttachEventToDocument(ASPx.TouchUIHelper.touchMouseDownEventName, ASPxClientRibbonCollection.onMouseDown);
 var ASPxClientRibbon = ASPx.CreateClass(ASPxClientControl, {
  constructor: function(name) {
   this.constructor.prototype.constructor.call(this, name);
   this.activeTab = null;
   this.activeTabIndex = 0;
   this.tabs = [];
   this.items = {};
   this.CommandExecuted = new ASPxClientEvent();
   this.ActiveTabChanged = new ASPxClientEvent();
   this.MinimizationStateChanged = new ASPxClientEvent();
   this.FileTabClicked = new ASPxClientEvent();
   this.DialogBoxLauncherClicked = new ASPxClientEvent();
   this.KeyTipsClosedOnEscape = new ASPxClientEvent();
   this.currentGroupInPopup = null;
   ASPxClientRibbonCollection.register(this);
   this.adjustLocked = false;
   this.minimized = false;
   this.showFileTab = true;
   this.allowMinimize = true;
   this.showTabs = true;
   this.oneLineMode = false;
   this.tabContentCollapsed = false;
   this.lastTabContentWidth = "";
   this.tabControl = null;
   this.keyboardSupport = false;
   this.accessKeysHelper = null;
   this.accessKey = null;
   this.keyTipModeShortcut = null;
   this.keyTipsPopupControl = null;
   this.fileTabAccesskey = null;
   this.pinButtonVisible = false;
   this.groupScroller = new ASPxClientRibbon.GroupScroller(this);
   this.groupScrollManager = {};
  },
  SetEnabled: function(enabled) {
   if(!this.enabled) return;
   this.setEnabledCore(enabled, false);
  },
  GetTab: function(index) {
   return this.tabs[index] || null;
  },
  GetTabByName: function(name) {
   for(var tab, i = 0; tab = this.tabs[i]; i++) {
    if(tab.name == name)
     return tab;
   }
   return null;
  },
  GetTabCount: function() {
   return this.tabs.length;
  },
  GetActiveTab: function() {
   return this.activeTab;
  },
  SetActiveTab: function(tab) {
   this.setActiveTabControlTab(tab.index);
  },
  SetActiveTabIndex: function(index) {
   this.setActiveTabControlTab(index);
  },
  GetItemByName: function(name) {
   var items = this.items;
   var subItem = null;
   for(var itemID in items) {
    if(!items.hasOwnProperty(itemID)) continue;
    if(items[itemID].name === name)
     return items[itemID];
    if(items[itemID].getItemByName && !subItem)
     subItem = items[itemID].getItemByName(name);
   }
   return subItem;
  },
  GetItemValueByName: function(name) {
   var item = this.GetItemByName(name);
   if(item)
    return item.GetValue();
  },
  SetItemValueByName: function(name, value) {
   var item = this.GetItemByName(name);
   if(item)
    item.SetValue(value);
  },
  SetMinimized: function(minimized) {
   this.setMininizedCore(minimized, true);
  },
  GetMinimized: function() {
   return this.minimized;
  },
  SetContextTabCategoryVisible: function(categoryName, visible) {
   for(var tab, i = 0; tab = this.tabs[i]; i++) {
    if(tab.isContext && tab.categoryName == categoryName)
     tab.setVisible(visible);
   }
  },
  ShowKeyTips: function() {
   if(this.accessKeysHelper)
    this.accessKeysHelper.Activate();
  },
  SetData: function(data) {
   if(data.items)
    this.loadItems(data.items);
  },
  InlineInitialize: function() {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   var mainElement = this.GetMainElement(),
    controlWidth = mainElement.offsetWidth;
   this.InitializeEvents();
   if(this.showTabs) {
    var existentActiveTab = this.getTabControlTab(this.activeTabIndex);
    if ((existentActiveTab && !existentActiveTab.visible) || !existentActiveTab) {
     return;
    }
   }
   this.setActiveTabContainer(this.activeTabIndex);
   this.setEnabledCore(this.enabled && this.clientEnabled, true);
   if(this.showTabs && !this.minimized)
    this.setActiveTabControlTab(this.activeTabIndex);
   if(this.minimized) {
    this.switchInactiveTab(false);
    ASPx.GetStateController().SelectElementBySrcElement(this.getMinimizeButton());
   }
   if(this.widthValueSetInPercentage)
    this.initWidth = mainElement.style.width;
   if(controlWidth > 0) {
    var innerWidth = controlWidth - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(mainElement);
    ASPx.SetOffsetWidth(this.activeTab.getTabContentElement(), innerWidth);
   }
   this.collapseTabContent();
  },
  InitializeEvents: function() {
   var minimizeButton = this.getMinimizeButton();
   if(minimizeButton)
    ASPx.Evt.AttachEventToElement(minimizeButton, "click", this.onMinimizeButtonClick.aspxBind(this));
   this.getPopupMenuHelper().initializeEvents();
  },
  Initialize: function() {
   ASPxClientControl.prototype.Initialize.call(this);
   if(this.activeTab)
    this.activeTab.initialize();
  },
  AfterInitialize: function() {
   ASPxClientControl.prototype.AfterInitialize.call(this);
   if(this.activeTab && this.enabled) {
    this.updatePercentageWidthCore();
    setTimeout(function() { this.activeTab.applyModification(); }.aspxBind(this), 100);
    this.InitializeKeyboard();
   }
  },
  getAddKeyTipFunction: function (keytipPostfix) {
   var keyTipsContainer = this.getKeyTipsContainer();
   var addKeyTip = function (id, accessKey) {
    var keyTipElement = document.createElement("div");
    keyTipElement.setAttribute("id", id + keytipPostfix);
    keyTipElement.setAttribute("class", "dxKeyTipDiv");
    keyTipsContainer.appendChild(keyTipElement);
    var keyTipLabel = document.createElement("div");
    keyTipLabel.innerHTML = accessKey;
    keyTipElement.appendChild(keyTipLabel);
    return keyTipElement;
   }.aspxBind(this);
   return addKeyTip;
  },
  createAccessKeyHelper: function() { return new RibbonAccessKeysHelper(this); },
  InitializeKeyboard: function () {
   if (!this.keyboardSupport)
    return;
   var addKeyTip = this.getAddKeyTipFunction(constants.KEYTIP_POSTFIX);
   this.accessKeysHelper = this.createAccessKeyHelper();
   this.accessKeysHelper.Init(this);
   this.accessKeysHelper.onClosedOnEscape = function () { this.raiseEvent("KeyTipsClosedOnEscape"); }.aspxBind(this);
   var kt = null;
   if (this.showTabs && this.showFileTab) {
    kt = addKeyTip(this.getTabControl().GetVisibleTabElement(this.getTabControlTabIndex(0)).id, this.fileTabAccessKey);
    var fileAccessKey = this.createAccessKey({ accessKeyClick: function() { this.onFileTabClick(); }.aspxBind(this) },
     function() { return this.getTabControl().GetVisibleTabElement(0); }.aspxBind(this), kt);
    this.accessKeysHelper.Add(fileAccessKey);
   }
   for (var i = 0, tab; tab = this.tabs[i]; i++) {
    var tabAccessKey = null;
    if(this.showTabs) {
     if(!tab.GetVisible() && !tab.isContext) continue;
     kt = addKeyTip(this.getTabElement(tab.index, true).id, tab.accessKey);
     tabAccessKey = this.createAccessKey(tab, function(tab) { return this.getTabControl().GetVisibleTabElement(this.getTabControlTabIndex(tab.index)); }.aspxBind(this), kt);
     this.accessKeysHelper.Add(tabAccessKey);
    }
    for(var j = 0, group; group = tab.groups[j]; j++) {
     if(!group.GetVisible()) continue;
     var groupID = group.getElement().id;
     var groupKeyTip = addKeyTip(groupID, group.accessKey);
     var groupAccessKey = this.createAccessKey(group, function(group) { return group.getExpandButtonElement(); }, groupKeyTip);
     if(this.showTabs) {
      tabAccessKey.needShowChilds = !this.showTabs;
      tabAccessKey.Add(groupAccessKey);
     } else {
      this.accessKeysHelper.Add(groupAccessKey);
     }
     var dbl = group.getDialogBoxLauncherElement();
     if (dbl) {
      var dblKeyTip = addKeyTip(groupID + constants.GROUPDIALOGBOXLAUNCHER_POSTFIX, group.dialogBoxLauncherAccessKey);
      groupAccessKey.Add(this.createAccessKey(group, function(group) { return group.getDialogBoxLauncherElement(); }, dblKeyTip, "", true));
     }
     for(var k = 0, item; item = group.items[k]; k++) {
      if(!item.GetVisible()) continue;
      var itemKeyTip = addKeyTip(item.id, item.accessKey);
      item.keyTipElement = itemKeyTip;
      var itemPopup = item.getPopup ? item.getPopup() : null;
      var itemAccessKey = this.createAccessKey(item, function(item) { return item.getAccessKeyPopupElement(); }, itemKeyTip, "", false, itemPopup);
      groupAccessKey.Add(itemAccessKey);
      this.addKeyTipToStateController(itemKeyTip, item);
     }
    }
   }
  },
  addKeyTipToStateController: function (itemKeyTip, item) {
   ASPx.GetStateController().AddDisabledItem(itemKeyTip.id,
   ["dxKeyTipDisabled"], [""], null, null, null);
   ASPx.GetStateController().SetElementEnabled(itemKeyTip, item.GetEnabled());
  },
  AdjustControlCore: function() {
   this.updateLayout(true);
   if(this.showTabs)
    this.getTabControl().AdjustControl(true);
   if(this.keyboardSupport && this.accessKeysHelper && this.accessKeysHelper.AreAccessKeysShown()) {
    this.accessKeysHelper.Update();
   }
  },
  OnBrowserWindowResize: function(e) {
   if(this.minimized)
    this.hideTabMinimizePopup();
   if(this.keyboardSupport && this.accessKeysHelper)
    this.accessKeysHelper.Stop();
   this.updateLayout();
  },
  NeedCollapseControlCore: function() {
   return !this.minimized;
  },
  CollapseControl: function() {
   this.isControlCollapsed = true;
   this.collapseTabContent();
   if(this.showTabs)
    this.getTabControl().CollapseControl();
  },
  ExpandControl: function() {
   this.isControlCollapsed = false;
   if(!this.tabContentCollapsed || !this.widthValueSetInPercentage) {
    if(this.activeTab) {
     var tabContent = this.activeTab.getTabContentElement(),
     tabWrapper = this.activeTab.getWrapperElement();
     tabContent.style.width = this.lastTabContentWidth;
     tabWrapper.style.position = "static";
     tabContent.style.position = "static";
    }
   }
   if(this.showTabs)
    this.getTabControl().ExpandControl();
  },
  collapseTabContent: function() {
   if(!this.tabContentCollapsed && this.activeTab) {
    var tabContent = this.activeTab.getTabContentElement(),
     tabWrapper = this.activeTab.getWrapperElement();
    this.lastTabContentWidth = tabContent.style.width;
    tabContent.style.position = "relative";
    tabWrapper.style.position = "absolute";
    tabContent.style.width = "auto";
    this.tabContentCollapsed = true;
   }
  },
  getPopupMenuHelper: function() {
   if(!this.popupMenuHelper) {
    this.popupMenuHelper = new ASPx.ASPxRibbonPopupMenuHelper(this.name, this.items);
   }
   return this.popupMenuHelper;
  },
  SetWidth: function(width) {
   ASPxClientControl.prototype.SetWidth.call(this, width);
   this.updateLayout(false, true);
   if(this.showTabs)
    this.getTabControl().AdjustControl(true);
  },
  updateLayout: function(adjustItems, forceUpdating) {
   if(forceUpdating || !this.adjustLocked) {
    if(forceUpdating || this.widthValueSetInPercentage)
     this.updatePercentageWidth(ASPx.Browser.Edge && (adjustItems || forceUpdating));
    this.hideAllPopups(true, true);
    this.updateTabMinimizePopup();
    if(forceUpdating || !this.widthValueSetInPercentage)
     this.activeTab.applyModification();
    if(adjustItems && this.activeTab)
     this.activeTab.adjustItems();
    this.groupScroller.updateGroupScrollButtonsVisibility();
   }
  },
  updateTabMinimizePopup: function() {
   var tabMinimizePopup = this.getTabMinimizePopup();
   if(tabMinimizePopup && tabMinimizePopup.IsVisible()) {
    var tcMainElement = this.getTabControl().GetMainElement();
    tabMinimizePopup.Hide();
    tabMinimizePopup.SetWidth(tcMainElement.offsetWidth);
    tabMinimizePopup.ShowAtElement(tcMainElement);
   }
  },
  updatePercentageWidth: function(immediately) {
   if(this.resizingTimer === undefined || immediately) {
    this.collapseTabContent();
    if(immediately)
     this.updatePercentageWidthCore();
    else
     this.resizingTimer = setTimeout(function() { this.updatePercentageWidthCore(); }.aspxBind(this), 100);
   }
  },
  updatePercentageWidthCore: function() {
   if(!this.activeTab) return;
   var tabContent = this.activeTab.getTabContentElement();
   var tabWrapper = this.activeTab.getWrapperElement();
   if(this.showTabs)
    this.getTabControl().CollapseControl();
   if(tabContent.offsetWidth > 0)
    ASPx.SetOffsetWidth(tabContent, tabContent.offsetWidth);
   tabWrapper.style.position = "static";
   tabContent.style.position = "static";
   this.tabContentCollapsed = false;
   this.activeTab.applyModification();
   if(this.showTabs)
    this.getTabControl().AdjustControl();
   this.resizingTimer = undefined;
   this.groupScroller.updateGroupScrollButtonsVisibility();
  },
  applyModifications: function() {
   if(!this.modificationsTimer) {
    this.modificationsTimer = window.setTimeout(function() {
     this.activeTab.applyModification();
     this.modificationsTimer = undefined;
    }.aspxBind(this), 200);
   }
  },
  loadItems: function(tabsInfo) {
   var factory = this.getBarItemsFactory();
   factory.create(this, tabsInfo, this.tabs, this.items);
  },
  getBarItemsFactory: function() {
   return this.itemsFactory || (this.itemsFactory = new ASPxRibbonItemsFactoryEx());
  },
  hideAllPopups: function(lockAdjust, skipTempTab) {
   lockAdjust = lockAdjust === undefined ? true : lockAdjust;
   if(lockAdjust)
    this.adjustLocked = true;
   this.hideGroupCollapsePopup(false, false);
   var helper = this.getPopupMenuHelper();
   if(helper.lastShownPopup && helper.lastShownPopup.IsVisible())
    helper.lastShownPopup.Hide();
   if(lockAdjust)
    this.adjustLocked = false;
   if(!skipTempTab)
    this.hideTabMinimizePopup();
  },
  onTabChanged: function (tcTab, byAccesKey) {
   if(tcTab.name == constants.INACTIVETAB_NAME) return;
   var newTabIndex = this.getRibbonTabIndex(tcTab.index);
   if(this.activeTab) {
    var actTabIndex = this.activeTab.index;
    this.setActiveTabContainer(newTabIndex, actTabIndex != newTabIndex);
   }
   else {
    var actTabIndex = this.getRibbonTabIndex(tcTab.index);
    this.setActiveTabContainer(newTabIndex, true);
   }
   if(this.widthValueSetInPercentage)
    this.updatePercentageWidth(ASPx.Browser.Edge);
   if (byAccesKey)
    this.accessKeysHelper.ShowAccessKeys();
  },
  onFileTabClick: function () {
   this.raiseEvent("FileTabClicked", new ASPxClientEventArgs());
  },
  onTabClick: function(tcTabIndex, evt) {
   if(evt.tab.name == constants.FILETAB_NAME) {
    evt.cancel = true;
    this.onFileTabClick();
   }
   var tabIndex = this.getRibbonTabIndex(tcTabIndex);
   if(this.minimized && tabIndex > -1) {
    setTimeout(function () {
     evt.cancel = true;
     if(this.minimized) {
      var tc = this.getTabControl();
      if(this.currentTemporaryTabPageIndex == tabIndex) {
       tc.SetActiveTab(tc.GetTab(tcTabIndex));
       this.lastShownTemporaryTabPageIndex = this.currentTemporaryTabPageIndex;
      }
      else {
       tc.SetActiveTab(tc.GetTabByName(constants.INACTIVETAB_NAME));
       this.lastShownTemporaryTabPageIndex = this.currentTemporaryTabPageIndex;
       this.currentTemporaryTabPageIndex = -1;
      }
     }
    }.aspxBind(this), 100);
   }
  },
  onTabElementMouseDown: function (tab) {
   if(this.minimized && tab.GetEnabled()) {
    setTimeout(function() {
     if(this.currentTemporaryTabPageIndex == tab.index)
      this.hideTabMinimizePopup();
     else
      this.showTabMinimizePopup(tab.index);
    }.aspxBind(this), 0);
   }
  },
  onTabElementDblClick: function(tab) {
   if(!this.GetEnabled()) return;
   this.setMininizedCore(!this.minimized);
   if(this.minimized)
    ASPx.GetStateController().SetCurrentHoverElementBySrcElement(this.getTabElement(tab.index, false));
  },
  onMinimizeButtonClick: function() {
   if(this.GetEnabled())
    this.setMininizedCore(!this.minimized);
  },
  onGalleryPopupPopUp: function(itemID, popup) {
   this.items[itemID].onPopupPopUp();
   this.getPopupMenuHelper().onItemPopupPopUp(itemID, popup);
  },
  onGalleryPopupCloseUp: function(itemID, popup) {
   this.getPopupMenuHelper().onItemPopupCloseUp(itemID, popup);
  },
  onGalleryPopupResize: function(itemID, popup) {
   var helper = this.getPopupMenuHelper();
   var ribbonGallery = helper.currentDropDownItem;
   if(ribbonGallery) {
    ribbonGallery.previousCol = ribbonGallery.col;
    ribbonGallery.col = ribbonGallery.getCurrentColCount();
    if(this.keyboardSupport)
     ribbonGallery.keyboardHelper.Focus();
   }
  },
  onMouseDown: function(evt) {
   if(!this.enabled) return;
   var source = ASPx.Evt.GetEventSource(evt);
   var helper = this.getPopupMenuHelper();
   if(ASPx.GetIsParent(this.GetMainElement(), source)) {
    if(this.currentTemporaryTabPageIndex > -1 && !ASPx.GetIsParent(this.activeTab.getTabContentElement(), source)) {
     if((!this.currentGroupInPopup || this.currentGroupInPopup.tab != this.activeTab) && (!helper.currentDropDownItem || helper.currentDropDownItem.group.tab != this.activeTab))
      this.hideTabMinimizePopup();
    }
    this.groupScroller.onMouseDown(evt, source);
   } else {
    this.hideAllPopups();
    if(this.minimized) {
     var tc = this.getTabControl();
     tc.SetActiveTab(tc.GetTabByName(constants.INACTIVETAB_NAME));
    }
   }
   if(this.currentGroupInPopup && !ASPx.GetIsParent(this.getGroupCollapsePopup().GetContentContainer(-1), source)) {
    var isExpandButtonClick = ASPx.GetIsParent(this.currentGroupInPopup.getExpandButtonElement(), source);
    var isInGroupPopupItemClick = helper.currentDropDownItem && ASPx.GetIsParent(helper.currentDropDownItem.getPopupElement(), source);
    if(!isExpandButtonClick && !isInGroupPopupItemClick)
     this.hideGroupCollapsePopup();
   }
  },
  onExecCommand: function(item, parameter) {
   if(!item.getEnabledCore()) return;
   this.hideGroupCollapsePopup();
   var processOnServer = this.IsServerEventAssigned("CommandExecuted");
   var args = new ASPxClientRibbonCommandExecutedEventArgs(item, parameter, processOnServer);
   this.raiseEvent("CommandExecuted", args);
   if(args.processOnServer)
    this.SendPostBack("COMMANDEXECUTED" + ASPx.CallbackSeparator + item.getFullIndexPath() + ASPx.CallbackSeparator + parameter);
  },
  onActiveTabChanged: function(needRaiseEvent) {
   if(needRaiseEvent)
    this.raiseEvent("ActiveTabChanged", new ASPxClientRibbonTabEventArgs(this.activeTab));
   this.groupScroller.onActiveTabChanged();
  },
  raiseEvent: function(eventName, args) {
   var evt = this[eventName];
   if(!evt.IsEmpty())
    evt.FireEvent(this, args);
   return args;
  },
  setEnabledCore: function(enabled, initialization) {
   if(!initialization)
    ASPxClientControl.prototype.SetEnabled.call(this, enabled);
   var clientEnabled = this.clientEnabled;
   for(var itemID in this.items) {
    if(!this.items.hasOwnProperty(itemID)) continue;
    var item = this.items[itemID];
    item.setEnabledCore(clientEnabled, initialization);
   }
   if(this.activeTab) {
    for(var group, i = 0; group = this.activeTab.groups[i]; i++) {
     var eb = group.getExpandButtonElement();
     if(eb)
      ASPx.GetStateController().SetElementEnabled(eb, enabled);
     var dbl = group.getDialogBoxLauncherElement();
     if(dbl)
      ASPx.GetStateController().SetElementEnabled(dbl, clientEnabled);
    }
   }
   var minimizeButton = this.getMinimizeButton();
   if(minimizeButton)
    ASPx.GetStateController().SetElementEnabled(minimizeButton, clientEnabled);
  },
  setMininizedCore: function (minimized, skipEvent) {
   if (this.pinButtonVisible)
    this.changeVisiblePinMinButtons(true);
   if (!this.allowMinimize || this.minimized == minimized) return;
   this.hideTabMinimizePopup();
   this.minimized = minimized;
   this.adjustLocked = true;
   if(this.minimized) {
    if (this.activeTab) this.activeTab.hideContainer();
    this.switchInactiveTab(false);
    ASPx.GetStateController().SelectElementBySrcElement(this.getMinimizeButton());
   }
   else {
    if (this.activeTab) this.activeTab.showContainer();
    this.switchInactiveTab(true);
    ASPx.GetStateController().DeselectElementBySrcElement(this.getMinimizeButton());
   }
   this.AdjustControlCore();
   this.adjustLocked = false;
   if(!skipEvent)
    this.raiseEvent("MinimizationStateChanged", new ASPxClientRibbonMinimizationStateEventArgs(minimized ? ASPxClientRibbonState.Minimized : ASPxClientRibbonState.Normal));
  },
  changeVisiblePinMinButtons: function (minVisible) {
   this.pinButtonVisible = !minVisible;
   this.getMinimizeButtonImage().style.display = minVisible ? "" : "none";
   this.getPinButtonImage().style.display = minVisible ? "none" : "";
  },
  restoreTabContainerContent: function() {
   if(this.popupActiveTab) {
    var tabContent = this.popupActiveTab.getTabContentElement();
    tabContent.style.display = 'none';
    this.getTabsContainer().appendChild(tabContent);
    this.popupActiveTab = null;
   }
  },
  showTabMinimizePopup: function (index) {
   if(!this.minimized || !this.isInitialized) return;
   var popup = this.getTabMinimizePopup();
   this.changeVisiblePinMinButtons(false);
   if(this.lastShownTemporaryTabPageIndex == index) return;
   this.currentTemporaryTabPageIndex = index;
   this.lastShownTemporaryTabPageIndex = index;
   var popupContent = popup.GetContentContainer(-1);
   var tab = this.tabs[index];
   this.restoreTabContainerContent();
   if (popupContent.childNodes.length)
    popupContent.innerHTML = "";
   if(!tab.initialized)
    tab.initialize(true);
   var tabContainer = tab.getTabContentElement();
   popupContent.appendChild(tabContainer);
   var tcMainElement = this.getTabControl().GetMainElement();
   var tcMainElementOffsetWidth = tcMainElement.offsetWidth;
   popup.SetHeight(0);
   popup.SetWidth(tcMainElementOffsetWidth);
   ASPx.SetOffsetWidth(tabContainer, tcMainElementOffsetWidth);
   tab.showContainer();
   if(this.widthValueSetInPercentage)
    this.updatePercentageWidth();
   popup.ShowAtElement(tcMainElement);
   var tabChanged = this.activeTab !== tab;
   this.activeTab = tab;
   this.popupActiveTab = tab; 
   this.raiseEvent("MinimizationStateChanged", new ASPxClientRibbonMinimizationStateEventArgs(ASPxClientRibbonState.TemporaryShown));
   if(tabChanged)
    this.onActiveTabChanged(true);
  },
  hideTabMinimizePopup: function() {
   this.restoreTabContainerContent();
   if(this.getTabMinimizePopup().IsVisible() || (this.activeTab && this.activeTab.getTabContentElement().parentNode != this.getTabsContainer()))
    this.hideTabMinimizePopupCore();
  },
  hideTabMinimizePopupCore: function () {
   this.changeVisiblePinMinButtons(true);
   this.getTabMinimizePopup().Hide();
   this.activeTab.hideContainer();
   if(this.minimized)
    this.switchInactiveTab(false);
   var tabIndex = this.currentTemporaryTabPageIndex;
   if(tabIndex > -1) {
    var tabElement = this.getTabElement(tabIndex);
    if(tabElement.hoverItem) {
     tabElement.hoverItem.Cancel(tabElement);
     tabElement.hoverItem = null;
    } else {
     ASPx.RemoveClassNameFromElement(tabElement, constants.CLASSNAMES.TAB_HOVER);
    }
    this.currentTemporaryTabPageIndex = -1;
    setTimeout(function() {
     if(this.lastShownTemporaryTabPageIndex == tabIndex)
      this.lastShownTemporaryTabPageIndex = -1;
    }.aspxBind(this), 100);
   }
   this.raiseEvent("MinimizationStateChanged", new ASPxClientRibbonMinimizationStateEventArgs(ASPxClientRibbonState.Minimized));
  },
  getFirstAllowableIndex: function() {
   for(var i = 0; i < this.GetTabCount(); i++) {
    var tab = this.tabs[i];
    if(tab.GetVisible() && tab.GetEnabled())
     return i;
   }
   return 0;
  },
  changeActiveTabToFirstAllowable: function() {
   var index = this.getFirstAllowableIndex();
   if(this.minimized) {
    this.hideTabMinimizePopup();
    this.setActiveTabContainer(index, true);
   }
   else
    this.SetActiveTabIndex(index);
  },
  setActiveTabContainer: function(index, raiseEvent) {
   if(index >= this.GetTabCount()) {
    this.setActiveTabContainer(this.GetTabCount() - 1, raiseEvent);
    index = this.GetTabCount() - 1;
   }
   if(index < 0)
    index = 0;
   var tab = this.tabs[index];
   if(tab.isContext && !tab.visible) {
    index = 0;
    tab = this.tabs[index];
   }
   if(!this.minimized) {
    if(this.activeTab)
     this.activeTab.hideContainer();
    if(!this.minimized)
     tab.showContainer();
   }
   this.activeTab = tab;
   this.activeTabIndex = index;
   this.updateClientStateField("ActiveTabIndex", this.activeTabIndex);
   window.setTimeout(function() { ASPx.GetControlCollection().AdjustControlsCore(tab.getWrapperElement(), true); }, 0);   
   this.onActiveTabChanged(raiseEvent);
  },
  showGroupCollapsePopup: function(group) {
   this.adjustLocked = true;
   if(this.currentGroupInPopup) {
    if(this.currentGroupInPopup != group)
     this.hideGroupCollapsePopup();
    else {
     this.adjustLocked = false;
     return;
    }
   }
   var pc = this.getGroupCollapsePopup();
   var cc = pc.GetContentContainer(-1);
   if(cc.childNodes.length > 0)
    pc.SetContentHtml("");
   if(this.oneLineMode) {
    var groupSubElements = group.getOneLineModeSubElements(true);
    this.activeTab.rollbackOneLineModeGroupModifications(group);
    for(var se, i = 0; se = groupSubElements[i]; i++) {
     se.parent = se.parentNode;
     cc.appendChild(se);
    }
   }
   else {
    var groupSubElements = group.getSubElements();
    for(var se, i = 0; se = groupSubElements[i]; i++) {
     se.parent = se.parentNode;
     cc.appendChild(se);
     se.style.width = (group.initWidth + 1) + "px";
    }
    this.activeTab.rollbackGroupModifications(group);
   }
   setTimeout(function() {
    pc.maxWidth = window.innerWidth;
    pc.SetHeight(0);
    pc.SetWidth(0);
    pc.ShowAtElement(group.getExpandButtonElement());
   }.aspxBind(this), 0);
   this.currentGroupInPopup = group;
   this.adjustLocked = false;
  },
  hideGroupCollapsePopup: function(skipHide, lockAdjust) {
   lockAdjust = lockAdjust === undefined ? true : lockAdjust;
   if(lockAdjust)
    this.adjustLocked = true;
   var pc = this.getGroupCollapsePopup();
   if(!pc) 
    return;
   if(this.enabled && !skipHide)
    pc.Hide();
   if(!this.currentGroupInPopup) {
    if(lockAdjust)
     this.adjustLocked = false;
    return;
   }
   var element = this.currentGroupInPopup.getExpandButtonElement();
   if(element.hoverItem) {
    element.hoverItem.Cancel(element);
    element.hoverItem = null;
   }
   if(this.oneLineMode)
    this.activeTab.restoreOneLineModeGroupModifications();
   else
    this.activeTab.restoreGroupModifications();
   var groupSubElements = this.oneLineMode ? this.currentGroupInPopup.getOneLineModeSubElements() : this.currentGroupInPopup.getSubElements();
   for(var i = 0, se; se = groupSubElements[i]; i++) {
    se.style.width = "";
    var isBlock = ASPx.ElementContainsCssClass(se, constants.CLASSNAMES.BLOCK);
    if(this.oneLineMode && isBlock)
     se.parent.insertBefore(se, this.currentGroupInPopup.getExpandButtonElement());
    else
     se.parent.appendChild(se);
   }
   if(lockAdjust)
    this.adjustLocked = false;
   this.currentGroupInPopup = undefined;
  },
  switchInactiveTab: function(activate) {
   var activeTabIndex = this.activeTab ? this.activeTab.index : -1;
   this.setActiveTabControlTab(activate ? activeTabIndex : -1);
  },
  getTabControl: function() {
   if(!this.tabControl)
    this.tabControl = ASPx.GetControlCollection().Get(this.name + constants.TABCONTROL_POSTFIX);
   return this.tabControl;
  },
  getGroupCollapsePopup: function() {
   return ASPx.GetControlCollection().Get(this.name + constants.GROUPCOLLAPSEPOPUP_POSTFIX);
  },
  getTabMinimizePopup: function() {
   return ASPx.GetControlCollection().Get(this.name + constants.TABMINIMIZEPOPUP_POSTFIX);
  },
  getTabsContainer: function() {
   return document.getElementById(this.name + constants.TABSCONTAINER_POSTFIX);
  },
  getKeyTipsContainer: function () {
   return document.getElementById(this.name + constants.KEYTIPSCONTAINER_POSTFIX);
  },
  getTabElement: function(index, active) {
   return this.getTabControl().GetTabElement(this.getTabControlTabIndex(index), active);
  },
  getMinimizeButton: function() {
   return document.getElementById(this.name + constants.TABCONTROL_POSTFIX + constants.MINIMIZEBUTTON_POSTFIX);
  },
  getMinimizeButtonImage: function () {
   return document.getElementById(this.name + constants.TABCONTROL_POSTFIX + constants.MINIMIZEBUTTONIMAGE_POSTFIX);
  },
  getPinButtonImage: function () {
   return document.getElementById(this.name + constants.TABCONTROL_POSTFIX + constants.PINBUTTONIMAGE_POSTFIX);
  },
  onBarItemExecCommand: function(item, parameter) {
   this.onExecCommand(item, parameter);
  },
  updateBarItemClientState: function(key, value) {
   this.updateClientStateField(key, value);
  },
  clearBarItemClientState: function(key) {
   this.clearClientStateField(key);
  },
  getBarItemTabControlTab: function(tabIndex) {
   return this.getTabControlTab(tabIndex);
  },
  forEachBarItem: function(func) {
   for(var i = 0, tab; tab = this.tabs[i]; i++) {
    for(var j = 0, group; group = tab.groups[j]; j++) {
     for(var k = 0, item; item = group.items[k]; k++)
      func(item);
    }
   }
  },
  getBarItemPopupHelper: function() {
   return this.getPopupMenuHelper();
  },
  isBarItemsTabVisible: function(tab) {
   return this.showTabs;
  },
  getControlEnabled: function(client) {
   return client ? this.clientEnabled : this.enabled;
  },
  getBarItemsKeyboardSupport: function() {
   return this.keyboardSupport;
  },
  getBarItemsIDPrefix: function() {
   return this.name;
  },
  updateClientStateField: function(key, value) {
   this.stateObject[key] = value;
   this.updateCookie();
  },
  clearClientStateField: function(key) {
   delete this.stateObject[key];
   this.updateCookie();
  },
  updateCookie: function() {
   if(this.cookieName && this.cookieName != "") {
    ASPx.Cookie.DelCookie(this.cookieName);
    ASPx.Cookie.SetCookie(this.cookieName, ASPx.Json.ToJson(this.stateObject));
   }
  },
  getTabControlTab: function(index) {
   if(!this.getTabControl()) return;
   var tcTabIndex = this.getTabControlTabIndex(index);
   return this.getTabControl().GetTab(tcTabIndex);
  },
  setActiveTabControlTab: function(index) {
   if(this.showTabs) {
    if(this.minimized && index > -1) {
     var tc = this.getTabControl();
     if(this.currentTemporaryTabPageIndex == index) {
      this.hideTabMinimizePopup();
      tc.scrollToActiveTab = false;
      tc.SetActiveTab(tc.GetTabByName(constants.INACTIVETAB_NAME));
     }
     else {
      this.showTabMinimizePopup(index);
      tc.scrollToActiveTab = true;
      tc.SetActiveTabIndex(this.getTabControlTabIndex(index));
     }
    }
    else {
     var tc = this.getTabControl();
     if(index === -1) {
      tc.scrollToActiveTab = false;
      tc.SetActiveTab(tc.GetTabByName(constants.INACTIVETAB_NAME));
     }
     else {
      tc.scrollToActiveTab = true;
      tc.SetActiveTabIndex(this.getTabControlTabIndex(index));
     } 
    }
   }
   else if(index >= 0)
    this.setActiveTabContainer(index, index != this.activeTab.index);
  },
  getActiveTabControlTab: function() {
   return this.getTabControl().GetActiveTab();
  },
  getTabControlTabIndex: function(rTabIndex) {
   return this.showFileTab ? (rTabIndex + 1) : rTabIndex;
  },
  getRibbonTabIndex: function(tcTabIndex) {
   return this.showFileTab ? (tcTabIndex - 1) : tcTabIndex;
  }
 });
 ASPxClientRibbon.Cast = ASPxClientControl.Cast;
 ASPxClientRibbon.onTabChanged = function(s, e) {
  var ribbon = getRibbonControl(s.name, constants.TABCONTROL_POSTFIX);
  if(!ribbon) return;
  return ribbon.onTabChanged(e.tab, e.byAccessKey);
 };
 ASPxClientRibbon.getRibbonControl = function(s, itemID) {
  return getRibbonControl(s.name, constants.POPUP_MENU_POSTFIX) || getRibbonControlByItem(s.name, constants.POPUP_MENU_POSTFIX, itemID);
 };
 ASPxClientRibbon.onTabClick = function(s, e) {
  return getRibbonControl(s.name, constants.TABCONTROL_POSTFIX).onTabClick(e.tab.index, e);
 };
 ASPxClientRibbon.onPopupGalleryPopUp = function(s, e) {
  var itemID = s.cpRibbonItemID;
  return getRibbonControlByItem(s.name, constants.POPUP_GALLERY_POSTFIX, itemID).onGalleryPopupPopUp(itemID, s);
 };
 ASPxClientRibbon.onPopupGalleryCloseUp = function(s, e) {
  var itemID = s.cpRibbonItemID;
  return getRibbonControlByItem(s.name, constants.POPUP_GALLERY_POSTFIX, itemID).onGalleryPopupCloseUp(itemID, s);
 };
 ASPxClientRibbon.onPopupGalleryResize = function(s, e) {
  var itemID = s.cpRibbonItemID;
  return getRibbonControlByItem(s.name, constants.POPUP_GALLERY_POSTFIX, itemID).onGalleryPopupResize(itemID, s);
 };
 function getCollapsedGroupWidth(group) {
  var groupElement = group.getElement();
  groupElement.className = groupElement.className.replace(constants.CLASSNAMES.GROUP, constants.CLASSNAMES.GROUP_COLLAPSED);
  var expandButton = group.getExpandButtonElement();
  if(!expandButton.style.width && !group.ribbon.oneLineMode) {
   var popout = group.getExpandButtonPopOutElement();
   var itemWidth = getLargeItemWidth(group.getExpandButtonLabelTextElement(), ASPx.GetLeftRightMargins(group.getExpandButtonLabelContentElement()), popout.offsetWidth + ASPx.GetLeftRightMargins(popout));
   expandButton.style.width = itemWidth + "px";
  }
  var width = groupElement.offsetWidth;
  groupElement.className = groupElement.className.replace(constants.CLASSNAMES.GROUP_COLLAPSED, constants.CLASSNAMES.GROUP);
  return width;
 }
 function getGroupExpandButtonWidth(group) {
  if(!group.ribbon.oneLineMode)
   return 0;
  var groupElement = group.getElement();
  var width = groupElement.offsetWidth;
  var expandButton = group.getExpandButtonElement();
  expandButton.className = expandButton.className.replace(constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND, constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND_VISIBLE);
  var deltaWidth = groupElement.offsetWidth - width;
  expandButton.className = expandButton.className.replace(constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND_VISIBLE, constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND);
  return deltaWidth;
 }
 function findNextModification(groupInfos) {
  var currentDelta,
   delta = Number.MAX_VALUE,
   priority = -1,
   indexPath = [-1, -1];
  for(var i = 0, groupInfo; groupInfo = groupInfos[i]; i++) {
   if(groupInfo.width < 0) continue;
   for(var j = 0, blockInfo; blockInfo = groupInfo.blockInfos[j]; j++) {
    if((blockInfo.activeMod + 1) >= blockInfo.mods.length) continue;
    var blockMod = blockInfo.mods[blockInfo.activeMod + 1];
    currentDelta = blockMod.width;
    if(blockMod.priority < priority) 
     continue;
    if(blockMod.priority > priority || currentDelta <= delta) {
     delta = currentDelta;
     indexPath = [i, j];
     priority = blockMod.priority;
    }
   }
  }
  if(indexPath[0] == -1) {
   for(var i = 0, groupInfo; groupInfo = groupInfos[i]; i++) {
    if(groupInfo.collapseWidth == -1 && groupInfo.width)
     continue;
    currentDelta = groupInfo.width - groupInfo.collapseWidth;
    if(currentDelta > 0 && currentDelta < delta) {
     delta = currentDelta;
     indexPath = [i, -1];
    }
   }
  }
  return { delta: delta, indexPath: indexPath };
 }
 function getRibbonControl(controlName, controlPostfix) {
  var ribbonID = controlName.substr(0, controlName.length - controlPostfix.length);
  return ASPx.GetControlCollection().Get(ribbonID);
 }
 function getRibbonControlByItem(controlName, controlPostfix, itemID) {
  return getRibbonControl(controlName, "_" + itemID + controlPostfix);
 }
 var Modification = function(delta, element, newClassName, prevClassName, group, isBlock) {
  this.delta = delta;
  this.element = element;
  this.newClassName = newClassName;
  this.prevClassName = prevClassName;
  this.group = group;
  this.isBlock = isBlock;
 };
 var ASPxClientRibbonCommandExecutedEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
  constructor: function(item, parameter, processOnServer) {
   this.constructor.prototype.constructor.call(this, processOnServer);
   this.item = item;
   this.parameter = parameter;
  }
 });
 var ASPxClientRibbonTabEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(tab) {
   this.constructor.prototype.constructor.call(this);
   this.tab = tab;
  }
 });
 var ASPxClientRibbonMinimizationStateEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function(ribbonState) {
   this.constructor.prototype.constructor.call(this);
   this.ribbonState = ribbonState;
  }
 });
 var ASPxClientRibbonDialogBoxLauncherClickedEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
  constructor: function(group, processOnServer) {
   this.constructor.prototype.constructor.call(this, processOnServer);
   this.group = group;
  }
 });
 var ASPxClientRibbonState = {
  Normal: 0,
  Minimized: 1,
  TemporaryShown: 2
 };
 var ASPxClientRibbonGroupEx = ASPx.CreateClass(ASPxClientRibbonGroup, {
  constructor: function(ribbon, tab, index, groupInfo) {
   this.constructor.prototype.constructor.call(this, ribbon, tab, index, groupInfo);
   this.dialogBoxLauncherAccessKey = groupInfo.dak || "";
   this.initWidth = 0;
  },
  initialize: function() {
   ASPxClientRibbonGroup.prototype.initialize.call(this);
   if(!this.getElement())
    return;
   this.initializeExpandButton();
   var dialogBoxLauncher = this.getDialogBoxLauncherElement();
   if(dialogBoxLauncher) {
    var _this = this;
    ASPx.Evt.AttachEventToElement(dialogBoxLauncher, "click", function() {
     var processOnServer = _this.ribbon.IsServerEventAssigned("DialogBoxLauncherClicked");
     var args = new ASPxClientRibbonDialogBoxLauncherClickedEventArgs(_this, processOnServer);
     _this.ribbon.raiseEvent("DialogBoxLauncherClicked", args);
     if(args.processOnServer)
      _this.ribbon.SendPostBack("DIALOGBOXLAUNCHERCLICKED" + ASPx.CallbackSeparator + _this.getIndexPath());
    });
   }
  },
  initializeExpandButton: function() {
   var expandButton = this.getExpandButtonElement();
   if(expandButton)
    ASPx.Evt.AttachEventToElement(expandButton, "mousedown", this.onExpandButtonClick.aspxBind(this));
  },
  onExpandButtonClick: function() {
   if(this.ribbon.GetEnabled()) {
    if(this.ribbon.currentGroupInPopup == this) {
     setTimeout(function() {
      this.ribbon.hideGroupCollapsePopup();
     }.aspxBind(this), 0);
    }
    else {
     setTimeout(function() {
      this.ribbon.showGroupCollapsePopup(this);
     }.aspxBind(this), 0);
    }
   }
  },
  getBlocksInfos: function(groupIndex) {
   var blockMods = [];
   var groupElement = this.getElement();
   var blocks = ASPx.GetNodesByClassName(groupElement, constants.CLASSNAMES.BLOCK);
   for(var block, i = 0; block = blocks[i]; i++) {
    if(!block.originalClassName)
     block.originalClassName = block.className;
    var info = this.getBlockInfo(block, groupElement, groupIndex * 100 + i + 1);
    blockMods.push(info);
   }
   this.initWidth = groupElement.offsetWidth;
   return blockMods;
  },
  getBlockInfo: function(block, groupElement, index) {
   var canReduceHorizontalBlock = function(items) {
    var itemsWidth = [];
    for(var i = 0, item; item = items[i]; i++) {
     var element = item.getElement();
     if(ASPx.GetNodesByClassName(element, constants.CLASSNAMES.IMAGE16).length == 0)
      return false;
     itemsWidth.push(element.offsetWidth);
    }
    ASPx.AddClassNameToElement(groupElement, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED);
    for(var i = 0, item; item = items[i]; i++) {
     if(item.getElement().offsetWidth == itemsWidth[i]) {
      ASPx.RemoveClassNameFromElement(groupElement, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED);
      return false;
     }
    }
    ASPx.RemoveClassNameFromElement(groupElement, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED);
    return true;
   };
   var canReduceLargeBlock = function(items) {
    for(var i = 0, item; item = items[i]; i++) {
     var element = item.getElement();
     if(ASPx.GetNodesByClassName(element, constants.CLASSNAMES.LABELTEXT).length == 0 &&
      ASPx.GetNodesByClassName(element, constants.CLASSNAMES.IMAGE16).length == 0)
      return false;
    }
    return true;
   };
   if(!groupElement)
    groupElement = this.getElement();
   var info = { block: block, activeMod: 0, mods: [], group: this };
   var initWidth = 0;
   var items = this.getBlockItems(block);
   if(ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS)) {
    initWidth = groupElement.offsetWidth;
    info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS, 0, -1));
    if(canReduceHorizontalBlock(items))
     info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED, -1, 0));
    if(this.ribbon.oneLineMode) {
     var priotiry = -1 + (index / 10000);
     for(var i = 0, item; item = items[i]; i++) {
      info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_HIDE, -1, priotiry));
     }
    }
   }
   else if(ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_LARGE_ITEMS)) {
    initWidth = groupElement.offsetWidth;
    info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_LARGE_ITEMS, 0, -1));
    if(canReduceLargeBlock(items)) {
     if(ASPx.GetNodesByClassName(block, constants.CLASSNAMES.BUTTONITEM).length > 1) {
      info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS, -1, 1));
      ASPx.RemoveClassNameFromElement(block, constants.CLASSNAMES.BLOCK_LARGE_ITEMS);
      ASPx.AddClassNameToElement(block, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS);
      if(canReduceHorizontalBlock(items))
       info.mods.push(new BlockMod(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED, -1, 0));
      ASPx.RemoveClassNameFromElement(block, constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS);
      ASPx.AddClassNameToElement(block, constants.CLASSNAMES.BLOCK_LARGE_ITEMS);
     }
    }
   }
   else if(ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_REGULAR_ITEMS)) {
    var ranges = this.getRegularBlockSizeRanges(block);
    var classNames = [constants.CLASSNAMES.BLOCK_REGULAR_ITEMS, constants.CLASSNAMES.BLOCK_REGULAR_ITEMS_REDUCED];
    for(var j = 0, range; range = ranges[j]; j++) {
     var classPostfix = ASPx.CreateImportantStyleRule(null, "width: " + ranges[j].width + "px;");
     var className = classNames[j] + " " + classPostfix;
     for(var k = 0; k < range.endNodes.length - 1; k++) {
      var rowEndNode = range.endNodes[k];
      var clearNode = document.createElement("b");
      clearNode.className = "dx-clear dxr-regClear-" + j;
      ASPx.InsertElementAfter(clearNode, rowEndNode);
     }
     if(j == 0) {
      block.className = block.className.replace(classNames[j], className);
      initWidth = groupElement.offsetWidth;
      info.mods.push(new BlockMod(className, 0, 2));
     }
     else
      info.mods.push(new BlockMod(className, -1, 2));
    }
   } else if(ASPx.ElementHasCssClass(block, constants.CLASSNAMES.BLOCK_SEPARATE_ITEMS)) {
    var gallery = items[0];
    if(gallery) {
     gallery.setBaseWidth();
     block.originClassName = block.className;
     var elementWidth = gallery.maxElementFullWidth;
     var blockWidth = block.offsetWidth;
     var baseClassName = constants.CLASSNAMES.BLOCK_SEPARATE_ITEMS;
     initWidth = groupElement.offsetWidth;
     var classPostfix = ASPx.CreateImportantStyleRule(null, "width: " + blockWidth + "px;");
     ASPx.AddClassNameToElement(block, classPostfix);
     info.mods.push(new BlockMod(baseClassName + " " + classPostfix, 0, 3));
     gallery.setBaseWidth(true);
     var colMax = gallery.getColMax();
     for(var j = 1; colMax - j >= gallery.colMin; j++) {
      var priority = 3;
      if((colMax - gallery.colMin) / 2 < j)
       priority = 2;
      var width = blockWidth - (elementWidth * j);
      classPostfix = ASPx.CreateImportantStyleRule(null, "width: " + width + "px;");
      var className = baseClassName + " " + classPostfix;
      info.mods.push(new BlockMod(className, -1, priority));
     }
    }
   }
   if(info.mods.length > 1) { 
    var calculateMod = function(currentMod, newMod) {
     block.className = block.className.replace(currentMod.className, newMod.className);
     if(newMod.width < 0) {
      newMod.width = initWidth - groupElement.offsetWidth;
      initWidth -= newMod.width;
     }
    };
    for(var j = 1, mod; mod = info.mods[j]; j++)
     calculateMod(info.mods[j - 1], mod);
    calculateMod(info.mods[info.mods.length - 1], info.mods[0]);
    for(var j = 1, mod; mod = info.mods[j]; j++) {
     if(mod.width < 0) {
      info.mods.splice(j, 1);
      var nextMod = info.mods[j + 1];
      if(nextMod)
       nextMod += mod.width;
      j--;
     }
    }
   }
   return info;
  },
  getRegularBlockSizeRanges: function(block) {
   var items = this.getBlockItems(block);
   var itemSizeInfos = [];
   var commonWidth = 0;
   var getRightBoundInfo = function(el) {
    var sibling,
     node = el,
     width = 0;
    while(el.nextSibling) {
     sibling = el.nextSibling;
     if(sibling.className && ASPx.ElementHasCssClass(sibling, constants.CLASSNAMES.ITEM))
      break;
     if(sibling.nodeType == 1) {
      var style = ASPx.GetCurrentStyle(sibling);
      width += sibling.offsetWidth + ASPx.PxToInt(style.marginLeft) + ASPx.PxToInt(style.marginRight);
      node = sibling;
     }
     el = sibling;
    }
    return { width: width, node: node };
   };
   for(var item, i = 0; item = items[i]; i++) {
    var element = item.getElement();
    var style = ASPx.GetCurrentStyle(element);
    var width = element.offsetWidth + ASPx.PxToInt(style.marginLeft) + ASPx.PxToInt(style.marginRight);
    var rightBoundInfo = getRightBoundInfo(element);
    width += rightBoundInfo.width;
    if(i > 0 && item.groupName && item.groupName == items[i - 1].groupName) {
     itemSizeInfos[itemSizeInfos.length - 1].width += width;
     itemSizeInfos[itemSizeInfos.length - 1].node = rightBoundInfo.node;
    }
    else
     itemSizeInfos.push({ width: width, node: rightBoundInfo.node });
    commonWidth += width;
   }
   if(this.ribbon.oneLineMode)
    return [
     this.calculateRegularItemsBlock(1, itemSizeInfos, commonWidth)
    ];
   else
    return [
     this.calculateRegularItemsBlock(2, itemSizeInfos, commonWidth),
     this.calculateRegularItemsBlock(3, itemSizeInfos, commonWidth)
    ];
  },
  getBlockItems: function(block) {
   var items = [];
   for(var item, i = 0; item = this.items[i]; i++) {
    if(!item.GetVisible())
     continue;
    if(item.getElement().parentNode == block)
     items.push(item);
    else if(items.length > 0)
     break;
   }
   return items;
  },
  calculateRegularItemsBlock: function(rowsAmount, itemInfos, commonWidth) {
   var maxRowIndex = 0,
    rowsInfo = [],
    results = { endNodes: [itemInfos[itemInfos.length - 1].node], width: (commonWidth + 2) },
    width = commonWidth,
    offsetWidth = 2;
   if(itemInfos.length < 2)
    return results;
   for(var i = 0; i < rowsAmount; i++)
    rowsInfo.push({ width: 0, items: [] });
   rowsInfo[0].width = commonWidth;
   for(var i = 0; i < itemInfos.length; i++)
    rowsInfo[0].items.push(itemInfos[i]);
   var getLongestRowIndex = function() {
    var res = 0;
    for(var i = 0; i < rowsAmount; i++) {
     if(rowsInfo[i].width > rowsInfo[res].width)
      res = i;
    }
    return res;
   };
   var moveItem = function(index) {
    var item = rowsInfo[index].items.pop();
    rowsInfo[index].width -= item.width;
    rowsInfo[index + 1].items.unshift(item);
    rowsInfo[index + 1].width += item.width;
   };
   var updateResults = function(width) {
    results.width = width + offsetWidth;
    results.endNodes = [];
    for(var i = 0; i < rowsAmount; i++) {
     var ri = rowsInfo[i];
     if(ri.items.length === 0) return;
     results.endNodes.push(ri.items[ri.items.length - 1].node);
    }
   };
   while(true) {
    maxRowIndex = getLongestRowIndex();
    width = rowsInfo[maxRowIndex].width;
    if(width != results.width - offsetWidth)
     updateResults(width);
    if(maxRowIndex == rowsAmount - 1) break;
    moveItem(maxRowIndex);
    for(var i = maxRowIndex + 1; i < rowsAmount; i++) {
     if(rowsInfo[i].width > width) {
      if(i == rowsAmount - 1)
       return results;
      moveItem(i);
     }
     else
      break;
    }
   }
   return results;
  },
  getOneLineModeSubElements: function(reGet) {
   if(reGet) {
    var element = this.getElement();
    this.subElements = ASPx.GetNodesByClassName(element, constants.CLASSNAMES.BlOCK_HIDE);
    var groupLabel = ASPx.GetNodeByClassName(element, constants.CLASSNAMES.GROUP_LABEL);
    if(!!groupLabel) {
     this.subElements.push(ASPx.GetPreviousSibling(groupLabel));
     this.subElements.push(groupLabel);
    }
   }
   return this.subElements;
  },
  getExpandButtonElement: function() {
   if(!this.getElement())
    return null;
   if(this.expandButtonElement === undefined)
    this.expandButtonElement = this.ribbon.oneLineMode ? ASPx.GetNodeByClassName(this.getElement(), constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND)
     : ASPx.GetNodeByClassName(this.getElement(), constants.CLASSNAMES.GROUP_EXPAND);
   return this.expandButtonElement;
  },
  getExpandButtonLabelTextElement: function() {
   if(this.expandButtonLabelTextElement === undefined)
    this.expandButtonLabelTextElement = ASPx.GetNodeByClassName(this.getExpandButtonElement(), constants.CLASSNAMES.LABELTEXT);
   return this.expandButtonLabelTextElement;
  },
  getExpandButtonLabelContentElement: function() {
   if(this.expandButtonLabelContentElement === undefined)
    this.expandButtonLabelContentElement = ASPx.GetNodeByClassName(this.getExpandButtonElement(), constants.CLASSNAMES.LABELCONTENT);
   return this.expandButtonLabelContentElement;
  },
  getExpandButtonPopOutElement: function() {
   if(this.expandButtonPopOutElement === undefined)
    this.expandButtonPopOutElement = ASPx.GetNodeByClassName(this.getExpandButtonElement(), constants.CLASSNAMES.ITEMPOPOUT);
   return this.expandButtonPopOutElement;
  },
  getDialogBoxLauncherElement: function() {
   var element = this.getElement();
   if(!element)
    return null;
   return document.getElementById(element.id + constants.GROUPDIALOGBOXLAUNCHER_POSTFIX);
  }
 });
 var ASPxClientRibbonTabEx = ASPx.CreateClass(ASPxClientRibbonTab, {
  constructor: function(ribbon, index, tabInfo) {
   this.constructor.prototype.constructor.call(this, ribbon, index, tabInfo);
   this.modifications = [];
   this.activeModificationIndex = -1;
   this.listWidth = -1;
   this.width = -1;
   this.height = -1;
   this.initializeHandlers();
   this.initializeSpacers();
  },
  initializeCore: function(forced) {
   var tabContentElement = this.getTabContentElement();
   var parent = tabContentElement.parentNode;
   if(tabContentElement.offsetWidth == 0 && forced) {
    ASPx.Attr.ChangeStyleAttribute(tabContentElement, "position", "absolute");
    ASPx.Attr.ChangeStyleAttribute(tabContentElement, "top", "-10000px");
    ASPx.Attr.ChangeStyleAttribute(tabContentElement, "left", "-10000px");
    ASPx.Attr.ChangeStyleAttribute(tabContentElement, "display", "block");
    this.ribbon.GetMainElement().appendChild(tabContentElement);
   }
   if(tabContentElement.offsetWidth > 0) {
    ASPxClientRibbonTab.prototype.initializeCore.call(this, forced);
    this.calculateModifications();
    this.applyModification();
    this.height = this.getListElement().offsetHeight;
    this.listWidth = this.getListElement().offsetWidth;
   }
   if(tabContentElement.parentNode != parent) {
    ASPx.Attr.RestoreStyleAttribute(tabContentElement, "display");
    ASPx.Attr.RestoreStyleAttribute(tabContentElement, "position");
    ASPx.Attr.RestoreStyleAttribute(tabContentElement, "top");
    ASPx.Attr.RestoreStyleAttribute(tabContentElement, "left");
    parent.appendChild(tabContentElement);
    tabContentElement.style.display = "";
   }
  },
  initializeHandlers: function() {
   if(this.ribbon.showTabs) {
    var tabControl = this.ribbon.getTabControl();
    var tcTab = this.getTabControlTab();
    if(this.ribbon.enabled && (this.isContext || this.GetVisible())) {
     if(ASPx.Browser.WebKitTouchUI) {
      ASPx.TouchUIHelper.AttachDoubleTapEventToElement(tabControl.GetTabElement(tcTab.index, true), this.onTabElementDblClick.aspxBind(this));
      ASPx.TouchUIHelper.AttachDoubleTapEventToElement(tabControl.GetTabElement(tcTab.index, false), this.onTabElementDblClick.aspxBind(this));
     }
     else {
      ASPx.Evt.AttachEventToElement(tabControl.GetTabElement(tcTab.index, true), 'dblclick', this.onTabElementDblClick.aspxBind(this));
      ASPx.Evt.AttachEventToElement(tabControl.GetTabElement(tcTab.index, false), 'dblclick', this.onTabElementDblClick.aspxBind(this));
     }
     ASPx.Evt.AttachEventToElement(tabControl.GetTabElement(tcTab.index, true), 'mousedown', this.onTabElementMouseDown.aspxBind(this));
     ASPx.Evt.AttachEventToElement(tabControl.GetTabElement(tcTab.index, false), 'mousedown', this.onTabElementMouseDown.aspxBind(this));
    }
   }
  },
  initializeSpacers: function() {
   if(this.isContext && this.ribbon.showTabs) {
    var tabElement = this.ribbon.getTabElement(this.index, this.ribbon.enabled);
    if(tabElement) {
     var spacer = tabElement.nextSibling;
     if(spacer && ASPx.ElementContainsCssClass(spacer, "dxtc-spacer"))
      spacer.style.width = "0px";
    }
   }
  },
  setVisible: function(visible) {
   if(this.visible == visible)
    return;
   ASPxClientRibbonTab.prototype.setVisible.call(this, visible);
   if(!visible && this.ribbon.activeTab.index == this.index)
    this.ribbon.changeActiveTabToFirstAllowable();
   this.getTabControlTab().SetVisible(visible);
   this.ribbon.updateClientStateField("T" + this.index, visible);
   this.visible = visible;
  },
  accessKeyClick: function() {
   ASPxClientRibbonTab.prototype.accessKeyClick.call(this);
   this.ribbon.hideAllPopups();
   var tabControl = this.ribbon.getTabControl(),
    tabControlAccessibility = tabControl.accessibilityCompliant;
   if(tabControlAccessibility)
    tabControl.accessibilityCompliant = false; 
   this.ribbon.SetActiveTab(this);
   if(tabControlAccessibility)
    tabControl.accessibilityCompliant = true;
  },
  showContainer: function() {
   this.getTabContentElement().style.display = "block";
   this.initialize();
   setTimeout(function() {
    this.ribbon.AdjustControl();
   }.aspxBind(this), 0);
  },
  hideContainer: function() {
   this.getTabContentElement().style.display = "";
  },
  onTabElementDblClick: function() {
   this.ribbon.onTabElementDblClick(this);
  },
  onTabElementMouseDown: function() {
   this.ribbon.onTabElementMouseDown(this);
  },
  deleteModifications: function() {
   ASPxClientRibbonTab.prototype.deleteModifications.call(this);
   for(var i = 0, group; group = this.groups[i]; i++) {
    if(!group.GetVisible())
     continue;
    group.getElement().className = constants.CLASSNAMES.GROUP;
    var blocks = ASPx.GetNodesByClassName(group.getElement(), constants.CLASSNAMES.BLOCK);
    for(var j = 0, block; block = blocks[j]; j++)
     if(block.originalClassName)
      block.className = block.originalClassName;
    for(var j = 0, item; item = group.items[j]; j++)
     if(item.setBaseWidth)
      item.setBaseWidth();
   }
   this.modifications = [];
  },
  recalculateModifications: function() {
   ASPxClientRibbonTab.prototype.recalculateModifications.call(this);
   this.calculateModifications();
   this.activeModificationIndex = -1;
   if(!this.ribbon.minimized)
    this.listWidth = -1;
   this.applyModification();
  },
  calculateModifications: function() {
   var groupInfos = [],
    blockInfos;
   for(var i = 0, group; group = this.groups[i]; i++) {
    if(!group.GetVisible())
     continue;
    blockInfos = group.getBlocksInfos(i);
    groupInfos.push({
     group: group,
     width: group.getElement().offsetWidth,
     collapseWidth: getCollapsedGroupWidth(group),
     blockInfos: blockInfos,
     expandButtonWidth: getGroupExpandButtonWidth(group)
    });
   }
   while(true) {
    var mod = findNextModification(groupInfos);
    if(mod.indexPath[0] == -1) break;
    var groupInfo = groupInfos[mod.indexPath[0]];
    if(this.ribbon.oneLineMode)
     this.pushOneLineModification(mod, groupInfo);
    else
     this.pushModification(mod, groupInfo);
   }
   for(var i = 0, groupInfoItem; groupInfoItem = groupInfos[i]; i++) {
    for(var j = 0, blockInfo; blockInfo = groupInfoItem.blockInfos[j]; j++)
     blockInfo.activeMod = 0;
   }
  },
  pushModification: function(mod, groupInfo) {
   if(mod.indexPath[1] > -1) {
    var blockInfo = groupInfo.blockInfos[mod.indexPath[1]];
    var newClassName = blockInfo.mods[blockInfo.activeMod + 1].className;
    var prevClassName = blockInfo.mods[blockInfo.activeMod].className;
    this.modifications.push(new Modification(mod.delta, blockInfo.block, newClassName, prevClassName, groupInfo.group, true));
    blockInfo.activeMod++;
    groupInfo.width -= blockInfo.mods[blockInfo.activeMod].width;
   }
   else {
    this.modifications.push(new Modification(mod.delta, groupInfo.group.getElement(), constants.CLASSNAMES.GROUP_COLLAPSED, constants.CLASSNAMES.GROUP, groupInfo.group, false));
    groupInfo.width = -1;
   }
  },
  pushOneLineModification: function(mod, groupInfo) {
   if(mod.indexPath[1] > -1) {
    var blockInfo = groupInfo.blockInfos[mod.indexPath[1]];
    var newClassName = blockInfo.mods[blockInfo.activeMod + 1].className;
    var prevClassName = blockInfo.mods[blockInfo.activeMod].className;
    var needToCollapse = groupInfo.width > groupInfo.expandButtonWidth;
    var needToShowExpandBtn = needToCollapse && newClassName.indexOf(constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_HIDE) != -1 && !groupInfo.expandBtnMod;
    if(needToShowExpandBtn) {
     this.modifications.push(new Modification(-groupInfo.expandButtonWidth, groupInfo.group.getExpandButtonElement(), constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND_VISIBLE, constants.CLASSNAMES.ONE_LINE_MODE_GROUP_EXPAND, groupInfo.group, false));
     groupInfo.expandBtnMod = true;
     groupInfo.width += groupInfo.expandButtonWidth;
    }
    if(needToCollapse)
     this.modifications.push(new Modification(mod.delta, blockInfo.block, newClassName, prevClassName, groupInfo.group, true));
    blockInfo.activeMod++;
    groupInfo.width -= blockInfo.mods[blockInfo.activeMod].width;
   }
   else {
    groupInfo.width = -1;
   }
  },
  applyModification: function() {
   if(!this.initialized)
    this.initialize();
   else if(!this.rollbackGroup) {
    var newWidth = this.ribbon.widthValueSetInPercentage ? ASPx.PxToInt(this.getTabContentElement().style.width) : this.getTabContentElement().offsetWidth;
    if(newWidth == 0)
     return;
    this.listWidth = this.getListElement().offsetWidth;
    var listWidth = this.listWidth;
    if(listWidth == 0) return;
    var deltaWidth = newWidth - listWidth;
    if(deltaWidth == 0) return;
    var modificator = deltaWidth < 0 ? 1 : -1;
    while(deltaWidth != 0) {
     var newIndex = deltaWidth < 0 ? (this.activeModificationIndex + modificator) : this.activeModificationIndex;
     var modification = this.modifications[newIndex];
     if(!modification)
      return;
     var modDelta = modification.delta;
     if(deltaWidth > 0 && deltaWidth - modDelta < 0)
      return;
     this.applyModificationCore(modification, modificator);
     if(deltaWidth < 0 && deltaWidth - modDelta > 0 && modDelta > 0)
      return;
     if(modificator > 0)
      deltaWidth += modDelta;
     else
      deltaWidth -= modDelta;
    }
   }
  },
  applyModificationCore: function(modification, modificator) {
   var modifyItemAttributes = function() {
    if(modification.newClassName == constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS) {
     forEachItemInModificationBlock(function(item) {
      if(!item.navigateUrl || !(item instanceof ASPx.ASPxClientRibbonDropDownMenuItem))
       return;
      var itemLabelTextElement = item.getLabelTextElement();
      if(modificator > 0)
       ASPx.Attr.SetAttribute(itemLabelTextElement, "href", item.navigateUrl);
      else
       ASPx.Attr.RemoveAttribute(itemLabelTextElement, "href");
     });
    }
    if(modification.newClassName == constants.CLASSNAMES.BLOCK_HORIZONTAL_ITEMS_REDUCED) {
     forEachItemInModificationBlock(function(item) {
      var itemElement = item.getElement();
      if(modificator > 0) {
       if(!ASPx.Attr.IsExistsAttribute(itemElement, "title") && item.text) {
        ASPx.Attr.SetAttribute(itemElement, "title", item.text);
        item.isTextTitleSet = true;
       }
      } else {
       if(item.isTextTitleSet) {
        ASPx.Attr.RemoveAttribute(itemElement, "title");
        item.isTextTitleSet = undefined;
       }
      }
     });
    }
   };
   var forEachItemInModificationBlock = function(func) {
    for(var item, i = 0; item = modification.group.items[i]; i++) {
     if(!item.GetVisible() || !modification.element.contains(item.getElement()))
      continue;
     func(item);
    }
   };
   var updateItems = function() {
    forEachItemInModificationBlock(function(item) {
     if(item.onAfterModification)
      item.onAfterModification();
    });
   };
   if(modificator > 0) {
    modification.element.className = modification.element.className.replace(modification.prevClassName, modification.newClassName);
   }
   else {
    modification.element.className = modification.element.className.replace(modification.newClassName, modification.prevClassName);
   }
   modifyItemAttributes();
   updateItems();
   this.activeModificationIndex = this.activeModificationIndex + modificator;
   this.listWidth = this.getListElement().offsetWidth;
  },
  rollbackOneLineModeGroupModifications: function(group) {
   var containsItem = function(modification) {
    for(var i = 0, element; element = modification.group.subElements[i]; i++)
     if(element == modification.element)
      return true;
    return false;
   };
   this.rollbackGroup = group;
   for(var mod, i = this.activeModificationIndex; mod = this.modifications[i]; i--) {
    if(mod.group == group && mod.isBlock && containsItem(mod))
     this.applyModificationCore(mod, -1);
   }
  },
  rollbackGroupModifications: function(group) {
   this.rollbackGroup = group;
   for(var mod, i = this.activeModificationIndex; mod = this.modifications[i]; i--) {
    if(mod.group == group && mod.isBlock)
     this.applyModificationCore(mod, -1);
   }
  },
  restoreOneLineModeGroupModifications: function() {
   var containsItem = function(modification) {
    for(var i = 0, element; element = modification.group.subElements[i]; i++)
     if(element == modification.element)
      return true;
    return false;
   };
   if(this.rollbackGroup) {
    var group = this.rollbackGroup;
    for(var mod, i = 0; mod = this.modifications[i]; i++) {
     var mod = this.modifications[i];
     if(mod.group == group && mod.isBlock && containsItem(mod))
      this.applyModificationCore(mod, 1);
    }
    this.rollbackGroup = null;
   }
  },
  restoreGroupModifications: function() {
   if(this.rollbackGroup) {
    var group = this.rollbackGroup;
    for(var i = 0; i <= this.activeModificationIndex; i++) {
     var mod = this.modifications[i];
     if(mod.group == group && mod.isBlock)
      this.applyModificationCore(mod, 1);
    }
    this.rollbackGroup = null;
   }
  },
 });
 var ASPxClientRibbonGalleryDropDownItem = ASPx.CreateClass(ASPx.ASPxClientRibbonDropDownMenuItem, {
  constructor: function(itemInfo, items, navigateUrl, properties) {
   this.constructor.prototype.constructor.call(this, itemInfo, navigateUrl);
   this.col = properties.col;
   this.previousCol = this.col;
   this.row = properties.row;
   this.containerHeight = 0;
   this.maxElementWidth = 0;
   this.maxElementHeight = 0;
   this.maxElementFullWidth = 0;
   this.maxElementFullHeight = 0;
   this.minPopupWidth = 0;
   this.minPopupHeight = 0;
   this.selectedValue = properties.val;
   this.selectedItem = null;
   this.allowSelectItem = properties.asi;
   this.ddColMin = properties.ddColMin;
   this.imageWidth = properties.iw;
   this.imageHeight = properties.ih;
   this.showText = properties.st;
   this.imagePosition = properties.ip;
   this.maxTextWidth = properties.tw;
   this.showGroupText = null;
   this.initialized = false;
   this.keyboardHelper = null;
   if(items !== undefined) {
    this.galleryGroups = [];
    for(var i = 0, groupInfo; groupInfo = items[i]; i++) {
     var galleryItems = [];
     groupInfo.index = i;
     for(var j = 0, itemInfo; itemInfo = groupInfo[j]; j++) {
      var galleryItem = [];
      galleryItem.group = groupInfo;
      galleryItem.index = itemInfo.indx;
      galleryItem.value = itemInfo.val;
      galleryItem.id = this.getItemID(galleryItem);
      galleryItem.element = ASPx.GetElementById(galleryItem.id);
      galleryItem.selected = false;
      galleryItems.push(galleryItem);
     }
     this.galleryGroups.push(galleryItems);
    }
   }
   if(this.ribbon.enabled)
    this.setContainerSize(1, 1);
  },
  initialize: function() {
   ASPx.ASPxClientRibbonDropDownMenuItem.prototype.initialize.call(this);
   this.setValueCore(this.selectedValue);
   if(this.ribbon.enabled) {
    this.initializeHandlers();
    if(ASPx.Browser.MSTouchUI) {
     var styleAttributeName = "touch-action";
     this.getGalleryDiv().parentNode.style[styleAttributeName] = "pan-y";
    }
    if(this.ribbon.keyboardSupport)
     this.InitializeKeyboardHelper();
   }
   var popup = this.getPopup();
   if(!!popup)
    popup.forceAdjustPositionToClientScreen = true;
  },
  initializeHandlers: function() {
   if(this.ribbon.enabled) {
    ASPx.Evt.AttachEventToElement(this.getGalleryDiv(), "click", function(evt) {
     this.onGalleryDropDownClick(evt);
    }.aspxBind(this));
   }
  },
  initializeSize: function() {
   if(!this.ribbon.enabled)
    return;
   var elements = [];
   this.eachItem(function(item) {
    elements.push(item.element);
   });
   this.initMaxElementSize(elements);
   ASPx.Data.ForEach(elements, function(element) {
    if(!element)
     return;
    this.setElementSize(element, this.maxElementWidth, this.maxElementHeight);
   }.aspxBind(this));
   if(this.getShowGroupText()) {
    var maxCount = this.getMaxItemsCountInGroup();
    this.col = this.col > maxCount ? maxCount : this.col;
   }
   if(this.ddColMin)
    this.col = !this.col || this.col < this.ddColMin ? this.ddColMin : this.col;
   this.setContainerSize(this.maxElementFullWidth * this.col, this.maxElementFullHeight * this.row);
  },
  setItems: function(items) {
   this.clearItems();
   var gallery = this.getGalleryDiv();
   this.setItemsInternal(gallery, items, true);
   for(var i = 0, groupInfo; groupInfo = items[i]; i++) {
    var galleryItems = [];
    groupInfo.index = i;
    for(var j = 0, itemInfo; itemInfo = groupInfo.items[j]; j++) {
     var galleryItem = [];
     galleryItem.group = groupInfo;
     galleryItem.index = j;
     galleryItem.value = itemInfo.value;
     galleryItem.id = this.getItemID(galleryItem);
     galleryItem.element = ASPx.GetElementById(galleryItem.id);
     galleryItem.selected = false;
     galleryItems.push(galleryItem);
    }
    this.galleryGroups.push(galleryItems);
   }
  },
  setItemsInternal: function(gallery, items, showGroups, itemIdGetter) {
   for(var i = 0, groupInfo; groupInfo = items[i]; i++) {
    if(showGroups) {
     var groupElement = document.createElement("div");
     groupElement.setAttribute("class", constants.CLASSNAMES.GALLERY_GROUP_DIV);
     groupElement.innerHTML = groupInfo.text;
     gallery.appendChild(groupElement);
    }
    for(var j = 0, itemInfo; itemInfo = groupInfo.items[j]; j++) {
     this.addItemInternal(gallery, itemInfo, i, j, itemIdGetter);
    }
   }
  },
  addItemInternal: function(gallery, itemInfo, groupIndex, itemIndex, itemIdGetter) {
   var itemId = itemIdGetter ? itemIdGetter.call(this, groupIndex, itemIndex) : this.getItemIDInternal(groupIndex, itemIndex);
   var glrItemElement = document.createElement("div");
   glrItemElement.setAttribute("class", constants.CLASSNAMES.GALLERY_ITEM);
   glrItemElement.setAttribute("id", itemId);
   var glrItemContentElement = document.createElement("div");
   glrItemContentElement.setAttribute("class", constants.CLASSNAMES.GALLERY_ITEM_CONTENT);
   glrItemElement.appendChild(glrItemContentElement);
   if(this.showText && (this.imagePosition == 'Bottom' || this.imagePosition == 'Right')) {
    this.addItemTextElement(glrItemContentElement, itemInfo);
   }
   var glrItemImage = document.createElement("img");
   glrItemImage.setAttribute("style", "width:" + this.imageWidth + ";height:" + this.imageHeight);
   glrItemImage.setAttribute("src", itemInfo.image.url ? itemInfo.image.url : ASPx.EmptyImageUrl);
   if(itemInfo.image.className)
    glrItemImage.setAttribute("class", itemInfo.image.className);
   glrItemContentElement.appendChild(glrItemImage);
   if(this.showText && (this.imagePosition == 'Top' || this.imagePosition == 'Left')) {
    this.addItemTextElement(glrItemContentElement, itemInfo);
   }
   gallery.appendChild(glrItemElement);
   ASPx.GetStateController().AddHoverItem(itemId,
    ["dxr-itemHover"],
    [""],
    null,
    null,
    null);
   ASPx.GetStateController().AddSelectedItem(itemId,
    ["dxr-itemChecked"],
    [""],
    null,
    null,
    null);
  },
  addItemTextElement: function(parent, itemInfo) {
   var glrItemTextElement = document.createElement("div");
   glrItemTextElement.setAttribute("class", constants.CLASSNAMES.GALLERY_ITEM_TEXT);
   glrItemTextElement.innerHTML = itemInfo.text;
   if(this.maxTextWidth)
    glrItemTextElement.style.width = this.maxTextWidth;
   parent.appendChild(glrItemTextElement);
  },
  clearItems: function() {
   this.selectedItem = null;
   this.selectedValue = null;
   this.galleryGroups = [];
   var gallery = this.getGalleryDiv();
   gallery.innerHTML = '';
   this.eachItem(function(item) {
    ASPx.GetStateController().RemoveSelectedItem(item.id);
    ASPx.GetStateController().RemoveHoverItem(item.id);
   });
   this.minPopupWidth = 0;
   this.minPopupHeight = 0;
   this.maxElementWidth = 0;
   this.maxElementHeight = 0;
   this.initialized = false;
  },
  onGalleryDropDownClick: function(evt) {
   if(!this.getEnabledCore()) return;
   var source = ASPx.Evt.GetEventSource(evt);
   var element = ASPx.GetParentByClassName(source, constants.CLASSNAMES.GALLERY_ITEM);
   if(element) {
    var item = this.getItemByElement(element);
    this.selectItem(item);
    this.execute();
   }
   var popup = this.getPopup();
   if(popup) {
    if(popup.IsVisible())
     popup.Hide();
   }
  },
  execute: function() {
   this.ribbon.onExecCommand(this, this.getValueCore());
  },
  setValueCore: function(value) {
   if(!value) {
    this.selectedValue = null;
    this.selectItem(null);
    return;
   }
   this.eachItem(function(item) {
    if(item.value == value) {
     if(!item.selected) {
      this.selectItem(item);
     }
    }
   });
  },
  selectItem: function(item, elementSelector) {
   if(!elementSelector)
    elementSelector = function(i) {
     return i.element;
    };
   if(item) {
    this.selectedValue = item.value;
    if(!this.allowSelectItem)
     return;
    this.selectedItem = item;
    ASPx.GetStateController().SelectElementBySrcElement(elementSelector(item));
   }
   this.updateClientState();
   this.eachItem(function(i) {
    if(!item || item.id != i.id)
     ASPx.GetStateController().DeselectElementBySrcElement(elementSelector(i));
   });
  },
  updateClientState: function() {
   this.ribbon.updateClientStateField(getItemID(this, true), this.selectedValue);
  },
  getValueCore: function() {
   return this.selectedValue;
  },
  getPopup: function() {
   return ASPx.GetControlCollection().Get(getItemID(this) + constants.POPUP_GALLERY_POSTFIX);
  },
  getGalleryDiv: function() {
   var popup = this.getPopup();
   if(!popup)
    return;
   var dropDownGalleryElement = ASPx.GetNodeByClassName(popup.GetWindowElement(-1), constants.CLASSNAMES.GALLERY_MAIN_DIV);
   return dropDownGalleryElement;
  },
  getItemByElement: function(element) {
   var result;
   this.eachItem(function(item) {
    if(item.id == element.id ||
     item.id.replace(constants.POPUP_GALLERY_POSTFIX, "") == element.id) {
     result = item;
     return false;
    }
   });
   return result;
  },
  setPopupOffset: function() {
   var popup = this.getPopup();
   popup.SetPopupVerticalOffset(this.getElement().offsetHeight);
  },
  preparePopupBeforeShow: function() {
   this.setPopupOffset();
  },
  afterPopupShown: function() {
   this.scrollPopUpToItem(this.selectedItem);
  },
  onPopupPopUp: function() {
   var popup = this.getPopup();
   this.initializeSize();
   this.initContainerHeight();
   if(!this.minPopupWidth || !this.minPopupHeight)
    this.eachItem(function(item) {
     this.minPopupWidth = item.element.offsetLeft + item.element.offsetWidth + ASPx.GetVerticalScrollBarWidth();
     this.minPopupHeight = item.element.offsetTop + item.element.offsetHeight + popup.GetWindowFooterHeightLite(-1);
     return false;
    });
   if(!this.initialized)
    this.initTooltips(function(item) { return item.element; });
   this.initialized = true;
   this.setPopupSize(popup, this.getPopupWidth(), this.containerHeight);
   popup.UpdatePositionAtElement(this.getElement());
   if(this.ribbon.keyboardSupport) {
    setTimeout(function() {
     this.Focus();
    }.aspxBind(this), 150);
   }
  },
  initTooltips: function(elementGetter) {
   if(!this.showText)
    return;
   var maxTextWidth = ASPx.PxToInt(this.maxTextWidth);
   this.eachItem(function(item) {
    var element = elementGetter(item);
    var textElement = ASPx.GetNodesByClassName(element, constants.CLASSNAMES.GALLERY_ITEM_TEXT)[0];
    if(textElement.scrollWidth > maxTextWidth) {
     var text = textElement.textContent;
     if(text)
      element.title = text.trim();
    }
   });
  },
  setPopupSize: function(popup, popupWidth, popupHeight) {
   this.setContainerSize(popupWidth, popupHeight);
   popup.minWidth = 0;
   popup.minHeight = 0;
   popup.SetSize(0, 0);
   var width = popup.GetWidth();
   var height = popup.GetHeight();
   popup.SetWidth(width);
   popup.SetHeight(height);
   popup.minWidth = width;
   popup.minHeight = this.minPopupHeight;
   this.setContainerSize();
  },
  setContainerSize: function(width, height) {
   this.setElementSize(this.getGalleryDiv(), width, height);
  },
  setElementSize: function(element, width, height) {
   var clearWidth = width - ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element);
   var clearHeight = height - ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element);
   var widthPx = width ? clearWidth + "px" : "";
   var heightPx = height ? clearHeight + "px" : "";
   element.style.width = widthPx;
   element.style.height = heightPx;
  },
  eachItem: function(callback) {
   for(var i = 0, group; group = this.galleryGroups[i]; i++) {
    for(var j = 0, item; item = group[j]; j++) {
     if((callback.aspxBind(this)(item)) == false)
      return;
    }
   }
  },
  getPopupWidth: function() {
   var popupWidth = this.col * this.maxElementFullWidth;
   return popupWidth;
  },
  getLastItem: function() {
   for(var i = this.galleryGroups.length - 1, group; group = this.galleryGroups[i]; i--) {
    for(var j = group.length - 1, item; item = group[j]; j--) {
     return item;
    }
   }
  },
  getItemsCount: function() {
   var count = 0;
   this.eachItem(function() {
    count++;
   });
   return count;
  },
  getMaxItemsCountInGroup: function() {
   var maxLength = 0;
   for(var i = 0, group; group = this.galleryGroups[i]; i++) {
    if(group.length > maxLength)
     maxLength = group.length;
   }
   return maxLength;
  },
  getItemID: function(item) {
   return this.getItemIDInternal(item.group.index, item.index);
  },
  getItemIDInternal: function(groupIndex, itemIndex) {
   return getItemID(this) + constants.POPUP_GALLERY_POSTFIX + "_" + groupIndex + "i" + itemIndex;
  },
  initMaxElementSize: function(elements) {
   if(this.maxElementWidth || this.maxElementHeight || !elements || !elements.length)
    return;
   var size = this.getMaxSize(elements);
   this.maxElementWidth = size.width;
   this.maxElementHeight = size.height;
   this.maxElementFullWidth = this.maxElementWidth + ASPx.GetLeftRightMargins(elements[0]);
   this.maxElementFullHeight = this.maxElementHeight + ASPx.GetTopBottomMargins(elements[0]);
  },
  getMaxSize: function(elements) {
   var maxWidth = 0;
   var maxHeight = 0;
   ASPx.Data.ForEach(elements, function(element) {
    if(!element)
     return;
    var width = element.offsetWidth;
    var height = element.offsetHeight;
    maxWidth = maxWidth < width ? width : maxWidth;
    maxHeight = maxHeight < height ? height : maxHeight;
   });
   var size = [];
   size.height = maxHeight;
   size.width = maxWidth;
   return size;
  },
  initContainerHeight: function() {
   var row = 1;
   var top = -1;
   var element = null;
   this.eachItem(function(item) {
    if(top == -1)
     top = item.element.offsetTop;
    var nextItemTop = item.element.offsetTop;
    if(nextItemTop != top) {
     row++;
     top = item.element.offsetTop;
    }
    if(row >= this.row) {
     element = item.element;
     return false;
    }
   });
   if(!element)
    element = this.getLastItem().element;
   if(element)
    this.containerHeight = element.offsetTop + element.offsetHeight - element.parentNode.offsetTop + 1;
  },
  getShowGroupText: function() {
   if(!this.showGroupText) {
    var groups = ASPx.GetChildNodesByClassName(this.getGalleryDiv(), "dxr-glrGroup");
    this.showGroupText = (groups.length != 0 && groups[0].textContent) ? true : false;
   }
   return this.showGroupText;
  },
  getItemRowNumber: function(item) {
   for(var i = 0, itemCount = 0, rowCount = 0; i < item.group.index; i++) {
    itemCount += this.galleryGroups[i].length;
    rowCount += Math.ceil(this.galleryGroups[i].length / this.col);
   }
   return this.showGroupText ? rowCount + Math.ceil((item.index + 1) / this.col) : Math.ceil((itemCount + item.index + 1) / this.col);
  },
  scrollPopUpToItem: function(item) {
   if(item) {
    var popup = this.getPopup();
    if(popup) {
     var content = popup.GetWindowContentElement(-1);
     var scrollPosistion = item.element.offsetHeight * (this.getItemRowNumber(item) - 1);
     var groupOffset = 0;
     if(this.showGroupText) {
      var firstGroupRow = Math.ceil((item.index + 1) / this.col) == 1 ? true : false;
      var groupLabelHeigth = ASPx.GetChildNodesByClassName(this.getGalleryDiv(), constants.CLASSNAMES.GALLERY_GROUP_DIV)[0].offsetHeight;
      var groupOffset = firstGroupRow ? groupLabelHeigth * item.group.index : groupLabelHeigth * (item.group.index + 1);
     }
     content.scrollTop = scrollPosistion + groupOffset;
    }
   }
  },
  getItem: function(group, index) {
   return this.galleryGroups[group][index] || false;
  },
  getItemElement: function(group, index) {
   if(this.getItem(group, index))
    return this.getItem(group, index).element;
  },
  getCurrentColCount: function() {
   return Math.floor(this.getPopup().width / this.maxElementFullWidth);
  },
  InitializeKeyboardHelper: function() {
   this.keyboardHelper = new ASPxRibbonGalleryKeyboardHelper(this);
   this.keyboardHelper.Init();
  },
  Focus: function() {
   if(this.keyboardHelper)
    this.keyboardHelper.Focus();
  }
 });
 var ASPxClientRibbonGalleryBarItem = ASPx.CreateClass(ASPxClientRibbonGalleryDropDownItem, {
  constructor: function(itemInfo, items, navigateUrl, properties) {
   this.constructor.prototype.constructor.call(this, itemInfo, items, navigateUrl, properties);
   this.eachItem(function(item) {
    item.barItemId = this.getBarItemID(item);
    item.barElement = ASPx.GetElementById(item.barItemId);
   });
   this.colMax = properties.colMax;
   this.colMin = properties.colMin;
   this.rowBar = properties.rowBar;
   this.scrollManager = null;
   this.scrollOffset = 0;
   this.needScollToSelectedItem = true;
   this.galleryWidth = 0;
   this.adjusted = true;
  },
  initialize: function() {
   ASPxClientRibbonGalleryDropDownItem.prototype.initialize.call(this);
   this.initializeCore();
  },
  initializeCore: function() {
   var noItems = true;
   this.eachItem(function() {
    noItems = false;
    return false;
   });
   if(noItems)
    return;
   this.initializeSize();
   this.initializeScrolling();
   this.initTooltips(function(item) { return item.barElement; });
   setTimeout(function() { this.setValueCore(this.selectedValue); }.aspxBind(this), 100);
  },
  initializeHandlers: function() {
   ASPxClientRibbonGalleryDropDownItem.prototype.initializeHandlers.call(this);
   if(this.ribbon.enabled) {
    ASPx.Evt.AttachEventToElement(this.getGalleryBarDiv(), "click", function(evt) {
     this.onGalleryBarClick(evt);
    }.aspxBind(this));
   }
  },
  initializeScrolling: function() {
   this.scrollManager = this.scrollManager ? this.scrollManager : new ASPx.ScrollingManager(this, {
    scrollableArea: this.getGalleryBarDiv(),
    orientation: [0, 1],
    onBeforeScrolling: this.onBeforeScrolling,
    onAfterScrolling: this.onAfterScrolling,
    forseEmulation: true,
    useMarginForPosition: false
   });
   this.scrollManager.scrollSessionInterval = 100;
   this.scrollManager.animationAcceleration = 2;
   this.scrollManager.animationOffset = 10;
   this.initializeScrollButton(this.getUpButtonElement(), -1);
   this.initializeScrollButton(this.getDownButtonElement(), 1);
   this.updateScrollButtonsEnabled();
   this.initializeScrollOffset();
   this.getElement().style.overflow = "hidden";
   if(ASPx.Browser.MSTouchUI) {
    this.getGalleryBarContainer().style.marginRight = "0px";
    this.getGalleryBarContainer().style["-ms-overflow-style"] = "none";
   }
  },
  initializeScrollOffset: function() {
   var galleryElement = this.getGalleryBarDiv();
   var width = galleryElement.style.width;
   galleryElement.style.width = this.maxElementFullWidth + "px";
   var rowsCount = 0;
   var offsetTop;
   var firstElementOffset = 0;
   this.eachItem(function(item) {
    if(offsetTop === undefined) {
     offsetTop = item.barElement.offsetTop;
     firstElementOffset = offsetTop;
    }
    var elementOffsetTop = item.barElement.offsetTop;
    if(offsetTop != elementOffsetTop) {
     rowsCount++;
     offsetTop = elementOffsetTop;
    }
    if(rowsCount >= this.rowBar)
     return false;
   });
   if(rowsCount >= this.rowBar)
    this.scrollOffset = offsetTop - firstElementOffset;
   else
    this.scrollOffset = this.maxElementFullHeight * this.rowBar;
   galleryElement.style.width = width;
  },
  initializeScrollButton: function(button, dir) {
   if(!button || !button.id) return;
   ASPx.Selection.SetElementSelectionEnabled(button, false);
   var manager = this.scrollManager;
   if(this.enabled) {
    ASPx.Evt.AttachEventToElement(button, ASPx.TouchUIHelper.touchMouseDownEventName, function(e) { manager.StartScrolling(dir, 10, 5); ASPx.Evt.PreventEvent(e); });
    ASPx.Evt.AttachEventToElement(button, ASPx.TouchUIHelper.touchMouseUpEventName, function(e) { manager.StopScrolling(); });
   }
  },
  initializeSize: function() {
   if(!this.maxElementWidth || !this.maxElementHeight) {
    var elements = [];
    this.eachItem(function(item) {
     elements.push(item.barElement);
    });
    this.initMaxElementSize(elements);
    var margin = this.calculateItemMargin();
    var height = this.maxElementHeight + margin * 2;
    var needChromeFix = (ASPx.Browser.WebKitFamily && height % Math.floor(height) >= 0.5); 
    if(needChromeFix)
     height = Math.floor(height);
    ASPx.Data.ForEach(elements, function(element) {
     if(!element)
      return;
     if(needChromeFix) {
      element.style.marginBottom = "1px";
     }
     this.setElementSize(element, this.maxElementWidth, height);
     element.children[0].style.marginTop = margin + "px";
    }.aspxBind(this));
    var colMax = this.getColMax();
    this.galleryWidth = this.maxElementFullWidth * colMax;
    this.setBaseWidth();
   }
   ASPxClientRibbonGalleryDropDownItem.prototype.initializeSize.call(this);
  },
  getColMax: function() {
   var itemsCount = this.getItemsCount();
   var colMax = this.colMax > itemsCount ? itemsCount : this.colMax;
   return colMax;
  },
  setItems: function(items) {
   ASPxClientRibbonGalleryDropDownItem.prototype.setItems.call(this, items);
   this.setItemsInternal(this.getGalleryBarDiv(), items, false, this.getBarItemIDInternal);
   this.eachItem(function(item) {
    item.barItemId = this.getBarItemID(item);
    item.barElement = ASPx.GetElementById(item.barItemId);
   });
   if(this.group.tab.tabElement.offsetParent === null) {
    this.adjusted = false;
    return;
   }
   this.group.tab.deleteModifications();
   this.initializeCore();
   this.group.tab.recalculateModifications();
   this.adjusted = true;
  },
  clearItems: function() {
   var gallery = this.getGalleryBarDiv();
   gallery.innerHTML = "";
   this.getGalleryBarDiv().style.top = "0px";
   this.eachItem(function(item) {
    ASPx.GetStateController().RemoveSelectedItem(item.barItemId);
    ASPx.GetStateController().RemoveHoverItem(item.barItemId);
   });
   ASPxClientRibbonGalleryDropDownItem.prototype.clearItems.call(this);
  },
  adjust: function() {
   if(this.adjusted)
    return;
   this.group.tab.deleteModifications();
   this.initializeCore();
   this.group.tab.recalculateModifications();
   this.adjusted = true;
  },
  setBaseWidth: function(reset) {
   var galleryElement = this.getGalleryBarDiv();
   if(reset)
    galleryElement.style.width = "";
   else
    galleryElement.style.width = this.galleryWidth + "px";
  },
  onGalleryBarClick: function(evt) {
   this.needScollToSelectedItem = false;
   this.onGalleryDropDownClick(evt);
  },
  selectItem: function(item) {
   ASPxClientRibbonGalleryDropDownItem.prototype.selectItem.call(this, item);
   ASPxClientRibbonGalleryDropDownItem.prototype.selectItem.call(this, item, function(i) {
    return i.barElement;
   });
   if(this.needScollToSelectedItem)
    this.scrollToItem(item);
   this.needScollToSelectedItem = true;
  },
  calculateItemMargin: function() {
   var rowsHeight = this.maxElementFullHeight * this.rowBar;
   var margin = ASPx.GetClearClientHeight(this.getGalleryBarContainer()) - rowsHeight;
   if(margin < 0)
    return 0;
   var marginTop = margin / (this.rowBar * 2);
   return marginTop;
  },
  onBeforeScrolling: function(manager, direction) {
   var gallery = manager.owner;
   if(!gallery.getEnabledCore() || (gallery.isFullyScrolledToBottom() && direction > 0 || gallery.isFullyScrolledToTop() && direction < 0)) {
    manager.StopScrolling();
    return;
   }
   var offset = gallery.scrollOffset;
   var top = ASPx.PxToInt(gallery.getGalleryBarDiv().style.top);
   if(direction < 0) {
    var newTop = top + gallery.scrollOffset;
    if(newTop > 0)
     offset = offset - newTop;
   }
   if(direction > 0) {
    var newTop = top - gallery.scrollOffset;
    var maxTop = -(gallery.getGalleryBarDiv().offsetHeight - offset);
    if(newTop < maxTop)
     offset = offset - (maxTop - newTop);
   }
   manager.animationOffset = offset;
  },
  onAfterScrolling: function(manager, direction) {
   manager.owner.updateScrollButtonsEnabled();
  },
  scrollToItem: function(item) {
   if(!item || !this.isNeedToScroll())
    return;
   var galleryBarDiv = this.getGalleryBarDiv();
   galleryBarDiv.style.top = 0;
   var itemOffsetTop = item.barElement.offsetTop;
   while(ASPx.PxToInt(galleryBarDiv.style.top) - this.scrollOffset >= -itemOffsetTop) {
    this.scrollManager.StartScrolling(1, 10, itemOffsetTop);
    this.scrollManager.StopScrolling();
   }
   this.updateScrollButtonsEnabled();
  },
  isNeedToScroll: function() {
   return this.scrollManager && this.getEnabledCore() && this.getGalleryBarDiv().offsetHeight >= this.getElement().clientHeight;
  },
  updateScrollButtonsEnabled: function() {
   ASPx.GetStateController().SetElementEnabled(this.getUpButtonElement(), !this.isFullyScrolledToTop());
   ASPx.GetStateController().SetElementEnabled(this.getDownButtonElement(), !this.isFullyScrolledToBottom());
  },
  isFullyScrolledToBottom: function() {
   return ASPx.PxToInt(this.getGalleryBarDiv().style.top) <= -(this.getGalleryBarDiv().offsetHeight - this.getElement().clientHeight);
  },
  isFullyScrolledToTop: function() {
   return ASPx.PxToInt(this.getGalleryBarDiv().style.top) >= 0;
  },
  onPopupPopUp: function() {
   ASPxClientRibbonGalleryDropDownItem.prototype.onPopupPopUp.call(this);
   var col = this.getCurrentBarColumnsCount();
   this.col = this.ddColMin && col < this.ddColMin ? this.ddColMin : col;
   this.setPopupSize(this.getPopup(), this.getPopupWidth(), this.containerHeight);
  },
  onAfterModification: function() {
   if(this.selectedItem)
    this.scrollToItem(this.selectedItem);
   else {
    var maxTop = -(this.getGalleryBarDiv().offsetHeight - this.getElement().clientHeight);
    var currentTop = ASPx.PxToInt(this.getGalleryBarDiv().style.top);
    if(maxTop > currentTop) {
     var lastItem = this.getLastItem();
     this.scrollToItem(lastItem);
    }
   }
   this.updateScrollButtonsEnabled();
  },
  getCurrentBarColumnsCount: function() {
   var galleryBarElement = this.getGalleryBarDiv();
   if(!galleryBarElement)
    return;
   var columnsCount = Math.floor(galleryBarElement.offsetWidth / this.maxElementFullWidth);
   return columnsCount;
  },
  getGalleryBarDiv: function() {
   return ASPx.GetNodeByClassName(this.getElement(), constants.CLASSNAMES.GALLERY_MAIN_DIV);
  },
  getGalleryBarContainer: function() {
   return ASPx.GetNodeByClassName(this.getElement(), constants.CLASSNAMES.GALLERY_BAR_CONTAINER);
  },
  getPopOutElement: function() {
   var itemElement = this.getElement();
   return ASPx.GetChildById(itemElement, getItemID(this) + "_PB");
  },
  getUpButtonElement: function() {
   var itemElement = this.getElement();
   return ASPx.GetChildById(itemElement, getItemID(this) + "_UB");
  },
  getDownButtonElement: function() {
   var itemElement = this.getElement();
   return ASPx.GetChildById(itemElement, getItemID(this) + "_DB");
  },
  getBarItemID: function(item) {
   return this.getBarItemIDInternal(item.group.index, item.index);
  },
  getBarItemIDInternal: function(groupIndex, itemIndex) {
   return getItemID(this) + "_" + groupIndex + "i" + itemIndex;
  },
  setPopupOffset: function() {
   return;
  },
  setEnabledCore: function(enabled, initialization) {
   ASPxClientRibbonGalleryDropDownItem.prototype.setEnabledCore.call(this, enabled, initialization);
   this.eachItem(function(item) {
    ASPx.GetStateController().SetElementEnabled(item.barElement, enabled);
   });
   if(enabled)
    this.updateScrollButtonsEnabled();
   else {
    ASPx.GetStateController().SetElementEnabled(this.getUpButtonElement(), enabled);
    ASPx.GetStateController().SetElementEnabled(this.getDownButtonElement(), enabled);
   }
   ASPx.GetStateController().SetElementEnabled(this.getPopOutElement(), enabled);
  },
  onClick: function(evt) {
   if(!this.getEnabledCore()) return;
   var source = ASPx.Evt.GetEventSource(evt);
   var popout = this.getPopOutElement();
   if(ASPx.GetIsParent(popout, source)) {
    ASPxClientRibbonGalleryDropDownItem.prototype.onClick.call(this, evt);
   }
  }
 });
 var ASPxRibbonGalleryKeyboardHelper = ASPx.CreateClass(ASPx.KbdHelper, {
  constructor: function(ribbonGalleryItem) {
   this.constructor.prototype.constructor.call(this, ribbonGalleryItem.getPopup());
   this.ribbonGallery = ribbonGalleryItem;
   this.popup = ribbonGalleryItem.getPopup();
   this.receivedFocus = false;
   this.focusedItemIndex = -1;
   this.focusedGroupIndex = -1;
  },
  Init: function() {
   setTimeout(function() {
    this.initInternal();
   }.aspxBind(this), 200);
  },
  initInternal: function() {
   ASPx.KbdHelper.GlobalInit();
   var element = this.GetFocusableElement();
   if(!element) {
    this.Init();
    return;
   }
   element.tabIndex = Math.max(element.tabIndex, 0);
   var instance = this;
   ASPx.Evt.AttachEventToElement(element, "focus", function(e) {
    if(!instance.CanFocus(e))
     return true;
    ASPx.KbdHelper.active = instance;
   });
   ASPx.Evt.AttachEventToElement(element, "blur", function() {
    instance.onBlur();
   });
  },
  GetFocusableElement: function() {
   return this.popup.GetContentContainer(-1);
  },
  HandleKeyDown: function(e) {
   switch(ASPx.Evt.GetKeyCode(e)) {
    case ASPx.Key.Left:
     this.TryMoveFocus("left");
     return true;
    case ASPx.Key.Right:
     this.TryMoveFocus("right");
     return true;
    case ASPx.Key.Up:
     this.TryMoveFocus("up");
     return true;
    case ASPx.Key.Down:
     this.TryMoveFocus("down");
     return true;
    case ASPx.Key.Enter:
     this.ProcessEnterKey();
     return true;
    case ASPx.Key.Esc:
     this.ribbonGallery.hidePopup();
     return true;
   }
   return false;
  },
  Focus: function() {
   setTimeout(function() {
    this.GetFocusableElement().focus();
   }.aspxBind(this), 10);
   var stateController = ASPx.GetStateController();
   stateController.SetCurrentFocusedElementBySrcElement();
   this.receivedFocus = true;
  },
  TryMoveFocus: function(direction) {
   var index = this.focusedItemIndex;
   var groupIndex = this.focusedGroupIndex;
   switch(direction) {
    case "left":
     if(this.TryReceiveFocus())
      break;
     index -= 1;
     if(index < 0) {
      index = this.ribbonGallery.col - 1;
      if(index >= this.ribbonGallery.galleryGroups[groupIndex].length)
       index = this.ribbonGallery.galleryGroups[groupIndex].length - 1;
     }
     else if(this.GetCurrentColumnNumberByIndex(index + 1) == 0) {
      index = (this.ribbonGallery.col * (this.GetCurrentGroupRowNumberByIndex(groupIndex, index + 1) + 1)) - 1;
      if(index >= this.ribbonGallery.galleryGroups[groupIndex].length)
       index = this.ribbonGallery.galleryGroups[groupIndex].length - 1;
     }
     this.TryFocusItemByIndex(groupIndex, index);
     break;
    case "right":
     if(this.TryReceiveFocus())
      break;
     index += 1;
     if(this.GetCurrentColumnNumberByIndex(index) == 0)
      index = this.ribbonGallery.col * (this.GetCurrentGroupRowNumberByIndex(groupIndex, index) - 1);
     else if(index >= this.ribbonGallery.galleryGroups[groupIndex].length)
      index = this.ribbonGallery.col * (this.GetCurrentGroupRowNumberByIndex(groupIndex, index));
     this.TryFocusItemByIndex(groupIndex, index);
     break;
    case "up":
     if(this.TryReceiveFocus())
      break;
     this.TryFocusNextRowItem(direction);
     break;
    case "down":
     if(this.TryReceiveFocus())
      break;
     this.TryFocusNextRowItem(direction);
     break;
   }
  },
  TryReceiveFocus: function() {
   if(this.receivedFocus) {
    this.receivedFocus = false;
    this.focusedItemIndex = 0;
    this.focusedGroupIndex = 0;
    this.TryFocusItemByIndex(this.focusedGroupIndex, this.focusedItemIndex);
    return true;
   }
   return false;
  },
  TryFocusNextRowItem: function(direction) {
   var initialItemIndex = this.focusedItemIndex;
   if(direction == "up") {
    this.focusedItemIndex -= this.ribbonGallery.col;
    if(this.focusedItemIndex < 0) {
     this.focusedGroupIndex -= 1;
     if(this.focusedGroupIndex < 0)
      this.focusedGroupIndex = this.ribbonGallery.galleryGroups.length - 1;
     this.focusedItemIndex = (this.GetGroupRowsCount(this.focusedGroupIndex) - 1) * this.ribbonGallery.col + this.GetCurrentColumnNumberByIndex(initialItemIndex);
    }
    if(this.TryFocusItemByIndex(this.focusedGroupIndex, this.focusedItemIndex))
     return true;
    else
     this.TryFocusNextRowItem(direction);
   }
   else {
    this.focusedItemIndex += this.ribbonGallery.col;
    if(this.focusedItemIndex >= this.ribbonGallery.galleryGroups[this.focusedGroupIndex].length) {
     this.focusedItemIndex = this.GetCurrentColumnNumberByIndex(initialItemIndex);
     this.focusedGroupIndex += 1;
     if(this.focusedGroupIndex >= this.ribbonGallery.galleryGroups.length) {
      this.focusedGroupIndex = 0;
      this.focusedItemIndex = this.GetCurrentColumnNumberByIndex(this.focusedItemIndex);
     }
    }
    if(this.TryFocusItemByIndex(this.focusedGroupIndex, this.focusedItemIndex))
     return true;
    else
     this.TryFocusNextRowItem(direction);
   }
  },
  TryFocusItemByIndex: function(group, index) {
   var stateController = ASPx.GetStateController();
   var element = this.ribbonGallery.getItemElement(group, index);
   if(element) {
    stateController.SetCurrentFocusedElementBySrcElement(element);
    this.ribbonGallery.scrollPopUpToItem(this.ribbonGallery.getItem(group, index));
    this.focusedItemIndex = index;
    this.focusedGroupIndex = group;
    return true;
   }
   return false;
  },
  GetGroupRowsCount: function(group) {
   return Math.ceil(this.ribbonGallery.galleryGroups[group].length / this.ribbonGallery.col);
  },
  GetCurrentGroupRowNumberByIndex: function(group, index) {
   return Math.ceil((index + 1) / this.ribbonGallery.col) - 1;
  },
  GetCurrentColumnNumberByIndex: function(index) {
   return index % this.ribbonGallery.col;
  },
  ProcessEnterKey: function() {
   var item = null;
   if(this.focusedGroupIndex >= 0 && this.focusedItemIndex >= 0)
    item = this.ribbonGallery.getItem(this.focusedGroupIndex, this.focusedItemIndex);
   if(item) {
    this.ribbonGallery.selectItem(item);
    this.ribbonGallery.execute();
   }
   this.ribbonGallery.hidePopup();
   this.focusedItemIndex = -1;
   this.focusedGroupIndex = -1;
  }
 });
 var ASPxRibbonItemsFactoryEx = ASPx.CreateClass(ASPx.ASPxRibbonItemsFactory, {
  createTab: function(control, index, tabInfo) {
   return new ASPxClientRibbonTabEx(control, index, tabInfo);
  },
  createGroup: function(control, tab, index, groupInfo) {
   return new ASPxClientRibbonGroupEx(control, tab, index, groupInfo);
  },
  createItem: function(ribbonItemInfo) {
   var rawInfo = ribbonItemInfo.rawInfo;
   switch(ribbonItemInfo.type) {
    case constants.ITEMTYPES.GALLERYDROPDOWN:
     return new ASPxClientRibbonGalleryDropDownItem(ribbonItemInfo, rawInfo.i, rawInfo.nu, rawInfo.pr);
    case constants.ITEMTYPES.GALLERYBAR:
     return new ASPxClientRibbonGalleryBarItem(ribbonItemInfo, rawInfo.i, rawInfo.nu, rawInfo.pr);
    default:
     return ASPx.ASPxRibbonItemsFactory.prototype.createItem.call(this, ribbonItemInfo);
   }
  }
 });
 var RibbonAccessKeysHelper = ASPx.CreateClass(ASPx.AccessKeysHelper, {
  TryMoveFocusLeft: function (modifier) {
  },
  TryMoveFocusRight: function (modifier) {
  },
  TryMoveFocusUp: function (modifier) {
  },
  TryMoveFocusDown: function (modifier) {
  },
  CanFocus: function(e) {
   var canFocusBase = ASPx.AccessKeysHelper.prototype.CanFocus.call(this, e);
   if(canFocusBase)
    return !this.eventSourceIsDropDownControl(e) && !this.eventSourceIsDropDownCalendarControl(e);
   return canFocusBase;
  },
  eventSourceIsDropDownControl: function(evt) {
   return ASPxClientRibbon.Events.eventSourceIsDropDownControl(evt);
  },
  eventSourceIsDropDownCalendarControl: function(evt) {
   return ASPxClientRibbon.Events.eventSourceIsDropDownCalendarControl(evt);
  }
 });
 var BlockMod = function(className, width, priority) {
  this.className = className;
  this.width = width;
  this.priority = priority;
 };
 ASPxClientRibbon.Events = {};
 ASPxClientRibbon.Events.eventSourceIsDropDownControl = function(evt) {
  var sourceElement = ASPx.Evt.GetEventSource(evt),
   parentElement = sourceElement;
  if(sourceElement && sourceElement.tagName === 'IMG')
   sourceElement = sourceElement.parentElement;
  if(sourceElement && sourceElement.tagName === 'SPAN')
   sourceElement = sourceElement.parentElement;
  if(sourceElement && sourceElement.tagName === "TD" && ASPx.ElementHasCssClass(sourceElement, "dxeButton") || ASPx.ElementHasCssClass(sourceElement, "dxic"))
   parentElement = ASPx.GetParentByTagName(sourceElement, "TABLE");
  return parentElement && ASPx.ElementHasCssClass(parentElement, "dxeButtonEditSys");
 };
 ASPxClientRibbon.Events.eventSourceIsDropDownCalendarControl = function(evt) {
  var sourceElement = ASPx.Evt.GetEventSource(evt),
   parentElement = sourceElement;
  if(sourceElement && sourceElement.tagName === "IMG")
   sourceElement = sourceElement.parentElement;
  if(sourceElement && sourceElement.tagName === "SPAN")
   sourceElement = sourceElement.parentElement;
  if(sourceElement && sourceElement.tagName === "TD" && (ASPx.ElementHasCssClass(sourceElement, "dxe") || ASPx.ElementHasCssClass(sourceElement, "dxeCHS")))
   sourceElement = ASPx.GetParentByTagName(sourceElement, "TABLE");
  if(sourceElement && sourceElement.parentElement)
   sourceElement = ASPx.GetParentByTagName(sourceElement.parentElement, "TABLE");
  if(sourceElement && sourceElement.parentElement)
   parentElement = ASPx.GetParentByTagName(sourceElement.parentElement, "TABLE");
  return parentElement && ASPx.ElementHasCssClass(parentElement, "dxeCVC");
 };
 ASPxClientRibbon.GroupScroller = function(ribbon) {
  this.groupScrollManager = {};
  this.scrollButtonStep = 70;
  function isLeftGroupScrollButton(element) {
   return ASPx.ElementContainsCssClass(element, constants.CLASSNAMES.GROUP_SCROLL_LEFT_DIV);
  }
  function isRightGroupScrollButton(element) {
   return ASPx.ElementContainsCssClass(element, constants.CLASSNAMES.GROUP_SCROLL_RIGHT_DIV);
  }
  function isGroupScrollButton(element) {
   return isLeftGroupScrollButton(element) || isRightGroupScrollButton(element);
  }
  function ensureGroupScrollButtons() {
   if(ASPx.Browser.TouchUI) return;
   var tabContent = ribbon.activeTab.getTabContentElement(),
    leftButton = ASPx.GetChildNodesByClassName(tabContent, constants.CLASSNAMES.GROUP_SCROLL_LEFT_DIV);
   if(leftButton.length === 0) {
    var container = document.createElement("DIV"),
     leftButton = document.createElement("DIV"),
     rightButton = document.createElement("DIV");
    container.className = constants.CLASSNAMES.GROUP_SCROLL_CONTAINER;
    leftButton.className = constants.CLASSNAMES.GROUP_SCROLL_LEFT_DIV;
    rightButton.className = constants.CLASSNAMES.GROUP_SCROLL_RIGHT_DIV;
    container.appendChild(leftButton);
    container.appendChild(rightButton);
    tabContent.insertBefore(container, tabContent.firstChild);
   }
  }
  function correctGroupScrollOffset(left) {
   if(left > 0) return 0;
   var groupListWidth = ribbon.activeTab.getListElement().offsetWidth,
    tabsContainerWidth = ribbon.getTabsContainer().offsetWidth;
   if(tabsContainerWidth > groupListWidth + left) {
    if(tabsContainerWidth >= groupListWidth)
     return 0;
    return tabsContainerWidth - groupListWidth;
   }
   return left;
  }
  function resetScrollPosition() {
   var scrollManager = getGroupScrollManager(),
    currentScrollPos = scrollManager.GetScrolledAreaPosition();
   if(currentScrollPos !== 0)
    scrollManager.SetScrolledAreaPosition(0);
  }
  var getGroupScrollManager = function() {
   var index = ribbon.activeTab.index;
   if(!this.groupScrollManager[index]) {
    ensureGroupScrollButtons();
    var groupList = ribbon.activeTab.getListElement();
    this.groupScrollManager[index] = new ASPx.MouseScrollingManager(this, {
     scrollableArea: groupList,
     orientation: [1, 0],
     onBeforeScrolling: null,
     onAfterScrolling: null,
     forseEmulation: true,
     mouseEventsElement: groupList,
     useMarginForPosition: true,
     preventOuterScroll: false
    });
    if(!ASPx.Browser.TouchUI)
     this.groupScrollManager[index].enableMouseScrollInternal = false;
    this.groupScrollManager[index].scrollSessionInterval = 5;
    this.groupScrollManager[index].animationAcceleration = 0.5;
    this.groupScrollManager[index].getValidNewScrollOffset = function(newOffset) {
     return correctGroupScrollOffset(newOffset);
    }.aspxBind(this);
   }
   return this.groupScrollManager[index];
  }.aspxBind(this);
  this.onActiveTabChanged = function() {
   resetScrollPosition();
  };
  this.onMouseDown = function(evt, source) {
   if(!isGroupScrollButton(source)) return;
   var scrollManager = getGroupScrollManager(),
    currentScrollPos = scrollManager.GetScrolledAreaPosition(),
    offset = isLeftGroupScrollButton(source) ? this.scrollButtonStep : - this.scrollButtonStep;
   scrollManager.SetScrolledAreaPosition(correctGroupScrollOffset(currentScrollPos + offset));
   this.updateGroupScrollButtonsVisibility();
  };
  this.updateGroupScrollButtonsVisibility = function() {
   if (ASPx.Browser.TouchUI || !ribbon.activeTab) return;
   var mainElement = ribbon.GetMainElement();
   var tabsContainer = ribbon.getTabsContainer();
   var groupList = ribbon.activeTab.getListElement();
   var groupListWidth = groupList.offsetWidth;
   var left = ASPx.PxToInt(groupList.style.marginLeft);
   ASPx.ToggleClassNameToElement(mainElement, "l", left < 0);
   ASPx.ToggleClassNameToElement(mainElement, "r", tabsContainer.offsetWidth < groupListWidth + left);
  };
 };
 function scItemOut(source, args) {
  var ribbon = ASPxClientRibbonCollection.find(args.item.name);
  var helper = ribbon && ribbon.getPopupMenuHelper();
  if(helper && helper.currentDropDownItem) {
   helper.tryApplyHoverState(args.item);
  }
  else if(ribbon && ribbon.currentGroupInPopup) {
   var expButton = ribbon.currentGroupInPopup.getExpandButtonElement();
   if(args.item.name == expButton.id) {
    var newHoverItem = args.item.Clone();
    expButton.hoverItem = newHoverItem;
    newHoverItem.Apply(expButton);
   }
  }
  if(ribbon && ribbon.showTabs && ribbon.minimized && ribbon.currentTemporaryTabPageIndex > -1) {
   var tcTabIndex = ribbon.getTabControlTabIndex(ribbon.currentTemporaryTabPageIndex);
   var tabElement = ribbon.getTabControl().GetTabElement(tcTabIndex, false);
   if(args.item.name == tabElement.id) {
    var newHoverItem = args.item.Clone();
    tabElement.hoverItem = newHoverItem;
    newHoverItem.Apply(tabElement);
   }
  }
 }
 ASPx.AddAfterClearFocusedState(scItemOut);
 ASPx.AddAfterClearHoverState(scItemOut);
 ASPx.RibbonConstants = constants;
 ASPx.ASPxClientRibbonTabEx = ASPxClientRibbonTabEx;
 ASPx.ASPxClientRibbonGroupEx = ASPxClientRibbonGroupEx;
 window.ASPxClientRibbon = ASPxClientRibbon;
 window.ASPxClientRibbonCommandExecutedEventArgs = ASPxClientRibbonCommandExecutedEventArgs;
 window.ASPxClientRibbonMinimizationStateEventArgs = ASPxClientRibbonMinimizationStateEventArgs;
 window.ASPxClientRibbonDialogBoxLauncherClickedEventArgs = ASPxClientRibbonDialogBoxLauncherClickedEventArgs;
 window.ASPxClientRibbonState = ASPxClientRibbonState;
 ASPx.RibbonAccessKeysHelper = RibbonAccessKeysHelper;
})();

(function() {
var MVCxClientPopupControl = ASPx.CreateClass(ASPxClientPopupControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 PerformCallback: function(data, onSuccess){
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientPopupControl.prototype.PerformCallback.call(this, data, onSuccess);
 },
 PerformWindowCallback: function(window, data) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  this.callbackCustomArgs["windowIndex"] = window ? window.index : -1;
  ASPxClientPopupControl.prototype.PerformWindowCallback.call(this, window, data);
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, null, this.callbackCustomArgs); }; 
  ASPxClientPopupControl.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command){
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 CreateCallbackCore: function(arg, command, callbackID){
  if(this.callbackCustomArgs != {})
   window.setTimeout(function(){ this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientPopupControl.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientPopupControl.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientPopupControl.prototype.EvalCallbackResult.call(this, resultString);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientPopupControl.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientPopupControl.Cast = ASPxClientControl.Cast;
window.MVCxClientPopupControl = MVCxClientPopupControl;
})();

(function () {
var ASPxClientRatingControl = ASPx.CreateClass(ASPxClientControl, {
 __isASPxRatingControl: true,
 INDEX_DEFAULT: 0,
 INDEX_USER: 1,
 INDEX_CHECKED: 2,
 INDEX_HOVER: 3,
 FILLPRECISION_EXACT: 0,
 FILLPRECISION_HALF: 1,
 FILLPRECISION_FULL: 2,
 constructor: function (name) {
  this.constructor.prototype.constructor.call(this, name);
  this.itemCount = 0;
  this.itemWidth = 0;
  this.itemHeight = 0;
  this.value = 0;
  this.readOnly = false;
  this.mainDiv = null;
  this.checkedDiv = null;
  this.hoverDiv = null;
  this.titles = [];
  this.fillPrecision = 0;
  this.hoverItemIndex = -1;
  this.hideSelectionOnHover = true;
  this.checkedDivWidth = "";
  this.itemLabels = [];
  this.controlDescriptionTemplate = null;
  this.ItemClick = new ASPxClientEvent();
  this.ItemMouseOver = new ASPxClientEvent();
  this.ItemMouseOut = new ASPxClientEvent();
 },
 Initialize: function () {
  ASPxClientControl.prototype.Initialize.call(this);
  this.AddAnchors();
 },
 applyAccessibilityAttributes: function(ariaDescriptor) {
  this.updateControlDescription();
  var argList = [];
  for(var i = 0; i < this.itemCount; i++)
   argList.push([["{0}", i + 1], ["{1}", this.itemCount]]);
  this.setAriaDescription("itemLink", argList);
 },
 updateControlDescription: function() {
  this.setAriaDescription("", [[["{0}", this.GetValue()]]]);
 },
 AddAnchors: function () {
  var div = this.GetMainDiv();
  if(div.lastChild.nodeName == "A")
   return;
  for(var i = 0; i < this.itemCount; i++)
   div.appendChild(this.CreateAnchor(i));
 },
 CreateAnchor: function (index) {
  var anchor = document.createElement("a");
  anchor.style.width = this.itemWidth + "px";
  anchor.style.height = this.itemHeight + "px";
  anchor.style[this.rtl ? "marginRight" : "marginLeft"] = index * this.itemWidth + "px";
  anchor.style.marginTop = -this.itemHeight + "px";
  anchor.style.display = "block";
  if(this.GetReadOnly())
    anchor.style.cursor = 'default';
  ASPx.Attr.SetAttribute(anchor, "DXIndex", index);
  ASPx.Attr.SetAttribute(anchor, "href", "javascript:void(0)");
  var title = this.GetTitle(index);
  if(title)
   ASPx.Attr.SetAttribute(anchor, "title", title);
  this.setItemLabel(anchor, index);
  ASPx.Evt.AttachEventToElement(anchor, "click", function () { aspxRatingControlVote(this.name, index); }.aspxBind(this));
  return anchor;
 },
 setItemLabel: function(anchor, index) {
  if(this.itemLabels && !!this.itemLabels[index])
   ASPx.Attr.SetAttribute(anchor, "aria-label", this.itemLabels[index]);   
 },
 GetTitle: function (index) {
  if(!this.GetEnabled())
   return null;
  if(this.titles && this.titles[index])
   return this.titles[index];
  if(this.toolTip)
   return this.toolTip;
  return null;
 },
 GetChildDiv: function (parent) {
  for(var i = 0; i < parent.childNodes.length; i++) {
   var child = parent.childNodes[i];
   if(child.tagName == "DIV")
    return child;
  }
 },
 GetMainDiv: function () {
  if(this.mainDiv == null)
   this.mainDiv = this.GetMainElement();
  return this.mainDiv;
 },
 GetCheckedDiv: function () {
  if(this.checkedDiv == null)
   this.checkedDiv = this.GetChildDiv(this.GetMainDiv());
  return this.checkedDiv;
 },
 GetHoverDiv: function () {
  if(this.hoverDiv == null)
   this.hoverDiv = this.GetChildDiv(this.GetCheckedDiv());
  return this.hoverDiv;
 },
 UpdateStateObject: function(){
  this.UpdateStateObjectWithObject({ readOnly: this.readOnly, value: this.value });
 },
 GetEnabled: function () {
  var disabled = ASPx.Attr.GetAttribute(this.GetMainElement(), "disabled");
  if(disabled && disabled === "disabled")
   return false;
  return true;
 },
 GetReadOnly: function () {
  if(!this.GetEnabled())
   return null;
  return this.readOnly;
 },
 SetReadOnly: function (readOnly) {
  if(!this.GetEnabled())
   return;
  this.readOnly = readOnly;
 },
 GetValue: function () {
  if(!this.GetEnabled())
   return null;
  return this.value;
 },
 SetValue: function (value, isUi) {
  if(!this.GetEnabled())
   return;
  if(value > this.itemCount)
   value = this.itemCount;
  this.value = value;
  this.UpdateCheckDiv(value, isUi);
  this.UpdateHoverDiv(-1);
 },
 UpdateCheckDiv: function (value, isUi) {
  var div = this.GetCheckedDiv();
  var index = isUi ? this.INDEX_USER : this.INDEX_CHECKED;
  div.style.backgroundPosition = "0 " + (-this.itemHeight * index) + "px";
  if(!isUi)
   value = this.QuantizeValue(value);
  div.style.width = this.itemWidth * value + "px";
 },
 QuantizeValue: function (input) {
  switch (this.fillPrecision) {
   case this.FILLPRECISION_EXACT:
    return input;
   case this.FILLPRECISION_FULL:
    return Math.round(input);
   case this.FILLPRECISION_HALF:
    return Math.round(input * 2) / 2;
  }
 },
 HandleVote: function (index) {
  if(this.hideSelectionOnHover)
   this.checkedDivWidth = "";
  if(this.GetReadOnly())
   return;
  this.SetValue(index + 1, true);
  this.updateControlDescription();
  var processOnServer = this.RaiseItemClick(index);
  if(processOnServer)
   this.SendPostBack(index);
 },
 HandleMouseMove: function (htmlEvent) {
  var index = this.GetItemIndexAtCursor(htmlEvent);
  if(index != -1) {
   if(this.hideSelectionOnHover)
    this.resetCheckedWidth();
   this.UpdateHoverDiv(index);
   this.hoverItemIndex = index;
   this.RaiseItemMouseOver(this.hoverItemIndex);
  }
 },
 HandleMouseOut: function () {
  this.UpdateHoverDiv(-1);
  if(this.hideSelectionOnHover)
   this.restoreCheckedWidth();
  this.RaiseItemMouseOut(this.hoverItemIndex);
  this.hoverItemIndex = -1;
 },
 GetItemIndexAtCursor: function (htmlEvent) {
  if(ASPx.Evt.GetEventSource(htmlEvent).nodeName == "A")
   return parseInt(ASPx.Evt.GetEventSource(htmlEvent).attributes.getNamedItem("DXIndex").value);
  return -1;
 },
 saveCheckedWidth: function () {
  if(this.GetCheckedDiv().style.width !== "0px")
   this.checkedDivWidth = this.GetCheckedDiv().style.width;
 },
 resetCheckedWidth: function () {
  this.saveCheckedWidth();
  this.GetCheckedDiv().style.width = "0px";
 },
 restoreCheckedWidth: function () {
  if(this.checkedDivWidth !== "")
   this.GetCheckedDiv().style.width = this.checkedDivWidth;
  this.checkedDivWidth = "";
 },
 UpdateHoverDiv: function (itemIndex) {
  this.GetHoverDiv().style.width = (itemIndex + 1) * this.itemWidth + "px";
 },
 Clear: function() {
  this.SetValue(0);
  return true;
 },
 RaiseItemClick: function (index) {
  var processOnServer = this.autoPostBack || this.IsServerEventAssigned("ItemClick");
  if(!this.ItemClick.IsEmpty()) {
   var args = new ASPxClientRatingControlItemClickEventArgs(processOnServer, index);
   this.ItemClick.FireEvent(this, args);
   processOnServer = args.processOnServer;
  }
  return processOnServer;
 },
 RaiseItemMouseOver: function (itemIndex) {
  if(!this.ItemMouseOver.IsEmpty()) {
   var args = new ASPxClientRatingControlItemMouseEventArgs(itemIndex);
   this.ItemMouseOver.FireEvent(this, args);
  }
 },
 RaiseItemMouseOut: function (itemIndex) {
  if(!this.ItemMouseOut.IsEmpty()) {
   var args = new ASPxClientRatingControlItemMouseEventArgs(itemIndex);
   this.ItemMouseOut.FireEvent(this, args);
  }
 }
});
ASPxClientRatingControl.Cast = ASPxClientControl.Cast;
ASPx.Ident.scripts.ASPxClientRatingControl = true;
ASPxClientRatingControl.RemoveDisposedElementUnderCursor = function(){
 if(!ASPx.IsValidElement(elementUnderCursor))
  elementUnderCursor = null;
};
var elementUnderCursor = null;
var activeRatingControl = null;
var DocMouseMoveHandler = function (htmlEvent) {
 var element = ASPx.Evt.GetEventSource(htmlEvent);
 if(element == elementUnderCursor)
  return;
 elementUnderCursor = element;
 for(var i = 0; i < 3 && element != null; i++) {
  if(element.id) {
   var obj = ASPx.GetControlCollection().Get(element.id);
   if(obj != null && obj.__isASPxRatingControl && obj.GetEnabled()) {
    if(activeRatingControl != null)
     activeRatingControl.HandleMouseOut();
    activeRatingControl = obj;
    if(!obj.GetReadOnly())
     obj.HandleMouseMove(htmlEvent);
    return;
   }
  }
  element = element.parentNode;
 }
 if(activeRatingControl != null && activeRatingControl.GetEnabled()) {
  activeRatingControl.HandleMouseOut();
  activeRatingControl = null;
 }
};
function aspxRatingControlVote(name, index) {
 var control = ASPx.GetControlCollection().Get(name);
 if(control)
  control.HandleVote(index);
}
var ASPxClientRatingControlItemClickEventArgs = ASPx.CreateClass(ASPxClientProcessingModeEventArgs, {
 constructor: function (processOnServer, index) {
  this.constructor.prototype.constructor.call(this, processOnServer);
  this.index = index;
 }
});
var ASPxClientRatingControlItemMouseEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function (index) {
  this.constructor.prototype.constructor.call(this);
  this.index = index;
 }
});
var handlerAssigned = false;
if(!handlerAssigned && !ASPx.Browser.TouchUI) {
 ASPx.Evt.AttachEventToDocument("mousemove", DocMouseMoveHandler);
 handlerAssigned = true;
}
window.ASPxClientRatingControl = ASPxClientRatingControl;
window.ASPxClientRatingControlItemClickEventArgs = ASPxClientRatingControlItemClickEventArgs;
window.ASPxClientRatingControlItemMouseEventArgs = ASPxClientRatingControlItemMouseEventArgs;
})();
(function () {
 var setAttributeIfValueExists = function(element, name, value) {
  if(ASPx.IsExists(value))
   ASPx.Attr.SetAttribute(element, name, value);
 };
 var CssClasses = {
  HeaderContentWrapper: "dxrpHCW",
  AnimationWrapper: "dxrpAW",
  ContentWrapper: "dxrpCW",
  Collapsed: "dxrpCollapsed",
  CollapseButtonRtl: "dxrpCollapseButtonRtl",
  CollapseButton: "dxrpCollapseButton"
 };
 var IDSuffixes = {
  HeaderElement: "_HC",
  GroupBoxCaption: "_GBC",
  ContentElement: "_RPC",
  HeaderTextContainer: "_RPHT"
 };
 var VerticalAlignEnum = {
  Top: 1,
  Middle: 2,
  Bottom: 3,
  NotSet: 0
 };
 var ASPxClientRoundPanel = ASPx.CreateClass(ASPxClientPanelBase, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
   this.animationDuration = 200;
   this.enableAnimation = true;
   this.allowCollapsingByHeaderClick = false;
   this.collapsed = false;
   this.isCollapsingAllowed = null;
   this.headerTextEmpty = false;
   this.collapseButton = null;
   this.collapseButtonImage = null;
   this.contentWrapper = null;
   this.animationWrapper = null;
   this.headerContentWrapper = null;
   this.isGroupBox = false;
   this.contentHeightBeforeCollapse = 0;
   this.contentWrapperHeight = 0;
   this.initialContentHeight = 0;
   this.tableInlineHeight = "";
   this.contentInlineHeight = "";
   this.headerCollapsedBorderSettings = {
    borderBottom: "",
    borderBottomLeftRadius: "",
    borderBottomRightRadius: ""
   };
   this.headerExpandedBorderSettings = {
    borderBottom: "",
    borderBottomLeftRadius: "",
    borderBottomRightRadius: ""
   };
   this.headerVerticalAlign = VerticalAlignEnum.Middle;
   this.loadContentViaCallback = false;
   this.isContentLoaded = false;
   this.CollapsedChanged = new ASPxClientEvent();
   this.CollapsedChanging = new ASPxClientEvent();
  },
  SetEnabled: function (enabled) {
   ASPx.GetStateController().SetElementWithChildNodesEnabled(this.name, enabled);
   this.isCollapsingAllowed = enabled;
   ASPxClientPanelBase.prototype.SetEnabled.call(this, enabled);
  },
  AdjustHeader: function () {
   var collapseButton = this.GetCollapseButton();
   var textWrapper = this.GetHeaderContentWrapper();
   if (!collapseButton || !textWrapper)
    return;
   var offset = Math.floor((collapseButton.offsetHeight - textWrapper.offsetHeight) * this.GetMarginTopMultiplier());
   if (offset > 0)
    textWrapper.style.marginTop = Math.abs(offset) + "px";
   if (offset < 0)
    collapseButton.style.marginTop = Math.abs(offset) + "px";
   var computedStyle = ASPx.GetCurrentStyle(collapseButton);
   var padding = collapseButton.offsetWidth + ASPx.PxToInt(computedStyle.marginRight) + ASPx.PxToInt(computedStyle.marginLeft);
   if (this.rtl)
    textWrapper.style.paddingLeft = padding + "px";
   else
    textWrapper.style.paddingRight = padding + "px";
  },
  GetMarginTopMultiplier: function () {
   switch (this.headerVerticalAlign) {
    case VerticalAlignEnum.Middle:
     return 0.5;
    case VerticalAlignEnum.Bottom:
     return 1;
    default:
     return 0;
   }
  },
  GetHeaderContentWrapper: function () {
   if (this.headerContentWrapper == null)
    this.headerContentWrapper = ASPx.GetChildByClassName(this.GetHeaderElement(), CssClasses.HeaderContentWrapper);
   return this.headerContentWrapper;
  },
  InlineInitialize: function () {
   ASPxClientPanelBase.prototype.InlineInitialize.call(this);
   this.SetCollapsed(this.collapsed);
   this.tableInlineHeight = this.GetMainElement().style.height;
   this.contentInlineHeight = this.GetContentElement().style.height;
   this.initialContentHeight = (+ASPx.PxToInt(this.contentInlineHeight));
   this.isContentLoaded = !this.GetCollapsed();
  },
  Initialize: function () {
   this.RemoveCollapsedCssClass();
   ASPxClientPanelBase.prototype.Initialize.call(this);
   this.InitializeHeaderBorderSettings(this.headerExpandedBorderSettings, false);
   this.InitializeHeaderBorderSettings(this.headerCollapsedBorderSettings, true);
   if (this.IsCollapsingAllowed()) {
    ASPx.Evt.AttachEventToElement(this.GetHeaderElement(), "click",
     function (evt) {
      this.OnHeaderClick(evt);
     }.aspxBind(this));
    if (this.GetCollapsed()) {
     if (this.GetAnimationWrapper())
      this.contentHeightBeforeCollapse = this.GetAnimationWrapper().offsetHeight;
     this.AssignCollapsedStyle();
    }
   }
   if (!this.clientEnabled)
    this.SetEnabled(this.clientEnabled);
  },
  GetAffectingSizeBordersAndPaddings: function (element, isVertical) {
   var boxSizing = ASPx.GetCurrentStyle(element).MozBoxSizing || ASPx.GetCurrentStyle(element).boxSizing;
   if (boxSizing == "padding-box")
    return isVertical ? ASPx.GetVerticalBordersWidth(element) : ASPx.GetHorizontalBordersWidth(element);
   else if (boxSizing == "border-box")
    return 0;
   else
    return isVertical ? ASPx.GetTopBottomBordersAndPaddingsSummaryValue(element) :
         ASPx.GetLeftRightBordersAndPaddingsSummaryValue(element);
  },
  InitializeHeaderBorderSettings: function (settings, isTopRadius) {
   if (!this.GetHeaderElement())
    return;
   var currentStyle = ASPx.GetCurrentStyle(this.GetHeaderElement());
   if (isTopRadius) {
    settings.borderBottomLeftRadius = currentStyle.borderTopLeftRadius;
    settings.borderBottomRightRadius = currentStyle.borderTopRightRadius;
    settings.borderBottom = currentStyle.borderTopWidth + " " + currentStyle.borderTopStyle + " " + currentStyle.borderTopColor;
   } else {
    settings.borderBottomLeftRadius = currentStyle.borderBottomLeftRadius;
    settings.borderBottomRightRadius = currentStyle.borderBottomRightRadius;
    settings.borderBottom = currentStyle.borderBottomWidth + " " + currentStyle.borderBottomStyle + " " + currentStyle.borderBottomColor;
   }
  },
  OnHeaderClick: function (evt) {
   var source = ASPx.Evt.GetEventSource(evt);
   if (ASPx.GetIsParent(this.GetCollapseButton(), source) || (this.allowCollapsingByHeaderClick && !ASPx.IsInteractiveControl(source)))
    this.setCollapsedInternal(!this.GetCollapsed(), true);
  },
  GetContentContainer: function () {
   return this.GetContentWrapper() || this.GetContentElement();
  },
  PerformCallback: function (parameter, onSuccess) {
   if (this.CanPerformCallback())
    this.CreateCallback(parameter, null, null, onSuccess);
  },
  CreateCallback: function (arg, command, callbackInfo, handler) {
   ASPxClientControl.prototype.CreateCallback.call(this, arg, command, handler);
   this.ShowLoadingElementsInternal();
  },
  OnCallback: function (html) {
   this.isContentLoaded = true;
   this.UpdateContentHtml(html);
  },
  UpdateContentHtml: function (html) {
   if (this.GetAnimationWrapper()) {
    var size = this.lockElementSize(this.GetAnimationWrapper(), false);
    this.SetContentHtmlInternal(html);
    this.StretchAnimationWrapper(size);
   } 
   else 
    this.SetContentHtmlInternal(html);
  },
  SetContentHtmlInternal: function (html) {
   var container = this.GetContentContainer();
   ASPx.Security.setInnerHtml(container, html, ASPx.Security.DataType.Trusted);
   this.lockElementSize(container, true);
  },
  lockElementSize: function (element, removeBlock) {
   var size = {
    width: element.offsetWidth - this.GetAffectingSizeBordersAndPaddings(element, false),
    height: element.offsetHeight - this.GetAffectingSizeBordersAndPaddings(element, true)
   };
   ASPx.SetStyles(element, {
    overflow: removeBlock ? "" : "hidden",
    width: removeBlock ? "" : size.width,
    height: removeBlock ? "" : size.height
   });
   return size;
  },
  StretchAnimationWrapper: function (size) {
   var contentWrapper = this.GetContentWrapper();
   ASPx.SetStyles(contentWrapper, { display: "table", height: "0px" });
   var width = contentWrapper.offsetWidth;
   var height = contentWrapper.offsetHeight;
   ASPx.Attr.RemoveStyleAttribute(contentWrapper, "height");
   ASPx.Attr.RemoveStyleAttribute(contentWrapper, "display");
   this.StartAnimation(this.GetAnimationWrapper(), function () {
    this.lockElementSize(this.GetAnimationWrapper(), true);
    this.RaiseCollapsedChanged();
   }.aspxBind(this),
   [
    { property: "height", to: height, from: size.height },
    { property: "width", to: width, from: size.width }
   ]);
  },
  ShowLoadingElementsInternal: function () {
   this.RestoreLoadingDivOpacity();
   this.ShowLoadingPanel();
   if (this.lpDelay > 0) {
    var clonedPanel = this.GetClonedLoadingPanel();
    clonedPanel.style.visibility = "hidden";
    window.setTimeout(function () {
     clonedPanel.style.visibility = "";
    }, this.lpDelay);
   }
  },
  CanPerformCallback: function () {
   return this.loadContentViaCallback && !this.InCallback();
  },
  CanPerformLoadContentCallback: function () {
   return this.CanPerformCallback() && !this.isContentLoaded;
  },
  ShowLoadingPanel: function () {
   var blockContentContainer = !this.IsContentHtmlEmpty();
   if (blockContentContainer)
    this.lockElementSize(this.GetContentContainer());
   this.CreateLoadingPanelInsideContainer(this.GetContentContainer(), true, false, false);
   if (!blockContentContainer)
    this.CenterLoadingPanel();
  },
  CenterLoadingPanel: function () {
   var loadingPanel = this.GetClonedLoadingPanel();
   if (!loadingPanel)
    return;
   var contentContainer = this.GetContentContainer();
   var parentHeight = ASPx.GetClearClientHeight(contentContainer);
   if (parentHeight > loadingPanel.offsetHeight)
    ASPx.SetStyles(loadingPanel, { marginTop: Math.floor((parentHeight - loadingPanel.offsetHeight) / 2) });
  },
  AdjustControlCore: function () {
   if (this.GetHeaderElement())
    this.AdjustHeader();
   this.UpdateContentHeight();
  },
  UpdateContentHeight: function () {
   if (!ASPx.PxToInt(this.contentInlineHeight) || !this.GetContentWrapper())
    return;
   var contentWrapper = this.GetContentWrapper();
   ASPx.SetStyles(contentWrapper, { display: "inline-block", height: "auto" });
   var realContentHeight = contentWrapper.offsetHeight;
   ASPx.Attr.RemoveStyleAttribute(contentWrapper, "height");
   ASPx.Attr.RemoveStyleAttribute(contentWrapper, "display");
   var contentHeight = Math.max(realContentHeight, this.initialContentHeight);
   if (contentHeight > 0) {
    this.contentInlineHeight = Math.max(realContentHeight, this.initialContentHeight) + "px";
    this.GetContentElement().style.height = this.contentInlineHeight;
   }
  },
  IsCollapsingAllowed: function () {
   return !this.isGroupBox && this.GetHeaderElement() && this.GetContentWrapper()
    && (this.isCollapsingAllowed != null ? this.isCollapsingAllowed : true);
  },
  GetContentElement: function () {
   return this.GetChildElement(IDSuffixes.ContentElement);
  },
  GetCollapseButton: function () {
   if (this.collapseButton == null)
    this.collapseButton = ASPx.GetNodesByClassName(this.GetMainElement(),
     this.rtl ? CssClasses.CollapseButtonRtl : CssClasses.CollapseButton)[0];
   return this.collapseButton;
  },
  GetCollapseButtonImage: function () {
   if (this.collapseButtonImage == null)
    this.collapseButtonImage = ASPx.GetNodeByTagName(this.GetCollapseButton(), "IMG", 0);
   return this.collapseButtonImage;
  },
  GetHeaderElement: function () {
   return this.GetChildElement(IDSuffixes.HeaderElement);
  },
  GetGroupBoxCaptionElement: function () {
   return this.GetChildElement(IDSuffixes.GroupBoxCaption);
  },
  GetHeaderTextContainer: function () {
   return this.GetChildElement(IDSuffixes.HeaderTextContainer);
  },
  GetHeaderText: function () {
   var textContainer = this.GetHeaderTextContainer();
   if (ASPx.IsExistsElement(textContainer) && textContainer.innerHTML != "&nbsp;")
    return ASPx.Str.Trim(textContainer.innerHTML);
   return "";
  },
  SetHeaderText: function (text) {
   var textContainer = this.GetHeaderTextContainer();
   if (ASPx.IsExistsElement(textContainer))
    ASPx.Security.setInnerHtml(textContainer, this.GetPreparedText(text), ASPx.Security.DataType.Trusted);
  },
  GetContentHtml: function () {
   var contentElement = this.GetContentContainer();
   if (ASPx.IsExistsElement(contentElement)) {
    var caption = this.isGroupBox ?  this.RemoveGroupBoxCaptionElement() : null;
    var contentHTML = contentElement.innerHTML;
    if (this.isGroupBox)
     this.RestoreGroupBoxCaptionElement(caption);
    if (contentHTML == "&nbsp;")
     contentHTML = "";
    return contentHTML;
   }
   return null;
  },
  SetContentHtml: function (html) {
   var contentElement = this.GetContentContainer();
   if (ASPx.IsExistsElement(contentElement)) {
    var caption = this.isGroupBox ? this.RemoveGroupBoxCaptionElement() : null;
    ASPx.Security.setInnerHtml(contentElement, this.GetPreparedText(html), ASPx.Security.DataType.Trusted);
    if (this.isGroupBox)
     this.RestoreGroupBoxCaptionElement(caption);
    this.UpdateContentHeight();
   }
  },
  IsContentHtmlEmpty: function () {
   return !ASPx.Str.Trim(this.GetContentHtml());
  },
  GetPreparedText: function (text) {
   if (!text || ASPx.Str.Trim(text) == "")
    text = "&nbsp;";
   return text;
  },
  RemoveGroupBoxCaptionElement: function () {
   var captionElement = this.GetGroupBoxCaptionElement();
   return captionElement ? captionElement.parentNode.removeChild(captionElement) : null;
  },
  RestoreGroupBoxCaptionElement: function (captionElement) {
   var contentElement = this.GetContentElement();
   if (contentElement) {
    if (contentElement.hasChildNodes())
     contentElement.insertBefore(captionElement, contentElement.firstChild);
    else
     contentElement.appendChild(captionElement);
   }
  },
  GetCollapsed: function () {
   if (!this.IsCollapsingAllowed())
    return false;
   return this.collapsed;
  },
  SetCollapsed: function (collapsed) {
   var isUserAction = false;
   this.setCollapsedInternal(collapsed, isUserAction);
  },
  setCollapsedInternal: function(collapsed, isUserAction) {
   if (isUserAction) {
    var args = this.RaiseCollapsedChanging();
    if (args && args.cancel) {
     return;
    }
   }
   if (this.IsCollapsingAllowed() && this.GetCollapsed() != collapsed) {
    this.collapsed = collapsed;
    this.ToggleAppearance();
   }
  },
  UpdateStateObject: function(){
   this.UpdateStateObjectWithObject({ collapsed: this.collapsed });
  },
  ToggleAppearance: function () {
   this.switchButtonAppearance();
   if (this.GetCollapsed())
    this.CollapseContent();
   else
    this.ExpandContent();
   if (!this.enableAnimation)
    this.RaiseCollapsedChanged();
  },
  switchButtonAppearance: function() {
   var image = this.GetCollapseButtonImage();
   if(!image)
    return;
   var props = this.GetCollapsed() ? this.expandImageProperties : this.collapseImageProperties;
   setAttributeIfValueExists(image, "src", props.s);
   setAttributeIfValueExists(image, "alt", props.a);
   setAttributeIfValueExists(image, "title", props.t);
   var styles = {};
   if(ASPx.IsExists(props.so.spriteBackground))
    styles.background = props.so.spriteBackground;
   if(ASPx.IsExists(props.w))
    styles.width = props.w;
   if(ASPx.IsExists(props.h))
    styles.height = props.h;
   if(ASPx.IsExists(props.so.spriteCssClass))
    styles.className = props.so.spriteCssClass;
   ASPx.SetStyles(image, styles);
  },
  GetAnimationWrapper: function () {
   if (this.animationWrapper == null)
    this.animationWrapper = ASPx.GetChildByClassName(this.GetContentElement(), CssClasses.AnimationWrapper);
   return this.animationWrapper;
  },
  GetContentWrapper: function () {
   if (this.contentWrapper == null)
    this.contentWrapper = ASPx.GetNodeByClassName(this.GetContentElement(), CssClasses.ContentWrapper);
   return this.contentWrapper;
  },
  CollapseContent: function() {
   var isVisible = ASPx.IsElementVisible(this.GetMainElement());
   if(this.enableAnimation && isVisible) {
    this.PrepareElementsToCollapseAnimation();
    this.StartAnimation(this.GetAnimationWrapper(), function () {
     this.CompleteCollapsing();
     this.RaiseCollapsedChanged();
    }.aspxBind(this), [{ property: "height", to: 0, from: this.contentHeightBeforeCollapse }]);
   } else
    this.CompleteCollapsing();
  },
  UpdateContentHeightBeforeExpand: function () {
   if (this.enableAnimation) {
    var deltaHeight = this.GetContentWrapper().offsetHeight - this.contentWrapperHeight;
    if (deltaHeight != 0 && (this.contentHeightBeforeCollapse + deltaHeight) > 0)
     this.contentHeightBeforeCollapse += deltaHeight;
   }
  },
  ExpandContent: function () {
   var contentLoadsOnCallback = this.CanPerformLoadContentCallback();
   if (contentLoadsOnCallback)
    this.PerformCallback();
   this.UpdateContentHeightBeforeExpand();
   this.RemoveCollapsedCssClass();
   this.PrepareElementsToExpand();
   if (this.enableAnimation)
    this.StartAnimation(this.GetAnimationWrapper(), function () {
     this.CompleteExpanding();
     if (!contentLoadsOnCallback)
      this.RaiseCollapsedChanged();
    }.aspxBind(this), [{ property: "height", from: 0, to: this.contentHeightBeforeCollapse }]);
  },
  PrepareElementsToCollapseAnimation: function () {
   this.contentHeightBeforeCollapse = this.GetAnimationWrapper().offsetHeight;
   ASPx.Attr.RemoveStyleAttribute(this.GetContentElement(), "height");
   ASPx.ClearHeight(this.GetMainElement());
  },
  GetContentHeight: function () {
   return this.GetContentElement().offsetHeight;
  },
  CompleteCollapsing: function () {
   this.AssignCollapsedStyle();
   if (this.enableAnimation)
    this.contentWrapperHeight = this.GetContentWrapper().offsetHeight;
   this.changeExpandingAccessible(false);
  },
  CompleteExpanding: function () {
   ASPx.ClearHeight(this.GetAnimationWrapper());
   if (this.tableInlineHeight)
    ASPx.SetStyles(this.GetMainElement(), { height: this.tableInlineHeight });
   if (this.contentInlineHeight)
    ASPx.SetStyles(this.GetContentElement(), { height: this.contentInlineHeight });
   this.UpdateContentHeight();
   this.changeExpandingAccessible(true);
  },
  changeExpandingAccessible: function(expanded) {
   var collapseButton = this.GetCollapseButton();
   if(!collapseButton)
    return;
   var link = ASPx.GetNodeByTagName(collapseButton, "A", 0);
   if(link)
    ASPx.Attr.SetAttribute(link, "aria-expanded", expanded ? "true" : "false");
  },
  AssignCollapsedStyle: function () {
   ASPx.AddClassNameToElement(this.GetMainElement(), CssClasses.Collapsed);
   ASPx.SetStyles(this.GetHeaderElement(), this.headerCollapsedBorderSettings);
   this.ChangeSelectStateForCollapseButton();
  },
  PrepareElementsToExpand: function () {
   ASPx.SetStyles(this.GetHeaderElement(), this.headerExpandedBorderSettings);
   this.ChangeSelectStateForCollapseButton();
  },
  RemoveCollapsedCssClass: function () {
   var element = this.GetMainElement();
   var regex = new RegExp("(?:^|\\s)" + CssClasses.Collapsed + "(?!\\S)");
   element.className = element.className.replace(regex, "");
  },
  StartAnimation: function (element, onComplete, propsToAnimate) {
   if (!propsToAnimate || !element)
    return;
   var props = [];
   for (var i = 0; i < propsToAnimate.length; i++) {
    if (propsToAnimate[i].from != propsToAnimate[i].to)
     props.push(propsToAnimate[i]);
   }
   if (props.length == 0)
    return;
   if (props.length == 1) {
    ASPx.AnimationHelper.createAnimationTransition(element, {
     property: props[0].property, unit: "px",
     duration: this.animationDuration, onComplete: onComplete
    }).Start(props[0].from, props[0].to);
   } else {
    var animationProperties = {};
    for (var i = 0; i < props.length; i++)
     animationProperties[props[i].property] = { unit: "px", from: props[i].from, to: props[i].to };
    ASPx.AnimationHelper.createMultipleAnimationTransition(element, {
     duration: this.animationDuration,
     onComplete: onComplete
    }).Start(animationProperties);
   }
  },
  RaiseCollapsedChanged: function () {
   if (!this.CollapsedChanged.IsEmpty())
    this.CollapsedChanged.FireEvent(this);
  },
  RaiseCollapsedChanging: function () {
   if (!this.CollapsedChanging.IsEmpty()) {
    var args = new ASPxClientCancelEventArgs();
    this.CollapsedChanging.FireEvent(this, args);
    return args;
   }
   return null;
  },
  ChangeSelectStateForCollapseButton: function () {
   if (!this.IsStateControllerEnabled() || !this.GetCollapseButton())
    return;
   if (this.GetCollapsed())
    ASPx.GetStateController().SelectElementBySrcElement(this.GetCollapseButton());
   else
    ASPx.GetStateController().DeselectElementBySrcElement(this.GetCollapseButton());
  }
 });
 ASPxClientRoundPanel.Cast = ASPxClientControl.Cast;
 window.ASPxClientRoundPanel = ASPxClientRoundPanel;
})();
(function() {
var MVCxClientRoundPanel = ASPx.CreateClass(ASPxClientRoundPanel, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 PerformCallback: function(data, onSuccess) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientRoundPanel.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, null, this.callbackCustomArgs); }; 
  ASPxClientRoundPanel.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 CreateCallbackCore: function(arg, command, callbackID) {
  if(this.callbackCustomArgs != {})
   window.setTimeout(function () { this.callbackCustomArgs = {}; } .aspxBind(this), 0);
  ASPxClientRoundPanel.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientRoundPanel.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientRoundPanel.prototype.EvalCallbackResult.call(this, resultString);
 }
});
MVCxClientRoundPanel.Cast = ASPxClientControl.Cast;
window.MVCxClientRoundPanel = MVCxClientRoundPanel;
})();

(function () {
 var Constants = {
  TabAction: {
   CLICK: "Click",
   MOUSE_OVER: "MouseOver",
   MOUSE_DOWN: "MouseDown"
  },
  CssClassName: {
   MULTIROW: "dxtc-multiRow",
   INIT_STATE: "dxtc-init",
   STRIP_WRAPPER: "dxtc-wrapper",
   STRIP: "dxtc-strip",
   TAB_ROW: "dxtc-row",
   TAB: "dxtc-tab",
   ACTIVE_TAB: "dxtc-activeTab",
   TAB_LINK: "dxtc-link",
   TAB_IMAGE: "dxtc-img",
   TAB_SPACER: "dxtc-spacer",
   TAB_FILLER: "dxtc-filler",
   LEFT_INDENT: "dxtc-leftIndent",
   RIGHT_INDENT: "dxtc-rightIndent",
   INDENT_TEMPLATE: "dxtc-it",
   TABS_HOLDER: "dxtc-tabs",
   ACTIVE_ROW_ITEM: "dxtc-activeRowItem",
   PINNED_TAB_HEADERS: "dxtc-pth",
   PINNED_STRIP_ITEM: "dxtc-psi",
   LEAD_TAB: "dxtc-lead",
   LAST_TAB: "dxtc-last",
   NEW_LINE_START_TAB: "dxtc-n",
   NEW_LINE_END_TAB: "dxtc-l",
   RIBBON_FILE_TAB: "dxr-fileTab",
   CONTENT: "dxtc-content",
   AUTO_HEIGHT: "dxtc-autoHeight",
   TAB_CONTROL: "dxtcSys",
   DISABLED: "dxtcLiteDisabled"
  }
 };
 var TabControlRenderHelper = ASPx.CreateClass(null, {
  constructor: function(tabControl) {
   this.tabControl = tabControl;
  },
  InitializeControlElements: function () {
   var mainElement = this.tabControl.GetMainElement();
   this.PrepareMainElement(mainElement);
   this.PrepareTabStrip(mainElement);
   this.PrepareContentContainer(mainElement);
  },
  PrepareMainElement: function(mainElement) {
   if(this.IsPercentageSize(mainElement, "width"))
    mainElement.style.overflow = "visible";
  },
  PrepareTabStrip: function(mainElement) {
   var tabStrip = this.GetTabStripElement(mainElement);
   if(tabStrip) {
    tabStrip.id = this.GetID(this.tabControl.GetTabsCellID());
    var hasRibbonTab = ASPx.GetChildNodesByClassName(tabStrip, Constants.CssClassName.RIBBON_FILE_TAB).length > 0;
    var indexCorrection = hasRibbonTab ? 1 : 0;
    this.PrepareElements(tabStrip, this.GetTabElements, this.PrepareTabElement);
    this.PrepareElements(tabStrip, this.GetActiveTabElements, this.PrepareActiveTabElement, indexCorrection);
    this.PrepareElements(tabStrip, this.GetSpacerElements, this.PrepareSpacerElement);
    this.PrepareElements(tabStrip, this.GetTabLinkElements, this.PrepareTabLinkElement);
    this.PrepareElements(tabStrip, this.GetTabImageElements, this.PrepareTabImageElement);
   }
   else
    this.hasTabStrip = false;
   this.tabControl.layoutManager.prepareTabStripForImageLoading();
  },
  PrepareTabElement: function(index, element) {
   var tabIndex = this.FindTabIndexByElementIndex(index);
   element.id = this.GetID(this.tabControl.GetTabElementID(tabIndex, false));
   if(!this.IsTabDisabled(element))
    this.AssignTabActionToElement(element, this.tabControl.getTabActivationHtmlEventName().substring(2),
     this.GetTabElementAction(this.tabControl.name, element, tabIndex));
  },
  AssignTabActionToElement: function(element, eventName, action) {
   ASPx.Evt.AttachEventToElement(element, eventName, action);
  },
  GetTabElementAction: function(name, element, index, preventPostBack) {
   var tabControl = this.tabControl;
   var sendPostBackHandler = function() {
    tabControl.SendPostBack("CLICK:" + index);
   };
   var itemClickHandler = function(e) {
    ASPx.TCTClick(e, name, index);
   };
   var link = ASPx.GetNodeByTagName(element, "A");
   var handler = !preventPostBack && tabControl.autoPostBack && !tabControl.IsClientSideEventsAssigned() && (!link || link.href === "")
    ? sendPostBackHandler
    : itemClickHandler;
   return function(e) {
    if(!element.clientDisabled)
     handler(e);
   };
  },
  PrepareActiveTabElement: function(index, element, indexCorrection) {
   var tabIndex = this.FindActiveTabIndexByElementIndex(index, indexCorrection);
   element.id = this.GetID(this.tabControl.GetTabElementID(tabIndex, true));
   if(!this.IsTabDisabled(element) && !this.tabControl.TabClick.IsEmpty())
    ASPx.Evt.AttachEventToElement(element, this.tabControl.getTabActivationHtmlEventName().substring(2), 
     this.GetTabElementAction(this.tabControl.name, element, tabIndex));
  },
  PrepareSpacerElement: function(index, element) {
   var separatorIndex = this.FindSeparatorIndexByElementIndex(index);
   if(ASPx.IsExists(separatorIndex)) 
    element.id = this.GetID(this.tabControl.GetSeparatorElementID(separatorIndex));
  },
  PrepareTabLinkElement: function(index, element) { 
   element.id = element.parentNode.id + "T"; 
  },
  PrepareTabImageElement: function(index, element) { 
   element.id = element.parentNode.parentNode.id + "Img"; 
  },
  PrepareContentContainer: function(mainElement) {
   var contentContainer = this.GetContentContainerElement(mainElement);
   if(!contentContainer) return;
   this.tabControl.hasContent = true;
   contentContainer.id = this.GetID(this.tabControl.GetContentsCellID());
   this.PrepareElements(contentContainer, this.GetContentElements, this.PrepareContentElement);
   if(!this.tabControl.GetTabsCell() && contentContainer.style.cssText) 
    contentContainer.style.cssText = ASPx.CreateImportantCssText(contentContainer.style.cssText);
  },
  PrepareContentElement: function(index, element) {
   var contentIndex = this.FindContentIndexByElementIndex(index);
   element.id = this.GetID(this.tabControl.GetContentElementID(contentIndex));
  },
  PrepareElements: function(container, getElements, prepareElement, indexCorrection) {
   var elements = getElements.call(this, container);
   for(var i = 0; i < elements.length; i++) {
    prepareElement.call(this, i, elements[i], indexCorrection);
   }
  },
  GetID: function(suffix){
   return this.tabControl.name + suffix;
  },
  IsPercentageSize: function (element, dimension) {
   return ASPx.IsPercentageSize(element.style[dimension]);
  },
  IsTabDisabled: function (element) {
   return ASPx.ElementContainsCssClass(element, Constants.CssClassName.DISABLED);
  },
  FindTabIndexByElementIndex: function (elementIndex) {
   var tabIndex = -1;
   var tabs = this.tabControl.tabs;
   for(var i = 0; i < tabs.length; i++) {
    var tab = tabs[i];
    if(tab.visible)
     tabIndex++;
    if(!this.tabControl.useClientVisibility && tab.clientVisible && i == this.tabControl.activeTabIndex)
     tabIndex--;
    if(tabIndex == elementIndex)
     return i;
   }
  },
  FindActiveTabIndexByElementIndex: function (elementIndex, indexCorrection) {
   if(!this.tabControl.useClientVisibility)
    return this.tabControl.activeTabIndex;
   var tabs = this.tabControl.tabs;
   var tabIndex = -1;
   for(var i = indexCorrection; i < tabs.length; i++) {
    var tab = tabs[i];
    if(tab.visible && tab.enabled)
     tabIndex++;
    if(tabIndex == elementIndex)
     return i;
   }
  },
  FindSeparatorIndexByElementIndex: function(elementIndex) {
   var separatorIndex = -1;
   var tabs = this.tabControl.tabs;
   for(var i = 0; i < tabs.length; i++) {
    var nextIndex = this.tabControl.GetNextVisibleTabIndex(i, true);
    var tab = tabs[i];
    if(tab.visible && nextIndex > -1) {
     if(this.tabControl.IsMultiRow()) {
      var nextTabElement = this.tabControl.GetVisibleTabElement(nextIndex);
      if(!(this.tabControl.isTabElementStartsNewLine(nextTabElement) && !this.tabControl.previousInvisibleTabExist(nextIndex, nextTabElement)))
       separatorIndex++;
     }
     else
      separatorIndex++;
    }
    if(separatorIndex === elementIndex) {
     if(!this.tabControl.enableScrolling || nextIndex > -1)
      return i;
    }
   }
  },
  FindContentIndexByElementIndex: function (elementIndex) {
   if(!this.tabControl.useClientVisibility)
    return this.tabControl.activeTabIndex;
   var tabs = this.tabControl.tabs;
   var tabIndex = -1;
   for(var i = 0; i < tabs.length; i++) {
    var tab = tabs[i];
    if(tab.visible && tab.enabled)
     tabIndex++;
    if(tabIndex == elementIndex)
     return i;
   }
  },
  GetTabStripElement: function(mainElement){
   var tabStrip = null;
   var elements = ASPx.GetChildElementNodes(mainElement);
   var elementCount = elements.length;
   for(var i = 0; i < elementCount; i++) {
    var element = elements[i];
    if(element.tagName == "UL") {
     if(element.className.indexOf(Constants.CssClassName.STRIP_WRAPPER) == -1)
      tabStrip = element;
     else {
      element.id = this.GetID(this.tabControl.GetTabsCellWrapperID());
      tabStrip = ASPx.GetNodeByClassName(element, Constants.CssClassName.STRIP);
     }
     break;
    }
   }
   return tabStrip;
  },
  GetTabElements: function(container) {
   return ASPx.GetNodesByClassName(container, Constants.CssClassName.TAB);
  },
  GetActiveTabElements: function(container) {
   return ASPx.GetNodesByClassName(container, Constants.CssClassName.ACTIVE_TAB);
  },
  GetSpacerElements: function(container) {
   return ASPx.GetNodesByClassName(container, Constants.CssClassName.TAB_SPACER);
  },
  GetTabLinkElements: function(container) {
   return ASPx.GetNodesByClassName(container, Constants.CssClassName.TAB_LINK);
  },
  GetTabImageElements: function(container) {
   return ASPx.GetNodesByClassName(container, Constants.CssClassName.TAB_IMAGE);
  },
  GetContentContainerElement: function(mainElement) {
   return ASPx.GetChildByClassName(mainElement, Constants.CssClassName.CONTENT);
  },
  GetContentElements: function(container) {
   return ASPx.GetChildNodes(container, function (el) { return !!el.tagName; });
  }
 });
 var ASPxClientTabControlBase = ASPx.CreateClass(ASPxClientControl, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
   this.activeTabIndex = 0;
   this.callbackCount = 0;
   this.cookieName = "";
   this.emptyHeight = false;
   this.emptyWidth = false;
   this.tabAlign = "Left";
   this.tabPosition = "Top";
   this.tabAction = Constants.TabAction.CLICK;
   this.tabs = [];
   this.tabsOrderInfo = null;
   this.tabsContentRequest = [];
   this.useClientVisibility = true;
   this.enableScrolling = !!this.GetScrollVisibleArea();
   this.hasScrollButtons = this.enableScrolling && !!this.GetScrollLeftButtonElement();
   this.firstShownTabIndex = 0;
   this.scrollManager = null;
   this.scrollingFillerElementWidth = 5000;
   this.scrollToActiveTab = true;
   this.handleClickOnWholeTab = true;
   this.deferredActions = [];
   this.layoutManager = null;
   this.hasTabStip = true;
   this.hasContent = false;
   this.renderHelper = this.CreateRenderHelper();
   this.isFullyInitializedInline = false;
   this.isFullyInitialized = false;
   this.initializationStepPassed = false;
   this.sizingConfig.correction = true;
   this.sizingConfig.adjustControl = true;
   this.flexEnabled = true;
   this.primaryDimension = "width";
   this.secondaryDimension = "height";
   this.adjustmentVars = { 
    stripLastSize: "",
    tabsLastSize: "",
    indentsSizes: { }, 
    scrolling: { },
    content: { },
    tabs: {
     lastSizes: { }
    }
   };
   this.tabStripImages = [];
   this.tabStripAdjustmentTimerID = -1;
   this.isLoadTabByCallback = false;
   this.isActiveTabChanged = false;
   this.shouldRaiseActiveTabChangedEvent = false;
   this.cacheEnabled = false;
   this.cacheDataFieldName = "aspxCache_CacheData";
   this.tabHeightManager = null;
   this.contentObserving = {
    enabled: false,
    canObserve: false,
    collapsingEnabled: false,
    collapsingTimerID: -1,
    collapsingTimeout: 500,
    collapsingShortTimeout: 100,
    sizeEqualityError: 3,
    timerID: -1,
    timeout: 500
   };
   this.minLeftIndentSizeLite = 0;
   this.minRightIndentSizeLite = 0;
   this.minScrollVisibleAreaSize = 50;
   this.TabClick = new ASPxClientEvent();
   this.ActiveTabChanged = new ASPxClientEvent();
   this.ActiveTabChanging = new ASPxClientEvent();
  },
  SetData: function(data){
   if(data.tabs)
    this.CreateTabs(data.tabs);
  },
  Initialize: function () {
   ASPxClientControl.prototype.Initialize.call(this);
   if(this.IsStateControllerEnabled())
    ASPxClientTabControlBase.PrepareStateController();
   if(this.IsControlVisible()) {
    this.layoutManager.updateTabStripImagesSizes();
    this.InitializeTabControl();
    this.UpdateLayout();
   }
   this.initializationStepPassed = true;
  },
  InlineInitialize: function () {
   ASPxClientControl.prototype.InlineInitialize.call(this);
   this.tabsOrderInfo = this.getTabsOrderInfo();
   this.initializeLayoutManager();
   this.InitializeControlElements();
   var tabsCell = this.GetTabsCell();
   if(tabsCell && this.IsStateControllerEnabled())
    ASPx.AssignAccessibilityEventsToChildrenLinks(tabsCell);
   this.InitializeAccessibleNavigation();
   this.UpdateAdjustmentFlags();
   this.initializeTabHeightManager();
   if(this.enableScrolling) {
    this.InitializeScrolling();
    if(!this.flexEnabled)
     this.initScrollingFixedLayout();
   }
   if(this.IsControlVisible())
    this.InitializeTabControlInline();
  },
  InitializeAccessibleNavigation: function() {
   if(this.accessibilityCompliant)
    ASPxClientTabControlBase.EnsureDocumentKeyDownHandler();
  },
  initializeLayoutManager: function() {
   this.layoutManager = this.flexEnabled ? new FlexLayoutManager(this) : new FixedLayoutManager(this);
  },
  createTabHeightManagerCore: function() {
   if(!(this.GetTabStripContainer() && this.IsTopBottomTabPosition()))
    return new FakeTabHeightManager();
   var elements = this.GetTabsElements(),
    elementCount = elements.length;
   for(var i = 0; i < elementCount; i++) {
    var element = elements[i];
    if(element.style.height)
     return new TabCustomHeightManager(this);
   }
   return new TabDefaultHeightManager(this);
  },
  initializeTabHeightManager: function() {
   this.tabHeightManager = this.layoutManager.createTabHeightManager();
  },
  initScrollingFixedLayout: function() {
   this.GetScrollableArea().style.position = "relative";
   var sva = this.GetScrollVisibleArea();
   sva.style.overflow = "hidden";
   sva.style.position = "relative";
   ASPx.SetElementFloat(sva, this.rtl ? "right" : "left");
  },
  InitializeTabControlInline: function () {
   this.layoutManager.inlineInitialize();
   this.InitializeEnabledAndVisible();
   this.InitializeTabControlCore();
   this.isFullyInitializedInline = true;
  },
  initFixedLayoutInline: function() {
   ASPx.RemoveClassNameFromElement(this.GetMainElement(), Constants.CssClassName.INIT_STATE);
   if(this.GetTabStripContainer()) {
    this.tabHeightManager.initialize();
    this.StoreInitialIndentsSize();
   }
   if(this.enableScrolling) {
    this.GetScrollVisibleArea().style.width = "1px";
    var tabStrip = this.GetTabsCell();
    var tabStripChilds = ASPx.GetChildNodesByTagName(tabStrip, "LI");
    var scrollFiller = tabStripChilds[tabStripChilds.length - 1];
    scrollFiller.style.width = this.scrollingFillerElementWidth + "px";
   }
  },
  InitializeTabControl: function () {
   if(!this.isFullyInitializedInline)
    this.InitializeTabControlInline();
   this.CalculateSizes();
   this.AdjustPageContents();
   this.SubsribeForDomObserver();
   this.isFullyInitialized = true;
  },
  SubsribeForDomObserver: function() {
   this.contentObserving.enabled = this.hasContent && this.layoutManager.isContentObservingEnabled();
   if(!this.contentObserving.enabled)
    return;
   this.contentObserving.collapsingEnabled = this.layoutManager.isCollapsingInObservingEnabled();
   this.EnableContentObservation();
   var callbackFunc = function(element) {
    this.OnContentSizeObserving(element);
   }.aspxBind(this);
   ASPx.GetDomObserver().subscribe(this.name + this.GetContentsCellID(), callbackFunc);
  },
  EnableContentObservation: function() {
   this.layoutManager.enableContentObservation();
   this.contentObserving.canObserve = true;
  },
  OnContentSizeObserving: function(element) {
   if(!this.contentObserving.canObserve || this.IsPartiallyInitialized() || !this.IsAdjustmentAllowed())
    return;
   if(this.contentObserving.collapsingEnabled)
    this.CollapseControl();
   if(this.checkAdjustmentRequired())
    this.layoutManager.adjustSizeOnContentModification();
   else if(this.contentObserving.collapsingEnabled)
    this.ExpandControl();
  },
  checkAdjustmentRequired: function() {
   var sizes = this.GetAdjustedSizes();
   var sizeChanged = this.layoutManager.isAdjustmenRequiredByNewSizes(this.adjustedSizes, sizes, this.contentObserving.sizeEqualityError);
   if(sizeChanged)
    this.adjustedSizes = sizes;
   return sizeChanged;
  },
  areEqualValues: function(val1, val2, error) {
   return val1 == val2 || Math.abs(val1 - val2) <= error;
  },
  SetObservationPaused: function(paused) {
   if(this.contentObserving.enabled) {
    var observer = ASPx.GetDomObserver(),
     contentContainer = this.GetContentsCell();
    if(paused)
     observer.pause(contentContainer, true);
    else
     observer.resume(contentContainer, true);
   }
  },
  IsPartiallyInitialized: function () {
   return !this.isFullyInitialized;
  },
  canUseOffsetSizes: function() {
   return this.isFullyInitialized && this.IsControlVisible();
  },
  EnsureControlInitialized: function () {
   if(this.IsPartiallyInitialized())
    this.InitializeTabControl();
  },
  UpdateStateObject: function(){
   this.UpdateStateObjectWithObject({ activeTabIndex: this.activeTabIndex });
  },
  BrowserWindowResizeSubscriber: function () {
   return this.widthValueSetInPercentage || this.heightValueSetInPercentage || this.IsControlCollapsed();
  },
  OnBrowserWindowResize: function (e) {
   if(!this.IsAdjustmentAllowed()) return;
   if(this.contentObserving.enabled) {
    if(this.contentObserving.timerID !== -1)
     window.clearTimeout(this.contentObserving.timerID);
    this.contentObserving.canObserve = false;
    var enableObservationFunc = function() { this.EnableContentObservation(); }.aspxBind(this);
    this.contentObserving.timerID = window.setTimeout(enableObservationFunc, this.contentObserving.timeout);
   }
   this.AdjustControlCore();
  },
  onFocusedTabKeyDown: function(e) {
   var decreaseKey = this.IsTopBottomTabPosition() ? ASPx.Key.Left : ASPx.Key.Up,
    increaseKey = this.IsTopBottomTabPosition() ? ASPx.Key.Right : ASPx.Key.Down,
    activeIndexDiff = e.keyCode === decreaseKey ? -1 : e.keyCode === increaseKey ? 1 : 0;
   this.switchActiveTab(activeIndexDiff);
  },
  switchActiveTab: function(activeIndexDiff) {
   if(activeIndexDiff === 0) return;
   var newActiveIndex = this.GetActiveTabIndex() + activeIndexDiff,
    tabCount = this.GetTabCount();
   if(newActiveIndex < 0)
    newActiveIndex = tabCount - 1;
   else if(newActiveIndex >= tabCount)
    newActiveIndex = 0;
   this.SetActiveTabIndex(newActiveIndex);
  },
  CanCauseReadjustment: function() {
   return false;
  },
  IsExpandableByAdjustment: function() {
   return true;
  },
  InitializeEnabledAndVisible: function () {
   for(var i = 0; i < this.tabs.length; i++) {
    this.SetTabVisibleCore(i, this.tabs[i].clientVisible, true);
    this.SetTabEnabled(i, this.tabs[i].clientEnabled, true);
   }
  },
  InitializeCallBackData: function () {
   var element = this.getActiveContentElement();
   if(element != null) element.loaded = true;
  },
  InitializeTabControlCore: function () {
   if(this.enableScrolling) {
    this.CalculateSizes();
    if(!this.flexEnabled)
     this.RecalculateTabStripWidthLite();
   }
   else
    this.AdjustTabControlSizeLite();
   if(this.IsMultiRow())
    this.PlaceActiveTabRowToBottom(this.activeTabIndex);
  },
  StoreInitialIndentsSize: function () {
   var leftIndent = this.GetLeftIndentLite(),
    rightIndent = this.GetRightIndentLite();
   if(leftIndent)
    this.minLeftIndentSizeLite = this.GetCachedElementSize(leftIndent);
   if(rightIndent)
    this.minRightIndentSizeLite = this.GetCachedElementSize(rightIndent);
   this.adjustmentVars.indentsSizes = {
    left: this.minLeftIndentSizeLite,
    right: this.minRightIndentSizeLite
   };
  },
  InitializeScrolling: function () {
   this.scrollManager = new TabControlScrollingManager(this, {
    scrollableArea: this.GetScrollableArea(),
    orientation: [1, 0],
    onBeforeScrolling: this.OnBeforeScrolling,
    onAfterScrolling: this.OnAfterScrolling.aspxBind(this),
    forseEmulation: true,
    mouseEventsElement: this.GetScrollVisibleArea(),
    useMarginForPosition: false,
    preventOuterScroll: true,
    handleMouseWheel: !this.scrollButtonsVisible
   });
   this.scrollManager.scrollSessionInterval = 5;
   this.scrollManager.animationAcceleration = 0.5;
   this.scrollManager.getValidNewScrollOffset = this.getValidNewScrollOffset.aspxBind(this);
   this.InitializeScrollButton(this.GetScrollLeftButtonElement());
   this.InitializeScrollButton(this.GetScrollRightButtonElement());
  },
  InitializeScrollButton: function (button) {
   if(!button || !button.id) return;
   var img = ASPx.GetNodeByTagName(button, "IMG", 0);
   if(!img) {
    img = ASPx.GetNodeByTagName(button, "svg", 0);
   }
   ASPx.Evt.PreventElementDrag(img);
   ASPx.Selection.SetElementSelectionEnabled(img, false);
   ASPx.Selection.SetElementSelectionEnabled(button, false);
   var manager = this.scrollManager;
   var dir = button.id.charAt(button.id.length - 1) == "R" ? 1 : -1;
   if(this.enabled) {
    ASPx.Evt.AttachEventToElement(button, ASPx.TouchUIHelper.touchMouseDownEventName, function (e) { manager.StartScrolling(dir, 5, 5); ASPx.Evt.PreventEvent(e); });
    ASPx.Evt.AttachEventToElement(button, ASPx.TouchUIHelper.touchMouseUpEventName, function (e) { manager.StopScrolling(); });
   }
  },
  setMouseScrollEnabled: function(enabled) {
   if(this.scrollManager)
    this.scrollManager.enableMouseScrollInternal = enabled;
  },
  getTabWithSeparatorWidth: function(index) {
   var tab = this.GetVisibleTabElement(index),
    separator = this.GetSeparatorElement(index);
   return this.GetCachedElementSize(tab) + this.GetCachedElementSize(separator);
  },
  ScrollToShowTab: function (tabIndex, doAnimation) {
   if(!this.GetVisibleTabElement(tabIndex))
    return;
   var startIndex = this.firstShownTabIndex;
   var endIndex = tabIndex;
   var scrollToRight = !this.rtl;
   if(tabIndex < this.firstShownTabIndex) {
    startIndex = tabIndex;
    endIndex = this.firstShownTabIndex - 1;
    scrollToRight = !scrollToRight;
   }
   var width = 0;
   var shift = 0;
   var tabCount = 0;
   var scrollVisibleAreaWidth = this.GetScrollVisibleArea().offsetWidth;
   for(var i = startIndex; i <= endIndex; i++)
    width += this.getTabWithSeparatorWidth(i);
   for(var i = startIndex; i <= endIndex; i++) {
    var diff = width - shift;
    if(diff > scrollVisibleAreaWidth || !(scrollToRight ^ this.rtl)) {
     shift += this.getTabWithSeparatorWidth(i);
     tabCount++;
    }
   }
   if(this.GetVisibleTabElement(tabIndex).offsetWidth >= scrollVisibleAreaWidth &&
      scrollToRight ^ this.rtl) {
    tabCount--;
    shift -= this.getTabWithSeparatorWidth(tabIndex);
   }
   if(shift <= 0) return;
   this.firstShownTabIndex += tabCount * (scrollToRight ^ this.rtl ? 1 : -1);
   if(doAnimation) {
    this.scrollManager.animationOffset = this.GetScrollAnimationOffset(this.firstShownTabIndex);
    this.scrollManager.PrepareForScrollAnimation();
    this.scrollManager.DoScrollSessionAnimation(scrollToRight ? -1 : 1);
   } else {
    this.scrollManager.SetScrolledAreaPosition(this.scrollManager.GetScrolledAreaPosition()
     + this.GetScrollAnimationOffset(this.firstShownTabIndex) * (scrollToRight ? -1 : 1));
   }
  },
  OnBeforeScrolling: function (manager, direction) {
   var tc = manager.owner;
   if(tc.IsFullyScrolledToLeft() && direction < 0 || tc.IsFullyScrolledToRight() && direction > 0) {
    manager.StopScrolling();
    return;
   }
   var diff = (direction > 0 ^ tc.rtl) ? 1 : -1;
   do {
    if(tc.firstShownTabIndex <= 0 && diff < 0
    || tc.firstShownTabIndex >= tc.tabs.length - 1 && diff > 0) break;
    tc.firstShownTabIndex += diff;
   } while(!tc.IsTabVisible(tc.firstShownTabIndex));
   manager.animationOffset = tc.GetScrollAnimationOffset(tc.firstShownTabIndex);
  },
  getValidNewScrollOffset: function(newOffset) {
   if(newOffset > 0 && !this.rtl || newOffset < 0 && this.rtl)
    newOffset = 0;
   var minOffset = this.getMaxVisibleOffset() - this.GetScrollableAreaWidth();
   if(!this.rtl && newOffset < minOffset)
    newOffset = minOffset;
   if(this.rtl && newOffset > Math.abs(minOffset))
    newOffset = Math.abs(minOffset);
   var hiddenWidth = Math.abs(newOffset),
    tabsWidth = 0;
   for(var i = 0; hiddenWidth >= tabsWidth && i < this.tabs.length - 1; i++)
    tabsWidth += this.getTabWithSeparatorWidth(i);
   this.firstShownTabIndex = i - 1;
   return newOffset;
  },
  getMaxVisibleOffset: function() {
   var visibleArea = this.GetScrollVisibleArea(),
    maxVisibleRightOffset = this.getRightTemplateOffset();
   for(var i = this.tabs.length - 1; i >= 0; i--) {
    var newWidth = maxVisibleRightOffset + this.getTabWithSeparatorWidth(i);
    if(newWidth > visibleArea.offsetWidth)
     break;
    maxVisibleRightOffset = newWidth;
   }
   return maxVisibleRightOffset;
  },
  getRightTemplateOffset: function() {
   return 0;
  },
  OnAfterScrolling: function(manager, direction) {
   this.focusActiveTab();
   manager.owner.UpdateScrollButtonsEnabled();
  },
  AdjustTabScrolling: function (scrollToActiveTab, doAnimation) {
   this.CalculateSizes();
   this.AdjustTabScrollingCore(scrollToActiveTab, doAnimation);
  },
  AfterInitialize: function() {
   ASPxClientControl.prototype.AfterInitialize.call(this);
   if(this.enableScrolling)
    this.AdjustTabScrollingCore(true, false);
  },
  AdjustTabScrollingCore: function(scrollToActiveTab, doAnimation) {
   if(!this.isInitialized || !this.GetMainElement()) return;
   this.adjustTabStripScrolling(scrollToActiveTab, doAnimation);
   this.AdjustPageContents();
  },
  adjustTabStripScrolling: function(scrollToActiveTab, doAnimation) {
   if(!this.enableScrolling) return;
   this.UpdateScrollButtonsVisible();
   if(scrollToActiveTab)
    this.ScrollToShowTab(this.activeTabIndex, doAnimation);
   if(this.enabled)
    this.UpdateScrollButtonsEnabled();
  },
  GetScrollAnimationOffset: function (newFirstShownTabIndex) {
   var newPos = 0;
   var i = this.GetNextVisibleTabIndex(-1);
   while(i < newFirstShownTabIndex && i > -1) {
    newPos += this.GetVisibleTabElement(i).offsetWidth;
    var separator = this.GetSeparatorElement(i);
    newPos += separator && separator.offsetWidth;
    i = this.GetNextVisibleTabIndex(i);
   }
   if(this.rtl)
    newPos = -newPos;
   return Math.abs(this.scrollManager.GetScrolledAreaPosition() + newPos);
  },
  AdjustScrollVisibleAreaWidth: function () {
   var sva = this.GetScrollVisibleArea();
   var mainElement = this.GetMainElement();
   if((mainElement.style.width == "" || mainElement.style.width == "0px") && !this.GetContentsCell()) {
    ASPx.SetOffsetWidth(sva, this.GetScrollableAreaWidth());
    return;
   }
   ASPx.SetOffsetWidth(sva, this.minScrollVisibleAreaSize);
   var scrollWrapper = this.GetTabsCellWrapperElement();
   var c = ASPx.GetChildElementNodes(scrollWrapper);
   var restWidth = 0;
   for(var i = 0; i < c.length; i++)
    restWidth += c[i].offsetWidth;
   restWidth = restWidth - sva.offsetWidth + this.GetStripContainerBordersPaddingsMarginsWidth();
   var svaWidth = this.adjustmentVars.controlSizes.primary - restWidth;
   ASPx.SetOffsetWidth(sva, svaWidth);
   var scrollWrapperWidth = restWidth + svaWidth;
   ASPx.SetOffsetWidth(scrollWrapper, scrollWrapperWidth);
   this.RecalculateTabStripWidthLite();
  },
  DoSafeScrollPositionOperation: function (func) {
   var lastScrollYPos = ASPx.GetDocumentScrollTop();
   var parent = this.GetMainElement().parentNode;
   var scrollParentYBefore = parent.scrollTop;
   func();
   if(scrollParentYBefore != parent.scrollTop)
    parent.scrollTop = scrollParentYBefore;
   var scrollY = ASPx.GetDocumentScrollTop();
   if(lastScrollYPos != scrollY)
    window.scrollTo(ASPx.GetDocumentScrollLeft(), lastScrollYPos);
  },
  UpdateScrollButtonsEnabled: function () {
   if(!this.IsStateControllerEnabled()) return;
   ASPx.GetStateController().SetElementEnabled(this.GetScrollLeftButtonElement(), !this.IsFullyScrolledToLeft());
   ASPx.GetStateController().SetElementEnabled(this.GetScrollRightButtonElement(), !this.IsFullyScrolledToRight());
  },
  UpdateScrollButtonsVisible: function () {
   this.layoutManager.adjustScrollVisibleAreaWidth();
   var svaWidth = this.GetScrollVisibleArea().offsetWidth;
   var scrollButtonsVisible = svaWidth < this.GetScrollableAreaWidth();
   if(this.hasScrollButtons) {
    ASPx.SetElementDisplay(this.GetScrollLeftButtonContainer(), scrollButtonsVisible);
    ASPx.SetElementDisplay(this.GetScrollRightButtonContainer(), scrollButtonsVisible);
   }
   if(!scrollButtonsVisible)
    this.ScrollToShowTab(0, true);
   this.layoutManager.adjustScrollVisibleAreaWidth();
  },
  GetScrollableAreaWidth: function () {
   return this.layoutManager.getScrollableAreaWidth();
  },
  getScrollableAreaWidthCore: function() {
   return this.GetScrollableArea().offsetWidth - this.scrollingFillerElementWidth;
  },
  IsFullyScrolledToLeft: function () {
   if(!this.rtl)
    return ASPx.PxToInt(this.GetScrollableArea().style.left) >= 0;
   var visibleWidth = this.GetScrollableAreaWidth() - ASPx.PxToInt(this.GetScrollableArea().style.left);
   return visibleWidth <= this.GetScrollVisibleArea().offsetWidth ||
     this.GetNextVisibleTabIndex(this.firstShownTabIndex) < 0;
  },
  IsFullyScrolledToRight: function () {
   if(this.rtl)
    return ASPx.PxToInt(this.GetScrollableArea().style.left) <= 0 || this.GetPrevVisibleTabIndex(this.firstShownTabIndex) < 0;
   var visibleWidth = this.GetScrollableAreaWidth() + ASPx.PxToInt(this.GetScrollableArea().style.left);
   return visibleWidth <= this.GetScrollVisibleArea().offsetWidth ||
     this.GetNextVisibleTabIndex(this.firstShownTabIndex) < 0;
  },
  CorrectTabHeightOnStateChanged: function (element) {
   this.tabHeightManager.correctTabHeightOnStateChanged(element);
  },
  CreateRenderHelper: function() {
   return new TabControlRenderHelper(this);
  },
  IsClientSideEventsAssigned: function() {
   return !this.TabClick.IsEmpty()
    || !this.ActiveTabChanging.IsEmpty()
    || !this.ActiveTabChanged.IsEmpty();
  },
  InitializeControlElements: function () {
   this.renderHelper.InitializeControlElements();
  },
  PrepareTabStripForImageLoading: function() {
   var stripContainer = this.GetTabStripContainer();
   if(stripContainer) {
    var images = ASPx.GetNodes(stripContainer, function(el) { return el.tagName == "IMG"; });
    for(var i = 0; i < images.length; i++) {
     var image = images[i];
     var imageInfo = {
      element: image,
      loaded: false,
      width: 0,
      height: 0
     };
     ASPx.Evt.AttachEventToElement(image, "load", this.GetTabStripImageLoadedHandler(imageInfo));
     this.tabStripImages.push(imageInfo);
    }
   }
  },
  GetTabStripImageLoadedHandler: function(imageInfo) {
   return function() {
    this.OnTabStripImageLoaded(imageInfo);
   }.aspxBind(this);
  },
  OnTabStripImageLoaded: function(imageInfo) {
   if(!(this.isInitialized && this.isFullyInitialized) || imageInfo.loaded) return;
   imageInfo.loaded = true;
   var imageWidth = imageInfo.element.offsetWidth,
    imageHeight = imageInfo.element.offsetHeight,
    imageSizeChanged = imageWidth !== imageInfo.width || imageHeight !== imageInfo.height;
   if(imageSizeChanged && this.tabStripAdjustmentTimerID === -1) {
    this.tabStripAdjustmentTimerID = window.setTimeout(function() {
     this.tabStripAdjustmentTimerID = -1;
     this.adjustControlInternal();
    }.aspxBind(this), 0);
   }
   imageInfo.width = imageWidth;
   imageInfo.height = imageHeight;
  },
  UpdateTabStripImagesSizes: function() {
   for(var i = 0; i < this.tabStripImages.length; i++) {
    var imageInfo = this.tabStripImages[i];
    imageInfo.width = imageInfo.element.offsetWidth;
    imageInfo.height = imageInfo.element.offsetHeight;
   }
  },
  AdjustTabContents: function() {
   this.CorrectWrappedText(this.GetTabLinkElements);
  },
  GetTabLinkElements: function () {
   var container = this.GetTabStripContainer();
   if(container)
    return ASPx.GetNodesByClassName(container, Constants.CssClassName.TAB_LINK);
   return null;
  },
  GetCachedBordersPaddingsMarginsWidth: function(element, dimension) {
   if(!dimension)
    dimension = this.primaryDimension;
   var cache = this.GetOrCreateElementCache(element);
   return dimension == "width" ? cache.horizontalBordersPaddingsMarginsWidth : cache.verticalBordersPaddingsMarginsWidth;
  },
  GetCachedBordersAndPaddingsWidth: function(element, dimension) {
   if(!dimension)
    dimension = this.primaryDimension;
   var cache = this.GetOrCreateElementCache(element);
   return dimension == "width" ? cache.horizontalBordersAndPaddingsWidth : cache.verticalBordersAndPaddingsWidth;
  },
  GetCachedVerticalBordersPaddingsMarginsWidth: function(element) {
   var cache = this.GetOrCreateElementCache(element);
   return cache.verticalBordersPaddingsMarginsWidth;
  },
  GetCachedHorizontalBordersPaddingsMarginsWidth: function(element) {
   var cache = this.GetOrCreateElementCache(element);
   return cache.horizontalBordersPaddingsMarginsWidth;
  },
  GetCachedVerticalBordersAndPaddingsWidth: function(element) {
   var cache = this.GetOrCreateElementCache(element);
   return cache.verticalBordersAndPaddingsWidth;
  },
  GetCachedHorizontalBordersAndPaddingsWidth: function(element) {
   var cache = this.GetOrCreateElementCache(element);
   return cache.horizontalBordersAndPaddingsWidth;
  },
  GetCachedElementInnerSize: function(element, dimension) {
   if(!element) return 0;
   if(!dimension)
    dimension = this.primaryDimension;
   var cache = this.GetOrCreateElementCache(element);
   return dimension === "width" ? cache.width : cache.height;
  },
  GetCachedElementSize: function(element, dimension) {
   if(!element) return 0;
   if(!dimension)
    dimension = this.primaryDimension;
   var cache = this.GetOrCreateElementCache(element);
   if(!cache.display)
    return 0;
   return dimension === "width" ? cache.outerWidth : cache.outerHeight;
  },
  GetElementCurrentStyle: function(element) {
   var style = element.currentStyle;
   if(style)
    return window.getComputedStyle ? window.getComputedStyle(element, null) : style;
   else
    return ASPx.GetCurrentStyle(element);
  },
  CacheElement: function(element) {
   var cache = { },
    style = this.GetElementCurrentStyle(element);
   var useOffsetSizes = style.height == "auto";
   cache.borderLeftWidth = style.borderLeftStyle != "none" ? ASPx.PxToFloat(style.borderLeftWidth) : 0;
   cache.borderRightWidth = style.borderRightStyle != "none" ? ASPx.PxToFloat(style.borderRightWidth) : 0;
   cache.borderTopWidth = style.borderTopStyle != "none" ? ASPx.PxToFloat(style.borderTopWidth) : 0;
   cache.borderBottomWidth = style.borderBottomStyle != "none" ? ASPx.PxToFloat(style.borderBottomWidth) : 0;
   cache.paddingLeft = ASPx.PxToFloat(style.paddingLeft);
   cache.paddingRight = ASPx.PxToFloat(style.paddingRight);
   cache.paddingTop = ASPx.PxToFloat(style.paddingTop);
   cache.paddingBottom = ASPx.PxToFloat(style.paddingBottom);
   cache.marginLeft = ASPx.PxToFloat(style.marginLeft);
   cache.marginRight = ASPx.PxToFloat(style.marginRight);
   cache.marginTop = ASPx.PxToFloat(style.marginTop);
   cache.marginBottom = ASPx.PxToFloat(style.marginBottom);
   cache.horizontalBordersAndPaddingsWidth = cache.borderLeftWidth + cache.borderRightWidth + cache.paddingLeft + cache.paddingRight;
   cache.verticalBordersAndPaddingsWidth = cache.borderTopWidth + cache.borderBottomWidth + cache.paddingTop + cache.paddingBottom;
   cache.horizontalMarginsWidth = cache.marginLeft + cache.marginRight;
   cache.verticalMarginsWidth = cache.marginTop + cache.marginBottom;
   cache.horizontalBordersPaddingsMarginsWidth = cache.horizontalBordersAndPaddingsWidth + cache.horizontalMarginsWidth;
   cache.verticalBordersPaddingsMarginsWidth = cache.verticalBordersAndPaddingsWidth + cache.verticalMarginsWidth;
   if(useOffsetSizes) {
    cache.width = element.offsetWidth - cache.horizontalBordersAndPaddingsWidth;
    cache.height = element.offsetHeight - cache.verticalBordersAndPaddingsWidth;
   }
   else {
    cache.width = ASPx.PxToFloat(style.width);
    cache.height = ASPx.PxToFloat(style.height);
   }
   cache.offsetWidth = cache.width + cache.horizontalBordersAndPaddingsWidth;
   cache.offsetHeight = cache.height + cache.verticalBordersAndPaddingsWidth;
   cache.outerWidth = cache.width + cache.horizontalBordersPaddingsMarginsWidth;
   cache.outerHeight = cache.height + cache.verticalBordersPaddingsMarginsWidth;
   cache.display = ASPx.GetElementDisplay(element);
   cache.needRefresh = !(ASPx.documentLoaded && cache.display);
   element[this.cacheDataFieldName] = cache;
  },
  GetElementCache: function(element) {
   return element[this.cacheDataFieldName];
  },
  GetOrCreateElementCache: function(element) {
   this.EnsureElementCached(element);
   return this.GetElementCache(element);
  },
  EnsureElementCached: function(element) {
   var cache = this.GetElementCache(element);
   if(!this.cacheEnabled || this.UseProportionalTabSizes() || !cache || cache.needRefresh)
    this.CacheElement(element);
  },
  ClearElementCache: function(element) {
   if(element)
    element[this.cacheDataFieldName] = null;
  },
  ClearTabElementsCache: function(index) {
   var activeTabElement = this.GetTabElement(index, true),
    tabElement = this.GetTabElement(index, false);
   if(activeTabElement)
    this.ClearElementCache(activeTabElement);
   if(tabElement)
    this.ClearElementCache(tabElement);
   this.tabHeightManager.requestAdjustment();
  },
  CollapseControl: function() {
   if(!this.NeedCollapseControlCore() || this.IsPartiallyInitialized()) return;
   this.isControlCollapsed = true;
   this.layoutManager.collapseTabStrip();
   if(this.adjustmentVars.content.needCollapsing) {
    this.SetObservationPaused(true);
    var contentHolder = this.getActiveContentHolder();
    if(contentHolder) {
     this.adjustmentVars.content.lastHeight = contentHolder.style.height;
     contentHolder.style.height = "";
    }
    this.SetObservationPaused(false);
   }
  },
  collapseTabStrip: function() {
   if(this.enableScrolling)
    this.CollapseTabScrolling();
   else
    this.CollapseControlCommon();
  },
  CollapseControlCommon: function() {
   var stripContainer = this.GetTabStripContainer(),
    leftIndent = this.GetLeftIndentLite(),
    rightIndent = this.GetRightIndentLite();
   if(!stripContainer) return;
   this.adjustmentVars.indentsSizes.leftLastSize = leftIndent.style[this.primaryDimension];
   this.adjustmentVars.indentsSizes.rightLastSize = rightIndent.style[this.primaryDimension];
   this.adjustmentVars.stripLastSize = stripContainer.style[this.primaryDimension];
   if(this.IsMultiRow()) {
    var tabsHolder = this.getTabsHolderElement();
    this.adjustmentVars.tabsLastSize = tabsHolder.style[this.primaryDimension];
   }
   if(this.UseProportionalTabSizes())
    this.CollapseTabSizes();
   this.SetCachedElementSize(leftIndent, this.minLeftIndentSizeLite);
   this.SetCachedElementSize(rightIndent, this.minRightIndentSizeLite);
   this.RecalculateTabStripWidthLite(this.GetStripSizeLite(), this.minLeftIndentSizeLite, this.minRightIndentSizeLite);
  },
  CollapseTabSizes: function() {
   this.adjustmentVars.tabs.lastSizes = { };
   var tabElements = this.GetTabsElements();
   for(var i = 0, count = tabElements.length; i < count; i++) {
    var tabElement = tabElements[i];
    this.adjustmentVars.tabs.lastSizes[tabElement.id] = tabElement.style.width;
    tabElement.style.width = "";
   }
  },
  CollapseTabScrolling: function() {
   var scrollWrapper = this.GetTabsCellWrapperElement(),
    sva = this.GetScrollVisibleArea();
   if(!scrollWrapper) return;
   this.adjustmentVars.scrolling.svaLastWidth = sva.style.width;
   this.adjustmentVars.scrolling.wrapperLastWidth = scrollWrapper.style.width;
   var mainElement = this.GetMainElement();
   if((mainElement.style.width == "" || mainElement.style.width == "0px") && !this.GetContentsCell()) {
    ASPx.SetOffsetWidth(sva, this.GetScrollableAreaWidth());
    return;
   }
   ASPx.SetOffsetWidth(sva, this.minScrollVisibleAreaSize);
   var c = ASPx.GetChildElementNodes(scrollWrapper),
    scrollWrapperWidth = 0;
   for(var i = 0; i < c.length; i++)
    scrollWrapperWidth += c[i].offsetWidth;
   scrollWrapper.style.width = scrollWrapperWidth + "px";
  },
  ExpandControl: function() {
   if(!this.NeedCollapseControlCore())
    return;
   this.isControlCollapsed = false;
   this.layoutManager.expandTabStrip();
   if(this.adjustmentVars.content.needCollapsing) {
    this.SetObservationPaused(true);
    var contentHolder = this.getActiveContentHolder();
    contentHolder.style.height = this.adjustmentVars.content.lastHeight;
    this.SetObservationPaused(false);
   }
  },
  expandTabStrip: function() {
   if(this.enableScrolling)
    this.ExpandTabScrolling();
   else
    this.ExpandControlCommon();
  },
  ExpandControlCommon: function() {
   var stripContainer = this.GetTabStripContainer();
   if(!stripContainer)
    return;
   var leftIndent = this.GetLeftIndentLite(),
    rightIndent = this.GetRightIndentLite();
   leftIndent.style[this.primaryDimension] = this.adjustmentVars.indentsSizes.leftLastSize;
   rightIndent.style[this.primaryDimension] = this.adjustmentVars.indentsSizes.rightLastSize;
   if(this.IsTopBottomTabPosition()) {
    stripContainer.style.width = this.adjustmentVars.stripLastSize;
    if(this.IsMultiRow()) {
     var tabsHolder = this.getTabsHolderElement();
     tabsHolder.style.width = this.adjustmentVars.tabsLastSize;
    }
    if(this.UseProportionalTabSizes())
     this.ExpandTabSizes();
   }
  },
  ExpandTabScrolling: function() {
   var sva = this.GetScrollVisibleArea(),
    scrollWrapper = this.GetTabsCellWrapperElement();
   if(!scrollWrapper) return;
   sva.style.width = this.adjustmentVars.scrolling.svaLastWidth;
   scrollWrapper.style.width = this.adjustmentVars.scrolling.wrapperLastWidth;
  },
  ExpandTabSizes: function() {
   var tabElements = this.GetTabsElements();
   for(var i = 0, count = tabElements.length; i < count; i++) {
    var tabElement = tabElements[i];
    tabElement.style.width = this.adjustmentVars.tabs.lastSizes[tabElement.id];
   }
  },
  NeedCollapseControlCore: function () {
   return this.layoutManager.needCollapseControl();
  },
  CalculateSizes: function() {
   this.layoutManager.calculateSizes();
  },
  calculateSizesCore: function () {
   this.updateContentAdjustmentFlags();
   this.tabHeightManager.adjustTabs();
   if(!this.isControlCollapsed)
    this.CollapseControl();
   this.isControlCollapsed = false;
   this.adjustmentVars.stripSizes = { };
   this.UpdateStripSizes(this.GetStripSizeLite(this.UseProportionalTabSizes()));
   this.AdjustTabStripHeight();
   this.calculateMainElementSizes();
   this.adjustmentVars.controlSizes = {};
   this.adjustmentVars.controlSizes.primary = this.GetMaxValueExtended(
    this.enableScrolling ? this.minScrollVisibleAreaSize : this.adjustmentVars.stripFullSize,
    this.adjustmentVars.mainElementSizes.primary);
   this.adjustmentVars.controlSizes.secondary = this.adjustmentVars.mainElementSizes.secondary;
   this.CalculateContentHeight();
  },
  AdjustTabStripHeight: function() {
   if(!this.tabHeightManager.needAdjustTabStrip())
    return;
   var stripContainer = this.GetTabStripContainer();
   var height = this.tabHeightManager.getTabStripHeight();
   this.adjustmentVars.stripSizes.secondary = height;
   height = this.GetPreparedSizeValue(height);
   height = height > 0 ? height : 0;
   stripContainer.style.height = height + "px";
  },
  calculateMainElementSizes: function() {
   var mainElement = this.GetMainElement();
   this.ClearElementCache(mainElement);
   var cache = this.GetOrCreateElementCache(mainElement);
   this.adjustmentVars.mainElementCache = cache;
   this.adjustmentVars.mainElementSizes = {
    primary: cache[this.primaryDimension],
    secondary: cache[this.secondaryDimension]
   };
  },
  updateContentAdjustmentFlags: function() {
   var contentInfo = this.adjustmentVars.content;
   contentInfo.needAdjustment = this.hasContent && this.layoutManager.isContentAdjustmentRequired();
   contentInfo.needCollapsing = contentInfo.needAdjustment && this.layoutManager.isContentCollapsingRequired();
  },
  CalculateContentHeight: function() {
   if(!this.adjustmentVars.content.needAdjustment) return;
   var mainElement = this.GetMainElement();
   var hasFixedHeight = !this.emptyHeight && !this.heightValueSetInPercentage;
   var contentHeight = 0,
    controlHeight = 0;
   if(hasFixedHeight)
    controlHeight = ASPx.PxToFloat(mainElement.style.height);
   else if(this.IsTopBottomTabPosition())
    controlHeight = this.adjustmentVars.controlSizes.secondary;
   else
    controlHeight = this.adjustmentVars.controlSizes.primary;
   if(this.IsTopBottomTabPosition()) {
    var stripContainer = this.GetTabStripContainer();
    var stripHeight = 0;
    if(stripContainer)
     stripHeight = this.adjustmentVars.stripSizes.secondary + this.GetCachedBordersPaddingsMarginsWidth(stripContainer, "height");
    contentHeight = controlHeight - stripHeight;
   }
   else
    contentHeight = controlHeight;
   this.adjustmentVars.content.height = contentHeight;
  },
  UpdateStripSizes: function(primarySize) {
   this.adjustmentVars.stripSizes.primary = primarySize;
   if(!this.enableScrolling)
    this.adjustmentVars.stripFullSize = this.adjustmentVars.stripSizes.primary + this.minLeftIndentSizeLite + this.minRightIndentSizeLite;
  },
  AdjustPageContents: function () {
   if(!(this.adjustmentVars.content.needAdjustment)) return;
   var contentContainer = this.GetContentsCell(),
    contentHolder = this.getActiveContentHolder();
   var contentInnerHeight = this.adjustmentVars.content.height - this.GetCachedVerticalBordersPaddingsMarginsWidth(contentContainer);
   if(contentHolder)
    contentHolder.style.height = contentInnerHeight + "px";
  },
  UpdateAdjustmentFlags: function () {
   var mainElement = this.GetMainElement();
   if(mainElement) {
    this.UpdatePercentSizeConfig([mainElement.style.width], [mainElement.style.height]);
    if(!this.IsTopBottomTabPosition()) {
     this.primaryDimension = "height";
     this.secondaryDimension = "width";
    }
   }
  },
  GetMaxValue: function (val1, val2) {
   return val1 > val2 ? val1 : val2;
  },
  GetMaxValueExtended: function (val1, val2, val3) {
   var ret = 0;
   for(var i = 0; i < arguments.length; i++) {
    if(arguments[i] > ret)
     ret = arguments[i];
   }
   return ret;
  },
  AdjustTabControlSizeLite: function() {
   this.layoutManager.adjustSize();
  },
  adjustTabControlSizeCore: function () {
   this.CalculateSizes();
   if(!this.GetTabsCell()) {
    this.AdjustPageContents();
    return;
   }
   var controlSize = this.adjustmentVars.controlSizes.primary;
   var tabsSize = this.adjustmentVars.stripSizes.primary;
   var indentsSize = controlSize - tabsSize - this.GetStripContainerBordersPaddingsMarginsWidth();
   this.ClearElementCache(this.GetLeftIndentLite());
   this.ClearElementCache(this.GetRightIndentLite());
   switch(this.tabAlign) {
    case "Left":
     var leftIndentSize = this.GetCachedElementSize(this.GetLeftIndentLite());
     indentsSize = indentsSize - leftIndentSize;
     this.adjustmentVars.indentsSizes = {
      left: leftIndentSize,
      right: this.GetMaxValue(indentsSize, this.minRightIndentSizeLite)
     };
     this.SetCachedElementSize(this.GetRightIndentLite(), this.adjustmentVars.indentsSizes.right);
     break;
    case "Right":
     var rightIndentSize = this.GetCachedElementSize(this.GetRightIndentLite());
     indentsSize = indentsSize - rightIndentSize;
     this.adjustmentVars.indentsSizes = {
      left: this.GetMaxValue(indentsSize, this.minLeftIndentSizeLite),
      right: rightIndentSize
     };
     this.SetCachedElementSize(this.GetLeftIndentLite(), this.adjustmentVars.indentsSizes.left);
     break;
    case "Center":
     indentsSize = Math.floor(indentsSize / 2);
     this.adjustmentVars.indentsSizes.left = this.GetMaxValue(indentsSize, this.minLeftIndentSizeLite);
     this.SetCachedElementSize(this.GetLeftIndentLite(), this.adjustmentVars.indentsSizes.left);
     indentsSize = controlSize - (tabsSize + indentsSize) - this.GetStripContainerBordersPaddingsMarginsWidth();
     this.adjustmentVars.indentsSizes.right = this.GetMaxValue(indentsSize, this.minRightIndentSizeLite);
     this.SetCachedElementSize(this.GetRightIndentLite(), this.adjustmentVars.indentsSizes.right);
     break;
    default:
     indentsSize = this.GetCachedElementSize(this.GetLeftIndentLite()) + this.GetCachedElementSize(this.GetRightIndentLite());
     tabsSize = controlSize - indentsSize;
   }
   if(this.UseProportionalTabSizes()) {
    this.SetStripSizeLite(tabsSize);
    this.UpdateStripSizes(tabsSize);
   }
   this.RecalculateTabStripWidthLite();
   this.AdjustPageContents();
  },
  GetStripContainerBordersPaddingsMarginsWidth: function() {
   if(this.IsTopBottomTabPosition() && !this.enableScrolling)
    return this.GetCachedHorizontalBordersPaddingsMarginsWidth(this.GetTabsCell());
   if(this.enableScrolling)
    return this.GetCachedHorizontalBordersPaddingsMarginsWidth(this.GetScrollVisibleArea().parentNode);
   return this.GetCachedVerticalBordersPaddingsMarginsWidth(this.GetTabsCell());
  },
  GetStripSizeLite: function (storeTabSizes) {
   if(!this.GetTabStripContainer())
    return 0;
   if(storeTabSizes) {
    this.adjustmentVars.tabSizes = {};
    this.adjustmentVars.tabSizesSums = {};
   }
   var size = 0,
    prevSize = 0,
    tab,
    rowIndex = this.IsMultiRow() ? -1 : 0;
   for(var i = 0; i < this.tabs.length; i++) {
    tab = this.GetVisibleTabElement(i);
    if(!tab)
     continue;
    if(this.isTabElementStartsNewLine(tab)) {
     rowIndex++;
     if(prevSize < size)
      prevSize = size;
     size = 0;
    }
    if(!this.GetTab(i).clientVisible)
     continue;
    var tabSize = this.GetCachedElementSize(tab, this.primaryDimension);
    if(storeTabSizes) {
     this.adjustmentVars.tabSizes[i] = tabSize;
     var tabSizesSums = this.adjustmentVars.tabSizesSums;
     if(!ASPx.IsExists(tabSizesSums[rowIndex]))
      tabSizesSums[rowIndex] = 0;
     tabSizesSums[rowIndex] += tabSize;
    }
    var separator = this.GetSeparatorElement(i);
    size += tabSize + this.GetCachedElementSize(separator, this.primaryDimension);
   }
   if(prevSize > size)
    size = prevSize;
   return size;
  },
  GetTabRows: function() {
   var rows = [],
    tabLines = this.getTabLines();
   for(var rowIndex = 0, tabLine; tabLine = tabLines[rowIndex]; rowIndex++) {
    var row = [];
    rows.push(row);
    for(var tabIndex = 0, tab; tab = tabLine[tabIndex]; tabIndex++) {
     if(tab.GetVisible())
      row.push(tab.index);
    }
   }
   return rows;
  },
  SetStripSizeLite: function (size) {
   var spacerSize = this.GetTabSpaceSizeLite(),
    rows = this.GetTabRows();
   for(var i = 0; i < rows.length; i++) {
    var row = rows[i],
     count = row.length,
     rowSize = size - spacerSize * (count - 1),
     newTabSizesSum = 0;
    for(var index = 0; index < count; index++) {
     var tabIndex = row[index],
      tabSize = this.adjustmentVars.tabSizes[tabIndex],
      newTabSizePrecise = rowSize * (tabSize / this.adjustmentVars.tabSizesSums[i]),
      newTabSize = this.GetPreparedSizeValue(newTabSizePrecise);
     newTabSizesSum += newTabSize;
     if(index == count - 1)
      newTabSize += rowSize - newTabSizesSum;
     var activeTabElement = this.GetTabElement(tabIndex, true),
      tabElement = this.GetTabElement(tabIndex, false);
     this.SetCachedElementSize(activeTabElement, newTabSize);
     this.SetCachedElementSize(tabElement, newTabSize);
     this.ClearElementCache(activeTabElement);
     this.ClearElementCache(tabElement);
    }
   }
  },
  getTabSpacerElement: function() {
   var spacerClassName = Constants.CssClassName.TAB_SPACER;
   if(this.IsMultiRow()) {
    var tabsHolder = this.getTabsHolderElement(),
     collection = ASPx.GetNodesByClassName(tabsHolder, spacerClassName);
    if(collection && collection.length > 0) {
     var len = collection.length;
     while(len--)
      if(ASPx.GetElementDisplay(collection[len]))
       return collection[len];
     return collection[0];
    }
    return null;
   }
   return ASPx.GetChildByClassName(this.GetTabsCell(), spacerClassName);
  },
  GetTabSpaceSizeLite: function() {
   var spacer = this.getTabSpacerElement();
   return spacer ? this.GetCachedElementSize(spacer) : 0;
  },
  RecalculateTabStripWidthLite: function(stripSize, leftIndentSize, rightIndentSize) {
   if(!this.IsTopBottomTabPosition())
    return;
   if(stripSize === undefined)
    stripSize = this.adjustmentVars.stripSizes.primary;
   if(leftIndentSize === undefined)
    leftIndentSize = this.adjustmentVars.indentsSizes.left;
   if(rightIndentSize === undefined)
    rightIndentSize = this.adjustmentVars.indentsSizes.right;
   if(this.IsMultiRow())
    stripSize = this.GetPreparedSizeValue(stripSize);
   var tabStrip = this.GetTabsCell(),
    tabStripActualWidth = stripSize + leftIndentSize + rightIndentSize;
   if(this.enableScrolling)
    tabStripActualWidth += this.scrollingFillerElementWidth;
   tabStripActualWidth = this.GetPreparedSizeValue(tabStripActualWidth, true);
   tabStrip.style.width = tabStripActualWidth + "px";
   if(this.IsMultiRow()) {
    var tabsHolder = this.getTabsHolderElement();
    tabsHolder.style.width = stripSize + "px";
   }
  },
  GetPreparedSizeValue: function(sizeValue, reserve) {
   if(!(ASPx.Browser.Chrome && ASPx.Browser.MajorVersion >= 45))
    return sizeValue;
   if(ASPx.Browser.Chrome)
    return +(Math.ceil(sizeValue + "e+2") + "e-2");
   if(ASPx.Browser.MajorVersion == 10 && reserve)
    return sizeValue + 0.1;
   var res = Math.floor(sizeValue);
   while(res < sizeValue)
    res += 0.1;
   return res;
  },
  SetCachedElementSize: function(element, size, dimension) {
   this.SetCachedElementSizeCore(element, size, dimension, "SetCachedElement");
  },
  SetCachedElementSizeCore: function(element, size, dimension, funcNamePrefix) {
   if(!element) return;
   if(!dimension)
    dimension = this.primaryDimension;
   var funcName = funcNamePrefix + (dimension == "width" ? "Width" : "Height");
   this[funcName](element, size);
  },
  SetCachedElementWidth: function(element, width) {
   var cache = this.GetOrCreateElementCache(element);
   this.SetElementSize(element, width, cache.horizontalBordersPaddingsMarginsWidth, "width");
  },
  SetCachedElementHeight: function(element, height) {
   var cache = this.GetOrCreateElementCache(element);
   this.SetElementSize(element, height, cache.verticalBordersPaddingsMarginsWidth, "height");
  },
  SetCachedElementOffsetSize: function(element, size, dimension) {
   this.SetCachedElementSizeCore(element, size, dimension, "SetCachedElementOffset");
  },
  SetCachedElementOffsetWidth: function(element, width) {
   var cache = this.GetOrCreateElementCache(element);
   this.SetElementSize(element, width, cache.horizontalBordersAndPaddingsWidth, "width");
  },
  SetCachedElementOffsetHeight: function(element, height) {
   var cache = this.GetOrCreateElementCache(element);
   this.SetElementSize(element, height, cache.verticalBordersAndPaddingsWidth, "height");
  },
  SetElementSize: function(element, value, correction, dimension) {
   value -= correction;
   if(value >= 0)
    element.style[dimension] = value + "px";
  },
  GetLeftIndentLite: function () {
   var container = this.GetTabStripContainer();
   return container
    ? ASPx.GetNodesByPartialClassName(container, Constants.CssClassName.LEFT_INDENT)[0]
    : null;
  },
  GetRightIndentLite: function () {
   var container = this.GetTabStripContainer();
   return container
    ? ASPx.GetNodesByPartialClassName(container, Constants.CssClassName.RIGHT_INDENT)[0]
    : null;
  },
  GetTabsCellID: function () {
   return "_TC";
  },
  GetTabsCell: function () {
   return this.GetChildElement(this.GetTabsCellID());
  },
  GetTabsCellWrapperID: function () {
   return "_WC";
  },
  GetTabsCellWrapperElement: function () {
   return this.GetChildElement(this.GetTabsCellWrapperID());
  },
  GetTabStripContainer: function () {
   return this.enableScrolling ? this.GetTabsCellWrapperElement() : this.GetTabsCell();
  },
  GetTabElementID: function (index, active) {
   return "_" + (active ? "A" : "") + "T" + index;
  },
  GetTabElement: function (index, active) {
   return this.GetChildElement(this.GetTabElementID(index, active));
  },
  GetTabsElements: function() {
   var tabsCell = this.GetTabsCell();
   if(!tabsCell)
    return [];
   var getNodesFunc = this.IsMultiRow() ? ASPx.GetNodes : ASPx.GetChildNodes;
   return getNodesFunc(tabsCell, function(el) {
    return el.tagName === "LI" && el.className && this.isTabElement(el);
   }.aspxBind(this));
  },
  GetTabInsideElement: function (index, isActive, insideClassName) {
   var tabElement = this.GetTabElement(index, isActive);
   if(!tabElement)
    return null;
   var c = ASPx.GetNodesByClassName(tabElement, insideClassName);
   return null || (c.length > 0 && c[0]);
  },
  GetTabLinkElement: function (index, active) {
   return this.GetTabInsideElement(index, active, Constants.CssClassName.TAB_LINK);
  },
  GetTabTextElement: function (index, active) {
   return this.GetTabLinkElement(index, active);
  },
  GetTabImageElement: function (index, active) {
   return this.GetTabInsideElement(index, active, Constants.CssClassName.TAB_IMAGE);
  },
  GetVisibleTabElement: function (index) {
   return this.GetChildElement(this.GetTabElementID(index, index == this.activeTabIndex));
  },
  GetContentsCellID: function () {
   return "_CC";
  },
  GetContentsCell: function () {
   return this.GetChildElement(this.GetContentsCellID());
  },
  GetContentElementID: function (index) {
   return "_C" + index;
  },
  GetContentElement: function (index) {
   return this.GetChildElement(this.GetContentElementID(index));
  },
  getActiveContentElement: function() {
   return this.GetContentElement(this.activeTabIndex);
  },
  GetContentHolder: function (index) {
   var contentElement = this.GetContentElement(index);
   if(!contentElement)
    return null;
   return ASPx.GetChildByTagName(contentElement, "DIV");
  },
  getActiveContentHolder: function() {
   return this.GetContentHolder(this.activeTabIndex);
  },
  GetSeparatorElementID: function (index) {
   return "_T" + index + "S";
  },
  GetSeparatorElement: function (index) {
   return this.GetChildElement(this.GetSeparatorElementID(index));
  },
  GetScrollVisibleAreaID: function () {
   return "_SVA";
  },
  GetScrollVisibleArea: function () {
   return this.GetChildElement(this.GetScrollVisibleAreaID());
  },
  GetScrollableArea: function () {
   return this.GetTabsCell();
  },
  GetScrollLeftButtonID: function () {
   return "_SBL";
  },
  GetScrollLeftButtonElement: function () {
   return this.GetChildElement(this.GetScrollLeftButtonID());
  },
  GetScrollLeftButtonContainer: function () {
   return this.GetScrollLeftButtonElement().parentNode;
  },
  GetScrollRightButtonID: function () {
   return "_SBR";
  },
  GetScrollRightButtonElement: function () {
   return this.GetChildElement(this.GetScrollRightButtonID());
  },
  GetScrollRightButtonContainer: function () {
   return this.GetScrollRightButtonElement().parentNode;
  },
  IsTopBottomTabPosition: function () {
   return (this.tabPosition == "Top" || this.tabPosition == "Bottom");
  },
  getAreAllTabsHidden: function() {
   return this.GetNextVisibleTabIndex(-1) === -1;
  },
  isInsideVisibleContainer: function() {
   return this.IsDisplayed() && !this.IsHidden();
  },
  IsControlVisible: function() {
   return this.clientVisible && !this.getAreAllTabsHidden() && this.isInsideVisibleContainer();
  },
  isTabElement: function(element) {
   return ASPx.ElementHasCssClass(element, Constants.CssClassName.TAB)
    || ASPx.ElementHasCssClass(element, Constants.CssClassName.ACTIVE_TAB);
  },
  isTemplateIndentElement: function(element) {
   return ASPx.ElementHasCssClass(element, Constants.CssClassName.INDENT_TEMPLATE);
  },
  isTabElementStartsNewLine: function(element) {
   return ASPx.ElementHasCssClass(element, Constants.CssClassName.NEW_LINE_START_TAB);
  },
  previousInvisibleTabExist: function(index, element){
   var parentElement = element.parentNode;
   if(parentElement.firstChild == element)
    return false;
   while(index--) {
    var tabElement = this.GetVisibleTabElement(index);
    if(tabElement && tabElement.parentNode == parentElement)
     return true;
   }
   return false;
  },
  FixControlSize: function () {
   this.FixElementSize(this.GetMainElement());
   var contentCell = this.GetContentsCell();
   if(!contentCell) return;
   var width = contentCell.offsetWidth;
   var height = contentCell.offsetHeight;
   width -= this.GetCachedHorizontalBordersAndPaddingsWidth(contentCell);
   height -= this.GetCachedVerticalBordersAndPaddingsWidth(contentCell);
   ASPx.Attr.ChangeStyleAttribute(contentCell, "width", width + "px");
   ASPx.Attr.ChangeStyleAttribute(contentCell, "height", height + "px");
  },
  UnfixControlSize: function () {
   this.UnfixElementSize(this.GetMainElement());
   this.UnfixElementSize(this.GetContentsCell());
  },
  FixElementSize: function (element) {
   if(element == null) return;
   var width = element.offsetWidth;
   var height = element.offsetHeight;
   ASPx.Attr.ChangeStyleAttribute(element, "width", width + "px");
   ASPx.Attr.ChangeStyleAttribute(element, "height", height + "px");
  },
  UnfixElementSize: function (element) {
   if(element == null) return;
   ASPx.Attr.RestoreStyleAttribute(element, "width");
   ASPx.Attr.RestoreStyleAttribute(element, "height");
  },
  AdjustSize: function () {
   this.adjustControlInternal();
  },
  adjustControlInternal: function() {
   this.AdjustControlCore();
   var cache = this.adjustmentVars.mainElementCache;
   var width = Math.ceil(cache.offsetWidth);
   var height = Math.ceil(cache.offsetHeight);
   this.adjustedSizes = { width: width, height: height };
  },
  AdjustControlCore: function () {
   ASPxClientControl.prototype.AdjustControlCore.call(this);
   this.EnsureControlInitialized();
   this.SetObservationPaused(true);
   this.UpdateLayout();
   this.ProcessDeferredActions();
   this.SetObservationPaused(false);
  },
  ProcessDeferredActions: function() {
   while(this.deferredActions.length > 0) {
    var action = this.deferredActions[0];
    try {
     this.SetTabVisibleCore(action.tabIndex, action.setVisible);
    }
    finally {
     ASPx.Data.ArrayRemoveAt(this.deferredActions, 0);
    }
   }
  },
  IsAdjustmentRequired: function() {
   if(this.deferredActions.length > 0)
    return true;
   return ASPxClientControl.prototype.IsAdjustmentRequired.call(this);
  },
  UpdateLayout: function () {
   if(!this.enableScrolling)
    this.AdjustTabControlSizeLite();
   else
    this.AdjustTabScrolling(this.scrollToActiveTab, false);
   this.AdjustTabContents();
  },
  AdjustAutoHeight: function () {
   if(!this.IsAdjustmentAllowed())
    return;
   this.EnsureControlInitialized();
   this.UpdateAutoHeight();
  },
  UpdateAutoHeight: function () {
   this.AdjustPageContents();
  },
  SetWidth: function(width) {
   var success = this.SetSizeInternal(width, "width");
   if(success && this.emptyWidth)
    this.emptyWidth = false;
  },
  SetHeight: function(height) {
   var success = this.SetSizeInternal(height, "height");
   if(success && this.emptyHeight)
    this.emptyHeight = false;
  },
  SetSizeInternal: function(value, dimension) {
   if(value < 0)
    return false;
   var mainElement = this.GetMainElement();
   var offsetSize = this.GetCachedElementInnerSize(mainElement, dimension) 
    + this.GetCachedBordersAndPaddingsWidth(mainElement, dimension);
   if(offsetSize === value)
    return false;
   this.SetCachedElementOffsetSize(mainElement, value, dimension);
   this.ClearElementCache(mainElement);
   this.ResetControlAdjustment();
   this.UpdateAdjustmentFlags();
   this.AdjustControl(true);
   return true;
  },
  CanLoadTabOnCallback: function (index) {
   return this.isLoadTabByCallback && ASPx.IsFunction(this.callBack);
  },
  finalizeChangeTabState: function () {},
  ChangeTabState: function (index, active) {
   var element = this.GetTabElement(index, true);
   if(element != null) this.SetElementDisplay(element, active);
   element = this.GetTabElement(index, false);
   if(element != null) this.SetElementDisplay(element, !active);
   element = this.GetContentElement(index);
   if(element != null) this.setContentDisplay(element, active);
   this.tabHeightManager.requestAdjustment();
  },
  setContentDisplay: function (element, active) {
   this.SetElementDisplay(element, active);
  },
  ChangeActiveTab: function (index, hasLink) {
   this.SetObservationPaused(true);
   var processingMode = this.RaiseActiveTabChanging(index);
   if(processingMode == "Client" || processingMode == "ClientWithReload") {
    var element = this.GetContentElement(index);
    if(this.CanLoadTabOnCallback(index) && element != null && (!element.loaded || processingMode == "ClientWithReload")) {
     if(this.callbackCount == 0)
      this.FixControlSize();
     this.DoChangeActiveTab(index);
     this.isActiveTabChanged = true;
     this.PerformCallbackInternal(index, element);
    }
    else {
     this.DoChangeActiveTab(index);
     if(this.GetMainElement()) {
      var activeContentElement = this.getActiveContentElement();
      if(activeContentElement) {
       window.setTimeout(function() {
        this.onActiveTabChangedTimeout(activeContentElement);
       }.aspxBind(this), 0);
      }
     }
     this.RaiseActiveTabChanged(index);
    }
   }
   else if(processingMode == "Server" && !hasLink)
    this.SendPostBack("ACTIVATE:" + index);
   this.SetObservationPaused(false);
  },
  onActiveTabChangedTimeout: function(activeContentElement) {
   this.DoSafeScrollPositionOperation(function() {
    this.onActiveTabChangedTimeoutCore(activeContentElement);
   }.aspxBind(this));
  },
  onActiveTabChangedTimeoutCore: function(activeContentElement) {
   this.SetObservationPaused(true);
   activeContentElement.style.position = "fixed";
   this.layoutManager.calculateSizes();
   activeContentElement.style.position = "";
   this.AdjustPageContents();
   ASPx.GetControlCollection().AdjustControlsCore(activeContentElement, true);
   this.adjustControlInternal();
   this.SetObservationPaused(false);
  },
  PerformCallbackInternal: function (tabIndex, tabContentElement, callbackArgument, handler) {
   if(typeof (callbackArgument) == "undefined")
    callbackArgument = tabIndex;
   if(!tabContentElement.loading) {
    this.callbackCount++;
    tabContentElement.loading = true;
    this.tabsContentRequest.push(tabIndex);
    this.ShowLoadingPanelInTabPage(tabIndex);
    this.CreateCallback(callbackArgument, null, handler);
   }
  },
  IsMultiRow: function () {
   if(!ASPx.IsExists(this.isMultiRow))
    this.isMultiRow = ASPx.ElementHasCssClass(this.GetMainElement(), Constants.CssClassName.MULTIROW);
   return this.isMultiRow;
  },
  UseProportionalTabSizes: function () {
   return this.IsMultiRow() || this.tabAlign == "Justify";
  },
  PlaceActiveTabRowToBottom: function(activeTabIndex) {
   var activeTabElement = this.GetVisibleTabElement(activeTabIndex);
   if(!activeTabElement) return;
   var newActiveRow = this.getTabRowByTabElement(activeTabElement);
   var currentActiveRow = this.getActiveTabRow();
   if(newActiveRow != currentActiveRow) {
    var tabsHolderElement = this.getTabsHolderElement();
    tabsHolderElement.insertBefore(currentActiveRow, newActiveRow);
    var refElement = this.tabPosition == "Top" ? null : tabsHolderElement.firstChild;
    tabsHolderElement.insertBefore(newActiveRow, refElement);
   }
   this.adjustTabRowsSpacing();
   this.replaceCssClassForChildren(currentActiveRow, Constants.CssClassName.ACTIVE_ROW_ITEM, "");
   this.replaceCssClassForChildren(newActiveRow, "", Constants.CssClassName.ACTIVE_ROW_ITEM);
  },
  getTabRowByTabElement: function(tabElement) {
   return tabElement.parentNode;
  },
  getTabsHolderElement: function() {
   var stripElement = this.GetTabsCell();
   return ASPx.GetChildByClassName(stripElement, Constants.CssClassName.TABS_HOLDER, 0);
  },
  getTabRows: function() {
   var tabsHolderElement = this.getTabsHolderElement();
   return ASPx.GetChildNodesByClassName(tabsHolderElement, Constants.CssClassName.TAB_ROW);
  },
  getActiveTabRow: function() {
   var tabRows = this.getTabRows();
   var rowIndex = this.getActiveTabRowIndex(tabRows);
   return tabRows[rowIndex];
  },
  getActiveTabRowIndex: function(tabRows) {
   return this.getActiveTabRowIndexCore(tabRows.length);
  },
  getActiveTabRowIndexCore: function(rowCount) {
   return this.tabPosition == "Top" ? rowCount - 1 : 0;
  },
  replaceCssClassForChildren: function(parentElement, className, newClassName) {
   var children = ASPx.GetChildElementNodes(parentElement);
   this.ReplaceCssClassLite(children, className, newClassName);
  },
  adjustTabRowsSpacing: function() {
   var tabSpace = this.GetTabSpaceSizeLite(); 
   var tabRows = this.getTabRows();
   var activeRowIndex = this.getActiveTabRowIndex(tabRows);
   var propName = "padding" + (this.tabPosition == "Top" ? "Bottom" : "Top");
   var paddingValue = tabSpace + "px";
   var nullPaddingValue = "0";
   for(var i = 0; i < tabRows.length; i++) {
    var tabRow = tabRows[i];
    var value = i == activeRowIndex ? nullPaddingValue : paddingValue;
    tabRow.style[propName] = value;
   }
  },
  ReplaceCssClassLite: function (collection, className, newClassName) {
   for(var i = 0; i < collection.length; i++) {
    if(!collection[i]) continue;
    var c = collection[i].className.replace(className, "");
    collection[i].className = ASPx.Str.Trim(c);
    if(newClassName != "")
     collection[i].className += " " + newClassName;
   }
  },
  needInvertedChange: function () {
   return ASPx.Browser.Firefox && ASPx.Browser.Version >= 3;
  },
  DoChangeActiveTab: function (index) {
   if(this.needInvertedChange()) { 
    var contentsCell = this.GetContentsCell();
    var isContentsCellExists = ASPx.IsExistsElement(contentsCell);
    if(isContentsCellExists)
     ASPx.SetElementVisibility(contentsCell, false);
    this.ChangeTabState(index, true);
    this.ChangeTabState(this.activeTabIndex, false);
    this.activeTabIndex = index;
    if(isContentsCellExists)
     ASPx.SetElementVisibility(contentsCell, true);
   } else {
    this.ChangeTabState(this.activeTabIndex, false);
    this.activeTabIndex = index;
    this.ChangeTabState(this.activeTabIndex, true);
   }
   this.finalizeChangeTabState();
   if(this.enableScrolling)
    this.AdjustTabScrolling(this.scrollToActiveTab, true);
   else
    this.AdjustTabControlSizeLite();
   if(this.IsMultiRow())
    this.PlaceActiveTabRowToBottom(index);
   this.AdjustTabContents();
   this.UpdateActiveTabIndexCookie();
   this.focusActiveTab();
  },
  focusActiveTab: function() {
   if(this.accessibilityCompliant && (!this.scrollManager || !this.scrollManager.IsInProgress())) {
    var linkEl = this.GetTabLinkElement(this.activeTabIndex, true);
    if(linkEl)
     linkEl.focus();
   }
  },
  SetActiveTabIndexInternal: function (index, hasLink) {
   if(this.activeTabIndex == index) return;
   this.DoSafeScrollPositionOperation(function () {
    this.ChangeActiveTab(index, hasLink);
   }.aspxBind(this));
   this.UpdateHoverState(index);
  },
  SwitchActiveTab: function(toNext) {
   var index = this.GetActiveTabIndex();
   if(toNext) index++;
   else index--;
   for (var i = index, tab; tab = this.tabs[i]; toNext ? i++ : i--) {
    if(tab.GetVisible()) {
     this.SetActiveTab(tab);
     return;
    }
   }
  },
  UpdateActiveTabIndexCookie: function () {
   if(this.cookieName == "") return;
   ASPx.Cookie.DelCookie(this.cookieName);
   ASPx.Cookie.SetCookie(this.cookieName, this.activeTabIndex);
  },
  UpdateHoverState: function (index) {
   if(!this.IsStateControllerEnabled()) return;
   var element = this.GetTabElement(index, true);
   if(element != null) ASPx.GetStateController().SetCurrentHoverElementBySrcElement(element);
  },
  OnTabClick: function (evt, index) {
   var processingMode = this.RaiseTabClick(index, evt);
   var clickedLinkElement = ASPx.GetParentByTagName(ASPx.Evt.GetEventSource(evt), "A");
   var isLinkClicked = (clickedLinkElement != null && !!clickedLinkElement.href && clickedLinkElement.href != ASPx.AccessibilityEmptyUrl);
   var element = this.GetTabElement(index, false);
   var linkElement = (element != null) ? ASPx.GetNodeByTagName(element, "A", 0) : null;
   if(linkElement != null && (!linkElement.href || linkElement.href == ASPx.AccessibilityEmptyUrl))
    linkElement = null;
   if(processingMode != "Handled") {
    var hasLink = isLinkClicked || linkElement != null;
    if(processingMode == "Server" && !hasLink)
     this.SendPostBack("CLICK:" + index);
    else {
     var clickWithHoldCtrlOnLink = hasLink && evt.ctrlKey;
     if(!clickWithHoldCtrlOnLink)
      this.SetActiveTabIndexInternal(index, hasLink);
    }
    var isMouseDownAction = this.tabAction == Constants.TabAction.MOUSE_DOWN;
    if(this.handleClickOnWholeTab && (!isLinkClicked || isMouseDownAction) && linkElement != null)
     ASPx.Url.NavigateByLink(linkElement);
   }
  },
  OnCallback: function (result) {
   this.OnCallbackInternal(result.html, result.index, false);
  },
  OnCallbackError: function (result, data) {
   this.OnCallbackInternal(result, data, true);
  },
  OnCallbackInternal: function (html, index, isError) {
   this.SetCallbackContent(html, index, isError);
   ASPx.Data.ArrayRemoveAt(this.tabsContentRequest, 0);
   if(!isError && this.isActiveTabChanged) {
    this.isActiveTabChanged = false;
    this.shouldRaiseActiveTabChangedEvent = true;
   }
   if(this.enableCallbackAnimation)
    ASPx.AnimationHelper.fadeIn(this.GetContentElement(index), function () { this.OnCallbackFinish(index); }.aspxBind(this));
  },
  OnCallbackFinish: function (index) {
   this.adjustControlInternal();
   if(this.shouldRaiseActiveTabChangedEvent) {
    this.shouldRaiseActiveTabChangedEvent = false;
    if(!ASPx.IsExists(index))
     index = this.GetActiveTabIndex();
    this.RaiseActiveTabChanged(index);
   }
  },
  OnCallbackFinalized: function () {
   if(!this.enableCallbackAnimation)
    this.OnCallbackFinish();
  },
  OnCallbackGeneralError: function (result) {
   var callbackTabIndex = (this.tabsContentRequest.length > 0) ? this.tabsContentRequest[0] : this.activeTabIndex;
   this.SetCallbackContent(result, callbackTabIndex, true);
   ASPx.Data.ArrayRemoveAt(this.tabsContentRequest, 0);
  },
  ShowLoadingPanelInTabPage: function (index) {
   if(this.lpDelay > 0)
    window.setTimeout(function () { this.ShowLoadingPanelInTabPageCore(index); }.aspxBind(this), this.lpDelay);
   else
    this.ShowLoadingPanelInTabPageCore(index);
  },
  ShowLoadingPanelInTabPageCore: function (index) {
   if(ASPx.Data.ArrayIndexOf(this.tabsContentRequest, index) < 0) return;
   var element = this.GetContentHolder(index);
   var hasContent = !!ASPx.Str.Trim(this.GetTabContentHTML(this.GetTab(index)));
   var loadingPanelElement = this.CreateLoadingPanelWithAbsolutePosition(element, this.GetContentsCell());
   if(!hasContent && loadingPanelElement)
    ASPx.AddClassNameToElement(loadingPanelElement, "dxlp-withoutBorders");
  },
  ShouldHideExistingLoadingElements: function () {
   return false;
  },
  SetCallbackContent: function (html, index, isError) {
   this.SetObservationPaused(true);
   var element = this.GetContentElement(index);
   if(element != null) {
    if(!isError)
     element.loaded = true;
    element.loading = false;
    ASPx.SetInnerHtml(this.GetContentHolder(index), html);
    this.callbackCount--;
    if(this.callbackCount == 0)
     this.UnfixControlSize();
   }
   this.SetObservationPaused(false);
  },
  GetClientTabType: function() {
   return ASPxClientTab;
  },
  CreateTabs: function (tabsProperties) {
   var tabType = this.GetClientTabType();
   for(var i = 0; i < tabsProperties.length; i++) {
    var tabName = tabsProperties[i][0] || "";
    var tab = new tabType(this, i, tabName);
    this.CreateTabProperties(tab, tabsProperties[i]);
    this.tabs.push(tab);
   }
  },
  CreateTabProperties: function (tab, tabProperties) {
   if(ASPx.IsExists(tabProperties[1]))
    tab.enabled = tabProperties[1];
   if(ASPx.IsExists(tabProperties[2]))
    tab.clientEnabled = tabProperties[2];
   if(ASPx.IsExists(tabProperties[3]))
    tab.visible = tabProperties[3];
   if(ASPx.IsExists(tabProperties[4]))
    tab.clientVisible = tabProperties[4];
   if(ASPx.IsExists(tabProperties[5]))
    tab.newLine = tabProperties[5];
  },
  CreateTabClickEventArgs: function(processOnServer, tab, htmlElement, htmlEvent) {
   return new ASPxClientTabControlTabClickEventArgs(processOnServer, tab, htmlElement, htmlEvent);
  },
  CreateTabEventArgs: function(tab) {
   return new ASPxClientTabControlTabEventArgs(tab);
  },
  CreateTabCancelEventArgs: function(processOnServer, tab) {
   return new ASPxClientTabControlTabCancelEventArgs(processOnServer, tab);
  },
  RaiseTabClick: function (index, htmlEvent) {
   var processingMode = this.autoPostBack || this.IsServerEventAssigned("TabClick") ? "Server" : "Client";
   if(!this.TabClick.IsEmpty()) {
    var htmlElement = this.GetTabElement(index, this.activeTabIndex == index);
    var args = this.CreateTabClickEventArgs(processingMode == "Server", this.GetTab(index), htmlElement, htmlEvent);
    this.TabClick.FireEvent(this, args);
    if(args.cancel)
     processingMode = "Handled";
    else
     processingMode = args.processOnServer ? "Server" : "Client";
   }
   return processingMode;
  },
  RaiseActiveTabChanged: function (index) {
   if(!this.ActiveTabChanged.IsEmpty()) {
    var args = this.CreateTabEventArgs(this.GetTab(index));
    this.ActiveTabChanged.FireEvent(this, args);
   }
  },
  RaiseActiveTabChanging: function (index) {
   var processingMode = this.autoPostBack ? "Server" : "Client";
   if(!this.ActiveTabChanging.IsEmpty()) {
    var args = this.CreateTabCancelEventArgs(processingMode == "Server", this.GetTab(index));
    this.ActiveTabChanging.FireEvent(this, args);
    if(args.cancel || (processingMode === "Server" && !args.processOnServer))
     processingMode = "Handled";
    else if(args.processOnServer)
     processingMode = "Server";
    else
     processingMode = args.reloadContentOnCallback ? "ClientWithReload" : "Client";
   }
   return processingMode;
  },
  SetEnabled: function (enabled) {
   for(var i = this.GetTabCount() - 1; i >= 0; i--) {
    var tab = this.GetTab(i);
    tab.SetEnabled(enabled, true );
   }
  },
  GetActiveTab: function () {
   return (this.activeTabIndex > -1) ? this.GetTab(this.activeTabIndex) : null;
  },
  SetActiveTab: function (tab) {
   if(this.IsTabVisible(tab.index))
    this.SetActiveTabIndexInternal(tab.index, false);
  },
  GetActiveTabIndex: function () {
   return this.activeTabIndex;
  },
  SetActiveTabIndex: function (index) {
   if(index < 0 || index >= this.tabs.length) return;
   if(this.IsTabVisible(index))
    this.SetActiveTabIndexInternal(index, false);
  },
  GetTabCount: function () {
   return this.tabs.length;
  },
  GetTab: function (index) {
   return (0 <= index && index < this.tabs.length) ? this.tabs[index] : null;
  },
  GetTabByName: function (name) {
   for(var i = 0; i < this.tabs.length; i++)
    if(this.tabs[i].name == name) return this.tabs[i];
   return null;
  },
  IsTabEnabled: function (index) {
   return this.tabs[index].GetEnabled();
  },
  SetTabEnabled: function (index, enabled, initialization, doNotChangeActiveTab) {
   if(!this.tabs[index].enabled) return;
   this.ClearTabElementsCache(index);
   if(!initialization || !enabled)
    this.ChangeTabEnabledStateItems(index, enabled);
   this.ChangeTabEnabledAttributes(index, enabled, doNotChangeActiveTab);
   if(!initialization && this.canUseOffsetSizes())
    this.adjustControlInternal();
  },
  ChangeTabEnabledAttributes: function (index, enabled, doNotChangeActiveTab) {
   if(enabled) {
    this.ChangeTabElementsEnabledAttributes(index, enabled, ASPx.Attr.RestoreAttribute, ASPx.Attr.RestoreStyleAttribute);
    var isActiveTabEnabled = this.activeTabIndex != -1 ? this.IsTabEnabled(this.activeTabIndex) : false;
    if(!doNotChangeActiveTab && !isActiveTabEnabled && this.IsTabVisible(index))
     this.SetActiveTabIndexInternal(index, false);
   }
   else {
    if(this.activeTabIndex == index && !doNotChangeActiveTab) {
     for(var i = 0; i < this.GetTabCount() ; i++) {
      if(this.IsTabVisible(i) && this.IsTabEnabled(i) && i != index) {
       this.SetActiveTabIndexInternal(i, false);
       break;
      }
     }
    }
    this.ChangeTabElementsEnabledAttributes(index, enabled, ASPx.Attr.ResetAttribute, ASPx.Attr.ResetStyleAttribute);
   }
  },
  ChangeTabElementsEnabledAttributes: function (index, enabled, method, styleMethod) {
   var eventName = this.getTabActivationHtmlEventName();
   var element = this.GetTabElement(index, false);
   if(element) {
    element.clientDisabled = !enabled;
    method(element, eventName);
    styleMethod(element, "cursor");
    var link = this.GetInternalHyperlinkElement(element, 0);
    if(link != null)
     this.ChangeTabLinkEnabledAttributes(link, enabled, method, styleMethod);
    link = this.GetInternalHyperlinkElement(element, 1);
    if(link != null) 
     this.ChangeTabLinkEnabledAttributes(link, enabled, method, styleMethod);
   }
   var activeElement = this.GetTabElement(index, true);
   if(activeElement) {
    method(activeElement, eventName);
    styleMethod(activeElement, "cursor");
   }
  },
  ChangeTabLinkEnabledAttributes: function (link, enabled, method, styleMethod) {
   method(link, "href");
   styleMethod(link, "cursor");
  },
  getTabActivationHtmlEventName: function() {
   switch(this.tabAction) {
    case Constants.TabAction.CLICK:
     return "onclick";
    case Constants.TabAction.MOUSE_OVER:
     return "onmouseover";
    case Constants.TabAction.MOUSE_DOWN:
     return ASPx.Browser.WebKitTouchUI ? "ontouchstart" : "onmousedown";
   }
   throw "This mode is not supported";
  },
  ChangeTabEnabledStateItems: function (index, enabled) {
   if(!this.IsStateControllerEnabled()) return;
   var element = this.GetTabElement(index, false);
   if(element != null) ASPx.GetStateController().SetElementEnabled(element, enabled);
   var activeElement = this.GetTabElement(index, true);
   if(activeElement != null) ASPx.GetStateController().SetElementEnabled(activeElement, enabled);
  },
  GetTabImageUrl: function (index, active) {
   var imgEl = this.GetTabImageElement(index, active);
   return imgEl ? imgEl.src : "";
  },
  SetTabImageUrl: function (index, active, url) {
   var imgEl = this.GetTabImageElement(index, active);
   if(imgEl) {
    imgEl.src = url;
    var tabEl = this.GetTabElement(index, active);
    this.ClearElementCache(tabEl);
    this.tabHeightManager.requestAdjustment();
    this.adjustControlInternal();
   }
  },
  GetTabNavigateUrl: function (index) {
   var linkEl = this.GetTabLinkElement(index, false);
   return linkEl ? (linkEl.href || ASPx.Attr.GetAttribute(linkEl, "savedhref")) : "";
  },
  SetTabNavigateUrl: function (index, url) {
   var linkEl = this.GetTabLinkElement(index, false);
   if(linkEl) {
    if(ASPx.Attr.IsExistsAttribute(linkEl, "savedhref"))
     ASPx.Attr.SetAttribute(linkEl, "savedhref", url);
    else if(ASPx.Attr.IsExistsAttribute(linkEl, "href"))
     linkEl.href = url;
   }
  },
  GetTabText: function (index) {
   var isActive = index == this.GetActiveTabIndex();
   var element = this.GetTabTextElement(index, isActive);
   if(element) {
    var textNode = ASPx.GetNormalizedTextNode(element);
    if(textNode != null)
     return ASPx.Str.Trim(textNode.nodeValue);
   }
   return "";
  },
  SetTabText: function (index, text) {
   this.SetTabTextInternal(index, false, text);
   this.SetTabTextInternal(index, true, text);
   this.ClearTabElementsCache(index);
   this.adjustControlInternal();
  },
  SetTabTextInternal: function (index, isActive, text) {
   var element = this.GetTabTextElement(index, isActive);
   if(element != null) {
    var textNode = ASPx.GetNormalizedTextNode(element);
    if(!textNode) {
     textNode = document.createTextNode("");
     element.appendChild(textNode);
    }
    textNode.nodeValue = text;
   }
  },
  IsTabVisible: function (index) {
   return this.tabs[index].GetVisible();
  },
  IsTabStartOutOfScrollArea: function (index) {
   var width = 0;
   for(var i = 0; i < index; i++) {
    width += this.GetVisibleTabElement(index).offsetWidth;
    var separator = this.GetSeparatorElement(index);
    if(separator)
     width += separator.offsetWidth;
   }
   return Math.abs(this.scrollManager.GetScrolledAreaPosition()) > width;
  },
  SetTabVisible: function(index, visible) {
   var needResetDisplay = this.clientVisible && this.getAreAllTabsHidden();
   var mainElement;
   if(needResetDisplay) {
    mainElement = this.GetMainElement();
    mainElement.style.display = "";
   }
   var controlVisible = this.clientVisible && this.isInsideVisibleContainer();
   if(needResetDisplay && (!controlVisible || this.isFullyInitialized))
    mainElement.style.display = "none";
   this.tabs[index].clientVisible = visible;
   if(controlVisible) {
    this.EnsureControlInitialized();
    this.SetTabVisibleCore(index, visible);
   }
   else {
    var action = { 
     tabIndex: index,
     setVisible: visible
    };
    this.deferredActions.push(action);
    if(needResetDisplay && visible)
     mainElement.style.display = "";
   }
  },
  SetTabVisibleCore: function(index, visible, initialization) {
   if(!this.tabs[index].visible || (visible && initialization))
    return;
   this.SetTabVisibleInternal(index, visible);
  },
  SetTabVisibleInternal: function(index, visible) {
   this.SetObservationPaused(true);
   var element = this.GetTabElement(index, false);
   var currentShiftWidth = 0,
    visibleTabElement = this.GetVisibleTabElement(index),
    separatorElement = this.GetSeparatorElement(index);
   if(visibleTabElement)
    currentShiftWidth = visibleTabElement.offsetWidth;
   if(separatorElement)
    currentShiftWidth += separatorElement.offsetWidth;
   var activeElement = this.GetTabElement(index, true);
   var contentElement = this.GetContentElement(index);
   if(this.IsMultiRow())
    this.setTabRowVisibility(index, visibleTabElement, visible);
   if(!visible) {
    if(this.activeTabIndex == index) {
     for(var i = 0; i < this.GetTabCount() ; i++) {
      if(this.IsTabVisible(i) && this.IsTabEnabled(i) && i != index) {
       this.SetActiveTabIndexInternal(i, false);
       break;
      }
     }
     for(var i = 0; i < this.GetTabCount() ; i++) {
      if(this.IsTabVisible(i) && i != index) {
       this.SetActiveTabIndexInternal(i, false);
       break;
      }
     }
     if(this.activeTabIndex == index) {
      this.activeTabIndex = -1;
      ASPx.SetElementDisplay(this.GetMainElement(), false);
     }
    }
    if(element != null)
     this.SetElementDisplay(element, false);
    if(activeElement != null)
     this.SetElementDisplay(activeElement, false);
    if(contentElement != null)
     this.setContentElementVisible(contentElement, false, index);
   }
   else {
    if(element != null)
     this.SetElementDisplay(element, this.activeTabIndex != index);
    if(activeElement != null)
     this.SetElementDisplay(activeElement, this.activeTabIndex == index);
    if(contentElement != null)
     this.setContentElementVisible(contentElement, this.activeTabIndex == index, index);
    if(this.activeTabIndex == -1) {
     ASPx.SetElementDisplay(this.GetMainElement(), true);
     this.SetActiveTabIndexInternal(index, false);
    }
    else if(!this.IsTabEnabled(this.activeTabIndex) && this.IsTabEnabled(index))
     this.SetActiveTabIndexInternal(index, false);
   }
   if(this.GetTabsCell())
    this.updateTabOrderCssMarkers();
   this.SetSeparatorsVisiblility();
   this.tabHeightManager.requestAdjustment();
   if(!this.enableScrolling)
    this.AdjustTabControlSizeLite();
   else {
    this.AdjustTabScrolling(false, false);
    if(this.IsTabStartOutOfScrollArea(index)) {
     currentShiftWidth = visible
      ? (this.GetVisibleTabElement(index).offsetWidth + this.GetSeparatorElement(index).offsetWidth) * (-1)
      : currentShiftWidth;
     this.CorrectScrollArea(currentShiftWidth);
    }
    if(this.firstShownTabIndex == index && !visible) {
     var newShownTabIndex = this.GetNextVisibleTabIndex(index);
     if(newShownTabIndex < 0) {
      newShownTabIndex = this.GetPrevVisibleTabIndex(index);
      if(newShownTabIndex < 0) return;
     }
     this.ScrollToShowTab(newShownTabIndex, true);
    }
   }
   this.SetObservationPaused(false);
  },
  setContentElementVisible: function (contentElement, value, index) {
   ASPx.SetElementDisplay(contentElement, value);
  },
  setTabRowVisibility: function(index, visibleTabElement, visible) {
   var tabRowContainer = this.GetVisibleTabElement(index).parentNode;
   if(!visible) {
    var areAllTabsInvisible = this.areAllTabsInRowInvisible(index);
    ASPx.SetElementDisplay(tabRowContainer, !areAllTabsInvisible);
   } else {
    ASPx.SetElementDisplay(tabRowContainer, true);
   }
  },
  areAllTabsInRowInvisible: function(index) {
   var visibleTabElement = this.GetVisibleTabElement(index),
    tabRowContainer = visibleTabElement.parentNode,
    tabIndices = [],
    findTargetContainer = false;
   for(var i = 0; i < this.GetTabCount() ; i++) {
    var tabElement = this.GetVisibleTabElement(i);
    if(tabElement) {
     var rowContainer = tabElement.parentNode;
     if(tabRowContainer == rowContainer) {
      tabIndices.push(i);
      findTargetContainer = true;
     } else {
      if(findTargetContainer)
       break;
     }
    }
   }
   var areAllTabsInvisible = true;
   if(tabIndices.length === 1) {
    areAllTabsInvisible = !this.IsTabVisible(index);
   } else {
    var len = tabIndices.length;
    while(len--)
     areAllTabsInvisible = areAllTabsInvisible && !this.IsTabVisible(tabIndices[len]);
   }
   return areAllTabsInvisible;
  },
  updateTabOrderCssMarkers: function() {
   var newTabsOrderInfo = this.getTabsOrderInfo();
   this.changeTabsOrderCssMarkers(this.tabsOrderInfo.leadTab, newTabsOrderInfo.leadTab, Constants.CssClassName.LEAD_TAB);
   this.changeTabsOrderCssMarkers(this.tabsOrderInfo.lastTab, newTabsOrderInfo.lastTab, Constants.CssClassName.LAST_TAB);
   if(this.IsMultiRow()) {
    for(var i = 0; i < this.tabsOrderInfo.lines.length; i++) {
     var oldLineInfo = this.tabsOrderInfo.lines[i];
     var newLineInfo = newTabsOrderInfo.lines[i];
     this.changeTabsOrderCssMarkers(oldLineInfo.startLineTab, newLineInfo.startLineTab, Constants.CssClassName.NEW_LINE_START_TAB);
     this.changeTabsOrderCssMarkers(oldLineInfo.endLineTab, newLineInfo.endLineTab, Constants.CssClassName.NEW_LINE_END_TAB);
    }
   }
   this.tabsOrderInfo = newTabsOrderInfo;
  },
  changeTabsOrderCssMarkers: function(oldTab, newTab, className) {
   if(oldTab !== newTab) {
    this.changeTabElementCssMarker(oldTab, className, false);
    this.changeTabElementCssMarker(newTab, className, true);
   }
  },
  changeTabElementCssMarker: function(tab, className, add) {
   if(!tab) return;
   var changeFunc = add ? this.addNewClassNameToElement : ASPx.RemoveClassNameFromElement;
   var tabElement = this.GetTabElement(tab.index, false);
   if(tabElement)
    changeFunc(tabElement, className);
   var activeTabElement = this.GetTabElement(tab.index, true);
   if(activeTabElement)
    changeFunc(activeTabElement, className);
  },
  addNewClassNameToElement: function(element, className) {
   element.className += " " + className;
  },
  getTabsOrderInfo: function() {
   var lines = this.getTabLines();
   var info = { lines: [] };
   for(var i = 0, line; line = lines[i]; i++) {
    var lineInfo = { };
    info.lines.push(lineInfo);
    for(var j = 0, tab; tab = line[j]; j++) {
     if(tab.GetVisible()) {
      if(i === 0)
       info.leadTab = tab;
      lineInfo.startLineTab = tab;
      break;
     }
    }
    for(var j = line.length - 1, tab; tab = line[j]; j--) {
     if(tab.GetVisible()) {
      if(i === lines.length - 1)
       info.lastTab = tab;
      lineInfo.endLineTab = tab;
      break;
     }
    }
   }
   return info;
  },
  getTabLines: function() {
   var line = [];
   var lines = [ line ];
   for(var i = 0, tab; tab = this.tabs[i]; i++) {
    if(tab.newLine) {
     line = [];
     lines.push(line);
    }
    line.push(tab);
   }
   return lines;
  },
  CorrectScrollArea: function (value) {
   var rtlCorrect = this.rtl ? -1 : 1;
   var newPostion = (this.scrollManager.GetScrolledAreaPosition() + value * rtlCorrect);
   this.scrollManager.SetScrolledAreaPosition((newPostion * rtlCorrect) <= 0 ? newPostion : 0);
  },
  SetSeparatorsVisiblility: function () {
   for(var i = 0; i < this.tabs.length; i++) {
    var nextVisibleTabIndex = this.GetNextVisibleTabIndex(i),
     nextVisibleTabElement = this.GetVisibleTabElement(nextVisibleTabIndex),
     separatorVisible = this.tabs[i].GetVisible() && nextVisibleTabIndex > -1 && !(this.IsMultiRow() && this.isTabElementStartsNewLine(nextVisibleTabElement)),
     separatorElement = this.GetSeparatorElement(i);
    if(separatorElement != null)
     ASPx.SetElementDisplay(separatorElement, separatorVisible);
   }
  },
  GetNextVisibleTabIndex: function (index, allowHidden) {
   for(var i = index + 1; i < this.tabs.length; i++) {
    if(allowHidden && this.tabs[i].visible || this.tabs[i].GetVisible())
     return i;
   }
   return -1;
  },
  GetPrevVisibleTabIndex: function (index) {
   for(var i = index - 1; i >= 0; i--) {
    if(this.tabs[i].GetVisible())
     return i;
   }
   return -1;
  },
  applyAccessibilityAttributes: function() {
   this.setAriaDescription("");
   this.setAriaDescription("tab");
   this.setAriaDescription("presentationElements");
  }
 });
 ASPxClientTabControlBase.FindOwnerTabControl = function(element) {
  var mainElement = ASPx.GetParentByClassName(element, Constants.CssClassName.TAB_CONTROL);
  if(mainElement)
   return ASPx.GetControlCollection().GetByName(mainElement.id);
  return null;
 };
 ASPxClientTabControlBase.HasDocumentKeyDownHandler = false;
 ASPxClientTabControlBase.EnsureDocumentKeyDownHandler = function() {
  if(!ASPxClientTabControlBase.HasDocumentKeyDownHandler) {
   ASPxClientTabControlBase.HasDocumentKeyDownHandler = true;
   ASPx.Evt.AttachEventToDocument("keydown", function(e) {
    var activeElement = document.activeElement;
    if(ASPx.ElementHasCssClass(activeElement, Constants.CssClassName.TAB_LINK)) {
     var tabControl = ASPxClientTabControlBase.FindOwnerTabControl(activeElement);
     if(tabControl)
      tabControl.onFocusedTabKeyDown(e);
    }
   });
  }
 };
 ASPxClientTabControlBase.TabChildElementIDRegExp = /^A?T\d+(T|Img)?$/;
 ASPxClientTabControlBase.IsTabChildElementID = function (id) {
  return ASPxClientTabControlBase.TabChildElementIDRegExp.test(id);
 };
 ASPxClientTabControlBase.PrepareStateController = function () {
  if(ASPxClientTabControlBase.IsStateControllerPrepared) return;
  ASPx.AddAfterSetHoverState(aspxTabStateChanged);
  ASPx.AddAfterClearHoverState(aspxTabStateChanged);
  ASPx.AddAfterSetPressedState(aspxTabStateChanged);
  ASPx.AddAfterClearPressedState(aspxTabStateChanged);
  ASPxClientTabControlBase.IsStateControllerPrepared = true;
 };
 var TabHeightManagerBase = ASPx.CreateClass(null, {
  constructor: function(tabControl) {
   this.tabControl = tabControl;
  },
  initialize: function() {
  },
  isMultiRow: function() {
   return this.tabControl.IsMultiRow();
  },
  correctTabHeightOnStateChanged: function(element) {
  },
  requestAdjustment: function() {
  },
  adjustTabs: function() {
  },
  needAdjustTabStrip: function() {
   return false;
  },
  getTabStripHeight: function() {
   return 0;
  }
 });
 var TabHeightManager = ASPx.CreateClass(TabHeightManagerBase, {
  constructor: function(tabControl) {
   this.constructor.prototype.constructor.call(this, tabControl);
   this.needCalculate = true;
   this.rowCount = 1;
   this.tabSpaceSize = 0;
   this.equalityError = 0.11;
  },
  initialize: function() {
   this.tabSpaceSize = this.tabControl.GetTabSpaceSizeLite();
   if(this.isMultiRow())
    this.rowCount = this.tabControl.getTabLines().length;
  },
  getTabStripElements: function() {
   return this.isMultiRow()
    ? this.getTabStripElementsMultirow()
    : this.getTabStripElementsCommon();
  },
  getTabStripElementsCommon: function() {
   var elements = ASPx.GetChildNodesByTagName(this.tabControl.GetTabStripContainer(), "LI");
   if(this.tabControl.enableScrolling) {
    var subElements = ASPx.GetChildNodesByTagName(this.tabControl.GetTabsCell(), "LI");
    elements.push.apply(elements, subElements);
   }
   return elements;
  },
  getTabStripElementsMultirow: function() {
   var elements = [];
   elements.push(this.tabControl.GetLeftIndentLite());
   elements.push(this.tabControl.GetRightIndentLite());
   var tabRows = this.tabControl.getTabRows();
   for(var i = 0, tabRow; tabRow = tabRows[i]; i++) {
    var subElements = ASPx.GetChildNodesByTagName(tabRow, "LI");
    elements.push.apply(elements, subElements);
   }
   return elements;
  },
  isSameValues: function(val1, val2) {
   if(!ASPx.IsExists(val1) || !ASPx.IsExists(val2))
    return false;
   return this.tabControl.areEqualValues(val1, val2, this.equalityError);
  },
  requestAdjustment: function() {
   this.needCalculate = true;
  },
  needAdjustTabStrip: function() {
   return true;
  },
  getTabStripHeight: function() {},
  adjustTabs: function() {
   this.needCalculate = this.tabControl.UseProportionalTabSizes() || this.needCalculate || !ASPx.documentLoaded;
   if(!this.needCalculate)
    return;
   var needAdjust = this.calculateTabs();
   if(needAdjust) {
    this.needCalculate = !this.tabControl.cacheEnabled;
    this.adjustTabStripElements();
   }
  },
  calculateTabs: function() {},
  adjustTabStripElements: function() {}
 });
 var TabCustomHeightManager = ASPx.CreateClass(TabHeightManager, {
  constructor: function(tabControl) {
   this.constructor.prototype.constructor.call(this, tabControl);
   this.rowHeightArray = null;
   this.updateInfo = null;
   this.margins = {};
  },
  initialize: function() {
   TabHeightManager.prototype.initialize.call(this);
   this.storeInitialTabMargins();
  },
  storeInitialTabMargins: function() {
   var elements = this.tabControl.GetTabsElements();
   var elementCount = elements.length;
   for(var i = 0; i < elementCount; i++) {
    var element = elements[i];
    var margin = ASPx.PxToFloat(ASPx.GetCurrentStyle(element)[this.getMarginStyleProperty()]);
    this.margins[element.id] = margin;
   }
  },
  setTabElementMargin: function(tabElement, margin) {
   var useImportant = !!this.getMarginById(tabElement.id);
   if(useImportant) {
    var styleProperty = 'margin-' + this.tabControl.tabPosition.toLowerCase();
    tabElement.style.cssText = this.createImportantAttribute(tabElement.style.cssText, styleProperty, margin + 'px');
   }
   else
    tabElement.style[this.getMarginStyleProperty()] = margin + 'px';
  },
  getMarginStyleProperty: function() {
   return this.tabControl.tabPosition === "Bottom" ? "marginBottom" : "marginTop";
  },
  createImportantAttribute: function(cssText, attribute, value) {
   var importantProperty = ' ' + attribute + ': ' + value + '!important';
   if(cssText.indexOf(attribute) == -1) {
    cssText += importantProperty;
    return cssText;
   }
   var attributes = cssText.split(";"); 
   var attributesLength = attributes.length;
   for(var i = 0; i < attributesLength; i++){
    if(attributes[i].indexOf(attribute) != -1) {
     attributes[i] = importantProperty;
     break;
    }
   }
   cssText = attributes.join(";");
   return cssText;
  },
  adjustTabStripElements: function() {
   var elementCount = this.updateInfo.length;
   for(var i = 0; i < elementCount; i++) {
    var correction = this.updateInfo[i];
    if(ASPx.IsExists(correction.margin))
     this.setTabElementMargin(correction.element, correction.margin);
    else
     correction.element.style.height = correction.height + 'px';
   }
  },
  getMarginById: function(tabId) {
   var margin = this.margins[tabId];
   if(!margin)
    return 0;
   return margin;
  },
  updateHeightByTab: function(element, rowIndex, cache) {
   this.updateHeightByElement(element, rowIndex, cache);
  },
  updateHeightByIndent: function(element, cache) {
   var rowIndex = this.getActiveTabRowIndexCore(this.rowCount);
   this.updateHeightByElement(element, rowIndex, cache);
  },
  updateHeightByElement: function(element, rowIndex, cache) {
   var rowHeight = this.rowHeightArray[rowIndex];
   var totalElementHeight = cache.height + cache.verticalBordersAndPaddingsWidth + this.getMarginById(element.id);
   this.rowHeightArray[rowIndex] = this.tabControl.GetMaxValue(totalElementHeight, rowHeight);
  },
  updateRowHeightArray: function(stripInfo) {
   for(var i = 0; i < this.rowCount; i++) {
    var rowLength = stripInfo[i].length;
    var rowInfo = stripInfo[i];
    for(var j = 0; j < rowLength; j++) {
     var element = rowInfo[j].element;
     if(this.tabControl.isTemplateIndentElement(element)) {
      var oldHeight = element.style.height;
      element.style.height = '';
      var cache = this.tabControl.GetOrCreateElementCache(element);
      rowInfo[j].cache = cache;
      this.updateHeightByIndent(element, cache);
      element.style.height = oldHeight;
     }
     else {
      var cache = this.tabControl.GetOrCreateElementCache(element);
      rowInfo[j].cache = cache;
      if(this.tabControl.isTabElement(element) && cache.display)
       this.updateHeightByTab(element, i, cache);
     }
    }  
   }
  },
  calculateTabs: function() {
   var info = this.createStripElementInfo();
   this.resetRowHeightArray();
   this.updateRowHeightArray(info);
   this.updateInfo = this.calculateUpdateInfo(info);
   return !!this.updateInfo;
  },
  createStripElementInfo: function() {
   if(this.isMultiRow())
    return this.createStripElementInfoMultirow();
   var tabStripElements = this.getTabStripElements();
   var rowElementsInfo = [];
   var stripElementInfo = [rowElementsInfo];
   for(var i = 0, element; element = tabStripElements[i]; i++) {
    var elementInfo = this.createElementInfo(element);
    rowElementsInfo.push(elementInfo);
   }
   return stripElementInfo;
  },
  createStripElementInfoMultirow: function() {
   var stripElementInfo = [];
   var tabLines = this.tabControl.getTabLines();
   for(var rowIndex = 0, tabLine; tabLine = tabLines[rowIndex]; rowIndex++) {
    var rowElementsInfo = [];
    stripElementInfo.push(rowElementsInfo);
    for(var tabIndex = 0, tab; tab = tabLine[tabIndex]; tabIndex++) {
     if(tab.GetVisible()) {
      var element = this.tabControl.GetVisibleTabElement(tab.index);
      var elementInfo = this.createElementInfo(element);
      rowElementsInfo.push(elementInfo);
     }
    }
   }
   var leftIndent = this.tabControl.GetLeftIndentLite();
   stripElementInfo.leftIndent = this.createElementInfo(leftIndent);
   var rightIndent = this.tabControl.GetRightIndentLite();
   stripElementInfo.rightIndent = this.createElementInfo(rightIndent);
   return stripElementInfo;
  },
  createElementInfo: function(element) {
   return { element: element, cache: null };
  },
  getActualTabStripHeight: function() {
   var result = 0;
   for(var i = 0; i < this.rowCount; i++)
    result += this.rowHeightArray[i];
   if(this.isMultiRow())
    result += (this.rowCount - 1) * this.tabSpaceSize;
   return result;
  },
  resetRowHeightArray: function() {
   if(this.rowHeightArray !== null)
    for(var i = 0; i < this.rowCount; i++)
     this.rowHeightArray[i] = 0;
   else {
    this.rowHeightArray = [];
    for(var i = 0; i < this.rowCount; i++)
     this.rowHeightArray.push(0);
   }
  },
  calculateUpdateInfo: function(stripInfo) {
   var updateInfo = [];
   for(var i = 0; i < this.rowCount; i++) {
    var rowHeight = this.rowHeightArray[i];
    var rowInfo = stripInfo[i];
    var rowLength = rowInfo.length;
    for(var j = 0; j < rowLength; j++)
     this.calcUpdateInfoForStripItem(updateInfo, rowInfo[j], rowHeight);
   }
   if(this.isMultiRow())
    this.calcUpdateInfoForIndents(updateInfo, stripInfo);
   return updateInfo.length > 0 ? updateInfo : null;
  },
  calcUpdateInfoForIndents: function(updateInfo, stripInfo) {
   var expectedHeignt = this.getActualTabStripHeight();
   this.calcUpdateInfoForStripItem(updateInfo, stripInfo.leftIndent, expectedHeignt);
   this.calcUpdateInfoForStripItem(updateInfo, stripInfo.rightIndent, expectedHeignt);
  },
  calcUpdateInfoForStripItem: function(updateInfo, stripItem, expectedHeight) {
   var element = stripItem.element,
    cache = stripItem.cache;
   var height = cache.height + cache.verticalBordersAndPaddingsWidth;
   if(!this.isSameValues(cache.outerHeight, expectedHeight)) {
    var updateItem = { element: element };
    if(this.tabControl.isTabElement(element))
     updateItem.margin = expectedHeight - height;
    else
     updateItem.height = expectedHeight - cache.verticalBordersAndPaddingsWidth;
    updateInfo.push(updateItem);
   }
  },
  correctTabHeightOnStateChanged: function(element) {
   this.adjustTabs();
   this.tabControl.AdjustTabStripHeight();
  },
  getTabStripHeight: function() {
   return this.getActualTabStripHeight();
  }
 });
 var TabDefaultHeightManager = ASPx.CreateClass(TabHeightManager, {
  constructor: function(tabControl) { 
   this.constructor.prototype.constructor.call(this, tabControl);
   this.lastValue = 0;
  },
  calculateTabs: function() {
   var height = this.getTabStripElementHeight();
   var lastTabHeight = this.lastValue;
   if(lastTabHeight && this.isSameValues(height, lastTabHeight))
    return false;
   this.lastValue = height;
   return true;
  },
  adjustTabStripElements: function() {
   var itemHeight = this.lastValue;
   var indentHeight = this.getTabStripHeight();
   var elements = this.getTabStripElements();
   for(var i = 0, element; element = elements[i]; i++) { 
    var useIndentHeight = this.isMultiRow() && 
     (ASPx.ElementHasCssClass(element, Constants.CssClassName.LEFT_INDENT) || 
     ASPx.ElementHasCssClass(element, Constants.CssClassName.RIGHT_INDENT));
    var height = useIndentHeight ? indentHeight : itemHeight;
    this.tabControl.SetCachedElementHeight(element, height);
   }
  },
  correctTabHeightOnStateChanged: function(element) {
   var tabElement = ASPx.GetParentByTagName(element, "LI");
   var height = this.lastValue;
   height -= this.tabControl.GetCachedVerticalBordersPaddingsMarginsWidth(tabElement);
   tabElement.style.height = height + "px";
  },
  getTabStripElementHeight: function () {
   var result = 0;
   var elements = this.getElementsForCalculation();
   var elementsLength = elements.length;
   for(var i = 0; i < elementsLength; i++) {
    var element = elements[i];
    var oldHeight = "";
    if(element.style.height) {
     oldHeight = element.style.height;
     element.style.height = "";
     if(this.isLayoutResetRequired())
      element.style.position = "relative";
    }
    var height = this.tabControl.GetCachedElementSize(element, "height");
    if(height > result)
     result = height;
    if(oldHeight) {
     element.style.height = oldHeight;
     if(this.isLayoutResetRequired())
      element.style.position = "";
    }
   }
   return result;
  },
  isLayoutResetRequired: function() {
   return ASPx.Browser.Firefox && ASPx.Browser.MajorVersion >= 41 && ASPx.Browser.MajorVersion < 43;
  },
  getElementsForCalculation: function() {
   var elements = this.getTabElements();
   if(!this.isMultiRow()) {
    var templateElements = this.getTemplateIndentElements();
    if(templateElements.length > 0)
     elements.push.apply(elements, templateElements);
   }
   return elements;
  },
  getTabElements: function() {
   var elements = [];
   var tabsLength = this.tabControl.tabs.length;
   for(var i = 0; i < tabsLength; i++) {
    if(this.tabControl.IsTabVisible(i)) {
     var element = this.tabControl.GetVisibleTabElement(i);
     if(element)
      elements.push(element);
    }
   }
   return elements;
  },
  getTemplateIndentElements: function() {
   var elements = [];
   var stripContainer = this.tabControl.GetTabStripContainer();
   var templateElements = ASPx.GetNodesByClassName(stripContainer, Constants.CssClassName.INDENT_TEMPLATE);
   var templateElementsLength = templateElements.length;
   for(var i = 0; i < templateElementsLength; i++) {
    var element = templateElements[i];
    if(element)
     elements.push(templateElements[i]);
   }
   return elements;
  },
  getTabStripHeight: function() {
   var result = this.lastValue * this.rowCount;
   if(this.isMultiRow())
    result += (this.rowCount - 1) * this.tabSpaceSize;
   return result;
  }
 });
 var FakeTabHeightManager = ASPx.CreateClass(TabHeightManager, {
  constructor: function() { 
   this.constructor.prototype.constructor.call(this);
  },
  initialize: function() {},
  adjustLineBreaks: function() {},
  adjustTabs: function() {},
  adjustTabStripElements: function() {},
  calculateTabs: function() {},
  correctTabHeightOnStateChanged: function() {},
  getTabStripElements: function() {},
  getTabStripHeight: function() {},
  isSameValues: function() {},
  needAdjustTabStrip: function() { return false; },
  requestAdjustment: function() {}
 });
 var FlexTabHeightManager = ASPx.CreateClass(TabHeightManagerBase, {
  constructor: function(tabControl) {
   this.constructor.prototype.constructor.call(this, tabControl);
  },
  correctTabHeightOnStateChanged: function(element) {
   this.adjustTabs();
  },
  adjustTabs: function() {
   var elements = this.getTabStripElements();
   var actualElements = [];
   for(var i = 0, element; element = elements[i]; i++) {
    if(element.style.display == "none")
     continue;
    actualElements.push(element);
    element.style.height = "";
    ASPx.RemoveClassNameFromElement(element, Constants.CssClassName.PINNED_STRIP_ITEM);
   }
   var heightArray = [];
   for(var i = 0, element; element = actualElements[i]; i++) {
    var height = this.tabControl.GetCachedElementInnerSize(element, "height");
    height = this.tabControl.GetPreparedSizeValue(height);
    heightArray.push(height);
   }
   for(var i = 0, element; element = actualElements[i]; i++) {
    var height = heightArray[i];
    element.style.height = height + "px";
    element.className += " " + Constants.CssClassName.PINNED_STRIP_ITEM;
   }
  },
  getTabStripElements: function() {
   var stripContainer = this.tabControl.GetTabStripContainer();
   return ASPx.GetNodes(stripContainer, function(el) { 
    return el.className &&
     (this.tabControl.isTabElement(el) ||
     this.tabControl.isTemplateIndentElement(el));
   }.aspxBind(this));
  }
 });
 var ASPxClientTabControl = ASPx.CreateClass(ASPxClientTabControlBase, {
  SetHeight: function (height) { }
 });
 ASPxClientTabControl.Cast = ASPxClientControl.Cast;
 var ASPxClientPageControl = ASPx.CreateClass(ASPxClientTabControlBase, {
  constructor: function (name) {
   this.constructor.prototype.constructor.call(this, name);
   this.handleClickOnWholeTab = false;
   this.sizingConfig.supportPercentHeight = true;
   this.sizingConfig.supportAutoHeight = true;
   getPageControlCollection().Add(this);
  },
  GetTabContentHTML: function (tab) {
   var element = this.GetContentHolder(tab.index);
   return (element != null) ? element.innerHTML : "";
  },
  SetTabContentHTML: function (tab, html, useAnimation) {
   var element = this.GetContentElement(tab.index);
   if(element != null) {
    ASPx.SetInnerHtml(this.GetContentHolder(tab.index), html);
    this.adjustControlInternal();
    if(useAnimation && typeof (ASPx.AnimationHelper) != "undefined")
     ASPx.AnimationHelper.fadeIn(element, function () { }.aspxBind(this));
   }
  },
  PerformCallback: function (parameter, onSuccess) {
   var index = this.GetActiveTabIndex();
   var element = this.GetContentElement(index);
   if(element != null) {
    var arg = index + "|" + parameter;
    this.PerformCallbackInternal(index, element, arg, onSuccess);
   }
  },
  onDocumentMouseDown: function(evt) {
   this.enableCollapsingExtended(evt);
  },
  onDocumentMouseUp: function(evt) {
   this.enableCollapsingExtended(evt);
  },
  onDocumentMouseMove: function(evt) {
   if(ASPx.Evt.IsLeftButtonPressed(evt))
    this.enableCollapsingExtended(evt);
  },
  onDocumentMouseClick: function(evt) {
   this.enableCollapsingExtended(evt);
  },
  onDocumentKeyDown: function(evt) {
   this.enableCollapsing(evt);
  },
  onDocumentKeyUp: function(evt) {
   this.enableCollapsing(evt);
  },
  onDocumentKeyPress: function(evt) {
   this.enableCollapsing(evt);
  },
  enableCollapsingExtended: function(evt) {
   var srcElement = ASPx.Evt.GetEventSource();
   var useShortTime = srcElement && ((src.tagName == "input" && (src.type == "text" || src.type == "password")) || scr.tagName == "textarea");
   this.enableCollapsing(evt, useShortTime);
  },
  enableCollapsing: function(evt, useShortTime) {
   this.contentObserving.collapsingEnabled = true;
   if(this.contentObserving.collapsingTimerID !== -1)
    window.clearTimeout(this.contentObserving.collapsingTimerID);
   this.contentObserving.collapsingTimerID = window.setTimeout(this.disableCollapsing.aspxBind(this), this.contentObserving.collapsingTimeout);
  },
  disableCollapsing: function() {
   this.contentObserving.collapsingTimerID = -1;
   this.contentObserving.collapsingEnabled = false;
  },
  applyAccessibilityAttributes: function() {
   ASPxClientTabControlBase.prototype.applyAccessibilityAttributes.call(this);
   this.setAriaDescription("tabPanel");
  }
 });
 ASPxClientPageControl.Cast = ASPxClientControl.Cast;
 var ASPxClientTab = ASPx.CreateClass(null, {
  constructor: function (tabControl, index, name) {
   this.tabControl = tabControl;
   this.index = index;
   this.name = name;
   this.enabled = true;
   this.clientEnabled = true;
   this.visible = true;
   this.clientVisible = true;
   this.newLine = false;
  },
  GetEnabled: function () {
   return this.enabled && this.clientEnabled;
  },
  SetEnabled: function (value, doNotChangeActiveTab) {
   if(this.clientEnabled != value) {
    this.clientEnabled = value;
    this.tabControl.SetTabEnabled(this.index, value, false, doNotChangeActiveTab);
   }
  },
  GetImageUrl: function (active) {
   return this.tabControl.GetTabImageUrl(this.index, active);
  },
  SetImageUrl: function (value, active) {
   this.tabControl.SetTabImageUrl(this.index, active, value);
  },
  GetActiveImageUrl: function () {
   return this.tabControl.GetTabImageUrl(this.index, true);
  },
  SetActiveImageUrl: function (value) {
   this.tabControl.SetTabImageUrl(this.index, true, value);
  },
  GetNavigateUrl: function () {
   return this.tabControl.GetTabNavigateUrl(this.index);
  },
  SetNavigateUrl: function (value) {
   this.tabControl.SetTabNavigateUrl(this.index, value);
  },
  GetText: function () {
   return this.tabControl.GetTabText(this.index);
  },
  SetText: function (value) {
   this.tabControl.SetTabText(this.index, value);
  },
  GetVisible: function () {
   return this.visible && this.clientVisible;
  },
  SetVisible: function (value) {
   if(this.clientVisible != value) {
    this.tabControl.SetTabVisible(this.index, value, false);
   }
  }
 });
 var ASPxClientTabControlTabEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
  constructor: function (tab, htmlElement, htmlEvent) {
   this.constructor.prototype.constructor.call(this);
   this.tab = tab;
  }
 });
 var ASPxClientTabControlTabCancelEventArgs = ASPx.CreateClass(ASPxClientProcessingModeCancelEventArgs, {
  constructor: function (processOnServer, tab) {
   this.constructor.prototype.constructor.call(this, processOnServer);
   this.tab = tab;
   this.reloadContentOnCallback = false;
  }
 });
 var ASPxClientTabControlTabClickEventArgs = ASPx.CreateClass(ASPxClientTabControlTabCancelEventArgs, {
  constructor: function (processOnServer, tab, htmlElement, htmlEvent) {
   this.constructor.prototype.constructor.call(this, processOnServer, tab);
   this.htmlElement = htmlElement;
   this.htmlEvent = htmlEvent;
  }
 });
 ASPx.TCTClick = function(evt, name, index) {
  var tc = ASPx.GetControlCollection().Get(name);
  if(tc != null) tc.OnTabClick(evt, index);
 };
 function aspxTabStateChanged(source, args) {
  var postfixIndex = args.item.name.lastIndexOf("_");
  var postfix = args.item.name.substring(postfixIndex + 1);
  if(!ASPxClientTabControlBase.IsTabChildElementID(postfix))
   return;
  var tcName = args.item.name.substring(0, postfixIndex);
  var tc = ASPx.GetControlCollection().Get(tcName);
  if(tc && tc.CorrectTabHeightOnStateChanged)
   tc.CorrectTabHeightOnStateChanged(args.element);
 }
 var TabControlScrollingManager = ASPx.CreateClass(ASPx.MouseScrollingManager, {
  setParentNodeOverflow: function() { }
 });
 var PageControlCollection = ASPx.CreateClass(ASPxClientControlCollection, {
  constructor: function() {
   this.constructor.prototype.constructor.call(this);
   this.initEvents();
  },
  GetCollectionType: function(){
   return "PageControl";
  },
  initEvents: function() {
   if(!(ASPx.Browser.IE && ASPx.Browser.MajorVersion == 10 && !ASPx.Browser.TouchUI)) return;
   ASPx.Evt.AttachEventToDocument("mousedown", this.onMouseDown.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("mouseup", this.onMouseUp.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("mousemove", this.onMouseMove.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("mouseclick", this.onMouseClick.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("keydown", this.onKeyDown.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("keyup",  this.onKeyUp.aspxBind(this));
   ASPx.Evt.AttachEventToDocument("keypress", this.onKeyPress.aspxBind(this));
  },
  raiseEventHandler: function(handlerName, evt) {
   this.ForEachControl(function(control) {
    if(control.IsDOMInitialized())
     control[handlerName](evt);
   });
  },
  onMouseDown: function(evt) {
   this.raiseEventHandler("onDocumentMouseDown", evt);
  },
  onMouseUp: function(evt) {
   this.raiseEventHandler("onDocumentMouseUp", evt);
  },
  onMouseMove: function(evt) {
   this.raiseEventHandler("onDocumentMouseMove", evt);
  },
  onMouseClick: function(evt) {
   this.raiseEventHandler("onDocumentMouseClick", evt);
  },
  onKeyDown: function(evt) {
   this.raiseEventHandler("onDocumentKeyDown", evt);
  },
  onKeyUp: function(evt) {
   this.raiseEventHandler("onDocumentKeyUp", evt);
  },
  onKeyPress: function(evt) {
   this.raiseEventHandler("onDocumentKeyPress", evt);
  }
 });
 var pageControlCollection = null;
 function getPageControlCollection() {
  if(pageControlCollection == null)
   pageControlCollection  = new PageControlCollection();
  return pageControlCollection;
 }
 var LayoutManagerBase = ASPx.CreateClass(null, {
  constructor: function(tabControl) {
   this.tabControl = tabControl;
  },
  isContentObservingEnabled: function() {
   return false;
  },
  isCollapsingInObservingEnabled: function() {
   return false;
  },
  isContentAdjustmentRequired: function() {
   return false;
  },
  isContentCollapsingRequired: function() {
   return false;
  },
  isAdjustmenRequiredByNewSizes: function(sizes, newSizes, error) {
   return false;
  },
  needCollapseControl: function() {
   return false;
  },
  areEqualValues: function(val1, val2, error) {
   return this.tabControl.areEqualValues(val1, val2, error);
  },
  enableContentObservation: function() {
  },
  calculateSizes: function() {
  },
  adjustSize: function() {
  },
  collapseTabStrip: function() {
  },
  adjustSizeOnContentModification: function() {
  },
  expandTabStrip: function() {
  },
  getScrollableAreaWidth: function() {
   return 0;
  },
  updateTabStripImagesSizes: function() {
  },
  prepareTabStripForImageLoading: function() {
  },
  adjustScrollVisibleAreaWidth: function() {
  },
  createTabHeightManager: function() {
   return null;
  },
  inlineInitialize: function() {
  }
 });
 var FixedLayoutManager = ASPx.CreateClass(LayoutManagerBase, {
  constructor: function(tabControl) {
   this.constructor.prototype.constructor.call(this, tabControl);
  },
  isContentObservingEnabled: function() {
   return true;
  },
  isCollapsingInObservingEnabled: function() {
   return true;
  },
  isContentAdjustmentRequired: function() {
   return !!this.tabControl.GetMainElement().style.height;
  },
  isContentCollapsingRequired: function() {
   return this.isContentAdjustmentRequired();
  },
  isAdjustmenRequiredByNewSizes: function(sizes, newSizes, error) {
   var control = this.tabControl;
   var checkOnlyPrimarySize = control.emptyHeight && control.contentObserving.collapsingEnabled;
   return checkOnlyPrimarySize
    ? !this.areEqualValues(sizes[control.primaryDimension], newSizes[control.primaryDimension], error)
    : !(this.areEqualValues(sizes.width, newSizes.width, error) && this.areEqualValues(sizes.height, newSizes.height, error));
  },
  needCollapseControl: function() {
   return true;
  },
  enableContentObservation: function() {
   this.tabControl.adjustedSizes = this.tabControl.GetAdjustedSizes();
  },
  calculateSizes: function() {
   this.tabControl.calculateSizesCore();
  },
  adjustSizeOnContentModification: function() {
   var control = this.tabControl;
   control.DoSafeScrollPositionOperation(function() {
    control.adjustControlInternal();
   });
  },
  adjustSize: function() {
   this.tabControl.adjustTabControlSizeCore();
  },
  collapseTabStrip: function() {
   this.tabControl.collapseTabStrip();
  },
  expandTabStrip: function() {
   this.tabControl.expandTabStrip();
  },
  getScrollableAreaWidth: function() {
   return this.tabControl.getScrollableAreaWidthCore();
  },
  updateTabStripImagesSizes: function() {
   this.tabControl.UpdateTabStripImagesSizes();
  },
  prepareTabStripForImageLoading: function() {
   this.tabControl.PrepareTabStripForImageLoading();
  },
  adjustScrollVisibleAreaWidth: function() {
   this.tabControl.AdjustScrollVisibleAreaWidth();
  },
  createTabHeightManager: function() {
   return this.tabControl.createTabHeightManagerCore();
  },
  inlineInitialize: function() {
   this.tabControl.initFixedLayoutInline();
  }
 });
 var FlexLayoutManager = ASPx.CreateClass(LayoutManagerBase, {
  constructor: function(tabControl) {
   this.constructor.prototype.constructor.call(this, tabControl);
   this.tabHeightManager = null;
  },
  inlineInitialize: function() {
   var control = this.tabControl;
   if(!control.hasContent || control.IsTopBottomTabPosition() || control.heightValueSetInPercentage)
    return;
   var contentContainer = control.GetContentsCell();
   ASPx.AddClassNameToElement(contentContainer, Constants.CssClassName.AUTO_HEIGHT);
  },
  isContentObservingEnabled: function() {
   return this.isTabScrollingEnabled() || this.isCollapsingInObservingEnabled();
  },
  isCollapsingInObservingEnabled: function() {
   return this.needCollapseControl();
  },
  isContentAdjustmentRequired: function() {
   return this.needAdjustContentHeight();
  },
  isContentCollapsingRequired: function() {
   return this.needCollapseContent();
  },
  isAdjustmenRequiredByNewSizes: function(sizes, newSizes, error) {
   if(this.needRefreshTabStrip())
    return false;
   var dimension = this.isTabScrollingEnabled() ? "width" : "height";
   return !this.areEqualValues(sizes[dimension], newSizes[dimension], error);
  },
  needAdjustContentHeight: function() {
   var control = this.tabControl;
   return control.IsTopBottomTabPosition()
    ? !control.emptyHeight
    : !(control.emptyHeight || control.heightValueSetInPercentage);
  },
  needCollapseContent: function() {
   return this.tabControl.IsTopBottomTabPosition() && this.tabControl.heightValueSetInPercentage;
  },
  needRefreshTabStrip: function() {
   var control = this.tabControl;
   return ASPx.Browser.Edge && control.hasTabStip && !control.IsTopBottomTabPosition();
  },
  needCollapseControl: function() {
   return this.needCollapseContent() || this.needRefreshTabStrip();
  },
  isTabScrollingEnabled: function() {
   return this.tabControl.enableScrolling;
  },
  calculateSizes: function() {
   var tabControl = this.tabControl;
   tabControl.updateContentAdjustmentFlags();
   this.tabHeightManager.adjustTabs();
   if(!tabControl.isControlCollapsed)
    tabControl.CollapseControl();
   tabControl.isControlCollapsed = false;
   var stripSizes = { primary: 0, secondary: 0 },
    controlSizes = { };
   var stripContainer = this.tabControl.GetTabStripContainer();
   if(tabControl.IsTopBottomTabPosition() && !tabControl.emptyHeight)
    stripSizes.secondary = tabControl.GetCachedElementInnerSize(stripContainer, "height");
   tabControl.calculateMainElementSizes();
   controlSizes.primary = tabControl.adjustmentVars.mainElementSizes.primary;
   controlSizes.secondary = tabControl.adjustmentVars.mainElementSizes.secondary;
   tabControl.adjustmentVars.stripSizes = stripSizes;
   tabControl.adjustmentVars.controlSizes = controlSizes;
   tabControl.CalculateContentHeight();
   this.expandTabStrip();
  },
  adjustSize: function() {
   this.calculateSizes();
   this.tabControl.AdjustPageContents();
  },
  adjustSizeOnContentModification: function() {
   var control = this.tabControl;
   if(this.needCollapseContent())
    control.adjustControlInternal();
   else
    control.adjustTabStripScrolling(true);
  },
  collapseTabStrip: function() {
   if(this.needRefreshTabStrip()) {
    var stripContainer = this.tabControl.GetTabStripContainer();
    stripContainer.style.height = "auto";
   }
  },
  expandTabStrip: function() {
   if(this.needRefreshTabStrip()) {
    var stripContainer = this.tabControl.GetTabStripContainer();
    stripContainer.style.height = "";
   }
  },
  getScrollableAreaWidth: function() {
   var scrollableArea = this.tabControl.GetScrollableArea();
   var items = ASPx.GetChildElementNodes(scrollableArea);
   var width = 0;
   for(var i = 0, item; item = items[i]; i++) {
    if(item.className.indexOf(Constants.CssClassName.TAB_FILLER) == -1)
     width += this.tabControl.GetCachedElementSize(item);
   }
   return width;
  },
  createTabHeightManager: function() {
   var strip = this.tabControl.GetTabsCell();
   var useManager = this.tabControl.IsTopBottomTabPosition() && strip && strip.className.indexOf(Constants.CssClassName.PINNED_TAB_HEADERS) == -1;
   this.tabHeightManager = useManager ? new FlexTabHeightManager(this.tabControl) : new FakeTabHeightManager();
   return this.tabHeightManager;
  }
 });
 var ASPxClientRibbonTabControl = ASPx.CreateClass(ASPxClientTabControl, {
  getTabActivationHtmlEventName: function() {
   return ASPx.Browser.TouchUI ? "onclick" : "onmousedown";
  }
 });
 ASPx.GetPageControlCollection = getPageControlCollection;
 ASPx.TabControlRenderHelper = TabControlRenderHelper;
 ASPx.FakeTabHeightManager = FakeTabHeightManager;
 ASPx.LayoutManagerBase = LayoutManagerBase;
 window.ASPxClientTabControlBase = ASPxClientTabControlBase;
 window.ASPxClientPageControl = ASPxClientPageControl;
 window.ASPxClientTabControl = ASPxClientTabControl;
 window.ASPxClientTab = ASPxClientTab;
 window.ASPxClientTabControlTabClickEventArgs = ASPxClientTabControlTabClickEventArgs;
 window.ASPxClientTabControlTabCancelEventArgs = ASPxClientTabControlTabCancelEventArgs;
 window.ASPxClientTabControlTabEventArgs = ASPxClientTabControlTabEventArgs;
 window.ASPxClientRibbonTabControl = ASPxClientRibbonTabControl;
})();

(function() {
var MVCxClientPageControl = ASPx.CreateClass(ASPxClientPageControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 PerformCallback: function(data, onSuccess) {
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, data);
  ASPxClientPageControl.prototype.PerformCallback.call(this, data, onSuccess);
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(arg), this.callbackCustomArgs); }; 
  ASPxClientPageControl.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  ASPx.Data.MergeHashTables(this.callbackCustomArgs, args.customArgs);
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 CreateCallbackCore: function(arg, command, callbackID) {
  if(this.callbackCustomArgs != {})
   window.setTimeout(function() { this.callbackCustomArgs = {}; }.aspxBind(this), 0);
  ASPxClientPageControl.prototype.CreateCallbackCore.call(this, arg, command, callbackID);
 },
 GetCallbackParams: function(arg){
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientPageControl.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result.html = resultStringParts[1];
   return resultObj;
  }
  return ASPxClientPageControl.prototype.EvalCallbackResult.call(this, resultString);
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientPageControl.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientPageControl.Cast = ASPxClientControl.Cast;
window.MVCxClientPageControl = MVCxClientPageControl;
})();

(function() {
var MVCxClientTreeView = ASPx.CreateClass(ASPxClientTreeView, {
 NodesInfoHiddenInputIDPostfix: "_NIHF",
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.callbackUrl = "";
  this.callbackCustomArgs = {};
 },
 InlineInitialize: function(){
  if(this.callbackUrl != "")
   this.callBack = function(arg){ MVCx.PerformControlCallback(this.name, this.callbackUrl, arg, this.GetCallbackParams(), this.callbackCustomArgs); }; 
  ASPxClientTreeView.prototype.InlineInitialize.call(this);
 },
 RaiseBeginCallbackInternal: function(command) {
  var args = new MVCxClientBeginCallbackEventArgs(command);
  if(!this.BeginCallback.IsEmpty())
   this.BeginCallback.FireEvent(this, args);
  this.callbackCustomArgs = args.customArgs;
 },
 CreateCallbackByInfo: function(arg, command, callbackInfo) {
  this.CreateCallbackInternal(arg, command, true, callbackInfo);
 },
 EvalCallbackResult: function(resultString){
  var resultStringParts = resultString.split(MVCx.CallbackHtmlContentPrefix);
  if(resultStringParts.length == 2){
   var resultObj = ASPxClientTreeView.prototype.EvalCallbackResult.call(this, resultStringParts[0]);
   resultObj.result[2] = resultObj.result[2].replace(MVCx.CallbackHtmlContentPlaceholder, resultStringParts[1]);
   return resultObj;
  }
  return ASPxClientTreeView.prototype.EvalCallbackResult.call(this, resultString);
 },
 GetCallbackParams: function(){
  var params = {};
  MVCx.AddCallbackParam(params, this.GetStateHiddenField());
  MVCx.AddCallbackParamsInContainer(params, this.GetMainElement());
  return params;
 },
 OnCallback: function (resultObj) {
  ASPxClientTreeView.prototype.OnCallback.call(this, resultObj);
  if(resultObj && resultObj[0] == this.ExpandNodeCommand)
   this.stateObject.nodesInfo = resultObj[resultObj.length - 1];
 },
 OnCallbackGeneralError: function(errorMessage) {
  ASPxClientTreeView.prototype.OnCallbackGeneralError.call(this, errorMessage);
  if(!this.serverExceptionOnLastCallback)
   MVCx.ThrowExceptionOnCallback();
 }
});
MVCxClientTreeView.Cast = ASPxClientControl.Cast;
window.MVCxClientTreeView = MVCxClientTreeView;
})();

(function() {
var ClassNames = {
 Container: "dx-fab-container",
 Button: "dx-fab-button",
 Action: "dx-fab-action",
 MainButton: "dx-fab-main-button",
 CloseButton: "dx-fab-close-button",
 TextContainer: "dx-fab-text",
 ContextButtonWithText: "dx-fab-context-with-text",
 ContentContainer: "dx-fab-content",
 ContextText: "dx-fab-context-text",
 ContextImagesContainer: "dx-fab-image-container",
 TextAlwaysVisible: "dx-fab-text-always-visible",
 TextHidden: "dx-fab-text-hidden",
 TextVisibleOnHover: "dx-fab-text-visible-on-hover",
 ActiveMainButton: "dx-fab-active-button",
 HiddenMainButton: "dx-fab-hidden-button",
 ActionsExpanded: "dx-fab-actions-expanded",
 ActionsVisible: "dx-fab-actions-visible",
 StickyPosition: "dx-fab-sticky-position",
 JsPosition: "dx-fab-js-position",
 FixedPosition: "dx-fab-fixed-position"
};
var VerticalPositionClassNames = {
 Bottom: "dx-fab-v-bottom",
 Top: "dx-fab-v-top",
 TopEdge: "dx-fab-v-top-edge"
};
var HorizontalPositionClassNames = {
 LeftEdge: "dx-fab-h-left-edge",
 Left: "dx-fab-h-left",
 Center: "dx-fab-h-center",
 Right: "dx-fab-h-right"
};
var PositionMode = {
 Sticky: "Sticky",
 Fixed: "Fixed",
 JS: "JS"
};
var ButtonSize = 56;
var VerticalPosition = {
 Bottom: "Bottom",
 Top: "Top",
 TopEdge: "TopEdge"
};
var HorizontalPosition = {
 LeftEdge: "LeftEdge",
 Left: "Left",
 Center: "Center",
 Right: "Right"
};
var TextVisibilityMode = {
 Always: "Always",
 OnHover: "OnHover",
 Hidden: "Hidden"
};
var ASPxClientFloatingActionButtonCollapseReason = {
 API: "API",
 CollapseButton: "CollapseButton",
 ActionButton: "ActionItem"
};
var ASPxClientFABActionItemBase = ASPx.CreateClass(null, {
 constructor: function(fab) {
  this.fab = fab;
  this.element = null;
  this.visible = true;
 },
 init: function(data) {
  this.actionName = data.actionName;
  this.text = data.text;
  this.image = data.image;
  this.cssClass = data.cssClass;
  this.element = this.renderButton();
 },
 GetText: function() {
  return this.text;
 },
 SetText: function(value) {
  this.text = value;
  this.recreateTextConteiner();
 },
 GetActionName: function() {
  return this.actionName;
 },
 GetVisible: function() {
  return this.visible;
 },
 SetVisible: function(value) {
  this.visible = value;
 },
 removeTextConteiner: function() {
  var el = this.getTextConteiner();
  if(el)
   ASPx.RemoveElement(el.parentNode);
 },
 getTextConteiner: function() {
 },
 getButton: function() {
  return this.element;
 },
 renderButton: function() {
  var button = this.fab.getRenderer().renderActionButton(this);
  this.attachEvents(button);
  ASPx.SetElementDisplay(button, false);
  return button;
 },
 attachEvents: function(element) {
  ASPx.Evt.AttachEventToElement(element, "click", function() {
   if(this.onClick)
    return this.onClick.apply(this, [this]);
  }.aspxBind(this));
 }
});
var ASPxClientFABActionItem = ASPx.CreateClass(ASPxClientFABActionItemBase, {
 constructor: function(fab) {
  this.constructor.prototype.constructor.call(this, fab);
 },
 getTextConteiner: function() {
  var container = ASPx.GetNodeByClassName(this.getButton(), ClassNames.TextContainer);
  return container ? container.firstChild : null;
 },
 recreateTextConteiner: function() {
  this.removeTextConteiner();
  if(this.GetText())
   this.fab.getRenderer().getFabActionButtonRenderer(this).renderText();
 }
});
var ASPxClientFABAction = ASPx.CreateClass(ASPxClientFABActionItemBase, {
 constructor: function(fab) {
  this.constructor.prototype.constructor.call(this, fab);
  this.actions = [];
 },
 init: function(data) {
  this.contextName = data.contextName;
  this.expandImg = data.expandImg;
  this.collapseImg = data.collapseImg;
  if(data.actionsData) {
   this.actionTransitionDelay = 0;
   this.actions = data.actionsData.map(this.ensureActionButton.aspxBind(this));
  }
  ASPxClientFABActionItemBase.prototype.init.call(this, data);
 },
 renderButton: function(contextData) {
  var button = this.fab.getRenderer().renderContextButton(this, this.fab.defaultImages);
  this.attachEvents(button);
  return button;
 },
 createFABActionItem: function() {
  return new ASPxClientFABActionItem(this.fab);
 },
 ensureActionButton: function(actionData) {
  var item = this.createFABActionItem();
  item.init(actionData);
  item.getButton().style.transitionDelay = this.actionTransitionDelay + "ms";
  this.actionTransitionDelay += 70;
  return item;
 },
 recreateTextConteiner: function() {
  this.removeTextConteiner();
  if(this.GetText())
   this.fab.getRenderer().createContextButtonRenderer(this).renderText(this.element);
 },
 getTextConteiner: function() {
  var conteiner = ASPx.GetNodeByClassName(this.getButton(), ClassNames.ContextText);
  return conteiner ? conteiner.firstChild : null;
 },
 hasVisibleAction: function() {
  if(this.GetActionName())
   return this.GetVisible();
  return this.GetVisible() && this.actions.some(function(action) { return action.GetVisible(); });
 },
 GetContextName: function() {
  return this.contextName;
 },
 GetActionItemCount: function() {
  return this.actions.length;
 },
 GetActionItem: function(index) {
  return this.actions[index];
 },
 GetActionItemByName: function(name) {
  return this.actions.filter(function(action) { return action.GetActionName() === name; })[0];
 }
});
var ASPxClientFloatingActionButton = ASPx.CreateClass(ASPxClientControl, {
 constructor: function(name) {
  this.constructor.prototype.constructor.call(this, name);
  this.ActionItemClick = new ASPxClientEvent();
  this.ContextChanging = new ASPxClientEvent();
  this.ActionExpanding = new ASPxClientEvent();
  this.ActionCollapsing = new ASPxClientEvent();
  this.verticalPosition = VerticalPosition.Bottom;
  this.horizontalPosition = HorizontalPosition.Right;
  this.verticalMargin = 15;
  this.horizontalMargin = 20;
  this.textVisibilityMode = TextVisibilityMode.OnHover;
  this.positionHelper = new FabPositionHelper(this);
  this.containerElementID = "";
  this.closeActionsImage = "";
  this.initialContext = null;
  this.contexts = {};
  this.contextsData = [];
  this.allowUsePositionCssClass = true;
 },
 getCurrentContext: function() {
  return this.contexts[this.currentContext];
 },
 isContextExist: function(name) {
  return !!this.contexts[name];
 },
 getCurrentActions: function(needFiltering) {
  var actions = this.getCurrentContext().actions;
  return needFiltering ? actions.filter(this.actionItemVisibility, this) : actions;
 },
 getButtonContainer: function() {
  return this.container;
 },
 getRenderer: function() {
  if(!this.renderer) {
   this.renderer = new FABRenderer(this.GetMainElement());
  }
  return this.renderer;
 },
 Initialize: function () {
  ASPxClientControl.prototype.Initialize.call(this);
  this.container = this.getRenderer().renderContainer();
  this.positionHelper.initialize();
  this.renderItems();
  this.SetTextVisibilityMode(this.textVisibilityMode);
  if(this.initialContext) {
   this.SetActionContext(this.initialContext);
  }
  this.ensureContainerElement();
 },
 getContainerElement: function() {
  return ASPx.GetElementById(this.containerElementID);
 },
 ensureContainerElement: function() {
  if(this.containerElementID && !this.positionHelper.parent) {
   var element = this.getContainerElement();
   if(element)
    this.SetContainerElement(element);
  }
 },
 OnBrowserWindowResizeInternal: function() {
  this.positionHelper.onWindowResize();
 },
 renderItems: function() {
  this.contextsData.forEach(function(contextData) {
   this.contexts[contextData.contextName] = this.createContext(contextData);
  }.aspxBind(this));
 },
 createContext: function(contextData) {
  return contextData.actionsData
   ? this.createExtendedContext(contextData)
   : this.createContextCore(contextData);
 },
 createFABAction: function() {
  return new ASPxClientFABAction(this);
 },
 createContextCore: function(contextData) {
  var contextItem = this.createFABAction();
  contextItem.init(contextData);
  contextItem.onClick = this.onContextItemClick.aspxBind(this);
  return contextItem;
 },
 createExtendedContext: function(contextData) {
  var context = this.createContextCore(contextData);
  context.actions.forEach(function(action) {
   action.onClick = this.onActionItemClick.aspxBind(this);
  }.aspxBind(this));
  return context;
 },
 onActionItemClick: function(actionItem) {
  this.toggleActions(ASPxClientFloatingActionButtonCollapseReason.ActionButton);
  this.onItemClick(actionItem.actionName);
 },
 onContextItemClick: function(contextItem) {
  if(contextItem.actions.length) {
   this.toggleActions(ASPxClientFloatingActionButtonCollapseReason.CollapseButton);
  }
  else {
   this.onItemClick(contextItem.actionName);
  }
 },
 onItemClick: function(actionName) {
  if(!this.ActionItemClick.IsEmpty()) {
   var args = new ASPxClientFloatingActionButtonActionItemClickEventArgs(actionName);
   this.ActionItemClick.FireEvent(this, args);
  }
 },
 onContextChanging: function(contextName) {
  var context = this.contexts[contextName];
  if(context && !this.ContextChanging.IsEmpty()) {
   var args = this.createContextChangingEventArgs(context);
   this.ContextChanging.FireEvent(this, args);
  }
 },
 createContextChangingEventArgs: function(context) {
  return new ASPxClientFloatingActionButtonContextChangingEventArgs(context);
 },
 toggleActions: function(reason) {
  this.actionsExpanded = !this.actionsExpanded;
  this.ensureContainerElement();
  this.toggleActionsExpand(reason);
 },
 setAnchorElement: function(element) {
  var halfButtonHeight = 23, 
   currentY = 25;
  var diff = element.offsetHeight - currentY - halfButtonHeight;
  ASPx.SetStyles(this.getButtonContainer(), {
   transform: "translateY(" + (-diff) + "px)"
  });
 },
 unsetAnchorElement: function() {
  ASPx.SetStyles(this.getButtonContainer(), {
   transform: "none"
  });
 },
 SetVerticalPosition: function(verticalPosition) {
  this.CollapseActionGroupItems();
  this.positionHelper.setVerticalPosition(verticalPosition);
 },
 SetHorizontalPosition: function(horizontalPosition) {
  this.CollapseActionGroupItems();
  this.positionHelper.setHorizontalPosition(horizontalPosition);
 },
 SetVerticalMargin: function(value) {
  this.positionHelper.setVerticalMargin(value);
 },
 SetHorizontalMargin: function(value) {
  this.positionHelper.setHorizontalMargin(value);
 },
 SetTextVisibilityMode: function(mode) {
  if(this.actualTextVisibilityMode === mode) return;
  this.ensureContainerElement();
  var container = this.getButtonContainer();
  if(this.actualTextVisibilityMode) {
   ASPx.RemoveClassNameFromElement(container, this.getTextVisibilityModeClassName(this.actualTextVisibilityMode));
  }
  ASPx.AddClassNameToElement(container, this.getTextVisibilityModeClassName(mode));
  this.actualTextVisibilityMode = mode;
 },
 getTextVisibilityModeClassName: function(mode) {
  if(mode === TextVisibilityMode.Always)
   return ClassNames.TextAlwaysVisible;
  else if(mode === TextVisibilityMode.OnHover && !ASPx.Browser.TouchUI)
   return ClassNames.TextVisibleOnHover;
  return ClassNames.TextHidden;
 },
 SetContainerElementID: function(id) {
  this.SetContainerElement(ASPx.GetElementById(id));
 },
 SetContainerElement: function(element) {
  this.positionHelper.setContainerElement(element);
 },
 SetActionContext: function(contextName, expand) {
  if(this.currentContext === contextName || !this.someContextsExist())
   return;
  if(this.actionsExpanded) {
   this.toggleActions(ASPxClientFloatingActionButtonCollapseReason.API);
  }
  this.onContextChanging(contextName);
  this.setActionsEnabled(this.currentContext, false);
  this.setActionsEnabled(contextName, true);
  this.currentContext = contextName;
  if(expand && this.canExpandActions()) {
   this.toggleActions();
  }
 },
 ExpandActionGroupItems: function() {
  if(this.isActionGroupContext(this.currentContext) && !this.actionsExpanded)
   this.toggleActions(ASPxClientFloatingActionButtonCollapseReason.API);
 },
 CollapseActionGroupItems: function() {
  if(this.isActionGroupContext(this.currentContext) && this.actionsExpanded)
   this.toggleActions(ASPxClientFloatingActionButtonCollapseReason.API);
 },
 GetAction: function(contextName) {
  return this.isContextExist(contextName) ? this.contexts[contextName] : null;
 },
 setActionContextInternal: function(contextName, expand) {
  if(!this.isContextExist(contextName))
   return;
  if(this.currentContext === contextName && !expand)
   this.CollapseActionGroupItems();
  else
   this.SetActionContext(contextName, expand);
 },
 canExpandActions: function() {
  return this.isActionGroupContext(this.currentContext) && !this.actionsExpanded;
 },
 isActionGroupContext: function(contextName) {
  return this.isContextExist(contextName) && this.getCurrentActions().length > 0;
 },
 GetActionContext: function() {
  return this.currentContext;
 },
 someContextsExist: function() {
  return ASPx.GetObjectKeys(this.contexts).length > 0;
 },
 setActionsEnabled: function(contextName, enabled) {
  if(!contextName) return;
  var context = this.contexts[contextName];
  if(!context)
   return;
  if(enabled && context.hasVisibleAction()) {
   this.ensureContainerElement();
   ASPx.RemoveClassNameFromElement(context.getButton(), ClassNames.HiddenMainButton);
   ASPx.AddClassNameToElement(context.getButton(), ClassNames.ActiveMainButton);
   this.showActions(context.actions);
  }
  else {
   ASPx.RemoveClassNameFromElement(context.getButton(), ClassNames.ActiveMainButton);
   ASPx.AddClassNameToElement(context.getButton(), ClassNames.HiddenMainButton);
   this.hideActions(context.actions);
  }
 },
 hideActions: function(contextActions) {
  contextActions.forEach(this.hideAction, this);
 },
 showActions: function(contextActions) {
  contextActions
   .filter(this.actionItemVisibility, this)
   .forEach(this.showAction, this);
 },
 actionItemVisibility: function(actionItem) {
  return actionItem.GetVisible();
 },
 showAction: function(actionData) {
  ASPx.SetElementDisplay(actionData.element, true);
 },
 hideAction: function(actionData) {
  ASPx.SetElementDisplay(actionData.element, false);
 },
 toggleActionsExpand: function(reason) {
  if(!this.currentContext || !this.isContextExist(this.currentContext)) return;
  if(this.actionsExpanded) {
   this.raiseActionExpanding(this.currentContext);
   this.expandActionsInternal();
  }
  else
   this.raiseActionCollapsing(this.currentContext, reason);
  var toggleCssClass = this.actionsExpanded ? ASPx.AddClassNameToElement : ASPx.RemoveClassNameFromElement;
  toggleCssClass(this.getCurrentContext().getButton(), ClassNames.ActionsExpanded);
  this.getCurrentActions(this.actionsExpanded).forEach(function(actionData) {
   toggleCssClass(actionData.element, ClassNames.ActionsVisible);
  });
 },
 expandActionsInternal: function() {
  if(this.verticalPosition === VerticalPosition.Bottom) {
   this.expandActionsUp();
  }
  else {
   this.expandActionsDown();
  }
 },
 expandActionsUp: function() {
  var bottom = this.getCurrentContext().getButton().offsetHeight + 15;
  this.getCurrentActions(true).forEach(function(actionData) {
   var actionButton = actionData.element;
   ASPx.Attr.RemoveStyleAttribute(actionButton, "top");
   ASPx.SetStyles(actionButton, {
    bottom: bottom
   });
   bottom += actionButton.offsetHeight + 10;
  });
 },
 expandActionsDown: function() {
  var top = 15;
  this.getCurrentActions(true).forEach(function(actionData) {
   var actionButton = actionData.element;
   ASPx.Attr.RemoveStyleAttribute(actionButton, "bottom");
   ASPx.SetStyles(actionButton, {
    top: top
   });
   top += actionButton.offsetHeight + 10;
  });
 },
 raiseActionExpanding: function(currentContext) {
  if(!this.ActionExpanding.IsEmpty()) {
   var args = new ASPxClientFloatingActionButtonActionExpandingEventArgs(currentContext);
   this.ActionExpanding.FireEvent(this, args);
  }
 },
 raiseActionCollapsing: function(currentContext, reason) {
  if(!this.ActionCollapsing.IsEmpty()) {
   var args = new ASPxClientFloatingActionButtonActionCollapsingEventArgs(currentContext, reason);
   this.ActionCollapsing.FireEvent(this, args);
  }
 }
});
var FABRenderer = ASPx.CreateClass(null, {
 constructor: function(mainElement) {
  this.mainElement = mainElement;
 },
 renderContainer: function() {
  this.container = ElementsRenderer.renderDiv(ClassNames.Container);
  this.mainElement.appendChild(this.container);
  return this.container;
 },
 renderActionButton: function(actionData) {
  return this.getFabActionButtonRenderer(actionData).render();
 },
 getFabActionButtonRenderer: function(actionData) {
  return new FabActionButtonRenderer(actionData, null, this.container);
 },
 renderContextButton: function(contextData, defaultImages) {
  return this.createContextButtonRenderer(contextData, defaultImages).render();
 },
 createContextButtonRenderer: function(contextData, defaultImages) {
  if(contextData.actions && contextData.actions.length > 0) {
   return new FabExtendedContextWithTextRenderer(contextData, defaultImages, this.container);
  }
  else {
   return new FabContextButtonWithTextRenderer(contextData, defaultImages, this.container);
  }
 }
});
var ElementsRenderer = (function() {
 var imagesCache = [];
 function renderImage(imageTemplate) {
  if(!imagesCache[imageTemplate]) {
   imagesCache[imageTemplate] = renderImageCore(imageTemplate);
  }
  return imagesCache[imageTemplate].cloneNode(true);
 }
 function renderImageCore(markup) {
  var wrapper;
  if(markup) {
   wrapper = document.createElement("div");
   ASPx.Security.setInnerHtml(wrapper, markup, ASPx.Security.DataType.Trusted);
  }
  return wrapper && wrapper.firstChild;
 }
 function renderBareButton(data, classNames) {
  var button = document.createElement("div");
  classNames = classNames || [];
  classNames.push(ClassNames.Button);
  if(data.cssClass) {
   classNames.push(data.cssClass);
  }
  classNames.forEach(function(className) {
   ASPx.AddClassNameToElement(button, className);
  });
  return button;
 }
 function renderDiv(className) {
  var div = document.createElement("div");
  div.className = className;
  return div;
 }
 return {
  renderDiv: renderDiv,
  renderImage: renderImage,
  renderBareButton: renderBareButton
 };
})();
var FabButtonRendererBase = ASPx.CreateClass(null, {
 constructor: function(data, defaultImages, container) {
  this.data = data;
  this.defaultImages = defaultImages;
  this.container = container;
 },
 render: function() {
  this.button = this.createButton(this.data);
  this.prepareButton();
  this.ensureImages();
  this.renderImages();
  this.renderText(this.button);
  this.container.appendChild(this.button);
  return this.button;
 },
 createButton: function(data) {
  return ElementsRenderer.renderBareButton(data, this.getClassNames());
 },
 getButton: function() {
  if(!this.button)
   this.button = ASPx.GetNodeByClassName(this.container, this.getClassNames()[0]);
  return this.button;
 },
 prepareButton: function() {
 },
 getClassNames: function() {
 },
 ensureImages: function() {
 },
 renderImages: function() {
 },
 createContentImage: function() {
  return ElementsRenderer.renderImage(this.data.image);
 },
 renderText: function(button) {
 }
});
var FabActionButtonRenderer = ASPx.CreateClass(FabButtonRendererBase, {
 getClassNames: function() {
  return [ClassNames.Action];
 },
 renderImages: function() {
  var image = this.createContentImage();
  this.getButton().appendChild(image);
 },
 renderText: function(button) {
  var textContainer = ElementsRenderer.renderDiv(ClassNames.TextContainer);
  if(!this.data.text)
   ASPx.SetElementDisplay(textContainer, false);
  var textField = document.createElement("span");
  if(this.data.text)
   textField.textContent = this.data.text;
  textContainer.appendChild(textField);
  this.getButton().appendChild(textContainer);
 }
});
var FabContextButtonRendererBase = ASPx.CreateClass(FabButtonRendererBase, {
 getClassNames: function() {
  return [ClassNames.MainButton, ClassNames.HiddenMainButton];
 },
 createCloseImage: function() {
  var closeImage = this.data.collapseImg || this.defaultImages.collapseActions;
  var closeImg = ElementsRenderer.renderImage(closeImage);
  ASPx.AddClassNameToElement(closeImg, ClassNames.CloseButton);
  return closeImg;
 },
 ensureExpandImage: function() {
  this.data.image = this.data.image || this.data.expandImg || this.defaultImages.expandActions;
 }
});
var FabContextButtonRenderer = ASPx.CreateClass(FabContextButtonRendererBase, {
 renderImages: function() {
  if(this.data.image) {
   this.getImageContainer().appendChild(this.createContentImage());
  }
 },
 getImageContainer: function() {
  return this.getButton();
 }
});
var FabContextButtonWithTextRenderer = ASPx.CreateClass(FabContextButtonRenderer, {
 getClassNames: function() {
  var classNames = FabContextButtonRenderer.prototype.getClassNames.call(this);
  classNames.push(ClassNames.ContextButtonWithText);
  if(!this.data.autoHideText) {
   classNames.push(ClassNames.ContextTextAlwaysVisible);
  }
  return classNames;
 },
 prepareButton: function() {
  this.renderContentContainer();
 },
 getContentContainer: function(button) {
  if(!this.contentContainer)
   this.contentContainer = ASPx.GetNodeByClassName(button, ClassNames.ContentContainer);
  return this.contentContainer;
 },
 renderContentContainer: function() {
  this.contentContainer = ElementsRenderer.renderDiv(ClassNames.ContentContainer);
  this.getButton().appendChild(this.contentContainer);
 },
 renderText: function(button) {
  var textContainer = ElementsRenderer.renderDiv(ClassNames.ContextText);
  if(!this.data.text)
   ASPx.AddClassNameToElement(textContainer, "dx-fab-context-text-hidden");
  var textField = document.createElement("span");
  if(this.data.text)
   textField.textContent = this.data.text;
  textContainer.appendChild(textField);
  this.getContentContainer(button).appendChild(textContainer);
 },
 getImageContainer: function() {
  return this.ensureImageContainer();
 },
 ensureImageContainer: function() {
  if(!this.imageContainer) {
   this.imageContainer = ElementsRenderer.renderDiv(ClassNames.ContextImagesContainer);
   this.contentContainer.appendChild(this.imageContainer);
  }
  return this.imageContainer;
 }
});
var FabExtendedContextWithTextRenderer = ASPx.CreateClass(FabContextButtonWithTextRenderer, {
 ensureImages: function() {
  this.ensureExpandImage();
 },
 renderImages: function() {
  FabContextButtonWithTextRenderer.prototype.renderImages.call(this);
  var closeImg = this.createCloseImage();
  this.ensureImageContainer().appendChild(closeImg);
 }
});
var FabPositionHelper = ASPx.CreateClass(null, {
 constructor: function(button) {
  this.button = button;
 },
 getMainElement: function() {
  return this.button.GetMainElement();
 },
 initialize: function() {
  this.choosePositionStrategy();
  this.setVerticalPosition(this.button.verticalPosition);
  this.setHorizontalPosition(this.button.horizontalPosition);
  this.setVerticalMargin(this.button.verticalMargin);
  this.setHorizontalMargin(this.button.horizontalMargin);
 },
 setContainerElement: function(container) {
  if(!container || this.parent && container === this.parent)
   return;
  if(this.button.allowUsePositionCssClass && this.parent)
   ASPx.RemoveClassNameFromElement(this.parent, "dx-fab-position");
  container.appendChild(this.getMainElement());
  this.parent = container;
  this.initialize();
  if(this.button.allowUsePositionCssClass && this.positionMode !== PositionMode.Fixed)
   ASPx.AddClassNameToElement(this.parent, "dx-fab-position");
  if(this.positionManager) {
   this.positionManager.setContainerElement(container);
  }
 },
 choosePositionStrategy: function() {
  this.positionMode = this.choosePositionMode();
  this.applyPositionClass();
  this.ensurePositionManagerDisposed();
  if(PositionMode.JS === this.positionMode) {
   this.useJsPositionManager();
  }
 },
 choosePositionMode: function() {
  if(this.button.allowStickyPosition && (ASPx.Browser.SupportsStickyPositioning() || ASPx.Browser.EdgeWebKit)) {
   return PositionMode.Sticky;
  }
  if(this.parent === document.body) {
   return PositionMode.Fixed;
  }
  return PositionMode.JS;
 },
 applyPositionClass: function() {
  if(this.positionClass) {
   ASPx.RemoveClassNameFromElement(this.getMainElement(), this.positionClass);
  }
  this.positionClass = this.getPositionClass();
  ASPx.AddClassNameToElement(this.getMainElement(), this.positionClass);
 },
 getPositionClass: function() {
  switch(this.positionMode) {
   case PositionMode.Sticky:
    return ClassNames.StickyPosition;
   case PositionMode.JS:
    return ClassNames.JsPosition;
   case PositionMode.Fixed:
    return ClassNames.FixedPosition;
  }
 },
 useJsPositionManager: function() {
  this.positionManager = new JsPositionManager(this);
  this.positionManager.initialize();
  if(this.parent) {
   this.positionManager.setContainerElement(this.parent);
  }
 },
 ensurePositionManagerDisposed: function() {
  if(this.positionManager) {
   this.positionManager.dispose();
   this.positionManager = null;
  }
 },
 setVerticalPosition: function(verticalPosition) {
  var container = this.getMainElement();
  if(this.verticalPosition) {
   ASPx.RemoveClassNameFromElement(container, VerticalPositionClassNames[this.verticalPosition]);
  }
  this.verticalPosition = verticalPosition;
  this.button.verticalPosition = verticalPosition;
  ASPx.AddClassNameToElement(container, VerticalPositionClassNames[verticalPosition]);
  this.applyGaps();
 },
 setHorizontalPosition: function(horizontalPosition) {
  var container = this.getMainElement();
  if(this.horizontalPosition) {
   ASPx.RemoveClassNameFromElement(container, HorizontalPositionClassNames[this.horizontalPosition]);
  }
  this.horizontalPosition = horizontalPosition;
  this.button.horizontalPosition = horizontalPosition;
  ASPx.AddClassNameToElement(container, HorizontalPositionClassNames[horizontalPosition]);
  this.applyGaps();
 },
 setVerticalMargin: function(verticalMargin) {
  this.verticalMargin = verticalMargin;
  this.applyGaps();
 },
 setHorizontalMargin: function(horizontalMargin) {
  this.horizontalMargin = horizontalMargin;
  this.applyGaps();
 },
 applyGaps: function() {
  var margins = this.getGapsMargins();
  ASPx.SetStyles(this.getMainElement(), {
   transform: "translate(" + margins[0] + "px, " + margins[1] + "px)"
  });
  if(this.positionManager) {
   this.positionManager.onScroll();
  }
 },
 getGapsMargins: function() {
  var verticalMargin = this.verticalPosition === VerticalPosition.Bottom ? -this.verticalMargin : this.verticalMargin;
  var horizontalMargin = this.horizontalPosition === HorizontalPosition.Right ? -this.horizontalMargin : this.horizontalMargin;
  if(this.verticalPosition === VerticalPosition.Top) {
   verticalMargin += ButtonSize;
  }
  if(this.verticalPosition === VerticalPosition.TopEdge) {
   verticalMargin = ButtonSize / 2;
  }
  if(this.horizontalPosition === HorizontalPosition.LeftEdge
   || (this.horizontalPosition === HorizontalPosition.Center && this.positionMode !== PositionMode.Sticky)) {
   horizontalMargin = -ButtonSize / 2;
   if(this.parent && this.horizontalPosition === HorizontalPosition.LeftEdge) {
    var currentStyle = ASPx.GetCurrentStyle(this.parent);
    if(currentStyle.paddingLeft)
     horizontalMargin -= parseInt(currentStyle.paddingLeft) + 1;
   }
  }
  return [horizontalMargin, verticalMargin];
 },
 onWindowResize: function() {
  if(this.positionManager) {
   this.positionManager.onWindowResize();
  }
 }
});
var JsPositionManager = ASPx.CreateClass(null, {
 constructor: function(positionHelper) {
  this.positionHelper = positionHelper;
  this.buttonElement = positionHelper.getMainElement();
  this.buttonSize = this.buttonElement.offsetHeight || 56;
  this.lastSize = {};
 },
 setContainerElement: function(container) {
  this.container = container;
  this.onScroll();
 },
 initialize: function() {
  this.scrollDelegate = this.onScroll.aspxBind(this);
  ASPx.Evt.AttachEventToElement(window, "scroll", this.scrollDelegate);
  this.onScroll();
 },
 dispose: function() {
  ASPx.Evt.DetachEventFromElement(window, "scroll", this.scrollDelegate);
 },
 onWindowResize: function() {
  this.onScroll();
 },
 onScroll: function() {
  if(!this.shouldChangePositionOnScroll()) return;
  if(!this.container.parentNode) {
    return this.dispose();
  }
  var bodyRect = document.body.getBoundingClientRect();
  var containerRect = this.container.getBoundingClientRect();
  this.alignButtonVertically(bodyRect, containerRect);
  this.alignButtonHorizontally(bodyRect, containerRect);
 },
 shouldChangePositionOnScroll: function() {
  return this.container && this.buttonElement
   && this.positionHelper.horizontalPosition !== HorizontalPosition.LeftEdge
   && this.positionHelper.horizontalPosition !== HorizontalPosition.Center
   && this.positionHelper.verticalPosition !== VerticalPosition.TopEdge;
 },
 alignButtonVertically: function(bodyRect, containerRect) {
  var pageTop = -bodyRect.top,
   pageBottom = pageTop + window.innerHeight,
   containerTop = containerRect.top + pageTop,
   containerBottom = containerTop + containerRect.height,
   margin = this.positionHelper.verticalMargin;
  switch(this.positionHelper.verticalPosition) {
   case VerticalPosition.Bottom:
    this.alignButtonCore(pageTop, pageBottom, containerTop, containerBottom, margin, "marginBottom", true);
    break;
   case VerticalPosition.Top:
    this.alignButtonCore(-pageBottom, -pageTop, -containerBottom, -containerTop, margin, "marginTop", true);
    break;
   default:
    break;
  }
 },
 alignButtonHorizontally: function(bodyRect, containerRect) {
  var pageLeft = -bodyRect.left,
   pageRight = pageLeft + window.innerWidth,
   containerLeft = containerRect.left + pageLeft,
   containerRight = containerLeft + containerRect.width,
   margin = this.positionHelper.horizontalMargin;
  switch(this.positionHelper.horizontalPosition) {
   case HorizontalPosition.Right:
    this.alignButtonCore(pageLeft, pageRight, containerLeft, containerRight, margin, "marginRight", true);
    break;
   case HorizontalPosition.Left:
    this.alignButtonCore(-pageRight, -pageLeft, -containerRight, -containerLeft, margin, "marginLeft", true);
    break;
   default:
    break;
  }
 },
 alignButtonCore: function(minBoundary, maxBoundary, containerMin, containerMax, gap, styleProp, invertOffset) {
  var offset = this.getButtonOffset(minBoundary, maxBoundary, containerMin, containerMax, gap);
  if(offset === null)
   return;
  if(invertOffset)
   offset *= -1;
  if(this.lastSize[styleProp] !== offset) {
   this.buttonElement.style[styleProp] = offset + "px";
   this.lastSize[styleProp] = offset;
  }
 },
 getButtonOffset: function(minBoundary, maxBoundary, containerMin, containerMax, gap) {
  var stickToScreenEdge = maxBoundary <= containerMax,
   containerMinReached = containerMin + this.buttonSize + gap * 2 >= maxBoundary, 
   shouldChangeOffset = !containerMinReached;
  if(!shouldChangeOffset) {
   return null;
  }
  if(stickToScreenEdge) {
   return maxBoundary - containerMax;
  }
  if(!containerMinReached) {
   return 0;
  }
 }
});
var ASPxClientFloatingActionButtonActionItemClickEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(actionName) {
  this.constructor.prototype.constructor.call(this);
  this.actionName = actionName;
 }
});
var ASPxClientFloatingActionButtonActionCollapsingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(contextName, collapseReason) {
  this.constructor.prototype.constructor.call(this);
  this.contextName = contextName;
  this.collapseReason = collapseReason;
 }
});
var ASPxClientFloatingActionButtonActionExpandingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(contextName) {
  this.constructor.prototype.constructor.call(this);
  this.contextName = contextName;
 }
});
var ASPxClientFloatingActionButtonContextChangingEventArgs = ASPx.CreateClass(ASPxClientEventArgs, {
 constructor: function(action) {
  this.constructor.prototype.constructor.call(this);
  this.action = action;
 }
});
ASPx.FabJsPositionManager = JsPositionManager;
ASPx.FABRenderer = FABRenderer;
ASPx.FabButtonRendererBase = FabButtonRendererBase;
window.ASPxClientFloatingActionButton = ASPxClientFloatingActionButton;
window.ASPxClientFloatingActionButtonCollapseReason = ASPxClientFloatingActionButtonCollapseReason;
window.ASPxClientFABActionItem = ASPxClientFABActionItem;
window.ASPxClientFABAction = ASPxClientFABAction;
window.ASPxClientFloatingActionButtonVerticalPosition = VerticalPosition;
window.ASPxClientFloatingActionButtonHorizontalPosition = HorizontalPosition;
window.ASPxClientFloatingActionButtonTextVisibilityMode = TextVisibilityMode;
window.ASPxClientFloatingActionButtonContextChangingEventArgs = ASPxClientFloatingActionButtonContextChangingEventArgs;
window.ASPxClientFloatingActionButtonActionExpandingEventArgs = ASPxClientFloatingActionButtonActionExpandingEventArgs;
window.ASPxClientFloatingActionButtonActionCollapsingEventArgs = ASPxClientFloatingActionButtonActionCollapsingEventArgs;
window.ASPxClientFloatingActionButtonActionItemClickEventArgs = ASPxClientFloatingActionButtonActionItemClickEventArgs;
})();
