k3NGuru

newq

Feb 3rd, 2020
378
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 400.46 KB | None | 0 0
  1.  
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
  5. <head>
  6.     <meta charset="UTF-8">
  7. </head>
  8. <head>
  9.  
  10.     <title>Портал обучения и развития ГК "Белуга Групп"</title>
  11.     <link rel="apple-touch-icon" sizes="180x180" href="download_file.html?file_id=6580249293358135002">
  12.     <link rel="icon" type="image/png" sizes="32x32" href="download_file.html?file_id=6580249740371323075">
  13.     <link rel="icon" type="image/png" sizes="16x16" href="download_file.html?file_id=6580249635751793539">
  14.     <!-- <link rel="manifest" href="/site.webmanifest"> -->
  15.     <link rel="SHORTCUT ICON" type="image/x-icon" href="download_file.html?file_id=6580249487043410683"/>
  16.     <link rel="mask-icon" href="download_file.html?file_id=6580250129698875782" color="#5bbad5">
  17.     <meta name="msapplication-TileColor" content="#da532c">
  18.     <meta name="theme-color" content="#ffffff">
  19.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  20.     <script type="text/javascript" src="scripts/jquery.js" language="javascript"></script>
  21.     <script type="text/javascript" src="scripts/main_functions.js" language="javascript"></script>
  22.     <script type="text/javascript" src="scripts/wt-common.js" language="javascript"></script>
  23.     <script type="text/javascript" src="scripts/wt-game.js" language="javascript"></script>
  24.     <!-- <script type="text/javascript" src="scripts/jquery.ui.totop.js" language="javascript"></script> -->
  25.     <script type="text/javascript" src="scripts/jquery.easing.1.3.js" language="javascript"></script>
  26.     <script type="text/javascript" src="scripts/jqplugins/qtip/jquery.qtip.min.js" language="javascript"></script>
  27.     <link href="wt-game.css" rel="stylesheet" type="text/css"/>
  28.  
  29.         <meta name="viewport" content="width=device-width">
  30.  
  31.     <link href="scripts/jqplugins/qtip/jquery.qtip.min.css" rel="stylesheet" type="text/css"/>
  32.     <link rel="stylesheet" href="fonts/fontico/style.css" type="text/css">
  33.  
  34.  
  35.     <link href="custom_web_template.html?object_id=6034009707764127317" rel="stylesheet" type="text/css"/>
  36.  
  37.     <link rel="stylesheet" href="scripts/extjs-5/build/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all.css" type="text/css">
  38.     <link rel="stylesheet" href="pp/Ext5/player.css" type="text/css">
  39.  
  40.     <link href="custom_web_template.html?object_id=6015134018786367009" rel="stylesheet" type="text/css"/>
  41.  
  42.     <!-- IE9 uses the same CSS rules as W3C. Older versions may need some CSS fixes. Files below are here to apply these fixes. IE6 is not supported anymore -->
  43.     <!--[if lte IE 8]><link rel="stylesheet" type="text/css" href="/ie8-lte.css" /><![endif]-->
  44.     <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/ie7-lte.css" /><![endif]-->
  45. </head>
  46. <link rel="stylesheet" href="fonts/fontico/style.css" type="text/css">
  47.  
  48.  
  49.  
  50.     <link href="/custom_web_template.html?object_id=5725320134341301769" rel="stylesheet" type="text/css"/>
  51.  
  52.     <link href="custom_web_template.html?object_id=6034009707764127317" rel="stylesheet" type="text/css"/>
  53.     <link href="/custom_web_template.html?object_id=6039881813288121903" rel="stylesheet" type="text/css"/>
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60. <link href="/custom_web_template.html?object_code=beluga_assessment_style" rel="stylesheet" type="text/css"/>
  61.  
  62.  
  63. <body id="wt-body" onload="OnLoad()" onresize="OnResize()">
  64.     <script>
  65.     var s = location.href;
  66.     if (s.indexOf("logout:true@") > 0)
  67.     {  
  68.         location.href = window.location.protocol+"//" +window.location.host + window.location.pathname + window.location.search;
  69.     }
  70.     </script>
  71. <script>
  72. /**
  73.  * Intro.js v0.9.0
  74.  * https://github.com/usablica/intro.js
  75.  * MIT licensed
  76.  *
  77.  * Copyright (C) 2013 usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh)
  78.  */
  79.  
  80. (function (root, factory) {
  81.   if (typeof exports === 'object') {
  82.     // CommonJS
  83.     factory(exports);
  84.   } else if (typeof define === 'function' && define.amd) {
  85.    // AMD. Register as an anonymous module.
  86.    define(['exports'], factory);
  87.   } else {
  88.     // Browser globals
  89.     factory(root);
  90.   }
  91. } (this, function (exports) {
  92.   //Default config/variables
  93.   var VERSION = '0.9.0';
  94.  
  95.   /**
  96.    * IntroJs main class
  97.    *
  98.    * @class IntroJs
  99.    */
  100.   function IntroJs(obj) {
  101.     this._targetElement = obj;
  102.  
  103.     this._options = {
  104.       /* Next button label in tooltip box */
  105.       /*nextLabel: 'Next &rarr;',*/
  106.       nextLabel: 'Далее &rarr;',
  107.       /* Previous button label in tooltip box */
  108.      /* prevLabel: '&larr; Back',*/
  109.        prevLabel: '&larr; Назад',
  110.       /* Skip button label in tooltip box */
  111.       /* skipLabel: 'Skip', */
  112.       skipLabel: 'Пропустить',
  113.       /* Done button label in tooltip box */
  114.      /* doneLabel: 'Done',*/
  115.       doneLabel: 'Готово',
  116.       /* Default tooltip box position */
  117.       tooltipPosition: 'bottom',
  118.       /* Next CSS class for tooltip boxes */
  119.       tooltipClass: '',
  120.       /* Close introduction when pressing Escape button? */
  121.       exitOnEsc: true,
  122.       /* Close introduction when clicking on overlay layer? */
  123.       exitOnOverlayClick: true,
  124.       /* Show step numbers in introduction? */
  125.       showStepNumbers: true,
  126.       /* Let user use keyboard to navigate the tour? */
  127.       keyboardNavigation: true,
  128.       /* Show tour control buttons? */
  129.       showButtons: true,
  130.       /* Show tour bullets? */
  131.       showBullets: true,
  132.       /* Scroll to highlighted element? */
  133.       scrollToElement: true,
  134.       /* Set the overlay opacity */
  135.       overlayOpacity: 0.8
  136.     };
  137.   }
  138.  
  139.   /**
  140.    * Initiate a new introduction/guide from an element in the page
  141.    *
  142.    * @api private
  143.    * @method _introForElement
  144.    * @param {Object} targetElm
  145.    * @returns {Boolean} Success or not?
  146.    */
  147.   function _introForElement(targetElm) {
  148.     var introItems = [],
  149.         self = this;
  150.  
  151.     if (this._options.steps) {
  152.       //use steps passed programmatically
  153.       var allIntroSteps = [];
  154.  
  155.       for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) {
  156.        var currentItem = _cloneObject(this._options.steps[i]);
  157.        //set the step
  158.        currentItem.step = introItems.length + 1;
  159.        //use querySelector function only when developer used CSS selector
  160.        if (typeof(currentItem.element) === 'string') {
  161.          //grab the element with given selector from the page
  162.          currentItem.element = document.querySelector(currentItem.element);
  163.        }
  164.  
  165.        //intro without element
  166.        if (typeof(currentItem.element) === 'undefined' || currentItem.element == null) {
  167.          var floatingElementQuery = document.querySelector(".introjsFloatingElement");
  168.  
  169.          if (floatingElementQuery == null) {
  170.            floatingElementQuery = document.createElement('div');
  171.            floatingElementQuery.className = 'introjsFloatingElement';
  172.  
  173.            document.body.appendChild(floatingElementQuery);
  174.          }
  175.  
  176.          currentItem.element  = floatingElementQuery;
  177.          currentItem.position = 'floating';
  178.        }
  179.  
  180.        if (currentItem.element != null) {
  181.          introItems.push(currentItem);
  182.        }
  183.      }
  184.  
  185.    } else {
  186.       //use steps from data-* annotations
  187.      var allIntroSteps = targetElm.querySelectorAll('*[data-intro]');
  188.      //if there's no element to intro
  189.      if (allIntroSteps.length < 1) {
  190.        return false;
  191.      }
  192.      //first add intro items with data-step
  193.      for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
  194.        var currentElement = allIntroSteps[i];
  195.        var step = parseInt(currentElement.getAttribute('data-step'), 10);
  196.        if (step > 0) {
  197.           introItems[step - 1] = {
  198.             element: currentElement,
  199.             intro: currentElement.getAttribute('data-intro'),
  200.             step: parseInt(currentElement.getAttribute('data-step'), 10),
  201.             tooltipClass: currentElement.getAttribute('data-tooltipClass'),
  202.             position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
  203.           };
  204.         }
  205.       }
  206.  
  207.       //next add intro items without data-step
  208.       //todo: we need a cleanup here, two loops are redundant
  209.       var nextStep = 0;
  210.       for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
  211.        var currentElement = allIntroSteps[i];
  212.  
  213.        if (currentElement.getAttribute('data-step') == null) {
  214.  
  215.          while (true) {
  216.            if (typeof introItems[nextStep] == 'undefined') {
  217.              break;
  218.            } else {
  219.              nextStep++;
  220.            }
  221.          }
  222.  
  223.          introItems[nextStep] = {
  224.            element: currentElement,
  225.            intro: currentElement.getAttribute('data-intro'),
  226.            step: nextStep + 1,
  227.            tooltipClass: currentElement.getAttribute('data-tooltipClass'),
  228.            position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
  229.          };
  230.        }
  231.      }
  232.    }
  233.  
  234.    //removing undefined/null elements
  235.    var tempIntroItems = [];
  236.    for (var z = 0; z < introItems.length; z++) {
  237.      introItems[z] && tempIntroItems.push(introItems[z]);  // copy non-empty values to the end of the array
  238.    }
  239.  
  240.    introItems = tempIntroItems;
  241.  
  242.    //Ok, sort all items with given steps
  243.    introItems.sort(function (a, b) {
  244.      return a.step - b.step;
  245.    });
  246.  
  247.    //set it to the introJs object
  248.    self._introItems = introItems;
  249.  
  250.    //add overlay layer to the page
  251.    if(_addOverlayLayer.call(self, targetElm)) {
  252.      //then, start the show
  253.      _nextStep.call(self);
  254.  
  255.      var skipButton     = targetElm.querySelector('.introjs-skipbutton'),
  256.          nextStepButton = targetElm.querySelector('.introjs-nextbutton');
  257.  
  258.      self._onKeyDown = function(e) {
  259.        if (e.keyCode === 27 && self._options.exitOnEsc == true) {
  260.          //escape key pressed, exit the intro
  261.          _exitIntro.call(self, targetElm);
  262.          //check if any callback is defined
  263.          if (self._introExitCallback != undefined) {
  264.            self._introExitCallback.call(self);
  265.          }
  266.        } else if(e.keyCode === 37) {
  267.          //left arrow
  268.          _previousStep.call(self);
  269.        } else if (e.keyCode === 39 || e.keyCode === 13) {
  270.          //right arrow or enter
  271.          _nextStep.call(self);
  272.          //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
  273.          if(e.preventDefault) {
  274.            e.preventDefault();
  275.          } else {
  276.            e.returnValue = false;
  277.          }
  278.        }
  279.      };
  280.  
  281.      self._onResize = function(e) {
  282.        _setHelperLayerPosition.call(self, document.querySelector('.introjs-helperLayer'));
  283.      };
  284.  
  285.      if (window.addEventListener) {
  286.        if (this._options.keyboardNavigation) {
  287.          window.addEventListener('keydown', self._onKeyDown, true);
  288.        }
  289.        //for window resize
  290.        window.addEventListener("resize", self._onResize, true);
  291.      } else if (document.attachEvent) { //IE
  292.        if (this._options.keyboardNavigation) {
  293.          document.attachEvent('onkeydown', self._onKeyDown);
  294.        }
  295.        //for window resize
  296.        document.attachEvent("onresize", self._onResize);
  297.      }
  298.    }
  299.    return false;
  300.  }
  301.  
  302. /*
  303.   * makes a copy of the object
  304.   * @api private
  305.   * @method _cloneObject
  306.  */
  307.  function _cloneObject(object) {
  308.      if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') {
  309.          return object;
  310.      }
  311.      var temp = {};
  312.      for (var key in object) {
  313.          temp[key] = _cloneObject(object[key]);
  314.      }
  315.      return temp;
  316.  }
  317.  /**
  318.   * Go to specific step of introduction
  319.   *
  320.   * @api private
  321.   * @method _goToStep
  322.   */
  323.  function _goToStep(step) {
  324.    //because steps starts with zero
  325.    this._currentStep = step - 2;
  326.    if (typeof (this._introItems) !== 'undefined') {
  327.      _nextStep.call(this);
  328.    }
  329.  }
  330.  
  331.  /**
  332.   * Go to next step on intro
  333.   *
  334.   * @api private
  335.   * @method _nextStep
  336.   */
  337.  function _nextStep() {
  338.    this._direction = 'forward';
  339.  
  340.    if (typeof (this._currentStep) === 'undefined') {
  341.      this._currentStep = 0;
  342.    } else {
  343.      ++this._currentStep;
  344.    }
  345.  
  346.    if ((this._introItems.length) <= this._currentStep) {
  347.      //end of the intro
  348.      //check if any callback is defined
  349.      if (typeof (this._introCompleteCallback) === 'function') {
  350.        this._introCompleteCallback.call(this);
  351.      }
  352.      _exitIntro.call(this, this._targetElement);
  353.      return;
  354.    }
  355.  
  356.    var nextStep = this._introItems[this._currentStep];
  357.    if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
  358.      this._introBeforeChangeCallback.call(this, nextStep.element);
  359.    }
  360.  
  361.    _showElement.call(this, nextStep);
  362.  }
  363.  
  364.  /**
  365.   * Go to previous step on intro
  366.   *
  367.   * @api private
  368.   * @method _nextStep
  369.   */
  370.  function _previousStep() {
  371.    this._direction = 'backward';
  372.  
  373.    if (this._currentStep === 0) {
  374.      return false;
  375.    }
  376.  
  377.    var nextStep = this._introItems[--this._currentStep];
  378.    if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
  379.      this._introBeforeChangeCallback.call(this, nextStep.element);
  380.    }
  381.  
  382.    _showElement.call(this, nextStep);
  383.  }
  384.  
  385.  /**
  386.   * Exit from intro
  387.   *
  388.   * @api private
  389.   * @method _exitIntro
  390.   * @param {Object} targetElement
  391.   */
  392.  function _exitIntro(targetElement) {
  393.    //remove overlay layer from the page
  394.    var overlayLayer = targetElement.querySelector('.introjs-overlay');
  395.  
  396.    //return if intro already completed or skipped
  397.    if (overlayLayer == null) {
  398.      return;
  399.    }
  400.  
  401.    //for fade-out animation
  402.    overlayLayer.style.opacity = 0;
  403.    setTimeout(function () {
  404.      if (overlayLayer.parentNode) {
  405.        overlayLayer.parentNode.removeChild(overlayLayer);
  406.      }
  407.    }, 500);
  408.  
  409.    //remove all helper layers
  410.    var helperLayer = targetElement.querySelector('.introjs-helperLayer');
  411.    if (helperLayer) {
  412.      helperLayer.parentNode.removeChild(helperLayer);
  413.    }
  414.  
  415.    //remove intro floating element
  416.    var floatingElement = document.querySelector('.introjsFloatingElement');
  417.    if (floatingElement) {
  418.      floatingElement.parentNode.removeChild(floatingElement);
  419.    }
  420.  
  421.    //remove `introjs-showElement` class from the element
  422.    var showElement = document.querySelector('.introjs-showElement');
  423.    if (showElement) {
  424.      showElement.className = showElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, ''); // This is a manual trim.
  425.    }
  426.  
  427.    //remove `introjs-fixParent` class from the elements
  428.    var fixParents = document.querySelectorAll('.introjs-fixParent');
  429.    if (fixParents && fixParents.length > 0) {
  430.       for (var i = fixParents.length - 1; i >= 0; i--) {
  431.         fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
  432.       };
  433.     }
  434.  
  435.     //clean listeners
  436.     if (window.removeEventListener) {
  437.       window.removeEventListener('keydown', this._onKeyDown, true);
  438.     } else if (document.detachEvent) { //IE
  439.       document.detachEvent('onkeydown', this._onKeyDown);
  440.     }
  441.  
  442.     //set the step to zero
  443.     this._currentStep = undefined;
  444.   }
  445.  
  446.   /**
  447.    * Render tooltip box in the page
  448.    *
  449.    * @api private
  450.    * @method _placeTooltip
  451.    * @param {Object} targetElement
  452.    * @param {Object} tooltipLayer
  453.    * @param {Object} arrowLayer
  454.    */
  455.   function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer) {
  456.     var tooltipCssClass = '',
  457.         currentStepObj,
  458.         tooltipOffset,
  459.         targetElementOffset;
  460.  
  461.     //reset the old style
  462.     tooltipLayer.style.top        = null;
  463.     tooltipLayer.style.right      = null;
  464.     tooltipLayer.style.bottom     = null;
  465.     tooltipLayer.style.left       = null;
  466.     tooltipLayer.style.marginLeft = null;
  467.     tooltipLayer.style.marginTop  = null;
  468.  
  469.     arrowLayer.style.display = 'inherit';
  470.  
  471.     if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
  472.      helperNumberLayer.style.top  = null;
  473.       helperNumberLayer.style.left = null;
  474.     }
  475.  
  476.     //prevent error when `this._currentStep` is undefined
  477.     if (!this._introItems[this._currentStep]) return;
  478.  
  479.     //if we have a custom css class for each step
  480.     currentStepObj = this._introItems[this._currentStep];
  481.     if (typeof (currentStepObj.tooltipClass) === 'string') {
  482.       tooltipCssClass = currentStepObj.tooltipClass;
  483.     } else {
  484.       tooltipCssClass = this._options.tooltipClass;
  485.     }
  486.  
  487.     tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, '');
  488.  
  489.     //custom css class for tooltip boxes
  490.     var tooltipCssClass = this._options.tooltipClass;
  491.  
  492.     currentTooltipPosition = this._introItems[this._currentStep].position;
  493.     switch (currentTooltipPosition) {
  494.       case 'top':
  495.         tooltipLayer.style.left = '15px';
  496.         tooltipLayer.style.top = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
  497.         arrowLayer.className = 'introjs-arrow bottom';
  498.         break;
  499.       case 'right':
  500.         tooltipLayer.style.left = (_getOffset(targetElement).width + 20) + 'px';
  501.         arrowLayer.className = 'introjs-arrow left';
  502.         break;
  503.       case 'left':
  504.         if (this._options.showStepNumbers == true) {
  505.           tooltipLayer.style.top = '15px';
  506.         }
  507.         tooltipLayer.style.right = (_getOffset(targetElement).width + 20) + 'px';
  508.         arrowLayer.className = 'introjs-arrow right';
  509.         break;
  510.       case 'floating':
  511.         arrowLayer.style.display = 'none';
  512.  
  513.         //we have to adjust the top and left of layer manually for intro items without element
  514.         tooltipOffset = _getOffset(tooltipLayer);
  515.  
  516.         tooltipLayer.style.left   = '50%';
  517.         tooltipLayer.style.top    = '50%';
  518.         tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2)  + 'px';
  519.         tooltipLayer.style.marginTop  = '-' + (tooltipOffset.height / 2) + 'px';
  520.  
  521.         if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
  522.          helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px';
  523.           helperNumberLayer.style.top  = '-' + ((tooltipOffset.height / 2) + 18) + 'px';
  524.         }
  525.  
  526.         break;
  527.       case 'bottom-right-aligned':
  528.         arrowLayer.className      = 'introjs-arrow top-right';
  529.         tooltipLayer.style.right  = '0px';
  530.         tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
  531.         break;
  532.       case 'bottom-middle-aligned':
  533.         targetElementOffset = _getOffset(targetElement);
  534.         tooltipOffset       = _getOffset(tooltipLayer);
  535.  
  536.         arrowLayer.className      = 'introjs-arrow top-middle';
  537.         tooltipLayer.style.left   = (targetElementOffset.width / 2 - tooltipOffset.width / 2) + 'px';
  538.         tooltipLayer.style.bottom = '-' + (tooltipOffset.height + 10) + 'px';
  539.         break;
  540.       case 'bottom-left-aligned':
  541.       // Bottom-left-aligned is the same as the default bottom
  542.       case 'bottom':
  543.       // Bottom going to follow the default behavior
  544.       default:
  545.         tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
  546.         arrowLayer.className = 'introjs-arrow top';
  547.         break;
  548.     }
  549.   }
  550.  
  551.   /**
  552.    * Update the position of the helper layer on the screen
  553.    *
  554.    * @api private
  555.    * @method _setHelperLayerPosition
  556.    * @param {Object} helperLayer
  557.    */
  558.   function _setHelperLayerPosition(helperLayer) {
  559.     if (helperLayer) {
  560.       //prevent error when `this._currentStep` in undefined
  561.       if (!this._introItems[this._currentStep]) return;
  562.  
  563.       var currentElement  = this._introItems[this._currentStep],
  564.           elementPosition = _getOffset(currentElement.element),
  565.           widthHeightPadding = 10;
  566.  
  567.       if (currentElement.position == 'floating') {
  568.         widthHeightPadding = 0;
  569.       }
  570.  
  571.       //set new position to helper layer
  572.       helperLayer.setAttribute('style', 'width: ' + (elementPosition.width  + widthHeightPadding)  + 'px; ' +
  573.                                         'height:' + (elementPosition.height + widthHeightPadding)  + 'px; ' +
  574.                                         'top:'    + (elementPosition.top    - 5)   + 'px;' +
  575.                                         'left: '  + (elementPosition.left   - 5)   + 'px;');
  576.     }
  577.   }
  578.  
  579.   /**
  580.    * Show an element on the page
  581.    *
  582.    * @api private
  583.    * @method _showElement
  584.    * @param {Object} targetElement
  585.    */
  586.   function _showElement(targetElement) {
  587.  
  588.     if (typeof (this._introChangeCallback) !== 'undefined') {
  589.         this._introChangeCallback.call(this, targetElement.element);
  590.     }
  591.  
  592.     var self = this,
  593.         oldHelperLayer = document.querySelector('.introjs-helperLayer'),
  594.         elementPosition = _getOffset(targetElement.element);
  595.  
  596.     if (oldHelperLayer != null) {
  597.       var oldHelperNumberLayer = oldHelperLayer.querySelector('.introjs-helperNumberLayer'),
  598.           oldtooltipLayer      = oldHelperLayer.querySelector('.introjs-tooltiptext'),
  599.           oldArrowLayer        = oldHelperLayer.querySelector('.introjs-arrow'),
  600.           oldtooltipContainer  = oldHelperLayer.querySelector('.introjs-tooltip'),
  601.           skipTooltipButton    = oldHelperLayer.querySelector('.introjs-skipbutton'),
  602.           prevTooltipButton    = oldHelperLayer.querySelector('.introjs-prevbutton'),
  603.           nextTooltipButton    = oldHelperLayer.querySelector('.introjs-nextbutton');
  604.  
  605.       //hide the tooltip
  606.       oldtooltipContainer.style.opacity = 0;
  607.  
  608.       if (oldHelperNumberLayer != null) {
  609.         var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)];
  610.  
  611.         if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) {
  612.          oldHelperNumberLayer.style.opacity = 0;
  613.         }
  614.       }
  615.  
  616.       //set new position to helper layer
  617.       _setHelperLayerPosition.call(self, oldHelperLayer);
  618.  
  619.       //remove `introjs-fixParent` class from the elements
  620.       var fixParents = document.querySelectorAll('.introjs-fixParent');
  621.       if (fixParents && fixParents.length > 0) {
  622.        for (var i = fixParents.length - 1; i >= 0; i--) {
  623.           fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
  624.         };
  625.       }
  626.  
  627.       //remove old classes
  628.       var oldShowElement = document.querySelector('.introjs-showElement');
  629.       oldShowElement.className = oldShowElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, '');
  630.       //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
  631.       if (self._lastShowElementTimer) {
  632.         clearTimeout(self._lastShowElementTimer);
  633.       }
  634.       self._lastShowElementTimer = setTimeout(function() {
  635.         //set current step to the label
  636.         if (oldHelperNumberLayer != null) {
  637.           oldHelperNumberLayer.innerHTML = targetElement.step;
  638.         }
  639.         //set current tooltip text
  640.         oldtooltipLayer.innerHTML = targetElement.intro;
  641.         //set the tooltip position
  642.         _placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer);
  643.  
  644.         //change active bullet
  645.         oldHelperLayer.querySelector('.introjs-bullets li > a.active').className = '';
  646.         oldHelperLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active';
  647.  
  648.         //show the tooltip
  649.         oldtooltipContainer.style.opacity = 1;
  650.         if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1;
  651.       }, 350);
  652.  
  653.     } else {
  654.       var helperLayer       = document.createElement('div'),
  655.           arrowLayer        = document.createElement('div'),
  656.           tooltipLayer      = document.createElement('div'),
  657.           tooltipTextLayer  = document.createElement('div'),
  658.           bulletsLayer      = document.createElement('div'),
  659.           buttonsLayer      = document.createElement('div');
  660.  
  661.       helperLayer.className = 'introjs-helperLayer';
  662.  
  663.       //set new position to helper layer
  664.       _setHelperLayerPosition.call(self, helperLayer);
  665.  
  666.       //add helper layer to target element
  667.       this._targetElement.appendChild(helperLayer);
  668.  
  669.       arrowLayer.className = 'introjs-arrow';
  670.  
  671.       tooltipTextLayer.className = 'introjs-tooltiptext';
  672.       tooltipTextLayer.innerHTML = targetElement.intro;
  673.  
  674.       bulletsLayer.className = 'introjs-bullets';
  675.  
  676.       if (this._options.showBullets === false) {
  677.         bulletsLayer.style.display = 'none';
  678.       }
  679.  
  680.       var ulContainer = document.createElement('ul');
  681.  
  682.       for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) {
  683.        var innerLi    = document.createElement('li');
  684.        var anchorLink = document.createElement('a');
  685.  
  686.        anchorLink.onclick = function() {
  687.          self.goToStep(this.getAttribute('data-stepnumber'));
  688.        };
  689.  
  690.        if (i === 0) anchorLink.className = "active";
  691.  
  692.        anchorLink.href = 'javascript:void(0);';
  693.        anchorLink.innerHTML = "&nbsp;";
  694.        anchorLink.setAttribute('data-stepnumber', this._introItems[i].step);
  695.  
  696.        innerLi.appendChild(anchorLink);
  697.        ulContainer.appendChild(innerLi);
  698.      }
  699.  
  700.      bulletsLayer.appendChild(ulContainer);
  701.  
  702.      buttonsLayer.className = 'introjs-tooltipbuttons';
  703.      if (this._options.showButtons === false) {
  704.        buttonsLayer.style.display = 'none';
  705.      }
  706.  
  707.      tooltipLayer.className = 'introjs-tooltip';
  708.      tooltipLayer.appendChild(tooltipTextLayer);
  709.      tooltipLayer.appendChild(bulletsLayer);
  710.  
  711.      //add helper layer number
  712.      if (this._options.showStepNumbers == true) {
  713.        var helperNumberLayer = document.createElement('span');
  714.        helperNumberLayer.className = 'introjs-helperNumberLayer';
  715.        helperNumberLayer.innerHTML = targetElement.step;
  716.        helperLayer.appendChild(helperNumberLayer);
  717.      }
  718.      tooltipLayer.appendChild(arrowLayer);
  719.      helperLayer.appendChild(tooltipLayer);
  720.  
  721.      //next button
  722.      var nextTooltipButton = document.createElement('a');
  723.  
  724.      nextTooltipButton.onclick = function() {
  725.        if (self._introItems.length - 1 != self._currentStep) {
  726.          _nextStep.call(self);
  727.        }
  728.      };
  729.  
  730.      nextTooltipButton.href = 'javascript:void(0);';
  731.      nextTooltipButton.innerHTML = this._options.nextLabel;
  732.  
  733.      //previous button
  734.      var prevTooltipButton = document.createElement('a');
  735.  
  736.      prevTooltipButton.onclick = function() {
  737.        if (self._currentStep != 0) {
  738.          _previousStep.call(self);
  739.        }
  740.      };
  741.  
  742.      prevTooltipButton.href = 'javascript:void(0);';
  743.      prevTooltipButton.innerHTML = this._options.prevLabel;
  744.  
  745.      //skip button
  746.      var skipTooltipButton = document.createElement('a');
  747.      skipTooltipButton.className = 'introjs-button introjs-skipbutton';
  748.      skipTooltipButton.href = 'javascript:void(0);';
  749.      skipTooltipButton.innerHTML = this._options.skipLabel;
  750.  
  751.      skipTooltipButton.onclick = function() {
  752.        if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
  753.          self._introCompleteCallback.call(self);
  754.        }
  755.  
  756.        if (self._introItems.length - 1 != self._currentStep && typeof (self._introExitCallback) === 'function') {
  757.          self._introExitCallback.call(self);
  758.        }
  759.  
  760.        _exitIntro.call(self, self._targetElement);
  761.      };
  762.  
  763.      buttonsLayer.appendChild(skipTooltipButton);
  764.  
  765.      //in order to prevent displaying next/previous button always
  766.      if (this._introItems.length > 1) {
  767.         buttonsLayer.appendChild(prevTooltipButton);
  768.         buttonsLayer.appendChild(nextTooltipButton);
  769.       }
  770.  
  771.       tooltipLayer.appendChild(buttonsLayer);
  772.  
  773.       //set proper position
  774.       _placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer);
  775.     }
  776.  
  777.     if (this._currentStep == 0 && this._introItems.length > 1) {
  778.      prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled';
  779.       nextTooltipButton.className = 'introjs-button introjs-nextbutton';
  780.       skipTooltipButton.innerHTML = this._options.skipLabel;
  781.     } else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) {
  782.       skipTooltipButton.innerHTML = this._options.doneLabel;
  783.       prevTooltipButton.className = 'introjs-button introjs-prevbutton';
  784.       nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled';
  785.     } else {
  786.       prevTooltipButton.className = 'introjs-button introjs-prevbutton';
  787.       nextTooltipButton.className = 'introjs-button introjs-nextbutton';
  788.       skipTooltipButton.innerHTML = this._options.skipLabel;
  789.     }
  790.  
  791.     //Set focus on "next" button, so that hitting Enter always moves you onto the next step
  792.     nextTooltipButton.focus();
  793.  
  794.     //add target element position style
  795.     targetElement.element.className += ' introjs-showElement';
  796.  
  797.     var currentElementPosition = _getPropValue(targetElement.element, 'position');
  798.     if (currentElementPosition !== 'absolute' &&
  799.        currentElementPosition !== 'relative') {
  800.      //change to new intro item
  801.      targetElement.element.className += ' introjs-relativePosition';
  802.     }
  803.  
  804.     var parentElm = targetElement.element.parentNode;
  805.     while (parentElm != null) {
  806.       if (parentElm.tagName.toLowerCase() === 'body') break;
  807.  
  808.       //fix The Stacking Contenxt problem.
  809.       //More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
  810.       var zIndex = _getPropValue(parentElm, 'z-index');
  811.       var opacity = parseFloat(_getPropValue(parentElm, 'opacity'));
  812.       if (/[0-9]+/.test(zIndex) || opacity < 1) {
  813.        parentElm.className += ' introjs-fixParent';
  814.      }
  815.  
  816.      parentElm = parentElm.parentNode;
  817.    }
  818.  
  819.    if (!_elementInViewport(targetElement.element) && this._options.scrollToElement === true) {
  820.      var rect = targetElement.element.getBoundingClientRect(),
  821.        winHeight=_getWinSize().height,
  822.        top = rect.bottom - (rect.bottom - rect.top),
  823.        bottom = rect.bottom - winHeight;
  824.  
  825.      //Scroll up
  826.      if (top < 0 || targetElement.element.clientHeight > winHeight) {
  827.         window.scrollBy(0, top - 30); // 30px padding from edge to look nice
  828.  
  829.       //Scroll down
  830.       } else {
  831.         window.scrollBy(0, bottom + 100); // 70px + 30px padding from edge to look nice
  832.       }
  833.     }
  834.  
  835.     if (typeof (this._introAfterChangeCallback) !== 'undefined') {
  836.         this._introAfterChangeCallback.call(this, targetElement.element);
  837.     }
  838.   }
  839.  
  840.   /**
  841.    * Get an element CSS property on the page
  842.    * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
  843.    *
  844.    * @api private
  845.    * @method _getPropValue
  846.    * @param {Object} element
  847.    * @param {String} propName
  848.    * @returns Element's property value
  849.    */
  850.   function _getPropValue (element, propName) {
  851.     var propValue = '';
  852.     if (element.currentStyle) { //IE
  853.       propValue = element.currentStyle[propName];
  854.     } else if (document.defaultView && document.defaultView.getComputedStyle) { //Others
  855.      propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
  856.     }
  857.  
  858.     //Prevent exception in IE
  859.     if (propValue && propValue.toLowerCase) {
  860.      return propValue.toLowerCase();
  861.     } else {
  862.       return propValue;
  863.     }
  864.   }
  865.  
  866.   /**
  867.    * Provides a cross-browser way to get the screen dimensions
  868.    * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
  869.    *
  870.    * @api private
  871.    * @method _getWinSize
  872.    * @returns {Object} width and height attributes
  873.    */
  874.   function _getWinSize() {
  875.     if (window.innerWidth != undefined) {
  876.       return { width: window.innerWidth, height: window.innerHeight };
  877.     } else {
  878.       var D = document.documentElement;
  879.       return { width: D.clientWidth, height: D.clientHeight };
  880.     }
  881.   }
  882.  
  883.   /**
  884.    * Add overlay layer to the page
  885.    * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
  886.    *
  887.    * @api private
  888.    * @method _elementInViewport
  889.    * @param {Object} el
  890.    */
  891.   function _elementInViewport(el) {
  892.     var rect = el.getBoundingClientRect();
  893.  
  894.     return (
  895.       rect.top >= 0 &&
  896.      rect.left >= 0 &&
  897.      (rect.bottom+80) <= window.innerHeight && // add 80 to get the text right
  898.      rect.right <= window.innerWidth
  899.    );
  900.   }
  901.  
  902.   /**
  903.    * Add overlay layer to the page
  904.    *
  905.    * @api private
  906.    * @method _addOverlayLayer
  907.    * @param {Object} targetElm
  908.    */
  909.   function _addOverlayLayer(targetElm) {
  910.     var overlayLayer = document.createElement('div'),
  911.         styleText = '',
  912.         self = this;
  913.  
  914.     //set css class name
  915.     overlayLayer.className = 'introjs-overlay';
  916.  
  917.     //check if the target element is body, we should calculate the size of overlay layer in a better way
  918.     if (targetElm.tagName.toLowerCase() === 'body') {
  919.       styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;';
  920.       overlayLayer.setAttribute('style', styleText);
  921.     } else {
  922.       //set overlay layer position
  923.       var elementPosition = _getOffset(targetElm);
  924.       if (elementPosition) {
  925.         styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;';
  926.         overlayLayer.setAttribute('style', styleText);
  927.       }
  928.     }
  929.  
  930.     targetElm.appendChild(overlayLayer);
  931.  
  932.     overlayLayer.onclick = function() {
  933.       if (self._options.exitOnOverlayClick == true) {
  934.         _exitIntro.call(self, targetElm);
  935.  
  936.         //check if any callback is defined
  937.         if (self._introExitCallback != undefined) {
  938.           self._introExitCallback.call(self);
  939.         }
  940.       }
  941.     };
  942.  
  943.     setTimeout(function() {
  944.       styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';';
  945.       overlayLayer.setAttribute('style', styleText);
  946.     }, 10);
  947.  
  948.     return true;
  949.   }
  950.  
  951.   /**
  952.    * Get an element position on the page
  953.    * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
  954.    *
  955.    * @api private
  956.    * @method _getOffset
  957.    * @param {Object} element
  958.    * @returns Element's position info
  959.    */
  960.   function _getOffset(element) {
  961.     var elementPosition = {};
  962.  
  963.     //set width
  964.     elementPosition.width = element.offsetWidth;
  965.  
  966.     //set height
  967.     elementPosition.height = element.offsetHeight;
  968.  
  969.     //calculate element top and left
  970.     var _x = 0;
  971.     var _y = 0;
  972.     while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
  973.      _x += element.offsetLeft;
  974.       _y += element.offsetTop;
  975.       element = element.offsetParent;
  976.     }
  977.     //set top
  978.     elementPosition.top = _y;
  979.     //set left
  980.     elementPosition.left = _x;
  981.  
  982.     return elementPosition;
  983.   }
  984.  
  985.   /**
  986.    * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
  987.    * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
  988.    *
  989.    * @param obj1
  990.    * @param obj2
  991.    * @returns obj3 a new object based on obj1 and obj2
  992.    */
  993.   function _mergeOptions(obj1,obj2) {
  994.     var obj3 = {};
  995.     for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
  996.     for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
  997.     return obj3;
  998.   }
  999.  
  1000.   var introJs = function (targetElm) {
  1001.     if (typeof (targetElm) === 'object') {
  1002.       //Ok, create a new instance
  1003.       return new IntroJs(targetElm);
  1004.  
  1005.     } else if (typeof (targetElm) === 'string') {
  1006.       //select the target element with query selector
  1007.       var targetElement = document.querySelector(targetElm);
  1008.  
  1009.       if (targetElement) {
  1010.         return new IntroJs(targetElement);
  1011.       } else {
  1012.         throw new Error('There is no element with given selector.');
  1013.       }
  1014.     } else {
  1015.       return new IntroJs(document.body);
  1016.     }
  1017.   };
  1018.  
  1019.   /**
  1020.    * Current IntroJs version
  1021.    *
  1022.    * @property version
  1023.    * @type String
  1024.    */
  1025.   introJs.version = VERSION;
  1026.  
  1027.   //Prototype
  1028.   introJs.fn = IntroJs.prototype = {
  1029.     clone: function () {
  1030.       return new IntroJs(this);
  1031.     },
  1032.     setOption: function(option, value) {
  1033.       this._options[option] = value;
  1034.       return this;
  1035.     },
  1036.     setOptions: function(options) {
  1037.       this._options = _mergeOptions(this._options, options);
  1038.       return this;
  1039.     },
  1040.     start: function () {
  1041.       _introForElement.call(this, this._targetElement);
  1042.       return this;
  1043.     },
  1044.     goToStep: function(step) {
  1045.       _goToStep.call(this, step);
  1046.       return this;
  1047.     },
  1048.     nextStep: function() {
  1049.       _nextStep.call(this);
  1050.       return this;
  1051.     },
  1052.     previousStep: function() {
  1053.       _previousStep.call(this);
  1054.       return this;
  1055.     },
  1056.     exit: function() {
  1057.       _exitIntro.call(this, this._targetElement);
  1058.     },
  1059.     refresh: function() {
  1060.       _setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer'));
  1061.       return this;
  1062.     },
  1063.     onbeforechange: function(providedCallback) {
  1064.       if (typeof (providedCallback) === 'function') {
  1065.         this._introBeforeChangeCallback = providedCallback;
  1066.       } else {
  1067.         throw new Error('Provided callback for onbeforechange was not a function');
  1068.       }
  1069.       return this;
  1070.     },
  1071.     onchange: function(providedCallback) {
  1072.       if (typeof (providedCallback) === 'function') {
  1073.         this._introChangeCallback = providedCallback;
  1074.       } else {
  1075.         throw new Error('Provided callback for onchange was not a function.');
  1076.       }
  1077.       return this;
  1078.     },
  1079.     onafterchange: function(providedCallback) {
  1080.       if (typeof (providedCallback) === 'function') {
  1081.         this._introAfterChangeCallback = providedCallback;
  1082.       } else {
  1083.         throw new Error('Provided callback for onafterchange was not a function');
  1084.       }
  1085.       return this;
  1086.     },
  1087.     oncomplete: function(providedCallback) {
  1088.       if (typeof (providedCallback) === 'function') {
  1089.         this._introCompleteCallback = providedCallback;
  1090.       } else {
  1091.         throw new Error('Provided callback for oncomplete was not a function.');
  1092.       }
  1093.       return this;
  1094.     },
  1095.     onexit: function(providedCallback) {
  1096.       if (typeof (providedCallback) === 'function') {
  1097.         this._introExitCallback = providedCallback;
  1098.       } else {
  1099.         throw new Error('Provided callback for onexit was not a function.');
  1100.       }
  1101.       return this;
  1102.     }
  1103.   };
  1104.  
  1105.   exports.introJs = introJs;
  1106.   return introJs;
  1107. }));
  1108. </script><script>
  1109. /*смена позиционирования у класса slide-wrap1 для плавной прокрутки верхнего слайдера-меню*/
  1110.  
  1111. var SLIDER_ANIMATION_DELAY = 400;
  1112.  
  1113. $(document).ready(function(){
  1114.     if (window.navigator.appName == "Microsoft Internet Explorer")
  1115.     {
  1116.        // This is an IE browser. What mode is the engine in?
  1117.        if (document.documentMode == 7) //
  1118.         {
  1119.             $("img.icon_of_task").css("margin-top", "0");
  1120.             $(".task_spis_list").css("width", "266px");
  1121.             $("p.day").css("margin-top", "0");
  1122.         }
  1123.     }  
  1124.  
  1125.     var slideWrap = $(".slide-wrap1");
  1126.    
  1127.     $(".slide-item1").mouseover(function() {
  1128.         if (!slideWrap.is(":animated"))
  1129.         {
  1130.             $(this).addClass("slide-item1-hover");
  1131.             css_heigth = $("body").height() -  $(".header_top").eq(0).height() + parseInt($(".top_slider").eq(0).css("padding-top").split("px")[0] )+200;
  1132.             $(".slide-list1").css("height", css_heigth);
  1133.             if ($(this).index() == 3)
  1134.             {
  1135.                 $(this).find(".dropmenu .dropdown_list").css("left", -238);
  1136.             }
  1137.             else
  1138.             {
  1139.                 $(this).find(".dropmenu .dropdown_list").css("left", 226);
  1140.             }
  1141.             // вертикальное центрирование текста:
  1142.             $(this).find(".item_name_many").each(function() {
  1143.                 $(this).css("padding-top", ($(this).parent().outerHeight() - $(this).height()) / 2 - 3);
  1144.             });
  1145.         }
  1146.     });
  1147.     $(".slide-item1").mouseout(function() {
  1148.         if (!slideWrap.is(":animated"))
  1149.         {
  1150.             $(this).removeClass("slide-item1-hover");
  1151.             $(".slide-list1").css("height", "");
  1152.         }
  1153.     });
  1154.    
  1155.     // выравнивание текста главного меню:
  1156.     $(".slide-item1-text").each(function() {
  1157.         $(this).css({
  1158.             top: ($(this).parent().outerHeight() - $(this).outerHeight()) / 2 - 3
  1159.         });
  1160.     });
  1161. });
  1162.  
  1163.  
  1164. /*нижний слайдер с брендами*/
  1165.  
  1166. function htmSlider(){
  1167.     /* Зададим следующие параметры */
  1168.     /* обертка слайдера */
  1169.     var slideWrap = jQuery('.slide-wrap');
  1170.     /* кнопки вперед/назад */
  1171.     var nextLink = jQuery('.next-slide');
  1172.     var prevLink = jQuery('.prev-slide');
  1173.     /* ширина слайда с отступами */
  1174.     var slideWidth = jQuery('.slide-item').outerWidth(true);
  1175.     /* смещение слайдера */
  1176.     var scrollSlider = -slideWidth;
  1177.    
  1178.     w = slideWrap.children().length *(slideWidth);
  1179.     if (w < slideWrap.parent().innerWidth())
  1180.     {
  1181.         nextLink.hide(); prevLink.hide();
  1182.     }
  1183.     else
  1184.     {
  1185.         nextLink.show(); prevLink.show();
  1186.     }
  1187.     /* Клик по ссылке на следующий слайд */
  1188.     nextLink.click(function(){
  1189.         if(!slideWrap.is(':animated')) {
  1190.             slideWrap.find('.slide-item:first').clone().appendTo(slideWrap);
  1191.             slideWrap.animate({left: scrollSlider}, SLIDER_ANIMATION_DELAY, function(){
  1192.                 slideWrap.find('.slide-item:first').remove();
  1193.                 slideWrap.css({'left': 0});
  1194.             });
  1195.         }
  1196.     });
  1197.  
  1198.     /* Клик по ссылке на предыдующий слайд */
  1199.     prevLink.click(function(){
  1200.         if(!slideWrap.is(':animated')) {
  1201.             slideWrap.css({'left': scrollSlider}).find('.slide-item:last').clone().prependTo(slideWrap);
  1202.             slideWrap.animate({left: 0}, SLIDER_ANIMATION_DELAY, function(){
  1203.                 slideWrap.find('.slide-item:last').remove();
  1204.             });
  1205.         }
  1206.     });    
  1207. }
  1208.  
  1209. jQuery(document).ready(function(){
  1210.     /* иницилизируем функцию слайдера */
  1211.     htmSlider();
  1212. });
  1213.  
  1214.  
  1215. /*верхний слайдер-меню*/
  1216.  
  1217. function htmSlider_m(){
  1218.     /* Зададим следующие параметры */
  1219.     /* обертка слайдера */
  1220.     var slideWrap = jQuery('.slide-wrap1');
  1221.     /* кнопки вперед/назад */
  1222.     var nextLink = jQuery('.next-slide1');
  1223.     var prevLink = jQuery('.prev-slide1');
  1224.     /* ширина слайда с отступами */
  1225.     var slideWidth = jQuery('.slide-item1').outerWidth(true);
  1226.     /* смещение слайдера */
  1227.     var scrollSlider = -slideWidth;
  1228.    
  1229.     //
  1230.     w = slideWrap.children().length *(slideWidth);
  1231.     if (w <= slideWrap.parent().innerWidth())
  1232.     {
  1233.         nextLink.hide(); prevLink.hide();
  1234.     }
  1235.     else
  1236.     {
  1237.         nextLink.show(); prevLink.show();
  1238.     }
  1239.     /* Клик по ссылке на следующий слайд */
  1240.     nextLink.click(function(){
  1241.         if(!slideWrap.is(':animated')) {
  1242.             slideWrap.animate({left: scrollSlider}, SLIDER_ANIMATION_DELAY, function(){
  1243.                 slideWrap
  1244.                 .find('.slide-item1:first')
  1245.                 .appendTo(slideWrap)
  1246.                 .parent()
  1247.                 .css({'left': 0});
  1248.                 slideWrap.find("div[num]").each(function(){
  1249.                     if ($(this).attr("rel") != undefined)
  1250.                     {
  1251.                         //$(this).attr("onclick", "window.location ='" + $(this).attr("rel") + "&slider=" + slideWrap.children().eq(0).attr("num") + "'; if (event.stopPropagation){    event.stopPropagation();event.cancelBubble = true;}else{ event.cancelBubble = true;};");
  1252.                         $(this).attr("slide", slideWrap.children().eq(0).attr("num"));
  1253.                     }
  1254.                 }) 
  1255.                 $(".crumbs").eq(0).children().each(function(){
  1256.                     if ($(this).attr("rel") != undefined)
  1257.                     {
  1258.                         //$(this).attr("onclick", "window.location ='" + $(this).attr("rel") + "&slider=" + slideWrap.children().eq(0).attr("num") + "'");
  1259.                         $(this).attr("slide", slideWrap.children().eq(0).attr("num"));
  1260.                     }
  1261.                 });
  1262.             });
  1263.            
  1264.         }
  1265.     });
  1266.  
  1267.     /* Клик по ссылке на предыдующий слайд */
  1268.     prevLink.click(function(){
  1269.         if(!slideWrap.is(':animated')) {
  1270.             slideWrap
  1271.             .css({'left': scrollSlider})
  1272.             .find('.slide-item1:last')
  1273.             .prependTo(slideWrap)
  1274.             .parent()
  1275.             .animate({left: 0}, SLIDER_ANIMATION_DELAY, function(){
  1276.                 slideWrap.find("div[num]").each(function(){
  1277.                     //$(this).attr("onclick", "window.location ='" + $(this).attr("rel") + "&slider=" + slideWrap.children().eq(0).attr("num") + "'; if (event.stopPropagation){    event.stopPropagation();event.cancelBubble = true;} else{ event.cancelBubble = true;};");
  1278.                     $(this).attr("slide", slideWrap.children().eq(0).attr("num"));
  1279.                 })
  1280.                 $(".crumbs").eq(0).children().each(function(){
  1281.                     if ($(this).attr("rel") != undefined)
  1282.                     {
  1283.                         //$(this).attr("onclick", "window.location ='" + $(this).attr("rel") + "&slider=" + slideWrap.children().eq(0).attr("num") + "'");
  1284.                         $(this).attr("slide", slideWrap.children().eq(0).attr("num"));
  1285.                     }
  1286.                 });
  1287.             });
  1288.            
  1289.         }
  1290.     });    
  1291. }
  1292.  
  1293. jQuery(document).ready(function(){
  1294.     /* иницилизируем функцию слайдера */
  1295.     htmSlider_m();
  1296. });
  1297.  
  1298. // Кастомизация элементов ввода:
  1299.  
  1300. var synergyGetSelectElementText = function(selectElement) {
  1301.     try {
  1302.         return selectElement.options[selectElement.selectedIndex].text;
  1303.     } catch(_err) {
  1304.         console.log("synergyGetSelectElementText ERROR : " + _err);
  1305.         return "";
  1306.     }
  1307. };
  1308.  
  1309. function HtmlEscapeString(str)
  1310.     {
  1311.         str = str.replace(/&/g, "&amp;");
  1312.         str = str.replace(/"/g, "&quot;");
  1313.         str = str.replace(/'/g, "&apos;");
  1314.         str = str.replace(/</g, "&lt;");
  1315.         str = str.replace(/>/g, "&gt;");
  1316.         return str;
  1317.     }
  1318.  
  1319. function synergyCustomizeElements() {
  1320.     // Выпадающие списки:
  1321.     $("select.synergy_select_element").each(function() {
  1322.         $(this).removeClass("synergy_select_element");
  1323.         $(this).hide();
  1324.         if ($(this).hasClass("select-disabled")){
  1325.             $(this).wrap("<div class=\"synergy_select_box select-disabled\"></div>");
  1326.         }
  1327.         else{
  1328.             $(this).wrap("<div class=\"synergy_select_box\"></div>");
  1329.         }
  1330.         $(this).after("<p class=\"synergy_select_box_text\">" + synergyGetSelectElementText(this) + "</p><div class=\"synergy_select_box_button\"></div>");
  1331.         var selectBoxDropdown = "<div class=\"synergy_select_box_dropdown\">";
  1332.         for (var i = 0; i < this.options.length; i++)
  1333.         {
  1334.             selectBoxDropdown += "<a index=\"" + i + "\" title=\"" + HtmlEscapeString(this.options[i].text) + "\">" + this.options[i].text + "</a>";
  1335.         }
  1336.         selectBoxDropdown += "</div>";
  1337.         $(this).parent().append(selectBoxDropdown);
  1338.     });
  1339. }
  1340.  
  1341. $(document).ready(function(){
  1342.     synergyCustomizeElements();
  1343.  
  1344.     $("body").click(function(event) {
  1345.         var target = event.target;
  1346.         if($(target).closest(".synergy_select_box.select-disabled").length){return};
  1347.  
  1348.         var dropdownVisible = $("div.synergy_select_box_dropdown:visible").get(0);
  1349.         if (dropdownVisible)
  1350.         {
  1351.             $(dropdownVisible).hide();
  1352.         }
  1353.         var targetSelectBox = $(target).hasClass("synergy_select_box") ? target : $(target).parents("div.synergy_select_box").get(0);
  1354.         if (targetSelectBox)
  1355.         {
  1356.             if ($(target).parent().hasClass("synergy_select_box_dropdown"))
  1357.             {
  1358.                 var selectElement = $(targetSelectBox).children("select").get(0);
  1359.                 selectElement.selectedIndex = parseInt($(target).attr("index"));
  1360.                 $(selectElement).trigger("change");
  1361.                 $(targetSelectBox).children("p").get(0).innerHTML = synergyGetSelectElementText(selectElement);
  1362.             }
  1363.             if (!dropdownVisible || dropdownVisible && $(dropdownVisible).parent().get(0) != targetSelectBox)
  1364.             {
  1365.                 $(targetSelectBox).children("div.synergy_select_box_dropdown").show();
  1366.             }
  1367.         }
  1368.     });
  1369. });
  1370. </script>
  1371. <div class="main-wrapper">
  1372.        
  1373.  
  1374.  
  1375. <script>
  1376.     $('head').append('<meta name="viewport" content="width=device-width">');
  1377. </script>
  1378.             <div id="b-shade" class="b-view-preloader" style="display: block;">
  1379.                 <div class="b-ball-1"></div>
  1380.                 <div class="b-ball-2"></div>
  1381.             </div>
  1382.             <!--HEADER-->
  1383.            
  1384. <script>
  1385.     function getInitials (string) {
  1386.         var names = (string != "" && string != " ") ? string.split(' ') : [];
  1387.         var initials = "";
  1388.  
  1389.         if (names.length > 1) {
  1390.             initials = names[1].substring(0, 1).toUpperCase();
  1391.             initials += (names[1] != "") ? "." : "";
  1392.             initials += names[0].substring(0, 1).toUpperCase();
  1393.             initials += (names[0] != "") ? "." : "";
  1394.         } else {
  1395.             if (names.length != 0) {
  1396.                 initials = string.substring(0, 1).toUpperCase();
  1397.                 initials += ".";
  1398.             }
  1399.         }
  1400.         return initials;
  1401.     }
  1402.  
  1403.     function closeMenu() {
  1404.         $("#work_cabinet_icon").removeClass("active");
  1405.         $("#wk_list").removeClass("active");
  1406.  
  1407.         $("#mob_work_cabinet").toggleClass("active");
  1408.         $("#mob_work_cabinet_content").toggleClass("active");
  1409.     }
  1410.  
  1411.     $(document).ready(function () {
  1412.         var options = {"userID":"6017678077230275438","is_admin":false,"dropdown_menu_items":[{"name":"Мои оцениваемые сотрудники","link_href":"view_doc.html?mode=my_employees_evaluation&amp;doc_id=6631859965698670224"},{"name":"Панель руководителя","link_href":"view_doc.html?mode=boss_panel&amp;doc_id=6335652978792405855"},{"name":"Адаптация сотрудника","link_href":"view_doc.html?mode=adaptation&amp;doc_id=6335653159623287534"},{"name":"Отчет по адаптации","link_href":"view_doc.html?mode=doc_type&amp;object_id=6039881813288121911&amp;doc_id=6335653748949613493"}],"user_roles":["func_manager_menu"],"menuItems":[{"name":"Каталог курсов","link_href":"view_doc.html?mode=edu_catalog&amp;doc_id=6628161676399233617"},{"name":"Документы","link_href":"view_doc.html?mode=lib&amp;doc_id=6628162092753246374"},{"name":"Обучение","link_href":"view_doc.html?mode=doc&amp;doc_id=5800376573543914533"},{"name":"МИРР","link_href":"view_doc.html?mode=self_assessment&amp;doc_id=6631857937049990730"},{"name":"Библиотека","link_href":"view_doc.html?mode=doc&amp;doc_id=6522717384966615904"},{"name":"Заявки","link_href":"view_doc.html?mode=doc&amp;doc_id=6148914691236517176"},{"name":"Вакансии компании","link_href":"view_doc.html?mode=company_vacancys&amp;doc_id=6711191531803911194"}],"avatar":"/download_file.html?file_id=6631996913705945604","fullname":"Лебедев Дмитрий Олегович","scores":0,"scoresText":"баллов","mode":"learning_stat","eventsCount":0,"learnCount":3,"auth_type":"outside","breadcrumbs":[]},
  1413.             mainMenuContainer,
  1414.             mainMobMenuContainer,
  1415.             workCabinetContainer,
  1416.             mobWorkCabinetContainer,
  1417.             roleNamesContainer,
  1418.             mobRoleNamesContainer;
  1419.  
  1420.         //отключаем прелоадер
  1421.         setTimeout(function () {
  1422.             $("#b-shade").hide();
  1423.         }, 2000);
  1424.  
  1425.         //мероприятия
  1426.         $('#header_events, #header_mob_events').text(options.eventsCount);
  1427.  
  1428.         //аватар
  1429.         if (options.avatar.length > 0) {
  1430.             $('#userpic').append(
  1431.                 $('<div/>')
  1432.                     .addClass("b-header__userpic")
  1433.                     .css("background-image", "url("+options.avatar+")")
  1434.             );
  1435.         } else {
  1436.             $('#userpic').append(
  1437.                 $('<div/>')
  1438.                     .addClass("b-user__avatar no-photo header active")
  1439.                     .text(getInitials(options.fullname))
  1440.             );
  1441.         }
  1442.  
  1443.         //меню
  1444.         mainMenuContainer = $('#header_menu_main');
  1445.         mainMobMenuContainer = $('#header_mob_menu_main');
  1446.         options.menuItems.forEach(function (item) {
  1447.             var a = $('<a href="' + item.link_href + '"></a>');
  1448.             a.text(item.name);
  1449.             mainMenuContainer.append(a);
  1450.  
  1451.             var li = $('<li><a href="' + item.link_href + '"></a></li>');
  1452.             $("a", li).text(item.name);
  1453.             mainMobMenuContainer.append(li);
  1454.         });
  1455.  
  1456.         //курсы тесты
  1457.         $('#header_learnings, #header_mob_learnings').text(options.learnCount);
  1458.  
  1459.         //меню рабочего кабинета
  1460.         roleNamesContainer = $('#role_names');
  1461.         mobRoleNamesContainer = $('#mob_role_names');
  1462.         if (options.is_admin) {
  1463.             roleNamesContainer.append(
  1464.                 $("<span/>")
  1465.                     .addClass("b-text__grey")
  1466.                     .text("Администратор")
  1467.             );
  1468.  
  1469.             mobRoleNamesContainer.append(
  1470.                 $("<li/>")
  1471.                     .append(
  1472.                         $("<a/>")
  1473.                             .attr("href", "javascript:void(0);")
  1474.                             .text("Администратор")
  1475.                     )
  1476.             );
  1477.         } else {
  1478.             options.user_roles.forEach(function (item) {
  1479.                 var span = $('<span class="b-text__grey"></span>'),
  1480.                     li = $('<li><a href="javascript:void(0);"></a></li>'),
  1481.                     a = $('a', li);
  1482.                 if (item == "sub_manager_menu") {
  1483.                     span.text("Руководитель подразделения");
  1484.                     a.text("Руководитель подразделения");
  1485.                 } else if (item == "hr_menu") {
  1486.                     span.text("HR");
  1487.                     a.text("HR");
  1488.                 } else if (item == "trainer_menu") {
  1489.                     span.text("Тренер");
  1490.                     a.text("Тренер");
  1491.                 } else if (item == "sv_menu") {
  1492.                     span.text("Супервайзер");
  1493.                     a.text("Супервайзер");
  1494.                 } else if (item == "field_manager_menu") {
  1495.                     span.text("Полевой руководитель");
  1496.                     a.text("Полевой руководитель");
  1497.                 } else if (item == "func_manager_menu") {
  1498.                     span.text("Функциональный руководитель");
  1499.                     a.text("Функциональный руководитель");
  1500.                 } else if (item == "ks_menu") {
  1501.                     span.text("КС");
  1502.                     a.text("КС");
  1503.                 } else if (item == "edu_manager_menu") {
  1504.                     span.text("Ответственный по обучению");
  1505.                     a.text("Ответственный по обучению");
  1506.                 }
  1507.  
  1508.                 roleNamesContainer.append(span);
  1509.                 mobRoleNamesContainer.append(li);
  1510.             });
  1511.         }
  1512.  
  1513.         workCabinetContainer = $('#wk_list');
  1514.         mobWorkCabinetContainer = $('#mob_wk_list');
  1515.         if (options.dropdown_menu_items.length > 0) {
  1516.             options.dropdown_menu_items.forEach(function (item) {
  1517.                 var li = $('<li class="b-header__user-account-item"><a href="' + item.link_href + '" class="b-header__user-account-links">' + item.name + '</a></li>');
  1518.                 workCabinetContainer.append(li);
  1519.  
  1520.                 var mob_li = $('<li/>')
  1521.                                 .append(
  1522.                                     $('<a href="' + item.link_href + '"></a>')
  1523.                                         .text(item.name)
  1524.                                 );
  1525.                 mobWorkCabinetContainer.append(mob_li);
  1526.             });
  1527.         } else {
  1528.             $("#work_cabinet")
  1529.                 .removeClass("b-header__user-link-item")
  1530.                 .text("Личный кабинет")
  1531.                 .css("font-size", "12px")
  1532.                 .css("line-height", "16px");
  1533.  
  1534.             $("#mob_work_cabinet span").text("Личный кабинет");
  1535.             $("#mob_work_cabinet i").remove();
  1536.         }
  1537.         //Хлебные крошки
  1538.         if(options.breadcrumbs.length > 0){
  1539.             options.breadcrumbs.forEach(function(el){
  1540.                 $(".b-breadcrumbs-ul").prepend(
  1541.                     $('<li/>')
  1542.                         .addClass('b-breadcrumbs-item')
  1543.                         .append(
  1544.                             (function(){
  1545.                                 var link = 'javascript:void(0);';
  1546.                                 if (el.template != '') {
  1547.                                     link = el.template;
  1548.                                 } else {
  1549.                                     link = 'view_doc.html?mode=doc&doc_id='+el.id;
  1550.                                 }
  1551.  
  1552.                                 return '<a href="' + link + '" class="b-breadcrumbs-link">' + el.name + '</a>';
  1553.                             })()                            
  1554.                         )
  1555.                 )
  1556.             });
  1557.         } else {
  1558.             $(".b-breadcrumbs").remove();
  1559.         }
  1560.  
  1561.         // скрытие рабочего кабинета
  1562.         $(document).on("click", function(event) {
  1563.             var target_id = event.target.id;
  1564.  
  1565.             if (target_id === "wk_list" || target_id === "work_cabinet_icon" || target_id === "work_cabinet") {
  1566.                 return false;
  1567.             } work_cabinet
  1568.  
  1569.             closeMenu();
  1570.         });
  1571.  
  1572.         //кнопка "рабочий кабинет"
  1573.         $("#work_cabinet_icon, #mob_work_cabinet span").on('click', function () {
  1574.             if (options.dropdown_menu_items.length > 0) {
  1575.                 if ( $("#work_cabinet_icon").hasClass("active")) {
  1576.                     $("#work_cabinet_icon").removeClass("active");
  1577.                     $("#wk_list").removeClass("active");
  1578.                 } else {
  1579.                     $("#work_cabinet_icon").addClass("active");
  1580.                     $("#wk_list").addClass("active");
  1581.                 }
  1582.  
  1583.                 $("#mob_work_cabinet").toggleClass("active");
  1584.                 $("#mob_work_cabinet_content").toggleClass("active");
  1585.             } else {
  1586.                 location.href = "/view_doc.html?mode=profile";
  1587.             }
  1588.         });
  1589.  
  1590.         //кнопка выход
  1591.         $('#header_exit, #mob_exit').on('click', function (event) {
  1592.             if (options.auth_type === 'cookie') {
  1593.                 var sDate = new Date(0).toUTCString();
  1594.                 document.cookie = "user_login=null; path=/; expires=" + sDate + ";";
  1595.                 document.cookie = "user_password=null; path=/; expires=" + sDate + ";";
  1596.                 document.location.href = window.location.protocol + "//" + window.location.host + "/view_doc.html?mode=default&logout=1";
  1597.             } else if (options.auth_type === 'basic') {
  1598.                 var xhr = new XMLHttpRequest();
  1599.                 xhr.open('GET', document.location.origin + '/view_doc.html?mode=home', true);
  1600.                 xhr.setRequestHeader('Authorization', '');
  1601.                 xhr.send();
  1602.                 document.location.href = document.location.origin + '/view_doc.html?mode=default';
  1603.             } else {
  1604.                 try {
  1605.                     if (document.all || !!navigator.userAgent.match(/Trident\/7\./)) {
  1606.                         document.execCommand("ClearAuthenticationCache");
  1607.                         window.history.back();
  1608.                         window.location.href = window.location.protocol + "//" + window.location.host + "/view_doc.html?mode=default&logout=1";
  1609.                     } else {
  1610.                         window.history.back();
  1611.                         window.location.href = window.location.protocol + "//logout:true@" + window.location.host + "/view_doc.html?mode=default&logout=1";
  1612.                     }
  1613.                 }
  1614.                 catch(e)
  1615.                 {}
  1616.             }
  1617.         });
  1618.  
  1619.         //ссылка на my_account
  1620.         $('#header_course_test_link, #header_event_link').on('click', function () {
  1621.             window.open('/view_doc.html?mode=my_account');
  1622.         });
  1623.  
  1624.         $('#mob_work_cabinet, #mob_work_cabinet span').on('click', function () {
  1625.             $('#mob_work_cabinet').toggleClass('active');
  1626.             $('.b-header__icon-open').toggleClass('active');
  1627.             $('.b-header__cabinet-content').toggleClass('active');
  1628.         });
  1629.  
  1630.         //клик по бургеру
  1631.         $(".b-header__toggle-menu").on('click', function(){
  1632.             $('.b-header__mob-menu-container').toggleClass('active');
  1633.             $('.b-header__fixed').toggleClass('active');
  1634.             $('#show-xs').toggleClass('is-close')
  1635.         });
  1636.     });
  1637. </script>
  1638. <script>
  1639.     function preloaderOn(){
  1640.         $("#b-shade").show();
  1641.     }
  1642.     function preloaderOff(){
  1643.         $("#b-shade").hide();
  1644.     }
  1645. </script>
  1646. <header class="b-header">
  1647.     <div class="b-header__mob-menu-container">
  1648.         <div class="b-container">
  1649.             <div class="b-header__mob-menu-but-wrap">
  1650.                 <a href="/view_doc.html?mode=my_account" class="b-header__mob-menu-but">
  1651.                     <div class="b-header__mob-menu-but-container">
  1652.                         <div class="float-left b-header__icon-course b-header__mob-icon-course"></div>
  1653.                         <div class="float-left b-header__icon-test b-header__mob-icon-test"></div>
  1654.                         <div id="header_mob_learnings" class="b-header__user-account-courses-num float-left b-header__mob-text"></div>
  1655.                     </div>
  1656.                 </a>
  1657.                 <a href="/view_doc.html?mode=my_account" class="b-header__mob-menu-but">
  1658.                     <div class="b-header__mob-menu-but-container two">
  1659.                         <div class="float-left b-header__icon-union b-header__mob-icon-union"></div>
  1660.                         <div id="header_mob_events" class="b-header__user-account-star-text float-left b-header__mob-text"></div>
  1661.                     </div>
  1662.                 </a>
  1663.             </div>
  1664.             <div id="mob_work_cabinet" class="b-header__cabinet"><span>Рабочий кабинет</span> <i class="b-icon__open little b-header__icon-open"></i></div>
  1665.             <div id="mob_work_cabinet_content" class="b-header__cabinet-content">
  1666.                 <ul id="mob_role_names" class="b-header__cabinet-breadcrumbs">
  1667.                 </ul>
  1668.                 <div class="b-header__cabinet-nav">
  1669.                     <ul id="mob_wk_list">
  1670.                     </ul>
  1671.                 </div>
  1672.             </div>
  1673.             <div class="b-header__mob-nav">
  1674.                 <ul id="header_mob_menu_main">
  1675.                 </ul>
  1676.             </div>
  1677.             <div class="b-header__mob-points clearfix">
  1678.                 <div class="b-header__mob-points-num">
  1679.                     <span id="header_mob_scores"></span>
  1680.                     <span id="header_mob_scores_text"></span>
  1681.                 </div>
  1682.                 <div class="b-header__mob-exit"><a id="mob_exit" href="javascript:void(0);">Выход <span class="b-icon__exit-white"></span></a></div>
  1683.             </div>
  1684.         </div>
  1685.     </div>
  1686.     <div class="b-container b-header__fixed">
  1687.         <div class="b-header__wrap clearfix">
  1688.             <div class="b-header__mob-menu float-left">
  1689.                 <div id="show-xs" class="b-header__toggle-menu hidden-lg show-xs">
  1690.                     <span class="b-header__toggle-wrapper-elements">
  1691.                         <span class="b-header__toggle-element-first"></span>
  1692.                         <span class="b-header__toggle-element-second"></span>
  1693.                         <span class="b-header__toggle-element-third"></span>
  1694.                     </span>
  1695.                 </div>
  1696.             </div>
  1697.             <div class="b-header__logo clearfix float-left">
  1698.                 <a href="/view_doc.html?mode=home" class="float-left"><img src="download_file.html?file_id=6621495142608807619" alt="logo"></a>
  1699.                 <div class="b-header__logo-text float-left"><span>Портал обучения и развития</span></div>
  1700.             </div>
  1701.             <div class="b-header__user-account-wrap clearfix float-right">
  1702.                 <div class="b-header__user-exit float-right">
  1703.                     <div class="t-icon-exit">
  1704.                         <div class="t-icon-exit__wrap-arrow">
  1705.                             <div class="t-icon-exit__arrow"></div>
  1706.                         </div>
  1707.                         <div class="t-icon-exit__wrap-footer">
  1708.                             <div id="header_exit" class="t-icon-exit__footer"></div>
  1709.                         </div>
  1710.                     </div>
  1711.                 </div>
  1712.                 <div class="b-header__user-account clearfix float-right">
  1713.                     <div class="b-header__user-account-icons clearfix float-left">
  1714.                         <div id="header_course_test_link" class="b-header__user-account-courses clearfix float-left">
  1715.                             <a href="javascript:void(0);" class="b-header__user-courses-link">
  1716.                                 <div class="b-icon-course float-left b-header__icon-course"></div>
  1717.                                 <div class="b-icon-test float-left b-header__icon-test"></div>
  1718.                                 <div id="header_learnings" class="b-header__user-account-courses-num float-left"></div>
  1719.                             </a>
  1720.                         </div>
  1721.                         <div id="header_event_link" class="b-header__user-account-star clearfix float-left">
  1722.                             <a href="javascript:void(0);" class="b-header__user-star-link">
  1723.                                 <div class="b-icon-union float-left b-header__icon-union"></div>
  1724.                                 <div id="header_events" class="b-header__user-account-star-text float-left"></div>
  1725.                             </a>
  1726.                         </div>
  1727.                     </div>
  1728.                     <div id="work_cabinet_icon" class="b-header__user-account-link float-left" style="cursor: pointer">
  1729.                         <a id="work_cabinet" href="javascript:void(0);" class="b-header__user-link-item">Рабочий кабинет</a>
  1730.                         <ul id="wk_list" class="b-header__user-account-wrapper">
  1731.                             <li id="role_names" class="b-header__user-account-item first"></li>
  1732.                         </ul>
  1733.                     </div>
  1734.  
  1735.                     <div class="b-header__user-account-image-wrap float-left">
  1736.                             <a id="userpic" href="/view_doc.html?mode=profile"></a>
  1737.                         </div>
  1738.                 </div>
  1739.             </div>
  1740.         </div>
  1741.         <div class="b-header__nav">
  1742.             <nav id="header_menu_main">
  1743.             </nav>
  1744.         </div>
  1745.     </div>
  1746. </header>
  1747. <!-- Global site tag (gtag.js) - Google Analytics -->
  1748. <script async src="https://www.googletagmanager.com/gtag/js?id=UA-146633021-1"></script>
  1749. <script>
  1750.   window.dataLayer = window.dataLayer || [];
  1751.   function gtag(){dataLayer.push(arguments);}
  1752.   gtag('js', new Date());
  1753.  
  1754.   gtag('config', 'UA-146633021-1');
  1755. </script>
  1756. <div class="b-breadcrumbs">
  1757.     <div class="b-container">
  1758.         <ul class="b-breadcrumbs-ul">
  1759.         </ul>
  1760.     </div>
  1761. </div> 
  1762.         <div class="content">
  1763.             <!--MAIN -->
  1764.             <script>
  1765. /*!
  1766.  * jQuery UI Core 1.9.2
  1767.  * http://jqueryui.com
  1768.  *
  1769.  * Copyright 2012 jQuery Foundation and other contributors
  1770.  * Released under the MIT license.
  1771.  * http://jquery.org/license
  1772.  *
  1773.  * http://api.jqueryui.com/category/ui-core/
  1774.  */
  1775. (function( $, undefined ) {
  1776.  
  1777. var uuid = 0,
  1778.     runiqueId = /^ui-id-\d+$/;
  1779.  
  1780. // prevent duplicate loading
  1781. // this is only a problem because we proxy existing functions
  1782. // and we don't want to double proxy them
  1783. $.ui = $.ui || {};
  1784. if ( $.ui.version ) {
  1785.     return;
  1786. }
  1787.  
  1788. $.extend( $.ui, {
  1789.     version: "1.9.2",
  1790.  
  1791.     keyCode: {
  1792.         BACKSPACE: 8,
  1793.         COMMA: 188,
  1794.         DELETE: 46,
  1795.         DOWN: 40,
  1796.         END: 35,
  1797.         ENTER: 13,
  1798.         ESCAPE: 27,
  1799.         HOME: 36,
  1800.         LEFT: 37,
  1801.         NUMPAD_ADD: 107,
  1802.         NUMPAD_DECIMAL: 110,
  1803.         NUMPAD_DIVIDE: 111,
  1804.         NUMPAD_ENTER: 108,
  1805.         NUMPAD_MULTIPLY: 106,
  1806.         NUMPAD_SUBTRACT: 109,
  1807.         PAGE_DOWN: 34,
  1808.         PAGE_UP: 33,
  1809.         PERIOD: 190,
  1810.         RIGHT: 39,
  1811.         SPACE: 32,
  1812.         TAB: 9,
  1813.         UP: 38
  1814.     }
  1815. });
  1816.  
  1817. // plugins
  1818. $.fn.extend({
  1819.     _focus: $.fn.focus,
  1820.     focus: function( delay, fn ) {
  1821.         return typeof delay === "number" ?
  1822.             this.each(function() {
  1823.                 var elem = this;
  1824.                 setTimeout(function() {
  1825.                     $( elem ).focus();
  1826.                     if ( fn ) {
  1827.                         fn.call( elem );
  1828.                     }
  1829.                 }, delay );
  1830.             }) :
  1831.             this._focus.apply( this, arguments );
  1832.     },
  1833.  
  1834.     scrollParent: function() {
  1835.         var scrollParent;
  1836.         if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
  1837.             scrollParent = this.parents().filter(function() {
  1838.                 return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
  1839.             }).eq(0);
  1840.         } else {
  1841.             scrollParent = this.parents().filter(function() {
  1842.                 return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
  1843.             }).eq(0);
  1844.         }
  1845.  
  1846.         return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
  1847.     },
  1848.  
  1849.     zIndex: function( zIndex ) {
  1850.         if ( zIndex !== undefined ) {
  1851.             return this.css( "zIndex", zIndex );
  1852.         }
  1853.  
  1854.         if ( this.length ) {
  1855.             var elem = $( this[ 0 ] ), position, value;
  1856.             while ( elem.length && elem[ 0 ] !== document ) {
  1857.                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
  1858.                 // This makes behavior of this function consistent across browsers
  1859.                 // WebKit always returns auto if the element is positioned
  1860.                 position = elem.css( "position" );
  1861.                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
  1862.                     // IE returns 0 when zIndex is not specified
  1863.                     // other browsers return a string
  1864.                     // we ignore the case of nested elements with an explicit value of 0
  1865.                     // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
  1866.                     value = parseInt( elem.css( "zIndex" ), 10 );
  1867.                     if ( !isNaN( value ) && value !== 0 ) {
  1868.                         return value;
  1869.                     }
  1870.                 }
  1871.                 elem = elem.parent();
  1872.             }
  1873.         }
  1874.  
  1875.         return 0;
  1876.     },
  1877.  
  1878.     uniqueId: function() {
  1879.         return this.each(function() {
  1880.             if ( !this.id ) {
  1881.                 this.id = "ui-id-" + (++uuid);
  1882.             }
  1883.         });
  1884.     },
  1885.  
  1886.     removeUniqueId: function() {
  1887.         return this.each(function() {
  1888.             if ( runiqueId.test( this.id ) ) {
  1889.                 $( this ).removeAttr( "id" );
  1890.             }
  1891.         });
  1892.     }
  1893. });
  1894.  
  1895. // selectors
  1896. function focusable( element, isTabIndexNotNaN ) {
  1897.     var map, mapName, img,
  1898.         nodeName = element.nodeName.toLowerCase();
  1899.     if ( "area" === nodeName ) {
  1900.         map = element.parentNode;
  1901.         mapName = map.name;
  1902.         if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
  1903.             return false;
  1904.         }
  1905.         img = $( "img[usemap=#" + mapName + "]" )[0];
  1906.         return !!img && visible( img );
  1907.     }
  1908.     return ( /input|select|textarea|button|object/.test( nodeName ) ?
  1909.         !element.disabled :
  1910.         "a" === nodeName ?
  1911.             element.href || isTabIndexNotNaN :
  1912.             isTabIndexNotNaN) &&
  1913.         // the element and all of its ancestors must be visible
  1914.         visible( element );
  1915. }
  1916.  
  1917. function visible( element ) {
  1918.     return $.expr.filters.visible( element ) &&
  1919.         !$( element ).parents().andSelf().filter(function() {
  1920.             return $.css( this, "visibility" ) === "hidden";
  1921.         }).length;
  1922. }
  1923.  
  1924. $.extend( $.expr[ ":" ], {
  1925.     data: $.expr.createPseudo ?
  1926.         $.expr.createPseudo(function( dataName ) {
  1927.             return function( elem ) {
  1928.                 return !!$.data( elem, dataName );
  1929.             };
  1930.         }) :
  1931.         // support: jQuery <1.8
  1932.         function( elem, i, match ) {
  1933.             return !!$.data( elem, match[ 3 ] );
  1934.         },
  1935.  
  1936.     focusable: function( element ) {
  1937.         return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
  1938.     },
  1939.  
  1940.     tabbable: function( element ) {
  1941.         var tabIndex = $.attr( element, "tabindex" ),
  1942.             isTabIndexNaN = isNaN( tabIndex );
  1943.         return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
  1944.     }
  1945. });
  1946.  
  1947. // support
  1948. $(function() {
  1949.     var body = document.body,
  1950.         div = body.appendChild( div = document.createElement( "div" ) );
  1951.  
  1952.     // access offsetHeight before setting the style to prevent a layout bug
  1953.     // in IE 9 which causes the element to continue to take up space even
  1954.     // after it is removed from the DOM (#8026)
  1955.     div.offsetHeight;
  1956.  
  1957.     $.extend( div.style, {
  1958.         minHeight: "100px",
  1959.         height: "auto",
  1960.         padding: 0,
  1961.         borderWidth: 0
  1962.     });
  1963.  
  1964.     $.support.minHeight = div.offsetHeight === 100;
  1965.     $.support.selectstart = "onselectstart" in div;
  1966.  
  1967.     // set display to none to avoid a layout bug in IE
  1968.     // http://dev.jquery.com/ticket/4014
  1969.     body.removeChild( div ).style.display = "none";
  1970. });
  1971.  
  1972. // support: jQuery <1.8
  1973. if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
  1974.     $.each( [ "Width", "Height" ], function( i, name ) {
  1975.         var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
  1976.             type = name.toLowerCase(),
  1977.             orig = {
  1978.                 innerWidth: $.fn.innerWidth,
  1979.                 innerHeight: $.fn.innerHeight,
  1980.                 outerWidth: $.fn.outerWidth,
  1981.                 outerHeight: $.fn.outerHeight
  1982.             };
  1983.  
  1984.         function reduce( elem, size, border, margin ) {
  1985.             $.each( side, function() {
  1986.                 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
  1987.                 if ( border ) {
  1988.                     size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
  1989.                 }
  1990.                 if ( margin ) {
  1991.                     size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
  1992.                 }
  1993.             });
  1994.             return size;
  1995.         }
  1996.  
  1997.         $.fn[ "inner" + name ] = function( size ) {
  1998.             if ( size === undefined ) {
  1999.                 return orig[ "inner" + name ].call( this );
  2000.             }
  2001.  
  2002.             return this.each(function() {
  2003.                 $( this ).css( type, reduce( this, size ) + "px" );
  2004.             });
  2005.         };
  2006.  
  2007.         $.fn[ "outer" + name] = function( size, margin ) {
  2008.             if ( typeof size !== "number" ) {
  2009.                 return orig[ "outer" + name ].call( this, size );
  2010.             }
  2011.  
  2012.             return this.each(function() {
  2013.                 $( this).css( type, reduce( this, size, true, margin ) + "px" );
  2014.             });
  2015.         };
  2016.     });
  2017. }
  2018.  
  2019. // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
  2020. if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
  2021.     $.fn.removeData = (function( removeData ) {
  2022.         return function( key ) {
  2023.             if ( arguments.length ) {
  2024.                 return removeData.call( this, $.camelCase( key ) );
  2025.             } else {
  2026.                 return removeData.call( this );
  2027.             }
  2028.         };
  2029.     })( $.fn.removeData );
  2030. }
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036. // deprecated
  2037.  
  2038. (function() {
  2039.     var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
  2040.     $.ui.ie = uaMatch.length ? true : false;
  2041.     $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
  2042. })();
  2043.  
  2044. $.fn.extend({
  2045.     disableSelection: function() {
  2046.         return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
  2047.             ".ui-disableSelection", function( event ) {
  2048.                 event.preventDefault();
  2049.             });
  2050.     },
  2051.  
  2052.     enableSelection: function() {
  2053.         return this.unbind( ".ui-disableSelection" );
  2054.     }
  2055. });
  2056.  
  2057. $.extend( $.ui, {
  2058.     // $.ui.plugin is deprecated.  Use the proxy pattern instead.
  2059.     plugin: {
  2060.         add: function( module, option, set ) {
  2061.             var i,
  2062.                 proto = $.ui[ module ].prototype;
  2063.             for ( i in set ) {
  2064.                 proto.plugins[ i ] = proto.plugins[ i ] || [];
  2065.                 proto.plugins[ i ].push( [ option, set[ i ] ] );
  2066.             }
  2067.         },
  2068.         call: function( instance, name, args ) {
  2069.             var i,
  2070.                 set = instance.plugins[ name ];
  2071.             if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
  2072.                 return;
  2073.             }
  2074.  
  2075.             for ( i = 0; i < set.length; i++ ) {
  2076.                 if ( instance.options[ set[ i ][ 0 ] ] ) {
  2077.                     set[ i ][ 1 ].apply( instance.element, args );
  2078.                 }
  2079.             }
  2080.         }
  2081.     },
  2082.  
  2083.     contains: $.contains,
  2084.  
  2085.     // only used by resizable
  2086.     hasScroll: function( el, a ) {
  2087.  
  2088.         //If overflow is hidden, the element might have extra content, but the user wants to hide it
  2089.         if ( $( el ).css( "overflow" ) === "hidden") {
  2090.             return false;
  2091.         }
  2092.  
  2093.         var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
  2094.             has = false;
  2095.  
  2096.         if ( el[ scroll ] > 0 ) {
  2097.             return true;
  2098.         }
  2099.  
  2100.         // TODO: determine which cases actually cause this to happen
  2101.         // if the element doesn't have the scroll set, see if it's possible to
  2102.         // set the scroll
  2103.         el[ scroll ] = 1;
  2104.         has = ( el[ scroll ] > 0 );
  2105.         el[ scroll ] = 0;
  2106.         return has;
  2107.     },
  2108.  
  2109.     // these are odd functions, fix the API or move into individual plugins
  2110.     isOverAxis: function( x, reference, size ) {
  2111.         //Determines when x coordinate is over "b" element axis
  2112.         return ( x > reference ) && ( x < ( reference + size ) );
  2113.     },
  2114.     isOver: function( y, x, top, left, height, width ) {
  2115.         //Determines when x, y coordinates is over "b" element
  2116.         return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
  2117.     }
  2118. });
  2119.  
  2120. })( jQuery );
  2121.  
  2122. //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnl1aS9qcXVlcnkudWkuY29yZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIGpRdWVyeSBVSSBDb3JlIDEuOS4yXG4gKiBodHRwOi8vanF1ZXJ5dWkuY29tXG4gKlxuICogQ29weXJpZ2h0IDIwMTIgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL2NhdGVnb3J5L3VpLWNvcmUvXG4gKi9cbihmdW5jdGlvbiggJCwgdW5kZWZpbmVkICkge1xuXG52YXIgdXVpZCA9IDAsXG5cdHJ1bmlxdWVJZCA9IC9edWktaWQtXFxkKyQvO1xuXG4vLyBwcmV2ZW50IGR1cGxpY2F0ZSBsb2FkaW5nXG4vLyB0aGlzIGlzIG9ubHkgYSBwcm9ibGVtIGJlY2F1c2Ugd2UgcHJveHkgZXhpc3RpbmcgZnVuY3Rpb25zXG4vLyBhbmQgd2UgZG9uJ3Qgd2FudCB0byBkb3VibGUgcHJveHkgdGhlbVxuJC51aSA9ICQudWkgfHwge307XG5pZiAoICQudWkudmVyc2lvbiApIHtcblx0cmV0dXJuO1xufVxuXG4kLmV4dGVuZCggJC51aSwge1xuXHR2ZXJzaW9uOiBcIjEuOS4yXCIsXG5cblx0a2V5Q29kZToge1xuXHRcdEJBQ0tTUEFDRTogOCxcblx0XHRDT01NQTogMTg4LFxuXHRcdERFTEVURTogNDYsXG5cdFx0RE9XTjogNDAsXG5cdFx0RU5EOiAzNSxcblx0XHRFTlRFUjogMTMsXG5cdFx0RVNDQVBFOiAyNyxcblx0XHRIT01FOiAzNixcblx0XHRMRUZUOiAzNyxcblx0XHROVU1QQURfQUREOiAxMDcsXG5cdFx0TlVNUEFEX0RFQ0lNQUw6IDExMCxcblx0XHROVU1QQURfRElWSURFOiAxMTEsXG5cdFx0TlVNUEFEX0VOVEVSOiAxMDgsXG5cdFx0TlVNUEFEX01VTFRJUExZOiAxMDYsXG5cdFx0TlVNUEFEX1NVQlRSQUNUOiAxMDksXG5cdFx0UEFHRV9ET1dOOiAzNCxcblx0XHRQQUdFX1VQOiAzMyxcblx0XHRQRVJJT0Q6IDE5MCxcblx0XHRSSUdIVDogMzksXG5cdFx0U1BBQ0U6IDMyLFxuXHRcdFRBQjogOSxcblx0XHRVUDogMzhcblx0fVxufSk7XG5cbi8vIHBsdWdpbnNcbiQuZm4uZXh0ZW5kKHtcblx0X2ZvY3VzOiAkLmZuLmZvY3VzLFxuXHRmb2N1czogZnVuY3Rpb24oIGRlbGF5LCBmbiApIHtcblx0XHRyZXR1cm4gdHlwZW9mIGRlbGF5ID09PSBcIm51bWJlclwiID9cblx0XHRcdHRoaXMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGVsZW0gPSB0aGlzO1xuXHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCQoIGVsZW0gKS5mb2N1cygpO1xuXHRcdFx0XHRcdGlmICggZm4gKSB7XG5cdFx0XHRcdFx0XHRmbi5jYWxsKCBlbGVtICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LCBkZWxheSApO1xuXHRcdFx0fSkgOlxuXHRcdFx0dGhpcy5fZm9jdXMuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHR9LFxuXG5cdHNjcm9sbFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHNjcm9sbFBhcmVudDtcblx0XHRpZiAoKCQudWkuaWUgJiYgKC8oc3RhdGljfHJlbGF0aXZlKS8pLnRlc3QodGhpcy5jc3MoJ3Bvc2l0aW9uJykpKSB8fCAoL2Fic29sdXRlLykudGVzdCh0aGlzLmNzcygncG9zaXRpb24nKSkpIHtcblx0XHRcdHNjcm9sbFBhcmVudCA9IHRoaXMucGFyZW50cygpLmZpbHRlcihmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICgvKHJlbGF0aXZlfGFic29sdXRlfGZpeGVkKS8pLnRlc3QoJC5jc3ModGhpcywncG9zaXRpb24nKSkgJiYgKC8oYXV0b3xzY3JvbGwpLykudGVzdCgkLmNzcyh0aGlzLCdvdmVyZmxvdycpKyQuY3NzKHRoaXMsJ292ZXJmbG93LXknKSskLmNzcyh0aGlzLCdvdmVyZmxvdy14JykpO1xuXHRcdFx0fSkuZXEoMCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNjcm9sbFBhcmVudCA9IHRoaXMucGFyZW50cygpLmZpbHRlcihmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICgvKGF1dG98c2Nyb2xsKS8pLnRlc3QoJC5jc3ModGhpcywnb3ZlcmZsb3cnKSskLmNzcyh0aGlzLCdvdmVyZmxvdy15JykrJC5jc3ModGhpcywnb3ZlcmZsb3cteCcpKTtcblx0XHRcdH0pLmVxKDApO1xuXHRcdH1cblxuXHRcdHJldHVybiAoL2ZpeGVkLykudGVzdCh0aGlzLmNzcygncG9zaXRpb24nKSkgfHwgIXNjcm9sbFBhcmVudC5sZW5ndGggPyAkKGRvY3VtZW50KSA6IHNjcm9sbFBhcmVudDtcblx0fSxcblxuXHR6SW5kZXg6IGZ1bmN0aW9uKCB6SW5kZXggKSB7XG5cdFx0aWYgKCB6SW5kZXggIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiB0aGlzLmNzcyggXCJ6SW5kZXhcIiwgekluZGV4ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdHZhciBlbGVtID0gJCggdGhpc1sgMCBdICksIHBvc2l0aW9uLCB2YWx1ZTtcblx0XHRcdHdoaWxlICggZWxlbS5sZW5ndGggJiYgZWxlbVsgMCBdICE9PSBkb2N1bWVudCApIHtcblx0XHRcdFx0Ly8gSWdub3JlIHotaW5kZXggaWYgcG9zaXRpb24gaXMgc2V0IHRvIGEgdmFsdWUgd2hlcmUgei1pbmRleCBpcyBpZ25vcmVkIGJ5IHRoZSBicm93c2VyXG5cdFx0XHRcdC8vIFRoaXMgbWFrZXMgYmVoYXZpb3Igb2YgdGhpcyBmdW5jdGlvbiBjb25zaXN0ZW50IGFjcm9zcyBicm93c2Vyc1xuXHRcdFx0XHQvLyBXZWJLaXQgYWx3YXlzIHJldHVybnMgYXV0byBpZiB0aGUgZWxlbWVudCBpcyBwb3NpdGlvbmVkXG5cdFx0XHRcdHBvc2l0aW9uID0gZWxlbS5jc3MoIFwicG9zaXRpb25cIiApO1xuXHRcdFx0XHRpZiAoIHBvc2l0aW9uID09PSBcImFic29sdXRlXCIgfHwgcG9zaXRpb24gPT09IFwicmVsYXRpdmVcIiB8fCBwb3NpdGlvbiA9PT0gXCJmaXhlZFwiICkge1xuXHRcdFx0XHRcdC8vIElFIHJldHVybnMgMCB3aGVuIHpJbmRleCBpcyBub3Qgc3BlY2lmaWVkXG5cdFx0XHRcdFx0Ly8gb3RoZXIgYnJvd3NlcnMgcmV0dXJuIGEgc3RyaW5nXG5cdFx0XHRcdFx0Ly8gd2UgaWdub3JlIHRoZSBjYXNlIG9mIG5lc3RlZCBlbGVtZW50cyB3aXRoIGFuIGV4cGxpY2l0IHZhbHVlIG9mIDBcblx0XHRcdFx0XHQvLyA8ZGl2IHN0eWxlPVwiei1pbmRleDogLTEwO1wiPjxkaXYgc3R5bGU9XCJ6LWluZGV4OiAwO1wiPjwvZGl2PjwvZGl2PlxuXHRcdFx0XHRcdHZhbHVlID0gcGFyc2VJbnQoIGVsZW0uY3NzKCBcInpJbmRleFwiICksIDEwICk7XG5cdFx0XHRcdFx0aWYgKCAhaXNOYU4oIHZhbHVlICkgJiYgdmFsdWUgIT09IDAgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsZW0gPSBlbGVtLnBhcmVudCgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiAwO1xuXHR9LFxuXG5cdHVuaXF1ZUlkOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCAhdGhpcy5pZCApIHtcblx0XHRcdFx0dGhpcy5pZCA9IFwidWktaWQtXCIgKyAoKyt1dWlkKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblxuXHRyZW1vdmVVbmlxdWVJZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGlmICggcnVuaXF1ZUlkLnRlc3QoIHRoaXMuaWQgKSApIHtcblx0XHRcdFx0JCggdGhpcyApLnJlbW92ZUF0dHIoIFwiaWRcIiApO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59KTtcblxuLy8gc2VsZWN0b3JzXG5mdW5jdGlvbiBmb2N1c2FibGUoIGVsZW1lbnQsIGlzVGFiSW5kZXhOb3ROYU4gKSB7XG5cdHZhciBtYXAsIG1hcE5hbWUsIGltZyxcblx0XHRub2RlTmFtZSA9IGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0aWYgKCBcImFyZWFcIiA9PT0gbm9kZU5hbWUgKSB7XG5cdFx0bWFwID0gZWxlbWVudC5wYXJlbnROb2RlO1xuXHRcdG1hcE5hbWUgPSBtYXAubmFtZTtcblx0XHRpZiAoICFlbGVtZW50LmhyZWYgfHwgIW1hcE5hbWUgfHwgbWFwLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwibWFwXCIgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdGltZyA9ICQoIFwiaW1nW3VzZW1hcD0jXCIgKyBtYXBOYW1lICsgXCJdXCIgKVswXTtcblx0XHRyZXR1cm4gISFpbWcgJiYgdmlzaWJsZSggaW1nICk7XG5cdH1cblx0cmV0dXJuICggL2lucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b258b2JqZWN0Ly50ZXN0KCBub2RlTmFtZSApID9cblx0XHQhZWxlbWVudC5kaXNhYmxlZCA6XG5cdFx0XCJhXCIgPT09IG5vZGVOYW1lID9cblx0XHRcdGVsZW1lbnQuaHJlZiB8fCBpc1RhYkluZGV4Tm90TmFOIDpcblx0XHRcdGlzVGFiSW5kZXhOb3ROYU4pICYmXG5cdFx0Ly8gdGhlIGVsZW1lbnQgYW5kIGFsbCBvZiBpdHMgYW5jZXN0b3JzIG11c3QgYmUgdmlzaWJsZVxuXHRcdHZpc2libGUoIGVsZW1lbnQgKTtcbn1cblxuZnVuY3Rpb24gdmlzaWJsZSggZWxlbWVudCApIHtcblx0cmV0dXJuICQuZXhwci5maWx0ZXJzLnZpc2libGUoIGVsZW1lbnQgKSAmJlxuXHRcdCEkKCBlbGVtZW50ICkucGFyZW50cygpLmFuZFNlbGYoKS5maWx0ZXIoZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJC5jc3MoIHRoaXMsIFwidmlzaWJpbGl0eVwiICkgPT09IFwiaGlkZGVuXCI7XG5cdFx0fSkubGVuZ3RoO1xufVxuXG4kLmV4dGVuZCggJC5leHByWyBcIjpcIiBdLCB7XG5cdGRhdGE6ICQuZXhwci5jcmVhdGVQc2V1ZG8gP1xuXHRcdCQuZXhwci5jcmVhdGVQc2V1ZG8oZnVuY3Rpb24oIGRhdGFOYW1lICkge1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRyZXR1cm4gISEkLmRhdGEoIGVsZW0sIGRhdGFOYW1lICk7XG5cdFx0XHR9O1xuXHRcdH0pIDpcblx0XHQvLyBzdXBwb3J0OiBqUXVlcnkgPDEuOFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBpLCBtYXRjaCApIHtcblx0XHRcdHJldHVybiAhISQuZGF0YSggZWxlbSwgbWF0Y2hbIDMgXSApO1xuXHRcdH0sXG5cblx0Zm9jdXNhYmxlOiBmdW5jdGlvbiggZWxlbWVudCApIHtcblx0XHRyZXR1cm4gZm9jdXNhYmxlKCBlbGVtZW50LCAhaXNOYU4oICQuYXR0ciggZWxlbWVudCwgXCJ0YWJpbmRleFwiICkgKSApO1xuXHR9LFxuXG5cdHRhYmJhYmxlOiBmdW5jdGlvbiggZWxlbWVudCApIHtcblx0XHR2YXIgdGFiSW5kZXggPSAkLmF0dHIoIGVsZW1lbnQsIFwidGFiaW5kZXhcIiApLFxuXHRcdFx0aXNUYWJJbmRleE5hTiA9IGlzTmFOKCB0YWJJbmRleCApO1xuXHRcdHJldHVybiAoIGlzVGFiSW5kZXhOYU4gfHwgdGFiSW5kZXggPj0gMCApICYmIGZvY3VzYWJsZSggZWxlbWVudCwgIWlzVGFiSW5kZXhOYU4gKTtcblx0fVxufSk7XG5cbi8vIHN1cHBvcnRcbiQoZnVuY3Rpb24oKSB7XG5cdHZhciBib2R5ID0gZG9jdW1lbnQuYm9keSxcblx0XHRkaXYgPSBib2R5LmFwcGVuZENoaWxkKCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkgKTtcblxuXHQvLyBhY2Nlc3Mgb2Zmc2V0SGVpZ2h0IGJlZm9yZSBzZXR0aW5nIHRoZSBzdHlsZSB0byBwcmV2ZW50IGEgbGF5b3V0IGJ1Z1xuXHQvLyBpbiBJRSA5IHdoaWNoIGNhdXNlcyB0aGUgZWxlbWVudCB0byBjb250aW51ZSB0byB0YWtlIHVwIHNwYWNlIGV2ZW5cblx0Ly8gYWZ0ZXIgaXQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00gKCM4MDI2KVxuXHRkaXYub2Zmc2V0SGVpZ2h0O1xuXG5cdCQuZXh0ZW5kKCBkaXYuc3R5bGUsIHtcblx0XHRtaW5IZWlnaHQ6IFwiMTAwcHhcIixcblx0XHRoZWlnaHQ6IFwiYXV0b1wiLFxuXHRcdHBhZGRpbmc6IDAsXG5cdFx0Ym9yZGVyV2lkdGg6IDBcblx0fSk7XG5cblx0JC5zdXBwb3J0Lm1pbkhlaWdodCA9IGRpdi5vZmZzZXRIZWlnaHQgPT09IDEwMDtcblx0JC5zdXBwb3J0LnNlbGVjdHN0YXJ0ID0gXCJvbnNlbGVjdHN0YXJ0XCIgaW4gZGl2O1xuXG5cdC8vIHNldCBkaXNwbGF5IHRvIG5vbmUgdG8gYXZvaWQgYSBsYXlvdXQgYnVnIGluIElFXG5cdC8vIGh0dHA6Ly9kZXYuanF1ZXJ5LmNvbS90aWNrZXQvNDAxNFxuXHRib2R5LnJlbW92ZUNoaWxkKCBkaXYgKS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG59KTtcblxuLy8gc3VwcG9ydDogalF1ZXJ5IDwxLjhcbmlmICggISQoIFwiPGE+XCIgKS5vdXRlcldpZHRoKCAxICkuanF1ZXJ5ICkge1xuXHQkLmVhY2goIFsgXCJXaWR0aFwiLCBcIkhlaWdodFwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRcdHZhciBzaWRlID0gbmFtZSA9PT0gXCJXaWR0aFwiID8gWyBcIkxlZnRcIiwgXCJSaWdodFwiIF0gOiBbIFwiVG9wXCIsIFwiQm90dG9tXCIgXSxcblx0XHRcdHR5cGUgPSBuYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRvcmlnID0ge1xuXHRcdFx0XHRpbm5lcldpZHRoOiAkLmZuLmlubmVyV2lkdGgsXG5cdFx0XHRcdGlubmVySGVpZ2h0OiAkLmZuLmlubmVySGVpZ2h0LFxuXHRcdFx0XHRvdXRlcldpZHRoOiAkLmZuLm91dGVyV2lkdGgsXG5cdFx0XHRcdG91dGVySGVpZ2h0OiAkLmZuLm91dGVySGVpZ2h0XG5cdFx0XHR9O1xuXG5cdFx0ZnVuY3Rpb24gcmVkdWNlKCBlbGVtLCBzaXplLCBib3JkZXIsIG1hcmdpbiApIHtcblx0XHRcdCQuZWFjaCggc2lkZSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHNpemUgLT0gcGFyc2VGbG9hdCggJC5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgdGhpcyApICkgfHwgMDtcblx0XHRcdFx0aWYgKCBib3JkZXIgKSB7XG5cdFx0XHRcdFx0c2l6ZSAtPSBwYXJzZUZsb2F0KCAkLmNzcyggZWxlbSwgXCJib3JkZXJcIiArIHRoaXMgKyBcIldpZHRoXCIgKSApIHx8IDA7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBtYXJnaW4gKSB7XG5cdFx0XHRcdFx0c2l6ZSAtPSBwYXJzZUZsb2F0KCAkLmNzcyggZWxlbSwgXCJtYXJnaW5cIiArIHRoaXMgKSApIHx8IDA7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuIHNpemU7XG5cdFx0fVxuXG5cdFx0JC5mblsgXCJpbm5lclwiICsgbmFtZSBdID0gZnVuY3Rpb24oIHNpemUgKSB7XG5cdFx0XHRpZiAoIHNpemUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIG9yaWdbIFwiaW5uZXJcIiArIG5hbWUgXS5jYWxsKCB0aGlzICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCQoIHRoaXMgKS5jc3MoIHR5cGUsIHJlZHVjZSggdGhpcywgc2l6ZSApICsgXCJweFwiICk7XG5cdFx0XHR9KTtcblx0XHR9O1xuXG5cdFx0JC5mblsgXCJvdXRlclwiICsgbmFtZV0gPSBmdW5jdGlvbiggc2l6ZSwgbWFyZ2luICkge1xuXHRcdFx0aWYgKCB0eXBlb2Ygc2l6ZSAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0cmV0dXJuIG9yaWdbIFwib3V0ZXJcIiArIG5hbWUgXS5jYWxsKCB0aGlzLCBzaXplICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCQoIHRoaXMpLmNzcyggdHlwZSwgcmVkdWNlKCB0aGlzLCBzaXplLCB0cnVlLCBtYXJnaW4gKSArIFwicHhcIiApO1xuXHRcdFx0fSk7XG5cdFx0fTtcblx0fSk7XG59XG5cbi8vIHN1cHBvcnQ6IGpRdWVyeSAxLjYuMSwgMS42LjIgKGh0dHA6Ly9idWdzLmpxdWVyeS5jb20vdGlja2V0Lzk0MTMpXG5pZiAoICQoIFwiPGE+XCIgKS5kYXRhKCBcImEtYlwiLCBcImFcIiApLnJlbW92ZURhdGEoIFwiYS1iXCIgKS5kYXRhKCBcImEtYlwiICkgKSB7XG5cdCQuZm4ucmVtb3ZlRGF0YSA9IChmdW5jdGlvbiggcmVtb3ZlRGF0YSApIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oIGtleSApIHtcblx0XHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdFx0cmV0dXJuIHJlbW92ZURhdGEuY2FsbCggdGhpcywgJC5jYW1lbENhc2UoIGtleSApICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gcmVtb3ZlRGF0YS5jYWxsKCB0aGlzICk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fSkoICQuZm4ucmVtb3ZlRGF0YSApO1xufVxuXG5cblxuXG5cbi8vIGRlcHJlY2F0ZWRcblxuKGZ1bmN0aW9uKCkge1xuXHR2YXIgdWFNYXRjaCA9IC9tc2llIChbXFx3Ll0rKS8uZXhlYyggbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpICkgfHwgW107XG5cdCQudWkuaWUgPSB1YU1hdGNoLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcblx0JC51aS5pZTYgPSBwYXJzZUZsb2F0KCB1YU1hdGNoWyAxIF0sIDEwICkgPT09IDY7XG59KSgpO1xuXG4kLmZuLmV4dGVuZCh7XG5cdGRpc2FibGVTZWxlY3Rpb246IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmJpbmQoICggJC5zdXBwb3J0LnNlbGVjdHN0YXJ0ID8gXCJzZWxlY3RzdGFydFwiIDogXCJtb3VzZWRvd25cIiApICtcblx0XHRcdFwiLnVpLWRpc2FibGVTZWxlY3Rpb25cIiwgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0fSk7XG5cdH0sXG5cblx0ZW5hYmxlU2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy51bmJpbmQoIFwiLnVpLWRpc2FibGVTZWxlY3Rpb25cIiApO1xuXHR9XG59KTtcblxuJC5leHRlbmQoICQudWksIHtcblx0Ly8gJC51aS5wbHVnaW4gaXMgZGVwcmVjYXRlZC4gIFVzZSB0aGUgcHJveHkgcGF0dGVybiBpbnN0ZWFkLlxuXHRwbHVnaW46IHtcblx0XHRhZGQ6IGZ1bmN0aW9uKCBtb2R1bGUsIG9wdGlvbiwgc2V0ICkge1xuXHRcdFx0dmFyIGksXG5cdFx0XHRcdHByb3RvID0gJC51aVsgbW9kdWxlIF0ucHJvdG90eXBlO1xuXHRcdFx0Zm9yICggaSBpbiBzZXQgKSB7XG5cdFx0XHRcdHByb3RvLnBsdWdpbnNbIGkgXSA9IHByb3RvLnBsdWdpbnNbIGkgXSB8fCBbXTtcblx0XHRcdFx0cHJvdG8ucGx1Z2luc1sgaSBdLnB1c2goIFsgb3B0aW9uLCBzZXRbIGkgXSBdICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjYWxsOiBmdW5jdGlvbiggaW5zdGFuY2UsIG5hbWUsIGFyZ3MgKSB7XG5cdFx0XHR2YXIgaSxcblx0XHRcdFx0c2V0ID0gaW5zdGFuY2UucGx1Z2luc1sgbmFtZSBdO1xuXHRcdFx0aWYgKCAhc2V0IHx8ICFpbnN0YW5jZS5lbGVtZW50WyAwIF0ucGFyZW50Tm9kZSB8fCBpbnN0YW5jZS5lbGVtZW50WyAwIF0ucGFyZW50Tm9kZS5ub2RlVHlwZSA9PT0gMTEgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggaSA9IDA7IGkgPCBzZXQubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdGlmICggaW5zdGFuY2Uub3B0aW9uc1sgc2V0WyBpIF1bIDAgXSBdICkge1xuXHRcdFx0XHRcdHNldFsgaSBdWyAxIF0uYXBwbHkoIGluc3RhbmNlLmVsZW1lbnQsIGFyZ3MgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRjb250YWluczogJC5jb250YWlucyxcblxuXHQvLyBvbmx5IHVzZWQgYnkgcmVzaXphYmxlXG5cdGhhc1Njcm9sbDogZnVuY3Rpb24oIGVsLCBhICkge1xuXG5cdFx0Ly9JZiBvdmVyZmxvdyBpcyBoaWRkZW4sIHRoZSBlbGVtZW50IG1pZ2h0IGhhdmUgZXh0cmEgY29udGVudCwgYnV0IHRoZSB1c2VyIHdhbnRzIHRvIGhpZGUgaXRcblx0XHRpZiAoICQoIGVsICkuY3NzKCBcIm92ZXJmbG93XCIgKSA9PT0gXCJoaWRkZW5cIikge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciBzY3JvbGwgPSAoIGEgJiYgYSA9PT0gXCJsZWZ0XCIgKSA/IFwic2Nyb2xsTGVmdFwiIDogXCJzY3JvbGxUb3BcIixcblx0XHRcdGhhcyA9IGZhbHNlO1xuXG5cdFx0aWYgKCBlbFsgc2Nyb2xsIF0gPiAwICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gVE9ETzogZGV0ZXJtaW5lIHdoaWNoIGNhc2VzIGFjdHVhbGx5IGNhdXNlIHRoaXMgdG8gaGFwcGVuXG5cdFx0Ly8gaWYgdGhlIGVsZW1lbnQgZG9lc24ndCBoYXZlIHRoZSBzY3JvbGwgc2V0LCBzZWUgaWYgaXQncyBwb3NzaWJsZSB0b1xuXHRcdC8vIHNldCB0aGUgc2Nyb2xsXG5cdFx0ZWxbIHNjcm9sbCBdID0gMTtcblx0XHRoYXMgPSAoIGVsWyBzY3JvbGwgXSA+IDAgKTtcblx0XHRlbFsgc2Nyb2xsIF0gPSAwO1xuXHRcdHJldHVybiBoYXM7XG5cdH0sXG5cblx0Ly8gdGhlc2UgYXJlIG9kZCBmdW5jdGlvbnMsIGZpeCB0aGUgQVBJIG9yIG1vdmUgaW50byBpbmRpdmlkdWFsIHBsdWdpbnNcblx0aXNPdmVyQXhpczogZnVuY3Rpb24oIHgsIHJlZmVyZW5jZSwgc2l6ZSApIHtcblx0XHQvL0RldGVybWluZXMgd2hlbiB4IGNvb3JkaW5hdGUgaXMgb3ZlciBcImJcIiBlbGVtZW50IGF4aXNcblx0XHRyZXR1cm4gKCB4ID4gcmVmZXJlbmNlICkgJiYgKCB4IDwgKCByZWZlcmVuY2UgKyBzaXplICkgKTtcblx0fSxcblx0aXNPdmVyOiBmdW5jdGlvbiggeSwgeCwgdG9wLCBsZWZ0LCBoZWlnaHQsIHdpZHRoICkge1xuXHRcdC8vRGV0ZXJtaW5lcyB3aGVuIHgsIHkgY29vcmRpbmF0ZXMgaXMgb3ZlciBcImJcIiBlbGVtZW50XG5cdFx0cmV0dXJuICQudWkuaXNPdmVyQXhpcyggeSwgdG9wLCBoZWlnaHQgKSAmJiAkLnVpLmlzT3ZlckF4aXMoIHgsIGxlZnQsIHdpZHRoICk7XG5cdH1cbn0pO1xuXG59KSggalF1ZXJ5ICk7XG4iXSwiZmlsZSI6ImpxdWVyeXVpL2pxdWVyeS51aS5jb3JlLmpzIn0=
  2123.  
  2124. /*!
  2125.  * jQuery UI Datepicker 1.9.2
  2126.  * http://jqueryui.com
  2127.  *
  2128.  * Copyright 2012 jQuery Foundation and other contributors
  2129.  * Released under the MIT license.
  2130.  * http://jquery.org/license
  2131.  *
  2132.  * http://api.jqueryui.com/datepicker/
  2133.  *
  2134.  * Depends:
  2135.  *  jquery.ui.core.js
  2136.  */
  2137. (function( $, undefined ) {
  2138.  
  2139. $.extend($.ui, { datepicker: { version: "1.9.2" } });
  2140.  
  2141. var PROP_NAME = 'datepicker';
  2142. var dpuuid = new Date().getTime();
  2143. var instActive;
  2144.  
  2145. /* Date picker manager.
  2146.    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
  2147.    Settings for (groups of) date pickers are maintained in an instance object,
  2148.    allowing multiple different settings on the same page. */
  2149.  
  2150. function Datepicker() {
  2151.     this.debug = false; // Change this to true to start debugging
  2152.     this._curInst = null; // The current instance in use
  2153.     this._keyEvent = false; // If the last event was a key event
  2154.     this._disabledInputs = []; // List of date picker inputs that have been disabled
  2155.     this._datepickerShowing = false; // True if the popup picker is showing , false if not
  2156.     this._inDialog = false; // True if showing within a "dialog", false if not
  2157.     this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
  2158.     this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
  2159.     this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
  2160.     this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
  2161.     this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
  2162.     this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
  2163.     this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
  2164.     this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
  2165.     this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
  2166.     this.regional = []; // Available regional settings, indexed by language code
  2167.     this.regional[''] = { // Default regional settings
  2168.         closeText: 'Done', // Display text for close link
  2169.         prevText: 'Prev', // Display text for previous month link
  2170.         nextText: 'Next', // Display text for next month link
  2171.         currentText: 'Today', // Display text for current month link
  2172.         monthNames: ['January','February','March','April','May','June',
  2173.             'July','August','September','October','November','December'], // Names of months for drop-down and formatting
  2174.         monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
  2175.         dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
  2176.         dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
  2177.         dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
  2178.         weekHeader: 'Wk', // Column header for week of the year
  2179.         dateFormat: 'mm/dd/yy', // See format options on parseDate
  2180.         firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
  2181.         isRTL: false, // True if right-to-left language, false if left-to-right
  2182.         showMonthAfterYear: false, // True if the year select precedes month, false for month then year
  2183.         yearSuffix: '' // Additional text to append to the year in the month headers
  2184.     };
  2185.     this._defaults = { // Global defaults for all the date picker instances
  2186.         showOn: 'focus', // 'focus' for popup on focus,
  2187.             // 'button' for trigger button, or 'both' for either
  2188.         showAnim: 'fadeIn', // Name of jQuery animation for popup
  2189.         showOptions: {}, // Options for enhanced animations
  2190.         defaultDate: null, // Used when field is blank: actual date,
  2191.             // +/-number for offset from today, null for today
  2192.         appendText: '', // Display text following the input box, e.g. showing the format
  2193.         buttonText: '...', // Text for trigger button
  2194.         buttonImage: '', // URL for trigger button image
  2195.         buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
  2196.         hideIfNoPrevNext: false, // True to hide next/previous month links
  2197.             // if not applicable, false to just disable them
  2198.         navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
  2199.         gotoCurrent: false, // True if today link goes back to current selection instead
  2200.         changeMonth: false, // True if month can be selected directly, false if only prev/next
  2201.         changeYear: false, // True if year can be selected directly, false if only prev/next
  2202.         yearRange: 'c-10:c+10', // Range of years to display in drop-down,
  2203.             // either relative to today's year (-nn:+nn), relative to currently displayed year
  2204.             // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
  2205.         showOtherMonths: false, // True to show dates in other months, false to leave blank
  2206.         selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
  2207.         showWeek: false, // True to show week of the year, false to not show it
  2208.         calculateWeek: this.iso8601Week, // How to calculate the week of the year,
  2209.             // takes a Date and returns the number of the week for it
  2210.         shortYearCutoff: '+10', // Short year values < this are in the current century,
  2211.             // > this are in the previous century,
  2212.             // string value starting with '+' for current year + value
  2213.         minDate: null, // The earliest selectable date, or null for no limit
  2214.         maxDate: null, // The latest selectable date, or null for no limit
  2215.         duration: 'fast', // Duration of display/closure
  2216.         beforeShowDay: null, // Function that takes a date and returns an array with
  2217.             // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
  2218.             // [2] = cell title (optional), e.g. $.datepicker.noWeekends
  2219.         beforeShow: null, // Function that takes an input field and
  2220.             // returns a set of custom settings for the date picker
  2221.         onSelect: null, // Define a callback function when a date is selected
  2222.         onChangeMonthYear: null, // Define a callback function when the month or year is changed
  2223.         onClose: null, // Define a callback function when the datepicker is closed
  2224.         numberOfMonths: 1, // Number of months to show at a time
  2225.         showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
  2226.         stepMonths: 1, // Number of months to step back/forward
  2227.         stepBigMonths: 12, // Number of months to step back/forward for the big links
  2228.         altField: '', // Selector for an alternate field to store selected dates into
  2229.         altFormat: '', // The date format to use for the alternate field
  2230.         constrainInput: true, // The input is constrained by the current date format
  2231.         showButtonPanel: false, // True to show button panel, false to not show it
  2232.         autoSize: false, // True to size the input for the date format, false to leave as is
  2233.         disabled: false // The initial disabled state
  2234.     };
  2235.     $.extend(this._defaults, this.regional['']);
  2236.     this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
  2237. }
  2238.  
  2239. $.extend(Datepicker.prototype, {
  2240.     /* Class name added to elements to indicate already configured with a date picker. */
  2241.     markerClassName: 'hasDatepicker',
  2242.  
  2243.     //Keep track of the maximum number of rows displayed (see #7043)
  2244.     maxRows: 4,
  2245.  
  2246.     /* Debug logging (if enabled). */
  2247.     log: function () {
  2248.         if (this.debug)
  2249.             console.log.apply('', arguments);
  2250.     },
  2251.  
  2252.     // TODO rename to "widget" when switching to widget factory
  2253.     _widgetDatepicker: function() {
  2254.         return this.dpDiv;
  2255.     },
  2256.  
  2257.     /* Override the default settings for all instances of the date picker.
  2258.        @param  settings  object - the new settings to use as defaults (anonymous object)
  2259.        @return the manager object */
  2260.     setDefaults: function(settings) {
  2261.         extendRemove(this._defaults, settings || {});
  2262.         return this;
  2263.     },
  2264.  
  2265.     /* Attach the date picker to a jQuery selection.
  2266.        @param  target    element - the target input field or division or span
  2267.        @param  settings  object - the new settings to use for this date picker instance (anonymous) */
  2268.     _attachDatepicker: function(target, settings) {
  2269.         // check for settings on the control itself - in namespace 'date:'
  2270.         var inlineSettings = null;
  2271.         for (var attrName in this._defaults) {
  2272.             var attrValue = target.getAttribute('date:' + attrName);
  2273.             if (attrValue) {
  2274.                 inlineSettings = inlineSettings || {};
  2275.                 try {
  2276.                     inlineSettings[attrName] = eval(attrValue);
  2277.                 } catch (err) {
  2278.                     inlineSettings[attrName] = attrValue;
  2279.                 }
  2280.             }
  2281.         }
  2282.         var nodeName = target.nodeName.toLowerCase();
  2283.         var inline = (nodeName == 'div' || nodeName == 'span');
  2284.         if (!target.id) {
  2285.             this.uuid += 1;
  2286.             target.id = 'dp' + this.uuid;
  2287.         }
  2288.         var inst = this._newInst($(target), inline);
  2289.         inst.settings = $.extend({}, settings || {}, inlineSettings || {});
  2290.         if (nodeName == 'input') {
  2291.             this._connectDatepicker(target, inst);
  2292.         } else if (inline) {
  2293.             this._inlineDatepicker(target, inst);
  2294.         }
  2295.     },
  2296.  
  2297.     /* Create a new instance object. */
  2298.     _newInst: function(target, inline) {
  2299.         var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
  2300.         return {id: id, input: target, // associated target
  2301.             selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
  2302.             drawMonth: 0, drawYear: 0, // month being drawn
  2303.             inline: inline, // is datepicker inline or not
  2304.             dpDiv: (!inline ? this.dpDiv : // presentation div
  2305.             bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
  2306.     },
  2307.  
  2308.     /* Attach the date picker to an input field. */
  2309.     _connectDatepicker: function(target, inst) {
  2310.         var input = $(target);
  2311.         inst.append = $([]);
  2312.         inst.trigger = $([]);
  2313.         if (input.hasClass(this.markerClassName))
  2314.             return;
  2315.         this._attachments(input, inst);
  2316.         input.addClass(this.markerClassName).keydown(this._doKeyDown).
  2317.             keypress(this._doKeyPress).keyup(this._doKeyUp).
  2318.             bind("setData.datepicker", function(event, key, value) {
  2319.                 inst.settings[key] = value;
  2320.             }).bind("getData.datepicker", function(event, key) {
  2321.                 return this._get(inst, key);
  2322.             });
  2323.         this._autoSize(inst);
  2324.         $.data(target, PROP_NAME, inst);
  2325.         //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
  2326.         if( inst.settings.disabled ) {
  2327.             this._disableDatepicker( target );
  2328.         }
  2329.     },
  2330.  
  2331.     /* Make attachments based on settings. */
  2332.     _attachments: function(input, inst) {
  2333.         var appendText = this._get(inst, 'appendText');
  2334.         var isRTL = this._get(inst, 'isRTL');
  2335.         if (inst.append)
  2336.             inst.append.remove();
  2337.         if (appendText) {
  2338.             inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
  2339.             input[isRTL ? 'before' : 'after'](inst.append);
  2340.         }
  2341.         input.unbind('focus', this._showDatepicker);
  2342.         if (inst.trigger)
  2343.             inst.trigger.remove();
  2344.         var showOn = this._get(inst, 'showOn');
  2345.         if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
  2346.             input.focus(this._showDatepicker);
  2347.         if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
  2348.             var buttonText = this._get(inst, 'buttonText');
  2349.             var buttonImage = this._get(inst, 'buttonImage');
  2350.             inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
  2351.                 $('<img/>').addClass(this._triggerClass).
  2352.                     attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
  2353.                 $('<button type="button"></button>').addClass(this._triggerClass).
  2354.                     html(buttonImage == '' ? buttonText : $('<img/>').attr(
  2355.                     { src:buttonImage, alt:buttonText, title:buttonText })));
  2356.             input[isRTL ? 'before' : 'after'](inst.trigger);
  2357.             inst.trigger.click(function() {
  2358.                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
  2359.                     $.datepicker._hideDatepicker();
  2360.                 else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
  2361.                     $.datepicker._hideDatepicker();
  2362.                     $.datepicker._showDatepicker(input[0]);
  2363.                 } else
  2364.                     $.datepicker._showDatepicker(input[0]);
  2365.                 return false;
  2366.             });
  2367.         }
  2368.     },
  2369.  
  2370.     /* Apply the maximum length for the date format. */
  2371.     _autoSize: function(inst) {
  2372.         if (this._get(inst, 'autoSize') && !inst.inline) {
  2373.             var date = new Date(2009, 12 - 1, 20); // Ensure double digits
  2374.             var dateFormat = this._get(inst, 'dateFormat');
  2375.             if (dateFormat.match(/[DM]/)) {
  2376.                 var findMax = function(names) {
  2377.                     var max = 0;
  2378.                     var maxI = 0;
  2379.                     for (var i = 0; i < names.length; i++) {
  2380.                         if (names[i].length > max) {
  2381.                             max = names[i].length;
  2382.                             maxI = i;
  2383.                         }
  2384.                     }
  2385.                     return maxI;
  2386.                 };
  2387.                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
  2388.                     'monthNames' : 'monthNamesShort'))));
  2389.                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
  2390.                     'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
  2391.             }
  2392.             inst.input.attr('size', this._formatDate(inst, date).length);
  2393.         }
  2394.     },
  2395.  
  2396.     /* Attach an inline date picker to a div. */
  2397.     _inlineDatepicker: function(target, inst) {
  2398.         var divSpan = $(target);
  2399.         if (divSpan.hasClass(this.markerClassName))
  2400.             return;
  2401.         divSpan.addClass(this.markerClassName).append(inst.dpDiv).
  2402.             bind("setData.datepicker", function(event, key, value){
  2403.                 inst.settings[key] = value;
  2404.             }).bind("getData.datepicker", function(event, key){
  2405.                 return this._get(inst, key);
  2406.             });
  2407.         $.data(target, PROP_NAME, inst);
  2408.         this._setDate(inst, this._getDefaultDate(inst), true);
  2409.         this._updateDatepicker(inst);
  2410.         this._updateAlternate(inst);
  2411.         //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
  2412.         if( inst.settings.disabled ) {
  2413.             this._disableDatepicker( target );
  2414.         }
  2415.         // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
  2416.         // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
  2417.         inst.dpDiv.css( "display", "block" );
  2418.     },
  2419.  
  2420.     /* Pop-up the date picker in a "dialog" box.
  2421.        @param  input     element - ignored
  2422.        @param  date      string or Date - the initial date to display
  2423.        @param  onSelect  function - the function to call when a date is selected
  2424.        @param  settings  object - update the dialog date picker instance's settings (anonymous object)
  2425.        @param  pos       int[2] - coordinates for the dialog's position within the screen or
  2426.                          event - with x/y coordinates or
  2427.                          leave empty for default (screen centre)
  2428.        @return the manager object */
  2429.     _dialogDatepicker: function(input, date, onSelect, settings, pos) {
  2430.         var inst = this._dialogInst; // internal instance
  2431.         if (!inst) {
  2432.             this.uuid += 1;
  2433.             var id = 'dp' + this.uuid;
  2434.             this._dialogInput = $('<input type="text" id="' + id +
  2435.                 '" style="position: absolute; top: -100px; width: 0px;"/>');
  2436.             this._dialogInput.keydown(this._doKeyDown);
  2437.             $('body').append(this._dialogInput);
  2438.             inst = this._dialogInst = this._newInst(this._dialogInput, false);
  2439.             inst.settings = {};
  2440.             $.data(this._dialogInput[0], PROP_NAME, inst);
  2441.         }
  2442.         extendRemove(inst.settings, settings || {});
  2443.         date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
  2444.         this._dialogInput.val(date);
  2445.  
  2446.         this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
  2447.         if (!this._pos) {
  2448.             var browserWidth = document.documentElement.clientWidth;
  2449.             var browserHeight = document.documentElement.clientHeight;
  2450.             var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
  2451.             var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
  2452.             this._pos = // should use actual width/height below
  2453.                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
  2454.         }
  2455.  
  2456.         // move input on screen for focus, but hidden behind dialog
  2457.         this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
  2458.         inst.settings.onSelect = onSelect;
  2459.         this._inDialog = true;
  2460.         this.dpDiv.addClass(this._dialogClass);
  2461.         this._showDatepicker(this._dialogInput[0]);
  2462.         if ($.blockUI)
  2463.             $.blockUI(this.dpDiv);
  2464.         $.data(this._dialogInput[0], PROP_NAME, inst);
  2465.         return this;
  2466.     },
  2467.  
  2468.     /* Detach a datepicker from its control.
  2469.        @param  target    element - the target input field or division or span */
  2470.     _destroyDatepicker: function(target) {
  2471.         var $target = $(target);
  2472.         var inst = $.data(target, PROP_NAME);
  2473.         if (!$target.hasClass(this.markerClassName)) {
  2474.             return;
  2475.         }
  2476.         var nodeName = target.nodeName.toLowerCase();
  2477.         $.removeData(target, PROP_NAME);
  2478.         if (nodeName == 'input') {
  2479.             inst.append.remove();
  2480.             inst.trigger.remove();
  2481.             $target.removeClass(this.markerClassName).
  2482.                 unbind('focus', this._showDatepicker).
  2483.                 unbind('keydown', this._doKeyDown).
  2484.                 unbind('keypress', this._doKeyPress).
  2485.                 unbind('keyup', this._doKeyUp);
  2486.         } else if (nodeName == 'div' || nodeName == 'span')
  2487.             $target.removeClass(this.markerClassName).empty();
  2488.     },
  2489.  
  2490.     /* Enable the date picker to a jQuery selection.
  2491.        @param  target    element - the target input field or division or span */
  2492.     _enableDatepicker: function(target) {
  2493.         var $target = $(target);
  2494.         var inst = $.data(target, PROP_NAME);
  2495.         if (!$target.hasClass(this.markerClassName)) {
  2496.             return;
  2497.         }
  2498.         var nodeName = target.nodeName.toLowerCase();
  2499.         if (nodeName == 'input') {
  2500.             target.disabled = false;
  2501.             inst.trigger.filter('button').
  2502.                 each(function() { this.disabled = false; }).end().
  2503.                 filter('img').css({opacity: '1.0', cursor: ''});
  2504.         }
  2505.         else if (nodeName == 'div' || nodeName == 'span') {
  2506.             var inline = $target.children('.' + this._inlineClass);
  2507.             inline.children().removeClass('ui-state-disabled');
  2508.             inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
  2509.                 prop("disabled", false);
  2510.         }
  2511.         this._disabledInputs = $.map(this._disabledInputs,
  2512.             function(value) { return (value == target ? null : value); }); // delete entry
  2513.     },
  2514.  
  2515.     /* Disable the date picker to a jQuery selection.
  2516.        @param  target    element - the target input field or division or span */
  2517.     _disableDatepicker: function(target) {
  2518.         var $target = $(target);
  2519.         var inst = $.data(target, PROP_NAME);
  2520.         if (!$target.hasClass(this.markerClassName)) {
  2521.             return;
  2522.         }
  2523.         var nodeName = target.nodeName.toLowerCase();
  2524.         if (nodeName == 'input') {
  2525.             target.disabled = true;
  2526.             inst.trigger.filter('button').
  2527.                 each(function() { this.disabled = true; }).end().
  2528.                 filter('img').css({opacity: '0.5', cursor: 'default'});
  2529.         }
  2530.         else if (nodeName == 'div' || nodeName == 'span') {
  2531.             var inline = $target.children('.' + this._inlineClass);
  2532.             inline.children().addClass('ui-state-disabled');
  2533.             inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
  2534.                 prop("disabled", true);
  2535.         }
  2536.         this._disabledInputs = $.map(this._disabledInputs,
  2537.             function(value) { return (value == target ? null : value); }); // delete entry
  2538.         this._disabledInputs[this._disabledInputs.length] = target;
  2539.     },
  2540.  
  2541.     /* Is the first field in a jQuery collection disabled as a datepicker?
  2542.        @param  target    element - the target input field or division or span
  2543.        @return boolean - true if disabled, false if enabled */
  2544.     _isDisabledDatepicker: function(target) {
  2545.         if (!target) {
  2546.             return false;
  2547.         }
  2548.         for (var i = 0; i < this._disabledInputs.length; i++) {
  2549.             if (this._disabledInputs[i] == target)
  2550.                 return true;
  2551.         }
  2552.         return false;
  2553.     },
  2554.  
  2555.     /* Retrieve the instance data for the target control.
  2556.        @param  target  element - the target input field or division or span
  2557.        @return  object - the associated instance data
  2558.        @throws  error if a jQuery problem getting data */
  2559.     _getInst: function(target) {
  2560.         try {
  2561.             return $.data(target, PROP_NAME);
  2562.         }
  2563.         catch (err) {
  2564.             throw 'Missing instance data for this datepicker';
  2565.         }
  2566.     },
  2567.  
  2568.     /* Update or retrieve the settings for a date picker attached to an input field or division.
  2569.        @param  target  element - the target input field or division or span
  2570.        @param  name    object - the new settings to update or
  2571.                        string - the name of the setting to change or retrieve,
  2572.                        when retrieving also 'all' for all instance settings or
  2573.                        'defaults' for all global defaults
  2574.        @param  value   any - the new value for the setting
  2575.                        (omit if above is an object or to retrieve a value) */
  2576.     _optionDatepicker: function(target, name, value) {
  2577.         var inst = this._getInst(target);
  2578.         if (arguments.length == 2 && typeof name == 'string') {
  2579.             return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
  2580.                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
  2581.                 this._get(inst, name)) : null));
  2582.         }
  2583.         var settings = name || {};
  2584.         if (typeof name == 'string') {
  2585.             settings = {};
  2586.             settings[name] = value;
  2587.         }
  2588.         if (inst) {
  2589.             if (this._curInst == inst) {
  2590.                 this._hideDatepicker();
  2591.             }
  2592.             var date = this._getDateDatepicker(target, true);
  2593.             var minDate = this._getMinMaxDate(inst, 'min');
  2594.             var maxDate = this._getMinMaxDate(inst, 'max');
  2595.             extendRemove(inst.settings, settings);
  2596.             // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
  2597.             if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
  2598.                 inst.settings.minDate = this._formatDate(inst, minDate);
  2599.             if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
  2600.                 inst.settings.maxDate = this._formatDate(inst, maxDate);
  2601.             this._attachments($(target), inst);
  2602.             this._autoSize(inst);
  2603.             this._setDate(inst, date);
  2604.             this._updateAlternate(inst);
  2605.             this._updateDatepicker(inst);
  2606.         }
  2607.     },
  2608.     // change method deprecated
  2609.     _changeDatepicker: function(target, name, value) {
  2610.         this._optionDatepicker(target, name, value);
  2611.     },
  2612.     /* Redraw the date picker attached to an input field or division.
  2613.        @param  target  element - the target input field or division or span */
  2614.     _refreshDatepicker: function(target) {
  2615.         var inst = this._getInst(target);
  2616.         if (inst) {
  2617.             this._updateDatepicker(inst);
  2618.         }
  2619.     },
  2620.     /* Set the dates for a jQuery selection.
  2621.        @param  target   element - the target input field or division or span
  2622.        @param  date     Date - the new date */
  2623.     _setDateDatepicker: function(target, date) {
  2624.         var inst = this._getInst(target);
  2625.         if (inst) {
  2626.             this._setDate(inst, date);
  2627.             this._updateDatepicker(inst);
  2628.             this._updateAlternate(inst);
  2629.         }
  2630.     },
  2631.     /* Get the date(s) for the first entry in a jQuery selection.
  2632.        @param  target     element - the target input field or division or span
  2633.        @param  noDefault  boolean - true if no default date is to be used
  2634.        @return Date - the current date */
  2635.     _getDateDatepicker: function(target, noDefault) {
  2636.         var inst = this._getInst(target);
  2637.         if (inst && !inst.inline)
  2638.             this._setDateFromField(inst, noDefault);
  2639.         return (inst ? this._getDate(inst) : null);
  2640.     },
  2641.     /* Handle keystrokes. */
  2642.     _doKeyDown: function(event) {
  2643.         var inst = $.datepicker._getInst(event.target);
  2644.         var handled = true;
  2645.         var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
  2646.         inst._keyEvent = true;
  2647.         if ($.datepicker._datepickerShowing)
  2648.             switch (event.keyCode) {
  2649.                 case 9: $.datepicker._hideDatepicker();
  2650.                         handled = false;
  2651.                         break; // hide on tab out
  2652.                 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
  2653.                                     $.datepicker._currentClass + ')', inst.dpDiv);
  2654.                         if (sel[0])
  2655.                             $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
  2656.                             var onSelect = $.datepicker._get(inst, 'onSelect');
  2657.                             if (onSelect) {
  2658.                                 var dateStr = $.datepicker._formatDate(inst);
  2659.                                 // trigger custom callback
  2660.                                 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
  2661.                             }
  2662.                         else
  2663.                             $.datepicker._hideDatepicker();
  2664.                         return false; // don't submit the form
  2665.                         break; // select the value on enter
  2666.                 case 27: $.datepicker._hideDatepicker();
  2667.                         break; // hide on escape
  2668.                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
  2669.                             -$.datepicker._get(inst, 'stepBigMonths') :
  2670.                             -$.datepicker._get(inst, 'stepMonths')), 'M');
  2671.                         break; // previous month/year on page up/+ ctrl
  2672.                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
  2673.                             +$.datepicker._get(inst, 'stepBigMonths') :
  2674.                             +$.datepicker._get(inst, 'stepMonths')), 'M');
  2675.                         break; // next month/year on page down/+ ctrl
  2676.                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
  2677.                         handled = event.ctrlKey || event.metaKey;
  2678.                         break; // clear on ctrl or command +end
  2679.                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
  2680.                         handled = event.ctrlKey || event.metaKey;
  2681.                         break; // current on ctrl or command +home
  2682.                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
  2683.                         handled = event.ctrlKey || event.metaKey;
  2684.                         // -1 day on ctrl or command +left
  2685.                         if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
  2686.                                     -$.datepicker._get(inst, 'stepBigMonths') :
  2687.                                     -$.datepicker._get(inst, 'stepMonths')), 'M');
  2688.                         // next month/year on alt +left on Mac
  2689.                         break;
  2690.                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
  2691.                         handled = event.ctrlKey || event.metaKey;
  2692.                         break; // -1 week on ctrl or command +up
  2693.                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
  2694.                         handled = event.ctrlKey || event.metaKey;
  2695.                         // +1 day on ctrl or command +right
  2696.                         if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
  2697.                                     +$.datepicker._get(inst, 'stepBigMonths') :
  2698.                                     +$.datepicker._get(inst, 'stepMonths')), 'M');
  2699.                         // next month/year on alt +right
  2700.                         break;
  2701.                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
  2702.                         handled = event.ctrlKey || event.metaKey;
  2703.                         break; // +1 week on ctrl or command +down
  2704.                 default: handled = false;
  2705.             }
  2706.         else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
  2707.             $.datepicker._showDatepicker(this);
  2708.         else {
  2709.             handled = false;
  2710.         }
  2711.         if (handled) {
  2712.             event.preventDefault();
  2713.             event.stopPropagation();
  2714.         }
  2715.     },
  2716.  
  2717.     /* Filter entered characters - based on date format. */
  2718.     _doKeyPress: function(event) {
  2719.         var inst = $.datepicker._getInst(event.target);
  2720.         if ($.datepicker._get(inst, 'constrainInput')) {
  2721.             var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
  2722.             var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
  2723.             return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
  2724.         }
  2725.     },
  2726.  
  2727.     /* Synchronise manual entry and field/alternate field. */
  2728.     _doKeyUp: function(event) {
  2729.         var inst = $.datepicker._getInst(event.target);
  2730.         if (inst.input.val() != inst.lastVal) {
  2731.             try {
  2732.                 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
  2733.                     (inst.input ? inst.input.val() : null),
  2734.                     $.datepicker._getFormatConfig(inst));
  2735.                 if (date) { // only if valid
  2736.                     $.datepicker._setDateFromField(inst);
  2737.                     $.datepicker._updateAlternate(inst);
  2738.                     $.datepicker._updateDatepicker(inst);
  2739.                 }
  2740.             }
  2741.             catch (err) {
  2742.                 $.datepicker.log(err);
  2743.             }
  2744.         }
  2745.         return true;
  2746.     },
  2747.  
  2748.     /* Pop-up the date picker for a given input field.
  2749.        If false returned from beforeShow event handler do not show.
  2750.        @param  input  element - the input field attached to the date picker or
  2751.                       event - if triggered by focus */
  2752.     _showDatepicker: function(input) {
  2753.         input = input.target || input;
  2754.         if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
  2755.             input = $('input', input.parentNode)[0];
  2756.         if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
  2757.             return;
  2758.         var inst = $.datepicker._getInst(input);
  2759.         if ($.datepicker._curInst && $.datepicker._curInst != inst) {
  2760.             $.datepicker._curInst.dpDiv.stop(true, true);
  2761.             if ( inst && $.datepicker._datepickerShowing ) {
  2762.                 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
  2763.             }
  2764.         }
  2765.         var beforeShow = $.datepicker._get(inst, 'beforeShow');
  2766.         var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
  2767.         if(beforeShowSettings === false){
  2768.             //false
  2769.             return;
  2770.         }
  2771.         extendRemove(inst.settings, beforeShowSettings);
  2772.         inst.lastVal = null;
  2773.         $.datepicker._lastInput = input;
  2774.         $.datepicker._setDateFromField(inst);
  2775.         if ($.datepicker._inDialog) // hide cursor
  2776.             input.value = '';
  2777.         if (!$.datepicker._pos) { // position below input
  2778.             $.datepicker._pos = $.datepicker._findPos(input);
  2779.             $.datepicker._pos[1] += input.offsetHeight; // add the height
  2780.         }
  2781.         var isFixed = false;
  2782.         $(input).parents().each(function() {
  2783.             isFixed |= $(this).css('position') == 'fixed';
  2784.             return !isFixed;
  2785.         });
  2786.         var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
  2787.         $.datepicker._pos = null;
  2788.         //to avoid flashes on Firefox
  2789.         inst.dpDiv.empty();
  2790.         // determine sizing offscreen
  2791.         inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
  2792.         $.datepicker._updateDatepicker(inst);
  2793.         // fix width for dynamic number of date pickers
  2794.         // and adjust position before showing
  2795.         offset = $.datepicker._checkOffset(inst, offset, isFixed);
  2796.         inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
  2797.             'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
  2798.             left: offset.left + 'px', top: offset.top + 'px'});
  2799.         if (!inst.inline) {
  2800.             var showAnim = $.datepicker._get(inst, 'showAnim');
  2801.             var duration = $.datepicker._get(inst, 'duration');
  2802.             var postProcess = function() {
  2803.                 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
  2804.                 if( !! cover.length ){
  2805.                     var borders = $.datepicker._getBorders(inst.dpDiv);
  2806.                     cover.css({left: -borders[0], top: -borders[1],
  2807.                         width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
  2808.                 }
  2809.             };
  2810.             inst.dpDiv.zIndex($(input).zIndex()+1);
  2811.             $.datepicker._datepickerShowing = true;
  2812.  
  2813.             // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
  2814.             if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
  2815.                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
  2816.             else
  2817.                 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
  2818.             if (!showAnim || !duration)
  2819.                 postProcess();
  2820.             if (inst.input.is(':visible') && !inst.input.is(':disabled'))
  2821.                 inst.input.focus();
  2822.             $.datepicker._curInst = inst;
  2823.         }
  2824.     },
  2825.  
  2826.     /* Generate the date picker content. */
  2827.     _updateDatepicker: function(inst) {
  2828.         this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
  2829.         var borders = $.datepicker._getBorders(inst.dpDiv);
  2830.         instActive = inst; // for delegate hover events
  2831.         inst.dpDiv.empty().append(this._generateHTML(inst));
  2832.         this._attachHandlers(inst);
  2833.         var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
  2834.         if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
  2835.             cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
  2836.         }
  2837.         inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
  2838.         var numMonths = this._getNumberOfMonths(inst);
  2839.         var cols = numMonths[1];
  2840.         var width = 17;
  2841.         inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
  2842.         if (cols > 1)
  2843.             inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
  2844.         inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
  2845.             'Class']('ui-datepicker-multi');
  2846.         inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
  2847.             'Class']('ui-datepicker-rtl');
  2848.         if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
  2849.                 // #6694 - don't focus the input if it's already focused
  2850.                 // this breaks the change event in IE
  2851.                 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
  2852.             inst.input.focus();
  2853.         // deffered render of the years select (to avoid flashes on Firefox)
  2854.         if( inst.yearshtml ){
  2855.             var origyearshtml = inst.yearshtml;
  2856.             setTimeout(function(){
  2857.                 //assure that inst.yearshtml didn't change.
  2858.                 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
  2859.                     inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
  2860.                 }
  2861.                 origyearshtml = inst.yearshtml = null;
  2862.             }, 0);
  2863.         }
  2864.     },
  2865.  
  2866.     /* Retrieve the size of left and top borders for an element.
  2867.        @param  elem  (jQuery object) the element of interest
  2868.        @return  (number[2]) the left and top borders */
  2869.     _getBorders: function(elem) {
  2870.         var convert = function(value) {
  2871.             return {thin: 1, medium: 2, thick: 3}[value] || value;
  2872.         };
  2873.         return [parseFloat(convert(elem.css('border-left-width'))),
  2874.             parseFloat(convert(elem.css('border-top-width')))];
  2875.     },
  2876.  
  2877.     /* Check positioning to remain on screen. */
  2878.     _checkOffset: function(inst, offset, isFixed) {
  2879.         var dpWidth = inst.dpDiv.outerWidth();
  2880.         var dpHeight = inst.dpDiv.outerHeight();
  2881.         var inputWidth = inst.input ? inst.input.outerWidth() : 0;
  2882.         var inputHeight = inst.input ? inst.input.outerHeight() : 0;
  2883.         var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
  2884.         var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
  2885.  
  2886.         offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
  2887.         offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
  2888.         offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
  2889.  
  2890.         // now check if datepicker is showing outside window viewport - move to a better place if so.
  2891.         offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
  2892.             Math.abs(offset.left + dpWidth - viewWidth) : 0);
  2893.         offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
  2894.             Math.abs(dpHeight + inputHeight) : 0);
  2895.  
  2896.         return offset;
  2897.     },
  2898.  
  2899.     /* Find an object's position on the screen. */
  2900.     _findPos: function(obj) {
  2901.         var inst = this._getInst(obj);
  2902.         var isRTL = this._get(inst, 'isRTL');
  2903.         while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
  2904.             obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
  2905.         }
  2906.         var position = $(obj).offset();
  2907.         return [position.left, position.top];
  2908.     },
  2909.  
  2910.     /* Hide the date picker from view.
  2911.        @param  input  element - the input field attached to the date picker */
  2912.     _hideDatepicker: function(input) {
  2913.         var inst = this._curInst;
  2914.         if (!inst || (input && inst != $.data(input, PROP_NAME)))
  2915.             return;
  2916.         if (this._datepickerShowing) {
  2917.             var showAnim = this._get(inst, 'showAnim');
  2918.             var duration = this._get(inst, 'duration');
  2919.             var postProcess = function() {
  2920.                 $.datepicker._tidyDialog(inst);
  2921.             };
  2922.  
  2923.             // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
  2924.             if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
  2925.                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
  2926.             else
  2927.                 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
  2928.                     (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
  2929.             if (!showAnim)
  2930.                 postProcess();
  2931.             this._datepickerShowing = false;
  2932.             var onClose = this._get(inst, 'onClose');
  2933.             if (onClose)
  2934.                 onClose.apply((inst.input ? inst.input[0] : null),
  2935.                     [(inst.input ? inst.input.val() : ''), inst]);
  2936.             this._lastInput = null;
  2937.             if (this._inDialog) {
  2938.                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
  2939.                 if ($.blockUI) {
  2940.                     $.unblockUI();
  2941.                     $('body').append(this.dpDiv);
  2942.                 }
  2943.             }
  2944.             this._inDialog = false;
  2945.         }
  2946.     },
  2947.  
  2948.     /* Tidy up after a dialog display. */
  2949.     _tidyDialog: function(inst) {
  2950.         inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
  2951.     },
  2952.  
  2953.     /* Close date picker if clicked elsewhere. */
  2954.     _checkExternalClick: function(event) {
  2955.         if (!$.datepicker._curInst)
  2956.             return;
  2957.  
  2958.         var $target = $(event.target),
  2959.             inst = $.datepicker._getInst($target[0]);
  2960.  
  2961.         if ( ( ( $target[0].id != $.datepicker._mainDivId &&
  2962.                 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
  2963.                 !$target.hasClass($.datepicker.markerClassName) &&
  2964.                 !$target.closest("." + $.datepicker._triggerClass).length &&
  2965.                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
  2966.             ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
  2967.             $.datepicker._hideDatepicker();
  2968.     },
  2969.  
  2970.     /* Adjust one of the date sub-fields. */
  2971.     _adjustDate: function(id, offset, period) {
  2972.         var target = $(id);
  2973.         var inst = this._getInst(target[0]);
  2974.         if (this._isDisabledDatepicker(target[0])) {
  2975.             return;
  2976.         }
  2977.         this._adjustInstDate(inst, offset +
  2978.             (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
  2979.             period);
  2980.         this._updateDatepicker(inst);
  2981.     },
  2982.  
  2983.     /* Action for current link. */
  2984.     _gotoToday: function(id) {
  2985.         var target = $(id);
  2986.         var inst = this._getInst(target[0]);
  2987.         if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
  2988.             inst.selectedDay = inst.currentDay;
  2989.             inst.drawMonth = inst.selectedMonth = inst.currentMonth;
  2990.             inst.drawYear = inst.selectedYear = inst.currentYear;
  2991.         }
  2992.         else {
  2993.             var date = new Date();
  2994.             inst.selectedDay = date.getDate();
  2995.             inst.drawMonth = inst.selectedMonth = date.getMonth();
  2996.             inst.drawYear = inst.selectedYear = date.getFullYear();
  2997.         }
  2998.         this._notifyChange(inst);
  2999.         this._adjustDate(target);
  3000.     },
  3001.  
  3002.     /* Action for selecting a new month/year. */
  3003.     _selectMonthYear: function(id, select, period) {
  3004.         var target = $(id);
  3005.         var inst = this._getInst(target[0]);
  3006.         inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
  3007.         inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
  3008.             parseInt(select.options[select.selectedIndex].value,10);
  3009.         this._notifyChange(inst);
  3010.         this._adjustDate(target);
  3011.     },
  3012.  
  3013.     /* Action for selecting a day. */
  3014.     _selectDay: function(id, month, year, td) {
  3015.         var target = $(id);
  3016.         if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
  3017.             return;
  3018.         }
  3019.         var inst = this._getInst(target[0]);
  3020.         inst.selectedDay = inst.currentDay = $('a', td).html();
  3021.         inst.selectedMonth = inst.currentMonth = month;
  3022.         inst.selectedYear = inst.currentYear = year;
  3023.         this._selectDate(id, this._formatDate(inst,
  3024.             inst.currentDay, inst.currentMonth, inst.currentYear));
  3025.     },
  3026.  
  3027.     /* Erase the input field and hide the date picker. */
  3028.     _clearDate: function(id) {
  3029.         var target = $(id);
  3030.         var inst = this._getInst(target[0]);
  3031.         this._selectDate(target, '');
  3032.     },
  3033.  
  3034.     /* Update the input field with the selected date. */
  3035.     _selectDate: function(id, dateStr) {
  3036.         var target = $(id);
  3037.         var inst = this._getInst(target[0]);
  3038.         dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
  3039.         if (inst.input)
  3040.             inst.input.val(dateStr);
  3041.         this._updateAlternate(inst);
  3042.         var onSelect = this._get(inst, 'onSelect');
  3043.         if (onSelect)
  3044.             onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
  3045.         else if (inst.input)
  3046.             inst.input.trigger('change'); // fire the change event
  3047.         if (inst.inline)
  3048.             this._updateDatepicker(inst);
  3049.         else {
  3050.             this._hideDatepicker();
  3051.             this._lastInput = inst.input[0];
  3052.             if (typeof(inst.input[0]) != 'object')
  3053.                 inst.input.focus(); // restore focus
  3054.             this._lastInput = null;
  3055.         }
  3056.     },
  3057.  
  3058.     /* Update any alternate field to synchronise with the main field. */
  3059.     _updateAlternate: function(inst) {
  3060.         var altField = this._get(inst, 'altField');
  3061.         if (altField) { // update alternate field too
  3062.             var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
  3063.             var date = this._getDate(inst);
  3064.             var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
  3065.             $(altField).each(function() { $(this).val(dateStr); });
  3066.         }
  3067.     },
  3068.  
  3069.     /* Set as beforeShowDay function to prevent selection of weekends.
  3070.        @param  date  Date - the date to customise
  3071.        @return [boolean, string] - is this date selectable?, what is its CSS class? */
  3072.     noWeekends: function(date) {
  3073.         var day = date.getDay();
  3074.         return [(day > 0 && day < 6), ''];
  3075.     },
  3076.  
  3077.     /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
  3078.        @param  date  Date - the date to get the week for
  3079.        @return  number - the number of the week within the year that contains this date */
  3080.     iso8601Week: function(date) {
  3081.         var checkDate = new Date(date.getTime());
  3082.         // Find Thursday of this week starting on Monday
  3083.         checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
  3084.         var time = checkDate.getTime();
  3085.         checkDate.setMonth(0); // Compare with Jan 1
  3086.         checkDate.setDate(1);
  3087.         return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
  3088.     },
  3089.  
  3090.     /* Parse a string value into a date object.
  3091.        See formatDate below for the possible formats.
  3092.  
  3093.        @param  format    string - the expected format of the date
  3094.        @param  value     string - the date in the above format
  3095.        @param  settings  Object - attributes include:
  3096.                          shortYearCutoff  number - the cutoff year for determining the century (optional)
  3097.                          dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
  3098.                          dayNames         string[7] - names of the days from Sunday (optional)
  3099.                          monthNamesShort  string[12] - abbreviated names of the months (optional)
  3100.                          monthNames       string[12] - names of the months (optional)
  3101.        @return  Date - the extracted date value or null if value is blank */
  3102.     parseDate: function (format, value, settings) {
  3103.         if (format == null || value == null)
  3104.             throw 'Invalid arguments';
  3105.         value = (typeof value == 'object' ? value.toString() : value + '');
  3106.         if (value == '')
  3107.             return null;
  3108.         var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
  3109.         shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
  3110.                 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
  3111.         var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
  3112.         var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
  3113.         var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
  3114.         var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
  3115.         var year = -1;
  3116.         var month = -1;
  3117.         var day = -1;
  3118.         var doy = -1;
  3119.         var literal = false;
  3120.         // Check whether a format character is doubled
  3121.         var lookAhead = function(match) {
  3122.             var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
  3123.             if (matches)
  3124.                 iFormat++;
  3125.             return matches;
  3126.         };
  3127.         // Extract a number from the string value
  3128.         var getNumber = function(match) {
  3129.             var isDoubled = lookAhead(match);
  3130.             var size = (match == '@' ? 14 : (match == '!' ? 20 :
  3131.                 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
  3132.             var digits = new RegExp('^\\d{1,' + size + '}');
  3133.             var num = value.substring(iValue).match(digits);
  3134.             if (!num)
  3135.                 throw 'Missing number at position ' + iValue;
  3136.             iValue += num[0].length;
  3137.             return parseInt(num[0], 10);
  3138.         };
  3139.         // Extract a name from the string value and convert to an index
  3140.         var getName = function(match, shortNames, longNames) {
  3141.             var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
  3142.                 return [ [k, v] ];
  3143.             }).sort(function (a, b) {
  3144.                 return -(a[1].length - b[1].length);
  3145.             });
  3146.             var index = -1;
  3147.             $.each(names, function (i, pair) {
  3148.                 var name = pair[1];
  3149.                 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
  3150.                     index = pair[0];
  3151.                     iValue += name.length;
  3152.                     return false;
  3153.                 }
  3154.             });
  3155.             if (index != -1)
  3156.                 return index + 1;
  3157.             else
  3158.                 throw 'Unknown name at position ' + iValue;
  3159.         };
  3160.         // Confirm that a literal character matches the string value
  3161.         var checkLiteral = function() {
  3162.             if (value.charAt(iValue) != format.charAt(iFormat))
  3163.                 throw 'Unexpected literal at position ' + iValue;
  3164.             iValue++;
  3165.         };
  3166.         var iValue = 0;
  3167.         for (var iFormat = 0; iFormat < format.length; iFormat++) {
  3168.             if (literal)
  3169.                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
  3170.                     literal = false;
  3171.                 else
  3172.                     checkLiteral();
  3173.             else
  3174.                 switch (format.charAt(iFormat)) {
  3175.                     case 'd':
  3176.                         day = getNumber('d');
  3177.                         break;
  3178.                     case 'D':
  3179.                         getName('D', dayNamesShort, dayNames);
  3180.                         break;
  3181.                     case 'o':
  3182.                         doy = getNumber('o');
  3183.                         break;
  3184.                     case 'm':
  3185.                         month = getNumber('m');
  3186.                         break;
  3187.                     case 'M':
  3188.                         month = getName('M', monthNamesShort, monthNames);
  3189.                         break;
  3190.                     case 'y':
  3191.                         year = getNumber('y');
  3192.                         break;
  3193.                     case '@':
  3194.                         var date = new Date(getNumber('@'));
  3195.                         year = date.getFullYear();
  3196.                         month = date.getMonth() + 1;
  3197.                         day = date.getDate();
  3198.                         break;
  3199.                     case '!':
  3200.                         var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
  3201.                         year = date.getFullYear();
  3202.                         month = date.getMonth() + 1;
  3203.                         day = date.getDate();
  3204.                         break;
  3205.                     case "'":
  3206.                         if (lookAhead("'"))
  3207.                             checkLiteral();
  3208.                         else
  3209.                             literal = true;
  3210.                         break;
  3211.                     default:
  3212.                         checkLiteral();
  3213.                 }
  3214.         }
  3215.         if (iValue < value.length){
  3216.             var extra = value.substr(iValue);
  3217.             if (!/^\s+/.test(extra)) {
  3218.                 throw "Extra/unparsed characters found in date: " + extra;
  3219.             }
  3220.         }
  3221.         if (year == -1)
  3222.             year = new Date().getFullYear();
  3223.         else if (year < 100)
  3224.             year += new Date().getFullYear() - new Date().getFullYear() % 100 +
  3225.                 (year <= shortYearCutoff ? 0 : -100);
  3226.         if (doy > -1) {
  3227.             month = 1;
  3228.             day = doy;
  3229.             do {
  3230.                 var dim = this._getDaysInMonth(year, month - 1);
  3231.                 if (day <= dim)
  3232.                     break;
  3233.                 month++;
  3234.                 day -= dim;
  3235.             } while (true);
  3236.         }
  3237.         var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
  3238.         if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
  3239.             throw 'Invalid date'; // E.g. 31/02/00
  3240.         return date;
  3241.     },
  3242.  
  3243.     /* Standard date formats. */
  3244.     ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
  3245.     COOKIE: 'D, dd M yy',
  3246.     ISO_8601: 'yy-mm-dd',
  3247.     RFC_822: 'D, d M y',
  3248.     RFC_850: 'DD, dd-M-y',
  3249.     RFC_1036: 'D, d M y',
  3250.     RFC_1123: 'D, d M yy',
  3251.     RFC_2822: 'D, d M yy',
  3252.     RSS: 'D, d M y', // RFC 822
  3253.     TICKS: '!',
  3254.     TIMESTAMP: '@',
  3255.     W3C: 'yy-mm-dd', // ISO 8601
  3256.  
  3257.     _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
  3258.         Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
  3259.  
  3260.     /* Format a date object into a string value.
  3261.        The format can be combinations of the following:
  3262.        d  - day of month (no leading zero)
  3263.        dd - day of month (two digit)
  3264.        o  - day of year (no leading zeros)
  3265.        oo - day of year (three digit)
  3266.        D  - day name short
  3267.        DD - day name long
  3268.        m  - month of year (no leading zero)
  3269.        mm - month of year (two digit)
  3270.        M  - month name short
  3271.        MM - month name long
  3272.        y  - year (two digit)
  3273.        yy - year (four digit)
  3274.        @ - Unix timestamp (ms since 01/01/1970)
  3275.        ! - Windows ticks (100ns since 01/01/0001)
  3276.        '...' - literal text
  3277.        '' - single quote
  3278.  
  3279.        @param  format    string - the desired format of the date
  3280.        @param  date      Date - the date value to format
  3281.        @param  settings  Object - attributes include:
  3282.                          dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
  3283.                          dayNames         string[7] - names of the days from Sunday (optional)
  3284.                          monthNamesShort  string[12] - abbreviated names of the months (optional)
  3285.                          monthNames       string[12] - names of the months (optional)
  3286.        @return  string - the date in the above format */
  3287.     formatDate: function (format, date, settings) {
  3288.         if (!date)
  3289.             return '';
  3290.         var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
  3291.         var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
  3292.         var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
  3293.         var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
  3294.         // Check whether a format character is doubled
  3295.         var lookAhead = function(match) {
  3296.             var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
  3297.             if (matches)
  3298.                 iFormat++;
  3299.             return matches;
  3300.         };
  3301.         // Format a number, with leading zero if necessary
  3302.         var formatNumber = function(match, value, len) {
  3303.             var num = '' + value;
  3304.             if (lookAhead(match))
  3305.                 while (num.length < len)
  3306.                     num = '0' + num;
  3307.             return num;
  3308.         };
  3309.         // Format a name, short or long as requested
  3310.         var formatName = function(match, value, shortNames, longNames) {
  3311.             return (lookAhead(match) ? longNames[value] : shortNames[value]);
  3312.         };
  3313.         var output = '';
  3314.         var literal = false;
  3315.         if (date)
  3316.             for (var iFormat = 0; iFormat < format.length; iFormat++) {
  3317.                 if (literal)
  3318.                     if (format.charAt(iFormat) == "'" && !lookAhead("'"))
  3319.                         literal = false;
  3320.                     else
  3321.                         output += format.charAt(iFormat);
  3322.                 else
  3323.                     switch (format.charAt(iFormat)) {
  3324.                         case 'd':
  3325.                             output += formatNumber('d', date.getDate(), 2);
  3326.                             break;
  3327.                         case 'D':
  3328.                             output += formatName('D', date.getDay(), dayNamesShort, dayNames);
  3329.                             break;
  3330.                         case 'o':
  3331.                             output += formatNumber('o',
  3332.                                 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
  3333.                             break;
  3334.                         case 'm':
  3335.                             output += formatNumber('m', date.getMonth() + 1, 2);
  3336.                             break;
  3337.                         case 'M':
  3338.                             output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
  3339.                             break;
  3340.                         case 'y':
  3341.                             output += (lookAhead('y') ? date.getFullYear() :
  3342.                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
  3343.                             break;
  3344.                         case '@':
  3345.                             output += date.getTime();
  3346.                             break;
  3347.                         case '!':
  3348.                             output += date.getTime() * 10000 + this._ticksTo1970;
  3349.                             break;
  3350.                         case "'":
  3351.                             if (lookAhead("'"))
  3352.                                 output += "'";
  3353.                             else
  3354.                                 literal = true;
  3355.                             break;
  3356.                         default:
  3357.                             output += format.charAt(iFormat);
  3358.                     }
  3359.             }
  3360.         return output;
  3361.     },
  3362.  
  3363.     /* Extract all possible characters from the date format. */
  3364.     _possibleChars: function (format) {
  3365.         var chars = '';
  3366.         var literal = false;
  3367.         // Check whether a format character is doubled
  3368.         var lookAhead = function(match) {
  3369.             var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
  3370.             if (matches)
  3371.                 iFormat++;
  3372.             return matches;
  3373.         };
  3374.         for (var iFormat = 0; iFormat < format.length; iFormat++)
  3375.             if (literal)
  3376.                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
  3377.                     literal = false;
  3378.                 else
  3379.                     chars += format.charAt(iFormat);
  3380.             else
  3381.                 switch (format.charAt(iFormat)) {
  3382.                     case 'd': case 'm': case 'y': case '@':
  3383.                         chars += '0123456789';
  3384.                         break;
  3385.                     case 'D': case 'M':
  3386.                         return null; // Accept anything
  3387.                     case "'":
  3388.                         if (lookAhead("'"))
  3389.                             chars += "'";
  3390.                         else
  3391.                             literal = true;
  3392.                         break;
  3393.                     default:
  3394.                         chars += format.charAt(iFormat);
  3395.                 }
  3396.         return chars;
  3397.     },
  3398.  
  3399.     /* Get a setting value, defaulting if necessary. */
  3400.     _get: function(inst, name) {
  3401.         return inst.settings[name] !== undefined ?
  3402.             inst.settings[name] : this._defaults[name];
  3403.     },
  3404.  
  3405.     /* Parse existing date and initialise date picker. */
  3406.     _setDateFromField: function(inst, noDefault) {
  3407.         if (inst.input.val() == inst.lastVal) {
  3408.             return;
  3409.         }
  3410.         var dateFormat = this._get(inst, 'dateFormat');
  3411.         var dates = inst.lastVal = inst.input ? inst.input.val() : null;
  3412.         var date, defaultDate;
  3413.         date = defaultDate = this._getDefaultDate(inst);
  3414.         var settings = this._getFormatConfig(inst);
  3415.         try {
  3416.             date = this.parseDate(dateFormat, dates, settings) || defaultDate;
  3417.         } catch (event) {
  3418.             this.log(event);
  3419.             dates = (noDefault ? '' : dates);
  3420.         }
  3421.         inst.selectedDay = date.getDate();
  3422.         inst.drawMonth = inst.selectedMonth = date.getMonth();
  3423.         inst.drawYear = inst.selectedYear = date.getFullYear();
  3424.         inst.currentDay = (dates ? date.getDate() : 0);
  3425.         inst.currentMonth = (dates ? date.getMonth() : 0);
  3426.         inst.currentYear = (dates ? date.getFullYear() : 0);
  3427.         this._adjustInstDate(inst);
  3428.     },
  3429.  
  3430.     /* Retrieve the default date shown on opening. */
  3431.     _getDefaultDate: function(inst) {
  3432.         return this._restrictMinMax(inst,
  3433.             this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
  3434.     },
  3435.  
  3436.     /* A date may be specified as an exact value or a relative one. */
  3437.     _determineDate: function(inst, date, defaultDate) {
  3438.         var offsetNumeric = function(offset) {
  3439.             var date = new Date();
  3440.             date.setDate(date.getDate() + offset);
  3441.             return date;
  3442.         };
  3443.         var offsetString = function(offset) {
  3444.             try {
  3445.                 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
  3446.                     offset, $.datepicker._getFormatConfig(inst));
  3447.             }
  3448.             catch (e) {
  3449.                 // Ignore
  3450.             }
  3451.             var date = (offset.toLowerCase().match(/^c/) ?
  3452.                 $.datepicker._getDate(inst) : null) || new Date();
  3453.             var year = date.getFullYear();
  3454.             var month = date.getMonth();
  3455.             var day = date.getDate();
  3456.             var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
  3457.             var matches = pattern.exec(offset);
  3458.             while (matches) {
  3459.                 switch (matches[2] || 'd') {
  3460.                     case 'd' : case 'D' :
  3461.                         day += parseInt(matches[1],10); break;
  3462.                     case 'w' : case 'W' :
  3463.                         day += parseInt(matches[1],10) * 7; break;
  3464.                     case 'm' : case 'M' :
  3465.                         month += parseInt(matches[1],10);
  3466.                         day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
  3467.                         break;
  3468.                     case 'y': case 'Y' :
  3469.                         year += parseInt(matches[1],10);
  3470.                         day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
  3471.                         break;
  3472.                 }
  3473.                 matches = pattern.exec(offset);
  3474.             }
  3475.             return new Date(year, month, day);
  3476.         };
  3477.         var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
  3478.             (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
  3479.         newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
  3480.         if (newDate) {
  3481.             newDate.setHours(0);
  3482.             newDate.setMinutes(0);
  3483.             newDate.setSeconds(0);
  3484.             newDate.setMilliseconds(0);
  3485.         }
  3486.         return this._daylightSavingAdjust(newDate);
  3487.     },
  3488.  
  3489.     /* Handle switch to/from daylight saving.
  3490.        Hours may be non-zero on daylight saving cut-over:
  3491.        > 12 when midnight changeover, but then cannot generate
  3492.        midnight datetime, so jump to 1AM, otherwise reset.
  3493.        @param  date  (Date) the date to check
  3494.        @return  (Date) the corrected date */
  3495.     _daylightSavingAdjust: function(date) {
  3496.         if (!date) return null;
  3497.         date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
  3498.         return date;
  3499.     },
  3500.  
  3501.     /* Set the date(s) directly. */
  3502.     _setDate: function(inst, date, noChange) {
  3503.         var clear = !date;
  3504.         var origMonth = inst.selectedMonth;
  3505.         var origYear = inst.selectedYear;
  3506.         var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
  3507.         inst.selectedDay = inst.currentDay = newDate.getDate();
  3508.         inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
  3509.         inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
  3510.         if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
  3511.             this._notifyChange(inst);
  3512.         this._adjustInstDate(inst);
  3513.         if (inst.input) {
  3514.             inst.input.val(clear ? '' : this._formatDate(inst));
  3515.         }
  3516.     },
  3517.  
  3518.     /* Retrieve the date(s) directly. */
  3519.     _getDate: function(inst) {
  3520.         var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
  3521.             this._daylightSavingAdjust(new Date(
  3522.             inst.currentYear, inst.currentMonth, inst.currentDay)));
  3523.             return startDate;
  3524.     },
  3525.  
  3526.     /* Attach the onxxx handlers.  These are declared statically so
  3527.      * they work with static code transformers like Caja.
  3528.      */
  3529.     _attachHandlers: function(inst) {
  3530.         var stepMonths = this._get(inst, 'stepMonths');
  3531.         var id = '#' + inst.id.replace( /\\\\/g, "\\" );
  3532.         inst.dpDiv.find('[data-handler]').map(function () {
  3533.             var handler = {
  3534.                 prev: function () {
  3535.                     window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
  3536.                 },
  3537.                 next: function () {
  3538.                     window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
  3539.                 },
  3540.                 hide: function () {
  3541.                     window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
  3542.                 },
  3543.                 today: function () {
  3544.                     window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
  3545.                 },
  3546.                 selectDay: function () {
  3547.                     window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
  3548.                     return false;
  3549.                 },
  3550.                 selectMonth: function () {
  3551.                     window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
  3552.                     return false;
  3553.                 },
  3554.                 selectYear: function () {
  3555.                     window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
  3556.                     return false;
  3557.                 }
  3558.             };
  3559.             $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
  3560.         });
  3561.     },
  3562.  
  3563.     /* Generate the HTML for the current state of the date picker. */
  3564.     _generateHTML: function(inst) {
  3565.         var today = new Date();
  3566.         today = this._daylightSavingAdjust(
  3567.             new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
  3568.         var isRTL = this._get(inst, 'isRTL');
  3569.         var showButtonPanel = this._get(inst, 'showButtonPanel');
  3570.         var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
  3571.         var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
  3572.         var numMonths = this._getNumberOfMonths(inst);
  3573.         var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
  3574.         var stepMonths = this._get(inst, 'stepMonths');
  3575.         var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
  3576.         var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
  3577.             new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
  3578.         var minDate = this._getMinMaxDate(inst, 'min');
  3579.         var maxDate = this._getMinMaxDate(inst, 'max');
  3580.         var drawMonth = inst.drawMonth - showCurrentAtPos;
  3581.         var drawYear = inst.drawYear;
  3582.         if (drawMonth < 0) {
  3583.             drawMonth += 12;
  3584.             drawYear--;
  3585.         }
  3586.         if (maxDate) {
  3587.             var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
  3588.                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
  3589.             maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
  3590.             while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
  3591.                 drawMonth--;
  3592.                 if (drawMonth < 0) {
  3593.                     drawMonth = 11;
  3594.                     drawYear--;
  3595.                 }
  3596.             }
  3597.         }
  3598.         inst.drawMonth = drawMonth;
  3599.         inst.drawYear = drawYear;
  3600.         var prevText = this._get(inst, 'prevText');
  3601.         prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
  3602.             this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
  3603.             this._getFormatConfig(inst)));
  3604.         var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
  3605.             '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
  3606.             ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
  3607.             (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
  3608.         var nextText = this._get(inst, 'nextText');
  3609.         nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
  3610.             this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
  3611.             this._getFormatConfig(inst)));
  3612.         var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
  3613.             '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
  3614.             ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
  3615.             (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
  3616.         var currentText = this._get(inst, 'currentText');
  3617.         var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
  3618.         currentText = (!navigationAsDateFormat ? currentText :
  3619.             this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
  3620.         var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
  3621.             this._get(inst, 'closeText') + '</button>' : '');
  3622.         var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
  3623.             (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
  3624.             '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
  3625.         var firstDay = parseInt(this._get(inst, 'firstDay'),10);
  3626.         firstDay = (isNaN(firstDay) ? 0 : firstDay);
  3627.         var showWeek = this._get(inst, 'showWeek');
  3628.         var dayNames = this._get(inst, 'dayNames');
  3629.         var dayNamesShort = this._get(inst, 'dayNamesShort');
  3630.         var dayNamesMin = this._get(inst, 'dayNamesMin');
  3631.         var monthNames = this._get(inst, 'monthNames');
  3632.         var monthNamesShort = this._get(inst, 'monthNamesShort');
  3633.         var beforeShowDay = this._get(inst, 'beforeShowDay');
  3634.         var showOtherMonths = this._get(inst, 'showOtherMonths');
  3635.         var selectOtherMonths = this._get(inst, 'selectOtherMonths');
  3636.         var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
  3637.         var defaultDate = this._getDefaultDate(inst);
  3638.         var html = '';
  3639.         for (var row = 0; row < numMonths[0]; row++) {
  3640.             var group = '';
  3641.             this.maxRows = 4;
  3642.             for (var col = 0; col < numMonths[1]; col++) {
  3643.                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
  3644.                 var cornerClass = ' ui-corner-all';
  3645.                 var calender = '';
  3646.                 if (isMultiMonth) {
  3647.                     calender += '<div class="ui-datepicker-group';
  3648.                     if (numMonths[1] > 1)
  3649.                         switch (col) {
  3650.                             case 0: calender += ' ui-datepicker-group-first';
  3651.                                 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
  3652.                             case numMonths[1]-1: calender += ' ui-datepicker-group-last';
  3653.                                 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
  3654.                             default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
  3655.                         }
  3656.                     calender += '">';
  3657.                 }
  3658.                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
  3659.                     (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
  3660.                     (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
  3661.                     this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
  3662.                     row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
  3663.                     '</div><table class="ui-datepicker-calendar"><thead>' +
  3664.                     '<tr>';
  3665.                 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
  3666.                 for (var dow = 0; dow < 7; dow++) { // days of the week
  3667.                     var day = (dow + firstDay) % 7;
  3668.                     thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
  3669.                         '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
  3670.                 }
  3671.                 calender += thead + '</tr></thead><tbody>';
  3672.                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
  3673.                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
  3674.                     inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
  3675.                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
  3676.                 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
  3677.                 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
  3678.                 this.maxRows = numRows;
  3679.                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
  3680.                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
  3681.                     calender += '<tr>';
  3682.                     var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
  3683.                         this._get(inst, 'calculateWeek')(printDate) + '</td>');
  3684.                     for (var dow = 0; dow < 7; dow++) { // create date picker days
  3685.                         var daySettings = (beforeShowDay ?
  3686.                             beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
  3687.                         var otherMonth = (printDate.getMonth() != drawMonth);
  3688.                         var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
  3689.                             (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
  3690.                         tbody += '<td class="' +
  3691.                             ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
  3692.                             (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
  3693.                             ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
  3694.                             (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
  3695.                             // or defaultDate is current printedDate and defaultDate is selectedDate
  3696.                             ' ' + this._dayOverClass : '') + // highlight selected day
  3697.                             (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
  3698.                             (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
  3699.                             (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
  3700.                             (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
  3701.                             ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
  3702.                             (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
  3703.                             (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
  3704.                             (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
  3705.                             (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
  3706.                             (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
  3707.                             (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
  3708.                             '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
  3709.                         printDate.setDate(printDate.getDate() + 1);
  3710.                         printDate = this._daylightSavingAdjust(printDate);
  3711.                     }
  3712.                     calender += tbody + '</tr>';
  3713.                 }
  3714.                 drawMonth++;
  3715.                 if (drawMonth > 11) {
  3716.                     drawMonth = 0;
  3717.                     drawYear++;
  3718.                 }
  3719.                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
  3720.                             ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
  3721.                 group += calender;
  3722.             }
  3723.             html += group;
  3724.         }
  3725.         html += buttonPanel + ($.ui.ie6 && !inst.inline ?
  3726.             '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
  3727.         inst._keyEvent = false;
  3728.         return html;
  3729.     },
  3730.  
  3731.     /* Generate the month and year header. */
  3732.     _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
  3733.             secondary, monthNames, monthNamesShort) {
  3734.         var changeMonth = this._get(inst, 'changeMonth');
  3735.         var changeYear = this._get(inst, 'changeYear');
  3736.         var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
  3737.         var html = '<div class="ui-datepicker-title">';
  3738.         var monthHtml = '';
  3739.         // month selection
  3740.         if (secondary || !changeMonth)
  3741.             monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
  3742.         else {
  3743.             var inMinYear = (minDate && minDate.getFullYear() == drawYear);
  3744.             var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
  3745.             monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
  3746.             for (var month = 0; month < 12; month++) {
  3747.                 if ((!inMinYear || month >= minDate.getMonth()) &&
  3748.                         (!inMaxYear || month <= maxDate.getMonth()))
  3749.                     monthHtml += '<option value="' + month + '"' +
  3750.                         (month == drawMonth ? ' selected="selected"' : '') +
  3751.                         '>' + monthNamesShort[month] + '</option>';
  3752.             }
  3753.             monthHtml += '</select>';
  3754.         }
  3755.         if (!showMonthAfterYear)
  3756.             html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
  3757.         // year selection
  3758.         if ( !inst.yearshtml ) {
  3759.             inst.yearshtml = '';
  3760.             if (secondary || !changeYear)
  3761.                 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
  3762.             else {
  3763.                 // determine range of years to display
  3764.                 var years = this._get(inst, 'yearRange').split(':');
  3765.                 var thisYear = new Date().getFullYear();
  3766.                 var determineYear = function(value) {
  3767.                     var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
  3768.                         (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
  3769.                         parseInt(value, 10)));
  3770.                     return (isNaN(year) ? thisYear : year);
  3771.                 };
  3772.                 var year = determineYear(years[0]);
  3773.                 var endYear = Math.max(year, determineYear(years[1] || ''));
  3774.                 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
  3775.                 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
  3776.                 inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
  3777.                 for (; year <= endYear; year++) {
  3778.                     inst.yearshtml += '<option value="' + year + '"' +
  3779.                         (year == drawYear ? ' selected="selected"' : '') +
  3780.                         '>' + year + '</option>';
  3781.                 }
  3782.                 inst.yearshtml += '</select>';
  3783.  
  3784.                 html += inst.yearshtml;
  3785.                 inst.yearshtml = null;
  3786.             }
  3787.         }
  3788.         html += this._get(inst, 'yearSuffix');
  3789.         if (showMonthAfterYear)
  3790.             html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
  3791.         html += '</div>'; // Close datepicker_header
  3792.         return html;
  3793.     },
  3794.  
  3795.     /* Adjust one of the date sub-fields. */
  3796.     _adjustInstDate: function(inst, offset, period) {
  3797.         var year = inst.drawYear + (period == 'Y' ? offset : 0);
  3798.         var month = inst.drawMonth + (period == 'M' ? offset : 0);
  3799.         var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
  3800.             (period == 'D' ? offset : 0);
  3801.         var date = this._restrictMinMax(inst,
  3802.             this._daylightSavingAdjust(new Date(year, month, day)));
  3803.         inst.selectedDay = date.getDate();
  3804.         inst.drawMonth = inst.selectedMonth = date.getMonth();
  3805.         inst.drawYear = inst.selectedYear = date.getFullYear();
  3806.         if (period == 'M' || period == 'Y')
  3807.             this._notifyChange(inst);
  3808.     },
  3809.  
  3810.     /* Ensure a date is within any min/max bounds. */
  3811.     _restrictMinMax: function(inst, date) {
  3812.         var minDate = this._getMinMaxDate(inst, 'min');
  3813.         var maxDate = this._getMinMaxDate(inst, 'max');
  3814.         var newDate = (minDate && date < minDate ? minDate : date);
  3815.         newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
  3816.         return newDate;
  3817.     },
  3818.  
  3819.     /* Notify change of month/year. */
  3820.     _notifyChange: function(inst) {
  3821.         var onChange = this._get(inst, 'onChangeMonthYear');
  3822.         if (onChange)
  3823.             onChange.apply((inst.input ? inst.input[0] : null),
  3824.                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
  3825.     },
  3826.  
  3827.     /* Determine the number of months to show. */
  3828.     _getNumberOfMonths: function(inst) {
  3829.         var numMonths = this._get(inst, 'numberOfMonths');
  3830.         return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
  3831.     },
  3832.  
  3833.     /* Determine the current maximum date - ensure no time components are set. */
  3834.     _getMinMaxDate: function(inst, minMax) {
  3835.         return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
  3836.     },
  3837.  
  3838.     /* Find the number of days in a given month. */
  3839.     _getDaysInMonth: function(year, month) {
  3840.         return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
  3841.     },
  3842.  
  3843.     /* Find the day of the week of the first of a month. */
  3844.     _getFirstDayOfMonth: function(year, month) {
  3845.         return new Date(year, month, 1).getDay();
  3846.     },
  3847.  
  3848.     /* Determines if we should allow a "next/prev" month display change. */
  3849.     _canAdjustMonth: function(inst, offset, curYear, curMonth) {
  3850.         var numMonths = this._getNumberOfMonths(inst);
  3851.         var date = this._daylightSavingAdjust(new Date(curYear,
  3852.             curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
  3853.         if (offset < 0)
  3854.             date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
  3855.         return this._isInRange(inst, date);
  3856.     },
  3857.  
  3858.     /* Is the given date in the accepted range? */
  3859.     _isInRange: function(inst, date) {
  3860.         var minDate = this._getMinMaxDate(inst, 'min');
  3861.         var maxDate = this._getMinMaxDate(inst, 'max');
  3862.         return ((!minDate || date.getTime() >= minDate.getTime()) &&
  3863.             (!maxDate || date.getTime() <= maxDate.getTime()));
  3864.     },
  3865.  
  3866.     /* Provide the configuration settings for formatting/parsing. */
  3867.     _getFormatConfig: function(inst) {
  3868.         var shortYearCutoff = this._get(inst, 'shortYearCutoff');
  3869.         shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
  3870.             new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
  3871.         return {shortYearCutoff: shortYearCutoff,
  3872.             dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
  3873.             monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
  3874.     },
  3875.  
  3876.     /* Format the given date for display. */
  3877.     _formatDate: function(inst, day, month, year) {
  3878.         if (!day) {
  3879.             inst.currentDay = inst.selectedDay;
  3880.             inst.currentMonth = inst.selectedMonth;
  3881.             inst.currentYear = inst.selectedYear;
  3882.         }
  3883.         var date = (day ? (typeof day == 'object' ? day :
  3884.             this._daylightSavingAdjust(new Date(year, month, day))) :
  3885.             this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
  3886.         return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
  3887.     }
  3888. });
  3889.  
  3890. /*
  3891.  * Bind hover events for datepicker elements.
  3892.  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
  3893.  * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
  3894.  */
  3895. function bindHover(dpDiv) {
  3896.     var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
  3897.     return dpDiv.delegate(selector, 'mouseout', function() {
  3898.             $(this).removeClass('ui-state-hover');
  3899.             if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
  3900.             if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
  3901.         })
  3902.         .delegate(selector, 'mouseover', function(){
  3903.             if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
  3904.                 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
  3905.                 $(this).addClass('ui-state-hover');
  3906.                 if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
  3907.                 if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
  3908.             }
  3909.         });
  3910. }
  3911.  
  3912. /* jQuery extend now ignores nulls! */
  3913. function extendRemove(target, props) {
  3914.     $.extend(target, props);
  3915.     for (var name in props)
  3916.         if (props[name] == null || props[name] == undefined)
  3917.             target[name] = props[name];
  3918.     return target;
  3919. };
  3920.  
  3921. /* Invoke the datepicker functionality.
  3922.    @param  options  string - a command, optionally followed by additional parameters or
  3923.                     Object - settings for attaching new datepicker functionality
  3924.    @return  jQuery object */
  3925. $.fn.datepicker = function(options){
  3926.  
  3927.     /* Verify an empty collection wasn't passed - Fixes #6976 */
  3928.     if ( !this.length ) {
  3929.         return this;
  3930.     }
  3931.  
  3932.     /* Initialise the date picker. */
  3933.     if (!$.datepicker.initialized) {
  3934.         $(document).mousedown($.datepicker._checkExternalClick).
  3935.             find(document.body).append($.datepicker.dpDiv);
  3936.         $.datepicker.initialized = true;
  3937.     }
  3938.  
  3939.     var otherArgs = Array.prototype.slice.call(arguments, 1);
  3940.     if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
  3941.         return $.datepicker['_' + options + 'Datepicker'].
  3942.             apply($.datepicker, [this[0]].concat(otherArgs));
  3943.     if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
  3944.         return $.datepicker['_' + options + 'Datepicker'].
  3945.             apply($.datepicker, [this[0]].concat(otherArgs));
  3946.     return this.each(function() {
  3947.         typeof options == 'string' ?
  3948.             $.datepicker['_' + options + 'Datepicker'].
  3949.                 apply($.datepicker, [this].concat(otherArgs)) :
  3950.             $.datepicker._attachDatepicker(this, options);
  3951.     });
  3952. };
  3953.  
  3954. $.datepicker = new Datepicker(); // singleton instance
  3955. $.datepicker.initialized = false;
  3956. $.datepicker.uuid = new Date().getTime();
  3957. $.datepicker.version = "1.9.2";
  3958.  
  3959. // Workaround for #4055
  3960. // Add another global to avoid noConflict issues with inline event handlers
  3961. window['DP_jQuery_' + dpuuid] = $;
  3962.  
  3963. })(jQuery);
  3964.  
  3965. //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnl1aS9qcXVlcnkudWkuZGF0ZXBpY2tlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIGpRdWVyeSBVSSBEYXRlcGlja2VyIDEuOS4yXG4gKiBodHRwOi8vanF1ZXJ5dWkuY29tXG4gKlxuICogQ29weXJpZ2h0IDIwMTIgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL2RhdGVwaWNrZXIvXG4gKlxuICogRGVwZW5kczpcbiAqXHRqcXVlcnkudWkuY29yZS5qc1xuICovXG4oZnVuY3Rpb24oICQsIHVuZGVmaW5lZCApIHtcblxuJC5leHRlbmQoJC51aSwgeyBkYXRlcGlja2VyOiB7IHZlcnNpb246IFwiMS45LjJcIiB9IH0pO1xuXG52YXIgUFJPUF9OQU1FID0gJ2RhdGVwaWNrZXInO1xudmFyIGRwdXVpZCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xudmFyIGluc3RBY3RpdmU7XG5cbi8qIERhdGUgcGlja2VyIG1hbmFnZXIuXG4gICBVc2UgdGhlIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzLCAkLmRhdGVwaWNrZXIsIHRvIGludGVyYWN0IHdpdGggdGhlIGRhdGUgcGlja2VyLlxuICAgU2V0dGluZ3MgZm9yIChncm91cHMgb2YpIGRhdGUgcGlja2VycyBhcmUgbWFpbnRhaW5lZCBpbiBhbiBpbnN0YW5jZSBvYmplY3QsXG4gICBhbGxvd2luZyBtdWx0aXBsZSBkaWZmZXJlbnQgc2V0dGluZ3Mgb24gdGhlIHNhbWUgcGFnZS4gKi9cblxuZnVuY3Rpb24gRGF0ZXBpY2tlcigpIHtcblx0dGhpcy5kZWJ1ZyA9IGZhbHNlOyAvLyBDaGFuZ2UgdGhpcyB0byB0cnVlIHRvIHN0YXJ0IGRlYnVnZ2luZ1xuXHR0aGlzLl9jdXJJbnN0ID0gbnVsbDsgLy8gVGhlIGN1cnJlbnQgaW5zdGFuY2UgaW4gdXNlXG5cdHRoaXMuX2tleUV2ZW50ID0gZmFsc2U7IC8vIElmIHRoZSBsYXN0IGV2ZW50IHdhcyBhIGtleSBldmVudFxuXHR0aGlzLl9kaXNhYmxlZElucHV0cyA9IFtdOyAvLyBMaXN0IG9mIGRhdGUgcGlja2VyIGlucHV0cyB0aGF0IGhhdmUgYmVlbiBkaXNhYmxlZFxuXHR0aGlzLl9kYXRlcGlja2VyU2hvd2luZyA9IGZhbHNlOyAvLyBUcnVlIGlmIHRoZSBwb3B1cCBwaWNrZXIgaXMgc2hvd2luZyAsIGZhbHNlIGlmIG5vdFxuXHR0aGlzLl9pbkRpYWxvZyA9IGZhbHNlOyAvLyBUcnVlIGlmIHNob3dpbmcgd2l0aGluIGEgXCJkaWFsb2dcIiwgZmFsc2UgaWYgbm90XG5cdHRoaXMuX21haW5EaXZJZCA9ICd1aS1kYXRlcGlja2VyLWRpdic7IC8vIFRoZSBJRCBvZiB0aGUgbWFpbiBkYXRlcGlja2VyIGRpdmlzaW9uXG5cdHRoaXMuX2lubGluZUNsYXNzID0gJ3VpLWRhdGVwaWNrZXItaW5saW5lJzsgLy8gVGhlIG5hbWUgb2YgdGhlIGlubGluZSBtYXJrZXIgY2xhc3Ncblx0dGhpcy5fYXBwZW5kQ2xhc3MgPSAndWktZGF0ZXBpY2tlci1hcHBlbmQnOyAvLyBUaGUgbmFtZSBvZiB0aGUgYXBwZW5kIG1hcmtlciBjbGFzc1xuXHR0aGlzLl90cmlnZ2VyQ2xhc3MgPSAndWktZGF0ZXBpY2tlci10cmlnZ2VyJzsgLy8gVGhlIG5hbWUgb2YgdGhlIHRyaWdnZXIgbWFya2VyIGNsYXNzXG5cdHRoaXMuX2RpYWxvZ0NsYXNzID0gJ3VpLWRhdGVwaWNrZXItZGlhbG9nJzsgLy8gVGhlIG5hbWUgb2YgdGhlIGRpYWxvZyBtYXJrZXIgY2xhc3Ncblx0dGhpcy5fZGlzYWJsZUNsYXNzID0gJ3VpLWRhdGVwaWNrZXItZGlzYWJsZWQnOyAvLyBUaGUgbmFtZSBvZiB0aGUgZGlzYWJsZWQgY292ZXJpbmcgbWFya2VyIGNsYXNzXG5cdHRoaXMuX3Vuc2VsZWN0YWJsZUNsYXNzID0gJ3VpLWRhdGVwaWNrZXItdW5zZWxlY3RhYmxlJzsgLy8gVGhlIG5hbWUgb2YgdGhlIHVuc2VsZWN0YWJsZSBjZWxsIG1hcmtlciBjbGFzc1xuXHR0aGlzLl9jdXJyZW50Q2xhc3MgPSAndWktZGF0ZXBpY2tlci1jdXJyZW50LWRheSc7IC8vIFRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IGRheSBtYXJrZXIgY2xhc3Ncblx0dGhpcy5fZGF5T3ZlckNsYXNzID0gJ3VpLWRhdGVwaWNrZXItZGF5cy1jZWxsLW92ZXInOyAvLyBUaGUgbmFtZSBvZiB0aGUgZGF5IGhvdmVyIG1hcmtlciBjbGFzc1xuXHR0aGlzLnJlZ2lvbmFsID0gW107IC8vIEF2YWlsYWJsZSByZWdpb25hbCBzZXR0aW5ncywgaW5kZXhlZCBieSBsYW5ndWFnZSBjb2RlXG5cdHRoaXMucmVnaW9uYWxbJyddID0geyAvLyBEZWZhdWx0IHJlZ2lvbmFsIHNldHRpbmdzXG5cdFx0Y2xvc2VUZXh0OiAnRG9uZScsIC8vIERpc3BsYXkgdGV4dCBmb3IgY2xvc2UgbGlua1xuXHRcdHByZXZUZXh0OiAnUHJldicsIC8vIERpc3BsYXkgdGV4dCBmb3IgcHJldmlvdXMgbW9udGggbGlua1xuXHRcdG5leHRUZXh0OiAnTmV4dCcsIC8vIERpc3BsYXkgdGV4dCBmb3IgbmV4dCBtb250aCBsaW5rXG5cdFx0Y3VycmVudFRleHQ6ICdUb2RheScsIC8vIERpc3BsYXkgdGV4dCBmb3IgY3VycmVudCBtb250aCBsaW5rXG5cdFx0bW9udGhOYW1lczogWydKYW51YXJ5JywnRmVicnVhcnknLCdNYXJjaCcsJ0FwcmlsJywnTWF5JywnSnVuZScsXG5cdFx0XHQnSnVseScsJ0F1Z3VzdCcsJ1NlcHRlbWJlcicsJ09jdG9iZXInLCdOb3ZlbWJlcicsJ0RlY2VtYmVyJ10sIC8vIE5hbWVzIG9mIG1vbnRocyBmb3IgZHJvcC1kb3duIGFuZCBmb3JtYXR0aW5nXG5cdFx0bW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sIC8vIEZvciBmb3JtYXR0aW5nXG5cdFx0ZGF5TmFtZXM6IFsnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknXSwgLy8gRm9yIGZvcm1hdHRpbmdcblx0XHRkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLCAvLyBGb3IgZm9ybWF0dGluZ1xuXHRcdGRheU5hbWVzTWluOiBbJ1N1JywnTW8nLCdUdScsJ1dlJywnVGgnLCdGcicsJ1NhJ10sIC8vIENvbHVtbiBoZWFkaW5ncyBmb3IgZGF5cyBzdGFydGluZyBhdCBTdW5kYXlcblx0XHR3ZWVrSGVhZGVyOiAnV2snLCAvLyBDb2x1bW4gaGVhZGVyIGZvciB3ZWVrIG9mIHRoZSB5ZWFyXG5cdFx0ZGF0ZUZvcm1hdDogJ21tL2RkL3l5JywgLy8gU2VlIGZvcm1hdCBvcHRpb25zIG9uIHBhcnNlRGF0ZVxuXHRcdGZpcnN0RGF5OiAwLCAvLyBUaGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBTdW4gPSAwLCBNb24gPSAxLCAuLi5cblx0XHRpc1JUTDogZmFsc2UsIC8vIFRydWUgaWYgcmlnaHQtdG8tbGVmdCBsYW5ndWFnZSwgZmFsc2UgaWYgbGVmdC10by1yaWdodFxuXHRcdHNob3dNb250aEFmdGVyWWVhcjogZmFsc2UsIC8vIFRydWUgaWYgdGhlIHllYXIgc2VsZWN0IHByZWNlZGVzIG1vbnRoLCBmYWxzZSBmb3IgbW9udGggdGhlbiB5ZWFyXG5cdFx0eWVhclN1ZmZpeDogJycgLy8gQWRkaXRpb25hbCB0ZXh0IHRvIGFwcGVuZCB0byB0aGUgeWVhciBpbiB0aGUgbW9udGggaGVhZGVyc1xuXHR9O1xuXHR0aGlzLl9kZWZhdWx0cyA9IHsgLy8gR2xvYmFsIGRlZmF1bHRzIGZvciBhbGwgdGhlIGRhdGUgcGlja2VyIGluc3RhbmNlc1xuXHRcdHNob3dPbjogJ2ZvY3VzJywgLy8gJ2ZvY3VzJyBmb3IgcG9wdXAgb24gZm9jdXMsXG5cdFx0XHQvLyAnYnV0dG9uJyBmb3IgdHJpZ2dlciBidXR0b24sIG9yICdib3RoJyBmb3IgZWl0aGVyXG5cdFx0c2hvd0FuaW06ICdmYWRlSW4nLCAvLyBOYW1lIG9mIGpRdWVyeSBhbmltYXRpb24gZm9yIHBvcHVwXG5cdFx0c2hvd09wdGlvbnM6IHt9LCAvLyBPcHRpb25zIGZvciBlbmhhbmNlZCBhbmltYXRpb25zXG5cdFx0ZGVmYXVsdERhdGU6IG51bGwsIC8vIFVzZWQgd2hlbiBmaWVsZCBpcyBibGFuazogYWN0dWFsIGRhdGUsXG5cdFx0XHQvLyArLy1udW1iZXIgZm9yIG9mZnNldCBmcm9tIHRvZGF5LCBudWxsIGZvciB0b2RheVxuXHRcdGFwcGVuZFRleHQ6ICcnLCAvLyBEaXNwbGF5IHRleHQgZm9sbG93aW5nIHRoZSBpbnB1dCBib3gsIGUuZy4gc2hvd2luZyB0aGUgZm9ybWF0XG5cdFx0YnV0dG9uVGV4dDogJy4uLicsIC8vIFRleHQgZm9yIHRyaWdnZXIgYnV0dG9uXG5cdFx0YnV0dG9uSW1hZ2U6ICcnLCAvLyBVUkwgZm9yIHRyaWdnZXIgYnV0dG9uIGltYWdlXG5cdFx0YnV0dG9uSW1hZ2VPbmx5OiBmYWxzZSwgLy8gVHJ1ZSBpZiB0aGUgaW1hZ2UgYXBwZWFycyBhbG9uZSwgZmFsc2UgaWYgaXQgYXBwZWFycyBvbiBhIGJ1dHRvblxuXHRcdGhpZGVJZk5vUHJldk5leHQ6IGZhbHNlLCAvLyBUcnVlIHRvIGhpZGUgbmV4dC9wcmV2aW91cyBtb250aCBsaW5rc1xuXHRcdFx0Ly8gaWYgbm90IGFwcGxpY2FibGUsIGZhbHNlIHRvIGp1c3QgZGlzYWJsZSB0aGVtXG5cdFx0bmF2aWdhdGlvbkFzRGF0ZUZvcm1hdDogZmFsc2UsIC8vIFRydWUgaWYgZGF0ZSBmb3JtYXR0aW5nIGFwcGxpZWQgdG8gcHJldi90b2RheS9uZXh0IGxpbmtzXG5cdFx0Z290b0N1cnJlbnQ6IGZhbHNlLCAvLyBUcnVlIGlmIHRvZGF5IGxpbmsgZ29lcyBiYWNrIHRvIGN1cnJlbnQgc2VsZWN0aW9uIGluc3RlYWRcblx0XHRjaGFuZ2VNb250aDogZmFsc2UsIC8vIFRydWUgaWYgbW9udGggY2FuIGJlIHNlbGVjdGVkIGRpcmVjdGx5LCBmYWxzZSBpZiBvbmx5IHByZXYvbmV4dFxuXHRcdGNoYW5nZVllYXI6IGZhbHNlLCAvLyBUcnVlIGlmIHllYXIgY2FuIGJlIHNlbGVjdGVkIGRpcmVjdGx5LCBmYWxzZSBpZiBvbmx5IHByZXYvbmV4dFxuXHRcdHllYXJSYW5nZTogJ2MtMTA6YysxMCcsIC8vIFJhbmdlIG9mIHllYXJzIHRvIGRpc3BsYXkgaW4gZHJvcC1kb3duLFxuXHRcdFx0Ly8gZWl0aGVyIHJlbGF0aXZlIHRvIHRvZGF5J3MgeWVhciAoLW5uOitubiksIHJlbGF0aXZlIHRvIGN1cnJlbnRseSBkaXNwbGF5ZWQgeWVhclxuXHRcdFx0Ly8gKGMtbm46YytubiksIGFic29sdXRlIChubm5uOm5ubm4pLCBvciBhIGNvbWJpbmF0aW9uIG9mIHRoZSBhYm92ZSAobm5ubjotbilcblx0XHRzaG93T3RoZXJNb250aHM6IGZhbHNlLCAvLyBUcnVlIHRvIHNob3cgZGF0ZXMgaW4gb3RoZXIgbW9udGhzLCBmYWxzZSB0byBsZWF2ZSBibGFua1xuXHRcdHNlbGVjdE90aGVyTW9udGhzOiBmYWxzZSwgLy8gVHJ1ZSB0byBhbGxvdyBzZWxlY3Rpb24gb2YgZGF0ZXMgaW4gb3RoZXIgbW9udGhzLCBmYWxzZSBmb3IgdW5zZWxlY3RhYmxlXG5cdFx0c2hvd1dlZWs6IGZhbHNlLCAvLyBUcnVlIHRvIHNob3cgd2VlayBvZiB0aGUgeWVhciwgZmFsc2UgdG8gbm90IHNob3cgaXRcblx0XHRjYWxjdWxhdGVXZWVrOiB0aGlzLmlzbzg2MDFXZWVrLCAvLyBIb3cgdG8gY2FsY3VsYXRlIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyLFxuXHRcdFx0Ly8gdGFrZXMgYSBEYXRlIGFuZCByZXR1cm5zIHRoZSBudW1iZXIgb2YgdGhlIHdlZWsgZm9yIGl0XG5cdFx0c2hvcnRZZWFyQ3V0b2ZmOiAnKzEwJywgLy8gU2hvcnQgeWVhciB2YWx1ZXMgPCB0aGlzIGFyZSBpbiB0aGUgY3VycmVudCBjZW50dXJ5LFxuXHRcdFx0Ly8gPiB0aGlzIGFyZSBpbiB0aGUgcHJldmlvdXMgY2VudHVyeSxcblx0XHRcdC8vIHN0cmluZyB2YWx1ZSBzdGFydGluZyB3aXRoICcrJyBmb3IgY3VycmVudCB5ZWFyICsgdmFsdWVcblx0XHRtaW5EYXRlOiBudWxsLCAvLyBUaGUgZWFybGllc3Qgc2VsZWN0YWJsZSBkYXRlLCBvciBudWxsIGZvciBubyBsaW1pdFxuXHRcdG1heERhdGU6IG51bGwsIC8vIFRoZSBsYXRlc3Qgc2VsZWN0YWJsZSBkYXRlLCBvciBudWxsIGZvciBubyBsaW1pdFxuXHRcdGR1cmF0aW9uOiAnZmFzdCcsIC8vIER1cmF0aW9uIG9mIGRpc3BsYXkvY2xvc3VyZVxuXHRcdGJlZm9yZVNob3dEYXk6IG51bGwsIC8vIEZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBkYXRlIGFuZCByZXR1cm5zIGFuIGFycmF5IHdpdGhcblx0XHRcdC8vIFswXSA9IHRydWUgaWYgc2VsZWN0YWJsZSwgZmFsc2UgaWYgbm90LCBbMV0gPSBjdXN0b20gQ1NTIGNsYXNzIG5hbWUocykgb3IgJycsXG5cdFx0XHQvLyBbMl0gPSBjZWxsIHRpdGxlIChvcHRpb25hbCksIGUuZy4gJC5kYXRlcGlja2VyLm5vV2Vla2VuZHNcblx0XHRiZWZvcmVTaG93OiBudWxsLCAvLyBGdW5jdGlvbiB0aGF0IHRha2VzIGFuIGlucHV0IGZpZWxkIGFuZFxuXHRcdFx0Ly8gcmV0dXJucyBhIHNldCBvZiBjdXN0b20gc2V0dGluZ3MgZm9yIHRoZSBkYXRlIHBpY2tlclxuXHRcdG9uU2VsZWN0OiBudWxsLCAvLyBEZWZpbmUgYSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIGEgZGF0ZSBpcyBzZWxlY3RlZFxuXHRcdG9uQ2hhbmdlTW9udGhZZWFyOiBudWxsLCAvLyBEZWZpbmUgYSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIHRoZSBtb250aCBvciB5ZWFyIGlzIGNoYW5nZWRcblx0XHRvbkNsb3NlOiBudWxsLCAvLyBEZWZpbmUgYSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIHRoZSBkYXRlcGlja2VyIGlzIGNsb3NlZFxuXHRcdG51bWJlck9mTW9udGhzOiAxLCAvLyBOdW1iZXIgb2YgbW9udGhzIHRvIHNob3cgYXQgYSB0aW1lXG5cdFx0c2hvd0N1cnJlbnRBdFBvczogMCwgLy8gVGhlIHBvc2l0aW9uIGluIG11bHRpcGUgbW9udGhzIGF0IHdoaWNoIHRvIHNob3cgdGhlIGN1cnJlbnQgbW9udGggKHN0YXJ0aW5nIGF0IDApXG5cdFx0c3RlcE1vbnRoczogMSwgLy8gTnVtYmVyIG9mIG1vbnRocyB0byBzdGVwIGJhY2svZm9yd2FyZFxuXHRcdHN0ZXBCaWdNb250aHM6IDEyLCAvLyBOdW1iZXIgb2YgbW9udGhzIHRvIHN0ZXAgYmFjay9mb3J3YXJkIGZvciB0aGUgYmlnIGxpbmtzXG5cdFx0YWx0RmllbGQ6ICcnLCAvLyBTZWxlY3RvciBmb3IgYW4gYWx0ZXJuYXRlIGZpZWxkIHRvIHN0b3JlIHNlbGVjdGVkIGRhdGVzIGludG9cblx0XHRhbHRGb3JtYXQ6ICcnLCAvLyBUaGUgZGF0ZSBmb3JtYXQgdG8gdXNlIGZvciB0aGUgYWx0ZXJuYXRlIGZpZWxkXG5cdFx0Y29uc3RyYWluSW5wdXQ6IHRydWUsIC8vIFRoZSBpbnB1dCBpcyBjb25zdHJhaW5lZCBieSB0aGUgY3VycmVudCBkYXRlIGZvcm1hdFxuXHRcdHNob3dCdXR0b25QYW5lbDogZmFsc2UsIC8vIFRydWUgdG8gc2hvdyBidXR0b24gcGFuZWwsIGZhbHNlIHRvIG5vdCBzaG93IGl0XG5cdFx0YXV0b1NpemU6IGZhbHNlLCAvLyBUcnVlIHRvIHNpemUgdGhlIGlucHV0IGZvciB0aGUgZGF0ZSBmb3JtYXQsIGZhbHNlIHRvIGxlYXZlIGFzIGlzXG5cdFx0ZGlzYWJsZWQ6IGZhbHNlIC8vIFRoZSBpbml0aWFsIGRpc2FibGVkIHN0YXRlXG5cdH07XG5cdCQuZXh0ZW5kKHRoaXMuX2RlZmF1bHRzLCB0aGlzLnJlZ2lvbmFsWycnXSk7XG5cdHRoaXMuZHBEaXYgPSBiaW5kSG92ZXIoJCgnPGRpdiBpZD1cIicgKyB0aGlzLl9tYWluRGl2SWQgKyAnXCIgY2xhc3M9XCJ1aS1kYXRlcGlja2VyIHVpLXdpZGdldCB1aS13aWRnZXQtY29udGVudCB1aS1oZWxwZXItY2xlYXJmaXggdWktY29ybmVyLWFsbFwiPjwvZGl2PicpKTtcbn1cblxuJC5leHRlbmQoRGF0ZXBpY2tlci5wcm90b3R5cGUsIHtcblx0LyogQ2xhc3MgbmFtZSBhZGRlZCB0byBlbGVtZW50cyB0byBpbmRpY2F0ZSBhbHJlYWR5IGNvbmZpZ3VyZWQgd2l0aCBhIGRhdGUgcGlja2VyLiAqL1xuXHRtYXJrZXJDbGFzc05hbWU6ICdoYXNEYXRlcGlja2VyJyxcblxuXHQvL0tlZXAgdHJhY2sgb2YgdGhlIG1heGltdW0gbnVtYmVyIG9mIHJvd3MgZGlzcGxheWVkIChzZWUgIzcwNDMpXG5cdG1heFJvd3M6IDQsXG5cblx0LyogRGVidWcgbG9nZ2luZyAoaWYgZW5hYmxlZCkuICovXG5cdGxvZzogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLmRlYnVnKVxuXHRcdFx0Y29uc29sZS5sb2cuYXBwbHkoJycsIGFyZ3VtZW50cyk7XG5cdH0sXG5cblx0Ly8gVE9ETyByZW5hbWUgdG8gXCJ3aWRnZXRcIiB3aGVuIHN3aXRjaGluZyB0byB3aWRnZXQgZmFjdG9yeVxuXHRfd2lkZ2V0RGF0ZXBpY2tlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZHBEaXY7XG5cdH0sXG5cblx0LyogT3ZlcnJpZGUgdGhlIGRlZmF1bHQgc2V0dGluZ3MgZm9yIGFsbCBpbnN0YW5jZXMgb2YgdGhlIGRhdGUgcGlja2VyLlxuXHQgICBAcGFyYW0gIHNldHRpbmdzICBvYmplY3QgLSB0aGUgbmV3IHNldHRpbmdzIHRvIHVzZSBhcyBkZWZhdWx0cyAoYW5vbnltb3VzIG9iamVjdClcblx0ICAgQHJldHVybiB0aGUgbWFuYWdlciBvYmplY3QgKi9cblx0c2V0RGVmYXVsdHM6IGZ1bmN0aW9uKHNldHRpbmdzKSB7XG5cdFx0ZXh0ZW5kUmVtb3ZlKHRoaXMuX2RlZmF1bHRzLCBzZXR0aW5ncyB8fCB7fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0LyogQXR0YWNoIHRoZSBkYXRlIHBpY2tlciB0byBhIGpRdWVyeSBzZWxlY3Rpb24uXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICAgIGVsZW1lbnQgLSB0aGUgdGFyZ2V0IGlucHV0IGZpZWxkIG9yIGRpdmlzaW9uIG9yIHNwYW5cblx0ICAgQHBhcmFtICBzZXR0aW5ncyAgb2JqZWN0IC0gdGhlIG5ldyBzZXR0aW5ncyB0byB1c2UgZm9yIHRoaXMgZGF0ZSBwaWNrZXIgaW5zdGFuY2UgKGFub255bW91cykgKi9cblx0X2F0dGFjaERhdGVwaWNrZXI6IGZ1bmN0aW9uKHRhcmdldCwgc2V0dGluZ3MpIHtcblx0XHQvLyBjaGVjayBmb3Igc2V0dGluZ3Mgb24gdGhlIGNvbnRyb2wgaXRzZWxmIC0gaW4gbmFtZXNwYWNlICdkYXRlOidcblx0XHR2YXIgaW5saW5lU2V0dGluZ3MgPSBudWxsO1xuXHRcdGZvciAodmFyIGF0dHJOYW1lIGluIHRoaXMuX2RlZmF1bHRzKSB7XG5cdFx0XHR2YXIgYXR0clZhbHVlID0gdGFyZ2V0LmdldEF0dHJpYnV0ZSgnZGF0ZTonICsgYXR0ck5hbWUpO1xuXHRcdFx0aWYgKGF0dHJWYWx1ZSkge1xuXHRcdFx0XHRpbmxpbmVTZXR0aW5ncyA9IGlubGluZVNldHRpbmdzIHx8IHt9O1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGlubGluZVNldHRpbmdzW2F0dHJOYW1lXSA9IGV2YWwoYXR0clZhbHVlKTtcblx0XHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdFx0aW5saW5lU2V0dGluZ3NbYXR0ck5hbWVdID0gYXR0clZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHZhciBub2RlTmFtZSA9IHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHZhciBpbmxpbmUgPSAobm9kZU5hbWUgPT0gJ2RpdicgfHwgbm9kZU5hbWUgPT0gJ3NwYW4nKTtcblx0XHRpZiAoIXRhcmdldC5pZCkge1xuXHRcdFx0dGhpcy51dWlkICs9IDE7XG5cdFx0XHR0YXJnZXQuaWQgPSAnZHAnICsgdGhpcy51dWlkO1xuXHRcdH1cblx0XHR2YXIgaW5zdCA9IHRoaXMuX25ld0luc3QoJCh0YXJnZXQpLCBpbmxpbmUpO1xuXHRcdGluc3Quc2V0dGluZ3MgPSAkLmV4dGVuZCh7fSwgc2V0dGluZ3MgfHwge30sIGlubGluZVNldHRpbmdzIHx8IHt9KTtcblx0XHRpZiAobm9kZU5hbWUgPT0gJ2lucHV0Jykge1xuXHRcdFx0dGhpcy5fY29ubmVjdERhdGVwaWNrZXIodGFyZ2V0LCBpbnN0KTtcblx0XHR9IGVsc2UgaWYgKGlubGluZSkge1xuXHRcdFx0dGhpcy5faW5saW5lRGF0ZXBpY2tlcih0YXJnZXQsIGluc3QpO1xuXHRcdH1cblx0fSxcblxuXHQvKiBDcmVhdGUgYSBuZXcgaW5zdGFuY2Ugb2JqZWN0LiAqL1xuXHRfbmV3SW5zdDogZnVuY3Rpb24odGFyZ2V0LCBpbmxpbmUpIHtcblx0XHR2YXIgaWQgPSB0YXJnZXRbMF0uaWQucmVwbGFjZSgvKFteQS1aYS16MC05Xy1dKS9nLCAnXFxcXFxcXFwkMScpOyAvLyBlc2NhcGUgalF1ZXJ5IG1ldGEgY2hhcnNcblx0XHRyZXR1cm4ge2lkOiBpZCwgaW5wdXQ6IHRhcmdldCwgLy8gYXNzb2NpYXRlZCB0YXJnZXRcblx0XHRcdHNlbGVjdGVkRGF5OiAwLCBzZWxlY3RlZE1vbnRoOiAwLCBzZWxlY3RlZFllYXI6IDAsIC8vIGN1cnJlbnQgc2VsZWN0aW9uXG5cdFx0XHRkcmF3TW9udGg6IDAsIGRyYXdZZWFyOiAwLCAvLyBtb250aCBiZWluZyBkcmF3blxuXHRcdFx0aW5saW5lOiBpbmxpbmUsIC8vIGlzIGRhdGVwaWNrZXIgaW5saW5lIG9yIG5vdFxuXHRcdFx0ZHBEaXY6ICghaW5saW5lID8gdGhpcy5kcERpdiA6IC8vIHByZXNlbnRhdGlvbiBkaXZcblx0XHRcdGJpbmRIb3ZlcigkKCc8ZGl2IGNsYXNzPVwiJyArIHRoaXMuX2lubGluZUNsYXNzICsgJyB1aS1kYXRlcGlja2VyIHVpLXdpZGdldCB1aS13aWRnZXQtY29udGVudCB1aS1oZWxwZXItY2xlYXJmaXggdWktY29ybmVyLWFsbFwiPjwvZGl2PicpKSl9O1xuXHR9LFxuXG5cdC8qIEF0dGFjaCB0aGUgZGF0ZSBwaWNrZXIgdG8gYW4gaW5wdXQgZmllbGQuICovXG5cdF9jb25uZWN0RGF0ZXBpY2tlcjogZnVuY3Rpb24odGFyZ2V0LCBpbnN0KSB7XG5cdFx0dmFyIGlucHV0ID0gJCh0YXJnZXQpO1xuXHRcdGluc3QuYXBwZW5kID0gJChbXSk7XG5cdFx0aW5zdC50cmlnZ2VyID0gJChbXSk7XG5cdFx0aWYgKGlucHV0Lmhhc0NsYXNzKHRoaXMubWFya2VyQ2xhc3NOYW1lKSlcblx0XHRcdHJldHVybjtcblx0XHR0aGlzLl9hdHRhY2htZW50cyhpbnB1dCwgaW5zdCk7XG5cdFx0aW5wdXQuYWRkQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpLmtleWRvd24odGhpcy5fZG9LZXlEb3duKS5cblx0XHRcdGtleXByZXNzKHRoaXMuX2RvS2V5UHJlc3MpLmtleXVwKHRoaXMuX2RvS2V5VXApLlxuXHRcdFx0YmluZChcInNldERhdGEuZGF0ZXBpY2tlclwiLCBmdW5jdGlvbihldmVudCwga2V5LCB2YWx1ZSkge1xuXHRcdFx0XHRpbnN0LnNldHRpbmdzW2tleV0gPSB2YWx1ZTtcblx0XHRcdH0pLmJpbmQoXCJnZXREYXRhLmRhdGVwaWNrZXJcIiwgZnVuY3Rpb24oZXZlbnQsIGtleSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fZ2V0KGluc3QsIGtleSk7XG5cdFx0XHR9KTtcblx0XHR0aGlzLl9hdXRvU2l6ZShpbnN0KTtcblx0XHQkLmRhdGEodGFyZ2V0LCBQUk9QX05BTUUsIGluc3QpO1xuXHRcdC8vSWYgZGlzYWJsZWQgb3B0aW9uIGlzIHRydWUsIGRpc2FibGUgdGhlIGRhdGVwaWNrZXIgb25jZSBpdCBoYXMgYmVlbiBhdHRhY2hlZCB0byB0aGUgaW5wdXQgKHNlZSB0aWNrZXQgIzU2NjUpXG5cdFx0aWYoIGluc3Quc2V0dGluZ3MuZGlzYWJsZWQgKSB7XG5cdFx0XHR0aGlzLl9kaXNhYmxlRGF0ZXBpY2tlciggdGFyZ2V0ICk7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIE1ha2UgYXR0YWNobWVudHMgYmFzZWQgb24gc2V0dGluZ3MuICovXG5cdF9hdHRhY2htZW50czogZnVuY3Rpb24oaW5wdXQsIGluc3QpIHtcblx0XHR2YXIgYXBwZW5kVGV4dCA9IHRoaXMuX2dldChpbnN0LCAnYXBwZW5kVGV4dCcpO1xuXHRcdHZhciBpc1JUTCA9IHRoaXMuX2dldChpbnN0LCAnaXNSVEwnKTtcblx0XHRpZiAoaW5zdC5hcHBlbmQpXG5cdFx0XHRpbnN0LmFwcGVuZC5yZW1vdmUoKTtcblx0XHRpZiAoYXBwZW5kVGV4dCkge1xuXHRcdFx0aW5zdC5hcHBlbmQgPSAkKCc8c3BhbiBjbGFzcz1cIicgKyB0aGlzLl9hcHBlbmRDbGFzcyArICdcIj4nICsgYXBwZW5kVGV4dCArICc8L3NwYW4+Jyk7XG5cdFx0XHRpbnB1dFtpc1JUTCA/ICdiZWZvcmUnIDogJ2FmdGVyJ10oaW5zdC5hcHBlbmQpO1xuXHRcdH1cblx0XHRpbnB1dC51bmJpbmQoJ2ZvY3VzJywgdGhpcy5fc2hvd0RhdGVwaWNrZXIpO1xuXHRcdGlmIChpbnN0LnRyaWdnZXIpXG5cdFx0XHRpbnN0LnRyaWdnZXIucmVtb3ZlKCk7XG5cdFx0dmFyIHNob3dPbiA9IHRoaXMuX2dldChpbnN0LCAnc2hvd09uJyk7XG5cdFx0aWYgKHNob3dPbiA9PSAnZm9jdXMnIHx8IHNob3dPbiA9PSAnYm90aCcpIC8vIHBvcC11cCBkYXRlIHBpY2tlciB3aGVuIGluIHRoZSBtYXJrZWQgZmllbGRcblx0XHRcdGlucHV0LmZvY3VzKHRoaXMuX3Nob3dEYXRlcGlja2VyKTtcblx0XHRpZiAoc2hvd09uID09ICdidXR0b24nIHx8IHNob3dPbiA9PSAnYm90aCcpIHsgLy8gcG9wLXVwIGRhdGUgcGlja2VyIHdoZW4gYnV0dG9uIGNsaWNrZWRcblx0XHRcdHZhciBidXR0b25UZXh0ID0gdGhpcy5fZ2V0KGluc3QsICdidXR0b25UZXh0Jyk7XG5cdFx0XHR2YXIgYnV0dG9uSW1hZ2UgPSB0aGlzLl9nZXQoaW5zdCwgJ2J1dHRvbkltYWdlJyk7XG5cdFx0XHRpbnN0LnRyaWdnZXIgPSAkKHRoaXMuX2dldChpbnN0LCAnYnV0dG9uSW1hZ2VPbmx5JykgP1xuXHRcdFx0XHQkKCc8aW1nLz4nKS5hZGRDbGFzcyh0aGlzLl90cmlnZ2VyQ2xhc3MpLlxuXHRcdFx0XHRcdGF0dHIoeyBzcmM6IGJ1dHRvbkltYWdlLCBhbHQ6IGJ1dHRvblRleHQsIHRpdGxlOiBidXR0b25UZXh0IH0pIDpcblx0XHRcdFx0JCgnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCI+PC9idXR0b24+JykuYWRkQ2xhc3ModGhpcy5fdHJpZ2dlckNsYXNzKS5cblx0XHRcdFx0XHRodG1sKGJ1dHRvbkltYWdlID09ICcnID8gYnV0dG9uVGV4dCA6ICQoJzxpbWcvPicpLmF0dHIoXG5cdFx0XHRcdFx0eyBzcmM6YnV0dG9uSW1hZ2UsIGFsdDpidXR0b25UZXh0LCB0aXRsZTpidXR0b25UZXh0IH0pKSk7XG5cdFx0XHRpbnB1dFtpc1JUTCA/ICdiZWZvcmUnIDogJ2FmdGVyJ10oaW5zdC50cmlnZ2VyKTtcblx0XHRcdGluc3QudHJpZ2dlci5jbGljayhmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCQuZGF0ZXBpY2tlci5fZGF0ZXBpY2tlclNob3dpbmcgJiYgJC5kYXRlcGlja2VyLl9sYXN0SW5wdXQgPT0gaW5wdXRbMF0pXG5cdFx0XHRcdFx0JC5kYXRlcGlja2VyLl9oaWRlRGF0ZXBpY2tlcigpO1xuXHRcdFx0XHRlbHNlIGlmICgkLmRhdGVwaWNrZXIuX2RhdGVwaWNrZXJTaG93aW5nICYmICQuZGF0ZXBpY2tlci5fbGFzdElucHV0ICE9IGlucHV0WzBdKSB7XG5cdFx0XHRcdFx0JC5kYXRlcGlja2VyLl9oaWRlRGF0ZXBpY2tlcigpO1xuXHRcdFx0XHRcdCQuZGF0ZXBpY2tlci5fc2hvd0RhdGVwaWNrZXIoaW5wdXRbMF0pO1xuXHRcdFx0XHR9IGVsc2Vcblx0XHRcdFx0XHQkLmRhdGVwaWNrZXIuX3Nob3dEYXRlcGlja2VyKGlucHV0WzBdKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIEFwcGx5IHRoZSBtYXhpbXVtIGxlbmd0aCBmb3IgdGhlIGRhdGUgZm9ybWF0LiAqL1xuXHRfYXV0b1NpemU6IGZ1bmN0aW9uKGluc3QpIHtcblx0XHRpZiAodGhpcy5fZ2V0KGluc3QsICdhdXRvU2l6ZScpICYmICFpbnN0LmlubGluZSkge1xuXHRcdFx0dmFyIGRhdGUgPSBuZXcgRGF0ZSgyMDA5LCAxMiAtIDEsIDIwKTsgLy8gRW5zdXJlIGRvdWJsZSBkaWdpdHNcblx0XHRcdHZhciBkYXRlRm9ybWF0ID0gdGhpcy5fZ2V0KGluc3QsICdkYXRlRm9ybWF0Jyk7XG5cdFx0XHRpZiAoZGF0ZUZvcm1hdC5tYXRjaCgvW0RNXS8pKSB7XG5cdFx0XHRcdHZhciBmaW5kTWF4ID0gZnVuY3Rpb24obmFtZXMpIHtcblx0XHRcdFx0XHR2YXIgbWF4ID0gMDtcblx0XHRcdFx0XHR2YXIgbWF4SSA9IDA7XG5cdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdFx0aWYgKG5hbWVzW2ldLmxlbmd0aCA+IG1heCkge1xuXHRcdFx0XHRcdFx0XHRtYXggPSBuYW1lc1tpXS5sZW5ndGg7XG5cdFx0XHRcdFx0XHRcdG1heEkgPSBpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF4STtcblx0XHRcdFx0fTtcblx0XHRcdFx0ZGF0ZS5zZXRNb250aChmaW5kTWF4KHRoaXMuX2dldChpbnN0LCAoZGF0ZUZvcm1hdC5tYXRjaCgvTU0vKSA/XG5cdFx0XHRcdFx0J21vbnRoTmFtZXMnIDogJ21vbnRoTmFtZXNTaG9ydCcpKSkpO1xuXHRcdFx0XHRkYXRlLnNldERhdGUoZmluZE1heCh0aGlzLl9nZXQoaW5zdCwgKGRhdGVGb3JtYXQubWF0Y2goL0RELykgP1xuXHRcdFx0XHRcdCdkYXlOYW1lcycgOiAnZGF5TmFtZXNTaG9ydCcpKSkgKyAyMCAtIGRhdGUuZ2V0RGF5KCkpO1xuXHRcdFx0fVxuXHRcdFx0aW5zdC5pbnB1dC5hdHRyKCdzaXplJywgdGhpcy5fZm9ybWF0RGF0ZShpbnN0LCBkYXRlKS5sZW5ndGgpO1xuXHRcdH1cblx0fSxcblxuXHQvKiBBdHRhY2ggYW4gaW5saW5lIGRhdGUgcGlja2VyIHRvIGEgZGl2LiAqL1xuXHRfaW5saW5lRGF0ZXBpY2tlcjogZnVuY3Rpb24odGFyZ2V0LCBpbnN0KSB7XG5cdFx0dmFyIGRpdlNwYW4gPSAkKHRhcmdldCk7XG5cdFx0aWYgKGRpdlNwYW4uaGFzQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpKVxuXHRcdFx0cmV0dXJuO1xuXHRcdGRpdlNwYW4uYWRkQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpLmFwcGVuZChpbnN0LmRwRGl2KS5cblx0XHRcdGJpbmQoXCJzZXREYXRhLmRhdGVwaWNrZXJcIiwgZnVuY3Rpb24oZXZlbnQsIGtleSwgdmFsdWUpe1xuXHRcdFx0XHRpbnN0LnNldHRpbmdzW2tleV0gPSB2YWx1ZTtcblx0XHRcdH0pLmJpbmQoXCJnZXREYXRhLmRhdGVwaWNrZXJcIiwgZnVuY3Rpb24oZXZlbnQsIGtleSl7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9nZXQoaW5zdCwga2V5KTtcblx0XHRcdH0pO1xuXHRcdCQuZGF0YSh0YXJnZXQsIFBST1BfTkFNRSwgaW5zdCk7XG5cdFx0dGhpcy5fc2V0RGF0ZShpbnN0LCB0aGlzLl9nZXREZWZhdWx0RGF0ZShpbnN0KSwgdHJ1ZSk7XG5cdFx0dGhpcy5fdXBkYXRlRGF0ZXBpY2tlcihpbnN0KTtcblx0XHR0aGlzLl91cGRhdGVBbHRlcm5hdGUoaW5zdCk7XG5cdFx0Ly9JZiBkaXNhYmxlZCBvcHRpb24gaXMgdHJ1ZSwgZGlzYWJsZSB0aGUgZGF0ZXBpY2tlciBiZWZvcmUgc2hvd2luZyBpdCAoc2VlIHRpY2tldCAjNTY2NSlcblx0XHRpZiggaW5zdC5zZXR0aW5ncy5kaXNhYmxlZCApIHtcblx0XHRcdHRoaXMuX2Rpc2FibGVEYXRlcGlja2VyKCB0YXJnZXQgKTtcblx0XHR9XG5cdFx0Ly8gU2V0IGRpc3BsYXk6YmxvY2sgaW4gcGxhY2Ugb2YgaW5zdC5kcERpdi5zaG93KCkgd2hpY2ggd29uJ3Qgd29yayBvbiBkaXNjb25uZWN0ZWQgZWxlbWVudHNcblx0XHQvLyBodHRwOi8vYnVncy5qcXVlcnl1aS5jb20vdGlja2V0Lzc1NTIgLSBBIERhdGVwaWNrZXIgY3JlYXRlZCBvbiBhIGRldGFjaGVkIGRpdiBoYXMgemVybyBoZWlnaHRcblx0XHRpbnN0LmRwRGl2LmNzcyggXCJkaXNwbGF5XCIsIFwiYmxvY2tcIiApO1xuXHR9LFxuXG5cdC8qIFBvcC11cCB0aGUgZGF0ZSBwaWNrZXIgaW4gYSBcImRpYWxvZ1wiIGJveC5cblx0ICAgQHBhcmFtICBpbnB1dCAgICAgZWxlbWVudCAtIGlnbm9yZWRcblx0ICAgQHBhcmFtICBkYXRlICAgICAgc3RyaW5nIG9yIERhdGUgLSB0aGUgaW5pdGlhbCBkYXRlIHRvIGRpc3BsYXlcblx0ICAgQHBhcmFtICBvblNlbGVjdCAgZnVuY3Rpb24gLSB0aGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGEgZGF0ZSBpcyBzZWxlY3RlZFxuXHQgICBAcGFyYW0gIHNldHRpbmdzICBvYmplY3QgLSB1cGRhdGUgdGhlIGRpYWxvZyBkYXRlIHBpY2tlciBpbnN0YW5jZSdzIHNldHRpbmdzIChhbm9ueW1vdXMgb2JqZWN0KVxuXHQgICBAcGFyYW0gIHBvcyAgICAgICBpbnRbMl0gLSBjb29yZGluYXRlcyBmb3IgdGhlIGRpYWxvZydzIHBvc2l0aW9uIHdpdGhpbiB0aGUgc2NyZWVuIG9yXG5cdCAgICAgICAgICAgICAgICAgICAgIGV2ZW50IC0gd2l0aCB4L3kgY29vcmRpbmF0ZXMgb3Jcblx0ICAgICAgICAgICAgICAgICAgICAgbGVhdmUgZW1wdHkgZm9yIGRlZmF1bHQgKHNjcmVlbiBjZW50cmUpXG5cdCAgIEByZXR1cm4gdGhlIG1hbmFnZXIgb2JqZWN0ICovXG5cdF9kaWFsb2dEYXRlcGlja2VyOiBmdW5jdGlvbihpbnB1dCwgZGF0ZSwgb25TZWxlY3QsIHNldHRpbmdzLCBwb3MpIHtcblx0XHR2YXIgaW5zdCA9IHRoaXMuX2RpYWxvZ0luc3Q7IC8vIGludGVybmFsIGluc3RhbmNlXG5cdFx0aWYgKCFpbnN0KSB7XG5cdFx0XHR0aGlzLnV1aWQgKz0gMTtcblx0XHRcdHZhciBpZCA9ICdkcCcgKyB0aGlzLnV1aWQ7XG5cdFx0XHR0aGlzLl9kaWFsb2dJbnB1dCA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGlkPVwiJyArIGlkICtcblx0XHRcdFx0J1wiIHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyB0b3A6IC0xMDBweDsgd2lkdGg6IDBweDtcIi8+Jyk7XG5cdFx0XHR0aGlzLl9kaWFsb2dJbnB1dC5rZXlkb3duKHRoaXMuX2RvS2V5RG93bik7XG5cdFx0XHQkKCdib2R5JykuYXBwZW5kKHRoaXMuX2RpYWxvZ0lucHV0KTtcblx0XHRcdGluc3QgPSB0aGlzLl9kaWFsb2dJbnN0ID0gdGhpcy5fbmV3SW5zdCh0aGlzLl9kaWFsb2dJbnB1dCwgZmFsc2UpO1xuXHRcdFx0aW5zdC5zZXR0aW5ncyA9IHt9O1xuXHRcdFx0JC5kYXRhKHRoaXMuX2RpYWxvZ0lucHV0WzBdLCBQUk9QX05BTUUsIGluc3QpO1xuXHRcdH1cblx0XHRleHRlbmRSZW1vdmUoaW5zdC5zZXR0aW5ncywgc2V0dGluZ3MgfHwge30pO1xuXHRcdGRhdGUgPSAoZGF0ZSAmJiBkYXRlLmNvbnN0cnVjdG9yID09IERhdGUgPyB0aGlzLl9mb3JtYXREYXRlKGluc3QsIGRhdGUpIDogZGF0ZSk7XG5cdFx0dGhpcy5fZGlhbG9nSW5wdXQudmFsKGRhdGUpO1xuXG5cdFx0dGhpcy5fcG9zID0gKHBvcyA/IChwb3MubGVuZ3RoID8gcG9zIDogW3Bvcy5wYWdlWCwgcG9zLnBhZ2VZXSkgOiBudWxsKTtcblx0XHRpZiAoIXRoaXMuX3Bvcykge1xuXHRcdFx0dmFyIGJyb3dzZXJXaWR0aCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcblx0XHRcdHZhciBicm93c2VySGVpZ2h0ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodDtcblx0XHRcdHZhciBzY3JvbGxYID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0O1xuXHRcdFx0dmFyIHNjcm9sbFkgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wO1xuXHRcdFx0dGhpcy5fcG9zID0gLy8gc2hvdWxkIHVzZSBhY3R1YWwgd2lkdGgvaGVpZ2h0IGJlbG93XG5cdFx0XHRcdFsoYnJvd3NlcldpZHRoIC8gMikgLSAxMDAgKyBzY3JvbGxYLCAoYnJvd3NlckhlaWdodCAvIDIpIC0gMTUwICsgc2Nyb2xsWV07XG5cdFx0fVxuXG5cdFx0Ly8gbW92ZSBpbnB1dCBvbiBzY3JlZW4gZm9yIGZvY3VzLCBidXQgaGlkZGVuIGJlaGluZCBkaWFsb2dcblx0XHR0aGlzLl9kaWFsb2dJbnB1dC5jc3MoJ2xlZnQnLCAodGhpcy5fcG9zWzBdICsgMjApICsgJ3B4JykuY3NzKCd0b3AnLCB0aGlzLl9wb3NbMV0gKyAncHgnKTtcblx0XHRpbnN0LnNldHRpbmdzLm9uU2VsZWN0ID0gb25TZWxlY3Q7XG5cdFx0dGhpcy5faW5EaWFsb2cgPSB0cnVlO1xuXHRcdHRoaXMuZHBEaXYuYWRkQ2xhc3ModGhpcy5fZGlhbG9nQ2xhc3MpO1xuXHRcdHRoaXMuX3Nob3dEYXRlcGlja2VyKHRoaXMuX2RpYWxvZ0lucHV0WzBdKTtcblx0XHRpZiAoJC5ibG9ja1VJKVxuXHRcdFx0JC5ibG9ja1VJKHRoaXMuZHBEaXYpO1xuXHRcdCQuZGF0YSh0aGlzLl9kaWFsb2dJbnB1dFswXSwgUFJPUF9OQU1FLCBpbnN0KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKiBEZXRhY2ggYSBkYXRlcGlja2VyIGZyb20gaXRzIGNvbnRyb2wuXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICAgIGVsZW1lbnQgLSB0aGUgdGFyZ2V0IGlucHV0IGZpZWxkIG9yIGRpdmlzaW9uIG9yIHNwYW4gKi9cblx0X2Rlc3Ryb3lEYXRlcGlja2VyOiBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHR2YXIgJHRhcmdldCA9ICQodGFyZ2V0KTtcblx0XHR2YXIgaW5zdCA9ICQuZGF0YSh0YXJnZXQsIFBST1BfTkFNRSk7XG5cdFx0aWYgKCEkdGFyZ2V0Lmhhc0NsYXNzKHRoaXMubWFya2VyQ2xhc3NOYW1lKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR2YXIgbm9kZU5hbWUgPSB0YXJnZXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHQkLnJlbW92ZURhdGEodGFyZ2V0LCBQUk9QX05BTUUpO1xuXHRcdGlmIChub2RlTmFtZSA9PSAnaW5wdXQnKSB7XG5cdFx0XHRpbnN0LmFwcGVuZC5yZW1vdmUoKTtcblx0XHRcdGluc3QudHJpZ2dlci5yZW1vdmUoKTtcblx0XHRcdCR0YXJnZXQucmVtb3ZlQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpLlxuXHRcdFx0XHR1bmJpbmQoJ2ZvY3VzJywgdGhpcy5fc2hvd0RhdGVwaWNrZXIpLlxuXHRcdFx0XHR1bmJpbmQoJ2tleWRvd24nLCB0aGlzLl9kb0tleURvd24pLlxuXHRcdFx0XHR1bmJpbmQoJ2tleXByZXNzJywgdGhpcy5fZG9LZXlQcmVzcykuXG5cdFx0XHRcdHVuYmluZCgna2V5dXAnLCB0aGlzLl9kb0tleVVwKTtcblx0XHR9IGVsc2UgaWYgKG5vZGVOYW1lID09ICdkaXYnIHx8IG5vZGVOYW1lID09ICdzcGFuJylcblx0XHRcdCR0YXJnZXQucmVtb3ZlQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpLmVtcHR5KCk7XG5cdH0sXG5cblx0LyogRW5hYmxlIHRoZSBkYXRlIHBpY2tlciB0byBhIGpRdWVyeSBzZWxlY3Rpb24uXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICAgIGVsZW1lbnQgLSB0aGUgdGFyZ2V0IGlucHV0IGZpZWxkIG9yIGRpdmlzaW9uIG9yIHNwYW4gKi9cblx0X2VuYWJsZURhdGVwaWNrZXI6IGZ1bmN0aW9uKHRhcmdldCkge1xuXHRcdHZhciAkdGFyZ2V0ID0gJCh0YXJnZXQpO1xuXHRcdHZhciBpbnN0ID0gJC5kYXRhKHRhcmdldCwgUFJPUF9OQU1FKTtcblx0XHRpZiAoISR0YXJnZXQuaGFzQ2xhc3ModGhpcy5tYXJrZXJDbGFzc05hbWUpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHZhciBub2RlTmFtZSA9IHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdGlmIChub2RlTmFtZSA9PSAnaW5wdXQnKSB7XG5cdFx0XHR0YXJnZXQuZGlzYWJsZWQgPSBmYWxzZTtcblx0XHRcdGluc3QudHJpZ2dlci5maWx0ZXIoJ2J1dHRvbicpLlxuXHRcdFx0XHRlYWNoKGZ1bmN0aW9uKCkgeyB0aGlzLmRpc2FibGVkID0gZmFsc2U7IH0pLmVuZCgpLlxuXHRcdFx0XHRmaWx0ZXIoJ2ltZycpLmNzcyh7b3BhY2l0eTogJzEuMCcsIGN1cnNvcjogJyd9KTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAobm9kZU5hbWUgPT0gJ2RpdicgfHwgbm9kZU5hbWUgPT0gJ3NwYW4nKSB7XG5cdFx0XHR2YXIgaW5saW5lID0gJHRhcmdldC5jaGlsZHJlbignLicgKyB0aGlzLl9pbmxpbmVDbGFzcyk7XG5cdFx0XHRpbmxpbmUuY2hpbGRyZW4oKS5yZW1vdmVDbGFzcygndWktc3RhdGUtZGlzYWJsZWQnKTtcblx0XHRcdGlubGluZS5maW5kKFwic2VsZWN0LnVpLWRhdGVwaWNrZXItbW9udGgsIHNlbGVjdC51aS1kYXRlcGlja2VyLXllYXJcIikuXG5cdFx0XHRcdHByb3AoXCJkaXNhYmxlZFwiLCBmYWxzZSk7XG5cdFx0fVxuXHRcdHRoaXMuX2Rpc2FibGVkSW5wdXRzID0gJC5tYXAodGhpcy5fZGlzYWJsZWRJbnB1dHMsXG5cdFx0XHRmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gKHZhbHVlID09IHRhcmdldCA/IG51bGwgOiB2YWx1ZSk7IH0pOyAvLyBkZWxldGUgZW50cnlcblx0fSxcblxuXHQvKiBEaXNhYmxlIHRoZSBkYXRlIHBpY2tlciB0byBhIGpRdWVyeSBzZWxlY3Rpb24uXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICAgIGVsZW1lbnQgLSB0aGUgdGFyZ2V0IGlucHV0IGZpZWxkIG9yIGRpdmlzaW9uIG9yIHNwYW4gKi9cblx0X2Rpc2FibGVEYXRlcGlja2VyOiBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHR2YXIgJHRhcmdldCA9ICQodGFyZ2V0KTtcblx0XHR2YXIgaW5zdCA9ICQuZGF0YSh0YXJnZXQsIFBST1BfTkFNRSk7XG5cdFx0aWYgKCEkdGFyZ2V0Lmhhc0NsYXNzKHRoaXMubWFya2VyQ2xhc3NOYW1lKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR2YXIgbm9kZU5hbWUgPSB0YXJnZXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRpZiAobm9kZU5hbWUgPT0gJ2lucHV0Jykge1xuXHRcdFx0dGFyZ2V0LmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdGluc3QudHJpZ2dlci5maWx0ZXIoJ2J1dHRvbicpLlxuXHRcdFx0XHRlYWNoKGZ1bmN0aW9uKCkgeyB0aGlzLmRpc2FibGVkID0gdHJ1ZTsgfSkuZW5kKCkuXG5cdFx0XHRcdGZpbHRlcignaW1nJykuY3NzKHtvcGFjaXR5OiAnMC41JywgY3Vyc29yOiAnZGVmYXVsdCd9KTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAobm9kZU5hbWUgPT0gJ2RpdicgfHwgbm9kZU5hbWUgPT0gJ3NwYW4nKSB7XG5cdFx0XHR2YXIgaW5saW5lID0gJHRhcmdldC5jaGlsZHJlbignLicgKyB0aGlzLl9pbmxpbmVDbGFzcyk7XG5cdFx0XHRpbmxpbmUuY2hpbGRyZW4oKS5hZGRDbGFzcygndWktc3RhdGUtZGlzYWJsZWQnKTtcblx0XHRcdGlubGluZS5maW5kKFwic2VsZWN0LnVpLWRhdGVwaWNrZXItbW9udGgsIHNlbGVjdC51aS1kYXRlcGlja2VyLXllYXJcIikuXG5cdFx0XHRcdHByb3AoXCJkaXNhYmxlZFwiLCB0cnVlKTtcblx0XHR9XG5cdFx0dGhpcy5fZGlzYWJsZWRJbnB1dHMgPSAkLm1hcCh0aGlzLl9kaXNhYmxlZElucHV0cyxcblx0XHRcdGZ1bmN0aW9uKHZhbHVlKSB7IHJldHVybiAodmFsdWUgPT0gdGFyZ2V0ID8gbnVsbCA6IHZhbHVlKTsgfSk7IC8vIGRlbGV0ZSBlbnRyeVxuXHRcdHRoaXMuX2Rpc2FibGVkSW5wdXRzW3RoaXMuX2Rpc2FibGVkSW5wdXRzLmxlbmd0aF0gPSB0YXJnZXQ7XG5cdH0sXG5cblx0LyogSXMgdGhlIGZpcnN0IGZpZWxkIGluIGEgalF1ZXJ5IGNvbGxlY3Rpb24gZGlzYWJsZWQgYXMgYSBkYXRlcGlja2VyP1xuXHQgICBAcGFyYW0gIHRhcmdldCAgICBlbGVtZW50IC0gdGhlIHRhcmdldCBpbnB1dCBmaWVsZCBvciBkaXZpc2lvbiBvciBzcGFuXG5cdCAgIEByZXR1cm4gYm9vbGVhbiAtIHRydWUgaWYgZGlzYWJsZWQsIGZhbHNlIGlmIGVuYWJsZWQgKi9cblx0X2lzRGlzYWJsZWREYXRlcGlja2VyOiBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRpZiAoIXRhcmdldCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2Rpc2FibGVkSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAodGhpcy5fZGlzYWJsZWRJbnB1dHNbaV0gPT0gdGFyZ2V0KVxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9LFxuXG5cdC8qIFJldHJpZXZlIHRoZSBpbnN0YW5jZSBkYXRhIGZvciB0aGUgdGFyZ2V0IGNvbnRyb2wuXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICBlbGVtZW50IC0gdGhlIHRhcmdldCBpbnB1dCBmaWVsZCBvciBkaXZpc2lvbiBvciBzcGFuXG5cdCAgIEByZXR1cm4gIG9iamVjdCAtIHRoZSBhc3NvY2lhdGVkIGluc3RhbmNlIGRhdGFcblx0ICAgQHRocm93cyAgZXJyb3IgaWYgYSBqUXVlcnkgcHJvYmxlbSBnZXR0aW5nIGRhdGEgKi9cblx0X2dldEluc3Q6IGZ1bmN0aW9uKHRhcmdldCkge1xuXHRcdHRyeSB7XG5cdFx0XHRyZXR1cm4gJC5kYXRhKHRhcmdldCwgUFJPUF9OQU1FKTtcblx0XHR9XG5cdFx0Y2F0Y2ggKGVycikge1xuXHRcdFx0dGhyb3cgJ01pc3NpbmcgaW5zdGFuY2UgZGF0YSBmb3IgdGhpcyBkYXRlcGlja2VyJztcblx0XHR9XG5cdH0sXG5cblx0LyogVXBkYXRlIG9yIHJldHJpZXZlIHRoZSBzZXR0aW5ncyBmb3IgYSBkYXRlIHBpY2tlciBhdHRhY2hlZCB0byBhbiBpbnB1dCBmaWVsZCBvciBkaXZpc2lvbi5cblx0ICAgQHBhcmFtICB0YXJnZXQgIGVsZW1lbnQgLSB0aGUgdGFyZ2V0IGlucHV0IGZpZWxkIG9yIGRpdmlzaW9uIG9yIHNwYW5cblx0ICAgQHBhcmFtICBuYW1lICAgIG9iamVjdCAtIHRoZSBuZXcgc2V0dGluZ3MgdG8gdXBkYXRlIG9yXG5cdCAgICAgICAgICAgICAgICAgICBzdHJpbmcgLSB0aGUgbmFtZSBvZiB0aGUgc2V0dGluZyB0byBjaGFuZ2Ugb3IgcmV0cmlldmUsXG5cdCAgICAgICAgICAgICAgICAgICB3aGVuIHJldHJpZXZpbmcgYWxzbyAnYWxsJyBmb3IgYWxsIGluc3RhbmNlIHNldHRpbmdzIG9yXG5cdCAgICAgICAgICAgICAgICAgICAnZGVmYXVsdHMnIGZvciBhbGwgZ2xvYmFsIGRlZmF1bHRzXG5cdCAgIEBwYXJhbSAgdmFsdWUgICBhbnkgLSB0aGUgbmV3IHZhbHVlIGZvciB0aGUgc2V0dGluZ1xuXHQgICAgICAgICAgICAgICAgICAgKG9taXQgaWYgYWJvdmUgaXMgYW4gb2JqZWN0IG9yIHRvIHJldHJpZXZlIGEgdmFsdWUpICovXG5cdF9vcHRpb25EYXRlcGlja2VyOiBmdW5jdGlvbih0YXJnZXQsIG5hbWUsIHZhbHVlKSB7XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KHRhcmdldCk7XG5cdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMiAmJiB0eXBlb2YgbmFtZSA9PSAnc3RyaW5nJykge1xuXHRcdFx0cmV0dXJuIChuYW1lID09ICdkZWZhdWx0cycgPyAkLmV4dGVuZCh7fSwgJC5kYXRlcGlja2VyLl9kZWZhdWx0cykgOlxuXHRcdFx0XHQoaW5zdCA/IChuYW1lID09ICdhbGwnID8gJC5leHRlbmQoe30sIGluc3Quc2V0dGluZ3MpIDpcblx0XHRcdFx0dGhpcy5fZ2V0KGluc3QsIG5hbWUpKSA6IG51bGwpKTtcblx0XHR9XG5cdFx0dmFyIHNldHRpbmdzID0gbmFtZSB8fCB7fTtcblx0XHRpZiAodHlwZW9mIG5hbWUgPT0gJ3N0cmluZycpIHtcblx0XHRcdHNldHRpbmdzID0ge307XG5cdFx0XHRzZXR0aW5nc1tuYW1lXSA9IHZhbHVlO1xuXHRcdH1cblx0XHRpZiAoaW5zdCkge1xuXHRcdFx0aWYgKHRoaXMuX2N1ckluc3QgPT0gaW5zdCkge1xuXHRcdFx0XHR0aGlzLl9oaWRlRGF0ZXBpY2tlcigpO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGRhdGUgPSB0aGlzLl9nZXREYXRlRGF0ZXBpY2tlcih0YXJnZXQsIHRydWUpO1xuXHRcdFx0dmFyIG1pbkRhdGUgPSB0aGlzLl9nZXRNaW5NYXhEYXRlKGluc3QsICdtaW4nKTtcblx0XHRcdHZhciBtYXhEYXRlID0gdGhpcy5fZ2V0TWluTWF4RGF0ZShpbnN0LCAnbWF4Jyk7XG5cdFx0XHRleHRlbmRSZW1vdmUoaW5zdC5zZXR0aW5ncywgc2V0dGluZ3MpO1xuXHRcdFx0Ly8gcmVmb3JtYXQgdGhlIG9sZCBtaW5EYXRlL21heERhdGUgdmFsdWVzIGlmIGRhdGVGb3JtYXQgY2hhbmdlcyBhbmQgYSBuZXcgbWluRGF0ZS9tYXhEYXRlIGlzbid0IHByb3ZpZGVkXG5cdFx0XHRpZiAobWluRGF0ZSAhPT0gbnVsbCAmJiBzZXR0aW5nc1snZGF0ZUZvcm1hdCddICE9PSB1bmRlZmluZWQgJiYgc2V0dGluZ3NbJ21pbkRhdGUnXSA9PT0gdW5kZWZpbmVkKVxuXHRcdFx0XHRpbnN0LnNldHRpbmdzLm1pbkRhdGUgPSB0aGlzLl9mb3JtYXREYXRlKGluc3QsIG1pbkRhdGUpO1xuXHRcdFx0aWYgKG1heERhdGUgIT09IG51bGwgJiYgc2V0dGluZ3NbJ2RhdGVGb3JtYXQnXSAhPT0gdW5kZWZpbmVkICYmIHNldHRpbmdzWydtYXhEYXRlJ10gPT09IHVuZGVmaW5lZClcblx0XHRcdFx0aW5zdC5zZXR0aW5ncy5tYXhEYXRlID0gdGhpcy5fZm9ybWF0RGF0ZShpbnN0LCBtYXhEYXRlKTtcblx0XHRcdHRoaXMuX2F0dGFjaG1lbnRzKCQodGFyZ2V0KSwgaW5zdCk7XG5cdFx0XHR0aGlzLl9hdXRvU2l6ZShpbnN0KTtcblx0XHRcdHRoaXMuX3NldERhdGUoaW5zdCwgZGF0ZSk7XG5cdFx0XHR0aGlzLl91cGRhdGVBbHRlcm5hdGUoaW5zdCk7XG5cdFx0XHR0aGlzLl91cGRhdGVEYXRlcGlja2VyKGluc3QpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBjaGFuZ2UgbWV0aG9kIGRlcHJlY2F0ZWRcblx0X2NoYW5nZURhdGVwaWNrZXI6IGZ1bmN0aW9uKHRhcmdldCwgbmFtZSwgdmFsdWUpIHtcblx0XHR0aGlzLl9vcHRpb25EYXRlcGlja2VyKHRhcmdldCwgbmFtZSwgdmFsdWUpO1xuXHR9LFxuXG5cdC8qIFJlZHJhdyB0aGUgZGF0ZSBwaWNrZXIgYXR0YWNoZWQgdG8gYW4gaW5wdXQgZmllbGQgb3IgZGl2aXNpb24uXG5cdCAgIEBwYXJhbSAgdGFyZ2V0ICBlbGVtZW50IC0gdGhlIHRhcmdldCBpbnB1dCBmaWVsZCBvciBkaXZpc2lvbiBvciBzcGFuICovXG5cdF9yZWZyZXNoRGF0ZXBpY2tlcjogZnVuY3Rpb24odGFyZ2V0KSB7XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KHRhcmdldCk7XG5cdFx0aWYgKGluc3QpIHtcblx0XHRcdHRoaXMuX3VwZGF0ZURhdGVwaWNrZXIoaW5zdCk7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIFNldCB0aGUgZGF0ZXMgZm9yIGEgalF1ZXJ5IHNlbGVjdGlvbi5cblx0ICAgQHBhcmFtICB0YXJnZXQgICBlbGVtZW50IC0gdGhlIHRhcmdldCBpbnB1dCBmaWVsZCBvciBkaXZpc2lvbiBvciBzcGFuXG5cdCAgIEBwYXJhbSAgZGF0ZSAgICAgRGF0ZSAtIHRoZSBuZXcgZGF0ZSAqL1xuXHRfc2V0RGF0ZURhdGVwaWNrZXI6IGZ1bmN0aW9uKHRhcmdldCwgZGF0ZSkge1xuXHRcdHZhciBpbnN0ID0gdGhpcy5fZ2V0SW5zdCh0YXJnZXQpO1xuXHRcdGlmIChpbnN0KSB7XG5cdFx0XHR0aGlzLl9zZXREYXRlKGluc3QsIGRhdGUpO1xuXHRcdFx0dGhpcy5fdXBkYXRlRGF0ZXBpY2tlcihpbnN0KTtcblx0XHRcdHRoaXMuX3VwZGF0ZUFsdGVybmF0ZShpbnN0KTtcblx0XHR9XG5cdH0sXG5cblx0LyogR2V0IHRoZSBkYXRlKHMpIGZvciB0aGUgZmlyc3QgZW50cnkgaW4gYSBqUXVlcnkgc2VsZWN0aW9uLlxuXHQgICBAcGFyYW0gIHRhcmdldCAgICAgZWxlbWVudCAtIHRoZSB0YXJnZXQgaW5wdXQgZmllbGQgb3IgZGl2aXNpb24gb3Igc3BhblxuXHQgICBAcGFyYW0gIG5vRGVmYXVsdCAgYm9vbGVhbiAtIHRydWUgaWYgbm8gZGVmYXVsdCBkYXRlIGlzIHRvIGJlIHVzZWRcblx0ICAgQHJldHVybiBEYXRlIC0gdGhlIGN1cnJlbnQgZGF0ZSAqL1xuXHRfZ2V0RGF0ZURhdGVwaWNrZXI6IGZ1bmN0aW9uKHRhcmdldCwgbm9EZWZhdWx0KSB7XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KHRhcmdldCk7XG5cdFx0aWYgKGluc3QgJiYgIWluc3QuaW5saW5lKVxuXHRcdFx0dGhpcy5fc2V0RGF0ZUZyb21GaWVsZChpbnN0LCBub0RlZmF1bHQpO1xuXHRcdHJldHVybiAoaW5zdCA/IHRoaXMuX2dldERhdGUoaW5zdCkgOiBudWxsKTtcblx0fSxcblxuXHQvKiBIYW5kbGUga2V5c3Ryb2tlcy4gKi9cblx0X2RvS2V5RG93bjogZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgaW5zdCA9ICQuZGF0ZXBpY2tlci5fZ2V0SW5zdChldmVudC50YXJnZXQpO1xuXHRcdHZhciBoYW5kbGVkID0gdHJ1ZTtcblx0XHR2YXIgaXNSVEwgPSBpbnN0LmRwRGl2LmlzKCcudWktZGF0ZXBpY2tlci1ydGwnKTtcblx0XHRpbnN0Ll9rZXlFdmVudCA9IHRydWU7XG5cdFx0aWYgKCQuZGF0ZXBpY2tlci5fZGF0ZXBpY2tlclNob3dpbmcpXG5cdFx0XHRzd2l0Y2ggKGV2ZW50LmtleUNvZGUpIHtcblx0XHRcdFx0Y2FzZSA5OiAkLmRhdGVwaWNrZXIuX2hpZGVEYXRlcGlja2VyKCk7XG5cdFx0XHRcdFx0XHRoYW5kbGVkID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRicmVhazsgLy8gaGlkZSBvbiB0YWIgb3V0XG5cdFx0XHRcdGNhc2UgMTM6IHZhciBzZWwgPSAkKCd0ZC4nICsgJC5kYXRlcGlja2VyLl9kYXlPdmVyQ2xhc3MgKyAnOm5vdCguJyArXG5cdFx0XHRcdFx0XHRcdFx0XHQkLmRhdGVwaWNrZXIuX2N1cnJlbnRDbGFzcyArICcpJywgaW5zdC5kcERpdik7XG5cdFx0XHRcdFx0XHRpZiAoc2VsWzBdKVxuXHRcdFx0XHRcdFx0XHQkLmRhdGVwaWNrZXIuX3NlbGVjdERheShldmVudC50YXJnZXQsIGluc3Quc2VsZWN0ZWRNb250aCwgaW5zdC5zZWxlY3RlZFllYXIsIHNlbFswXSk7XG5cdFx0XHRcdFx0XHRcdHZhciBvblNlbGVjdCA9ICQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdvblNlbGVjdCcpO1xuXHRcdFx0XHRcdFx0XHRpZiAob25TZWxlY3QpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgZGF0ZVN0ciA9ICQuZGF0ZXBpY2tlci5fZm9ybWF0RGF0ZShpbnN0KTtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIHRyaWdnZXIgY3VzdG9tIGNhbGxiYWNrXG5cdFx0XHRcdFx0XHRcdFx0b25TZWxlY3QuYXBwbHkoKGluc3QuaW5wdXQgPyBpbnN0LmlucHV0WzBdIDogbnVsbCksIFtkYXRlU3RyLCBpbnN0XSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0JC5kYXRlcGlja2VyLl9oaWRlRGF0ZXBpY2tlcigpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlOyAvLyBkb24ndCBzdWJtaXQgdGhlIGZvcm1cblx0XHRcdFx0XHRcdGJyZWFrOyAvLyBzZWxlY3QgdGhlIHZhbHVlIG9uIGVudGVyXG5cdFx0XHRcdGNhc2UgMjc6ICQuZGF0ZXBpY2tlci5faGlkZURhdGVwaWNrZXIoKTtcblx0XHRcdFx0XHRcdGJyZWFrOyAvLyBoaWRlIG9uIGVzY2FwZVxuXHRcdFx0XHRjYXNlIDMzOiAkLmRhdGVwaWNrZXIuX2FkanVzdERhdGUoZXZlbnQudGFyZ2V0LCAoZXZlbnQuY3RybEtleSA/XG5cdFx0XHRcdFx0XHRcdC0kLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnc3RlcEJpZ01vbnRocycpIDpcblx0XHRcdFx0XHRcdFx0LSQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdzdGVwTW9udGhzJykpLCAnTScpO1xuXHRcdFx0XHRcdFx0YnJlYWs7IC8vIHByZXZpb3VzIG1vbnRoL3llYXIgb24gcGFnZSB1cC8rIGN0cmxcblx0XHRcdFx0Y2FzZSAzNDogJC5kYXRlcGlja2VyLl9hZGp1c3REYXRlKGV2ZW50LnRhcmdldCwgKGV2ZW50LmN0cmxLZXkgP1xuXHRcdFx0XHRcdFx0XHQrJC5kYXRlcGlja2VyLl9nZXQoaW5zdCwgJ3N0ZXBCaWdNb250aHMnKSA6XG5cdFx0XHRcdFx0XHRcdCskLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnc3RlcE1vbnRocycpKSwgJ00nKTtcblx0XHRcdFx0XHRcdGJyZWFrOyAvLyBuZXh0IG1vbnRoL3llYXIgb24gcGFnZSBkb3duLysgY3RybFxuXHRcdFx0XHRjYXNlIDM1OiBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAkLmRhdGVwaWNrZXIuX2NsZWFyRGF0ZShldmVudC50YXJnZXQpO1xuXHRcdFx0XHRcdFx0aGFuZGxlZCA9IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleTtcblx0XHRcdFx0XHRcdGJyZWFrOyAvLyBjbGVhciBvbiBjdHJsIG9yIGNvbW1hbmQgK2VuZFxuXHRcdFx0XHRjYXNlIDM2OiBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAkLmRhdGVwaWNrZXIuX2dvdG9Ub2RheShldmVudC50YXJnZXQpO1xuXHRcdFx0XHRcdFx0aGFuZGxlZCA9IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleTtcblx0XHRcdFx0XHRcdGJyZWFrOyAvLyBjdXJyZW50IG9uIGN0cmwgb3IgY29tbWFuZCAraG9tZVxuXHRcdFx0XHRjYXNlIDM3OiBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAkLmRhdGVwaWNrZXIuX2FkanVzdERhdGUoZXZlbnQudGFyZ2V0LCAoaXNSVEwgPyArMSA6IC0xKSwgJ0QnKTtcblx0XHRcdFx0XHRcdGhhbmRsZWQgPSBldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXk7XG5cdFx0XHRcdFx0XHQvLyAtMSBkYXkgb24gY3RybCBvciBjb21tYW5kICtsZWZ0XG5cdFx0XHRcdFx0XHRpZiAoZXZlbnQub3JpZ2luYWxFdmVudC5hbHRLZXkpICQuZGF0ZXBpY2tlci5fYWRqdXN0RGF0ZShldmVudC50YXJnZXQsIChldmVudC5jdHJsS2V5ID9cblx0XHRcdFx0XHRcdFx0XHRcdC0kLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnc3RlcEJpZ01vbnRocycpIDpcblx0XHRcdFx0XHRcdFx0XHRcdC0kLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnc3RlcE1vbnRocycpKSwgJ00nKTtcblx0XHRcdFx0XHRcdC8vIG5leHQgbW9udGgveWVhciBvbiBhbHQgK2xlZnQgb24gTWFjXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAzODogaWYgKGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleSkgJC5kYXRlcGlja2VyLl9hZGp1c3REYXRlKGV2ZW50LnRhcmdldCwgLTcsICdEJyk7XG5cdFx0XHRcdFx0XHRoYW5kbGVkID0gZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5O1xuXHRcdFx0XHRcdFx0YnJlYWs7IC8vIC0xIHdlZWsgb24gY3RybCBvciBjb21tYW5kICt1cFxuXHRcdFx0XHRjYXNlIDM5OiBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAkLmRhdGVwaWNrZXIuX2FkanVzdERhdGUoZXZlbnQudGFyZ2V0LCAoaXNSVEwgPyAtMSA6ICsxKSwgJ0QnKTtcblx0XHRcdFx0XHRcdGhhbmRsZWQgPSBldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXk7XG5cdFx0XHRcdFx0XHQvLyArMSBkYXkgb24gY3RybCBvciBjb21tYW5kICtyaWdodFxuXHRcdFx0XHRcdFx0aWYgKGV2ZW50Lm9yaWdpbmFsRXZlbnQuYWx0S2V5KSAkLmRhdGVwaWNrZXIuX2FkanVzdERhdGUoZXZlbnQudGFyZ2V0LCAoZXZlbnQuY3RybEtleSA/XG5cdFx0XHRcdFx0XHRcdFx0XHQrJC5kYXRlcGlja2VyLl9nZXQoaW5zdCwgJ3N0ZXBCaWdNb250aHMnKSA6XG5cdFx0XHRcdFx0XHRcdFx0XHQrJC5kYXRlcGlja2VyLl9nZXQoaW5zdCwgJ3N0ZXBNb250aHMnKSksICdNJyk7XG5cdFx0XHRcdFx0XHQvLyBuZXh0IG1vbnRoL3llYXIgb24gYWx0ICtyaWdodFxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgNDA6IGlmIChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpICQuZGF0ZXBpY2tlci5fYWRqdXN0RGF0ZShldmVudC50YXJnZXQsICs3LCAnRCcpO1xuXHRcdFx0XHRcdFx0aGFuZGxlZCA9IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleTtcblx0XHRcdFx0XHRcdGJyZWFrOyAvLyArMSB3ZWVrIG9uIGN0cmwgb3IgY29tbWFuZCArZG93blxuXHRcdFx0XHRkZWZhdWx0OiBoYW5kbGVkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0ZWxzZSBpZiAoZXZlbnQua2V5Q29kZSA9PSAzNiAmJiBldmVudC5jdHJsS2V5KSAvLyBkaXNwbGF5IHRoZSBkYXRlIHBpY2tlciBvbiBjdHJsK2hvbWVcblx0XHRcdCQuZGF0ZXBpY2tlci5fc2hvd0RhdGVwaWNrZXIodGhpcyk7XG5cdFx0ZWxzZSB7XG5cdFx0XHRoYW5kbGVkID0gZmFsc2U7XG5cdFx0fVxuXHRcdGlmIChoYW5kbGVkKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIEZpbHRlciBlbnRlcmVkIGNoYXJhY3RlcnMgLSBiYXNlZCBvbiBkYXRlIGZvcm1hdC4gKi9cblx0X2RvS2V5UHJlc3M6IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIGluc3QgPSAkLmRhdGVwaWNrZXIuX2dldEluc3QoZXZlbnQudGFyZ2V0KTtcblx0XHRpZiAoJC5kYXRlcGlja2VyLl9nZXQoaW5zdCwgJ2NvbnN0cmFpbklucHV0JykpIHtcblx0XHRcdHZhciBjaGFycyA9ICQuZGF0ZXBpY2tlci5fcG9zc2libGVDaGFycygkLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnZGF0ZUZvcm1hdCcpKTtcblx0XHRcdHZhciBjaHIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGV2ZW50LmNoYXJDb2RlID09IHVuZGVmaW5lZCA/IGV2ZW50LmtleUNvZGUgOiBldmVudC5jaGFyQ29kZSk7XG5cdFx0XHRyZXR1cm4gZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IChjaHIgPCAnICcgfHwgIWNoYXJzIHx8IGNoYXJzLmluZGV4T2YoY2hyKSA+IC0xKTtcblx0XHR9XG5cdH0sXG5cblx0LyogU3luY2hyb25pc2UgbWFudWFsIGVudHJ5IGFuZCBmaWVsZC9hbHRlcm5hdGUgZmllbGQuICovXG5cdF9kb0tleVVwOiBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBpbnN0ID0gJC5kYXRlcGlja2VyLl9nZXRJbnN0KGV2ZW50LnRhcmdldCk7XG5cdFx0aWYgKGluc3QuaW5wdXQudmFsKCkgIT0gaW5zdC5sYXN0VmFsKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR2YXIgZGF0ZSA9ICQuZGF0ZXBpY2tlci5wYXJzZURhdGUoJC5kYXRlcGlja2VyLl9nZXQoaW5zdCwgJ2RhdGVGb3JtYXQnKSxcblx0XHRcdFx0XHQoaW5zdC5pbnB1dCA/IGluc3QuaW5wdXQudmFsKCkgOiBudWxsKSxcblx0XHRcdFx0XHQkLmRhdGVwaWNrZXIuX2dldEZvcm1hdENvbmZpZyhpbnN0KSk7XG5cdFx0XHRcdGlmIChkYXRlKSB7IC8vIG9ubHkgaWYgdmFsaWRcblx0XHRcdFx0XHQkLmRhdGVwaWNrZXIuX3NldERhdGVGcm9tRmllbGQoaW5zdCk7XG5cdFx0XHRcdFx0JC5kYXRlcGlja2VyLl91cGRhdGVBbHRlcm5hdGUoaW5zdCk7XG5cdFx0XHRcdFx0JC5kYXRlcGlja2VyLl91cGRhdGVEYXRlcGlja2VyKGluc3QpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdCQuZGF0ZXBpY2tlci5sb2coZXJyKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH0sXG5cblx0LyogUG9wLXVwIHRoZSBkYXRlIHBpY2tlciBmb3IgYSBnaXZlbiBpbnB1dCBmaWVsZC5cblx0ICAgSWYgZmFsc2UgcmV0dXJuZWQgZnJvbSBiZWZvcmVTaG93IGV2ZW50IGhhbmRsZXIgZG8gbm90IHNob3cuXG5cdCAgIEBwYXJhbSAgaW5wdXQgIGVsZW1lbnQgLSB0aGUgaW5wdXQgZmllbGQgYXR0YWNoZWQgdG8gdGhlIGRhdGUgcGlja2VyIG9yXG5cdCAgICAgICAgICAgICAgICAgIGV2ZW50IC0gaWYgdHJpZ2dlcmVkIGJ5IGZvY3VzICovXG5cdF9zaG93RGF0ZXBpY2tlcjogZnVuY3Rpb24oaW5wdXQpIHtcblx0XHRpbnB1dCA9IGlucHV0LnRhcmdldCB8fCBpbnB1dDtcblx0XHRpZiAoaW5wdXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAhPSAnaW5wdXQnKSAvLyBmaW5kIGZyb20gYnV0dG9uL2ltYWdlIHRyaWdnZXJcblx0XHRcdGlucHV0ID0gJCgnaW5wdXQnLCBpbnB1dC5wYXJlbnROb2RlKVswXTtcblx0XHRpZiAoJC5kYXRlcGlja2VyLl9pc0Rpc2FibGVkRGF0ZXBpY2tlcihpbnB1dCkgfHwgJC5kYXRlcGlja2VyLl9sYXN0SW5wdXQgPT0gaW5wdXQpIC8vIGFscmVhZHkgaGVyZVxuXHRcdFx0cmV0dXJuO1xuXHRcdHZhciBpbnN0ID0gJC5kYXRlcGlja2VyLl9nZXRJbnN0KGlucHV0KTtcblx0XHRpZiAoJC5kYXRlcGlja2VyLl9jdXJJbnN0ICYmICQuZGF0ZXBpY2tlci5fY3VySW5zdCAhPSBpbnN0KSB7XG5cdFx0XHQkLmRhdGVwaWNrZXIuX2N1ckluc3QuZHBEaXYuc3RvcCh0cnVlLCB0cnVlKTtcblx0XHRcdGlmICggaW5zdCAmJiAkLmRhdGVwaWNrZXIuX2RhdGVwaWNrZXJTaG93aW5nICkge1xuXHRcdFx0XHQkLmRhdGVwaWNrZXIuX2hpZGVEYXRlcGlja2VyKCAkLmRhdGVwaWNrZXIuX2N1ckluc3QuaW5wdXRbMF0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dmFyIGJlZm9yZVNob3cgPSAkLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnYmVmb3JlU2hvdycpO1xuXHRcdHZhciBiZWZvcmVTaG93U2V0dGluZ3MgPSBiZWZvcmVTaG93ID8gYmVmb3JlU2hvdy5hcHBseShpbnB1dCwgW2lucHV0LCBpbnN0XSkgOiB7fTtcblx0XHRpZihiZWZvcmVTaG93U2V0dGluZ3MgPT09IGZhbHNlKXtcblx0XHRcdC8vZmFsc2Vcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZXh0ZW5kUmVtb3ZlKGluc3Quc2V0dGluZ3MsIGJlZm9yZVNob3dTZXR0aW5ncyk7XG5cdFx0aW5zdC5sYXN0VmFsID0gbnVsbDtcblx0XHQkLmRhdGVwaWNrZXIuX2xhc3RJbnB1dCA9IGlucHV0O1xuXHRcdCQuZGF0ZXBpY2tlci5fc2V0RGF0ZUZyb21GaWVsZChpbnN0KTtcblx0XHRpZiAoJC5kYXRlcGlja2VyLl9pbkRpYWxvZykgLy8gaGlkZSBjdXJzb3Jcblx0XHRcdGlucHV0LnZhbHVlID0gJyc7XG5cdFx0aWYgKCEkLmRhdGVwaWNrZXIuX3BvcykgeyAvLyBwb3NpdGlvbiBiZWxvdyBpbnB1dFxuXHRcdFx0JC5kYXRlcGlja2VyLl9wb3MgPSAkLmRhdGVwaWNrZXIuX2ZpbmRQb3MoaW5wdXQpO1xuXHRcdFx0JC5kYXRlcGlja2VyLl9wb3NbMV0gKz0gaW5wdXQub2Zmc2V0SGVpZ2h0OyAvLyBhZGQgdGhlIGhlaWdodFxuXHRcdH1cblx0XHR2YXIgaXNGaXhlZCA9IGZhbHNlO1xuXHRcdCQoaW5wdXQpLnBhcmVudHMoKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aXNGaXhlZCB8PSAkKHRoaXMpLmNzcygncG9zaXRpb24nKSA9PSAnZml4ZWQnO1xuXHRcdFx0cmV0dXJuICFpc0ZpeGVkO1xuXHRcdH0pO1xuXHRcdHZhciBvZmZzZXQgPSB7bGVmdDogJC5kYXRlcGlja2VyLl9wb3NbMF0sIHRvcDogJC5kYXRlcGlja2VyLl9wb3NbMV19O1xuXHRcdCQuZGF0ZXBpY2tlci5fcG9zID0gbnVsbDtcblx0XHQvL3RvIGF2b2lkIGZsYXNoZXMgb24gRmlyZWZveFxuXHRcdGluc3QuZHBEaXYuZW1wdHkoKTtcblx0XHQvLyBkZXRlcm1pbmUgc2l6aW5nIG9mZnNjcmVlblxuXHRcdGluc3QuZHBEaXYuY3NzKHtwb3NpdGlvbjogJ2Fic29sdXRlJywgZGlzcGxheTogJ2Jsb2NrJywgdG9wOiAnLTEwMDBweCd9KTtcblx0XHQkLmRhdGVwaWNrZXIuX3VwZGF0ZURhdGVwaWNrZXIoaW5zdCk7XG5cdFx0Ly8gZml4IHdpZHRoIGZvciBkeW5hbWljIG51bWJlciBvZiBkYXRlIHBpY2tlcnNcblx0XHQvLyBhbmQgYWRqdXN0IHBvc2l0aW9uIGJlZm9yZSBzaG93aW5nXG5cdFx0b2Zmc2V0ID0gJC5kYXRlcGlja2VyLl9jaGVja09mZnNldChpbnN0LCBvZmZzZXQsIGlzRml4ZWQpO1xuXHRcdGluc3QuZHBEaXYuY3NzKHtwb3NpdGlvbjogKCQuZGF0ZXBpY2tlci5faW5EaWFsb2cgJiYgJC5ibG9ja1VJID9cblx0XHRcdCdzdGF0aWMnIDogKGlzRml4ZWQgPyAnZml4ZWQnIDogJ2Fic29sdXRlJykpLCBkaXNwbGF5OiAnbm9uZScsXG5cdFx0XHRsZWZ0OiBvZmZzZXQubGVmdCArICdweCcsIHRvcDogb2Zmc2V0LnRvcCArICdweCd9KTtcblx0XHRpZiAoIWluc3QuaW5saW5lKSB7XG5cdFx0XHR2YXIgc2hvd0FuaW0gPSAkLmRhdGVwaWNrZXIuX2dldChpbnN0LCAnc2hvd0FuaW0nKTtcblx0XHRcdHZhciBkdXJhdGlvbiA9ICQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdkdXJhdGlvbicpO1xuXHRcdFx0dmFyIHBvc3RQcm9jZXNzID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBjb3ZlciA9IGluc3QuZHBEaXYuZmluZCgnaWZyYW1lLnVpLWRhdGVwaWNrZXItY292ZXInKTsgLy8gSUU2LSBvbmx5XG5cdFx0XHRcdGlmKCAhISBjb3Zlci5sZW5ndGggKXtcblx0XHRcdFx0XHR2YXIgYm9yZGVycyA9ICQuZGF0ZXBpY2tlci5fZ2V0Qm9yZGVycyhpbnN0LmRwRGl2KTtcblx0XHRcdFx0XHRjb3Zlci5jc3Moe2xlZnQ6IC1ib3JkZXJzWzBdLCB0b3A6IC1ib3JkZXJzWzFdLFxuXHRcdFx0XHRcdFx0d2lkdGg6IGluc3QuZHBEaXYub3V0ZXJXaWR0aCgpLCBoZWlnaHQ6IGluc3QuZHBEaXYub3V0ZXJIZWlnaHQoKX0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0aW5zdC5kcERpdi56SW5kZXgoJChpbnB1dCkuekluZGV4KCkrMSk7XG5cdFx0XHQkLmRhdGVwaWNrZXIuX2RhdGVwaWNrZXJTaG93aW5nID0gdHJ1ZTtcblxuXHRcdFx0Ly8gREVQUkVDQVRFRDogYWZ0ZXIgQkMgZm9yIDEuOC54ICQuZWZmZWN0c1sgc2hvd0FuaW0gXSBpcyBub3QgbmVlZGVkXG5cdFx0XHRpZiAoICQuZWZmZWN0cyAmJiAoICQuZWZmZWN0cy5lZmZlY3RbIHNob3dBbmltIF0gfHwgJC5lZmZlY3RzWyBzaG93QW5pbSBdICkgKVxuXHRcdFx0XHRpbnN0LmRwRGl2LnNob3coc2hvd0FuaW0sICQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdzaG93T3B0aW9ucycpLCBkdXJhdGlvbiwgcG9zdFByb2Nlc3MpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRpbnN0LmRwRGl2W3Nob3dBbmltIHx8ICdzaG93J10oKHNob3dBbmltID8gZHVyYXRpb24gOiBudWxsKSwgcG9zdFByb2Nlc3MpO1xuXHRcdFx0aWYgKCFzaG93QW5pbSB8fCAhZHVyYXRpb24pXG5cdFx0XHRcdHBvc3RQcm9jZXNzKCk7XG5cdFx0XHRpZiAoaW5zdC5pbnB1dC5pcygnOnZpc2libGUnKSAmJiAhaW5zdC5pbnB1dC5pcygnOmRpc2FibGVkJykpXG5cdFx0XHRcdGluc3QuaW5wdXQuZm9jdXMoKTtcblx0XHRcdCQuZGF0ZXBpY2tlci5fY3VySW5zdCA9IGluc3Q7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIEdlbmVyYXRlIHRoZSBkYXRlIHBpY2tlciBjb250ZW50LiAqL1xuXHRfdXBkYXRlRGF0ZXBpY2tlcjogZnVuY3Rpb24oaW5zdCkge1xuXHRcdHRoaXMubWF4Um93cyA9IDQ7IC8vUmVzZXQgdGhlIG1heCBudW1iZXIgb2Ygcm93cyBiZWluZyBkaXNwbGF5ZWQgKHNlZSAjNzA0Mylcblx0XHR2YXIgYm9yZGVycyA9ICQuZGF0ZXBpY2tlci5fZ2V0Qm9yZGVycyhpbnN0LmRwRGl2KTtcblx0XHRpbnN0QWN0aXZlID0gaW5zdDsgLy8gZm9yIGRlbGVnYXRlIGhvdmVyIGV2ZW50c1xuXHRcdGluc3QuZHBEaXYuZW1wdHkoKS5hcHBlbmQodGhpcy5fZ2VuZXJhdGVIVE1MKGluc3QpKTtcblx0XHR0aGlzLl9hdHRhY2hIYW5kbGVycyhpbnN0KTtcblx0XHR2YXIgY292ZXIgPSBpbnN0LmRwRGl2LmZpbmQoJ2lmcmFtZS51aS1kYXRlcGlja2VyLWNvdmVyJyk7IC8vIElFNi0gb25seVxuXHRcdGlmKCAhIWNvdmVyLmxlbmd0aCApeyAvL2F2b2lkIGNhbGwgdG8gb3V0ZXJYWFhYKCkgd2hlbiBub3QgaW4gSUU2XG5cdFx0XHRjb3Zlci5jc3Moe2xlZnQ6IC1ib3JkZXJzWzBdLCB0b3A6IC1ib3JkZXJzWzFdLCB3aWR0aDogaW5zdC5kcERpdi5vdXRlcldpZHRoKCksIGhlaWdodDogaW5zdC5kcERpdi5vdXRlckhlaWdodCgpfSlcblx0XHR9XG5cdFx0aW5zdC5kcERpdi5maW5kKCcuJyArIHRoaXMuX2RheU92ZXJDbGFzcyArICcgYScpLm1vdXNlb3ZlcigpO1xuXHRcdHZhciBudW1Nb250aHMgPSB0aGlzLl9nZXROdW1iZXJPZk1vbnRocyhpbnN0KTtcblx0XHR2YXIgY29scyA9IG51bU1vbnRoc1sxXTtcblx0XHR2YXIgd2lkdGggPSAxNztcblx0XHRpbnN0LmRwRGl2LnJlbW92ZUNsYXNzKCd1aS1kYXRlcGlja2VyLW11bHRpLTIgdWktZGF0ZXBpY2tlci1tdWx0aS0zIHVpLWRhdGVwaWNrZXItbXVsdGktNCcpLndpZHRoKCcnKTtcblx0XHRpZiAoY29scyA+IDEpXG5cdFx0XHRpbnN0LmRwRGl2LmFkZENsYXNzKCd1aS1kYXRlcGlja2VyLW11bHRpLScgKyBjb2xzKS5jc3MoJ3dpZHRoJywgKHdpZHRoICogY29scykgKyAnZW0nKTtcblx0XHRpbnN0LmRwRGl2WyhudW1Nb250aHNbMF0gIT0gMSB8fCBudW1Nb250aHNbMV0gIT0gMSA/ICdhZGQnIDogJ3JlbW92ZScpICtcblx0XHRcdCdDbGFzcyddKCd1aS1kYXRlcGlja2VyLW11bHRpJyk7XG5cdFx0aW5zdC5kcERpdlsodGhpcy5fZ2V0KGluc3QsICdpc1JUTCcpID8gJ2FkZCcgOiAncmVtb3ZlJykgK1xuXHRcdFx0J0NsYXNzJ10oJ3VpLWRhdGVwaWNrZXItcnRsJyk7XG5cdFx0aWYgKGluc3QgPT0gJC5kYXRlcGlja2VyLl9jdXJJbnN0ICYmICQuZGF0ZXBpY2tlci5fZGF0ZXBpY2tlclNob3dpbmcgJiYgaW5zdC5pbnB1dCAmJlxuXHRcdFx0XHQvLyAjNjY5NCAtIGRvbid0IGZvY3VzIHRoZSBpbnB1dCBpZiBpdCdzIGFscmVhZHkgZm9jdXNlZFxuXHRcdFx0XHQvLyB0aGlzIGJyZWFrcyB0aGUgY2hhbmdlIGV2ZW50IGluIElFXG5cdFx0XHRcdGluc3QuaW5wdXQuaXMoJzp2aXNpYmxlJykgJiYgIWluc3QuaW5wdXQuaXMoJzpkaXNhYmxlZCcpICYmIGluc3QuaW5wdXRbMF0gIT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudClcblx0XHRcdGluc3QuaW5wdXQuZm9jdXMoKTtcblx0XHQvLyBkZWZmZXJlZCByZW5kZXIgb2YgdGhlIHllYXJzIHNlbGVjdCAodG8gYXZvaWQgZmxhc2hlcyBvbiBGaXJlZm94KVxuXHRcdGlmKCBpbnN0LnllYXJzaHRtbCApe1xuXHRcdFx0dmFyIG9yaWd5ZWFyc2h0bWwgPSBpbnN0LnllYXJzaHRtbDtcblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdFx0Ly9hc3N1cmUgdGhhdCBpbnN0LnllYXJzaHRtbCBkaWRuJ3QgY2hhbmdlLlxuXHRcdFx0XHRpZiggb3JpZ3llYXJzaHRtbCA9PT0gaW5zdC55ZWFyc2h0bWwgJiYgaW5zdC55ZWFyc2h0bWwgKXtcblx0XHRcdFx0XHRpbnN0LmRwRGl2LmZpbmQoJ3NlbGVjdC51aS1kYXRlcGlja2VyLXllYXI6Zmlyc3QnKS5yZXBsYWNlV2l0aChpbnN0LnllYXJzaHRtbCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0b3JpZ3llYXJzaHRtbCA9IGluc3QueWVhcnNodG1sID0gbnVsbDtcblx0XHRcdH0sIDApO1xuXHRcdH1cblx0fSxcblxuXHQvKiBSZXRyaWV2ZSB0aGUgc2l6ZSBvZiBsZWZ0IGFuZCB0b3AgYm9yZGVycyBmb3IgYW4gZWxlbWVudC5cblx0ICAgQHBhcmFtICBlbGVtICAoalF1ZXJ5IG9iamVjdCkgdGhlIGVsZW1lbnQgb2YgaW50ZXJlc3Rcblx0ICAgQHJldHVybiAgKG51bWJlclsyXSkgdGhlIGxlZnQgYW5kIHRvcCBib3JkZXJzICovXG5cdF9nZXRCb3JkZXJzOiBmdW5jdGlvbihlbGVtKSB7XG5cdFx0dmFyIGNvbnZlcnQgPSBmdW5jdGlvbih2YWx1ZSkge1xuXHRcdFx0cmV0dXJuIHt0aGluOiAxLCBtZWRpdW06IDIsIHRoaWNrOiAzfVt2YWx1ZV0gfHwgdmFsdWU7XG5cdFx0fTtcblx0XHRyZXR1cm4gW3BhcnNlRmxvYXQoY29udmVydChlbGVtLmNzcygnYm9yZGVyLWxlZnQtd2lkdGgnKSkpLFxuXHRcdFx0cGFyc2VGbG9hdChjb252ZXJ0KGVsZW0uY3NzKCdib3JkZXItdG9wLXdpZHRoJykpKV07XG5cdH0sXG5cblx0LyogQ2hlY2sgcG9zaXRpb25pbmcgdG8gcmVtYWluIG9uIHNjcmVlbi4gKi9cblx0X2NoZWNrT2Zmc2V0OiBmdW5jdGlvbihpbnN0LCBvZmZzZXQsIGlzRml4ZWQpIHtcblx0XHR2YXIgZHBXaWR0aCA9IGluc3QuZHBEaXYub3V0ZXJXaWR0aCgpO1xuXHRcdHZhciBkcEhlaWdodCA9IGluc3QuZHBEaXYub3V0ZXJIZWlnaHQoKTtcblx0XHR2YXIgaW5wdXRXaWR0aCA9IGluc3QuaW5wdXQgPyBpbnN0LmlucHV0Lm91dGVyV2lkdGgoKSA6IDA7XG5cdFx0dmFyIGlucHV0SGVpZ2h0ID0gaW5zdC5pbnB1dCA/IGluc3QuaW5wdXQub3V0ZXJIZWlnaHQoKSA6IDA7XG5cdFx0dmFyIHZpZXdXaWR0aCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCArIChpc0ZpeGVkID8gMCA6ICQoZG9jdW1lbnQpLnNjcm9sbExlZnQoKSk7XG5cdFx0dmFyIHZpZXdIZWlnaHQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0ICsgKGlzRml4ZWQgPyAwIDogJChkb2N1bWVudCkuc2Nyb2xsVG9wKCkpO1xuXG5cdFx0b2Zmc2V0LmxlZnQgLT0gKHRoaXMuX2dldChpbnN0LCAnaXNSVEwnKSA/IChkcFdpZHRoIC0gaW5wdXRXaWR0aCkgOiAwKTtcblx0XHRvZmZzZXQubGVmdCAtPSAoaXNGaXhlZCAmJiBvZmZzZXQubGVmdCA9PSBpbnN0LmlucHV0Lm9mZnNldCgpLmxlZnQpID8gJChkb2N1bWVudCkuc2Nyb2xsTGVmdCgpIDogMDtcblx0XHRvZmZzZXQudG9wIC09IChpc0ZpeGVkICYmIG9mZnNldC50b3AgPT0gKGluc3QuaW5wdXQub2Zmc2V0KCkudG9wICsgaW5wdXRIZWlnaHQpKSA/ICQoZG9jdW1lbnQpLnNjcm9sbFRvcCgpIDogMDtcblxuXHRcdC8vIG5vdyBjaGVjayBpZiBkYXRlcGlja2VyIGlzIHNob3dpbmcgb3V0c2lkZSB3aW5kb3cgdmlld3BvcnQgLSBtb3ZlIHRvIGEgYmV0dGVyIHBsYWNlIGlmIHNvLlxuXHRcdG9mZnNldC5sZWZ0IC09IE1hdGgubWluKG9mZnNldC5sZWZ0LCAob2Zmc2V0LmxlZnQgKyBkcFdpZHRoID4gdmlld1dpZHRoICYmIHZpZXdXaWR0aCA+IGRwV2lkdGgpID9cblx0XHRcdE1hdGguYWJzKG9mZnNldC5sZWZ0ICsgZHBXaWR0aCAtIHZpZXdXaWR0aCkgOiAwKTtcblx0XHRvZmZzZXQudG9wIC09IE1hdGgubWluKG9mZnNldC50b3AsIChvZmZzZXQudG9wICsgZHBIZWlnaHQgPiB2aWV3SGVpZ2h0ICYmIHZpZXdIZWlnaHQgPiBkcEhlaWdodCkgP1xuXHRcdFx0TWF0aC5hYnMoZHBIZWlnaHQgKyBpbnB1dEhlaWdodCkgOiAwKTtcblxuXHRcdHJldHVybiBvZmZzZXQ7XG5cdH0sXG5cblx0LyogRmluZCBhbiBvYmplY3QncyBwb3NpdGlvbiBvbiB0aGUgc2NyZWVuLiAqL1xuXHRfZmluZFBvczogZnVuY3Rpb24ob2JqKSB7XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KG9iaik7XG5cdFx0dmFyIGlzUlRMID0gdGhpcy5fZ2V0KGluc3QsICdpc1JUTCcpO1xuXHRcdHdoaWxlIChvYmogJiYgKG9iai50eXBlID09ICdoaWRkZW4nIHx8IG9iai5ub2RlVHlwZSAhPSAxIHx8ICQuZXhwci5maWx0ZXJzLmhpZGRlbihvYmopKSkge1xuXHRcdFx0b2JqID0gb2JqW2lzUlRMID8gJ3ByZXZpb3VzU2libGluZycgOiAnbmV4dFNpYmxpbmcnXTtcblx0XHR9XG5cdFx0dmFyIHBvc2l0aW9uID0gJChvYmopLm9mZnNldCgpO1xuXHRcdHJldHVybiBbcG9zaXRpb24ubGVmdCwgcG9zaXRpb24udG9wXTtcblx0fSxcblxuXHQvKiBIaWRlIHRoZSBkYXRlIHBpY2tlciBmcm9tIHZpZXcuXG5cdCAgIEBwYXJhbSAgaW5wdXQgIGVsZW1lbnQgLSB0aGUgaW5wdXQgZmllbGQgYXR0YWNoZWQgdG8gdGhlIGRhdGUgcGlja2VyICovXG5cdF9oaWRlRGF0ZXBpY2tlcjogZnVuY3Rpb24oaW5wdXQpIHtcblx0XHR2YXIgaW5zdCA9IHRoaXMuX2N1ckluc3Q7XG5cdFx0aWYgKCFpbnN0IHx8IChpbnB1dCAmJiBpbnN0ICE9ICQuZGF0YShpbnB1dCwgUFJPUF9OQU1FKSkpXG5cdFx0XHRyZXR1cm47XG5cdFx0aWYgKHRoaXMuX2RhdGVwaWNrZXJTaG93aW5nKSB7XG5cdFx0XHR2YXIgc2hvd0FuaW0gPSB0aGlzLl9nZXQoaW5zdCwgJ3Nob3dBbmltJyk7XG5cdFx0XHR2YXIgZHVyYXRpb24gPSB0aGlzLl9nZXQoaW5zdCwgJ2R1cmF0aW9uJyk7XG5cdFx0XHR2YXIgcG9zdFByb2Nlc3MgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0JC5kYXRlcGlja2VyLl90aWR5RGlhbG9nKGluc3QpO1xuXHRcdFx0fTtcblxuXHRcdFx0Ly8gREVQUkVDQVRFRDogYWZ0ZXIgQkMgZm9yIDEuOC54ICQuZWZmZWN0c1sgc2hvd0FuaW0gXSBpcyBub3QgbmVlZGVkXG5cdFx0XHRpZiAoICQuZWZmZWN0cyAmJiAoICQuZWZmZWN0cy5lZmZlY3RbIHNob3dBbmltIF0gfHwgJC5lZmZlY3RzWyBzaG93QW5pbSBdICkgKVxuXHRcdFx0XHRpbnN0LmRwRGl2LmhpZGUoc2hvd0FuaW0sICQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdzaG93T3B0aW9ucycpLCBkdXJhdGlvbiwgcG9zdFByb2Nlc3MpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRpbnN0LmRwRGl2WyhzaG93QW5pbSA9PSAnc2xpZGVEb3duJyA/ICdzbGlkZVVwJyA6XG5cdFx0XHRcdFx0KHNob3dBbmltID09ICdmYWRlSW4nID8gJ2ZhZGVPdXQnIDogJ2hpZGUnKSldKChzaG93QW5pbSA/IGR1cmF0aW9uIDogbnVsbCksIHBvc3RQcm9jZXNzKTtcblx0XHRcdGlmICghc2hvd0FuaW0pXG5cdFx0XHRcdHBvc3RQcm9jZXNzKCk7XG5cdFx0XHR0aGlzLl9kYXRlcGlja2VyU2hvd2luZyA9IGZhbHNlO1xuXHRcdFx0dmFyIG9uQ2xvc2UgPSB0aGlzLl9nZXQoaW5zdCwgJ29uQ2xvc2UnKTtcblx0XHRcdGlmIChvbkNsb3NlKVxuXHRcdFx0XHRvbkNsb3NlLmFwcGx5KChpbnN0LmlucHV0ID8gaW5zdC5pbnB1dFswXSA6IG51bGwpLFxuXHRcdFx0XHRcdFsoaW5zdC5pbnB1dCA/IGluc3QuaW5wdXQudmFsKCkgOiAnJyksIGluc3RdKTtcblx0XHRcdHRoaXMuX2xhc3RJbnB1dCA9IG51bGw7XG5cdFx0XHRpZiAodGhpcy5faW5EaWFsb2cpIHtcblx0XHRcdFx0dGhpcy5fZGlhbG9nSW5wdXQuY3NzKHsgcG9zaXRpb246ICdhYnNvbHV0ZScsIGxlZnQ6ICcwJywgdG9wOiAnLTEwMHB4JyB9KTtcblx0XHRcdFx0aWYgKCQuYmxvY2tVSSkge1xuXHRcdFx0XHRcdCQudW5ibG9ja1VJKCk7XG5cdFx0XHRcdFx0JCgnYm9keScpLmFwcGVuZCh0aGlzLmRwRGl2KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dGhpcy5faW5EaWFsb2cgPSBmYWxzZTtcblx0XHR9XG5cdH0sXG5cblx0LyogVGlkeSB1cCBhZnRlciBhIGRpYWxvZyBkaXNwbGF5LiAqL1xuXHRfdGlkeURpYWxvZzogZnVuY3Rpb24oaW5zdCkge1xuXHRcdGluc3QuZHBEaXYucmVtb3ZlQ2xhc3ModGhpcy5fZGlhbG9nQ2xhc3MpLnVuYmluZCgnLnVpLWRhdGVwaWNrZXItY2FsZW5kYXInKTtcblx0fSxcblxuXHQvKiBDbG9zZSBkYXRlIHBpY2tlciBpZiBjbGlja2VkIGVsc2V3aGVyZS4gKi9cblx0X2NoZWNrRXh0ZXJuYWxDbGljazogZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoISQuZGF0ZXBpY2tlci5fY3VySW5zdClcblx0XHRcdHJldHVybjtcblxuXHRcdHZhciAkdGFyZ2V0ID0gJChldmVudC50YXJnZXQpLFxuXHRcdFx0aW5zdCA9ICQuZGF0ZXBpY2tlci5fZ2V0SW5zdCgkdGFyZ2V0WzBdKTtcblxuXHRcdGlmICggKCAoICR0YXJnZXRbMF0uaWQgIT0gJC5kYXRlcGlja2VyLl9tYWluRGl2SWQgJiZcblx0XHRcdFx0JHRhcmdldC5wYXJlbnRzKCcjJyArICQuZGF0ZXBpY2tlci5fbWFpbkRpdklkKS5sZW5ndGggPT0gMCAmJlxuXHRcdFx0XHQhJHRhcmdldC5oYXNDbGFzcygkLmRhdGVwaWNrZXIubWFya2VyQ2xhc3NOYW1lKSAmJlxuXHRcdFx0XHQhJHRhcmdldC5jbG9zZXN0KFwiLlwiICsgJC5kYXRlcGlja2VyLl90cmlnZ2VyQ2xhc3MpLmxlbmd0aCAmJlxuXHRcdFx0XHQkLmRhdGVwaWNrZXIuX2RhdGVwaWNrZXJTaG93aW5nICYmICEoJC5kYXRlcGlja2VyLl9pbkRpYWxvZyAmJiAkLmJsb2NrVUkpICkgKSB8fFxuXHRcdFx0KCAkdGFyZ2V0Lmhhc0NsYXNzKCQuZGF0ZXBpY2tlci5tYXJrZXJDbGFzc05hbWUpICYmICQuZGF0ZXBpY2tlci5fY3VySW5zdCAhPSBpbnN0ICkgKVxuXHRcdFx0JC5kYXRlcGlja2VyLl9oaWRlRGF0ZXBpY2tlcigpO1xuXHR9LFxuXG5cdC8qIEFkanVzdCBvbmUgb2YgdGhlIGRhdGUgc3ViLWZpZWxkcy4gKi9cblx0X2FkanVzdERhdGU6IGZ1bmN0aW9uKGlkLCBvZmZzZXQsIHBlcmlvZCkge1xuXHRcdHZhciB0YXJnZXQgPSAkKGlkKTtcblx0XHR2YXIgaW5zdCA9IHRoaXMuX2dldEluc3QodGFyZ2V0WzBdKTtcblx0XHRpZiAodGhpcy5faXNEaXNhYmxlZERhdGVwaWNrZXIodGFyZ2V0WzBdKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLl9hZGp1c3RJbnN0RGF0ZShpbnN0LCBvZmZzZXQgK1xuXHRcdFx0KHBlcmlvZCA9PSAnTScgPyB0aGlzLl9nZXQoaW5zdCwgJ3Nob3dDdXJyZW50QXRQb3MnKSA6IDApLCAvLyB1bmRvIHBvc2l0aW9uaW5nXG5cdFx0XHRwZXJpb2QpO1xuXHRcdHRoaXMuX3VwZGF0ZURhdGVwaWNrZXIoaW5zdCk7XG5cdH0sXG5cblx0LyogQWN0aW9uIGZvciBjdXJyZW50IGxpbmsuICovXG5cdF9nb3RvVG9kYXk6IGZ1bmN0aW9uKGlkKSB7XG5cdFx0dmFyIHRhcmdldCA9ICQoaWQpO1xuXHRcdHZhciBpbnN0ID0gdGhpcy5fZ2V0SW5zdCh0YXJnZXRbMF0pO1xuXHRcdGlmICh0aGlzLl9nZXQoaW5zdCwgJ2dvdG9DdXJyZW50JykgJiYgaW5zdC5jdXJyZW50RGF5KSB7XG5cdFx0XHRpbnN0LnNlbGVjdGVkRGF5ID0gaW5zdC5jdXJyZW50RGF5O1xuXHRcdFx0aW5zdC5kcmF3TW9udGggPSBpbnN0LnNlbGVjdGVkTW9udGggPSBpbnN0LmN1cnJlbnRNb250aDtcblx0XHRcdGluc3QuZHJhd1llYXIgPSBpbnN0LnNlbGVjdGVkWWVhciA9IGluc3QuY3VycmVudFllYXI7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0dmFyIGRhdGUgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0aW5zdC5zZWxlY3RlZERheSA9IGRhdGUuZ2V0RGF0ZSgpO1xuXHRcdFx0aW5zdC5kcmF3TW9udGggPSBpbnN0LnNlbGVjdGVkTW9udGggPSBkYXRlLmdldE1vbnRoKCk7XG5cdFx0XHRpbnN0LmRyYXdZZWFyID0gaW5zdC5zZWxlY3RlZFllYXIgPSBkYXRlLmdldEZ1bGxZZWFyKCk7XG5cdFx0fVxuXHRcdHRoaXMuX25vdGlmeUNoYW5nZShpbnN0KTtcblx0XHR0aGlzLl9hZGp1c3REYXRlKHRhcmdldCk7XG5cdH0sXG5cblx0LyogQWN0aW9uIGZvciBzZWxlY3RpbmcgYSBuZXcgbW9udGgveWVhci4gKi9cblx0X3NlbGVjdE1vbnRoWWVhcjogZnVuY3Rpb24oaWQsIHNlbGVjdCwgcGVyaW9kKSB7XG5cdFx0dmFyIHRhcmdldCA9ICQoaWQpO1xuXHRcdHZhciBpbnN0ID0gdGhpcy5fZ2V0SW5zdCh0YXJnZXRbMF0pO1xuXHRcdGluc3RbJ3NlbGVjdGVkJyArIChwZXJpb2QgPT0gJ00nID8gJ01vbnRoJyA6ICdZZWFyJyldID1cblx0XHRpbnN0WydkcmF3JyArIChwZXJpb2QgPT0gJ00nID8gJ01vbnRoJyA6ICdZZWFyJyldID1cblx0XHRcdHBhcnNlSW50KHNlbGVjdC5vcHRpb25zW3NlbGVjdC5zZWxlY3RlZEluZGV4XS52YWx1ZSwxMCk7XG5cdFx0dGhpcy5fbm90aWZ5Q2hhbmdlKGluc3QpO1xuXHRcdHRoaXMuX2FkanVzdERhdGUodGFyZ2V0KTtcblx0fSxcblxuXHQvKiBBY3Rpb24gZm9yIHNlbGVjdGluZyBhIGRheS4gKi9cblx0X3NlbGVjdERheTogZnVuY3Rpb24oaWQsIG1vbnRoLCB5ZWFyLCB0ZCkge1xuXHRcdHZhciB0YXJnZXQgPSAkKGlkKTtcblx0XHRpZiAoJCh0ZCkuaGFzQ2xhc3ModGhpcy5fdW5zZWxlY3RhYmxlQ2xhc3MpIHx8IHRoaXMuX2lzRGlzYWJsZWREYXRlcGlja2VyKHRhcmdldFswXSkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KHRhcmdldFswXSk7XG5cdFx0aW5zdC5zZWxlY3RlZERheSA9IGluc3QuY3VycmVudERheSA9ICQoJ2EnLCB0ZCkuaHRtbCgpO1xuXHRcdGluc3Quc2VsZWN0ZWRNb250aCA9IGluc3QuY3VycmVudE1vbnRoID0gbW9udGg7XG5cdFx0aW5zdC5zZWxlY3RlZFllYXIgPSBpbnN0LmN1cnJlbnRZZWFyID0geWVhcjtcblx0XHR0aGlzLl9zZWxlY3REYXRlKGlkLCB0aGlzLl9mb3JtYXREYXRlKGluc3QsXG5cdFx0XHRpbnN0LmN1cnJlbnREYXksIGluc3QuY3VycmVudE1vbnRoLCBpbnN0LmN1cnJlbnRZZWFyKSk7XG5cdH0sXG5cblx0LyogRXJhc2UgdGhlIGlucHV0IGZpZWxkIGFuZCBoaWRlIHRoZSBkYXRlIHBpY2tlci4gKi9cblx0X2NsZWFyRGF0ZTogZnVuY3Rpb24oaWQpIHtcblx0XHR2YXIgdGFyZ2V0ID0gJChpZCk7XG5cdFx0dmFyIGluc3QgPSB0aGlzLl9nZXRJbnN0KHRhcmdldFswXSk7XG5cdFx0dGhpcy5fc2VsZWN0RGF0ZSh0YXJnZXQsICcnKTtcblx0fSxcblxuXHQvKiBVcGRhdGUgdGhlIGlucHV0IGZpZWxkIHdpdGggdGhlIHNlbGVjdGVkIGRhdGUuICovXG5cdF9zZWxlY3REYXRlOiBmdW5jdGlvbihpZCwgZGF0ZVN0cikge1xuXHRcdHZhciB0YXJnZXQgPSAkKGlkKTtcblx0XHR2YXIgaW5zdCA9IHRoaXMuX2dldEluc3QodGFyZ2V0WzBdKTtcblx0XHRkYXRlU3RyID0gKGRhdGVTdHIgIT0gbnVsbCA/IGRhdGVTdHIgOiB0aGlzLl9mb3JtYXREYXRlKGluc3QpKTtcblx0XHRpZiAoaW5zdC5pbnB1dClcblx0XHRcdGluc3QuaW5wdXQudmFsKGRhdGVTdHIpO1xuXHRcdHRoaXMuX3VwZGF0ZUFsdGVybmF0ZShpbnN0KTtcblx0XHR2YXIgb25TZWxlY3QgPSB0aGlzLl9nZXQoaW5zdCwgJ29uU2VsZWN0Jyk7XG5cdFx0aWYgKG9uU2VsZWN0KVxuXHRcdFx0b25TZWxlY3QuYXBwbHkoKGluc3QuaW5wdXQgPyBpbnN0LmlucHV0WzBdIDogbnVsbCksIFtkYXRlU3RyLCBpbnN0XSk7ICAvLyB0cmlnZ2VyIGN1c3RvbSBjYWxsYmFja1xuXHRcdGVsc2UgaWYgKGluc3QuaW5wdXQpXG5cdFx0XHRpbnN0LmlucHV0LnRyaWdnZXIoJ2NoYW5nZScpOyAvLyBmaXJlIHRoZSBjaGFuZ2UgZXZlbnRcblx0XHRpZiAoaW5zdC5pbmxpbmUpXG5cdFx0XHR0aGlzLl91cGRhdGVEYXRlcGlja2VyKGluc3QpO1xuXHRcdGVsc2Uge1xuXHRcdFx0dGhpcy5faGlkZURhdGVwaWNrZXIoKTtcblx0XHRcdHRoaXMuX2xhc3RJbnB1dCA9IGluc3QuaW5wdXRbMF07XG5cdFx0XHRpZiAodHlwZW9mKGluc3QuaW5wdXRbMF0pICE9ICdvYmplY3QnKVxuXHRcdFx0XHRpbnN0LmlucHV0LmZvY3VzKCk7IC8vIHJlc3RvcmUgZm9jdXNcblx0XHRcdHRoaXMuX2xhc3RJbnB1dCA9IG51bGw7XG5cdFx0fVxuXHR9LFxuXG5cdC8qIFVwZGF0ZSBhbnkgYWx0ZXJuYXRlIGZpZWxkIHRvIHN5bmNocm9uaXNlIHdpdGggdGhlIG1haW4gZmllbGQuICovXG5cdF91cGRhdGVBbHRlcm5hdGU6IGZ1bmN0aW9uKGluc3QpIHtcblx0XHR2YXIgYWx0RmllbGQgPSB0aGlzLl9nZXQoaW5zdCwgJ2FsdEZpZWxkJyk7XG5cdFx0aWYgKGFsdEZpZWxkKSB7IC8vIHVwZGF0ZSBhbHRlcm5hdGUgZmllbGQgdG9vXG5cdFx0XHR2YXIgYWx0Rm9ybWF0ID0gdGhpcy5fZ2V0KGluc3QsICdhbHRGb3JtYXQnKSB8fCB0aGlzLl9nZXQoaW5zdCwgJ2RhdGVGb3JtYXQnKTtcblx0XHRcdHZhciBkYXRlID0gdGhpcy5fZ2V0RGF0ZShpbnN0KTtcblx0XHRcdHZhciBkYXRlU3RyID0gdGhpcy5mb3JtYXREYXRlKGFsdEZvcm1hdCwgZGF0ZSwgdGhpcy5fZ2V0Rm9ybWF0Q29uZmlnKGluc3QpKTtcblx0XHRcdCQoYWx0RmllbGQpLmVhY2goZnVuY3Rpb24oKSB7ICQodGhpcykudmFsKGRhdGVTdHIpOyB9KTtcblx0XHR9XG5cdH0sXG5cblx0LyogU2V0IGFzIGJlZm9yZVNob3dEYXkgZnVuY3Rpb24gdG8gcHJldmVudCBzZWxlY3Rpb24gb2Ygd2Vla2VuZHMuXG5cdCAgIEBwYXJhbSAgZGF0ZSAgRGF0ZSAtIHRoZSBkYXRlIHRvIGN1c3RvbWlzZVxuXHQgICBAcmV0dXJuIFtib29sZWFuLCBzdHJpbmddIC0gaXMgdGhpcyBkYXRlIHNlbGVjdGFibGU/LCB3aGF0IGlzIGl0cyBDU1MgY2xhc3M/ICovXG5cdG5vV2Vla2VuZHM6IGZ1bmN0aW9uKGRhdGUpIHtcblx0XHR2YXIgZGF5ID0gZGF0ZS5nZXREYXkoKTtcblx0XHRyZXR1cm4gWyhkYXkgPiAwICYmIGRheSA8IDYpLCAnJ107XG5cdH0sXG5cblx0LyogU2V0IGFzIGNhbGN1bGF0ZVdlZWsgdG8gZGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGJhc2VkIG9uIHRoZSBJU08gODYwMSBkZWZpbml0aW9uLlxuXHQgICBAcGFyYW0gIGRhdGUgIERhdGUgLSB0aGUgZGF0ZSB0byBnZXQgdGhlIHdlZWsgZm9yXG5cdCAgIEByZXR1cm4gIG51bWJlciAtIHRoZSBudW1iZXIgb2YgdGhlIHdlZWsgd2l0aGluIHRoZSB5ZWFyIHRoYXQgY29udGFpbnMgdGhpcyBkYXRlICovXG5cdGlzbzg2MDFXZWVrOiBmdW5jdGlvbihkYXRlKSB7XG5cdFx0dmFyIGNoZWNrRGF0ZSA9IG5ldyBEYXRlKGRhdGUuZ2V0VGltZSgpKTtcblx0XHQvLyBGaW5kIFRodXJzZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBNb25kYXlcblx0XHRjaGVja0RhdGUuc2V0RGF0ZShjaGVja0RhdGUuZ2V0RGF0ZSgpICsgNCAtIChjaGVja0RhdGUuZ2V0RGF5KCkgfHwgNykpO1xuXHRcdHZhciB0aW1lID0gY2hlY2tEYXRlLmdldFRpbWUoKTtcblx0XHRjaGVja0RhdGUuc2V0TW9udGgoMCk7IC8vIENvbXBhcmUgd2l0aCBKYW4gMVxuXHRcdGNoZWNrRGF0ZS5zZXREYXRlKDEpO1xuXHRcdHJldHVybiBNYXRoLmZsb29yKE1hdGgucm91bmQoKHRpbWUgLSBjaGVja0RhdGUpIC8gODY0MDAwMDApIC8gNykgKyAxO1xuXHR9LFxuXG5cdC8qIFBhcnNlIGEgc3RyaW5nIHZhbHVlIGludG8gYSBkYXRlIG9iamVjdC5cblx0ICAgU2VlIGZvcm1hdERhdGUgYmVsb3cgZm9yIHRoZSBwb3NzaWJsZSBmb3JtYXRzLlxuXG5cdCAgIEBwYXJhbSAgZm9ybWF0ICAgIHN0cmluZyAtIHRoZSBleHBlY3RlZCBmb3JtYXQgb2YgdGhlIGRhdGVcblx0ICAgQHBhcmFtICB2YWx1ZSAgICAgc3RyaW5nIC0gdGhlIGRhdGUgaW4gdGhlIGFib3ZlIGZvcm1hdFxuXHQgICBAcGFyYW0gIHNldHRpbmdzICBPYmplY3QgLSBhdHRyaWJ1dGVzIGluY2x1ZGU6XG5cdCAgICAgICAgICAgICAgICAgICAgIHNob3J0WWVhckN1dG9mZiAgbnVtYmVyIC0gdGhlIGN1dG9mZiB5ZWFyIGZvciBkZXRlcm1pbmluZyB0aGUgY2VudHVyeSAob3B0aW9uYWwpXG5cdCAgICAgICAgICAgICAgICAgICAgIGRheU5hbWVzU2hvcnQgICAgc3RyaW5nWzddIC0gYWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkgKG9wdGlvbmFsKVxuXHQgICAgICAgICAgICAgICAgICAgICBkYXlOYW1lcyAgICAgICAgIHN0cmluZ1s3XSAtIG5hbWVzIG9mIHRoZSBkYXlzIGZyb20gU3VuZGF5IChvcHRpb25hbClcblx0ICAgICAgICAgICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0ICBzdHJpbmdbMTJdIC0gYWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIG1vbnRocyAob3B0aW9uYWwpXG5cdCAgICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXMgICAgICAgc3RyaW5nWzEyXSAtIG5hbWVzIG9mIHRoZSBtb250aHMgKG9wdGlvbmFsKVxuXHQgICBAcmV0dXJuICBEYXRlIC0gdGhlIGV4dHJhY3RlZCBkYXRlIHZhbHVlIG9yIG51bGwgaWYgdmFsdWUgaXMgYmxhbmsgKi9cblx0cGFyc2VEYXRlOiBmdW5jdGlvbiAoZm9ybWF0LCB2YWx1ZSwgc2V0dGluZ3MpIHtcblx0XHRpZiAoZm9ybWF0ID09IG51bGwgfHwgdmFsdWUgPT0gbnVsbClcblx0XHRcdHRocm93ICdJbnZhbGlkIGFyZ3VtZW50cyc7XG5cdFx0dmFsdWUgPSAodHlwZW9mIHZhbHVlID09ICdvYmplY3QnID8gdmFsdWUudG9TdHJpbmcoKSA6IHZhbHVlICsgJycpO1xuXHRcdGlmICh2YWx1ZSA9PSAnJylcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdHZhciBzaG9ydFllYXJDdXRvZmYgPSAoc2V0dGluZ3MgPyBzZXR0aW5ncy5zaG9ydFllYXJDdXRvZmYgOiBudWxsKSB8fCB0aGlzLl9kZWZhdWx0cy5zaG9ydFllYXJDdXRvZmY7XG5cdFx0c2hvcnRZZWFyQ3V0b2ZmID0gKHR5cGVvZiBzaG9ydFllYXJDdXRvZmYgIT0gJ3N0cmluZycgPyBzaG9ydFllYXJDdXRvZmYgOlxuXHRcdFx0XHRuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCkgJSAxMDAgKyBwYXJzZUludChzaG9ydFllYXJDdXRvZmYsIDEwKSk7XG5cdFx0dmFyIGRheU5hbWVzU2hvcnQgPSAoc2V0dGluZ3MgPyBzZXR0aW5ncy5kYXlOYW1lc1Nob3J0IDogbnVsbCkgfHwgdGhpcy5fZGVmYXVsdHMuZGF5TmFtZXNTaG9ydDtcblx0XHR2YXIgZGF5TmFtZXMgPSAoc2V0dGluZ3MgPyBzZXR0aW5ncy5kYXlOYW1lcyA6IG51bGwpIHx8IHRoaXMuX2RlZmF1bHRzLmRheU5hbWVzO1xuXHRcdHZhciBtb250aE5hbWVzU2hvcnQgPSAoc2V0dGluZ3MgPyBzZXR0aW5ncy5tb250aE5hbWVzU2hvcnQgOiBudWxsKSB8fCB0aGlzLl9kZWZhdWx0cy5tb250aE5hbWVzU2hvcnQ7XG5cdFx0dmFyIG1vbnRoTmFtZXMgPSAoc2V0dGluZ3MgPyBzZXR0aW5ncy5tb250aE5hbWVzIDogbnVsbCkgfHwgdGhpcy5fZGVmYXVsdHMubW9udGhOYW1lcztcblx0XHR2YXIgeWVhciA9IC0xO1xuXHRcdHZhciBtb250aCA9IC0xO1xuXHRcdHZhciBkYXkgPSAtMTtcblx0XHR2YXIgZG95ID0gLTE7XG5cdFx0dmFyIGxpdGVyYWwgPSBmYWxzZTtcblx0XHQvLyBDaGVjayB3aGV0aGVyIGEgZm9ybWF0IGNoYXJhY3RlciBpcyBkb3VibGVkXG5cdFx0dmFyIGxvb2tBaGVhZCA9IGZ1bmN0aW9uKG1hdGNoKSB7XG5cdFx0XHR2YXIgbWF0Y2hlcyA9IChpRm9ybWF0ICsgMSA8IGZvcm1hdC5sZW5ndGggJiYgZm9ybWF0LmNoYXJBdChpRm9ybWF0ICsgMSkgPT0gbWF0Y2gpO1xuXHRcdFx0aWYgKG1hdGNoZXMpXG5cdFx0XHRcdGlGb3JtYXQrKztcblx0XHRcdHJldHVybiBtYXRjaGVzO1xuXHRcdH07XG5cdFx0Ly8gRXh0cmFjdCBhIG51bWJlciBmcm9tIHRoZSBzdHJpbmcgdmFsdWVcblx0XHR2YXIgZ2V0TnVtYmVyID0gZnVuY3Rpb24obWF0Y2gpIHtcblx0XHRcdHZhciBpc0RvdWJsZWQgPSBsb29rQWhlYWQobWF0Y2gpO1xuXHRcdFx0dmFyIHNpemUgPSAobWF0Y2ggPT0gJ0AnID8gMTQgOiAobWF0Y2ggPT0gJyEnID8gMjAgOlxuXHRcdFx0XHQobWF0Y2ggPT0gJ3knICYmIGlzRG91YmxlZCA/IDQgOiAobWF0Y2ggPT0gJ28nID8gMyA6IDIpKSkpO1xuXHRcdFx0dmFyIGRpZ2l0cyA9IG5ldyBSZWdFeHAoJ15cXFxcZHsxLCcgKyBzaXplICsgJ30nKTtcblx0XHRcdHZhciBudW0gPSB2YWx1ZS5zdWJzdHJpbmcoaVZhbHVlKS5tYXRjaChkaWdpdHMpO1xuXHRcdFx0aWYgKCFudW0pXG5cdFx0XHRcdHRocm93ICdNaXNzaW5nIG51bWJlciBhdCBwb3NpdGlvbiAnICsgaVZhbHVlO1xuXHRcdFx0aVZhbHVlICs9IG51bVswXS5sZW5ndGg7XG5cdFx0XHRyZXR1cm4gcGFyc2VJbnQobnVtWzBdLCAxMCk7XG5cdFx0fTtcblx0XHQvLyBFeHRyYWN0IGEgbmFtZSBmcm9tIHRoZSBzdHJpbmcgdmFsdWUgYW5kIGNvbnZlcnQgdG8gYW4gaW5kZXhcblx0XHR2YXIgZ2V0TmFtZSA9IGZ1bmN0aW9uKG1hdGNoLCBzaG9ydE5hbWVzLCBsb25nTmFtZXMpIHtcblx0XHRcdHZhciBuYW1lcyA9ICQubWFwKGxvb2tBaGVhZChtYXRjaCkgPyBsb25nTmFtZXMgOiBzaG9ydE5hbWVzLCBmdW5jdGlvbiAodiwgaykge1xuXHRcdFx0XHRyZXR1cm4gWyBbaywgdl0gXTtcblx0XHRcdH0pLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcblx0XHRcdFx0cmV0dXJuIC0oYVsxXS5sZW5ndGggLSBiWzFdLmxlbmd0aCk7XG5cdFx0XHR9KTtcblx0XHRcdHZhciBpbmRleCA9IC0xO1xuXHRcdFx0JC5lYWNoKG5hbWVzLCBmdW5jdGlvbiAoaSwgcGFpcikge1xuXHRcdFx0XHR2YXIgbmFtZSA9IHBhaXJbMV07XG5cdFx0XHRcdGlmICh2YWx1ZS5zdWJzdHIoaVZhbHVlLCBuYW1lLmxlbmd0aCkudG9Mb3dlckNhc2UoKSA9PSBuYW1lLnRvTG93ZXJDYXNlKCkpIHtcblx0XHRcdFx0XHRpbmRleCA9IHBhaXJbMF07XG5cdFx0XHRcdFx0aVZhbHVlICs9IG5hbWUubGVuZ3RoO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAoaW5kZXggIT0gLTEpXG5cdFx0XHRcdHJldHVybiBpbmRleCArIDE7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHRocm93ICdVbmtub3duIG5hbWUgYXQgcG9zaXRpb24gJyArIGlWYWx1ZTtcblx0XHR9O1xuXHRcdC8vIENvbmZpcm0gdGhhdCBhIGxpdGVyYWwgY2hhcmFjdGVyIG1hdGNoZXMgdGhlIHN0cmluZyB2YWx1ZVxuXHRcdHZhciBjaGVja0xpdGVyYWwgPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICh2YWx1ZS5jaGFyQXQoaVZhbHVlKSAhPSBmb3JtYXQuY2hhckF0KGlGb3JtYXQpKVxuXHRcdFx0XHR0aHJvdyAnVW5leHBlY3RlZCBsaXRlcmFsIGF0IHBvc2l0aW9uICcgKyBpVmFsdWU7XG5cdFx0XHRpVmFsdWUrKztcblx0XHR9O1xuXHRcdHZhciBpVmFsdWUgPSAwO1xuXHRcdGZvciAodmFyIGlGb3JtYXQgPSAwOyBpRm9ybWF0IDwgZm9ybWF0Lmxlbmd0aDsgaUZvcm1hdCsrKSB7XG5cdFx0XHRpZiAobGl0ZXJhbClcblx0XHRcdFx0aWYgKGZvcm1hdC5jaGFyQXQoaUZvcm1hdCkgPT0gXCInXCIgJiYgIWxvb2tBaGVhZChcIidcIikpXG5cdFx0XHRcdFx0bGl0ZXJhbCA9IGZhbHNlO1xuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0Y2hlY2tMaXRlcmFsKCk7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHN3aXRjaCAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSkge1xuXHRcdFx0XHRcdGNhc2UgJ2QnOlxuXHRcdFx0XHRcdFx0ZGF5ID0gZ2V0TnVtYmVyKCdkJyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdEJzpcblx0XHRcdFx0XHRcdGdldE5hbWUoJ0QnLCBkYXlOYW1lc1Nob3J0LCBkYXlOYW1lcyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdvJzpcblx0XHRcdFx0XHRcdGRveSA9IGdldE51bWJlcignbycpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnbSc6XG5cdFx0XHRcdFx0XHRtb250aCA9IGdldE51bWJlcignbScpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnTSc6XG5cdFx0XHRcdFx0XHRtb250aCA9IGdldE5hbWUoJ00nLCBtb250aE5hbWVzU2hvcnQsIG1vbnRoTmFtZXMpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAneSc6XG5cdFx0XHRcdFx0XHR5ZWFyID0gZ2V0TnVtYmVyKCd5Jyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdAJzpcblx0XHRcdFx0XHRcdHZhciBkYXRlID0gbmV3IERhdGUoZ2V0TnVtYmVyKCdAJykpO1xuXHRcdFx0XHRcdFx0eWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcblx0XHRcdFx0XHRcdG1vbnRoID0gZGF0ZS5nZXRNb250aCgpICsgMTtcblx0XHRcdFx0XHRcdGRheSA9IGRhdGUuZ2V0RGF0ZSgpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnISc6XG5cdFx0XHRcdFx0XHR2YXIgZGF0ZSA9IG5ldyBEYXRlKChnZXROdW1iZXIoJyEnKSAtIHRoaXMuX3RpY2tzVG8xOTcwKSAvIDEwMDAwKTtcblx0XHRcdFx0XHRcdHllYXIgPSBkYXRlLmdldEZ1bGxZZWFyKCk7XG5cdFx0XHRcdFx0XHRtb250aCA9IGRhdGUuZ2V0TW9udGgoKSArIDE7XG5cdFx0XHRcdFx0XHRkYXkgPSBkYXRlLmdldERhdGUoKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCInXCI6XG5cdFx0XHRcdFx0XHRpZiAobG9va0FoZWFkKFwiJ1wiKSlcblx0XHRcdFx0XHRcdFx0Y2hlY2tMaXRlcmFsKCk7XG5cdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdGxpdGVyYWwgPSB0cnVlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdGNoZWNrTGl0ZXJhbCgpO1xuXHRcdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChpVmFsdWUgPCB2YWx1ZS5sZW5ndGgpe1xuXHRcdFx0dmFyIGV4dHJhID0gdmFsdWUuc3Vic3RyKGlWYWx1ZSk7XG5cdFx0XHRpZiAoIS9eXFxzKy8udGVzdChleHRyYSkpIHtcblx0XHRcdFx0dGhyb3cgXCJFeHRyYS91bnBhcnNlZCBjaGFyYWN0ZXJzIGZvdW5kIGluIGRhdGU6IFwiICsgZXh0cmE7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICh5ZWFyID09IC0xKVxuXHRcdFx0eWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKTtcblx0XHRlbHNlIGlmICh5ZWFyIDwgMTAwKVxuXHRcdFx0eWVhciArPSBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCkgLSBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCkgJSAxMDAgK1xuXHRcdFx0XHQoeWVhciA8PSBzaG9ydFllYXJDdXRvZmYgPyAwIDogLTEwMCk7XG5cdFx0aWYgKGRveSA+IC0xKSB7XG5cdFx0XHRtb250aCA9IDE7XG5cdFx0XHRkYXkgPSBkb3k7XG5cdFx0XHRkbyB7XG5cdFx0XHRcdHZhciBkaW0gPSB0aGlzLl9nZXREYXlzSW5Nb250aCh5ZWFyLCBtb250aCAtIDEpO1xuXHRcdFx0XHRpZiAoZGF5IDw9IGRpbSlcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0bW9udGgrKztcblx0XHRcdFx0ZGF5IC09IGRpbTtcblx0XHRcdH0gd2hpbGUgKHRydWUpO1xuXHRcdH1cblx0XHR2YXIgZGF0ZSA9IHRoaXMuX2RheWxpZ2h0U2F2aW5nQWRqdXN0KG5ldyBEYXRlKHllYXIsIG1vbnRoIC0gMSwgZGF5KSk7XG5cdFx0aWYgKGRhdGUuZ2V0RnVsbFllYXIoKSAhPSB5ZWFyIHx8IGRhdGUuZ2V0TW9udGgoKSArIDEgIT0gbW9udGggfHwgZGF0ZS5nZXREYXRlKCkgIT0gZGF5KVxuXHRcdFx0dGhyb3cgJ0ludmFsaWQgZGF0ZSc7IC8vIEUuZy4gMzEvMDIvMDBcblx0XHRyZXR1cm4gZGF0ZTtcblx0fSxcblxuXHQvKiBTdGFuZGFyZCBkYXRlIGZvcm1hdHMuICovXG5cdEFUT006ICd5eS1tbS1kZCcsIC8vIFJGQyAzMzM5IChJU08gODYwMSlcblx0Q09PS0lFOiAnRCwgZGQgTSB5eScsXG5cdElTT184NjAxOiAneXktbW0tZGQnLFxuXHRSRkNfODIyOiAnRCwgZCBNIHknLFxuXHRSRkNfODUwOiAnREQsIGRkLU0teScsXG5cdFJGQ18xMDM2OiAnRCwgZCBNIHknLFxuXHRSRkNfMTEyMzogJ0QsIGQgTSB5eScsXG5cdFJGQ18yODIyOiAnRCwgZCBNIHl5Jyxcblx0UlNTOiAnRCwgZCBNIHknLCAvLyBSRkMgODIyXG5cdFRJQ0tTOiAnIScsXG5cdFRJTUVTVEFNUDogJ0AnLFxuXHRXM0M6ICd5eS1tbS1kZCcsIC8vIElTTyA4NjAxXG5cblx0X3RpY2tzVG8xOTcwOiAoKCgxOTcwIC0gMSkgKiAzNjUgKyBNYXRoLmZsb29yKDE5NzAgLyA0KSAtIE1hdGguZmxvb3IoMTk3MCAvIDEwMCkgK1xuXHRcdE1hdGguZmxvb3IoMTk3MCAvIDQwMCkpICogMjQgKiA2MCAqIDYwICogMTAwMDAwMDApLFxuXG5cdC8qIEZvcm1hdCBhIGRhdGUgb2JqZWN0IGludG8gYSBzdHJpbmcgdmFsdWUuXG5cdCAgIFRoZSBmb3JtYXQgY2FuIGJlIGNvbWJpbmF0aW9ucyBvZiB0aGUgZm9sbG93aW5nOlxuXHQgICBkICAtIGRheSBvZiBtb250aCAobm8gbGVhZGluZyB6ZXJvKVxuXHQgICBkZCAtIGRheSBvZiBtb250aCAodHdvIGRpZ2l0KVxuXHQgICBvICAtIGRheSBvZiB5ZWFyIChubyBsZWFkaW5nIHplcm9zKVxuXHQgICBvbyAtIGRheSBvZiB5ZWFyICh0aHJlZSBkaWdpdClcblx0ICAgRCAgLSBkYXkgbmFtZSBzaG9ydFxuXHQgICBERCAtIGRheSBuYW1lIGxvbmdcblx0ICAgbSAgLSBtb250aCBvZiB5ZWFyIChubyBsZWFkaW5nIHplcm8pXG5cdCAgIG1tIC0gbW9udGggb2YgeWVhciAodHdvIGRpZ2l0KVxuXHQgICBNICAtIG1vbnRoIG5hbWUgc2hvcnRcblx0ICAgTU0gLSBtb250aCBuYW1lIGxvbmdcblx0ICAgeSAgLSB5ZWFyICh0d28gZGlnaXQpXG5cdCAgIHl5IC0geWVhciAoZm91ciBkaWdpdClcblx0ICAgQCAtIFVuaXggdGltZXN0YW1wIChtcyBzaW5jZSAwMS8wMS8xOTcwKVxuXHQgICAhIC0gV2luZG93cyB0aWNrcyAoMTAwbnMgc2luY2UgMDEvMDEvMDAwMSlcblx0ICAgJy4uLicgLSBsaXRlcmFsIHRleHRcblx0ICAgJycgLSBzaW5nbGUgcXVvdGVcblxuXHQgICBAcGFyYW0gIGZvcm1hdCAgICBzdHJpbmcgLSB0aGUgZGVzaXJlZCBmb3JtYXQgb2YgdGhlIGRhdGVcblx0ICAgQHBhcmFtICBkYXRlICAgICAgRGF0ZSAtIHRoZSBkYXRlIHZhbHVlIHRvIGZvcm1hdFxuXHQgICBAcGFyYW0gIHNldHRpbmdzICBPYmplY3QgLSBhdHRyaWJ1dGVzIGluY2x1ZGU6XG5cdCAgICAgICAgICAgICAgICAgICAgIGRheU5hbWVzU2hvcnQgICAgc3RyaW5nWzddIC0gYWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIGRheXMgZnJvbSBTdW5kYXkgKG9wdGlvbmFsKVxuXHQgICAgICAgICAgICAgICAgICAgICBkYXlOYW1lcyAgICAgICAgIHN0cmluZ1s3XSAtIG5hbWVzIG9mIHRoZSBkYXlzIGZyb20gU3VuZGF5IChvcHRpb25hbClcblx0ICAgICAgICAgICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0ICBzdHJpbmdbMTJdIC0gYWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIG1vbnRocyAob3B0aW9uYWwpXG5cdCAgICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXMgICAgICAgc3RyaW5nWzEyXSAtIG5hbWVzIG9mIHRoZSBtb250aHMgKG9wdGlvbmFsKVxuXHQgICBAcmV0dXJuICBzdHJpbmcgLSB0aGUgZGF0ZSBpbiB0aGUgYWJvdmUgZm9ybWF0ICovXG5cdGZvcm1hdERhdGU6IGZ1bmN0aW9uIChmb3JtYXQsIGRhdGUsIHNldHRpbmdzKSB7XG5cdFx0aWYgKCFkYXRlKVxuXHRcdFx0cmV0dXJuICcnO1xuXHRcdHZhciBkYXlOYW1lc1Nob3J0ID0gKHNldHRpbmdzID8gc2V0dGluZ3MuZGF5TmFtZXNTaG9ydCA6IG51bGwpIHx8IHRoaXMuX2RlZmF1bHRzLmRheU5hbWVzU2hvcnQ7XG5cdFx0dmFyIGRheU5hbWVzID0gKHNldHRpbmdzID8gc2V0dGluZ3MuZGF5TmFtZXMgOiBudWxsKSB8fCB0aGlzLl9kZWZhdWx0cy5kYXlOYW1lcztcblx0XHR2YXIgbW9udGhOYW1lc1Nob3J0ID0gKHNldHRpbmdzID8gc2V0dGluZ3MubW9udGhOYW1lc1Nob3J0IDogbnVsbCkgfHwgdGhpcy5fZGVmYXVsdHMubW9udGhOYW1lc1Nob3J0O1xuXHRcdHZhciBtb250aE5hbWVzID0gKHNldHRpbmdzID8gc2V0dGluZ3MubW9udGhOYW1lcyA6IG51bGwpIHx8IHRoaXMuX2RlZmF1bHRzLm1vbnRoTmFtZXM7XG5cdFx0Ly8gQ2hlY2sgd2hldGhlciBhIGZvcm1hdCBjaGFyYWN0ZXIgaXMgZG91YmxlZFxuXHRcdHZhciBsb29rQWhlYWQgPSBmdW5jdGlvbihtYXRjaCkge1xuXHRcdFx0dmFyIG1hdGNoZXMgPSAoaUZvcm1hdCArIDEgPCBmb3JtYXQubGVuZ3RoICYmIGZvcm1hdC5jaGFyQXQoaUZvcm1hdCArIDEpID09IG1hdGNoKTtcblx0XHRcdGlmIChtYXRjaGVzKVxuXHRcdFx0XHRpRm9ybWF0Kys7XG5cdFx0XHRyZXR1cm4gbWF0Y2hlcztcblx0XHR9O1xuXHRcdC8vIEZvcm1hdCBhIG51bWJlciwgd2l0aCBsZWFkaW5nIHplcm8gaWYgbmVjZXNzYXJ5XG5cdFx0dmFyIGZvcm1hdE51bWJlciA9IGZ1bmN0aW9uKG1hdGNoLCB2YWx1ZSwgbGVuKSB7XG5cdFx0XHR2YXIgbnVtID0gJycgKyB2YWx1ZTtcblx0XHRcdGlmIChsb29rQWhlYWQobWF0Y2gpKVxuXHRcdFx0XHR3aGlsZSAobnVtLmxlbmd0aCA8IGxlbilcblx0XHRcdFx0XHRudW0gPSAnMCcgKyBudW07XG5cdFx0XHRyZXR1cm4gbnVtO1xuXHRcdH07XG5cdFx0Ly8gRm9ybWF0IGEgbmFtZSwgc2hvcnQgb3IgbG9uZyBhcyByZXF1ZXN0ZWRcblx0XHR2YXIgZm9ybWF0TmFtZSA9IGZ1bmN0aW9uKG1hdGNoLCB2YWx1ZSwgc2hvcnROYW1lcywgbG9uZ05hbWVzKSB7XG5cdFx0XHRyZXR1cm4gKGxvb2tBaGVhZChtYXRjaCkgPyBsb25nTmFtZXNbdmFsdWVdIDogc2hvcnROYW1lc1t2YWx1ZV0pO1xuXHRcdH07XG5cdFx0dmFyIG91dHB1dCA9ICcnO1xuXHRcdHZhciBsaXRlcmFsID0gZmFsc2U7XG5cdFx0aWYgKGRhdGUpXG5cdFx0XHRmb3IgKHZhciBpRm9ybWF0ID0gMDsgaUZvcm1hdCA8IGZvcm1hdC5sZW5ndGg7IGlGb3JtYXQrKykge1xuXHRcdFx0XHRpZiAobGl0ZXJhbClcblx0XHRcdFx0XHRpZiAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSA9PSBcIidcIiAmJiAhbG9va0FoZWFkKFwiJ1wiKSlcblx0XHRcdFx0XHRcdGxpdGVyYWwgPSBmYWxzZTtcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRvdXRwdXQgKz0gZm9ybWF0LmNoYXJBdChpRm9ybWF0KTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHN3aXRjaCAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSkge1xuXHRcdFx0XHRcdFx0Y2FzZSAnZCc6XG5cdFx0XHRcdFx0XHRcdG91dHB1dCArPSBmb3JtYXROdW1iZXIoJ2QnLCBkYXRlLmdldERhdGUoKSwgMik7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAnRCc6XG5cdFx0XHRcdFx0XHRcdG91dHB1dCArPSBmb3JtYXROYW1lKCdEJywgZGF0ZS5nZXREYXkoKSwgZGF5TmFtZXNTaG9ydCwgZGF5TmFtZXMpO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgJ28nOlxuXHRcdFx0XHRcdFx0XHRvdXRwdXQgKz0gZm9ybWF0TnVtYmVyKCdvJyxcblx0XHRcdFx0XHRcdFx0XHRNYXRoLnJvdW5kKChuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCkpLmdldFRpbWUoKSAtIG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgMCwgMCkuZ2V0VGltZSgpKSAvIDg2NDAwMDAwKSwgMyk7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAnbSc6XG5cdFx0XHRcdFx0XHRcdG91dHB1dCArPSBmb3JtYXROdW1iZXIoJ20nLCBkYXRlLmdldE1vbnRoKCkgKyAxLCAyKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlICdNJzpcblx0XHRcdFx0XHRcdFx0b3V0cHV0ICs9IGZvcm1hdE5hbWUoJ00nLCBkYXRlLmdldE1vbnRoKCksIG1vbnRoTmFtZXNTaG9ydCwgbW9udGhOYW1lcyk7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAneSc6XG5cdFx0XHRcdFx0XHRcdG91dHB1dCArPSAobG9va0FoZWFkKCd5JykgPyBkYXRlLmdldEZ1bGxZZWFyKCkgOlxuXHRcdFx0XHRcdFx0XHRcdChkYXRlLmdldFllYXIoKSAlIDEwMCA8IDEwID8gJzAnIDogJycpICsgZGF0ZS5nZXRZZWFyKCkgJSAxMDApO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgJ0AnOlxuXHRcdFx0XHRcdFx0XHRvdXRwdXQgKz0gZGF0ZS5nZXRUaW1lKCk7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAnISc6XG5cdFx0XHRcdFx0XHRcdG91dHB1dCArPSBkYXRlLmdldFRpbWUoKSAqIDEwMDAwICsgdGhpcy5fdGlja3NUbzE5NzA7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSBcIidcIjpcblx0XHRcdFx0XHRcdFx0aWYgKGxvb2tBaGVhZChcIidcIikpXG5cdFx0XHRcdFx0XHRcdFx0b3V0cHV0ICs9IFwiJ1wiO1xuXHRcdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRcdFx0bGl0ZXJhbCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdFx0b3V0cHV0ICs9IGZvcm1hdC5jaGFyQXQoaUZvcm1hdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH0sXG5cblx0LyogRXh0cmFjdCBhbGwgcG9zc2libGUgY2hhcmFjdGVycyBmcm9tIHRoZSBkYXRlIGZvcm1hdC4gKi9cblx0X3Bvc3NpYmxlQ2hhcnM6IGZ1bmN0aW9uIChmb3JtYXQpIHtcblx0XHR2YXIgY2hhcnMgPSAnJztcblx0XHR2YXIgbGl0ZXJhbCA9IGZhbHNlO1xuXHRcdC8vIENoZWNrIHdoZXRoZXIgYSBmb3JtYXQgY2hhcmFjdGVyIGlzIGRvdWJsZWRcblx0XHR2YXIgbG9va0FoZWFkID0gZnVuY3Rpb24obWF0Y2gpIHtcblx0XHRcdHZhciBtYXRjaGVzID0gKGlGb3JtYXQgKyAxIDwgZm9ybWF0Lmxlbmd0aCAmJiBmb3JtYXQuY2hhckF0KGlGb3JtYXQgKyAxKSA9PSBtYXRjaCk7XG5cdFx0XHRpZiAobWF0Y2hlcylcblx0XHRcdFx0aUZvcm1hdCsrO1xuXHRcdFx0cmV0dXJuIG1hdGNoZXM7XG5cdFx0fTtcblx0XHRmb3IgKHZhciBpRm9ybWF0ID0gMDsgaUZvcm1hdCA8IGZvcm1hdC5sZW5ndGg7IGlGb3JtYXQrKylcblx0XHRcdGlmIChsaXRlcmFsKVxuXHRcdFx0XHRpZiAoZm9ybWF0LmNoYXJBdChpRm9ybWF0KSA9PSBcIidcIiAmJiAhbG9va0FoZWFkKFwiJ1wiKSlcblx0XHRcdFx0XHRsaXRlcmFsID0gZmFsc2U7XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRjaGFycyArPSBmb3JtYXQuY2hhckF0KGlGb3JtYXQpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRzd2l0Y2ggKGZvcm1hdC5jaGFyQXQoaUZvcm1hdCkpIHtcblx0XHRcdFx0XHRjYXNlICdkJzogY2FzZSAnbSc6IGNhc2UgJ3knOiBjYXNlICdAJzpcblx0XHRcdFx0XHRcdGNoYXJzICs9ICcwMTIzNDU2Nzg5Jztcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ0QnOiBjYXNlICdNJzpcblx0XHRcdFx0XHRcdHJldHVybiBudWxsOyAvLyBBY2NlcHQgYW55dGhpbmdcblx0XHRcdFx0XHRjYXNlIFwiJ1wiOlxuXHRcdFx0XHRcdFx0aWYgKGxvb2tBaGVhZChcIidcIikpXG5cdFx0XHRcdFx0XHRcdGNoYXJzICs9IFwiJ1wiO1xuXHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0XHRsaXRlcmFsID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHRjaGFycyArPSBmb3JtYXQuY2hhckF0KGlGb3JtYXQpO1xuXHRcdFx0XHR9XG5cdFx0cmV0dXJuIGNoYXJzO1xuXHR9LFxuXG5cdC8qIEdldCBhIHNldHRpbmcgdmFsdWUsIGRlZmF1bHRpbmcgaWYgbmVjZXNzYXJ5LiAqL1xuXHRfZ2V0OiBmdW5jdGlvbihpbnN0LCBuYW1lKSB7XG5cdFx0cmV0dXJuIGluc3Quc2V0dGluZ3NbbmFtZV0gIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRpbnN0LnNldHRpbmdzW25hbWVdIDogdGhpcy5fZGVmYXVsdHNbbmFtZV07XG5cdH0sXG5cblx0LyogUGFyc2UgZXhpc3RpbmcgZGF0ZSBhbmQgaW5pdGlhbGlzZSBkYXRlIHBpY2tlci4gKi9cblx0X3NldERhdGVGcm9tRmllbGQ6IGZ1bmN0aW9uKGluc3QsIG5vRGVmYXVsdCkge1xuXHRcdGlmIChpbnN0LmlucHV0LnZhbCgpID09IGluc3QubGFzdFZhbCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR2YXIgZGF0ZUZvcm1hdCA9IHRoaXMuX2dldChpbnN0LCAnZGF0ZUZvcm1hdCcpO1xuXHRcdHZhciBkYXRlcyA9IGluc3QubGFzdFZhbCA9IGluc3QuaW5wdXQgPyBpbnN0LmlucHV0LnZhbCgpIDogbnVsbDtcblx0XHR2YXIgZGF0ZSwgZGVmYXVsdERhdGU7XG5cdFx0ZGF0ZSA9IGRlZmF1bHREYXRlID0gdGhpcy5fZ2V0RGVmYXVsdERhdGUoaW5zdCk7XG5cdFx0dmFyIHNldHRpbmdzID0gdGhpcy5fZ2V0Rm9ybWF0Q29uZmlnKGluc3QpO1xuXHRcdHRyeSB7XG5cdFx0XHRkYXRlID0gdGhpcy5wYXJzZURhdGUoZGF0ZUZvcm1hdCwgZGF0ZXMsIHNldHRpbmdzKSB8fCBkZWZhdWx0RGF0ZTtcblx0XHR9IGNhdGNoIChldmVudCkge1xuXHRcdFx0dGhpcy5sb2coZXZlbnQpO1xuXHRcdFx0ZGF0ZXMgPSAobm9EZWZhdWx0ID8gJycgOiBkYXRlcyk7XG5cdFx0fVxuXHRcdGluc3Quc2VsZWN0ZWREYXkgPSBkYXRlLmdldERhdGUoKTtcblx0XHRpbnN0LmRyYXdNb250aCA9IGluc3Quc2VsZWN0ZWRNb250aCA9IGRhdGUuZ2V0TW9udGgoKTtcblx0XHRpbnN0LmRyYXdZZWFyID0gaW5zdC5zZWxlY3RlZFllYXIgPSBkYXRlLmdldEZ1bGxZZWFyKCk7XG5cdFx0aW5zdC5jdXJyZW50RGF5ID0gKGRhdGVzID8gZGF0ZS5nZXREYXRlKCkgOiAwKTtcblx0XHRpbnN0LmN1cnJlbnRNb250aCA9IChkYXRlcyA/IGRhdGUuZ2V0TW9udGgoKSA6IDApO1xuXHRcdGluc3QuY3VycmVudFllYXIgPSAoZGF0ZXMgPyBkYXRlLmdldEZ1bGxZZWFyKCkgOiAwKTtcblx0XHR0aGlzLl9hZGp1c3RJbnN0RGF0ZShpbnN0KTtcblx0fSxcblxuXHQvKiBSZXRyaWV2ZSB0aGUgZGVmYXVsdCBkYXRlIHNob3duIG9uIG9wZW5pbmcuICovXG5cdF9nZXREZWZhdWx0RGF0ZTogZnVuY3Rpb24oaW5zdCkge1xuXHRcdHJldHVybiB0aGlzLl9yZXN0cmljdE1pbk1heChpbnN0LFxuXHRcdFx0dGhpcy5fZGV0ZXJtaW5lRGF0ZShpbnN0LCB0aGlzLl9nZXQoaW5zdCwgJ2RlZmF1bHREYXRlJyksIG5ldyBEYXRlKCkpKTtcblx0fSxcblxuXHQvKiBBIGRhdGUgbWF5IGJlIHNwZWNpZmllZCBhcyBhbiBleGFjdCB2YWx1ZSBvciBhIHJlbGF0aXZlIG9uZS4gKi9cblx0X2RldGVybWluZURhdGU6IGZ1bmN0aW9uKGluc3QsIGRhdGUsIGRlZmF1bHREYXRlKSB7XG5cdFx0dmFyIG9mZnNldE51bWVyaWMgPSBmdW5jdGlvbihvZmZzZXQpIHtcblx0XHRcdHZhciBkYXRlID0gbmV3IERhdGUoKTtcblx0XHRcdGRhdGUuc2V0RGF0ZShkYXRlLmdldERhdGUoKSArIG9mZnNldCk7XG5cdFx0XHRyZXR1cm4gZGF0ZTtcblx0XHR9O1xuXHRcdHZhciBvZmZzZXRTdHJpbmcgPSBmdW5jdGlvbihvZmZzZXQpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHJldHVybiAkLmRhdGVwaWNrZXIucGFyc2VEYXRlKCQuZGF0ZXBpY2tlci5fZ2V0KGluc3QsICdkYXRlRm9ybWF0JyksXG5cdFx0XHRcdFx0b2Zmc2V0LCAkLmRhdGVwaWNrZXIuX2dldEZvcm1hdENvbmZpZyhpbnN0KSk7XG5cdFx0XHR9XG5cdFx0XHRjYXRjaCAoZSkge1xuXHRcdFx0XHQvLyBJZ25vcmVcblx0XHRcdH1cblx0XHRcdHZhciBkYXRlID0gKG9mZnNldC50b0xvd2VyQ2FzZSgpLm1hdGNoKC9eYy8pID9cblx0XHRcdFx0JC5kYXRlcGlja2VyLl9nZXREYXRlKGluc3QpIDogbnVsbCkgfHwgbmV3IERhdGUoKTtcblx0XHRcdHZhciB5ZWFyID0gZGF0ZS5nZXRGdWxsWWVhcigpO1xuXHRcdFx0dmFyIG1vbnRoID0gZGF0ZS5nZXRNb250aCgpO1xuXHRcdFx0dmFyIGRheSA9IGRhdGUuZ2V0RGF0ZSgpO1xuXHRcdFx0dmFyIHBhdHRlcm4gPSAvKFsrLV0/WzAtOV0rKVxccyooZHxEfHd8V3xtfE18eXxZKT8vZztcblx0XHRcdHZhciBtYXRjaGVzID0gcGF0dGVybi5leGVjKG9mZnNldCk7XG5cdFx0XHR3aGlsZSAobWF0Y2hlcykge1xuXHRcdFx0XHRzd2l0Y2ggKG1hdGNoZXNbMl0gfHwgJ2QnKSB7XG5cdFx0XHRcdFx0Y2FzZSAnZCcgOiBjYXNlICdEJyA6XG5cdFx0XHRcdFx0XHRkYXkgKz0gcGFyc2VJbnQobWF0Y2hlc1sxXSwxMCk7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3cnIDogY2FzZSAnVycgOlxuXHRcdFx0XHRcdFx0ZGF5ICs9IHBhcnNlSW50KG1hdGNoZXNbMV0sMTApICogNzsgYnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnbScgOiBjYXNlICdNJyA6XG5cdFx0XHRcdFx0XHRtb250aCArPSBwYXJzZUludChtYXRjaGVzWzFdLDEwKTtcblx0XHRcdFx0XHRcdGRheSA9IE1hdGgubWluKGRheSwgJC5kYXRlcGlja2VyLl9nZXREYXlzSW5Nb250aCh5ZWFyLCBtb250aCkpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAneSc6IGNhc2UgJ1knIDpcblx0XHRcdFx0XHRcdHllYXIgKz0gcGFyc2VJbnQobWF0Y2hlc1sxXSwxMCk7XG5cdFx0XHRcdFx0XHRkYXkgPSBNYXRoLm1pbihkYXksICQuZGF0ZXBpY2tlci5fZ2V0RGF5c0luTW9udGgoeWVhciwgbW9udGgpKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG1hdGNoZXMgPSBwYXR0ZXJuLmV4ZWMob2Zmc2V0KTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBuZXcgRGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcblx0XHR9O1xuXHRcdHZhciBuZXdEYXRlID0gKGRhdGUgPT0gbnVsbCB8fCBkYXRlID09PSAnJyA/IGRlZmF1bHREYXRlIDogKHR5cGVvZiBkYXRlID09ICdzdHJpbmcnID8gb2Zmc2V0U3RyaW5nKGRhdGUpIDpcblx0XHRcdCh0eXBlb2YgZGF0ZSA9PSAnbnVtYmVyJyA/IChpc05hTihkYXRlKSA/IGRlZmF1bHREYXRlIDogb2Zmc2V0TnVtZXJpYyhkYXRlKSkgOiBuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSkpKSk7XG5cdFx0bmV3RGF0ZSA9IChuZXdEYXRlICYmIG5ld0RhdGUudG9TdHJpbmcoKSA9PSAnSW52YWxpZCBEYXRlJyA/IGRlZmF1bHREYXRlIDogbmV3RGF0ZSk7XG5cdFx0aWYgKG5ld0RhdGUpIHtcblx0XHRcdG5ld0RhdGUuc2V0SG91cnMoMCk7XG5cdFx0XHRuZXdEYXRlLnNldE1pbnV0ZXMoMCk7XG5cdFx0XHRuZXdEYXRlLnNldFNlY29uZHMoMCk7XG5cdFx0XHRuZXdEYXRlLnNldE1pbGxpc2Vjb25kcygwKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuX2RheWxpZ2h0U2F2aW5nQWRqdXN0KG5ld0RhdGUpO1xuXHR9LFxuXG5cdC8qIEhhbmRsZSBzd2l0Y2ggdG8vZnJvbSBkYXlsaWdodCBzYXZpbmcuXG5cdCAgIEhvdXJzIG1heSBiZSBub24temVybyBvbiBkYXlsaWdodCBzYXZpbmcgY3V0LW92ZXI6XG5cdCAgID4gMTIgd2hlbiBtaWRuaWdodCBjaGFuZ2VvdmVyLCBidXQgdGhlbiBjYW5ub3QgZ2VuZXJhdGVcblx0ICAgbWlkbmlnaHQgZGF0ZXRpbWUsIHNvIGp1bXAgdG8gMUFNLCBvdGhlcndpc2UgcmVzZXQuXG5cdCAgIEBwYXJhbSAgZGF0ZSAgKERhdGUpIHRoZSBkYXRlIHRvIGNoZWNrXG5cdCAgIEByZXR1cm4gIChEYXRlKSB0aGUgY29ycmVjdGVkIGRhdGUgKi9cblx0X2RheWxpZ2h0U2F2aW5nQWRqdXN0OiBmdW5jdGlvbihkYXRlKSB7XG5cdFx0aWYgKCFkYXRlKSByZXR1cm4gbnVsbDtcblx0XHRkYXRlLnNldEhvdXJzKGRhdGUuZ2V0SG91cnMoKSA+IDEyID8gZGF0ZS5nZXRIb3VycygpICsgMiA6IDApO1xuXHRcdHJldHVybiBkYXRlO1xuXHR9LFxuXG5cdC8qIFNldCB0aGUgZGF0ZShzKSBkaXJlY3RseS4gKi9cblx0X3NldERhdGU6IGZ1bmN0aW9uKGluc3QsIGRhdGUsIG5vQ2hhbmdlKSB7XG5cdFx0dmFyIGNsZWFyID0gIWRhdGU7XG5cdFx0dmFyIG9yaWdNb250aCA9IGluc3Quc2VsZWN0ZWRNb250aDtcblx0XHR2YXIgb3JpZ1llYXIgPSBpbnN0LnNlbGVjdGVkWWVhcjtcblx0XHR2YXIgbmV3RGF0ZSA9IHRoaXMuX3Jlc3RyaWN0TWluTWF4KGluc3QsIHRoaXMuX2RldGVybWluZURhdGUoaW5zdCwgZGF0ZSwgbmV3IERhdGUoKSkpO1xuXHRcdGluc3Quc2VsZWN0ZWREYXkgPSBpbnN0LmN1cnJlbnREYXkgPSBuZXdEYXRlLmdldERhdGUoKTtcblx0XHRpbnN0LmRyYXdNb250aCA9IGluc3Quc2VsZWN0ZWRNb250aCA9IGluc3QuY3VycmVudE1vbnRoID0gbmV3RGF0ZS5nZXRNb250aCgpO1xuXHRcdGluc3QuZHJhd1llYXIgPSBpbnN0LnNlbGVjdGVkWWVhciA9IGluc3QuY3VycmVudFllYXIgPSBuZXdEYXRlLmdldEZ1bGxZZWFyKCk7XG5cdFx0aWYgKChvcmlnTW9udGggIT0gaW5zdC5zZWxlY3RlZE1vbnRoIHx8IG9yaWdZZWFyICE9IGluc3Quc2VsZWN0ZWRZZWFyKSAmJiAhbm9DaGFuZ2UpXG5cdFx0XHR0aGlzLl9ub3RpZnlDaGFuZ2UoaW5zdCk7XG5cdFx0dGhpcy5fYWRqdXN0SW5zdERhdGUoaW5zdCk7XG5cdFx0aWYgKGluc3QuaW5wdXQpIHtcblx0XHRcdGluc3QuaW5wdXQudmFsKGNsZWFyID8gJycgOiB0aGlzLl9mb3JtYXREYXRlKGluc3QpKTtcblx0XHR9XG5cdH0sXG5cblx0LyogUmV0cmlldmUgdGhlIGRhdGUocykgZGlyZWN0bHkuICovXG5cdF9nZXREYXRlOiBmdW5jdGlvbihpbnN0KSB7XG5cdFx0dmFyIHN0YXJ0RGF0ZSA9ICghaW5zdC5jdXJyZW50WWVhciB8fCAoaW5zdC5pbnB1dCAmJiBpbnN0LmlucHV0LnZhbCgpID09ICcnKSA/IG51bGwgOlxuXHRcdFx0dGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoXG5cdFx0XHRpbnN0LmN1cnJlbnRZZWFyLCBpbnN0LmN1cnJlbnRNb250aCwgaW5zdC5jdXJyZW50RGF5KSkpO1xuXHRcdFx0cmV0dXJuIHN0YXJ0RGF0ZTtcblx0fSxcblxuXHQvKiBBdHRhY2ggdGhlIG9ueHh4IGhhbmRsZXJzLiAgVGhlc2UgYXJlIGRlY2xhcmVkIHN0YXRpY2FsbHkgc29cblx0ICogdGhleSB3b3JrIHdpdGggc3RhdGljIGNvZGUgdHJhbnNmb3JtZXJzIGxpa2UgQ2FqYS5cblx0ICovXG5cdF9hdHRhY2hIYW5kbGVyczogZnVuY3Rpb24oaW5zdCkge1xuXHRcdHZhciBzdGVwTW9udGhzID0gdGhpcy5fZ2V0KGluc3QsICdzdGVwTW9udGhzJyk7XG5cdFx0dmFyIGlkID0gJyMnICsgaW5zdC5pZC5yZXBsYWNlKCAvXFxcXFxcXFwvZywgXCJcXFxcXCIgKTtcblx0XHRpbnN0LmRwRGl2LmZpbmQoJ1tkYXRhLWhhbmRsZXJdJykubWFwKGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBoYW5kbGVyID0ge1xuXHRcdFx0XHRwcmV2OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0d2luZG93WydEUF9qUXVlcnlfJyArIGRwdXVpZF0uZGF0ZXBpY2tlci5fYWRqdXN0RGF0ZShpZCwgLXN0ZXBNb250aHMsICdNJyk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG5leHQ6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHR3aW5kb3dbJ0RQX2pRdWVyeV8nICsgZHB1dWlkXS5kYXRlcGlja2VyLl9hZGp1c3REYXRlKGlkLCArc3RlcE1vbnRocywgJ00nKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0aGlkZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHdpbmRvd1snRFBfalF1ZXJ5XycgKyBkcHV1aWRdLmRhdGVwaWNrZXIuX2hpZGVEYXRlcGlja2VyKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRvZGF5OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0d2luZG93WydEUF9qUXVlcnlfJyArIGRwdXVpZF0uZGF0ZXBpY2tlci5fZ290b1RvZGF5KGlkKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0c2VsZWN0RGF5OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0d2luZG93WydEUF9qUXVlcnlfJyArIGRwdXVpZF0uZGF0ZXBpY2tlci5fc2VsZWN0RGF5KGlkLCArdGhpcy5nZXRBdHRyaWJ1dGUoJ2RhdGEtbW9udGgnKSwgK3RoaXMuZ2V0QXR0cmlidXRlKCdkYXRhLXllYXInKSwgdGhpcyk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRzZWxlY3RNb250aDogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHdpbmRvd1snRFBfalF1ZXJ5XycgKyBkcHV1aWRdLmRhdGVwaWNrZXIuX3NlbGVjdE1vbnRoWWVhcihpZCwgdGhpcywgJ00nKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHNlbGVjdFllYXI6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHR3aW5kb3dbJ0RQX2pRdWVyeV8nICsgZHB1dWlkXS5kYXRlcGlja2VyLl9zZWxlY3RNb250aFllYXIoaWQsIHRoaXMsICdZJyk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0JCh0aGlzKS5iaW5kKHRoaXMuZ2V0QXR0cmlidXRlKCdkYXRhLWV2ZW50JyksIGhhbmRsZXJbdGhpcy5nZXRBdHRyaWJ1dGUoJ2RhdGEtaGFuZGxlcicpXSk7XG5cdFx0fSk7XG5cdH0sXG5cblx0LyogR2VuZXJhdGUgdGhlIEhUTUwgZm9yIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBkYXRlIHBpY2tlci4gKi9cblx0X2dlbmVyYXRlSFRNTDogZnVuY3Rpb24oaW5zdCkge1xuXHRcdHZhciB0b2RheSA9IG5ldyBEYXRlKCk7XG5cdFx0dG9kYXkgPSB0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChcblx0XHRcdG5ldyBEYXRlKHRvZGF5LmdldEZ1bGxZZWFyKCksIHRvZGF5LmdldE1vbnRoKCksIHRvZGF5LmdldERhdGUoKSkpOyAvLyBjbGVhciB0aW1lXG5cdFx0dmFyIGlzUlRMID0gdGhpcy5fZ2V0KGluc3QsICdpc1JUTCcpO1xuXHRcdHZhciBzaG93QnV0dG9uUGFuZWwgPSB0aGlzLl9nZXQoaW5zdCwgJ3Nob3dCdXR0b25QYW5lbCcpO1xuXHRcdHZhciBoaWRlSWZOb1ByZXZOZXh0ID0gdGhpcy5fZ2V0KGluc3QsICdoaWRlSWZOb1ByZXZOZXh0Jyk7XG5cdFx0dmFyIG5hdmlnYXRpb25Bc0RhdGVGb3JtYXQgPSB0aGlzLl9nZXQoaW5zdCwgJ25hdmlnYXRpb25Bc0RhdGVGb3JtYXQnKTtcblx0XHR2YXIgbnVtTW9udGhzID0gdGhpcy5fZ2V0TnVtYmVyT2ZNb250aHMoaW5zdCk7XG5cdFx0dmFyIHNob3dDdXJyZW50QXRQb3MgPSB0aGlzLl9nZXQoaW5zdCwgJ3Nob3dDdXJyZW50QXRQb3MnKTtcblx0XHR2YXIgc3RlcE1vbnRocyA9IHRoaXMuX2dldChpbnN0LCAnc3RlcE1vbnRocycpO1xuXHRcdHZhciBpc011bHRpTW9udGggPSAobnVtTW9udGhzWzBdICE9IDEgfHwgbnVtTW9udGhzWzFdICE9IDEpO1xuXHRcdHZhciBjdXJyZW50RGF0ZSA9IHRoaXMuX2RheWxpZ2h0U2F2aW5nQWRqdXN0KCghaW5zdC5jdXJyZW50RGF5ID8gbmV3IERhdGUoOTk5OSwgOSwgOSkgOlxuXHRcdFx0bmV3IERhdGUoaW5zdC5jdXJyZW50WWVhciwgaW5zdC5jdXJyZW50TW9udGgsIGluc3QuY3VycmVudERheSkpKTtcblx0XHR2YXIgbWluRGF0ZSA9IHRoaXMuX2dldE1pbk1heERhdGUoaW5zdCwgJ21pbicpO1xuXHRcdHZhciBtYXhEYXRlID0gdGhpcy5fZ2V0TWluTWF4RGF0ZShpbnN0LCAnbWF4Jyk7XG5cdFx0dmFyIGRyYXdNb250aCA9IGluc3QuZHJhd01vbnRoIC0gc2hvd0N1cnJlbnRBdFBvcztcblx0XHR2YXIgZHJhd1llYXIgPSBpbnN0LmRyYXdZZWFyO1xuXHRcdGlmIChkcmF3TW9udGggPCAwKSB7XG5cdFx0XHRkcmF3TW9udGggKz0gMTI7XG5cdFx0XHRkcmF3WWVhci0tO1xuXHRcdH1cblx0XHRpZiAobWF4RGF0ZSkge1xuXHRcdFx0dmFyIG1heERyYXcgPSB0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZShtYXhEYXRlLmdldEZ1bGxZZWFyKCksXG5cdFx0XHRcdG1heERhdGUuZ2V0TW9udGgoKSAtIChudW1Nb250aHNbMF0gKiBudW1Nb250aHNbMV0pICsgMSwgbWF4RGF0ZS5nZXREYXRlKCkpKTtcblx0XHRcdG1heERyYXcgPSAobWluRGF0ZSAmJiBtYXhEcmF3IDwgbWluRGF0ZSA/IG1pbkRhdGUgOiBtYXhEcmF3KTtcblx0XHRcdHdoaWxlICh0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZShkcmF3WWVhciwgZHJhd01vbnRoLCAxKSkgPiBtYXhEcmF3KSB7XG5cdFx0XHRcdGRyYXdNb250aC0tO1xuXHRcdFx0XHRpZiAoZHJhd01vbnRoIDwgMCkge1xuXHRcdFx0XHRcdGRyYXdNb250aCA9IDExO1xuXHRcdFx0XHRcdGRyYXdZZWFyLS07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0aW5zdC5kcmF3TW9udGggPSBkcmF3TW9udGg7XG5cdFx0aW5zdC5kcmF3WWVhciA9IGRyYXdZZWFyO1xuXHRcdHZhciBwcmV2VGV4dCA9IHRoaXMuX2dldChpbnN0LCAncHJldlRleHQnKTtcblx0XHRwcmV2VGV4dCA9ICghbmF2aWdhdGlvbkFzRGF0ZUZvcm1hdCA/IHByZXZUZXh0IDogdGhpcy5mb3JtYXREYXRlKHByZXZUZXh0LFxuXHRcdFx0dGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoZHJhd1llYXIsIGRyYXdNb250aCAtIHN0ZXBNb250aHMsIDEpKSxcblx0XHRcdHRoaXMuX2dldEZvcm1hdENvbmZpZyhpbnN0KSkpO1xuXHRcdHZhciBwcmV2ID0gKHRoaXMuX2NhbkFkanVzdE1vbnRoKGluc3QsIC0xLCBkcmF3WWVhciwgZHJhd01vbnRoKSA/XG5cdFx0XHQnPGEgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLXByZXYgdWktY29ybmVyLWFsbFwiIGRhdGEtaGFuZGxlcj1cInByZXZcIiBkYXRhLWV2ZW50PVwiY2xpY2tcIicgK1xuXHRcdFx0JyB0aXRsZT1cIicgKyBwcmV2VGV4dCArICdcIj48c3BhbiBjbGFzcz1cInVpLWljb24gdWktaWNvbi1jaXJjbGUtdHJpYW5nbGUtJyArICggaXNSVEwgPyAnZScgOiAndycpICsgJ1wiPicgKyBwcmV2VGV4dCArICc8L3NwYW4+PC9hPicgOlxuXHRcdFx0KGhpZGVJZk5vUHJldk5leHQgPyAnJyA6ICc8YSBjbGFzcz1cInVpLWRhdGVwaWNrZXItcHJldiB1aS1jb3JuZXItYWxsIHVpLXN0YXRlLWRpc2FibGVkXCIgdGl0bGU9XCInKyBwcmV2VGV4dCArJ1wiPjxzcGFuIGNsYXNzPVwidWktaWNvbiB1aS1pY29uLWNpcmNsZS10cmlhbmdsZS0nICsgKCBpc1JUTCA/ICdlJyA6ICd3JykgKyAnXCI+JyArIHByZXZUZXh0ICsgJzwvc3Bhbj48L2E+JykpO1xuXHRcdHZhciBuZXh0VGV4dCA9IHRoaXMuX2dldChpbnN0LCAnbmV4dFRleHQnKTtcblx0XHRuZXh0VGV4dCA9ICghbmF2aWdhdGlvbkFzRGF0ZUZvcm1hdCA/IG5leHRUZXh0IDogdGhpcy5mb3JtYXREYXRlKG5leHRUZXh0LFxuXHRcdFx0dGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoZHJhd1llYXIsIGRyYXdNb250aCArIHN0ZXBNb250aHMsIDEpKSxcblx0XHRcdHRoaXMuX2dldEZvcm1hdENvbmZpZyhpbnN0KSkpO1xuXHRcdHZhciBuZXh0ID0gKHRoaXMuX2NhbkFkanVzdE1vbnRoKGluc3QsICsxLCBkcmF3WWVhciwgZHJhd01vbnRoKSA/XG5cdFx0XHQnPGEgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLW5leHQgdWktY29ybmVyLWFsbFwiIGRhdGEtaGFuZGxlcj1cIm5leHRcIiBkYXRhLWV2ZW50PVwiY2xpY2tcIicgK1xuXHRcdFx0JyB0aXRsZT1cIicgKyBuZXh0VGV4dCArICdcIj48c3BhbiBjbGFzcz1cInVpLWljb24gdWktaWNvbi1jaXJjbGUtdHJpYW5nbGUtJyArICggaXNSVEwgPyAndycgOiAnZScpICsgJ1wiPicgKyBuZXh0VGV4dCArICc8L3NwYW4+PC9hPicgOlxuXHRcdFx0KGhpZGVJZk5vUHJldk5leHQgPyAnJyA6ICc8YSBjbGFzcz1cInVpLWRhdGVwaWNrZXItbmV4dCB1aS1jb3JuZXItYWxsIHVpLXN0YXRlLWRpc2FibGVkXCIgdGl0bGU9XCInKyBuZXh0VGV4dCArICdcIj48c3BhbiBjbGFzcz1cInVpLWljb24gdWktaWNvbi1jaXJjbGUtdHJpYW5nbGUtJyArICggaXNSVEwgPyAndycgOiAnZScpICsgJ1wiPicgKyBuZXh0VGV4dCArICc8L3NwYW4+PC9hPicpKTtcblx0XHR2YXIgY3VycmVudFRleHQgPSB0aGlzLl9nZXQoaW5zdCwgJ2N1cnJlbnRUZXh0Jyk7XG5cdFx0dmFyIGdvdG9EYXRlID0gKHRoaXMuX2dldChpbnN0LCAnZ290b0N1cnJlbnQnKSAmJiBpbnN0LmN1cnJlbnREYXkgPyBjdXJyZW50RGF0ZSA6IHRvZGF5KTtcblx0XHRjdXJyZW50VGV4dCA9ICghbmF2aWdhdGlvbkFzRGF0ZUZvcm1hdCA/IGN1cnJlbnRUZXh0IDpcblx0XHRcdHRoaXMuZm9ybWF0RGF0ZShjdXJyZW50VGV4dCwgZ290b0RhdGUsIHRoaXMuX2dldEZvcm1hdENvbmZpZyhpbnN0KSkpO1xuXHRcdHZhciBjb250cm9scyA9ICghaW5zdC5pbmxpbmUgPyAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLWNsb3NlIHVpLXN0YXRlLWRlZmF1bHQgdWktcHJpb3JpdHktcHJpbWFyeSB1aS1jb3JuZXItYWxsXCIgZGF0YS1oYW5kbGVyPVwiaGlkZVwiIGRhdGEtZXZlbnQ9XCJjbGlja1wiPicgK1xuXHRcdFx0dGhpcy5fZ2V0KGluc3QsICdjbG9zZVRleHQnKSArICc8L2J1dHRvbj4nIDogJycpO1xuXHRcdHZhciBidXR0b25QYW5lbCA9IChzaG93QnV0dG9uUGFuZWwpID8gJzxkaXYgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLWJ1dHRvbnBhbmUgdWktd2lkZ2V0LWNvbnRlbnRcIj4nICsgKGlzUlRMID8gY29udHJvbHMgOiAnJykgK1xuXHRcdFx0KHRoaXMuX2lzSW5SYW5nZShpbnN0LCBnb3RvRGF0ZSkgPyAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLWN1cnJlbnQgdWktc3RhdGUtZGVmYXVsdCB1aS1wcmlvcml0eS1zZWNvbmRhcnkgdWktY29ybmVyLWFsbFwiIGRhdGEtaGFuZGxlcj1cInRvZGF5XCIgZGF0YS1ldmVudD1cImNsaWNrXCInICtcblx0XHRcdCc+JyArIGN1cnJlbnRUZXh0ICsgJzwvYnV0dG9uPicgOiAnJykgKyAoaXNSVEwgPyAnJyA6IGNvbnRyb2xzKSArICc8L2Rpdj4nIDogJyc7XG5cdFx0dmFyIGZpcnN0RGF5ID0gcGFyc2VJbnQodGhpcy5fZ2V0KGluc3QsICdmaXJzdERheScpLDEwKTtcblx0XHRmaXJzdERheSA9IChpc05hTihmaXJzdERheSkgPyAwIDogZmlyc3REYXkpO1xuXHRcdHZhciBzaG93V2VlayA9IHRoaXMuX2dldChpbnN0LCAnc2hvd1dlZWsnKTtcblx0XHR2YXIgZGF5TmFtZXMgPSB0aGlzLl9nZXQoaW5zdCwgJ2RheU5hbWVzJyk7XG5cdFx0dmFyIGRheU5hbWVzU2hvcnQgPSB0aGlzLl9nZXQoaW5zdCwgJ2RheU5hbWVzU2hvcnQnKTtcblx0XHR2YXIgZGF5TmFtZXNNaW4gPSB0aGlzLl9nZXQoaW5zdCwgJ2RheU5hbWVzTWluJyk7XG5cdFx0dmFyIG1vbnRoTmFtZXMgPSB0aGlzLl9nZXQoaW5zdCwgJ21vbnRoTmFtZXMnKTtcblx0XHR2YXIgbW9udGhOYW1lc1Nob3J0ID0gdGhpcy5fZ2V0KGluc3QsICdtb250aE5hbWVzU2hvcnQnKTtcblx0XHR2YXIgYmVmb3JlU2hvd0RheSA9IHRoaXMuX2dldChpbnN0LCAnYmVmb3JlU2hvd0RheScpO1xuXHRcdHZhciBzaG93T3RoZXJNb250aHMgPSB0aGlzLl9nZXQoaW5zdCwgJ3Nob3dPdGhlck1vbnRocycpO1xuXHRcdHZhciBzZWxlY3RPdGhlck1vbnRocyA9IHRoaXMuX2dldChpbnN0LCAnc2VsZWN0T3RoZXJNb250aHMnKTtcblx0XHR2YXIgY2FsY3VsYXRlV2VlayA9IHRoaXMuX2dldChpbnN0LCAnY2FsY3VsYXRlV2VlaycpIHx8IHRoaXMuaXNvODYwMVdlZWs7XG5cdFx0dmFyIGRlZmF1bHREYXRlID0gdGhpcy5fZ2V0RGVmYXVsdERhdGUoaW5zdCk7XG5cdFx0dmFyIGh0bWwgPSAnJztcblx0XHRmb3IgKHZhciByb3cgPSAwOyByb3cgPCBudW1Nb250aHNbMF07IHJvdysrKSB7XG5cdFx0XHR2YXIgZ3JvdXAgPSAnJztcblx0XHRcdHRoaXMubWF4Um93cyA9IDQ7XG5cdFx0XHRmb3IgKHZhciBjb2wgPSAwOyBjb2wgPCBudW1Nb250aHNbMV07IGNvbCsrKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZERhdGUgPSB0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZShkcmF3WWVhciwgZHJhd01vbnRoLCBpbnN0LnNlbGVjdGVkRGF5KSk7XG5cdFx0XHRcdHZhciBjb3JuZXJDbGFzcyA9ICcgdWktY29ybmVyLWFsbCc7XG5cdFx0XHRcdHZhciBjYWxlbmRlciA9ICcnO1xuXHRcdFx0XHRpZiAoaXNNdWx0aU1vbnRoKSB7XG5cdFx0XHRcdFx0Y2FsZW5kZXIgKz0gJzxkaXYgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLWdyb3VwJztcblx0XHRcdFx0XHRpZiAobnVtTW9udGhzWzFdID4gMSlcblx0XHRcdFx0XHRcdHN3aXRjaCAoY29sKSB7XG5cdFx0XHRcdFx0XHRcdGNhc2UgMDogY2FsZW5kZXIgKz0gJyB1aS1kYXRlcGlja2VyLWdyb3VwLWZpcnN0Jztcblx0XHRcdFx0XHRcdFx0XHRjb3JuZXJDbGFzcyA9ICcgdWktY29ybmVyLScgKyAoaXNSVEwgPyAncmlnaHQnIDogJ2xlZnQnKTsgYnJlYWs7XG5cdFx0XHRcdFx0XHRcdGNhc2UgbnVtTW9udGhzWzFdLTE6IGNhbGVuZGVyICs9ICcgdWktZGF0ZXBpY2tlci1ncm91cC1sYXN0Jztcblx0XHRcdFx0XHRcdFx0XHRjb3JuZXJDbGFzcyA9ICcgdWktY29ybmVyLScgKyAoaXNSVEwgPyAnbGVmdCcgOiAncmlnaHQnKTsgYnJlYWs7XG5cdFx0XHRcdFx0XHRcdGRlZmF1bHQ6IGNhbGVuZGVyICs9ICcgdWktZGF0ZXBpY2tlci1ncm91cC1taWRkbGUnOyBjb3JuZXJDbGFzcyA9ICcnOyBicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjYWxlbmRlciArPSAnXCI+Jztcblx0XHRcdFx0fVxuXHRcdFx0XHRjYWxlbmRlciArPSAnPGRpdiBjbGFzcz1cInVpLWRhdGVwaWNrZXItaGVhZGVyIHVpLXdpZGdldC1oZWFkZXIgdWktaGVscGVyLWNsZWFyZml4JyArIGNvcm5lckNsYXNzICsgJ1wiPicgK1xuXHRcdFx0XHRcdCgvYWxsfGxlZnQvLnRlc3QoY29ybmVyQ2xhc3MpICYmIHJvdyA9PSAwID8gKGlzUlRMID8gbmV4dCA6IHByZXYpIDogJycpICtcblx0XHRcdFx0XHQoL2FsbHxyaWdodC8udGVzdChjb3JuZXJDbGFzcykgJiYgcm93ID09IDAgPyAoaXNSVEwgPyBwcmV2IDogbmV4dCkgOiAnJykgK1xuXHRcdFx0XHRcdHRoaXMuX2dlbmVyYXRlTW9udGhZZWFySGVhZGVyKGluc3QsIGRyYXdNb250aCwgZHJhd1llYXIsIG1pbkRhdGUsIG1heERhdGUsXG5cdFx0XHRcdFx0cm93ID4gMCB8fCBjb2wgPiAwLCBtb250aE5hbWVzLCBtb250aE5hbWVzU2hvcnQpICsgLy8gZHJhdyBtb250aCBoZWFkZXJzXG5cdFx0XHRcdFx0JzwvZGl2Pjx0YWJsZSBjbGFzcz1cInVpLWRhdGVwaWNrZXItY2FsZW5kYXJcIj48dGhlYWQ+JyArXG5cdFx0XHRcdFx0Jzx0cj4nO1xuXHRcdFx0XHR2YXIgdGhlYWQgPSAoc2hvd1dlZWsgPyAnPHRoIGNsYXNzPVwidWktZGF0ZXBpY2tlci13ZWVrLWNvbFwiPicgKyB0aGlzLl9nZXQoaW5zdCwgJ3dlZWtIZWFkZXInKSArICc8L3RoPicgOiAnJyk7XG5cdFx0XHRcdGZvciAodmFyIGRvdyA9IDA7IGRvdyA8IDc7IGRvdysrKSB7IC8vIGRheXMgb2YgdGhlIHdlZWtcblx0XHRcdFx0XHR2YXIgZGF5ID0gKGRvdyArIGZpcnN0RGF5KSAlIDc7XG5cdFx0XHRcdFx0dGhlYWQgKz0gJzx0aCcgKyAoKGRvdyArIGZpcnN0RGF5ICsgNikgJSA3ID49IDUgPyAnIGNsYXNzPVwidWktZGF0ZXBpY2tlci13ZWVrLWVuZFwiJyA6ICcnKSArICc+JyArXG5cdFx0XHRcdFx0XHQnPHNwYW4gdGl0bGU9XCInICsgZGF5TmFtZXNbZGF5XSArICdcIj4nICsgZGF5TmFtZXNNaW5bZGF5XSArICc8L3NwYW4+PC90aD4nO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNhbGVuZGVyICs9IHRoZWFkICsgJzwvdHI+PC90aGVhZD48dGJvZHk+Jztcblx0XHRcdFx0dmFyIGRheXNJbk1vbnRoID0gdGhpcy5fZ2V0RGF5c0luTW9udGgoZHJhd1llYXIsIGRyYXdNb250aCk7XG5cdFx0XHRcdGlmIChkcmF3WWVhciA9PSBpbnN0LnNlbGVjdGVkWWVhciAmJiBkcmF3TW9udGggPT0gaW5zdC5zZWxlY3RlZE1vbnRoKVxuXHRcdFx0XHRcdGluc3Quc2VsZWN0ZWREYXkgPSBNYXRoLm1pbihpbnN0LnNlbGVjdGVkRGF5LCBkYXlzSW5Nb250aCk7XG5cdFx0XHRcdHZhciBsZWFkRGF5cyA9ICh0aGlzLl9nZXRGaXJzdERheU9mTW9udGgoZHJhd1llYXIsIGRyYXdNb250aCkgLSBmaXJzdERheSArIDcpICUgNztcblx0XHRcdFx0dmFyIGN1clJvd3MgPSBNYXRoLmNlaWwoKGxlYWREYXlzICsgZGF5c0luTW9udGgpIC8gNyk7IC8vIGNhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIHJvd3MgdG8gZ2VuZXJhdGVcblx0XHRcdFx0dmFyIG51bVJvd3MgPSAoaXNNdWx0aU1vbnRoID8gdGhpcy5tYXhSb3dzID4gY3VyUm93cyA/IHRoaXMubWF4Um93cyA6IGN1clJvd3MgOiBjdXJSb3dzKTsgLy9JZiBtdWx0aXBsZSBtb250aHMsIHVzZSB0aGUgaGlnaGVyIG51bWJlciBvZiByb3dzIChzZWUgIzcwNDMpXG5cdFx0XHRcdHRoaXMubWF4Um93cyA9IG51bVJvd3M7XG5cdFx0XHRcdHZhciBwcmludERhdGUgPSB0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZShkcmF3WWVhciwgZHJhd01vbnRoLCAxIC0gbGVhZERheXMpKTtcblx0XHRcdFx0Zm9yICh2YXIgZFJvdyA9IDA7IGRSb3cgPCBudW1Sb3dzOyBkUm93KyspIHsgLy8gY3JlYXRlIGRhdGUgcGlja2VyIHJvd3Ncblx0XHRcdFx0XHRjYWxlbmRlciArPSAnPHRyPic7XG5cdFx0XHRcdFx0dmFyIHRib2R5ID0gKCFzaG93V2VlayA/ICcnIDogJzx0ZCBjbGFzcz1cInVpLWRhdGVwaWNrZXItd2Vlay1jb2xcIj4nICtcblx0XHRcdFx0XHRcdHRoaXMuX2dldChpbnN0LCAnY2FsY3VsYXRlV2VlaycpKHByaW50RGF0ZSkgKyAnPC90ZD4nKTtcblx0XHRcdFx0XHRmb3IgKHZhciBkb3cgPSAwOyBkb3cgPCA3OyBkb3crKykgeyAvLyBjcmVhdGUgZGF0ZSBwaWNrZXIgZGF5c1xuXHRcdFx0XHRcdFx0dmFyIGRheVNldHRpbmdzID0gKGJlZm9yZVNob3dEYXkgP1xuXHRcdFx0XHRcdFx0XHRiZWZvcmVTaG93RGF5LmFwcGx5KChpbnN0LmlucHV0ID8gaW5zdC5pbnB1dFswXSA6IG51bGwpLCBbcHJpbnREYXRlXSkgOiBbdHJ1ZSwgJyddKTtcblx0XHRcdFx0XHRcdHZhciBvdGhlck1vbnRoID0gKHByaW50RGF0ZS5nZXRNb250aCgpICE9IGRyYXdNb250aCk7XG5cdFx0XHRcdFx0XHR2YXIgdW5zZWxlY3RhYmxlID0gKG90aGVyTW9udGggJiYgIXNlbGVjdE90aGVyTW9udGhzKSB8fCAhZGF5U2V0dGluZ3NbMF0gfHxcblx0XHRcdFx0XHRcdFx0KG1pbkRhdGUgJiYgcHJpbnREYXRlIDwgbWluRGF0ZSkgfHwgKG1heERhdGUgJiYgcHJpbnREYXRlID4gbWF4RGF0ZSk7XG5cdFx0XHRcdFx0XHR0Ym9keSArPSAnPHRkIGNsYXNzPVwiJyArXG5cdFx0XHRcdFx0XHRcdCgoZG93ICsgZmlyc3REYXkgKyA2KSAlIDcgPj0gNSA/ICcgdWktZGF0ZXBpY2tlci13ZWVrLWVuZCcgOiAnJykgKyAvLyBoaWdobGlnaHQgd2Vla2VuZHNcblx0XHRcdFx0XHRcdFx0KG90aGVyTW9udGggPyAnIHVpLWRhdGVwaWNrZXItb3RoZXItbW9udGgnIDogJycpICsgLy8gaGlnaGxpZ2h0IGRheXMgZnJvbSBvdGhlciBtb250aHNcblx0XHRcdFx0XHRcdFx0KChwcmludERhdGUuZ2V0VGltZSgpID09IHNlbGVjdGVkRGF0ZS5nZXRUaW1lKCkgJiYgZHJhd01vbnRoID09IGluc3Quc2VsZWN0ZWRNb250aCAmJiBpbnN0Ll9rZXlFdmVudCkgfHwgLy8gdXNlciBwcmVzc2VkIGtleVxuXHRcdFx0XHRcdFx0XHQoZGVmYXVsdERhdGUuZ2V0VGltZSgpID09IHByaW50RGF0ZS5nZXRUaW1lKCkgJiYgZGVmYXVsdERhdGUuZ2V0VGltZSgpID09IHNlbGVjdGVkRGF0ZS5nZXRUaW1lKCkpID9cblx0XHRcdFx0XHRcdFx0Ly8gb3IgZGVmYXVsdERhdGUgaXMgY3VycmVudCBwcmludGVkRGF0ZSBhbmQgZGVmYXVsdERhdGUgaXMgc2VsZWN0ZWREYXRlXG5cdFx0XHRcdFx0XHRcdCcgJyArIHRoaXMuX2RheU92ZXJDbGFzcyA6ICcnKSArIC8vIGhpZ2hsaWdodCBzZWxlY3RlZCBkYXlcblx0XHRcdFx0XHRcdFx0KHVuc2VsZWN0YWJsZSA/ICcgJyArIHRoaXMuX3Vuc2VsZWN0YWJsZUNsYXNzICsgJyB1aS1zdGF0ZS1kaXNhYmxlZCc6ICcnKSArICAvLyBoaWdobGlnaHQgdW5zZWxlY3RhYmxlIGRheXNcblx0XHRcdFx0XHRcdFx0KG90aGVyTW9udGggJiYgIXNob3dPdGhlck1vbnRocyA/ICcnIDogJyAnICsgZGF5U2V0dGluZ3NbMV0gKyAvLyBoaWdobGlnaHQgY3VzdG9tIGRhdGVzXG5cdFx0XHRcdFx0XHRcdChwcmludERhdGUuZ2V0VGltZSgpID09IGN1cnJlbnREYXRlLmdldFRpbWUoKSA/ICcgJyArIHRoaXMuX2N1cnJlbnRDbGFzcyA6ICcnKSArIC8vIGhpZ2hsaWdodCBzZWxlY3RlZCBkYXlcblx0XHRcdFx0XHRcdFx0KHByaW50RGF0ZS5nZXRUaW1lKCkgPT0gdG9kYXkuZ2V0VGltZSgpID8gJyB1aS1kYXRlcGlja2VyLXRvZGF5JyA6ICcnKSkgKyAnXCInICsgLy8gaGlnaGxpZ2h0IHRvZGF5IChpZiBkaWZmZXJlbnQpXG5cdFx0XHRcdFx0XHRcdCgoIW90aGVyTW9udGggfHwgc2hvd090aGVyTW9udGhzKSAmJiBkYXlTZXR0aW5nc1syXSA/ICcgdGl0bGU9XCInICsgZGF5U2V0dGluZ3NbMl0gKyAnXCInIDogJycpICsgLy8gY2VsbCB0aXRsZVxuXHRcdFx0XHRcdFx0XHQodW5zZWxlY3RhYmxlID8gJycgOiAnIGRhdGEtaGFuZGxlcj1cInNlbGVjdERheVwiIGRhdGEtZXZlbnQ9XCJjbGlja1wiIGRhdGEtbW9udGg9XCInICsgcHJpbnREYXRlLmdldE1vbnRoKCkgKyAnXCIgZGF0YS15ZWFyPVwiJyArIHByaW50RGF0ZS5nZXRGdWxsWWVhcigpICsgJ1wiJykgKyAnPicgKyAvLyBhY3Rpb25zXG5cdFx0XHRcdFx0XHRcdChvdGhlck1vbnRoICYmICFzaG93T3RoZXJNb250aHMgPyAnJiN4YTA7JyA6IC8vIGRpc3BsYXkgZm9yIG90aGVyIG1vbnRoc1xuXHRcdFx0XHRcdFx0XHQodW5zZWxlY3RhYmxlID8gJzxzcGFuIGNsYXNzPVwidWktc3RhdGUtZGVmYXVsdFwiPicgKyBwcmludERhdGUuZ2V0RGF0ZSgpICsgJzwvc3Bhbj4nIDogJzxhIGNsYXNzPVwidWktc3RhdGUtZGVmYXVsdCcgK1xuXHRcdFx0XHRcdFx0XHQocHJpbnREYXRlLmdldFRpbWUoKSA9PSB0b2RheS5nZXRUaW1lKCkgPyAnIHVpLXN0YXRlLWhpZ2hsaWdodCcgOiAnJykgK1xuXHRcdFx0XHRcdFx0XHQocHJpbnREYXRlLmdldFRpbWUoKSA9PSBjdXJyZW50RGF0ZS5nZXRUaW1lKCkgPyAnIHVpLXN0YXRlLWFjdGl2ZScgOiAnJykgKyAvLyBoaWdobGlnaHQgc2VsZWN0ZWQgZGF5XG5cdFx0XHRcdFx0XHRcdChvdGhlck1vbnRoID8gJyB1aS1wcmlvcml0eS1zZWNvbmRhcnknIDogJycpICsgLy8gZGlzdGluZ3Vpc2ggZGF0ZXMgZnJvbSBvdGhlciBtb250aHNcblx0XHRcdFx0XHRcdFx0J1wiIGhyZWY9XCIjXCI+JyArIHByaW50RGF0ZS5nZXREYXRlKCkgKyAnPC9hPicpKSArICc8L3RkPic7IC8vIGRpc3BsYXkgc2VsZWN0YWJsZSBkYXRlXG5cdFx0XHRcdFx0XHRwcmludERhdGUuc2V0RGF0ZShwcmludERhdGUuZ2V0RGF0ZSgpICsgMSk7XG5cdFx0XHRcdFx0XHRwcmludERhdGUgPSB0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChwcmludERhdGUpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjYWxlbmRlciArPSB0Ym9keSArICc8L3RyPic7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZHJhd01vbnRoKys7XG5cdFx0XHRcdGlmIChkcmF3TW9udGggPiAxMSkge1xuXHRcdFx0XHRcdGRyYXdNb250aCA9IDA7XG5cdFx0XHRcdFx0ZHJhd1llYXIrKztcblx0XHRcdFx0fVxuXHRcdFx0XHRjYWxlbmRlciArPSAnPC90Ym9keT48L3RhYmxlPicgKyAoaXNNdWx0aU1vbnRoID8gJzwvZGl2PicgK1xuXHRcdFx0XHRcdFx0XHQoKG51bU1vbnRoc1swXSA+IDAgJiYgY29sID09IG51bU1vbnRoc1sxXS0xKSA/ICc8ZGl2IGNsYXNzPVwidWktZGF0ZXBpY2tlci1yb3ctYnJlYWtcIj48L2Rpdj4nIDogJycpIDogJycpO1xuXHRcdFx0XHRncm91cCArPSBjYWxlbmRlcjtcblx0XHRcdH1cblx0XHRcdGh0bWwgKz0gZ3JvdXA7XG5cdFx0fVxuXHRcdGh0bWwgKz0gYnV0dG9uUGFuZWwgKyAoJC51aS5pZTYgJiYgIWluc3QuaW5saW5lID9cblx0XHRcdCc8aWZyYW1lIHNyYz1cImphdmFzY3JpcHQ6ZmFsc2U7XCIgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLWNvdmVyXCIgZnJhbWVib3JkZXI9XCIwXCI+PC9pZnJhbWU+JyA6ICcnKTtcblx0XHRpbnN0Ll9rZXlFdmVudCA9IGZhbHNlO1xuXHRcdHJldHVybiBodG1sO1xuXHR9LFxuXG5cdC8qIEdlbmVyYXRlIHRoZSBtb250aCBhbmQgeWVhciBoZWFkZXIuICovXG5cdF9nZW5lcmF0ZU1vbnRoWWVhckhlYWRlcjogZnVuY3Rpb24oaW5zdCwgZHJhd01vbnRoLCBkcmF3WWVhciwgbWluRGF0ZSwgbWF4RGF0ZSxcblx0XHRcdHNlY29uZGFyeSwgbW9udGhOYW1lcywgbW9udGhOYW1lc1Nob3J0KSB7XG5cdFx0dmFyIGNoYW5nZU1vbnRoID0gdGhpcy5fZ2V0KGluc3QsICdjaGFuZ2VNb250aCcpO1xuXHRcdHZhciBjaGFuZ2VZZWFyID0gdGhpcy5fZ2V0KGluc3QsICdjaGFuZ2VZZWFyJyk7XG5cdFx0dmFyIHNob3dNb250aEFmdGVyWWVhciA9IHRoaXMuX2dldChpbnN0LCAnc2hvd01vbnRoQWZ0ZXJZZWFyJyk7XG5cdFx0dmFyIGh0bWwgPSAnPGRpdiBjbGFzcz1cInVpLWRhdGVwaWNrZXItdGl0bGVcIj4nO1xuXHRcdHZhciBtb250aEh0bWwgPSAnJztcblx0XHQvLyBtb250aCBzZWxlY3Rpb25cblx0XHRpZiAoc2Vjb25kYXJ5IHx8ICFjaGFuZ2VNb250aClcblx0XHRcdG1vbnRoSHRtbCArPSAnPHNwYW4gY2xhc3M9XCJ1aS1kYXRlcGlja2VyLW1vbnRoXCI+JyArIG1vbnRoTmFtZXNbZHJhd01vbnRoXSArICc8L3NwYW4+Jztcblx0XHRlbHNlIHtcblx0XHRcdHZhciBpbk1pblllYXIgPSAobWluRGF0ZSAmJiBtaW5EYXRlLmdldEZ1bGxZZWFyKCkgPT0gZHJhd1llYXIpO1xuXHRcdFx0dmFyIGluTWF4WWVhciA9IChtYXhEYXRlICYmIG1heERhdGUuZ2V0RnVsbFllYXIoKSA9PSBkcmF3WWVhcik7XG5cdFx0XHRtb250aEh0bWwgKz0gJzxzZWxlY3QgY2xhc3M9XCJ1aS1kYXRlcGlja2VyLW1vbnRoXCIgZGF0YS1oYW5kbGVyPVwic2VsZWN0TW9udGhcIiBkYXRhLWV2ZW50PVwiY2hhbmdlXCI+Jztcblx0XHRcdGZvciAodmFyIG1vbnRoID0gMDsgbW9udGggPCAxMjsgbW9udGgrKykge1xuXHRcdFx0XHRpZiAoKCFpbk1pblllYXIgfHwgbW9udGggPj0gbWluRGF0ZS5nZXRNb250aCgpKSAmJlxuXHRcdFx0XHRcdFx0KCFpbk1heFllYXIgfHwgbW9udGggPD0gbWF4RGF0ZS5nZXRNb250aCgpKSlcblx0XHRcdFx0XHRtb250aEh0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCInICsgbW9udGggKyAnXCInICtcblx0XHRcdFx0XHRcdChtb250aCA9PSBkcmF3TW9udGggPyAnIHNlbGVjdGVkPVwic2VsZWN0ZWRcIicgOiAnJykgK1xuXHRcdFx0XHRcdFx0Jz4nICsgbW9udGhOYW1lc1Nob3J0W21vbnRoXSArICc8L29wdGlvbj4nO1xuXHRcdFx0fVxuXHRcdFx0bW9udGhIdG1sICs9ICc8L3NlbGVjdD4nO1xuXHRcdH1cblx0XHRpZiAoIXNob3dNb250aEFmdGVyWWVhcilcblx0XHRcdGh0bWwgKz0gbW9udGhIdG1sICsgKHNlY29uZGFyeSB8fCAhKGNoYW5nZU1vbnRoICYmIGNoYW5nZVllYXIpID8gJyYjeGEwOycgOiAnJyk7XG5cdFx0Ly8geWVhciBzZWxlY3Rpb25cblx0XHRpZiAoICFpbnN0LnllYXJzaHRtbCApIHtcblx0XHRcdGluc3QueWVhcnNodG1sID0gJyc7XG5cdFx0XHRpZiAoc2Vjb25kYXJ5IHx8ICFjaGFuZ2VZZWFyKVxuXHRcdFx0XHRodG1sICs9ICc8c3BhbiBjbGFzcz1cInVpLWRhdGVwaWNrZXIteWVhclwiPicgKyBkcmF3WWVhciArICc8L3NwYW4+Jztcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBkZXRlcm1pbmUgcmFuZ2Ugb2YgeWVhcnMgdG8gZGlzcGxheVxuXHRcdFx0XHR2YXIgeWVhcnMgPSB0aGlzLl9nZXQoaW5zdCwgJ3llYXJSYW5nZScpLnNwbGl0KCc6Jyk7XG5cdFx0XHRcdHZhciB0aGlzWWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKTtcblx0XHRcdFx0dmFyIGRldGVybWluZVllYXIgPSBmdW5jdGlvbih2YWx1ZSkge1xuXHRcdFx0XHRcdHZhciB5ZWFyID0gKHZhbHVlLm1hdGNoKC9jWystXS4qLykgPyBkcmF3WWVhciArIHBhcnNlSW50KHZhbHVlLnN1YnN0cmluZygxKSwgMTApIDpcblx0XHRcdFx0XHRcdCh2YWx1ZS5tYXRjaCgvWystXS4qLykgPyB0aGlzWWVhciArIHBhcnNlSW50KHZhbHVlLCAxMCkgOlxuXHRcdFx0XHRcdFx0cGFyc2VJbnQodmFsdWUsIDEwKSkpO1xuXHRcdFx0XHRcdHJldHVybiAoaXNOYU4oeWVhcikgPyB0aGlzWWVhciA6IHllYXIpO1xuXHRcdFx0XHR9O1xuXHRcdFx0XHR2YXIgeWVhciA9IGRldGVybWluZVllYXIoeWVhcnNbMF0pO1xuXHRcdFx0XHR2YXIgZW5kWWVhciA9IE1hdGgubWF4KHllYXIsIGRldGVybWluZVllYXIoeWVhcnNbMV0gfHwgJycpKTtcblx0XHRcdFx0eWVhciA9IChtaW5EYXRlID8gTWF0aC5tYXgoeWVhciwgbWluRGF0ZS5nZXRGdWxsWWVhcigpKSA6IHllYXIpO1xuXHRcdFx0XHRlbmRZZWFyID0gKG1heERhdGUgPyBNYXRoLm1pbihlbmRZZWFyLCBtYXhEYXRlLmdldEZ1bGxZZWFyKCkpIDogZW5kWWVhcik7XG5cdFx0XHRcdGluc3QueWVhcnNodG1sICs9ICc8c2VsZWN0IGNsYXNzPVwidWktZGF0ZXBpY2tlci15ZWFyXCIgZGF0YS1oYW5kbGVyPVwic2VsZWN0WWVhclwiIGRhdGEtZXZlbnQ9XCJjaGFuZ2VcIj4nO1xuXHRcdFx0XHRmb3IgKDsgeWVhciA8PSBlbmRZZWFyOyB5ZWFyKyspIHtcblx0XHRcdFx0XHRpbnN0LnllYXJzaHRtbCArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyB5ZWFyICsgJ1wiJyArXG5cdFx0XHRcdFx0XHQoeWVhciA9PSBkcmF3WWVhciA/ICcgc2VsZWN0ZWQ9XCJzZWxlY3RlZFwiJyA6ICcnKSArXG5cdFx0XHRcdFx0XHQnPicgKyB5ZWFyICsgJzwvb3B0aW9uPic7XG5cdFx0XHRcdH1cblx0XHRcdFx0aW5zdC55ZWFyc2h0bWwgKz0gJzwvc2VsZWN0Pic7XG5cblx0XHRcdFx0aHRtbCArPSBpbnN0LnllYXJzaHRtbDtcblx0XHRcdFx0aW5zdC55ZWFyc2h0bWwgPSBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRodG1sICs9IHRoaXMuX2dldChpbnN0LCAneWVhclN1ZmZpeCcpO1xuXHRcdGlmIChzaG93TW9udGhBZnRlclllYXIpXG5cdFx0XHRodG1sICs9IChzZWNvbmRhcnkgfHwgIShjaGFuZ2VNb250aCAmJiBjaGFuZ2VZZWFyKSA/ICcmI3hhMDsnIDogJycpICsgbW9udGhIdG1sO1xuXHRcdGh0bWwgKz0gJzwvZGl2Pic7IC8vIENsb3NlIGRhdGVwaWNrZXJfaGVhZGVyXG5cdFx0cmV0dXJuIGh0bWw7XG5cdH0sXG5cblx0LyogQWRqdXN0IG9uZSBvZiB0aGUgZGF0ZSBzdWItZmllbGRzLiAqL1xuXHRfYWRqdXN0SW5zdERhdGU6IGZ1bmN0aW9uKGluc3QsIG9mZnNldCwgcGVyaW9kKSB7XG5cdFx0dmFyIHllYXIgPSBpbnN0LmRyYXdZZWFyICsgKHBlcmlvZCA9PSAnWScgPyBvZmZzZXQgOiAwKTtcblx0XHR2YXIgbW9udGggPSBpbnN0LmRyYXdNb250aCArIChwZXJpb2QgPT0gJ00nID8gb2Zmc2V0IDogMCk7XG5cdFx0dmFyIGRheSA9IE1hdGgubWluKGluc3Quc2VsZWN0ZWREYXksIHRoaXMuX2dldERheXNJbk1vbnRoKHllYXIsIG1vbnRoKSkgK1xuXHRcdFx0KHBlcmlvZCA9PSAnRCcgPyBvZmZzZXQgOiAwKTtcblx0XHR2YXIgZGF0ZSA9IHRoaXMuX3Jlc3RyaWN0TWluTWF4KGluc3QsXG5cdFx0XHR0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZSh5ZWFyLCBtb250aCwgZGF5KSkpO1xuXHRcdGluc3Quc2VsZWN0ZWREYXkgPSBkYXRlLmdldERhdGUoKTtcblx0XHRpbnN0LmRyYXdNb250aCA9IGluc3Quc2VsZWN0ZWRNb250aCA9IGRhdGUuZ2V0TW9udGgoKTtcblx0XHRpbnN0LmRyYXdZZWFyID0gaW5zdC5zZWxlY3RlZFllYXIgPSBkYXRlLmdldEZ1bGxZZWFyKCk7XG5cdFx0aWYgKHBlcmlvZCA9PSAnTScgfHwgcGVyaW9kID09ICdZJylcblx0XHRcdHRoaXMuX25vdGlmeUNoYW5nZShpbnN0KTtcblx0fSxcblxuXHQvKiBFbnN1cmUgYSBkYXRlIGlzIHdpdGhpbiBhbnkgbWluL21heCBib3VuZHMuICovXG5cdF9yZXN0cmljdE1pbk1heDogZnVuY3Rpb24oaW5zdCwgZGF0ZSkge1xuXHRcdHZhciBtaW5EYXRlID0gdGhpcy5fZ2V0TWluTWF4RGF0ZShpbnN0LCAnbWluJyk7XG5cdFx0dmFyIG1heERhdGUgPSB0aGlzLl9nZXRNaW5NYXhEYXRlKGluc3QsICdtYXgnKTtcblx0XHR2YXIgbmV3RGF0ZSA9IChtaW5EYXRlICYmIGRhdGUgPCBtaW5EYXRlID8gbWluRGF0ZSA6IGRhdGUpO1xuXHRcdG5ld0RhdGUgPSAobWF4RGF0ZSAmJiBuZXdEYXRlID4gbWF4RGF0ZSA/IG1heERhdGUgOiBuZXdEYXRlKTtcblx0XHRyZXR1cm4gbmV3RGF0ZTtcblx0fSxcblxuXHQvKiBOb3RpZnkgY2hhbmdlIG9mIG1vbnRoL3llYXIuICovXG5cdF9ub3RpZnlDaGFuZ2U6IGZ1bmN0aW9uKGluc3QpIHtcblx0XHR2YXIgb25DaGFuZ2UgPSB0aGlzLl9nZXQoaW5zdCwgJ29uQ2hhbmdlTW9udGhZZWFyJyk7XG5cdFx0aWYgKG9uQ2hhbmdlKVxuXHRcdFx0b25DaGFuZ2UuYXBwbHkoKGluc3QuaW5wdXQgPyBpbnN0LmlucHV0WzBdIDogbnVsbCksXG5cdFx0XHRcdFtpbnN0LnNlbGVjdGVkWWVhciwgaW5zdC5zZWxlY3RlZE1vbnRoICsgMSwgaW5zdF0pO1xuXHR9LFxuXG5cdC8qIERldGVybWluZSB0aGUgbnVtYmVyIG9mIG1vbnRocyB0byBzaG93LiAqL1xuXHRfZ2V0TnVtYmVyT2ZNb250aHM6IGZ1bmN0aW9uKGluc3QpIHtcblx0XHR2YXIgbnVtTW9udGhzID0gdGhpcy5fZ2V0KGluc3QsICdudW1iZXJPZk1vbnRocycpO1xuXHRcdHJldHVybiAobnVtTW9udGhzID09IG51bGwgPyBbMSwgMV0gOiAodHlwZW9mIG51bU1vbnRocyA9PSAnbnVtYmVyJyA/IFsxLCBudW1Nb250aHNdIDogbnVtTW9udGhzKSk7XG5cdH0sXG5cblx0LyogRGV0ZXJtaW5lIHRoZSBjdXJyZW50IG1heGltdW0gZGF0ZSAtIGVuc3VyZSBubyB0aW1lIGNvbXBvbmVudHMgYXJlIHNldC4gKi9cblx0X2dldE1pbk1heERhdGU6IGZ1bmN0aW9uKGluc3QsIG1pbk1heCkge1xuXHRcdHJldHVybiB0aGlzLl9kZXRlcm1pbmVEYXRlKGluc3QsIHRoaXMuX2dldChpbnN0LCBtaW5NYXggKyAnRGF0ZScpLCBudWxsKTtcblx0fSxcblxuXHQvKiBGaW5kIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIGdpdmVuIG1vbnRoLiAqL1xuXHRfZ2V0RGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG5cdFx0cmV0dXJuIDMyIC0gdGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoeWVhciwgbW9udGgsIDMyKSkuZ2V0RGF0ZSgpO1xuXHR9LFxuXG5cdC8qIEZpbmQgdGhlIGRheSBvZiB0aGUgd2VlayBvZiB0aGUgZmlyc3Qgb2YgYSBtb250aC4gKi9cblx0X2dldEZpcnN0RGF5T2ZNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcblx0XHRyZXR1cm4gbmV3IERhdGUoeWVhciwgbW9udGgsIDEpLmdldERheSgpO1xuXHR9LFxuXG5cdC8qIERldGVybWluZXMgaWYgd2Ugc2hvdWxkIGFsbG93IGEgXCJuZXh0L3ByZXZcIiBtb250aCBkaXNwbGF5IGNoYW5nZS4gKi9cblx0X2NhbkFkanVzdE1vbnRoOiBmdW5jdGlvbihpbnN0LCBvZmZzZXQsIGN1clllYXIsIGN1ck1vbnRoKSB7XG5cdFx0dmFyIG51bU1vbnRocyA9IHRoaXMuX2dldE51bWJlck9mTW9udGhzKGluc3QpO1xuXHRcdHZhciBkYXRlID0gdGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoY3VyWWVhcixcblx0XHRcdGN1ck1vbnRoICsgKG9mZnNldCA8IDAgPyBvZmZzZXQgOiBudW1Nb250aHNbMF0gKiBudW1Nb250aHNbMV0pLCAxKSk7XG5cdFx0aWYgKG9mZnNldCA8IDApXG5cdFx0XHRkYXRlLnNldERhdGUodGhpcy5fZ2V0RGF5c0luTW9udGgoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCkpKTtcblx0XHRyZXR1cm4gdGhpcy5faXNJblJhbmdlKGluc3QsIGRhdGUpO1xuXHR9LFxuXG5cdC8qIElzIHRoZSBnaXZlbiBkYXRlIGluIHRoZSBhY2NlcHRlZCByYW5nZT8gKi9cblx0X2lzSW5SYW5nZTogZnVuY3Rpb24oaW5zdCwgZGF0ZSkge1xuXHRcdHZhciBtaW5EYXRlID0gdGhpcy5fZ2V0TWluTWF4RGF0ZShpbnN0LCAnbWluJyk7XG5cdFx0dmFyIG1heERhdGUgPSB0aGlzLl9nZXRNaW5NYXhEYXRlKGluc3QsICdtYXgnKTtcblx0XHRyZXR1cm4gKCghbWluRGF0ZSB8fCBkYXRlLmdldFRpbWUoKSA+PSBtaW5EYXRlLmdldFRpbWUoKSkgJiZcblx0XHRcdCghbWF4RGF0ZSB8fCBkYXRlLmdldFRpbWUoKSA8PSBtYXhEYXRlLmdldFRpbWUoKSkpO1xuXHR9LFxuXG5cdC8qIFByb3ZpZGUgdGhlIGNvbmZpZ3VyYXRpb24gc2V0dGluZ3MgZm9yIGZvcm1hdHRpbmcvcGFyc2luZy4gKi9cblx0X2dldEZvcm1hdENvbmZpZzogZnVuY3Rpb24oaW5zdCkge1xuXHRcdHZhciBzaG9ydFllYXJDdXRvZmYgPSB0aGlzLl9nZXQoaW5zdCwgJ3Nob3J0WWVhckN1dG9mZicpO1xuXHRcdHNob3J0WWVhckN1dG9mZiA9ICh0eXBlb2Ygc2hvcnRZZWFyQ3V0b2ZmICE9ICdzdHJpbmcnID8gc2hvcnRZZWFyQ3V0b2ZmIDpcblx0XHRcdG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSAlIDEwMCArIHBhcnNlSW50KHNob3J0WWVhckN1dG9mZiwgMTApKTtcblx0XHRyZXR1cm4ge3Nob3J0WWVhckN1dG9mZjogc2hvcnRZZWFyQ3V0b2ZmLFxuXHRcdFx0ZGF5TmFtZXNTaG9ydDogdGhpcy5fZ2V0KGluc3QsICdkYXlOYW1lc1Nob3J0JyksIGRheU5hbWVzOiB0aGlzLl9nZXQoaW5zdCwgJ2RheU5hbWVzJyksXG5cdFx0XHRtb250aE5hbWVzU2hvcnQ6IHRoaXMuX2dldChpbnN0LCAnbW9udGhOYW1lc1Nob3J0JyksIG1vbnRoTmFtZXM6IHRoaXMuX2dldChpbnN0LCAnbW9udGhOYW1lcycpfTtcblx0fSxcblxuXHQvKiBGb3JtYXQgdGhlIGdpdmVuIGRhdGUgZm9yIGRpc3BsYXkuICovXG5cdF9mb3JtYXREYXRlOiBmdW5jdGlvbihpbnN0LCBkYXksIG1vbnRoLCB5ZWFyKSB7XG5cdFx0aWYgKCFkYXkpIHtcblx0XHRcdGluc3QuY3VycmVudERheSA9IGluc3Quc2VsZWN0ZWREYXk7XG5cdFx0XHRpbnN0LmN1cnJlbnRNb250aCA9IGluc3Quc2VsZWN0ZWRNb250aDtcblx0XHRcdGluc3QuY3VycmVudFllYXIgPSBpbnN0LnNlbGVjdGVkWWVhcjtcblx0XHR9XG5cdFx0dmFyIGRhdGUgPSAoZGF5ID8gKHR5cGVvZiBkYXkgPT0gJ29iamVjdCcgPyBkYXkgOlxuXHRcdFx0dGhpcy5fZGF5bGlnaHRTYXZpbmdBZGp1c3QobmV3IERhdGUoeWVhciwgbW9udGgsIGRheSkpKSA6XG5cdFx0XHR0aGlzLl9kYXlsaWdodFNhdmluZ0FkanVzdChuZXcgRGF0ZShpbnN0LmN1cnJlbnRZZWFyLCBpbnN0LmN1cnJlbnRNb250aCwgaW5zdC5jdXJyZW50RGF5KSkpO1xuXHRcdHJldHVybiB0aGlzLmZvcm1hdERhdGUodGhpcy5fZ2V0KGluc3QsICdkYXRlRm9ybWF0JyksIGRhdGUsIHRoaXMuX2dldEZvcm1hdENvbmZpZyhpbnN0KSk7XG5cdH1cbn0pO1xuXG4vKlxuICogQmluZCBob3ZlciBldmVudHMgZm9yIGRhdGVwaWNrZXIgZWxlbWVudHMuXG4gKiBEb25lIHZpYSBkZWxlZ2F0ZSBzbyB0aGUgYmluZGluZyBvbmx5IG9jY3VycyBvbmNlIGluIHRoZSBsaWZldGltZSBvZiB0aGUgcGFyZW50IGRpdi5cbiAqIEdsb2JhbCBpbnN0QWN0aXZlLCBzZXQgYnkgX3VwZGF0ZURhdGVwaWNrZXIgYWxsb3dzIHRoZSBoYW5kbGVycyB0byBmaW5kIHRoZWlyIHdheSBiYWNrIHRvIHRoZSBhY3RpdmUgcGlja2VyLlxuICovXG5mdW5jdGlvbiBiaW5kSG92ZXIoZHBEaXYpIHtcblx0dmFyIHNlbGVjdG9yID0gJ2J1dHRvbiwgLnVpLWRhdGVwaWNrZXItcHJldiwgLnVpLWRhdGVwaWNrZXItbmV4dCwgLnVpLWRhdGVwaWNrZXItY2FsZW5kYXIgdGQgYSc7XG5cdHJldHVybiBkcERpdi5kZWxlZ2F0ZShzZWxlY3RvciwgJ21vdXNlb3V0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHQkKHRoaXMpLnJlbW92ZUNsYXNzKCd1aS1zdGF0ZS1ob3ZlcicpO1xuXHRcdFx0aWYgKHRoaXMuY2xhc3NOYW1lLmluZGV4T2YoJ3VpLWRhdGVwaWNrZXItcHJldicpICE9IC0xKSAkKHRoaXMpLnJlbW92ZUNsYXNzKCd1aS1kYXRlcGlja2VyLXByZXYtaG92ZXInKTtcblx0XHRcdGlmICh0aGlzLmNsYXNzTmFtZS5pbmRleE9mKCd1aS1kYXRlcGlja2VyLW5leHQnKSAhPSAtMSkgJCh0aGlzKS5yZW1vdmVDbGFzcygndWktZGF0ZXBpY2tlci1uZXh0LWhvdmVyJyk7XG5cdFx0fSlcblx0XHQuZGVsZWdhdGUoc2VsZWN0b3IsICdtb3VzZW92ZXInLCBmdW5jdGlvbigpe1xuXHRcdFx0aWYgKCEkLmRhdGVwaWNrZXIuX2lzRGlzYWJsZWREYXRlcGlja2VyKCBpbnN0QWN0aXZlLmlubGluZSA/IGRwRGl2LnBhcmVudCgpWzBdIDogaW5zdEFjdGl2ZS5pbnB1dFswXSkpIHtcblx0XHRcdFx0JCh0aGlzKS5wYXJlbnRzKCcudWktZGF0ZXBpY2tlci1jYWxlbmRhcicpLmZpbmQoJ2EnKS5yZW1vdmVDbGFzcygndWktc3RhdGUtaG92ZXInKTtcblx0XHRcdFx0JCh0aGlzKS5hZGRDbGFzcygndWktc3RhdGUtaG92ZXInKTtcblx0XHRcdFx0aWYgKHRoaXMuY2xhc3NOYW1lLmluZGV4T2YoJ3VpLWRhdGVwaWNrZXItcHJldicpICE9IC0xKSAkKHRoaXMpLmFkZENsYXNzKCd1aS1kYXRlcGlja2VyLXByZXYtaG92ZXInKTtcblx0XHRcdFx0aWYgKHRoaXMuY2xhc3NOYW1lLmluZGV4T2YoJ3VpLWRhdGVwaWNrZXItbmV4dCcpICE9IC0xKSAkKHRoaXMpLmFkZENsYXNzKCd1aS1kYXRlcGlja2VyLW5leHQtaG92ZXInKTtcblx0XHRcdH1cblx0XHR9KTtcbn1cblxuLyogalF1ZXJ5IGV4dGVuZCBub3cgaWdub3JlcyBudWxscyEgKi9cbmZ1bmN0aW9uIGV4dGVuZFJlbW92ZSh0YXJnZXQsIHByb3BzKSB7XG5cdCQuZXh0ZW5kKHRhcmdldCwgcHJvcHMpO1xuXHRmb3IgKHZhciBuYW1lIGluIHByb3BzKVxuXHRcdGlmIChwcm9wc1tuYW1lXSA9PSBudWxsIHx8IHByb3BzW25hbWVdID09IHVuZGVmaW5lZClcblx0XHRcdHRhcmdldFtuYW1lXSA9IHByb3BzW25hbWVdO1xuXHRyZXR1cm4gdGFyZ2V0O1xufTtcblxuLyogSW52b2tlIHRoZSBkYXRlcGlja2VyIGZ1bmN0aW9uYWxpdHkuXG4gICBAcGFyYW0gIG9wdGlvbnMgIHN0cmluZyAtIGEgY29tbWFuZCwgb3B0aW9uYWxseSBmb2xsb3dlZCBieSBhZGRpdGlvbmFsIHBhcmFtZXRlcnMgb3Jcblx0ICAgICAgICAgICAgICAgIE9iamVjdCAtIHNldHRpbmdzIGZvciBhdHRhY2hpbmcgbmV3IGRhdGVwaWNrZXIgZnVuY3Rpb25hbGl0eVxuICAgQHJldHVybiAgalF1ZXJ5IG9iamVjdCAqL1xuJC5mbi5kYXRlcGlja2VyID0gZnVuY3Rpb24ob3B0aW9ucyl7XG5cblx0LyogVmVyaWZ5IGFuIGVtcHR5IGNvbGxlY3Rpb24gd2Fzbid0IHBhc3NlZCAtIEZpeGVzICM2OTc2ICovXG5cdGlmICggIXRoaXMubGVuZ3RoICkge1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyogSW5pdGlhbGlzZSB0aGUgZGF0ZSBwaWNrZXIuICovXG5cdGlmICghJC5kYXRlcGlja2VyLmluaXRpYWxpemVkKSB7XG5cdFx0JChkb2N1bWVudCkubW91c2Vkb3duKCQuZGF0ZXBpY2tlci5fY2hlY2tFeHRlcm5hbENsaWNrKS5cblx0XHRcdGZpbmQoZG9jdW1lbnQuYm9keSkuYXBwZW5kKCQuZGF0ZXBpY2tlci5kcERpdik7XG5cdFx0JC5kYXRlcGlja2VyLmluaXRpYWxpemVkID0gdHJ1ZTtcblx0fVxuXG5cdHZhciBvdGhlckFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXHRpZiAodHlwZW9mIG9wdGlvbnMgPT0gJ3N0cmluZycgJiYgKG9wdGlvbnMgPT0gJ2lzRGlzYWJsZWQnIHx8IG9wdGlvbnMgPT0gJ2dldERhdGUnIHx8IG9wdGlvbnMgPT0gJ3dpZGdldCcpKVxuXHRcdHJldHVybiAkLmRhdGVwaWNrZXJbJ18nICsgb3B0aW9ucyArICdEYXRlcGlja2VyJ10uXG5cdFx0XHRhcHBseSgkLmRhdGVwaWNrZXIsIFt0aGlzWzBdXS5jb25jYXQob3RoZXJBcmdzKSk7XG5cdGlmIChvcHRpb25zID09ICdvcHRpb24nICYmIGFyZ3VtZW50cy5sZW5ndGggPT0gMiAmJiB0eXBlb2YgYXJndW1lbnRzWzFdID09ICdzdHJpbmcnKVxuXHRcdHJldHVybiAkLmRhdGVwaWNrZXJbJ18nICsgb3B0aW9ucyArICdEYXRlcGlja2VyJ10uXG5cdFx0XHRhcHBseSgkLmRhdGVwaWNrZXIsIFt0aGlzWzBdXS5jb25jYXQob3RoZXJBcmdzKSk7XG5cdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0dHlwZW9mIG9wdGlvbnMgPT0gJ3N0cmluZycgP1xuXHRcdFx0JC5kYXRlcGlja2VyWydfJyArIG9wdGlvbnMgKyAnRGF0ZXBpY2tlciddLlxuXHRcdFx0XHRhcHBseSgkLmRhdGVwaWNrZXIsIFt0aGlzXS5jb25jYXQob3RoZXJBcmdzKSkgOlxuXHRcdFx0JC5kYXRlcGlja2VyLl9hdHRhY2hEYXRlcGlja2VyKHRoaXMsIG9wdGlvbnMpO1xuXHR9KTtcbn07XG5cbiQuZGF0ZXBpY2tlciA9IG5ldyBEYXRlcGlja2VyKCk7IC8vIHNpbmdsZXRvbiBpbnN0YW5jZVxuJC5kYXRlcGlja2VyLmluaXRpYWxpemVkID0gZmFsc2U7XG4kLmRhdGVwaWNrZXIudXVpZCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuJC5kYXRlcGlja2VyLnZlcnNpb24gPSBcIjEuOS4yXCI7XG5cbi8vIFdvcmthcm91bmQgZm9yICM0MDU1XG4vLyBBZGQgYW5vdGhlciBnbG9iYWwgdG8gYXZvaWQgbm9Db25mbGljdCBpc3N1ZXMgd2l0aCBpbmxpbmUgZXZlbnQgaGFuZGxlcnNcbndpbmRvd1snRFBfalF1ZXJ5XycgKyBkcHV1aWRdID0gJDtcblxufSkoalF1ZXJ5KTtcbiJdLCJmaWxlIjoianF1ZXJ5dWkvanF1ZXJ5LnVpLmRhdGVwaWNrZXIuanMifQ==
  3966. </script><script>
  3967. /*! Selectric ϟ v1.13.0 (2017-08-22) - git.io/tjl9sQ - Copyright (c) 2017 Leonardo Santos - MIT License */
  3968. $(document).on("ready", function () {
  3969. !function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,s){return void 0===s&&(s="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(s),s}:e(jQuery)}(function(e){"use strict";var t=e(document),s=e(window),l=["a","e","i","o","u","n","c","y"],i=[/[\xE0-\xE5]/g,/[\xE8-\xEB]/g,/[\xEC-\xEF]/g,/[\xF2-\xF6]/g,/[\xF9-\xFC]/g,/[\xF1]/g,/[\xE7]/g,/[\xFD-\xFF]/g],n=function(t,s){var l=this;l.element=t,l.$element=e(t),l.state={multiple:!!l.$element.attr("multiple"),enabled:!1,opened:!1,currValue:-1,selectedIdx:-1,highlightedIdx:-1},l.eventTriggers={open:l.open,close:l.close,destroy:l.destroy,refresh:l.refresh,init:l.init},l.init(s)};n.prototype={utils:{isMobile:function(){return/android|ip(hone|od|ad)/i.test(navigator.userAgent)},escapeRegExp:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},replaceDiacritics:function(e){for(var t=i.length;t--;)e=e.toLowerCase().replace(i[t],l[t]);return e},format:function(e){var t=arguments;return(""+e).replace(/\{(?:(\d+)|(\w+))\}/g,function(e,s,l){return l&&t[1]?t[1][l]:t[s]})},nextEnabledItem:function(e,t){for(;e[t=(t+1)%e.length].disabled;);return t},previousEnabledItem:function(e,t){for(;e[t=(t>0?t:e.length)-1].disabled;);return t},toDash:function(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()},triggerCallback:function(t,s){var l=s.element,i=s.options["on"+t],n=[l].concat([].slice.call(arguments).slice(1));e.isFunction(i)&&i.apply(l,n),e(l).trigger("selectric-"+this.toDash(t),n)},arrayToClassname:function(t){var s=e.grep(t,function(e){return!!e});return e.trim(s.join(" "))}},init:function(t){var s=this;if(s.options=e.extend(!0,{},e.fn.selectric.defaults,s.options,t),s.utils.triggerCallback("BeforeInit",s),s.destroy(!0),s.options.disableOnMobile&&s.utils.isMobile())return void(s.disableOnMobile=!0);s.classes=s.getClassNames();var l=e("<input/>",{class:s.classes.input,readonly:s.utils.isMobile()}),i=e("<div/>",{class:s.classes.items,tabindex:-1}),n=e("<div/>",{class:s.classes.scroll}),a=e("<div/>",{class:s.classes.prefix,html:s.options.arrowButtonMarkup}),o=e("<span/>",{class:"label"}),r=s.$element.wrap("<div/>").parent().append(a.prepend(o),i,l),u=e("<div/>",{class:s.classes.hideselect});s.elements={input:l,items:i,itemsScroll:n,wrapper:a,label:o,outerWrapper:r},s.options.nativeOnMobile&&s.utils.isMobile()&&(s.elements.input=void 0,u.addClass(s.classes.prefix+"-is-native"),s.$element.on("change",function(){s.refresh()})),s.$element.on(s.eventTriggers).wrap(u),s.originalTabindex=s.$element.prop("tabindex"),s.$element.prop("tabindex",-1),s.populate(),s.activate(),s.utils.triggerCallback("Init",s)},activate:function(){var e=this,t=e.elements.items.closest(":visible").children(":hidden").addClass(e.classes.tempshow),s=e.$element.width();t.removeClass(e.classes.tempshow),e.utils.triggerCallback("BeforeActivate",e),e.elements.outerWrapper.prop("class",e.utils.arrayToClassname([e.classes.wrapper,e.$element.prop("class").replace(/\S+/g,e.classes.prefix+"-$&"),e.options.responsive?e.classes.responsive:""])),e.options.inheritOriginalWidth&&s>0&&e.elements.outerWrapper.width(s),e.unbindEvents(),e.$element.prop("disabled")?(e.elements.outerWrapper.addClass(e.classes.disabled),e.elements.input&&e.elements.input.prop("disabled",!0)):(e.state.enabled=!0,e.elements.outerWrapper.removeClass(e.classes.disabled),e.$li=e.elements.items.removeAttr("style").find("li"),e.bindEvents()),e.utils.triggerCallback("Activate",e)},getClassNames:function(){var t=this,s=t.options.customClass,l={};return e.each("Input Items Open Disabled TempShow HideSelect Wrapper Focus Hover Responsive Above Below Scroll Group GroupLabel".split(" "),function(e,i){var n=s.prefix+i;l[i.toLowerCase()]=s.camelCase?n:t.utils.toDash(n)}),l.prefix=s.prefix,l},setLabel:function(){var t=this,s=t.options.labelBuilder;if(t.state.multiple){var l=e.isArray(t.state.currValue)?t.state.currValue:[t.state.currValue];l=0===l.length?[0]:l;var i=e.map(l,function(s){return e.grep(t.lookupItems,function(e){return e.index===s})[0]});i=e.grep(i,function(t){return i.length>1||0===i.length?""!==e.trim(t.value):t}),i=e.map(i,function(l){return e.isFunction(s)?s(l):t.utils.format(s,l)}),t.options.multiple.maxLabelEntries&&(i.length>=t.options.multiple.maxLabelEntries+1?(i=i.slice(0,t.options.multiple.maxLabelEntries),i.push(e.isFunction(s)?s({text:"..."}):t.utils.format(s,{text:"..."}))):i.slice(i.length-1)),t.elements.label.html(i.join(t.options.multiple.separator))}else{var n=t.lookupItems[t.state.currValue];t.elements.label.html(e.isFunction(s)?s(n):t.utils.format(s,n))}},populate:function(){var t=this,s=t.$element.children(),l=t.$element.find("option"),i=l.filter(":selected"),n=l.index(i),a=0,o=t.state.multiple?[]:0;i.length>1&&t.state.multiple&&(n=[],i.each(function(){n.push(e(this).index())})),t.state.currValue=~n?n:o,t.state.selectedIdx=t.state.currValue,t.state.highlightedIdx=t.state.currValue,t.items=[],t.lookupItems=[],s.length&&(s.each(function(s){var l=e(this);if(l.is("optgroup")){var i={element:l,label:l.prop("label"),groupDisabled:l.prop("disabled"),items:[]};l.children().each(function(s){var l=e(this);i.items[s]=t.getItemData(a,l,i.groupDisabled||l.prop("disabled")),t.lookupItems[a]=i.items[s],a++}),t.items[s]=i}else t.items[s]=t.getItemData(a,l,l.prop("disabled")),t.lookupItems[a]=t.items[s],a++}),t.setLabel(),t.elements.items.append(t.elements.itemsScroll.html(t.getItemsMarkup(t.items))))},getItemData:function(t,s,l){var i=this;return{index:t,element:s,value:s.val(),className:s.prop("class"),text:s.html(),slug:e.trim(i.utils.replaceDiacritics(s.html())),alt:s.attr("data-alt"),selected:s.prop("selected"),disabled:l}},getItemsMarkup:function(t){var s=this,l="<ul>";return e.isFunction(s.options.listBuilder)&&s.options.listBuilder&&(t=s.options.listBuilder(t)),e.each(t,function(t,i){void 0!==i.label?(l+=s.utils.format('<ul class="{1}"><li class="{2}">{3}</li>',s.utils.arrayToClassname([s.classes.group,i.groupDisabled?"disabled":"",i.element.prop("class")]),s.classes.grouplabel,i.element.prop("label")),e.each(i.items,function(e,t){l+=s.getItemMarkup(t.index,t)}),l+="</ul>"):l+=s.getItemMarkup(i.index,i)}),l+"</ul>"},getItemMarkup:function(t,s){var l=this,i=l.options.optionsItemBuilder,n={value:s.value,text:s.text,slug:s.slug,index:s.index};return l.utils.format('<li data-index="{1}" class="{2}">{3}</li>',t,l.utils.arrayToClassname([s.className,t===l.items.length-1?"last":"",s.disabled?"disabled":"",s.selected?"selected":""]),e.isFunction(i)?l.utils.format(i(s,this.$element,t),s):l.utils.format(i,n))},unbindEvents:function(){var e=this;e.elements.wrapper.add(e.$element).add(e.elements.outerWrapper).add(e.elements.input).off(".sl")},bindEvents:function(){var t=this;t.elements.outerWrapper.on("mouseenter.sl mouseleave.sl",function(s){e(this).toggleClass(t.classes.hover,"mouseenter"===s.type),t.options.openOnHover&&(clearTimeout(t.closeTimer),"mouseleave"===s.type?t.closeTimer=setTimeout(e.proxy(t.close,t),t.options.hoverIntentTimeout):t.open())}),t.elements.wrapper.on("click.sl",function(e){t.state.opened?t.close():t.open(e)}),t.options.nativeOnMobile&&t.utils.isMobile()||(t.$element.on("focus.sl",function(){t.elements.input.focus()}),t.elements.input.prop({tabindex:t.originalTabindex,disabled:!1}).on("keydown.sl",e.proxy(t.handleKeys,t)).on("focusin.sl",function(e){t.elements.outerWrapper.addClass(t.classes.focus),t.elements.input.one("blur",function(){t.elements.input.blur()}),t.options.openOnFocus&&!t.state.opened&&t.open(e)}).on("focusout.sl",function(){t.elements.outerWrapper.removeClass(t.classes.focus)}).on("input propertychange",function(){var s=t.elements.input.val(),l=new RegExp("^"+t.utils.escapeRegExp(s),"i");clearTimeout(t.resetStr),t.resetStr=setTimeout(function(){t.elements.input.val("")},t.options.keySearchTimeout),s.length&&e.each(t.items,function(e,s){if(!s.disabled){if(l.test(s.text)||l.test(s.slug))return void t.highlight(e);if(s.alt)for(var i=s.alt.split("|"),n=0;n<i.length&&i[n];n++)if(l.test(i[n].trim()))return void t.highlight(e)}})})),t.$li.on({mousedown:function(e){e.preventDefault(),e.stopPropagation()},click:function(){return t.select(e(this).data("index")),!1}})},handleKeys:function(t){var s=this,l=t.which,i=s.options.keys,n=e.inArray(l,i.previous)>-1,a=e.inArray(l,i.next)>-1,o=e.inArray(l,i.select)>-1,r=e.inArray(l,i.open)>-1,u=s.state.highlightedIdx,p=n&&0===u||a&&u+1===s.items.length,c=0;if(13!==l&&32!==l||t.preventDefault(),n||a){if(!s.options.allowWrap&&p)return;n&&(c=s.utils.previousEnabledItem(s.lookupItems,u)),a&&(c=s.utils.nextEnabledItem(s.lookupItems,u)),s.highlight(c)}if(o&&s.state.opened)return s.select(u),void(s.state.multiple&&s.options.multiple.keepMenuOpen||s.close());r&&!s.state.opened&&s.open()},refresh:function(){var e=this;e.populate(),e.activate(),e.utils.triggerCallback("Refresh",e)},setOptionsDimensions:function(){var e=this,t=e.elements.items.closest(":visible").children(":hidden").addClass(e.classes.tempshow),s=e.options.maxHeight,l=e.elements.items.outerWidth(),i=e.elements.wrapper.outerWidth()-(l-e.elements.items.width());!e.options.expandToItemText||i>l?e.finalWidth=i:(e.elements.items.css("overflow","scroll"),e.elements.outerWrapper.width(9e4),e.finalWidth=e.elements.items.width(),e.elements.items.css("overflow",""),e.elements.outerWrapper.width("")),e.elements.items.width(e.finalWidth).height()>s&&e.elements.items.height(s),t.removeClass(e.classes.tempshow)},isInViewport:function(){var e=this;if(!0===e.options.forceRenderAbove)e.elements.outerWrapper.addClass(e.classes.above);else if(!0===e.options.forceRenderBelow)e.elements.outerWrapper.addClass(e.classes.below);else{var t=s.scrollTop(),l=s.height(),i=e.elements.outerWrapper.offset().top,n=e.elements.outerWrapper.outerHeight(),a=i+n+e.itemsHeight<=t+l,o=i-e.itemsHeight>t,r=!a&&o,u=!r;e.elements.outerWrapper.toggleClass(e.classes.above,r),e.elements.outerWrapper.toggleClass(e.classes.below,u)}},detectItemVisibility:function(t){var s=this,l=s.$li.filter("[data-index]");s.state.multiple&&(t=e.isArray(t)&&0===t.length?0:t,t=e.isArray(t)?Math.min.apply(Math,t):t);var i=l.eq(t).outerHeight(),n=l[t].offsetTop,a=s.elements.itemsScroll.scrollTop(),o=n+2*i;s.elements.itemsScroll.scrollTop(o>a+s.itemsHeight?o-s.itemsHeight:n-i<a?n-i:a)},open:function(s){var l=this;if(l.options.nativeOnMobile&&l.utils.isMobile())return!1;l.utils.triggerCallback("BeforeOpen",l),s&&(s.preventDefault(),l.options.stopPropagation&&s.stopPropagation()),l.state.enabled&&(l.setOptionsDimensions(),e("."+l.classes.hideselect,"."+l.classes.open).children().selectric("close"),l.state.opened=!0,l.itemsHeight=l.elements.items.outerHeight(),l.itemsInnerHeight=l.elements.items.height(),l.elements.outerWrapper.addClass(l.classes.open),l.elements.input.val(""),s&&"focusin"!==s.type&&l.elements.input.focus(),setTimeout(function(){t.on("click.sl",e.proxy(l.close,l)).on("scroll.sl",e.proxy(l.isInViewport,l))},1),l.isInViewport(),l.options.preventWindowScroll&&t.on("mousewheel.sl DOMMouseScroll.sl","."+l.classes.scroll,function(t){var s=t.originalEvent,i=e(this).scrollTop(),n=0;"detail"in s&&(n=-1*s.detail),"wheelDelta"in s&&(n=s.wheelDelta),"wheelDeltaY"in s&&(n=s.wheelDeltaY),"deltaY"in s&&(n=-1*s.deltaY),(i===this.scrollHeight-l.itemsInnerHeight&&n<0||0===i&&n>0)&&t.preventDefault()}),l.detectItemVisibility(l.state.selectedIdx),l.highlight(l.state.multiple?-1:l.state.selectedIdx),l.utils.triggerCallback("Open",l))},close:function(){var e=this;e.utils.triggerCallback("BeforeClose",e),t.off(".sl"),e.elements.outerWrapper.removeClass(e.classes.open),e.state.opened=!1,e.utils.triggerCallback("Close",e)},change:function(){var t=this;t.utils.triggerCallback("BeforeChange",t),t.state.multiple?(e.each(t.lookupItems,function(e){t.lookupItems[e].selected=!1,t.$element.find("option").prop("selected",!1)}),e.each(t.state.selectedIdx,function(e,s){t.lookupItems[s].selected=!0,t.$element.find("option").eq(s).prop("selected",!0)}),t.state.currValue=t.state.selectedIdx,t.setLabel(),t.utils.triggerCallback("Change",t)):t.state.currValue!==t.state.selectedIdx&&(t.$element.prop("selectedIndex",t.state.currValue=t.state.selectedIdx).data("value",t.lookupItems[t.state.selectedIdx].text),t.setLabel(),t.utils.triggerCallback("Change",t))},highlight:function(e){var t=this,s=t.$li.filter("[data-index]").removeClass("highlighted");t.utils.triggerCallback("BeforeHighlight",t),void 0===e||-1===e||t.lookupItems[e].disabled||(s.eq(t.state.highlightedIdx=e).addClass("highlighted"),t.detectItemVisibility(e),t.utils.triggerCallback("Highlight",t))},select:function(t){var s=this,l=s.$li.filter("[data-index]");if(s.utils.triggerCallback("BeforeSelect",s,t),void 0!==t&&-1!==t&&!s.lookupItems[t].disabled){if(s.state.multiple){s.state.selectedIdx=e.isArray(s.state.selectedIdx)?s.state.selectedIdx:[s.state.selectedIdx];var i=e.inArray(t,s.state.selectedIdx);-1!==i?s.state.selectedIdx.splice(i,1):s.state.selectedIdx.push(t),l.removeClass("selected").filter(function(t){return-1!==e.inArray(t,s.state.selectedIdx)}).addClass("selected")}else l.removeClass("selected").eq(s.state.selectedIdx=t).addClass("selected");s.state.multiple&&s.options.multiple.keepMenuOpen||s.close(),s.change(),s.utils.triggerCallback("Select",s,t)}},destroy:function(e){var t=this;t.state&&t.state.enabled&&(t.elements.items.add(t.elements.wrapper).add(t.elements.input).remove(),e||t.$element.removeData("selectric").removeData("value"),t.$element.prop("tabindex",t.originalTabindex).off(".sl").off(t.eventTriggers).unwrap().unwrap(),t.state.enabled=!1)}},e.fn.selectric=function(t){return this.each(function(){var s=e.data(this,"selectric");s&&!s.disableOnMobile?"string"==typeof t&&s[t]?s[t]():s.init(t):e.data(this,"selectric",new n(this,t))})},e.fn.selectric.defaults={onChange:function(t){e(t).change()},maxHeight:300,keySearchTimeout:500,arrowButtonMarkup:'<b class="button">&#x25be;</b>',disableOnMobile:!1,nativeOnMobile:!0,openOnFocus:!0,openOnHover:!1,hoverIntentTimeout:500,expandToItemText:!1,responsive:!1,preventWindowScroll:!0,inheritOriginalWidth:!1,allowWrap:!0,forceRenderAbove:!1,forceRenderBelow:!1,stopPropagation:!0,optionsItemBuilder:"{text}",labelBuilder:"{text}",listBuilder:!1,keys:{previous:[37,38],next:[39,40],select:[9,13,27],open:[13,32,37,38,39,40],close:[9,27]},customClass:{prefix:"selectric",camelCase:!1},multiple:{separator:", ",keepMenuOpen:!0,maxLabelEntries:!1}}});
  3970. });
  3971. </script><script>
  3972.     $('.b-search__input').attr('autocomplete','off');
  3973.     $(document).ready(function(){
  3974.    
  3975.         //setModal();
  3976.         //setTabs();
  3977.    
  3978.     });
  3979.  
  3980.    
  3981.  
  3982.     function setModalMaxHeight(element) {
  3983.  
  3984.         this.$element     = $(element);  
  3985.         this.$content     = this.$element.find('.b-modal__wrapper');
  3986.         var contentHeight = $(window).height();
  3987.         var headerHeight  = this.$element.find('.b-modal__header').outerHeight(true) || 0;
  3988.         var footerHeight  = this.$element.find('.b-modal__footer').outerHeight(true) || 0;
  3989.         var magicMargin = $(window).width() < 768 ? 0 : 70;
  3990.        var maxHeight     = contentHeight - (headerHeight + footerHeight + magicMargin);
  3991.  
  3992.        this.$content.css({
  3993.            'overflow': 'hidden'
  3994.        });
  3995.  
  3996.        this.$element
  3997.            .find('.b-modal__content').css({
  3998.                'max-height': maxHeight,
  3999.                'overflow-y': 'auto'
  4000.            });
  4001.    }
  4002.  
  4003.    $('.b-modal').on('show.bs.modal', function() {
  4004.    $(this).show();
  4005.    setModalMaxHeight(this);
  4006.    });
  4007.  
  4008.    $(window).resize(function() {
  4009.    if ($('.b-modal').length != 0) {
  4010.        $('.b-modal').each(function (index, item) {
  4011.        setModalMaxHeight(item);
  4012.        });
  4013.    }
  4014.    });  
  4015.    
  4016.    $(document)
  4017.       .on("hover", ".js-hover-active", function() {
  4018.        $(this).toggleClass("active");
  4019.        $( ".b-shadow").toggleClass("active");
  4020.      });
  4021.    
  4022.     $(".js-togg-active").mouseover(function(){
  4023.      //.on("mouseup", ".js-togg-active", function() {
  4024.        $(this).addClass("active");
  4025.      });
  4026.     $(".js-togg-active").mouseout(function(){
  4027.        $(this).removeClass("active");
  4028.      });
  4029.    
  4030.    
  4031.    $(document).on("click", ".js-open-button", function() {
  4032.      
  4033.      $(this).siblings( ".js-close-button" ).addClass("active");
  4034.      $(this).siblings( ".js-close-button" ).removeClass("hide");
  4035.      
  4036.      $(this).siblings(".js-hide").addClass("active");
  4037.      
  4038.      var _row = $(this).closest(".b-comments__table-row");
  4039.      $(_row).next(".js-hide").addClass("active");
  4040.      //$('.js-close-button, .js-hide').addClass("active");
  4041.      $(this).addClass("hide");
  4042.      //$('.js-close-button').removeClass("hide");
  4043.    });
  4044.    
  4045.    $(document).on("click", ".js-close-button", function() {
  4046.      $(this).removeClass("active");
  4047.      $(this).siblings( ".js-open-button" ).removeClass("hide");
  4048.      
  4049.      $(this).siblings(".js-hide").removeClass("active");
  4050.      
  4051.      var _row = $(this).closest(".b-comments__table-row");
  4052.      $(_row).next(".js-hide").removeClass("active");
  4053.      
  4054.      //$('.js-close-button, .js-hide').removeClass("active");
  4055.      //$('.js-open-button').removeClass("hide");
  4056.      $(this).addClass("hide");
  4057.    });
  4058.    
  4059.    $(document).on("click", ".js-open", function() {
  4060.        if ($(this).hasClass("container-open"))
  4061.        {
  4062.            $('#container_comments').toggle();
  4063.        }
  4064.        else
  4065.        {
  4066.            $('.b-competere').toggle();
  4067.        }
  4068.        $(this).toggleClass('active');
  4069.        $('.js-toggle-active').toggleClass('active');
  4070.    });
  4071.    
  4072.    $(document).on("click", ".js-togg-active", function() {
  4073.        $(this).toggleClass("active");
  4074.    });
  4075.    
  4076.    $(document).on("click", ".b-personal-info__open-button.prew", function() {
  4077.      $('.b-icon__open.little').toggleClass("active");
  4078.      $('.b-personal-info__table-row.prew').toggleClass("hide");
  4079.    });
  4080.    
  4081.    
  4082.    //menu
  4083.    /*$(function(){
  4084.      $('.b-header__toggle-menu').click(function(){
  4085.        $('.b-header__toggle-menu').toggleClass('is-close');
  4086.      });
  4087.    });
  4088.    
  4089.    $(function(){
  4090.    $(".b-header__toggle-menu").click(function(){
  4091.        $('.b-header__menu').toggleClass('active');
  4092.        $('.col-lg-9.col-md-9.hidden-xs').toggleClass('show-xs');
  4093.      });
  4094.    });
  4095.    
  4096.    
  4097.    //tabs
  4098.    /*function setTabs(){
  4099.      $(".js-tab-content").hide();
  4100.      $(".js-tab-item.active").each(function(){
  4101.        var activeTabPre = $(this).attr('rel');
  4102.        $("#"+activeTabPre).show();
  4103.      })
  4104.    
  4105.      $(".js-tab-item").click(function() {
  4106.        $(this).closest(".js-tab").next(".js-tab-group").children(".js-tab-content").hide();
  4107.        var activeTab = $(this).attr("rel");
  4108.        $("#"+activeTab).show();
  4109.    
  4110.        $(this).closest(".js-tab").find(".js-tab-item").removeClass("active");
  4111.        $(this).addClass("active");
  4112.      });
  4113.    }
  4114.    
  4115.    $(".b-textarea, .b-input").on("focusout", function () {
  4116.      $(this).css("color", "black");
  4117.    });
  4118.    
  4119.    
  4120.    // Модалки
  4121.     $(".js-open-modal").click(function(){
  4122.        $(".b-modal, .b-shadow").show();
  4123.        $("body").addClass("off-scroll");
  4124.      });
  4125.    
  4126.      $(".js-close-modal, .b-shadow").click(function(){
  4127.        $(".b-modal, .b-shadow").hide();
  4128.        $("body").removeClass("off-scroll");
  4129.      });
  4130.    
  4131.    
  4132.    
  4133.    
  4134.    /* Sticky-kit v1.1.2 */
  4135.    (function() {
  4136.      var $, win;
  4137.    
  4138.      $ = this.jQuery || window.jQuery;
  4139.    
  4140.      win = $(window);
  4141.    
  4142.      $.fn.stick_in_parent = function(opts) {
  4143.        var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, parent_selector, recalc_every, sticky_class;
  4144.        if (opts == null) {
  4145.          opts = {};
  4146.        }
  4147.        sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
  4148.        if (offset_top == null) {
  4149.          offset_top = 0;
  4150.        }
  4151.        if (parent_selector == null) {
  4152.          parent_selector = void 0;
  4153.        }
  4154.        if (inner_scrolling == null) {
  4155.          inner_scrolling = true;
  4156.        }
  4157.        if (sticky_class == null) {
  4158.          sticky_class = "is_stuck";
  4159.        }
  4160.        doc = $(document);
  4161.        if (enable_bottoming == null) {
  4162.          enable_bottoming = true;
  4163.        }
  4164.        fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
  4165.          var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
  4166.          if (elm.data("sticky_kit")) {
  4167.            return;
  4168.          }
  4169.          elm.data("sticky_kit", true);
  4170.          last_scroll_height = doc.height();
  4171.          parent = elm.parent();
  4172.          if (parent_selector != null) {
  4173.            parent = parent.closest(parent_selector);
  4174.          }
  4175.          if (!parent.length) {
  4176.            throw "failed to find stick parent";
  4177.          }
  4178.          fixed = false;
  4179.          bottomed = false;
  4180.          spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
  4181.           if (spacer) {
  4182.             spacer.css('position', elm.css('position'));
  4183.           }
  4184.           recalc = function() {
  4185.             var border_top, padding_top, restore;
  4186.             if (detached) {
  4187.               return;
  4188.             }
  4189.             last_scroll_height = doc.height();
  4190.             border_top = parseInt(parent.css("border-top-width"), 10);
  4191.             padding_top = parseInt(parent.css("padding-top"), 10);
  4192.             padding_bottom = parseInt(parent.css("padding-bottom"), 10);
  4193.             parent_top = parent.offset().top + border_top + padding_top;
  4194.             parent_height = parent.height();
  4195.             if (fixed) {
  4196.               fixed = false;
  4197.               bottomed = false;
  4198.               if (manual_spacer == null) {
  4199.                 elm.insertAfter(spacer);
  4200.                 spacer.detach();
  4201.               }
  4202.               elm.css({
  4203.                 position: "",
  4204.                 top: "",
  4205.                 width: "",
  4206.                 bottom: ""
  4207.               }).removeClass(sticky_class);
  4208.               restore = true;
  4209.             }
  4210.             top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
  4211.             height = elm.outerHeight(true);
  4212.             el_float = elm.css("float");
  4213.             if (spacer) {
  4214.               spacer.css({
  4215.                 width: elm.outerWidth(true),
  4216.                 height: height,
  4217.                 display: elm.css("display"),
  4218.                 "vertical-align": elm.css("vertical-align"),
  4219.                 "float": el_float
  4220.               });
  4221.             }
  4222.             if (restore) {
  4223.               return tick();
  4224.             }
  4225.           };
  4226.           recalc();
  4227.           if (height === parent_height) {
  4228.             return;
  4229.           }
  4230.           last_pos = void 0;
  4231.           offset = offset_top;
  4232.           recalc_counter = recalc_every;
  4233.           tick = function() {
  4234.             var css, delta, recalced, scroll, will_bottom, win_height;
  4235.             if (detached) {
  4236.               return;
  4237.             }
  4238.             recalced = false;
  4239.             if (recalc_counter != null) {
  4240.               recalc_counter -= 1;
  4241.               if (recalc_counter <= 0) {
  4242.                recalc_counter = recalc_every;
  4243.                recalc();
  4244.                recalced = true;
  4245.              }
  4246.            }
  4247.            if (!recalced && doc.height() !== last_scroll_height) {
  4248.              recalc();
  4249.              recalced = true;
  4250.            }
  4251.            scroll = win.scrollTop();
  4252.            if (last_pos != null) {
  4253.              delta = scroll - last_pos;
  4254.            }
  4255.            last_pos = scroll;
  4256.            if (fixed) {
  4257.              if (enable_bottoming) {
  4258.                will_bottom = scroll + height + offset > parent_height + parent_top;
  4259.                 if (bottomed && !will_bottom) {
  4260.                  bottomed = false;
  4261.                   elm.css({
  4262.                     position: "fixed",
  4263.                     bottom: "",
  4264.                     top: offset
  4265.                   }).trigger("sticky_kit:unbottom");
  4266.                 }
  4267.               }
  4268.               if (scroll < top) {
  4269.                fixed = false;
  4270.                offset = offset_top;
  4271.                if (manual_spacer == null) {
  4272.                  if (el_float === "left" || el_float === "right") {
  4273.                    elm.insertAfter(spacer);
  4274.                  }
  4275.                  spacer.detach();
  4276.                }
  4277.                css = {
  4278.                  position: "",
  4279.                  width: "",
  4280.                  top: ""
  4281.                };
  4282.                elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
  4283.              }
  4284.              if (inner_scrolling) {
  4285.                win_height = win.height();
  4286.                if (height + offset_top > win_height) {
  4287.                   if (!bottomed) {
  4288.                     offset -= delta;
  4289.                     offset = Math.max(win_height - height, offset);
  4290.                     offset = Math.min(offset_top, offset);
  4291.                     if (fixed) {
  4292.                       elm.css({
  4293.                         top: offset + "px"
  4294.                       });
  4295.                     }
  4296.                   }
  4297.                 }
  4298.               }
  4299.             } else {
  4300.               if (scroll > top) {
  4301.                 fixed = true;
  4302.                 css = {
  4303.                   position: "fixed",
  4304.                   top: offset
  4305.                 };
  4306.                 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
  4307.                 elm.css(css).addClass(sticky_class);
  4308.                 if (manual_spacer == null) {
  4309.                   elm.after(spacer);
  4310.                   if (el_float === "left" || el_float === "right") {
  4311.                     spacer.append(elm);
  4312.                   }
  4313.                 }
  4314.                 elm.trigger("sticky_kit:stick");
  4315.               }
  4316.             }
  4317.             if (fixed && enable_bottoming) {
  4318.              if (will_bottom == null) {
  4319.                will_bottom = scroll + height + offset > parent_height + parent_top;
  4320.               }
  4321.               if (!bottomed && will_bottom) {
  4322.                bottomed = true;
  4323.                 if (parent.css("position") === "static") {
  4324.                   parent.css({
  4325.                     position: "relative"
  4326.                   });
  4327.                 }
  4328.                 return elm.css({
  4329.                   position: "absolute",
  4330.                   bottom: padding_bottom,
  4331.                   top: "auto"
  4332.                 }).trigger("sticky_kit:bottom");
  4333.               }
  4334.             }
  4335.           };
  4336.           recalc_and_tick = function() {
  4337.             recalc();
  4338.             return tick();
  4339.           };
  4340.           detach = function() {
  4341.             detached = true;
  4342.             win.off("touchmove", tick);
  4343.             win.off("scroll", tick);
  4344.             win.off("resize", recalc_and_tick);
  4345.             $(document.body).off("sticky_kit:recalc", recalc_and_tick);
  4346.             elm.off("sticky_kit:detach", detach);
  4347.             elm.removeData("sticky_kit");
  4348.             elm.css({
  4349.               position: "",
  4350.               bottom: "",
  4351.               top: "",
  4352.               width: ""
  4353.             });
  4354.             parent.position("position", "");
  4355.             if (fixed) {
  4356.               if (manual_spacer == null) {
  4357.                 if (el_float === "left" || el_float === "right") {
  4358.                   elm.insertAfter(spacer);
  4359.                 }
  4360.                 spacer.remove();
  4361.               }
  4362.               return elm.removeClass(sticky_class);
  4363.             }
  4364.           };
  4365.           win.on("touchmove", tick);
  4366.           win.on("scroll", tick);
  4367.           win.on("resize", recalc_and_tick);
  4368.           $(document.body).on("sticky_kit:recalc", recalc_and_tick);
  4369.           elm.on("sticky_kit:detach", detach);
  4370.           return setTimeout(tick, 0);
  4371.         };
  4372.         for (i = 0, len = this.length; i < len; i++) {
  4373.          elm = this[i];
  4374.          fn($(elm));
  4375.        }
  4376.        return this;
  4377.      };
  4378.    
  4379.    }).call(this);
  4380.    
  4381.    
  4382.    
  4383.    
  4384.    /*! Selectric ϟ v1.13.0 (2017-08-22) - git.io/tjl9sQ - Copyright (c) 2017 Leonardo Santos - MIT License */
  4385.    !function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,s){return void 0===s&&(s="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(s),s}:e(jQuery)}(function(e){"use strict";var t=e(document),s=e(window),l=["a","e","i","o","u","n","c","y"],i=[/[\xE0-\xE5]/g,/[\xE8-\xEB]/g,/[\xEC-\xEF]/g,/[\xF2-\xF6]/g,/[\xF9-\xFC]/g,/[\xF1]/g,/[\xE7]/g,/[\xFD-\xFF]/g],n=function(t,s){var l=this;l.element=t,l.$element=e(t),l.state={multiple:!!l.$element.attr("multiple"),enabled:!1,opened:!1,currValue:-1,selectedIdx:-1,highlightedIdx:-1},l.eventTriggers={open:l.open,close:l.close,destroy:l.destroy,refresh:l.refresh,init:l.init},l.init(s)};n.prototype={utils:{isMobile:function(){return/android|ip(hone|od|ad)/i.test(navigator.userAgent)},escapeRegExp:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},replaceDiacritics:function(e){for(var t=i.length;t--;)e=e.toLowerCase().replace(i[t],l[t]);return e},format:function(e){var t=arguments;return(""+e).replace(/\{(?:(\d+)|(\w+))\}/g,function(e,s,l){return l&&t[1]?t[1][l]:t[s]})},nextEnabledItem:function(e,t){for(;e[t=(t+1)%e.length].disabled;);return t},previousEnabledItem:function(e,t){for(;e[t=(t>0?t:e.length)-1].disabled;);return t},toDash:function(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()},triggerCallback:function(t,s){var l=s.element,i=s.options["on"+t],n=[l].concat([].slice.call(arguments).slice(1));e.isFunction(i)&&i.apply(l,n),e(l).trigger("selectric-"+this.toDash(t),n)},arrayToClassname:function(t){var s=e.grep(t,function(e){return!!e});return e.trim(s.join(" "))}},init:function(t){var s=this;if(s.options=e.extend(!0,{},e.fn.selectric.defaults,s.options,t),s.utils.triggerCallback("BeforeInit",s),s.destroy(!0),s.options.disableOnMobile&&s.utils.isMobile())return void(s.disableOnMobile=!0);s.classes=s.getClassNames();var l=e("<input/>",{class:s.classes.input,readonly:s.utils.isMobile()}),i=e("<div/>",{class:s.classes.items,tabindex:-1}),n=e("<div/>",{class:s.classes.scroll}),a=e("<div/>",{class:s.classes.prefix,html:s.options.arrowButtonMarkup}),o=e("<span/>",{class:"label"}),r=s.$element.wrap("<div/>").parent().append(a.prepend(o),i,l),u=e("<div/>",{class:s.classes.hideselect});s.elements={input:l,items:i,itemsScroll:n,wrapper:a,label:o,outerWrapper:r},s.options.nativeOnMobile&&s.utils.isMobile()&&(s.elements.input=void 0,u.addClass(s.classes.prefix+"-is-native"),s.$element.on("change",function(){s.refresh()})),s.$element.on(s.eventTriggers).wrap(u),s.originalTabindex=s.$element.prop("tabindex"),s.$element.prop("tabindex",-1),s.populate(),s.activate(),s.utils.triggerCallback("Init",s)},activate:function(){var e=this,t=e.elements.items.closest(":visible").children(":hidden").addClass(e.classes.tempshow),s=e.$element.width();t.removeClass(e.classes.tempshow),e.utils.triggerCallback("BeforeActivate",e),e.elements.outerWrapper.prop("class",e.utils.arrayToClassname([e.classes.wrapper,e.$element.prop("class").replace(/\S+/g,e.classes.prefix+"-$&"),e.options.responsive?e.classes.responsive:""])),e.options.inheritOriginalWidth&&s>0&&e.elements.outerWrapper.width(s),e.unbindEvents(),e.$element.prop("disabled")?(e.elements.outerWrapper.addClass(e.classes.disabled),e.elements.input&&e.elements.input.prop("disabled",!0)):(e.state.enabled=!0,e.elements.outerWrapper.removeClass(e.classes.disabled),e.$li=e.elements.items.removeAttr("style").find("li"),e.bindEvents()),e.utils.triggerCallback("Activate",e)},getClassNames:function(){var t=this,s=t.options.customClass,l={};return e.each("Input Items Open Disabled TempShow HideSelect Wrapper Focus Hover Responsive Above Below Scroll Group GroupLabel".split(" "),function(e,i){var n=s.prefix+i;l[i.toLowerCase()]=s.camelCase?n:t.utils.toDash(n)}),l.prefix=s.prefix,l},setLabel:function(){var t=this,s=t.options.labelBuilder;if(t.state.multiple){var l=e.isArray(t.state.currValue)?t.state.currValue:[t.state.currValue];l=0===l.length?[0]:l;var i=e.map(l,function(s){return e.grep(t.lookupItems,function(e){return e.index===s})[0]});i=e.grep(i,function(t){return i.length>1||0===i.length?""!==e.trim(t.value):t}),i=e.map(i,function(l){return e.isFunction(s)?s(l):t.utils.format(s,l)}),t.options.multiple.maxLabelEntries&&(i.length>=t.options.multiple.maxLabelEntries+1?(i=i.slice(0,t.options.multiple.maxLabelEntries),i.push(e.isFunction(s)?s({text:"..."}):t.utils.format(s,{text:"..."}))):i.slice(i.length-1)),t.elements.label.html(i.join(t.options.multiple.separator))}else{var n=t.lookupItems[t.state.currValue];t.elements.label.html(e.isFunction(s)?s(n):t.utils.format(s,n))}},populate:function(){var t=this,s=t.$element.children(),l=t.$element.find("option"),i=l.filter(":selected"),n=l.index(i),a=0,o=t.state.multiple?[]:0;i.length>1&&t.state.multiple&&(n=[],i.each(function(){n.push(e(this).index())})),t.state.currValue=~n?n:o,t.state.selectedIdx=t.state.currValue,t.state.highlightedIdx=t.state.currValue,t.items=[],t.lookupItems=[],s.length&&(s.each(function(s){var l=e(this);if(l.is("optgroup")){var i={element:l,label:l.prop("label"),groupDisabled:l.prop("disabled"),items:[]};l.children().each(function(s){var l=e(this);i.items[s]=t.getItemData(a,l,i.groupDisabled||l.prop("disabled")),t.lookupItems[a]=i.items[s],a++}),t.items[s]=i}else t.items[s]=t.getItemData(a,l,l.prop("disabled")),t.lookupItems[a]=t.items[s],a++}),t.setLabel(),t.elements.items.append(t.elements.itemsScroll.html(t.getItemsMarkup(t.items))))},getItemData:function(t,s,l){var i=this;return{index:t,element:s,value:s.val(),className:s.prop("class"),text:s.html(),slug:e.trim(i.utils.replaceDiacritics(s.html())),alt:s.attr("data-alt"),selected:s.prop("selected"),disabled:l}},getItemsMarkup:function(t){var s=this,l="<ul>";return e.isFunction(s.options.listBuilder)&&s.options.listBuilder&&(t=s.options.listBuilder(t)),e.each(t,function(t,i){void 0!==i.label?(l+=s.utils.format('<ul class="{1}"><li class="{2}">{3}</li>',s.utils.arrayToClassname([s.classes.group,i.groupDisabled?"disabled":"",i.element.prop("class")]),s.classes.grouplabel,i.element.prop("label")),e.each(i.items,function(e,t){l+=s.getItemMarkup(t.index,t)}),l+="</ul>"):l+=s.getItemMarkup(i.index,i)}),l+"</ul>"},getItemMarkup:function(t,s){var l=this,i=l.options.optionsItemBuilder,n={value:s.value,text:s.text,slug:s.slug,index:s.index};return l.utils.format('<li data-index="{1}" class="{2}">{3}</li>',t,l.utils.arrayToClassname([s.className,t===l.items.length-1?"last":"",s.disabled?"disabled":"",s.selected?"selected":""]),e.isFunction(i)?l.utils.format(i(s,this.$element,t),s):l.utils.format(i,n))},unbindEvents:function(){var e=this;e.elements.wrapper.add(e.$element).add(e.elements.outerWrapper).add(e.elements.input).off(".sl")},bindEvents:function(){var t=this;t.elements.outerWrapper.on("mouseenter.sl mouseleave.sl",function(s){e(this).toggleClass(t.classes.hover,"mouseenter"===s.type),t.options.openOnHover&&(clearTimeout(t.closeTimer),"mouseleave"===s.type?t.closeTimer=setTimeout(e.proxy(t.close,t),t.options.hoverIntentTimeout):t.open())}),t.elements.wrapper.on("click.sl",function(e){t.state.opened?t.close():t.open(e)}),t.options.nativeOnMobile&&t.utils.isMobile()||(t.$element.on("focus.sl",function(){t.elements.input.focus()}),t.elements.input.prop({tabindex:t.originalTabindex,disabled:!1}).on("keydown.sl",e.proxy(t.handleKeys,t)).on("focusin.sl",function(e){t.elements.outerWrapper.addClass(t.classes.focus),t.elements.input.one("blur",function(){t.elements.input.blur()}),t.options.openOnFocus&&!t.state.opened&&t.open(e)}).on("focusout.sl",function(){t.elements.outerWrapper.removeClass(t.classes.focus)}).on("input propertychange",function(){var s=t.elements.input.val(),l=new RegExp("^"+t.utils.escapeRegExp(s),"i");clearTimeout(t.resetStr),t.resetStr=setTimeout(function(){t.elements.input.val("")},t.options.keySearchTimeout),s.length&&e.each(t.items,function(e,s){if(!s.disabled){if(l.test(s.text)||l.test(s.slug))return void t.highlight(e);if(s.alt)for(var i=s.alt.split("|"),n=0;n<i.length&&i[n];n++)if(l.test(i[n].trim()))return void t.highlight(e)}})})),t.$li.on({mousedown:function(e){e.preventDefault(),e.stopPropagation()},click:function(){return t.select(e(this).data("index")),!1}})},handleKeys:function(t){var s=this,l=t.which,i=s.options.keys,n=e.inArray(l,i.previous)>-1,a=e.inArray(l,i.next)>-1,o=e.inArray(l,i.select)>-1,r=e.inArray(l,i.open)>-1,u=s.state.highlightedIdx,p=n&&0===u||a&&u+1===s.items.length,c=0;if(13!==l&&32!==l||t.preventDefault(),n||a){if(!s.options.allowWrap&&p)return;n&&(c=s.utils.previousEnabledItem(s.lookupItems,u)),a&&(c=s.utils.nextEnabledItem(s.lookupItems,u)),s.highlight(c)}if(o&&s.state.opened)return s.select(u),void(s.state.multiple&&s.options.multiple.keepMenuOpen||s.close());r&&!s.state.opened&&s.open()},refresh:function(){var e=this;e.populate(),e.activate(),e.utils.triggerCallback("Refresh",e)},setOptionsDimensions:function(){var e=this,t=e.elements.items.closest(":visible").children(":hidden").addClass(e.classes.tempshow),s=e.options.maxHeight,l=e.elements.items.outerWidth(),i=e.elements.wrapper.outerWidth()-(l-e.elements.items.width());!e.options.expandToItemText||i>l?e.finalWidth=i:(e.elements.items.css("overflow","scroll"),e.elements.outerWrapper.width(9e4),e.finalWidth=e.elements.items.width(),e.elements.items.css("overflow",""),e.elements.outerWrapper.width("")),e.elements.items.width(e.finalWidth).height()>s&&e.elements.items.height(s),t.removeClass(e.classes.tempshow)},isInViewport:function(){var e=this;if(!0===e.options.forceRenderAbove)e.elements.outerWrapper.addClass(e.classes.above);else if(!0===e.options.forceRenderBelow)e.elements.outerWrapper.addClass(e.classes.below);else{var t=s.scrollTop(),l=s.height(),i=e.elements.outerWrapper.offset().top,n=e.elements.outerWrapper.outerHeight(),a=i+n+e.itemsHeight<=t+l,o=i-e.itemsHeight>t,r=!a&&o,u=!r;e.elements.outerWrapper.toggleClass(e.classes.above,r),e.elements.outerWrapper.toggleClass(e.classes.below,u)}},detectItemVisibility:function(t){var s=this,l=s.$li.filter("[data-index]");s.state.multiple&&(t=e.isArray(t)&&0===t.length?0:t,t=e.isArray(t)?Math.min.apply(Math,t):t);var i=l.eq(t).outerHeight(),n=l[t].offsetTop,a=s.elements.itemsScroll.scrollTop(),o=n+2*i;s.elements.itemsScroll.scrollTop(o>a+s.itemsHeight?o-s.itemsHeight:n-i<a?n-i:a)},open:function(s){var l=this;if(l.options.nativeOnMobile&&l.utils.isMobile())return!1;l.utils.triggerCallback("BeforeOpen",l),s&&(s.preventDefault(),l.options.stopPropagation&&s.stopPropagation()),l.state.enabled&&(l.setOptionsDimensions(),e("."+l.classes.hideselect,"."+l.classes.open).children().selectric("close"),l.state.opened=!0,l.itemsHeight=l.elements.items.outerHeight(),l.itemsInnerHeight=l.elements.items.height(),l.elements.outerWrapper.addClass(l.classes.open),l.elements.input.val(""),s&&"focusin"!==s.type&&l.elements.input.focus(),setTimeout(function(){t.on("click.sl",e.proxy(l.close,l)).on("scroll.sl",e.proxy(l.isInViewport,l))},1),l.isInViewport(),l.options.preventWindowScroll&&t.on("mousewheel.sl DOMMouseScroll.sl","."+l.classes.scroll,function(t){var s=t.originalEvent,i=e(this).scrollTop(),n=0;"detail"in s&&(n=-1*s.detail),"wheelDelta"in s&&(n=s.wheelDelta),"wheelDeltaY"in s&&(n=s.wheelDeltaY),"deltaY"in s&&(n=-1*s.deltaY),(i===this.scrollHeight-l.itemsInnerHeight&&n<0||0===i&&n>0)&&t.preventDefault()}),l.detectItemVisibility(l.state.selectedIdx),l.highlight(l.state.multiple?-1:l.state.selectedIdx),l.utils.triggerCallback("Open",l))},close:function(){var e=this;e.utils.triggerCallback("BeforeClose",e),t.off(".sl"),e.elements.outerWrapper.removeClass(e.classes.open),e.state.opened=!1,e.utils.triggerCallback("Close",e)},change:function(){var t=this;t.utils.triggerCallback("BeforeChange",t),t.state.multiple?(e.each(t.lookupItems,function(e){t.lookupItems[e].selected=!1,t.$element.find("option").prop("selected",!1)}),e.each(t.state.selectedIdx,function(e,s){t.lookupItems[s].selected=!0,t.$element.find("option").eq(s).prop("selected",!0)}),t.state.currValue=t.state.selectedIdx,t.setLabel(),t.utils.triggerCallback("Change",t)):t.state.currValue!==t.state.selectedIdx&&(t.$element.prop("selectedIndex",t.state.currValue=t.state.selectedIdx).data("value",t.lookupItems[t.state.selectedIdx].text),t.setLabel(),t.utils.triggerCallback("Change",t))},highlight:function(e){var t=this,s=t.$li.filter("[data-index]").removeClass("highlighted");t.utils.triggerCallback("BeforeHighlight",t),void 0===e||-1===e||t.lookupItems[e].disabled||(s.eq(t.state.highlightedIdx=e).addClass("highlighted"),t.detectItemVisibility(e),t.utils.triggerCallback("Highlight",t))},select:function(t){var s=this,l=s.$li.filter("[data-index]");if(s.utils.triggerCallback("BeforeSelect",s,t),void 0!==t&&-1!==t&&!s.lookupItems[t].disabled){if(s.state.multiple){s.state.selectedIdx=e.isArray(s.state.selectedIdx)?s.state.selectedIdx:[s.state.selectedIdx];var i=e.inArray(t,s.state.selectedIdx);-1!==i?s.state.selectedIdx.splice(i,1):s.state.selectedIdx.push(t),l.removeClass("selected").filter(function(t){return-1!==e.inArray(t,s.state.selectedIdx)}).addClass("selected")}else l.removeClass("selected").eq(s.state.selectedIdx=t).addClass("selected");s.state.multiple&&s.options.multiple.keepMenuOpen||s.close(),s.change(),s.utils.triggerCallback("Select",s,t)}},destroy:function(e){var t=this;t.state&&t.state.enabled&&(t.elements.items.add(t.elements.wrapper).add(t.elements.input).remove(),e||t.$element.removeData("selectric").removeData("value"),t.$element.prop("tabindex",t.originalTabindex).off(".sl").off(t.eventTriggers).unwrap().unwrap(),t.state.enabled=!1)}},e.fn.selectric=function(t){return this.each(function(){var s=e.data(this,"selectric");s&&!s.disableOnMobile?"string"==typeof t&&s[t]?s[t]():s.init(t):e.data(this,"selectric",new n(this,t))})},e.fn.selectric.defaults={onChange:function(t){e(t).change()},maxHeight:300,keySearchTimeout:500,arrowButtonMarkup:'<b class="button">&#x25be;</b>',disableOnMobile:!1,nativeOnMobile:!0,openOnFocus:!0,openOnHover:!1,hoverIntentTimeout:500,expandToItemText:!1,responsive:!1,preventWindowScroll:!0,inheritOriginalWidth:!1,allowWrap:!0,forceRenderAbove:!1,forceRenderBelow:!1,stopPropagation:!0,optionsItemBuilder:"{text}",labelBuilder:"{text}",listBuilder:!1,keys:{previous:[37,38],next:[39,40],select:[9,13,27],open:[13,32,37,38,39,40],close:[9,27]},customClass:{prefix:"selectric",camelCase:!1},multiple:{separator:", ",keepMenuOpen:!0,maxLabelEntries:!1}}});
  4386.    
  4387.    
  4388.    
  4389.     /*
  4390.      * jQuery autoResize (textarea auto-resizer)
  4391.      * @copyright James Padolsey http://james.padolsey.com
  4392.      * @version 1.04
  4393.      */
  4394.    
  4395.     (function($){
  4396.        
  4397.         $.fn.autoResize = function(options) {
  4398.            
  4399.             // Just some abstracted details,
  4400.             // to make plugin users happy:
  4401.             var settings = $.extend({
  4402.                 onResize : function(){
  4403.              
  4404.           },
  4405.                 animate : true,
  4406.                 animateDuration : 150,
  4407.                 animateCallback : function(){},
  4408.                 extraSpace : 20,
  4409.                 limit: 1000
  4410.             }, options);
  4411.            
  4412.             // Only textarea's auto-resize:
  4413.             this.filter('textarea').each(function(){
  4414.                
  4415.                     // Get rid of scrollbars and disable WebKit resizing:
  4416.                 var textarea = $(this).css({resize:'none','overflow-y':'hidden'}),
  4417.                
  4418.                     // Cache original height, for use later:
  4419.                     origHeight = textarea.height(),
  4420.            
  4421.                            
  4422.                     // Need clone of textarea, hidden off screen:
  4423.                     clone = (function(){
  4424.    
  4425.                         // Properties which may effect space taken up by chracters:
  4426.                         var props = ['height','width','lineHeight','textDecoration','letterSpacing'],
  4427.                             propOb = {};
  4428.      
  4429.                         // Create object of styles to apply:
  4430.                         $.each(props, function(i, prop){
  4431.                             propOb[prop] = textarea.css(prop);
  4432.                         });
  4433.                        
  4434.                         // Clone the actual textarea removing unique properties
  4435.                         // and insert before original textarea:
  4436.                         return textarea.clone().removeAttr('id').removeAttr('name').css({
  4437.                             position: 'absolute',
  4438.                             top: 0,
  4439.                             left: -9999
  4440.                         }).css(propOb).attr('tabIndex','-1').insertBefore(textarea);
  4441.              
  4442.                     })(),
  4443.                     lastScrollTop = null,
  4444.                     updateSize = function() {
  4445.                         // Prepare the clone:
  4446.                         clone.height(0).val($(this).val()).scrollTop(10000);
  4447.              
  4448.                         // Find the height of text:
  4449.                         var scrollTop = Math.max(clone.scrollTop(), origHeight) + settings.extraSpace,
  4450.                             toChange = $(this).add(clone);
  4451.                
  4452.                         // Don't do anything if scrollTip hasen't changed:
  4453.                         if (lastScrollTop === scrollTop) { return; }
  4454.                         lastScrollTop = scrollTop;
  4455.              
  4456.                         // Check for limit:
  4457.                         if ( scrollTop >= settings.limit ) {
  4458.                             $(this).css('overflow-y','');
  4459.                             return;
  4460.                         }
  4461.                         // Fire off callback:
  4462.                         settings.onResize.call(this);
  4463.              
  4464.                         // Either animate or directly apply height:
  4465.                        settings.animate && textarea.css('display') === 'block' ?
  4466.                            toChange.stop().animate({height:scrollTop}, settings.animateDuration, settings.animateCallback)
  4467.                            : toChange.height(scrollTop);
  4468.                
  4469.              
  4470.                     };
  4471.                                      
  4472.                 // Bind namespaced handlers to appropriate events:
  4473.                 textarea
  4474.                     .unbind('.dynSiz')
  4475.                     .bind('keyup.dynSiz', updateSize)
  4476.                     .bind('keydown.dynSiz', updateSize)
  4477.                     .bind('change.dynSiz', updateSize);
  4478.                
  4479.             });
  4480.            
  4481.             // Chain:
  4482.             return this;
  4483.            
  4484.         };
  4485.        
  4486.        
  4487.        
  4488.     })(jQuery);/*
  4489.      * jQuery autoResize (textarea auto-resizer)
  4490.      * @copyright James Padolsey http://james.padolsey.com
  4491.      * @version 1.04
  4492.      */
  4493.    
  4494.     (function($){
  4495.        
  4496.         $.fn.autoResize = function(options) {
  4497.            
  4498.             // Just some abstracted details,
  4499.             // to make plugin users happy:
  4500.             var settings = $.extend({
  4501.                 onResize : function(){
  4502.              
  4503.           },
  4504.                 animate : true,
  4505.                 animateDuration : 150,
  4506.                 animateCallback : function(){},
  4507.                 extraSpace : 20,
  4508.                 limit: 1000
  4509.             }, options);
  4510.            
  4511.             // Only textarea's auto-resize:
  4512.             this.filter('textarea').each(function(){
  4513.                
  4514.                     // Get rid of scrollbars and disable WebKit resizing:
  4515.                 var textarea = $(this).css({resize:'none','overflow-y':'hidden'}),
  4516.                
  4517.                     // Cache original height, for use later:
  4518.                     origHeight = textarea.height(),
  4519.            
  4520.                            
  4521.                     // Need clone of textarea, hidden off screen:
  4522.                     clone = (function(){
  4523.    
  4524.                         // Properties which may effect space taken up by chracters:
  4525.                         var props = ['height','width','lineHeight','textDecoration','letterSpacing'],
  4526.                             propOb = {};
  4527.      
  4528.                         // Create object of styles to apply:
  4529.                         $.each(props, function(i, prop){
  4530.                             propOb[prop] = textarea.css(prop);
  4531.                         });
  4532.                        
  4533.                         // Clone the actual textarea removing unique properties
  4534.                         // and insert before original textarea:
  4535.                         return textarea.clone().removeAttr('id').removeAttr('name').css({
  4536.                             position: 'absolute',
  4537.                             top: 0,
  4538.                             left: -9999
  4539.                         }).css(propOb).attr('tabIndex','-1').insertBefore(textarea);
  4540.              
  4541.                     })(),
  4542.                     lastScrollTop = null,
  4543.                     updateSize = function() {
  4544.                         // Prepare the clone:
  4545.                         clone.height(0).val($(this).val()).scrollTop(10000);
  4546.              
  4547.                         // Find the height of text:
  4548.                         var scrollTop = Math.max(clone.scrollTop(), origHeight) + settings.extraSpace,
  4549.                             toChange = $(this).add(clone);
  4550.                
  4551.                         // Don't do anything if scrollTip hasen't changed:
  4552.                         if (lastScrollTop === scrollTop) { return; }
  4553.                         lastScrollTop = scrollTop;
  4554.              
  4555.                         // Check for limit:
  4556.                         if ( scrollTop >= settings.limit ) {
  4557.                             $(this).css('overflow-y','');
  4558.                             return;
  4559.                         }
  4560.                         // Fire off callback:
  4561.                         settings.onResize.call(this);
  4562.              
  4563.                         // Either animate or directly apply height:
  4564.                        settings.animate && textarea.css('display') === 'block' ?
  4565.                            toChange.stop().animate({height:scrollTop}, settings.animateDuration, settings.animateCallback)
  4566.                            : toChange.height(scrollTop);
  4567.                
  4568.              
  4569.                     };
  4570.                                      
  4571.                 // Bind namespaced handlers to appropriate events:
  4572.                 textarea
  4573.                     .unbind('.dynSiz')
  4574.                     .bind('keyup.dynSiz', updateSize)
  4575.                     .bind('keydown.dynSiz', updateSize)
  4576.                     .bind('change.dynSiz', updateSize);
  4577.                
  4578.             });
  4579.            
  4580.             // Chain:
  4581.             return this;
  4582.            
  4583.         };
  4584.        
  4585.        
  4586.        
  4587.     })(jQuery);
  4588.    
  4589.    
  4590.    
  4591.     /*!
  4592.      * jQuery UI Touch Punch 0.2.3
  4593.      *
  4594.      * Copyright 2011–2014, Dave Furfero
  4595.      * Dual licensed under the MIT or GPL Version 2 licenses.
  4596.      *
  4597.      * Depends:
  4598.      *  jquery.ui.widget.js
  4599.      *  jquery.ui.mouse.js
  4600.      */
  4601.     !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
  4602.    
  4603.     </script><script>
  4604. /*!
  4605.  * Masonry PACKAGED v3.3.2
  4606.  * Cascading grid layout library
  4607.  * http://masonry.desandro.com
  4608.  * MIT License
  4609.  * by David DeSandro
  4610.  */
  4611.  
  4612. !function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}return this.each(function(){var d=a.data(this,b);d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d))})}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;"function"==typeof define&&define.amd?define("jquery-bridget/jquery.bridget",["jquery"],c):c("object"==typeof exports?require("jquery"):a.jQuery)}(window),function(a){function b(b){var c=a.event;return c.target=c.target||c.srcElement||b,c}var c=document.documentElement,d=function(){};c.addEventListener?d=function(a,b,c){a.addEventListener(b,c,!1)}:c.attachEvent&&(d=function(a,c,d){a[c+d]=d.handleEvent?function(){var c=b(a);d.handleEvent.call(d,c)}:function(){var c=b(a);d.call(a,c)},a.attachEvent("on"+c,a[c+d])});var e=function(){};c.removeEventListener?e=function(a,b,c){a.removeEventListener(b,c,!1)}:c.detachEvent&&(e=function(a,b,c){a.detachEvent("on"+b,a[b+c]);try{delete a[b+c]}catch(d){a[b+c]=void 0}});var f={bind:d,unbind:e};"function"==typeof define&&define.amd?define("eventie/eventie",f):"object"==typeof exports?module.exports=f:a.eventie=f}(window),function(){function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;b<a.length;b+=1)c.push(a[b].listener);return c},d.getListenersAsObject=function(a){var b,c=this.getListeners(a);return c instanceof Array&&(b={},b[a]=c),b||c},d.addListener=function(a,c){var d,e=this.getListenersAsObject(a),f="object"==typeof c;for(d in e)e.hasOwnProperty(d)&&-1===b(e[d],c)&&e[d].push(f?c:{listener:c,once:!1});return this},d.on=c("addListener"),d.addOnceListener=function(a,b){return this.addListener(a,{listener:b,once:!0})},d.once=c("addOnceListener"),d.defineEvent=function(a){return this.getListeners(a),this},d.defineEvents=function(a){for(var b=0;b<a.length;b+=1)this.defineEvent(a[b]);return this},d.removeListener=function(a,c){var d,e,f=this.getListenersAsObject(a);for(e in f)f.hasOwnProperty(e)&&(d=b(f[e],c),-1!==d&&f[e].splice(d,1));return this},d.off=c("removeListener"),d.addListeners=function(a,b){return this.manipulateListeners(!1,a,b)},d.removeListeners=function(a,b){return this.manipulateListeners(!0,a,b)},d.manipulateListeners=function(a,b,c){var d,e,f=a?this.removeListener:this.addListener,g=a?this.removeListeners:this.addListeners;if("object"!=typeof b||b instanceof RegExp)for(d=c.length;d--;)f.call(this,b,c[d]);else for(d in b)b.hasOwnProperty(d)&&(e=b[d])&&("function"==typeof e?f.call(this,d,e):g.call(this,d,e));return this},d.removeEvent=function(a){var b,c=typeof a,d=this._getEvents();if("string"===c)delete d[a];else if(a instanceof RegExp)for(b in d)d.hasOwnProperty(b)&&a.test(b)&&delete d[b];else delete this._events;return this},d.removeAllListeners=c("removeEvent"),d.emitEvent=function(a,b){var c,d,e,f,g=this.getListenersAsObject(a);for(e in g)if(g.hasOwnProperty(e))for(d=g[e].length;d--;)c=g[e][d],c.once===!0&&this.removeListener(a,c.listener),f=c.listener.apply(this,b||[]),f===this._getOnceReturnValue()&&this.removeListener(a,c.listener);return this},d.trigger=c("emitEvent"),d.emit=function(a){var b=Array.prototype.slice.call(arguments,1);return this.emitEvent(a,b)},d.setOnceReturnValue=function(a){return this._onceReturnValue=a,this},d._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},d._getEvents=function(){return this._events||(this._events={})},a.noConflict=function(){return e.EventEmitter=f,a},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return a}):"object"==typeof module&&module.exports?module.exports=a:e.EventEmitter=a}.call(this),function(a){function b(a){if(a){if("string"==typeof d[a])return a;a=a.charAt(0).toUpperCase()+a.slice(1);for(var b,e=0,f=c.length;f>e;e++)if(b=c[e]+a,"string"==typeof d[b])return b}}var c="Webkit Moz ms Ms O".split(" "),d=document.documentElement.style;"function"==typeof define&&define.amd?define("get-style-property/get-style-property",[],function(){return b}):"object"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a){function b(a){var b=parseFloat(a),c=-1===a.indexOf("%")&&!isNaN(b);return c&&b}function c(){}function d(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=g.length;c>b;b++){var d=g[b];a[d]=0}return a}function e(c){function e(){if(!m){m=!0;var d=a.getComputedStyle;if(j=function(){var a=d?function(a){return d(a,null)}:function(a){return a.currentStyle};return function(b){var c=a(b);return c||f("Style returned "+c+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),c}}(),k=c("boxSizing")){var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style[k]="border-box";var g=document.body||document.documentElement;g.appendChild(e);var h=j(e);l=200===b(h.width),g.removeChild(e)}}}function h(a){if(e(),"string"==typeof a&&(a=document.querySelector(a)),a&&"object"==typeof a&&a.nodeType){var c=j(a);if("none"===c.display)return d();var f={};f.width=a.offsetWidth,f.height=a.offsetHeight;for(var h=f.isBorderBox=!(!k||!c[k]||"border-box"!==c[k]),m=0,n=g.length;n>m;m++){var o=g[m],p=c[o];p=i(a,p);var q=parseFloat(p);f[o]=isNaN(q)?0:q}var r=f.paddingLeft+f.paddingRight,s=f.paddingTop+f.paddingBottom,t=f.marginLeft+f.marginRight,u=f.marginTop+f.marginBottom,v=f.borderLeftWidth+f.borderRightWidth,w=f.borderTopWidth+f.borderBottomWidth,x=h&&l,y=b(c.width);y!==!1&&(f.width=y+(x?0:r+v));var z=b(c.height);return z!==!1&&(f.height=z+(x?0:s+w)),f.innerWidth=f.width-(r+v),f.innerHeight=f.height-(s+w),f.outerWidth=f.width+t,f.outerHeight=f.height+u,f}}function i(b,c){if(a.getComputedStyle||-1===c.indexOf("%"))return c;var d=b.style,e=d.left,f=b.runtimeStyle,g=f&&f.left;return g&&(f.left=b.currentStyle.left),d.left=c,c=d.pixelLeft,d.left=e,g&&(f.left=g),c}var j,k,l,m=!1;return h}var f="undefined"==typeof console?c:function(a){console.error(a)},g=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define("get-size/get-size",["get-style-property/get-style-property"],e):"object"==typeof exports?module.exports=e(require("desandro-get-style-property")):a.getSize=e(a.getStyleProperty)}(window),function(a){function b(a){"function"==typeof a&&(b.isReady?a():g.push(a))}function c(a){var c="readystatechange"===a.type&&"complete"!==f.readyState;b.isReady||c||d()}function d(){b.isReady=!0;for(var a=0,c=g.length;c>a;a++){var d=g[a];d()}}function e(e){return"complete"===f.readyState?d():(e.bind(f,"DOMContentLoaded",c),e.bind(f,"readystatechange",c),e.bind(a,"load",c)),b}var f=a.document,g=[];b.isReady=!1,"function"==typeof define&&define.amd?define("doc-ready/doc-ready",["eventie/eventie"],e):"object"==typeof exports?module.exports=e(require("eventie")):a.docReady=e(a.eventie)}(window),function(a){function b(a,b){return a[g](b)}function c(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function d(a,b){c(a);for(var d=a.parentNode.querySelectorAll(b),e=0,f=d.length;f>e;e++)if(d[e]===a)return!0;return!1}function e(a,d){return c(a),b(a,d)}var f,g=function(){if(a.matches)return"matches";if(a.matchesSelector)return"matchesSelector";for(var b=["webkit","moz","ms","o"],c=0,d=b.length;d>c;c++){var e=b[c],f=e+"MatchesSelector";if(a[f])return f}}();if(g){var h=document.createElement("div"),i=b(h,"div");f=i?b:e}else f=d;"function"==typeof define&&define.amd?define("matches-selector/matches-selector",[],function(){return f}):"object"==typeof exports?module.exports=f:window.matchesSelector=f}(Element.prototype),function(a,b){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["doc-ready/doc-ready","matches-selector/matches-selector"],function(c,d){return b(a,c,d)}):"object"==typeof exports?module.exports=b(a,require("doc-ready"),require("desandro-matches-selector")):a.fizzyUIUtils=b(a,a.docReady,a.matchesSelector)}(window,function(a,b,c){var d={};d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.modulo=function(a,b){return(a%b+b)%b};var e=Object.prototype.toString;d.isArray=function(a){return"[object Array]"==e.call(a)},d.makeArray=function(a){var b=[];if(d.isArray(a))b=a;else if(a&&"number"==typeof a.length)for(var c=0,e=a.length;e>c;c++)b.push(a[c]);else b.push(a);return b},d.indexOf=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},d.removeFrom=function(a,b){var c=d.indexOf(a,b);-1!=c&&a.splice(c,1)},d.isElement="function"==typeof HTMLElement||"object"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&"object"==typeof a&&1==a.nodeType&&"string"==typeof a.nodeName},d.setText=function(){function a(a,c){b=b||(void 0!==document.documentElement.textContent?"textContent":"innerText"),a[b]=c}var b;return a}(),d.getParent=function(a,b){for(;a!=document.body;)if(a=a.parentNode,c(a,b))return a},d.getQueryElement=function(a){return"string"==typeof a?document.querySelector(a):a},d.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},d.filterFindElements=function(a,b){a=d.makeArray(a);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f];if(d.isElement(h))if(b){c(h,b)&&e.push(h);for(var i=h.querySelectorAll(b),j=0,k=i.length;k>j;j++)e.push(i[j])}else e.push(h)}return e},d.debounceMethod=function(a,b,c){var d=a.prototype[b],e=b+"Timeout";a.prototype[b]=function(){var a=this[e];a&&clearTimeout(a);var b=arguments,f=this;this[e]=setTimeout(function(){d.apply(f,b),delete f[e]},c||100)}},d.toDashed=function(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()};var f=a.console;return d.htmlInit=function(c,e){b(function(){for(var b=d.toDashed(e),g=document.querySelectorAll(".js-"+b),h="data-"+b+"-options",i=0,j=g.length;j>i;i++){var k,l=g[i],m=l.getAttribute(h);try{k=m&&JSON.parse(m)}catch(n){f&&f.error("Error parsing "+h+" on "+l.nodeName.toLowerCase()+(l.id?"#"+l.id:"")+": "+n);continue}var o=new c(l,k),p=a.jQuery;p&&p.data(l,e,o)}})},d}),function(a,b){"function"==typeof define&&define.amd?define("outlayer/item",["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property","fizzy-ui-utils/utils"],function(c,d,e,f){return b(a,c,d,e,f)}):"object"==typeof exports?module.exports=b(a,require("wolfy87-eventemitter"),require("get-size"),require("desandro-get-style-property"),require("fizzy-ui-utils")):(a.Outlayer={},a.Outlayer.Item=b(a,a.EventEmitter,a.getSize,a.getStyleProperty,a.fizzyUIUtils))}(window,function(a,b,c,d,e){function f(a){for(var b in a)return!1;return b=null,!0}function g(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}function h(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}var i=a.getComputedStyle,j=i?function(a){return i(a,null)}:function(a){return a.currentStyle},k=d("transition"),l=d("transform"),m=k&&l,n=!!d("perspective"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[k],p=["transform","transition","transitionDuration","transitionProperty"],q=function(){for(var a={},b=0,c=p.length;c>b;b++){var e=p[b],f=d(e);f&&f!==e&&(a[e]=f)}return a}();e.extend(g.prototype,b.prototype),g.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.getSize=function(){this.size=c(this.element)},g.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=q[c]||c;b[d]=a[c]}},g.prototype.getPosition=function(){var a=j(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=a[c?"left":"right"],f=a[d?"top":"bottom"],g=this.layout.size,h=-1!=e.indexOf("%")?parseFloat(e)/100*g.width:parseInt(e,10),i=-1!=f.indexOf("%")?parseFloat(f)/100*g.height:parseInt(f,10);h=isNaN(h)?0:h,i=isNaN(i)?0:i,h-=c?g.paddingLeft:g.paddingRight,i-=d?g.paddingTop:g.paddingBottom,this.position.x=h,this.position.y=i},g.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={},d=b.isOriginLeft?"paddingLeft":"paddingRight",e=b.isOriginLeft?"left":"right",f=b.isOriginLeft?"right":"left",g=this.position.x+a[d];c[e]=this.getXValue(g),c[f]="";var h=b.isOriginTop?"paddingTop":"paddingBottom",i=b.isOriginTop?"top":"bottom",j=b.isOriginTop?"bottom":"top",k=this.position.y+a[h];c[i]=this.getYValue(k),c[j]="",this.css(c),this.emitEvent("layout",[this])},g.prototype.getXValue=function(a){var b=this.layout.options;return b.percentPosition&&!b.isHorizontal?a/this.layout.size.width*100+"%":a+"px"},g.prototype.getYValue=function(a){var b=this.layout.options;return b.percentPosition&&b.isHorizontal?a/this.layout.size.height*100+"%":a+"px"},g.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={};j.transform=this.getTranslate(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},g.prototype.getTranslate=function(a,b){var c=this.layout.options;return a=c.isOriginLeft?a:-a,b=c.isOriginTop?b:-b,n?"translate3d("+a+"px, "+b+"px, 0)":"translate("+a+"px, "+b+"px)"},g.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},g.prototype.moveTo=m?g.prototype._transitionTo:g.prototype.goTo,g.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},g.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},g.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var r="opacity,"+h(q.transform||"transform");g.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:r,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(o,this,!1))},g.prototype.transition=g.prototype[k?"_transition":"_nonTransition"],g.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},g.prototype.onotransitionend=function(a){this.ontransitionend(a)};var s={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};g.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,c=s[a.propertyName]||a.propertyName;if(delete b.ingProperties[c],f(b.ingProperties)&&this.disableTransition(),c in b.clean&&(this.element.style[a.propertyName]="",delete b.clean[c]),c in b.onEnd){var d=b.onEnd[c];d.call(this),delete b.onEnd[c]}this.emitEvent("transitionEnd",[this])}},g.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(o,this,!1),this.isTransitioning=!1},g.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]="";this.css(b)};var t={transitionProperty:"",transitionDuration:""};return g.prototype.removeTransitionStyles=function(){this.css(t)},g.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},g.prototype.remove=function(){if(!k||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.once("transitionEnd",function(){a.removeElem()}),this.hide()},g.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("visibleStyle");b[c]=this.onRevealTransitionEnd,this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},g.prototype.getHideRevealTransitionEndProperty=function(a){var b=this.layout.options[a];if(b.opacity)return"opacity";for(var c in b)return c},g.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("hiddenStyle");b[c]=this.onHideTransitionEnd,this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},g.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},g}),function(a,b){"function"==typeof define&&define.amd?define("outlayer/outlayer",["eventie/eventie","eventEmitter/EventEmitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(c,d,e,f,g){return b(a,c,d,e,f,g)}):"object"==typeof exports?module.exports=b(a,require("eventie"),require("wolfy87-eventemitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):a.Outlayer=b(a,a.eventie,a.EventEmitter,a.getSize,a.fizzyUIUtils,a.Outlayer.Item)}(window,function(a,b,c,d,e,f){function g(a,b){var c=e.getQueryElement(a);if(!c)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(c||a)));this.element=c,i&&(this.$element=i(this.element)),this.options=e.extend({},this.constructor.defaults),this.option(b);var d=++k;this.element.outlayerGUID=d,l[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var h=a.console,i=a.jQuery,j=function(){},k=0,l={};return g.namespace="outlayer",g.Item=f,g.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},e.extend(g.prototype,c.prototype),g.prototype.option=function(a){e.extend(this.options,a)},g.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),e.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},g.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},g.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},g.prototype._filterFindItemElements=function(a){return e.filterFindElements(a,this.options.itemSelector)},g.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},g.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},g.prototype._init=g.prototype.layout,g.prototype._resetLayout=function(){this.getSize()},g.prototype.getSize=function(){this.size=d(this.element)},g.prototype._getMeasurement=function(a,b){var c,f=this.options[a];f?("string"==typeof f?c=this.element.querySelector(f):e.isElement(f)&&(c=f),this[a]=c?d(c)[b]:f):this[a]=0},g.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},g.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},g.prototype._layoutItems=function(a,b){if(this._emitCompleteOnItems("layout",a),a&&a.length){for(var c=[],d=0,e=a.length;e>d;d++){var f=a[d],g=this._getItemLayoutPosition(f);g.item=f,g.isInstant=b||f.isLayoutInstant,c.push(g)}this._processLayoutQueue(c)}},g.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},g.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},g.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},g.prototype._postLayout=function(){this.resizeContainer()},g.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},g.prototype._getContainerSize=j,g.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?"width":"height"]=a+"px"}},g.prototype._emitCompleteOnItems=function(a,b){function c(){e.dispatchEvent(a+"Complete",null,[b])}function d(){g++,g===f&&c()}var e=this,f=b.length;if(!b||!f)return void c();for(var g=0,h=0,i=b.length;i>h;h++){var j=b[h];j.once(a,d)}},g.prototype.dispatchEvent=function(a,b,c){var d=b?[b].concat(c):c;if(this.emitEvent(a,d),i)if(this.$element=this.$element||i(this.element),b){var e=i.Event(b);e.type=a,this.$element.trigger(e,c)}else this.$element.trigger(a,c)},g.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},g.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},g.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},g.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e.removeFrom(this.stamps,d),this.unignore(d)}},g.prototype._find=function(a){return a?("string"==typeof a&&(a=this.element.querySelectorAll(a)),a=e.makeArray(a)):void 0},g.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},g.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},g.prototype._manageStamp=j,g.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,e=d(a),f={left:b.left-c.left-e.marginLeft,top:b.top-c.top-e.marginTop,right:c.right-b.right-e.marginRight,bottom:c.bottom-b.bottom-e.marginBottom};return f},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.bindResize=function(){this.isResizeBound||(b.bind(a,"resize",this),this.isResizeBound=!0)},g.prototype.unbindResize=function(){this.isResizeBound&&b.unbind(a,"resize",this),this.isResizeBound=!1},g.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},g.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},g.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},g.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},g.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},g.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},g.prototype.reveal=function(a){this._emitCompleteOnItems("reveal",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.reveal()}},g.prototype.hide=function(a){this._emitCompleteOnItems("hide",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.hide()}},g.prototype.revealItemElements=function(a){var b=this.getItems(a);this.reveal(b)},g.prototype.hideItemElements=function(a){var b=this.getItems(a);this.hide(b)},g.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},g.prototype.getItems=function(a){a=e.makeArray(a);for(var b=[],c=0,d=a.length;d>c;c++){var f=a[c],g=this.getItem(f);g&&b.push(g)}return b},g.prototype.remove=function(a){var b=this.getItems(a);if(this._emitCompleteOnItems("remove",b),b&&b.length)for(var c=0,d=b.length;d>c;c++){var f=b[c];f.remove(),e.removeFrom(this.items,f)}},g.prototype.destroy=function(){var a=this.element.style;a.height="",a.position="",a.width="";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize();var e=this.element.outlayerGUID;delete l[e],delete this.element.outlayerGUID,i&&i.removeData(this.element,this.constructor.namespace)},g.data=function(a){a=e.getQueryElement(a);var b=a&&a.outlayerGUID;return b&&l[b]},g.create=function(a,b){function c(){g.apply(this,arguments)}return Object.create?c.prototype=Object.create(g.prototype):e.extend(c.prototype,g.prototype),c.prototype.constructor=c,c.defaults=e.extend({},g.defaults),e.extend(c.defaults,b),c.prototype.settings={},c.namespace=a,c.data=g.data,c.Item=function(){f.apply(this,arguments)},c.Item.prototype=new f,e.htmlInit(c,a),i&&i.bridget&&i.bridget(a,c),c},g.Item=f,g}),function(a,b){"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size","fizzy-ui-utils/utils"],b):"object"==typeof exports?module.exports=b(require("outlayer"),require("get-size"),require("fizzy-ui-utils")):a.Masonry=b(a.Outlayer,a.getSize,a.fizzyUIUtils)}(window,function(a,b,c){var d=a.create("masonry");return d.prototype._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns();var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0);this.maxY=0},d.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var a=this.items[0],c=a&&a.element;this.columnWidth=c&&b(c).outerWidth||this.containerWidth}var d=this.columnWidth+=this.gutter,e=this.containerWidth+this.gutter,f=e/d,g=d-e%d,h=g&&1>g?"round":"floor";f=Math[h](f),this.cols=Math.max(f,1)},d.prototype.getContainerWidth=function(){var a=this.options.isFitWidth?this.element.parentNode:this.element,c=b(a);this.containerWidth=c&&c.innerWidth},d.prototype._getItemLayoutPosition=function(a){a.getSize();var b=a.size.outerWidth%this.columnWidth,d=b&&1>b?"round":"ceil",e=Math[d](a.size.outerWidth/this.columnWidth);e=Math.min(e,this.cols);for(var f=this._getColGroup(e),g=Math.min.apply(Math,f),h=c.indexOf(f,g),i={x:this.columnWidth*h,y:g},j=g+a.size.outerHeight,k=this.cols+1-f.length,l=0;k>l;l++)this.colYs[h+l]=j;return i},d.prototype._getColGroup=function(a){if(2>a)return this.colYs;for(var b=[],c=this.cols+1-a,d=0;c>d;d++){var e=this.colYs.slice(d,d+a);b[d]=Math.max.apply(Math,e)}return b},d.prototype._manageStamp=function(a){var c=b(a),d=this._getElementOffset(a),e=this.options.isOriginLeft?d.left:d.right,f=e+c.outerWidth,g=Math.floor(e/this.columnWidth);g=Math.max(0,g);var h=Math.floor(f/this.columnWidth);h-=f%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var i=(this.options.isOriginTop?d.top:d.bottom)+c.outerHeight,j=g;h>=j;j++)this.colYs[j]=Math.max(i,this.colYs[j])},d.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var a={height:this.maxY};return this.options.isFitWidth&&(a.width=this._getContainerFitWidth()),a},d.prototype._getContainerFitWidth=function(){for(var a=0,b=this.cols;--b&&0===this.colYs[b];)a++;return(this.cols-a)*this.columnWidth-this.gutter},d.prototype.needsResizeLayout=function(){var a=this.containerWidth;return this.getContainerWidth(),a!==this.containerWidth},d});
  4613. </script>
  4614. <style>
  4615. .hidden {
  4616.     display: none !important;
  4617. }
  4618. </style>
  4619. <script type="text/javascript">
  4620. (function(course_data){
  4621. "use strict";
  4622. function GetLearningData(){
  4623.     preloaderOn();
  4624.     $.ajax({
  4625.         type: "POST",
  4626.         url: "/pp/Ext/extjs_json_collection_data.html",
  4627.         dataType: "json",
  4628.         data: {
  4629.             collection_code: "beluga_course_data_rc",
  4630.             parameters: "learning_id="+course_data.learningID
  4631.         },
  4632.         success: function (data, textStatus, jqXHR) {
  4633.             preloaderOff();
  4634.             RenderLearningData(data.results[0]);
  4635.         }
  4636.     });
  4637. };
  4638. function RenderLearningData(data){
  4639.     $("#start_learning").off();
  4640.     $("#finish_learning").off();
  4641.     $("#learning_title").text(data.name);
  4642.     data.categories.forEach(function(el){
  4643.         $("#categories").after(
  4644.             '<li class="b-test__breadcrumbs-item"><a href="javascript:void(0);" class="b-test__breadcrumbs-link">'+el+'</a></li>'              
  4645.         );
  4646.     });
  4647.     $("#categories").remove();
  4648.     if (data.course_resource != undefined && data.course_resource != ""){
  4649.        $("#course_image").css("background", "url('download_file.html?file_id="+data.course_resource+"') no-repeat center center");
  4650.     } else {
  4651.         $("#course_image").remove();
  4652.     }
  4653.     switch (data.status) {
  4654.         case 0:
  4655.             $("#course_status").text("Назначен");
  4656.             $("#finish_learning").addClass("hidden");
  4657.             $("#start_learning").text("Начать");
  4658.             break;
  4659.         case 1:
  4660.             $("#course_status").text("В процессе");
  4661.             $("#start_learning").text("Продолжить");
  4662.             if(!data.has_unfinished_required_parts || data.finish_without_mastery_score){
  4663.                 $("#finish_learning").removeClass("hidden");
  4664.             } else {
  4665.                 $("#finish_learning").addClass("hidden");
  4666.             }
  4667.             if(!data.has_unfinished_parts){
  4668.                 $("#start_learning").addClass("hidden");
  4669.             } else {
  4670.                 $("#start_learning").removeClass("hidden");
  4671.             }
  4672.             break;
  4673.         case 2:
  4674.             $("#course_status").text("Завершен");
  4675.             $("#finish_learning").removeClass("hidden");
  4676.             if(data.is_self_enrolled){
  4677.                 $("#start_learning").text("Начать заново");
  4678.             } else {
  4679.                 $("#start_learning").addClass("hidden");
  4680.             }
  4681.             if (data.feedback_type_id != null) {
  4682.                 $("#feedback").attr("href", "view_doc.html?mode=response&doc_id=&response_object_id="+data.course_id+"&response_type_id="+data.feedback_type_id);
  4683.                 $("#feedback").show();
  4684.             }
  4685.             break;
  4686.         case 3:
  4687.             $("#course_status").text("Не пройден");
  4688.             $("#finish_learning").removeClass("hidden");
  4689.             if(data.is_self_enrolled){
  4690.                 $("#start_learning").text("Начать заново");
  4691.             } else {
  4692.                 $("#start_learning").addClass("hidden");
  4693.             }
  4694.             if (data.feedback_type_id != null) {
  4695.                 $("#feedback").attr("href", "view_doc.html?mode=response&doc_id=&response_object_id="+data.course_id+"&response_type_id="+data.feedback_type_id);
  4696.                 $("#feedback").show();
  4697.             }
  4698.             break;
  4699.         case 4:
  4700.             $("#course_status").text("Пройден");
  4701.             $("#finish_learning").removeClass("hidden");
  4702.             if(data.is_self_enrolled){
  4703.                 $("#start_learning").text("Начать заново");
  4704.             } else {
  4705.                 $("#start_learning").addClass("hidden");
  4706.             }
  4707.             if (data.feedback_type_id != null) {
  4708.                 $("#feedback").attr("href", "view_doc.html?mode=response&doc_id=&response_object_id="+data.course_id+"&response_type_id="+data.feedback_type_id);
  4709.                 $("#feedback").show();
  4710.             }
  4711.             break;
  4712.         case 5:
  4713.             $("#course_status").text("Просмотрен");
  4714.             $("#finish_learning").removeClass("hidden");
  4715.             if(data.is_self_enrolled){
  4716.                 $("#start_learning").text("Начать заново");
  4717.             } else {
  4718.                 $("#start_learning").addClass("hidden");
  4719.             }
  4720.             if (data.feedback_type_id != null) {
  4721.                 $("#feedback").attr("href", "view_doc.html?mode=response&doc_id=&response_object_id="+data.course_id+"&response_type_id="+data.feedback_type_id);
  4722.                 $("#feedback").show();
  4723.             }
  4724.             break;
  4725.         case 10:
  4726.             if(data.is_self_enrolled){
  4727.                 $("#course_status").text("Не назначен");
  4728.                 $("#start_learning").text("Начать");
  4729.             } else {
  4730.                 $("#course_status").text("Не доступен");    
  4731.                 $("#start_learning").off();
  4732.                 $("#start_learning").addClass("hidden");
  4733.             }
  4734.             $("#finish_learning").addClass("hidden");
  4735.             break;
  4736.         case 11:
  4737.             $("#course_status").text("Не доступен");    
  4738.             $("#start_learning").addClass("hidden");
  4739.             $("#finish_learning").addClass("hidden");
  4740.             $("#start_learning").off();
  4741.             $("#finish_learning").off();
  4742.             break;
  4743.         default:
  4744.             break;
  4745.     }
  4746.     if(data.a_l_id == ""){
  4747.         $("#finish_learning").addClass("hidden");          
  4748.     }
  4749.     if(data.status != 11){
  4750.         $("#course_score").text(data.course_score);
  4751.         $("#date_start").text(data.date_start != '' ? data.date_start : '-');
  4752.         $("#date_l_start").text(data.date_l_start != '' ? data.date_l_start : '-');
  4753.         $("#date_finish").text(data.date_finish != '' ? data.date_finish : '-');
  4754.         if(data.description != ""){
  4755.             $("#course_desc").html(data.description);
  4756.         } else {
  4757.             $("#course_desc").remove();
  4758.         }
  4759.        
  4760.         $("#course_materials").empty();
  4761.         $("#course_map").empty();
  4762.         if(data.course_map.length > 0){
  4763.             data.course_map.forEach(function(el){
  4764.                 switch (el.type) {
  4765.                     case 'Курс':
  4766.                         var btn = (function(){
  4767.                             if(data.status == 10){
  4768.                                 return ''
  4769.                             } else if (el.state_id <= 1 && data.status <= 2) {
  4770.                                return $('<div>')
  4771.                                 .addClass("b-test__table-cell b-course__table-cell b-course__table-but")
  4772.                                 .append(
  4773.                                     $("<div>").addClass("b-course__table-cell-wrap").append(
  4774.                                         $('<a>')
  4775.                                         .attr('href', 'javascript:void(0);')
  4776.                                         .addClass("b-course__button-empty b-course__table-button")
  4777.                                         .text(el.state_id == 0 ? "Начать":"Продолжить")
  4778.                                         .on('click', function(){
  4779.                                             var _form = new FormData;
  4780.                                             _form.append("course_id", data.course_id);
  4781.                                             $.ajax({
  4782.                                                 url: "/custom_web_template.html?object_code=beluga_get_session_id_sum",
  4783.                                                 type: "POST",
  4784.                                                 data: _form,
  4785.                                                 dataType: "json",
  4786.                                                 processData: false,
  4787.                                                 contentType: false,
  4788.                                                 success: function(res) {
  4789.                                                     var courseWindow = window.open( 'course_launch.html?course_id='+data.course_id+'&object_id='+data.a_l_id+'&sid='+res.responseText+ "&part_code="+ el.parts);
  4790.                                                     var _intrval_mod = setInterval(function(){
  4791.                                                         if (courseWindow.closed) {
  4792.                                                             clearInterval(_intrval_mod);
  4793.                                                             location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  4794.                                                         }
  4795.                                                     }, 500);
  4796.                                                 }
  4797.                                             });
  4798.                                         }),
  4799.                                         (function(){
  4800.                                             if(el.cur_attempt < el.attempts){
  4801.                                                return $('<a>')
  4802.                                                 .attr('href', 'javascript:void(0);')
  4803.                                                 .addClass("b-course__complete-attempt-link")
  4804.                                                 .text("Завершить попытку")
  4805.                                                 .on('click', function(){
  4806.                                                     var _form = new FormData;
  4807.                                                     _form.append("course_id", data.course_id);
  4808.                                                     _form.append("learning_id", data.a_l_id);
  4809.                                                     _form.append("part_code", el.parts);
  4810.                                                     $.ajax({
  4811.                                                         url: "/custom_web_template.html?object_code=beluga_course_finish_attempt",
  4812.                                                         type: "POST",
  4813.                                                         data: _form,
  4814.                                                         dataType: "json",
  4815.                                                         processData: false,
  4816.                                                         contentType: false,
  4817.                                                         success: function(res) {
  4818.                                                             GetLearningData();
  4819.                                                         }
  4820.                                                     });
  4821.                                                 })
  4822.                                             }
  4823.                                         })()
  4824.                                     )
  4825.                                 )
  4826.                             } else {
  4827.                                 var score = 0;
  4828.                                 if(el.max_score != 0){
  4829.                                     score = el.score/el.max_score;
  4830.                                 } else {
  4831.                                     score = 1;
  4832.                                 }
  4833.                                 return  $("<div>")
  4834.                                 .addClass("b-test__table-cell b-course__table-cell b-course__table-no-but")
  4835.                                 .append(
  4836.                                     $("<div>").addClass("b-course__table-cell-wrap").append(
  4837.                                         $("<div>").addClass("b-course__type-wrap").append(
  4838.                                             $("<div>")
  4839.                                             .addClass('goal-map__type '+(el.state_id != 3 ? "ready":"not-ready")+' b-course__type')
  4840.                                             .append(
  4841.                                                 $('<span>')
  4842.                                                 .text(el.state_name)
  4843.                                                 .on('click', function(){
  4844.                                                     var _form = new FormData;
  4845.                                                     _form.append("course_id", data.course_id);
  4846.                                                     $.ajax({
  4847.                                                         url: "/custom_web_template.html?object_code=beluga_get_session_id_sum",
  4848.                                                         type: "POST",
  4849.                                                         data: _form,
  4850.                                                         dataType: "json",
  4851.                                                         processData: false,
  4852.                                                         contentType: false,
  4853.                                                         success: function(res) {
  4854.                                                             var courseWindow = window.open( 'course_launch.html?course_id='+data.course_id+'&object_id='+data.a_l_id+'&sid='+res.responseText+ "&part_code="+ el.parts);
  4855.                                                             var _intrval_mod = setInterval(function(){
  4856.                                                                 if (courseWindow.closed) {
  4857.                                                                     clearInterval(_intrval_mod);
  4858.                                                                     location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  4859.                                                                 }
  4860.                                                             }, 500);
  4861.                                                         }
  4862.                                                     });
  4863.                                                 }),
  4864.                                                 $('<span>')
  4865.                                                 .addClass("b-course__text-last")
  4866.                                                 .text(Math.round(score*100)+"%")
  4867.                                             )
  4868.                                         ),
  4869.                                         (function(){
  4870.                                             if(el.cur_attempt < el.attempts){
  4871.                                                return $('<a>')
  4872.                                                 .attr('href', 'javascript:void(0);')
  4873.                                                 .addClass("b-course__complete-attempt-link new")
  4874.                                                 .text("Пройти заново")
  4875.                                                 .on('click', function(){
  4876.                                                     var _form = new FormData;
  4877.                                                     _form.append("course_id", data.course_id);
  4878.                                                     _form.append("learning_id", data.a_l_id);
  4879.                                                     _form.append("part_code", el.parts);
  4880.                                                     $.ajax({
  4881.                                                         url: "/custom_web_template.html?object_code=beluga_course_finish_attempt",
  4882.                                                         type: "POST",
  4883.                                                         data: _form,
  4884.                                                         dataType: "json",
  4885.                                                         processData: false,
  4886.                                                         contentType: false,
  4887.                                                         success: function(res) {
  4888.                                                             GetLearningData();
  4889.                                                         }
  4890.                                                     });
  4891.                                                 })
  4892.                                             }
  4893.                                         })()
  4894.                                     )
  4895.                                 )
  4896.                             }
  4897.                         })();
  4898.                         break;
  4899.                     case 'Тест':
  4900.                         var btn = (function(){
  4901.                             if(data.status == 10 || data.status == 11){
  4902.                                 return;
  4903.                             } else if (el.state_id <= 1  && data.status <= 2) {
  4904.                                return $('<div>')
  4905.                                 .addClass("b-test__table-cell b-course__table-cell b-course__table-but")
  4906.                                 .append(
  4907.                                     $("<div>").addClass("b-course__table-cell-wrap").append(
  4908.                                         '<a href="javascript:void(0);" class="b-course__button-empty b-course__table-button">'+(el.state_id == 0 ? "Начать":"Продолжить")+'</a>'
  4909.                                     )
  4910.                                 )
  4911.                                 .on('click', function(){
  4912.                                     location.href = "view_doc.html?mode=test_page&object_id="+el.test_id+"&course_id="+data.course_id+"&part_code="+el.parts+(data.a_l_id != "" ? "&learning_id="+data.a_l_id : "");
  4913.                                 });
  4914.                             } else {
  4915.                                 if(!el.is_locked){
  4916.                                     var score = 0;
  4917.                                     if(el.max_score != 0){
  4918.                                         score = el.score/el.max_score;
  4919.                                     } else {
  4920.                                         score = 1;
  4921.                                     }
  4922.                                     return $("<div>")
  4923.                                     .addClass("b-test__table-cell b-course__table-cell b-course__table-no-but")
  4924.                                     .append(
  4925.                                         $("<div>").addClass("b-course__table-cell-wrap").append(
  4926.                                             $("<div>").addClass("b-course__type-wrap").append(
  4927.                                                 $("<div>")
  4928.                                                 .addClass("goal-map__type "+(el.state_id != 3 ? "ready":"not-ready")+" b-course__type")
  4929.                                                 .append(
  4930.                                                     $("<span>").text(el.state_name),
  4931.                                                     $("<span>").addClass("b-course__text-last").text(Math.round((score)*100)+"%")
  4932.                                                 )                                                        
  4933.                                             ).on('click', function(){
  4934.                                                 location.href = "view_doc.html?mode=test_page&object_id="+el.test_id+"&course_id="+data.course_id+"&part_code="+el.parts+(data.a_l_id != "" ? "&learning_id="+data.a_l_id : "");
  4935.                                             })
  4936.                                         )
  4937.                                     );
  4938.                                 }                                
  4939.                             }
  4940.                         })();
  4941.                         break;
  4942.                     default:
  4943.                         var btn = (function(){
  4944.                             if(data.status == 10 || data.status == 11){
  4945.                                     return;
  4946.                             } else {
  4947.                                 return $('<div>')
  4948.                                 .addClass("b-test__table-cell b-course__table-cell b-course__table-but")
  4949.                                 .append(
  4950.                                     $("<div>").addClass("b-course__table-cell-wrap").append(
  4951.                                         '<a href="javascript:void(0);" class="b-course__button-empty b-course__table-button">Открыть</a>'
  4952.                                     )
  4953.                                 )
  4954.                                 .on('click', function(){
  4955.                                     var _form = new FormData;
  4956.                                     _form.append("course_id", data.course_id);
  4957.                                     $.ajax({
  4958.                                         url: "/custom_web_template.html?object_code=beluga_get_session_id_sum",
  4959.                                         type: "POST",
  4960.                                         data: _form,
  4961.                                         dataType: "json",
  4962.                                         processData: false,
  4963.                                         contentType: false,
  4964.                                         success: function(res) {
  4965.                                             var url = 'course_launch.html?course_id='+data.course_id+'&object_id='+data.a_l_id+'&sid='+res.responseText+ "&part_code="+ el.parts;
  4966.                                             if(data.a_l_id == "" && el.type == 'Файл'){
  4967.                                                url = el.url;
  4968.                                             }
  4969.                                             var courseWindow = window.open(url);
  4970.                                             var _intrval_mod = setInterval(function(){
  4971.                                                 if (courseWindow.closed) {
  4972.                                                     clearInterval(_intrval_mod);
  4973.                                                     location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  4974.                                                 }
  4975.                                             }, 500);
  4976.                                         }
  4977.                                     });
  4978.                                 });
  4979.                             }
  4980.                         })();
  4981.                         break;
  4982.                 }
  4983.                 $("#course_map").append(
  4984.                     $("<div>")
  4985.                     .addClass("b-test__table-row b-course__table-row")
  4986.                     .append(
  4987.                         $("<div>")
  4988.                         .addClass("b-test__table-cell b-course__table-cell")
  4989.                         .append(
  4990.                             '<a href="javascript:void(0);" class="b-course__title-link">'+el.name+'</a>'
  4991.                         ),
  4992.                         $("<div>")
  4993.                         .addClass("b-test__table-cell b-text__grey b-course__table-cell clearfix")
  4994.                         .append(
  4995.                             '<span class="b-course__table-text">'+el.type+'</span><span class="b-course__table-num">'+el.score+(el.max_score != 0 && el.max_score != '-' ? '/'+el.max_score : '')+'</span>'
  4996.                        ),
  4997.                        btn
  4998.                    )
  4999.                );
  5000.             });
  5001.         } else {
  5002.             $("#map_block").remove();
  5003.         }
  5004.         if(data.docs.length != 0){
  5005.             data.docs.forEach(function(el){
  5006.             $("#course_materials").append(
  5007.                 $("<div>")
  5008.                 .addClass("b-test__table-row b-course__table-row" + (el.type == 'video' ? " b-course__table-row-video": ""))
  5009.                 .append(
  5010.                     $("<div>")
  5011.                     .addClass("b-test__table-cell b-course__table-cell b-course__material-cell")
  5012.                     .append(
  5013.                         (function(){
  5014.                             if(el.type == 'video'){
  5015.                                 return '<div class="b-course__material-icon-video"><i class="b-icon__play b-course__material-icon"></i></div>';
  5016.                             } else {
  5017.                                 return '';
  5018.                             }
  5019.                         }),
  5020.                         ' <a href="javascript:void(0);" class="b-course__title-link">'+el.name+'</a>'
  5021.                     ),
  5022.                     '<div class="b-test__table-cell b-text__grey clearfix b-course__material-cell">'+
  5023.                     '    <span class="b-course__table-text b-course__big-text">'+el.type+'</span>'+
  5024.                     '    <span class="b-course__table-num b-course__material-text">'+el.size+'</span></div>'+
  5025.                     '</div>',
  5026.                     $('<div>')
  5027.                     .addClass("b-test__table-cell b-course__table-cell b-course__table-but b-course__material-cell")
  5028.                     .append('<a href="javascript:void(0);" class="b-course__button-empty b-course__table-button b-course__material-button float-right b-course__material-button-download">Скачать</a>')
  5029.                     .on("click", function(){                                
  5030.                         window.open(el.url );
  5031.                     })
  5032.                     )
  5033.                 );
  5034.             });      
  5035.         } else {
  5036.             $("#materials_block").remove();
  5037.         }
  5038.     } else {
  5039.         $("#course_block").empty().append(
  5040.             '<h2 class="b-title__h2 b-course__h2">Курс находится в разработке.</h2>'
  5041.         )
  5042.     }
  5043.     if($("#start_learning").hasClass("hidden") && $("#finish_learning").hasClass("hidden")){
  5044.        $(".b-fixpanel").hide();
  5045.     }
  5046.  
  5047.     $("#start_learning").on("click", function(){
  5048.         if(data.status == 0 || data.status == 1){
  5049.             var _form = new FormData;
  5050.             _form.append("course_id", data.course_id);
  5051.             $.ajax({
  5052.                 url: "/custom_web_template.html?object_code=beluga_get_session_id_sum",
  5053.                 type: "POST",
  5054.                 data: _form,
  5055.                 dataType: "json",
  5056.                 processData: false,
  5057.                 contentType: false,
  5058.                 success: function(res) {
  5059.                     var courseWindow = window.open( 'course_launch.html?course_id='+data.course_id+'&object_id='+data.a_l_id+'&sid='+res.responseText+ "&part_code="+ data.c_part);
  5060.                     var _intrval_mod = setInterval(function(){
  5061.                         if (courseWindow.closed) {
  5062.                             clearInterval(_intrval_mod);
  5063.                             location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  5064.                         }
  5065.                     }, 500);
  5066.                 }
  5067.             });
  5068.         } else {
  5069.             var form_data = new FormData();
  5070.             form_data.append("course_id", data.course_id)
  5071.             form_data.append("course_part", data.c_part)
  5072.             $.ajax({
  5073.                 url: "/custom_web_template.html?object_code=beluga_activate_course",
  5074.                 type: "POST",
  5075.                 data: form_data,
  5076.                 dataType: "json",
  5077.                 processData: false,
  5078.                 contentType: false,
  5079.                 success: function(res) {
  5080.                     if(!res.error){
  5081.                         var courseWindow = window.open(res.url);
  5082.                         var _intrval_mod = setInterval(function(){
  5083.                             if (courseWindow.closed) {
  5084.                                 clearInterval(_intrval_mod);
  5085.                                 location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  5086.                             }
  5087.                         }, 500);
  5088.                     } else {
  5089.                         alert(data.message);
  5090.                     }                            
  5091.                 }
  5092.             });
  5093.         }                
  5094.     });
  5095.     $("#finish_learning").click(function(){
  5096.         var form_data = new FormData();
  5097.         form_data.append("course_id", data.course_id);                        
  5098.         $.ajax({
  5099.             url: "/custom_web_template.html?object_code=beluga_finish_course",
  5100.             type: "POST",
  5101.             data: form_data,
  5102.             dataType: "json",
  5103.             processData: false,
  5104.             contentType: false,
  5105.             success: function(data) {
  5106.                 location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  5107.             },
  5108.             error: function(){
  5109.                 location.href = 'view_doc.html?mode=course_page&object_id='+course_data.learningID;
  5110.             }
  5111.         });
  5112.     });
  5113.     var h = $(".b-fixpanel").outerHeight();
  5114.     $("#panel_fix_height").css("height", h+"px");
  5115.     $(".b-course__title-link").on("click", function(){
  5116.         $(this).parent().next().next().click();
  5117.     });
  5118. }
  5119. function init(){
  5120.     GetLearningData();
  5121. }
  5122. init();
  5123. $(window).on('load, resize, scroll', function(){
  5124.     var h = $(".b-footer").outerHeight();
  5125.     if  (Math.round($(window).scrollTop()) == $(document).outerHeight() - $(window).outerHeight())
  5126.     {
  5127.         //Пользователь долистал до низа страницы
  5128.         $(".b-fixpanel").css("bottom", h+"px");
  5129.     }
  5130.     else {
  5131.         $(".b-fixpanel").css("bottom", "");
  5132.     }
  5133. });
  5134. })({"learningID":"6541234634070967339"});
  5135. </script>
  5136.  <div class="b-page__title">
  5137.     <div class="b-container">
  5138.       <h1 class="b-title__h1 b-course__h1" id="learning_title"></h1>
  5139.     </div>
  5140.     </div>
  5141.     <div class="b-test__breadcrumbs">
  5142.     <div class="b-container">
  5143.       <div class="b-test__breadcrumbs-wrap b-course__breadcrumbs-wrap">
  5144.         <ul class="b-test__breadcrumbs-ul">
  5145.           <li class="b-test__breadcrumbs-item"><a href="javascript:void(0);"><div class="b-icon-course b-test__icon-course b-test__icon-test float-left"></div>Курс</a></li>
  5146.           <li class="b-test__breadcrumbs-item" id="categories"><a href="javascript:void(0);" class="b-test__breadcrumbs-link" >Вводные тесты</a></li>
  5147.           <li class="b-test__breadcrumbs-item active"><a href="javascript:void(0);" class="b-test__breadcrumbs-link b-test__breadcrumbs-link-last"><div class="icon-play b-test__icon-play float-left"></div> <span id="course_status">В процессе</span></a></li>
  5148.         </ul>
  5149.       </div>
  5150.     </div>
  5151.   </div>
  5152.   <div class="b-container" id="course_block">
  5153.     <div class="b-course__image" id="course_image"></div>
  5154.     <div class="b-test__table b-course__table">
  5155.       <div class="b-test__table-row">
  5156.         <div class="b-test__table-cell b-text__grey b-course__text-little">Баллы</div>
  5157.         <div class="b-test__table-cell"><span class="wl-text__orange" id="course_score"></span></div>
  5158.       </div>
  5159.       <div class="b-test__table-row">
  5160.         <div class="b-test__table-cell b-text__grey b-course__text-little">Дата активации</div>
  5161.         <div class="b-test__table-cell" id="date_start"></div>
  5162.       </div>
  5163.       <div class="b-test__table-row">
  5164.         <div class="b-test__table-cell b-text__grey b-course__text-little">Дата последнего посещения</div>
  5165.         <div class="b-test__table-cell" id="date_l_start"></div>
  5166.       </div>
  5167.       <div class="b-test__table-row">
  5168.         <div class="b-test__table-cell b-text__grey b-course__text-little">Дата планируемого завершения</div>
  5169.         <div class="b-test__table-cell" id="date_finish"></div>
  5170.       </div>
  5171.     </div>
  5172.     <div class="b-test__description" id="course_desc">
  5173.  
  5174.     </div>
  5175.     <div id="map_block">
  5176.       <h3 class="b-test__h3">Карта курса</h3>
  5177.       <div class="b-course__table-wrap" >
  5178.         <div class="b-test__table b-course__table" id="course_map">
  5179.         </div>
  5180.       </div>
  5181.     </div>
  5182.      <div id="materials_block">
  5183.       <h3 class="b-test__h3">Материалы курса</h3>
  5184.       <div class="b-course__table-wrap">
  5185.         <div class="b-test__table b-course__table b-course__table-material" id="course_materials">
  5186.          
  5187.         </div>
  5188.       </div>
  5189.      </div>
  5190.   </div>
  5191.   <div id="panel_fix_height"></div>
  5192.   <div class="b-fixpanel">
  5193.     <div class="b-container">
  5194.       <a href="javascript:void(0);" class="b-fixpanel__save" style="margin-right: 10px;" id="start_learning">Продолжить</a>
  5195.       <a href="javascript:void(0);" class="b-fixpanel__complete" id="finish_learning">Завершить</a>
  5196.       <a href="javascript:void(0);" class="b-fixpanel__complete" style="margin-right: 10px; display: none;" id="feedback">Оставить отзыв</a>
  5197.     </div>
  5198.     </div>
  5199.   <!--footer end -->
  5200.   <script type="text/javascript" src="scorm_api.js" language="javascript"></script>
  5201.  
  5202.  
  5203.   <script type="text/javascript">
  5204.         /*jQuery(function(){
  5205.       jQuery('textarea').autoResize();
  5206.     });*/
  5207.         $('select').selectric({
  5208.             maxHeight: 200
  5209.         });
  5210.   </script>
  5211.   <script type="text/javascript">
  5212.         $(".b-library__container").masonry({
  5213.             itemSelector: '.item',
  5214.             columnWidth: ".item",
  5215.             gutter: 10,
  5216.             isInitLayout: true,
  5217.             //isFitWidth: true,
  5218.             isResizeBound: true,
  5219.         });
  5220.   </script>
  5221.     <div class="b-container">
  5222.         </div><div class="b-container"><a style="margin-bottom: 100px; " class="b-button__blue full" href='view_print_form.html?print_form_id=6473426798783395895&object_id=6716797818596368129&sid=6473426798783395895'><h2>РАСПЕЧАТАТЬ СЕРТИФИКАТ</h2></a>
  5223. </div><!-- старт сокрытие рамки новостей-->
  5224.  
  5225. <!-- конец сокрытие рамки новостей--><!-- старт Ссылка на страницу новости со страницу одной новости-->
  5226.  
  5227. <!-- конец Ссылка на страницу новости со страницу одной новости--><script>
  5228. $(document).ready(function(){
  5229.    
  5230.     $(".portalhelp").click(function(){
  5231.         if(!$(".introjs-overlay").length>0)
  5232. {
  5233.         introJs().start();
  5234. }
  5235.     })
  5236. })
  5237. </script>
  5238.         </div>
  5239.     </div>
  5240.        
  5241. <footer class="b-footer blue">
  5242.     <div class="b-container">
  5243.         <div class="b-footer__wrap">
  5244.             <div class="b-footer__header clearfix">
  5245.                 <div class="b-footer__nav float-left">
  5246.                     <nav id="footer_menu_main">
  5247.                     </nav>
  5248.                 </div>
  5249.                 <div class="b-footer__link">
  5250.                     <a id="footer_send_admin" href="javascript:void(0)">Написать администратору</a>
  5251.                 </div>
  5252.             </div>
  5253.             <div class="b-footer__footer clearfix">
  5254.                 <div class="b-footer__logo float-left">
  5255.                     <a href="javascript:void(0)"><img src="download_file.html?file_id=6621426380956391193" alt="logo"></a>
  5256.                 </div>
  5257.                 <div class="b-footer__group float-left">
  5258.                     <a id="footer_copy" href="javascript:void(0)"></a>
  5259.                 </div>
  5260.                 <div class="b-footer__logo-lab float-right">
  5261.                     <a href="https://labmedia.su/">
  5262.                         <img src="download_file.html?file_id=6621426457715887988" alt="logo">
  5263.                     </a>
  5264.                 </div>
  5265.             </div>
  5266.         </div>
  5267.     </div>
  5268.     <div id="footer_modal_admin"></div>
  5269. </footer>
  5270. <script>
  5271.     $(document).ready(function () {
  5272.         'use strict';
  5273.  
  5274.         //модальное окно
  5275.         var Modal = (function  () {
  5276.             var defaultText = 'Не более 5 МБ',
  5277.                 maxFileSize = 1024 * 1024 * 5; //5 МБ
  5278.             function Constructor (config) {
  5279.                 var self = this,
  5280.  
  5281.                 emailTextArea = config.curUserEmail != "" ? $() : $('<textarea/>')
  5282.                     .addClass("comment_input b-textarea comments")
  5283.                     .attr({
  5284.                         "id": "footer_send_from",
  5285.                         "rows": 1,
  5286.                         "placeholder": "Введите ваш адрес электронной почты",
  5287.                         "style": "margin-top: 0; margin-bottom: 23px;"
  5288.                     }),
  5289.                 textarea = $('<textarea/>')
  5290.                                 .attr('maxlength', '3000')
  5291.                                 .addClass("b-write-to-admin__textarea-item"),
  5292.                 label = $('<span/>')
  5293.                             .addClass('b-write-to-admin__desc')
  5294.                             .text(defaultText),
  5295.                 delFileBtn = $('<a/>')
  5296.                                 .addClass('delete_file_btn')
  5297.                                 .attr('href', 'javascript:void(0);')
  5298.                                 .append(
  5299.                                     $('<i/>')
  5300.                                         .addClass('b-icon__delete')
  5301.                                         .css({
  5302.                                             'position': 'absolute',
  5303.                                             'margin-top': '23px',
  5304.                                             'margin-left': '5px'
  5305.                                         })
  5306.                                 ),
  5307.                 sendBtn = $('<a/>')
  5308.                                 .attr('href', 'javascript:void(0);')
  5309.                                 .addClass('b-write-to-admin__blue')
  5310.                                 .text('Отправить'),
  5311.                 cancelBtn = $('<a/>')
  5312.                                 .attr('href', 'javascript:void(0);')
  5313.                                 .addClass('b-button__empty')
  5314.                                 .text('Отмена'),
  5315.                 loadFileBtn = $('<a/>')
  5316.                                 .addClass('b-write-to-admin__but')
  5317.                                 .attr('href', 'javascript:void(0);')
  5318.                                 .append(
  5319.                                     $("<span/>")
  5320.                                         .text('Загрузить файл')
  5321.                                 ),
  5322.                 fileInput = $('<input/>')
  5323.                                 .hide()
  5324.                                 .attr('accept', '.jpg, .jpeg, .png')
  5325.                                 .attr('type', 'file'),
  5326.                 fileBlock = $('<div/>')
  5327.                                 .addClass('b-write-to-admin__download')
  5328.                                 .append(
  5329.                                     loadFileBtn,
  5330.                                     fileInput,
  5331.                                     label,
  5332.                                     delFileBtn
  5333.                                 ),
  5334.                 domElement = $('<div/>')
  5335.                                 .addClass('b-shadow fade in')
  5336.                                 .hide()
  5337.                                 .append(
  5338.                                     $('<div/>')
  5339.                                         .addClass('b-modal b-report-selection b-write-to-admin')
  5340.                                         .hide()
  5341.                                         .append(
  5342.                                             $('<div/>')
  5343.                                                 .addClass('b-modal__wrapper')
  5344.                                                 .css('overflow', 'hidden')
  5345.                                                 .append(
  5346.                                                     $('<div/>')
  5347.                                                         .addClass('b-modal__header b-report-selection__header')
  5348.                                                         .append(
  5349.                                                             $('<h3/>')
  5350.                                                                 .addClass('b-modal__title b-report-selection__title')
  5351.                                                                 .text('Написать администратору')
  5352.                                                         ),
  5353.                                                     $('<div/>')
  5354.                                                         .addClass('b-modal__content')
  5355.                                                         .css({
  5356.                                                             'max-height': '247px;',
  5357.                                                             'overflow-y': 'auto;'
  5358.                                                         })
  5359.                                                         .append(
  5360.                                                             $('<div/>')
  5361.                                                                 .addClass('b-write-to-admin__textarea')
  5362.                                                                 .append(
  5363.                                                                     emailTextArea,
  5364.                                                                     textarea
  5365.                                                                 ),
  5366.                                                             fileBlock
  5367.                                                         ),
  5368.                                                     $('<div/>')
  5369.                                                         .addClass('b-report-selection__footer b-write-to-admin__footer')
  5370.                                                         .append(
  5371.                                                             sendBtn,
  5372.                                                             cancelBtn
  5373.                                                         )
  5374.                                                 )
  5375.                                         )
  5376.                                 );
  5377.  
  5378.                 //если в браузере нет FormData картинки не грузим
  5379.                 if (!('FileReader' in window)) {
  5380.                     fileBlock.hide();
  5381.                 }
  5382.  
  5383.                 //клик по кнопке Загрузить файл
  5384.                 loadFileBtn.on('click', function (event) {
  5385.                     fileInput.click();
  5386.                 });
  5387.                 //клик по кнопке Удалить файл
  5388.                 delFileBtn.on('click', function (event) {
  5389.                     fileInput.val('');
  5390.                     self.fileText(defaultText);
  5391.                     $(".delete_file_btn").hide();
  5392.                 })
  5393.                 //клик по кнопке Отправить
  5394.                 sendBtn.on('click', function (event) {
  5395.                     //клик обрабатывается если кнопка активна и передан колбэк и указана почта по требованию
  5396.                     if (sendBtn.hasClass('active')) {
  5397.                         var files = fileInput.prop("files"), form_data;
  5398.  
  5399.                         if (files.length > 0) {
  5400.  
  5401.                             var fr = new FileReader();
  5402.                             fr.onload = function (res) {
  5403.                                 self.sendAjax(self.textarea.val(), fr.result, files[0].name);
  5404.                             };
  5405.  
  5406.                             fr.readAsBinaryString(files[0]);
  5407.                         } else {
  5408.                             self.sendAjax(self.textarea.val(), '', '');
  5409.                         }
  5410.                         sendBtn.removeClass('active');
  5411.                     }
  5412.                 });
  5413.  
  5414.                 //добавление картинки
  5415.                 fileInput.on('change', function (event) {
  5416.                     var files = fileInput.prop("files"), form_data;
  5417.                    
  5418.                     if (files.length > 0) {
  5419.                         //проверяем размер файла
  5420.                         if (maxFileSize >= files[0].size) {
  5421.                             $(".delete_file_btn").show();
  5422.                             self.fileText(files[0].name);
  5423.                         } else {
  5424.                             $(".delete_file_btn").hide();
  5425.                             self.errorFileText('Размер файла превышает 5 МБ');
  5426.                         }
  5427.                     }
  5428.                 });
  5429.  
  5430.                 //клик по кнопке Отменить
  5431.                 cancelBtn.on('click', function (event) {
  5432.                     self.hide();
  5433.                 });
  5434.  
  5435.                 //обработчик для textarea
  5436.  
  5437.                 textarea.on('input change keyup', function (event) {
  5438.                     sendBtn.toggleClass('active', self.validateInput());
  5439.                 });
  5440.  
  5441.                 emailTextArea.on('input change keyup', function (event) {
  5442.                     sendBtn.toggleClass('active', self.validateInput());
  5443.                 });
  5444.  
  5445.                 //рендер на странице
  5446.                 if (config.renderToId)
  5447.                     $('#' + config.renderToId).append(domElement);
  5448.  
  5449.                 //интерфейс класса
  5450.                 self.domElement = domElement;
  5451.                 self.label = label;
  5452.                 self.emailTextArea = emailTextArea;
  5453.                 self.textarea = textarea;
  5454.                 self.fileInput = fileInput;
  5455.                 self.sendBtn = sendBtn;
  5456.                 self.curUserEmail = config.curUserEmail;
  5457.             }
  5458.             Constructor.prototype.deleteFile = function() {
  5459.                 var self = this;
  5460.                 self.fileText(defaultText);
  5461.                 $(".delete_file_btn").hide();
  5462.             }
  5463.             Constructor.prototype.show = function () {
  5464.                 var self = this;
  5465.  
  5466.                 //при повторном открытии очищаем введенный текст, выбранный файл, кнопку отправить делаем не активной
  5467.                 self.textarea.val('');
  5468.                 self.fileText(defaultText);
  5469.                 self.fileInput.val('');
  5470.                 self.sendBtn.removeClass('active');
  5471.                 $(".delete_file_btn").hide();
  5472.                 self.domElement.show();
  5473.                 $(".b-modal", self.domElement).show();
  5474.                 $("body").addClass("off-scroll");
  5475.             }
  5476.  
  5477.             Constructor.prototype.hide = function () {
  5478.                 var self = this;
  5479.  
  5480.                 $("body").removeClass("off-scroll");
  5481.                 $(".b-modal", self.domElement).hide();
  5482.                 self.domElement.hide();
  5483.             }
  5484.  
  5485.             Constructor.prototype.getDomElement = function () {
  5486.                 return this.domElement;
  5487.             }
  5488.  
  5489.             Constructor.prototype.errorFileText = function (str) {
  5490.                 var self = this;
  5491.  
  5492.                 self.label
  5493.                         .text(str)
  5494.                         .css('color', 'red');
  5495.             }
  5496.  
  5497.             Constructor.prototype.fileText = function (str) {
  5498.                 var self = this;
  5499.  
  5500.                 self.label
  5501.                         .text(str)
  5502.                         .css('color', '');
  5503.             }
  5504.  
  5505.             Constructor.prototype.validateInput = function () {
  5506.                 var self = this,
  5507.                     validator = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/gim),
  5508.                     isFilledTextarea = self.textarea.val().trim() != "";
  5509.  
  5510.                 if (self.curUserEmail == "") {
  5511.                     isFilledTextarea = validator.test(self.emailTextArea.val()) && isFilledTextarea;
  5512.                 }
  5513.  
  5514.                 return isFilledTextarea;
  5515.             }
  5516.  
  5517.             Constructor.prototype.sendAjax = function (text, fileString, file_name) {
  5518.                 var self = this;
  5519.                 $.ajax({
  5520.                     url: "/custom_web_template.html?object_code=beluga_send_admin_server",
  5521.                     type: "POST",
  5522.                     data: {
  5523.                         text: text,
  5524.                         file: fileString,
  5525.                         file_name: file_name,
  5526.                         cur_user_email: self.curUserEmail || self.emailTextArea.val()
  5527.                     },
  5528.                     dataType: "json",
  5529.                     success: function (data, textStatus, jqXHR) {
  5530.                         self.hide();
  5531.                     },
  5532.                     error: function () {
  5533.                         alert('Возникла ошибка при отправке');
  5534.                     }
  5535.                 });
  5536.             }
  5537.  
  5538.             return Constructor;
  5539.         })();
  5540.  
  5541.         var options = {"menuItems":[{"name":"Каталог курсов","link_href":"view_doc.html?mode=edu_catalog&amp;doc_id=6628161676399233617"},{"name":"Документы","link_href":"view_doc.html?mode=lib&amp;doc_id=6628162092753246374"},{"name":"Обучение","link_href":"view_doc.html?mode=doc&amp;doc_id=5800376573543914533"},{"name":"МИРР","link_href":"view_doc.html?mode=self_assessment&amp;doc_id=6631857937049990730"},{"name":"Библиотека","link_href":"view_doc.html?mode=doc&amp;doc_id=6522717384966615904"},{"name":"Заявки","link_href":"view_doc.html?mode=doc&amp;doc_id=6148914691236517176"},{"name":"Вакансии компании","link_href":"view_doc.html?mode=company_vacancys&amp;doc_id=6711191531803911194"}],"cur_user_email":"LebedevDO@belugagroup.ru"};
  5542.  
  5543.         //создание модального окна Написать администратору
  5544.         var modalAdmin = new Modal({
  5545.             renderToId: 'footer_modal_admin',
  5546.             curUserEmail: options.cur_user_email
  5547.         });
  5548.  
  5549.         //открытие модалки Написать администратору
  5550.         $('#footer_send_admin').on('click', function (event) {
  5551.             modalAdmin.show();
  5552.         });
  5553.  
  5554.         //меню
  5555.         var mainMenuContainer = $('#footer_menu_main');
  5556.         options.menuItems.forEach(function (item) {
  5557.             var a = $('<a href="' + item.link_href + '"></a>');
  5558.             a.text(item.name);
  5559.             mainMenuContainer.append(a);
  5560.         });
  5561.  
  5562.         $('#footer_copy').text('© ' + new Date().getFullYear() + ' BELUGA GROUP')
  5563.     });
  5564. </script>
  5565.         <!--footer -->
  5566.            
  5567.            
  5568.  
  5569.  
  5570.    
  5571. </body>
  5572. </html>
Add Comment
Please, Sign In to add comment