<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Toolbox</title>
</head>
<body style="display:none;">
  <!-- ========= -->
  <!--   HTML    -->
  <!-- ========= -->


  
  <div id="container">
    <div id="expressioneditor-container">
    
    </div>
   <div id="containerdata" ></div>
    <div class="modal" id="LabelModal" role="dialog" aria-labelledby="myModalLabel">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title tr" id="myModalLabel">Select Label</h4>
          </div>
          <div class="modal-body">
            <select class="form-control" id="LabelNameInput" placeholder="Label">
            </select>
            <span id="NoLabelFound" class="tr">No label found. Create one with Set label action.</span>

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-primary labelok standartbutton tr" data-dismiss="modal">Ok</button>
            <button type="button" class="btn btn-default standartbutton tr" data-dismiss="modal">Cancel</button>
          </div>
        </div>
      </div>
    </div>

    <div class="modal " id="TimeoutModal" role="dialog" aria-labelledby="myModalLabel">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title tr" id="myModalLabel">Maximum time to perform an action.</h4>
          </div>
          <div class="modal-body">
            <div class="row">
              <div class="col-lg-12">
                <div class="input-group">
                  <input type="number" id="TimeoutValue" class="form-control"/>
                  <span class="input-group-btn">
                    <button class="btn btn-default tr" type="submit">seconds</button>
                  </span>
                </div>
              </div>
            </div>
            <div class="row">
              <div class="col-lg-12">
               <span class="tr" style="font-size:small;color:gray">Use 'Timeout' action to set default timeout.</span>
              </div>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-primary timeoutok standartbutton tr" data-dismiss="modal">Ok</button>
            <button type="button" class="btn btn-default timeoutdefault standartbutton tr" data-dismiss="modal">Default</button>
            <button type="button" class="btn btn-default standartbutton tr" data-dismiss="modal">Cancel</button>
          </div>
        </div>
      </div>
    </div>


    <div class="modal text-center" id="WaitingModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-keyboard="false" data-backdrop="static">
    <div class="vertical-alignment-helper">
        <div class="modal-dialog vertical-align-center">
            <div class="modal-content">
                <div class="modal-body" style="margin-top:10px;margin-bottom:10px"><span class="tr">Executing Action</span>: <span class="tr text-danger" id="WaitingActionName">Unknown</span>
                
                <p style="margin-top:30px"><span id="InterruptMessage" class="tr" style="display:none">Trying to interrupt ...</span><a href="#" id="WaitingDisable" class="btn btn-default tr">Interrupt</a></p>
                </div>
                
            </div>
        </div>
    </div>
</div>

    

  </div>

  <!-- ========= -->
  <!-- TEMPLATES -->
  <!-- ========= -->

  <script type="text/template" id="targetfields">
    <span id="target-data" style="display:none">
      <%= _.template($('#input_constructor').html())({id:"TargetUrl", description:tr("Target url"), default_selector: "string", disable_int:true, value_string: "*", help: {description: tr("Change this parameter if you want to apply action only to certain urls. * symbol means any number of any characters. You can use several actions with different \"Target Url\" parameters. For example, set one proxy to *instagram.com* urls and another to *google.com* urls. Or set one proxy for *instagram.com* urls and another for all rest with *"), examples:[{code:"*",description:tr("Any url")},{code:"*google.com*",description:tr("Any url which contains google.com")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"TargetTabNumber", description:tr("Target tab number"), default_selector: "string", value_string: "*", value_number: 0, help: {description: tr("Change this parameter if you want to apply action only to certain tabs. * means any tabs. Numbering starts from 0. You can use several actions with different \"Target tab number\" parameters. For example, set one proxy to 0 tab and another to 1 tab. Or set one proxy for 0 tab and another for all rest with *"), examples:[{code:"*",description:tr("Any tab")},{code:"0",description:tr("Only first tab")}]}}) %>
    </span>
  </script>

  <script type="text/template" id="movefields">
    <div id="move-data" style="display:none" class="container-fluid moveandclick">

      <%= _.template($('#input_constructor').html())({id:"Speed", description:tr("Speed"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "100", help: {description: tr("Mouse movement speed as floating point value, if you change this, don't forget to change gravity and deviation proportionally.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Gravity", description:tr("Gravity"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "6", help: {description: tr("Floating point value which sets force of cursor attraction to strait line between starting and ending points. If you set this value too big, cursor will move by straight line, if you set it too low, cursor will move chaotically on the screen.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Deviation", description:tr("Deviation"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "2.5", help: {description: tr("Floating point value which sets force of cursor deviation from strait line between starting and ending points. Think of it as a wind, which blows cursor away from the line - the shortest path between two points.")}}) %>
    </div>
  </script>

  <script type="text/template" id="emulationfields">
    <div id="emulation-data" style="display:none" class="container-fluid">

      <%= _.template($('#info').html())({color: "gray", description: tr("<b>Idle emulation</b>. This section allows to configure idle emulation which will take place before current action. Idle emulation allows to browse of the current page as if the user is exploring it or searching for something on it.")}) %>
      <%= _.template($('#info').html())({color: "gray", description: tr("This section allows to configure idle emulation only for this individual action. Use <a href=\"#!/IdleEmulationSetGeneralSettings\">Enable automatic idle emulation</a> action to configure emulation generally. Use <a href=\"#!/IdleEmulationNew\">idle emulation</a> action to start emulation instantly. Specified settings from this section will override any default or general settings, and for unspecified, default or general settings will be used.")}) %>
      <%= _.template($('#input_constructor').html())({id:"time",description:tr("Maximum emulation time"),default_selector:"string",variants:[{value:"disable",description:tr("Disable emulation")},{value:"short",type:"string",description:tr("Short emulation time")},{value:"medium",type:"string",description:tr("Average emulation time")},{value:"long",type:"string",description:tr("Long emulation time")},{value:"30",type:"int",description:tr("30 sec")},{value:"{min: 15, max: 30}",type:"expression",description:tr("From 15 to 30 sec")}],value_string:"",min_number:1,max_number:999999,help:{description:tr("Maximum execution time of emulation before action.")+" "+tr("As a value can be specified as one of the three presets \"short\", \"medium\" or \"long\", or the exact value in seconds.")+" "+tr("And also you can disable emulation by specifying \"disable\".")+" "+tr("The exact emulation time will be determined immediately before the action depending on the emulation state."),examples:[{code:"short",description:tr("Short emulation time")},{code:"medium",description:tr("Average emulation time")},{code:"long",description:tr("Long emulation time")},{code:"disable",description:tr("Disable emulation")},{code:"30",description:tr("30 sec")},{code:"{min: 15, max: 30}",description:tr("From 15 to 30 sec")}]}})%>
      <%= _.template($('#input_constructor').html())({id:"accuracy",description:tr("Actions accuracy"),default_selector:"string",variants:["low","medium","high"],disable_int:true,value_string:"",help:{description:tr("Accuracy of actions is a parameter that determines the degree of detail of the algorithm's actions on the page. With high accuracy, the algorithm works with fewer elements by pointing the cursor precisely from one element to another. At low accuracy, the algorithm works with more elements performing many aimless movements."),examples:[{code:"low",description:tr("The probability of misses, delays and pointing to random coordinates is increased")},{code:"medium",description:tr("The parameters responsible for the accuracy of actions have average values")},{code:"high",description:tr("The probability of misses, delays and pointing to random coordinates is reduced")}]}})%>
      <%= _.template($('#input_constructor').html())({id:"intensity",description:tr("Actions intensity"),default_selector:"string",variants:["low","medium","high"],disable_int:true,value_string:"",help:{description:tr("Intensity of actions is a parameter controls the level of algorithm activity during emulation. If the intensity is high, the algorithm will interact with the page more frequently and dynamically. At low intensity, on the contrary, the algorithm will behave more restrained and patient."),examples:[{code:"low",description:tr("The probability of sleeping and the probability of short cursor movements is increased, the cursor speed is reduced")},{code:"medium",description:tr("The parameters responsible for the intensity of actions have average values")},{code:"high",description:tr("The probability of long cursor movements and page scrolling is increased, while the probability of sleeping is reduced")}]}})%>
      <%= _.template($('#block_start').html())({id:"Additional", smaller_fonts: true, name: tr("Actions performed"), description: tr("Using the parameters from this block, you can select what actions will be performed during emulation.")}) %>
        <%= _.template($('#input_constructor').html())({id:"sleep",description:tr("Sleep"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Sleep random time."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"longElementMove",description:tr("Long move to element"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Movement to a random element, with a large search radius for elements."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"shortElementMove",description:tr("Short move to element"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Movement to a random element, with a small search radius for elements."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"scroll",description:tr("Scroll"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Scroll at random distance."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"randomMove",description:tr("Random movement"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Cursor movement to random coordinates."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"microMove",description:tr("Micro movement"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Small movements of the cursor, simulating raising the mouse."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"goingBeyond",description:tr("Going beyond"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Going beyond the screen and returning back."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"moveAlongText",description:tr("Movement along text"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Slowly moving the cursor over an element with text from left to right to emulate reading."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#block_start').html())({id:"manualSetting", smaller_fonts: true, name: tr("Manual parameter setting"), description: tr("Using the parameters from this block, you can manually configure some emulation parameters. Specified parameters will be taken into account and default settings will be used for unspecified ones.")}) %>
        <%= _.template($('#input_constructor').html())({id:"longMax",description:tr("Long movements"),default_selector:"string",variants:["35%","50%","80%"],value_string:"",min_number:1,max_number:100,help:{description:tr("The radius of searching for elements during a long movement, measured as a percentage of the screen diagonal."),examples:[{code:"35%"},{code:"50%"},{code:"80%"}]}})%>
        <%= _.template($('#input_constructor').html())({id:"shortMax",description:tr("Short movements"),default_selector:"string",variants:["15%","25%","35%"],value_string:"",min_number:1,max_number:100,help:{description:tr("The radius of searching for elements during a short movement, measured as a percentage of the screen diagonal."),examples:[{code:"15%"},{code:"25%"},{code:"30%"}]}})%>
        <%= _.template($('#input_constructor').html())({id:"miss",description:tr("Misses on an element"),default_selector:"string",variants:[{value:"disable",description:tr("Disable misses")},{value:"low",description:tr("The chance of a miss and its distance is less")},{value:"medium",description:tr("The chance of a miss and its distance have average values")},{value:"high",description:tr("The chance of a miss and its distance is greater")}],disable_int:true,value_string:"",help:{description:tr("The mode of performing a miss on an element. The chance of a miss and its distance depend on it."),examples:[{code:"low",description:tr("The chance of a miss and its distance is less")},{code:"medium",description:tr("The chance of a miss and its distance have average values")},{code:"high",description:tr("The chance of a miss and its distance is greater")},{code:"disable",description:tr("Disable misses")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"delay",description:tr("Delay before hover"),default_selector:"string",variants:[{value:"disable",description:tr("Disable delay")},{value:"low",description:tr("The chance of delay and its duration is less")},{value:"medium",description:tr("The chance of delay and its duration have average values")},{value:"high",description:tr("The chance of delay and its duration is greater")}],disable_int:true,value_string:"",help:{description:tr("The mode of performing a delay before hover. The chance of a delay and its duration depends on it."),examples:[{code:"low",description:tr("The chance of delay and its duration is less")},{code:"medium",description:tr("The chance of delay and its duration have average values")},{code:"high",description:tr("The chance of delay and its duration is greater")},{code:"disable",description:tr("Disable delay")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"targetScroll",description:tr("Scroll to target"),default_selector:"string",variants:[{value:"disable",description:tr("Disable scrolling to target")},{value:"low",description:tr("Scrolling is slower, the pauses between several spins of the wheel is longer")},{value:"medium",description:tr("The scrolling speed and the duration of pauses between several spins of the wheel have average values")},{value:"high",description:tr("Scrolling is faster, the pauses between several spins of the wheel is shorter")}],disable_int:true,value_string:"",help:{description:tr("The mode of performing a scroll to target. The scrolling settings and whether it will be executed depend on it."),examples:[{code:"low",description:tr("Scrolling is slower, the pauses between several spins of the wheel is longer")},{code:"medium",description:tr("The scrolling speed and the duration of pauses between several spins of the wheel have average values")},{code:"high",description:tr("Scrolling is faster, the pauses between several spins of the wheel is shorter")},{code:"disable",description:tr("Disable scrolling to target")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"targetDelay",description:tr("Delay before click"),default_selector:"string",variants:[{value:"disable",description:tr("Disable delay")},{value:"low",description:tr("The chance of delay and its duration is less")},{value:"medium",description:tr("The chance of delay and its duration have average values")},{value:"high",description:tr("The chance of delay and its duration is greater")}],disable_int:true,value_string:"",help:{description:tr("The mode of performing a delay before click. The chance of a delay and its duration depends on it."),examples:[{code:"low",description:tr("The chance of delay and its duration is less")},{code:"medium",description:tr("The chance of delay and its duration have average values")},{code:"high",description:tr("The chance of delay and its duration is greater")},{code:"disable",description:tr("Disable delay")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"filters",description:tr("Selecting an element to hover"),default_selector:"string",variants:[{value:"all",description:tr("Don't filter elements")},{value:"link",description:tr("Links")},{value:"input",description:tr("Input fields")},{value:"clickable",description:tr("Clickable elements")},{value:"header",description:tr("Headings")},{value:"text",description:tr("Texts")},{value:"image",description:tr("Images")},{value:"icon",description:tr("Icons")}],disable_int:true,value_string:"",help:{description:tr("The mode for selecting elements for hovering, by which elements will be filtered for long and short movements."),examples:[{code:"link",description:tr("Links")},{code:"input",description:tr("Input fields")},{code:"clickable",description:tr("Clickable elements")},{code:"header",description:tr("Headings")},{code:"text",description:tr("Texts")},{code:"image",description:tr("Images")},{code:"icon",description:tr("Icons")},{code:"all",description:tr("Don't filter elements")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"hoverMode",description:tr("Hover position"),default_selector:"string",variants:[{value:"random",description:tr("Random position")},{value:"tocenter",description:tr("Position close to the center")},{value:"randomorcenter",description:tr("Random position or close to the center")}],disable_int:true,value_string:"",help:{description:tr("The position on the element to which hovering will be performed."),examples:[{code:"random",description:tr("Random position")},{code:"tocenter",description:tr("Position close to the center")},{code:"randomorcenter",description:tr("Random position or close to the center")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"maxRepeatSkip",description:tr("Re-hovering over an element"),default_selector:"int",disable_string:true,variants:[{value:"0",type:"int",description:tr("The element can be re-hovered immediately")},{value:"1",type:"int",description:tr("The element can be re-hovered after one iteration of move to element, from the search of which this element will be excluded")},{value:"3",type:"int",description:tr("The element can be re-hovered after 3 iterations of move to element, from the search of which this element will be excluded")},{value:"-1",type:"int",description:tr("The element can be re-hovered only after it goes out of visibility")}],value_number:"",min_number:-1,max_number:999999,help:{description:tr("The number of iterations of move to element after which the element can be hovered again. Also, the element can be hovered again if it goes out of visibility while scrolling."),examples:[{code:"0",description:tr("The element can be re-hovered immediately")},{code:"1",description:tr("The element can be re-hovered after one iteration of move to element, from the search of which this element will be excluded")},{code:"3",description:tr("The element can be re-hovered after 3 iterations of move to element, from the search of which this element will be excluded")},{code:"-1",description:tr("The element can be re-hovered only after it goes out of visibility")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"overlapByPoints",description:tr("Overlap by points"),default_selector:"int",disable_string:true,variants:[{value:"1",type:"int",description:tr("An element will be considered accessible if at least one of the points on it is not overlapped")},{value:"2",type:"int",description:tr("An element will be considered accessible if at least 2 points on it are not overlapped")},{value:"3",type:"int",description:tr("An element will be considered accessible if at least 3 points on it are not overlapped")},{value:"4",type:"int",description:tr("An element will be considered accessible if at least 4 points on it are not overlapped")},{value:"5",type:"int",description:tr("The element will be considered accessible only if all 5 points are not overlapped")}],value_number:"",min_number:1,max_number:5,help:{description:tr("The number of points on the element by which it will be determined whether the found element is overlapped, a maximum of 5 points: top right, top left, center, bottom right, bottom left."),examples:[{code:"1",description:tr("An element will be considered accessible if at least one of the points on it is not overlapped")},{code:"2",description:tr("An element will be considered accessible if at least 2 points on it are not overlapped")},{code:"3",description:tr("An element will be considered accessible if at least 3 points on it are not overlapped")},{code:"4",description:tr("An element will be considered accessible if at least 4 points on it are not overlapped")},{code:"5",description:tr("The element will be considered accessible only if all 5 points are not overlapped")}]}})%>
        <%= _.template($('#input_constructor').html())({id:"reverseScroll",description:tr("Reverse scroll chance"),default_selector:"string",variants:[{value:"disable",description:tr("Disable reverse scrolling")},{value:"low",description:tr("The chance of reverse scrolling is less")},{value:"medium",description:tr("The chance of reverse scrolling have average values")},{value:"high",description:tr("The chance of reverse scrolling is greater")},{value:"5",type:"int",description:tr("The chance of reverse scrolling 5 percent")}],value_string:"",help:{description:tr("Chance of a reverse scroll drop. As a value can be specified as one of the four presets \"disable\", \"low\", \"medium\" or \"high\", or an exact number from 0 to 100."),examples:[{code:"low",description:tr("The chance of reverse scrolling is less")},{code:"medium",description:tr("The chance of reverse scrolling have average values")},{code:"high",description:tr("The chance of reverse scrolling is greater")},{code:"disable",description:tr("Disable reverse scrolling")},{code:"5",description:tr("The chance of reverse scrolling 5 percent")}]}})%>
        <% if(typeof(additionalEmulation) != "undefined" && additionalEmulation){ %>
          <%= _.template($('#input_constructor').html())({id:"additionalEmulation",description:tr("Additional emulation"),default_selector:"string",disable_int:true,value_string:"",variants:[{value:"enable",description:tr("Perform")},{value:"disable",description:tr("Don't perform")}],help:{description:tr("Perform additional emulation during action execution.")+" "+tr("Additional emulation is small actions such as sleep, mouse movement, and in rare cases scrolling performed before, during, and/or after the target action. This emulation may also include improvements to emulate the target action, such as text type stuttering, typing speed changes, and improved hover position selection."),examples:[{code:"enable",description:tr("Perform")},{code:"disable",description:tr("Don't perform")}]}})%>
        <% } %>
      <%= _.template($('#block_end').html())() %>
    </div>
  </script>

  <script type="text/template" id="scrollparamsfields">
    <div id="scroll-params-data" style="display:none" class="container-fluid">

      <%= _.template($('#info').html())({color: "gray", description: tr("Using the parameters from this block, you can configure page scrolling at your discretion by changing the scrolling speed, pause time, and cursor movement while scrolling.")}) %>
      <%= _.template($('#input_constructor').html())({id:"scrollSpeed", description:tr("Scroll speed"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "100", help: {description:tr("The speed of scrolling, as a number. The higher the number, the faster the scrolling, and the lower the number, the slower the scrolling."),examples:[{code:"70"},{code:"100"},{code:"120"}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"minPause",description:tr("Minimum pause"),default_selector:"int",disable_string:true,value_number:100,min_number:1,max_number:999999,help:{description:tr("Minimum pause between several spins of the wheel, in milliseconds."),examples:[{code:"100"},{code:"300"},{code:"500"}]}})%>
      <%= _.template($('#input_constructor').html())({id:"maxPause",description:tr("Maximum pause"),default_selector:"int",disable_string:true,value_number:400,min_number:1,max_number:999999,help:{description:tr("Maximum pause between several spins of the wheel, in milliseconds."),examples:[{code:"200"},{code:"500"},{code:"1000"}]}})%>
      <%= _.template($('#input_constructor').html())({id:"moveChance",description:tr("Move chance"),default_selector:"expression",disable_int:true,disable_string:true,value_string:"0.2",help:{description:tr("Chance of performing a mouse movement during scrolling, as a floating point number, with a value from 0 to 100."),examples:[{code:"0.2"},{code:"5"},{code:"25"},{code:"0",description:tr("Don't move the mouse while scrolling")}]}})%>
      <%= _.template($('#checkbox').html())({id: "moveInScrollDirection", title: tr("Move in scroll direction"), help: {title: tr("Move in scroll direction"), description: tr("If enabled, the mouse movement will be in the scrolling direction and only in rare cases in the opposite direction."), examples: [{code: tr("Activated"), description: tr("Mouse movement in scroll direction")}, {code: tr("Deactivated"), description: tr("Mouse movement in a random direction")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"moveBeyond",description:tr("Screen border"),default_selector:"string",disable_int:true,variants:[{value: "random", description: tr("The mode will be selected randomly before scrolling starts")},{value: "avoid", description: tr("Don't go beyond the boundaries, the cursor will rest against them")},{value: "goandreturn", description: tr("The cursor may go out of boundaries, but when exiting it will be returned to the screen")}],value_string:"avoid",help:{description:tr("The mode of interaction of the mouse cursor with the borders of the screen when the mouse moves."),examples:[{code:"random",description:tr("The mode will be selected randomly before scrolling starts")},{code:"avoid",description:tr("Don't go beyond the boundaries, the cursor will rest against them")},{code:"goandreturn",description:tr("The cursor may go out of boundaries, but when exiting it will be returned to the screen")}]}})%>
      <%= _.template($('#input_constructor').html())({id:"moveMinDistance",description:tr("Move minimum distance"),default_selector:"int",disable_string:true,value_number:5,min_number:0,max_number:999999,help:{description:tr("Minimum mouse movement distance, in pixels."),examples:[{code:0},{code:20},{code:40}]}})%>
      <%= _.template($('#input_constructor').html())({id:"moveMaxDistance",description:tr("Move maximum distance"),default_selector:"int",disable_string:true,value_number:35,min_number:1,max_number:999999,help:{description:tr("Maximum mouse movement distance, in pixels."),examples:[{code:20},{code:35},{code:50}]}})%>
      <%= _.template($('#input_constructor').html())({id:"moveSpeed", description:tr("Move speed"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "100", help: {description: tr("Mouse movement speed as floating point value, if you change this, don't forget to change gravity and deviation proportionally.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"moveGravity", description:tr("Move gravity"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "6", help: {description: tr("Floating point value which sets force of cursor attraction to strait line between starting and ending points. If you set this value too big, cursor will move by straight line, if you set it too low, cursor will move chaotically on the screen.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"moveDeviation", description:tr("Move deviation"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "2.5", help: {description: tr("Floating point value which sets force of cursor deviation from strait line between starting and ending points. Think of it as a wind, which blows cursor away from the line - the shortest path between two points.")}}) %>
    </div>
  </script>

  <script type="text/template" id="multiselect">

    <div class="container-fluid multiselect">
      
      <div class="col-xs-12 multiselectborder" >
        <div class="multiselecttitle">
             <span class="tr">Multiparsing mode is on. Click on items inside browser to add "must include" or "must exclude" elements. This will tweak the selection.</span>
             <br/>
             
             <a onclick="BrowserAutomationStudio_OpenUrl('https://youtu.be/PQSQmJRVKvk');return false" class="tr-ru" href="#"><i class="fa fa-youtube-play" aria-hidden="true"></i> Как это работает?</a>
             <a onclick="BrowserAutomationStudio_OpenUrl('https://youtu.be/5XxXsgPj75U');return false" class="tr-en" href="#"><i class="fa fa-youtube-play" aria-hidden="true"></i> How it works?</a>

        </div>
        <div class="multiselectinclude">
            <span class="multiselectincludesign"> </span>
            <span class="tr">Elements that selection must include:</span> <strong id="multiselectincludenumber">0</strong>
        </div>
        <div class="multiselectexclude">
            <span class="multiselectexcludesign"> </span>
            <span class="tr">Elements that should not be included:</span> <strong id="multiselectexcludenumber">0</strong>
        </div>
        <div class="multiselectclearlinkcontainer">
            <a href="#" onclick="_MultiSelectManager.PathManuallyRest();return false;" class="multiselectreset"><i class="fa fa-trash-o" aria-hidden="true"></i> <span class="multiselectclearicon tr">Clear elements</span></a>
        </div>
      </div>

    </div>

  </script>

  <script type="text/template" id="expressioneditor">
    

    <div id="expressioneditor-list"></div>
    <div id="expressioneditor-constructor">
      
      <div id="expressioneditor-overlay">
        <div class="expressioneditor-overlay-title"><h2><span class="tr">Enter Value</span>:</h2></div>
        <div class="expressioneditor-overlay-data"><%= _.template($('#input_constructor').html())({id:"ExpressionValue", description:tr(""), default_selector: "string",disable_editor:true,min_number:-999999}) %></div>
        <div class="expressioneditor-overlay-buttons">
          <a href="#" class="btn btn-success btn-sm expressioneditor-button-accept" id="expressioneditor-valueok" ><span class="tr">OK</span></a><a href="#" id="expressioneditor-valuecancel" class="btn btn-danger btn-sm expressioneditor-button-accept" ><span class="tr">CANCEL</span></span></a>
        </div>
      </div>

      <div id="expressioneditor-overlay-confirm">
        <div class="expressioneditor-overlay-title"><h2><span class="tr">Confirm Changes</span>:</span></h2></div>
        <div class="expressioneditor-overlay-olddata"><span class="tr">Replace old value</span> <span id="expressioneditor-old-value"></span> <span class="tr">with new one</span>:</div>
        <div class="expressioneditor-overlay-data"><%= _.template($('#input_constructor').html())({id:"ExpressionValueConfirm", description:tr(""), default_selector: "expression",disable_editor:true,disable_int:true,disable_string:true}) %></div>
        <div class="expressioneditor-overlay-buttons">
          <a href="#" class="btn btn-success btn-sm expressioneditor-button-accept" id="expressioneditor-confirmok" ><span class="tr">OK</a><a href="#" id="expressioneditor-confirmcancel" class="btn btn-danger btn-sm expressioneditor-button-accept" ><span class="tr">CANCEL</span></a>
        </div>
      </div>

      <div class="expressioneditor-container">
        
        <button type="button" class="btn btn-info expressioneditor-add-string btn-sm"><span class="tr">STRING</span> +</button>
        <button type="button" class="btn btn-info expressioneditor-add-int btn-sm"><span class="tr">INT</span> +</button>
        <button type="button" class="btn btn-info expressioneditor-add-expression btn-sm"><span class="tr">EXPRESSION</span> +</button>
        
        <span id="expressioneditor-expression"></span>
        <div class="expressioneditor-bottom-titlebar">
           <a href="#" class="btn btn-success btn-sm expressioneditor-button-accept" id="expressioneditor-ok" ><span class="tr">ACCEPT</span> &gt;</a>   <a href="#" id="expressioneditor-cancel" class="btn btn-danger btn-sm expressioneditor-button-accept" ><span class="tr">CANCEL</tr></a>
        </div>
        <div class="expressioneditor-navigator">
        </div>
      </div>
    </div>
  </script>

  <script type="text/template" id="expressioneditor-list-item">
    <div><a href="#" class="expressioneditor-tool" data-name="<%= name %>"><%= name_translate %></a> : <%= description %></div>
  </script>

  <script type="text/template" id="checkbox">
    <div class="col-xs-12 <%= (typeof(additional_classes) == 'string') ? additional_classes : '' %>"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <form class="form-horizontal">
         <div class="form-group">
           <span 
           <% if(typeof(dont_preserve) != "boolean" || !dont_preserve){ %>
            data-preserve="true" 
          <%}%>
          data-preserve-type="check" data-preserve-id="<%= id %>"  class="nice-form-group">
            <input type="checkbox" id="<%= id %>" data-visibility-trigger="<%= id %>"
            
            <%= (typeof(checked) == "boolean" && checked) ? "checked='checked' data-default='true'" : "data-default='false'" %>
            
            /> 
            <label for="<%= id %>"> <%= title %></label> 
            <% if(typeof(help) == "object" && help){ %>
              <i style="margin-left:5px;cursor: pointer" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="select" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:help.title,description:help.description,examples:help.examples})) %>"></i>
            <% } %>
           </span>
         </div>
       </form>
    </div>
  </script>

  <script type="text/template" id="checkbox_inline">
    <div>
      <span data-preserve="true" data-preserve-type="check" data-preserve-id="<%= id %>" class="nice-form-group">
      <input type="checkbox" id="<%= id %>" data-visibility-trigger="<%= id %>"
      
      <%= (typeof(checked) == "boolean" && checked) ? "checked='checked' data-default='true'" : "data-default='false'" %>
      
      /> 
      <label for="<%= id %>"> <%= title %></label> 
      <% if(typeof(help) == "object" && help){ %>
        <i style="margin-left:5px;cursor: pointer" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="checkboxinline" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:help.title,description:help.description,examples:help.examples})) %>"></i>
      <% } %>
      </span>
    </div>
  </script>

  <script type="text/template" id="description">
    <div class="col-xs-12"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <form class="form-horizontal">
         <div class="form-group">
           
          <span style="margin:15px"> <%= name %></span> 
          <% if(typeof(help) == "object" && help){ %>
            <i style="margin-left:5px;cursor: pointer" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="select" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:help.title,description:help.description,examples:help.examples})) %>"></i>
          <% } %>
          
         </div>
       </form>
    </div>

  </script>

  <script type="text/template" id="radio">
    <div class="col-xs-12"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div class="form-horizontal">
         <div class="form-group">
           <span data-preserve="true" data-preserve-type="check" data-preserve-id="<%= id %>" class="nice-form-group">
            <input type="radio" id="<%= id %>" name="<%= name %>" data-visibility-trigger="<%= id %>"
            
            <%= (typeof(checked) == "boolean" && checked) ? "checked='checked' data-default='true'" : "data-default='false'" %>
            
            /> 
            <label for="<%= id %>"> <%= title %></label> 
            <% if(typeof(help) == "object" && help){ %>
              <i style="margin-left:5px;cursor: pointer" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="select" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:help.title,description:help.description,examples:help.examples})) %>"></i>
            <% } %>
           </span>
         </div>
       </div>
    </div>
  </script>

  <script type="text/template" id="combobox">
    <div class="col-xs-12"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div class="form-horizontal">
         <div class="form-group">
          <div class="combobox-container align-vertically">
            <span 
             <% if(typeof(dont_preserve) != "boolean" || !dont_preserve){ %>
              data-preserve="true" 
             <% } %>
             data-preserve-type="select" data-preserve-id="<%= id %>">
              <select class="combobox" id="<%= id %>" placeholder="<%= (typeof(title) == "string" ? _.escape(title) : "") %>"
                <%= (typeof(search) == "boolean" && search) ? "data-use-search='true' " : "" %>
                <%= (typeof(onchange) == "string" && onchange) ? "onchange='" + _.escape(onchange) + "' " : "" %>
                >
                  <% for(let item of items){ %>
                    <option 
                      value="<%= _.escape(item.value) %>"
                      <%= (typeof(item.selected) == "boolean" && item.selected) ? "selected='selected' data-default='true' " : "" %>
                      <% if(typeof(item.data) == "object"){ %>
                        <% for(let key in item.data){ %>
                          data-<%= key %>="<%= _.escape(item.data[key]) %>"
                        <% } %>
                      <% } %>
                      <% if(typeof(item.title) == "string"){ %>
                        data-html="<span title='<%= _.escape(item.title) %>' style='width: calc(100% + 14px); margin: -5px -7px -5px -7px; padding: 5px 7px 5px 7px;'><%= _.escape(item.name) %></span>"
                      <% } %>
                      ><%= _.escape(item.name) %></option>  
                  <% } %>
              </select>
            </span>
            <% if(typeof(title) == "string" && title){ %>
              <label style="margin-bottom: 0px;margin-left:10px;font-size:smaller;color:#555" for="<%= id %>"><%= _.escape(title) %></label>
            <% } %>
            <% if(typeof(help) == "object" && help){ %>
              <i style="margin-left:10px;cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="combobox" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:(help.title || title),description:help.description,examples:help.examples})) %>"></i>
            <% } %>
          </div>
        </div>
      </div>
    </div>

  </script>

  <script type="text/template" id="combobox_stretch">
    <div class="col-xs-12"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div class="form-horizontal">
         <div class="form-group">
          <div class="col-xs-12">
            <div class="input-group">
              <span 
               <% if(typeof(dont_preserve) != "boolean" || !dont_preserve){ %>
                data-preserve="true" 
               <% } %>
               data-preserve-type="select" data-preserve-id="<%= id %>">
                <select class="combobox" id="<%= id %>" placeholder="<%= _.escape(title) %>"
                  <%= (typeof(search) == "boolean" && search) ? "data-use-search='true' " : "" %>
                  <%= (typeof(onchange) == "string" && onchange) ? `onchange='${_.escape(onchange)}' ` : "" %>
                  >
                    <% for(let item of items){ %>
                      <option 
                        value="<%= _.escape(item.value) %>"
                        <%= (typeof(item.selected) == "boolean" && item.selected) ? "selected='selected' data-default='true' " : "" %>
                        <% if(typeof(item.data) == "object"){ %>
                          <% for(let key in item.data){ %>
                            data-<%= key %>="<%= _.escape(item.data[key]) %>"
                          <% } %>
                        <% } %>
                        <% if(typeof(item.title) == "string"){ %>
                          data-html="<span title='<%= _.escape(item.title) %>' style='width: calc(100% + 14px); margin: -5px -7px -5px -7px; padding: 5px 7px 5px 7px;'><%= _.escape(item.name) %></span>"
                        <% } %>
                        ><%= _.escape(item.name) %></option>  
                    <% } %>
                </select>
              </span>
              <span class="input-group-addon input-description"><%= title %>
                <% if(typeof(help) == "object"){ %>
                  <i style="cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-html="true" title="<%= _.escape(_.template($("#help_popup").html())({title:(help.title || title),description:help.description,examples:help.examples})) %>" ></i>
                <% } %>
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>

  </script>


  <script type="text/template" id="block_start">
    <span 
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div style="height:0px;clear: both;margin-bottom:-4px">&nbsp;</div>


      <div style="margin-left: 15px; background-color: #333; padding: left:10px; padding-left: 10px; border-radius: 2px; margin-top: 3px; margin-bottom: 4px; margin-right: 15px;">
        <i id="<%= id %>Icon" class="fa fa-caret-right" style="opacity: 0.5;margin-right:3px;margin-left:3px;width: 8px;"></i>
        <input type="checkbox" id="<%= id %>Check" onchange="if($('#<%= id %>Block').css('display') == 'none'){$('#<%= id %>Block').css('display', 'table-cell');} else {$('#<%= id %>Block').css('display', 'none');}$('#<%= id %>Icon').toggleClass('fa-caret-right').toggleClass('fa-caret-down')" style="margin-top: 6px;display:none" /> 
        <label for="<%= id %>Check" style="<%= (typeof(smaller_fonts) == 'boolean' && smaller_fonts) ? 'font-size: smaller;color: #4b4b4b;' : '' %> padding-top: 5px;padding-bottom: 5px;margin-bottom: 0px !important;width: calc(100% - 40px);cursor:pointer" ><%= name %></label>
      </div>

      <span id="<%= id %>Block" style="display:none;width: 100vw;padding-left:10px;">
          <% if(description){ %>
            <div class="block_info_gray"><%= description %></div>
          <% } %>
  </script>

  <script type="text/template" id="block_end">
      </span>
    </span>
  </script>

  <script type="text/template" id="info">
    <div style="height:0px;clear: both;">&nbsp;</div>
    <div class="block_info_<%= color %>"><%= description %></div>
  </script>


  <script type="text/template" id="ip_information">

    <%= _.template($('#block_start').html())({id: "IpInfo", name: tr("IP information"), description: tr("Options below will define method to obtain information about IP. Default settings will work fine.")}) %>

      <%= _.template($('#input_constructor').html())({id:"IpInfoMethod", description:tr("IP info method"), default_selector: "string", disable_int:true, value_string: "database", variants: ["database<br/><span style='color:gray;font-size:small'>" + tr("Use internal IP database") + "</span>","ip-api.com<br/><span style='color:gray;font-size:small'>" + tr("Use ip-api.com service") + "</span>","custom function<br/><span style='color:gray;font-size:small'>" + tr("Сustom BAS function to obtain IP information") + "</span>"], help: {description: tr("Method which will be used to obtain information about IP."),examples:[{code:"database",description:tr("Use internal database, it is fast and always available. Even though the database is constantly being updated, this method may not be the most accurate compared to the others.")},{code:"ip-api.com",description:tr("Use ip-api.com service. Free version has limit - 45 requests from single IP. Pro version is not limited to request number but costs 15$ per month.")},{code:"custom function",description:tr("Use custom BAS function to obtain IP information.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"IpApiKey", description:tr("ip-api.com key. Can be blank."), default_selector: "string", disable_int:true, help: {description: tr("Key from the ip-api.com service, pro version. Key available after purchase. This parameter is used only if \"IP info method\" is set to \"ip-api.com\" value."), examples:[{code:tr("Empty string"),description:tr("Use free version")},{code:tr("Key"),description:tr("Use pro version")}]}}) %>

      <div class="container-fluid executefunction">
        <div class="col-xs-12" style="margin-bottom: 5px;padding-right: 0px;">
          
          <div class="input-group">
            
            <span data-preserve="true" data-preserve-type="text" data-preserve-id="FunctionName">
              <input class="form-control function-input" type="text" id="FunctionName" placeholder="Custom IP information function">
              <ul class="dropdown-menu input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown">
                <li>
                  <a tabindex="-1" href="#" class="func" data-result-target="#FunctionName">
                    <span class="tr">Select function</span>
                  </a>
                </li>
              </ul>
            </span>        

            <span class="input-group-addon input-description">
              <span class="tr">Custom IP information function</span>

              <i style="cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())(
                {
                  title:tr('Custom IP information function'),
                  description:tr('Custom BAS function, which takes IP string as input(&quot;Ip&quot; input parameter) and returns JSON with IP information. This parameter is used only if &quot;IP info method&quot; is set to &quot;custom function&quot; value.'),
                  examples:[
                  { code: `{
                    <div style='margin-left:5px'>valid: true,</div>
                    <div style='margin-left:5px'>city: "Frankfurt am Main",</div>
                    <div style='margin-left:5px'>country: "DE",</div>
                    <div style='margin-left:5px'>dstoffset: -120,</div>
                    <div style='margin-left:5px'>offset: -60,</div>
                    <div style='margin-left:5px'>timezone: "Europe/Berlin",</div>
                    <div style='margin-left:5px'>longitude: 8.6843,</div>
                    <div style='margin-left:5px'>latitude: 50.1188</div>
                  }`, description: tr('JSON example, which must return custom function.') },
                ]
                }
              )) %>" ></i>

            </span>
          </div>
          
        </div>
        
      </div>

      <%= _.template($('#block_end').html())() %>
  </script>

  <script type="text/template" id="___none">
  </script>

  <script type="text/template" id="main">
    <div class="leftactionpaneltitledrop" style="display:none">
      <i class="fa fa-trash-o" aria-hidden="true"></i>
    </div>
    <div class="container-fluid search-bar-container">
      <div class="search-bar">
        <input type="text" class="search-input" id="searchinput" placeholder="What to search?">
        <span class="search-control search-icon">
          <i class="fa fa-fw fa-search" aria-hidden="true"></i>
        </span>
        <span class="search-pagination" id="pagination">
          <button type="button" class="search-control search-page-button" id="prevpage">
            <i class="fa fa-fw fa-chevron-left" aria-hidden="true"></i>
          </button>
          <span class="search-page-label">
            <span class="text-dark" id="currpage"></span>
            <span class="text-gray">-</span>
            <span class="text-gray" id="lastpage"></span>
          </span>
          <button type="button" class="search-control search-page-button" id="nextpage">
            <i class="fa fa-fw fa-chevron-right" aria-hidden="true"></i>
          </button>
          </span>
        <button type="button" class="search-control search-clear-button" id="searchclear">
          <i class="fa fa-fw fa-times" aria-hidden="true"></i>
        </button>
        </div>
      </div>
    <div class="search">
      <span class="results-recent"></span>
      <span class="results-empty"></span>
      <ol class="results-list" id="results"></ol>
    </div>
    <div class="actions">
      <div class="leftpanel">
        <button type="button" id="showbookmarks" class="btn btn-default btn-sm" style="margin-bottom:5px"><i class="fa fa-bookmark" aria-hidden="true"></i></button>
        <button type="button" id="showhistory" class="btn btn-default btn-sm"><i class="fa fa-history" aria-hidden="true"></i></button>
      </div>
      <div class="leftactionpanel" style="display:none">
        
        <div class="leftactionpaneltitle"></div>
        <div class="leftactionpaneltitlebody" style="margin-top:3px;margin-bottom:3px">

        </div>
        
      </div>
      <div class="container-fluid mainscreen" >
        <div class="panel-group" style="margin-bottom: 0px;">
            <% var group = null; %>


            <% _.each(data, function(task) { %>
                <% if(typeof(task.type) != "undefined" && task.type == "group") { %>
                  <% group = task.name; %>
                  <span data-group="<%= task.name %>" data-group-all="<%= task.name %>"  ondragstart="return false;" ondrop="return false;">
                    <a href="#" data-group="<%= task.name %>" data-group-all="<%= task.name %>" class="groupshow" style="color:black" >
                      <div class="panelgrid text-center panelgrid-<%= group %>" data-toggle-none="tooltip" data-placement-none="auto" title-none="<%=task.info%>">
                        
                        <div class="panelgridtitle"><div class="panelgridtitleinner"><%= task.description %></div></div>
                        <div class="panelgridimage">
                          <span class="helper"></span>
                          <% if(typeof(task.icon) != "undefined") { %>
                            <img src="<%= task.icon %>" class="center-block img-responsive" />
                          <% } else { %>
                            <img src="../icons/module.png" class="center-block img-responsive" />
                          <% } %>
                        </div>
                      </div>
                    </a>
                    <span data-group="<%= task.name %>" style="display:none">
                      <div class="returntomaindiv">
                        <a href="#" class="returntomain"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> <span class="tr" style="font-size:smaller">Return to main screen</span></a>
                      </div>
                      <hr style="margin-top:5px;margin-bottom:5px" />
                      <% if(typeof(task.info) != "undefined") { %>
                        <div class="panelgriddescription"><%= task.info %>
                        </div>
                      <% } %>
                      <div style="clear: both;"></div>

                      
                    </span>
                  </span>
                <% }else{ %>
                    <a class="toolbutton <%= ((typeof(BookmarkList) != "undefined" && BookmarkList.indexOf(task.ref) >= 0) ? "toolbookmark" : "") %>" href="#!/<%= task.ref %>" data-placement="right" title="<%= task.description %>" data-name="<%= task.name %>" data-ref="<%= task.ref %>" data-group="<%= group %>" style="display:none"  >
                      <div class="tool">
                         <span class="toolinner"><%= task.name %></span>
                      </div>
                    </a>
                <% } %>
            <% }); %>


            <% _.each(unused, function(task) { %>
              
                <span data-group="<%= task.name %>" data-group-all="<%= task.name %>"  ondragstart="return false;" ondrop="return false;">
                  <a href="#" data-group="<%= task.name %>" data-group-all="<%= task.name %>" class="groupshow" style="color:black" >
                    <div class="panelgrid panelunused text-center" data-toggle-none="tooltip" data-placement-none="auto" title-none="<%=task.name%>" data-task-name="<%= task.name %>">
                      
                      
                      
                      <div class="panelgridtitle"><div class="panelgridtitleinner"><%= task.description %></div></div>
                      <div class="panelgridimage">
                        <span class="helper"></span>
                        <% if(typeof(task.icon) != "undefined") { %>
                          <img src="<%= task.icon %>" class="center-block img-responsive" />
                        <% } else { %>
                          <img src="../icons/modules.png" class="center-block img-responsive" />
                        <% } %>
                      </div>
                      <i class="fa fa-plus-square unused-add-icon" ></i>
                    </div>
                  </a>
                </span>
              
          <% }); %>


            </div>
          </div>
        </div>
      </div>
    </div>
  </script>

  <script type="text/template" id="back">
    <div class="container-fluid back" >
      <div class="col-xs-12">
        
        <div class="action-name-container">
          <% var GroupInfo = _GobalModel.GetGroupInfo() %>

          <div style="margin-right:5px">
            <a href="#!/" id="backtohomefromtopmenu" class="tr" >Main</a>
          </div>
          
          <div style="margin-right:5px;">
            /
          </div>
          


          <% if(typeof(GroupInfo) == "object" && GroupInfo !== null && typeof(GroupInfo.description) == "string"  && GroupInfo.description.length > 0 && typeof(GroupInfo.name) == "string"  && GroupInfo.name.length > 0){ %>
            <div style="margin-right:5px;">
              <a href="#!/" id="backtomainfromtopmenu" data-group-name="<%= GroupInfo.name %>">
                <%= GroupInfo.description %>
              </a>
            </div>
            <div style="margin-right:5px;">
              /
            </div>
          <% } %>
          <div class="action-name-action-name">
            <% 
              var State = _GobalModel.get("state") 
              var Name = _GobalModel.GetPageInfo() || name
              if(typeof(State) == "string")
              {
                if(State == "threadnumber")
                {
                  Name = tr("Thread number")
                }else if(State == "successnumber")
                {
                  Name = tr("Success number")
                }else if(State == "failnumber")
                {
                  Name = tr("Fail number")
                }
              }
            %>

            <%= Name %> 
          </div>

          <% if(typeof(modal_code_id) != "undefined"){ %>
            <% if(typeof(use_modal_template) != "undefined"){ %>
              <a onclick="bootbox.alert({message: _.template($('#<%= modal_code_id %>').html())({}), size: 'large'});return false;" href="#" style="margin-top: 1px;" class="text-info"><i class="fa fa-question-circle help-input"></i>  </a>
            <% }else{ %>      
              <a onclick="bootbox.alert({message: $('#<%= modal_code_id %>').html(), size: 'large'});return false;" href="#" style="margin-top: 1px;" class="text-info"><i class="fa fa-question-circle help-input"></i>  </a>
            <% } %>  
          <% } %>  
        </div>

        
        <div class="back-container">
          <div class="back-container-left">
            <% if(typeof(only_cancel) == "undefined"){ %> <a tabindex="-1" class="btn btn-success standartbutton tr" id="ok">Ok</a> <% } %> <a tabindex="-1" class="btn btn-danger standartbutton tr" href="#!/" id="backtomain">Cancel</a>
          </div>

          <div class="back-container-middle">
        
            <% if(typeof(only_cancel) == "undefined"){ %>
              <% if(typeof(use_waiter) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-waiter" class="<%= (typeof(waiter_enabled) != "undefined" && waiter_enabled) ? "" : "use-waiter-disabled" %> trtitle" data-enabled="<%= (typeof(waiter_enabled) != "undefined" && waiter_enabled) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="<%= (typeof(waiter_title) != "undefined") ? waiter_title : "Wait full page load after this action" %>"><i class="fa fa-clock-o" aria-hidden="true"></i></a>

              <% } %>

              <% if(typeof(use_target) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-target" class="<%= (typeof(target_enabled) != "undefined" && target_enabled) ? "" : "use-target-disabled" %> trtitle" data-enabled="<%= (typeof(target_enabled) != "undefined" && target_enabled) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="Toggle target. Apply this action only to specific url or to specific tab."><i class="fa fa-dot-circle-o" aria-hidden="true"></i></a>

              <% } %>

              <% if(typeof(use_timeout) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-timeout" data-value="<%= (typeof(timeout_value) != "undefined" && timeout_value > 0) ? timeout_value : "0" %>" class="<%= (typeof(timeout_value) != "undefined" && timeout_value > 0) ? "" : "use-timeout-disabled" %> trtitle"  data-enabled="<%= (typeof(timeout_value) != "undefined" && timeout_value > 0) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="Maximum time to perform an action.">
                  <i class="fa fa-hourglass-end" aria-hidden="true" ><small id="timeout-is-default" class="tr" <%= (typeof(timeout_value) != "undefined" && timeout_value > 0) ? "style='display:none'" : "" %> >default </small></i><small id="timeout-val"><%= (typeof(timeout_value) != "undefined" && timeout_value > 0) ? ("" + timeout_value) : "" %></small></a>
              <% } %>

              <% if(typeof(use_move) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-move" class="<%= (typeof(move_enabled) != "undefined" && move_enabled) ? "" : "use-move-disabled" %> trtitle" data-enabled="<%= (typeof(move_enabled) != "undefined" && move_enabled) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="Tweak speed and other parameters for mouse move."><i class="fa fa-sliders" aria-hidden="true"></i></a>
              <% } %>
    
              <% if(typeof(use_scroll_params) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-scroll-params" class="<%= (typeof(scroll_params_enabled) != "undefined" && scroll_params_enabled) ? "" : "use-scroll-params-disabled" %> trtitle" data-enabled="<%= (typeof(scroll_params_enabled) != "undefined" && scroll_params_enabled) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="Tweak speed and other scrolling parameters."><i class="fa fa-sliders" aria-hidden="true"></i></a>
              <% } %>
    
              <% if(typeof(use_emulation) != "undefined"){ %>
                <a href="#" tabindex="-1" id="use-emulation" class="<%= (typeof(emulation_enabled) != "undefined" && emulation_enabled) ? "" : "use-emulation-disabled" %> trtitle" data-enabled="<%= (typeof(emulation_enabled) != "undefined" && emulation_enabled) ? "true" : "false" %>" data-toggle="tooltip" data-placement="top" title="Tweak emulation before action.">
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M9 3.5V2M5.06066 5.06066L4 4M5.06066 13L4 14.0607M13 5.06066L14.0607 4M3.5 9H2M8.5 8.5L12.6111 21.2778L15.5 18.3889L19.1111 22L22 19.1111L18.3889 15.5L21.2778 12.6111L8.5 8.5Z" stroke="#31708f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                  </svg>
                </a>
              <% } %>
            <% } %>
          </div>

          <% if (typeof(only_cancel) === 'undefined' && visible) { %>
            <div class="back-container-right">
              <div class="input-group-btn execute-type" id="executeType">
                <button tabindex="-1" type="button" class="btn dropdown-toggle execute-type-btn" id="executeTypeValue" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-placement="top" title="<%= tr(`By default action will be added to scenario panel and executed. Change this option if action must only be executed or only added to scenario panel.`) %>"></button>
                <ul class="dropdown-menu dropdown-black execute-type-menu dropdown-menu-right" data-auto-width="menu">
                  <li class="dropdown-item dropdown-border" >
                    <a tabindex="-1" href="#" class="btn execute-type-item" data-action="add" data-placement="top" data-toggle="tooltip" title="<%= tr(`Don't execute this action but save it to script tab.`) %>">
                      <svg class="dropdown-icon" width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M9.375 3.375H10.625V6.5H13.75V7.75H10.625V10.875H9.375V7.75H6.25V6.5H9.375V3.375Z" fill="#606060" />
                        <path d="M0.625 15.625V0.375H19.375V15.625H0.625ZM18.125 1.625H1.875V13.125H18.125V1.625Z" fill="#606060" />
                      </svg>                      
                      <span class="dropdown-text execute-type-text"><%= tr('Only add') %></span>
                    </a>
                  </li>
                  <li class="dropdown-item dropdown-border">
                    <a tabindex="-1" href="#" class="btn execute-type-item" data-action="execute" data-placement="top" data-toggle="tooltip" title="<%= tr(`Execute this action and don't save it to script tab.`) %>">
                      <svg class="dropdown-icon" width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M8.99974 10.516L14.8898 4.6666L14.0024 3.73242L8.99992 8.65567L6.74752 6.44294L5.86035 7.3768L8.99974 10.516Z" fill="#606060"/>
                        <path d="M0.625 15.625V0.375H19.375V15.625H0.625ZM18.125 1.625H1.875V13.125H18.125V1.625Z" fill="#606060" />
                      </svg>                      
                      <span class="dropdown-text execute-type-text"><%= tr('Only execute') %></span>
                    </a>
                  </li>
                  <li class="dropdown-item dropdown-border">
                    <a tabindex="-1" href="#" class="btn execute-type-item" data-action="executeandadd" data-placement="top" data-toggle="tooltip" title="<%= tr(`Execute this action and save it to script tab.`) %>">
                      <svg class="dropdown-icon" width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M7.41573 6.49994H8.38202H14V7.74994H8.38202H7.41573H5V6.49994H7.41573Z" fill="#606060" />
                        <path d="M15.1265 7.11752L14.2426 8.0014L10 3.75876L10.8839 2.87488L15.1265 7.11752Z" fill="#606060" />
                        <path d="M10.8838 11.3603L9.99991 10.4765L14.2426 6.23383L15.1264 7.11771L10.8838 11.3603Z" fill="#606060" />
                        <path d="M0.625 15.625V0.375H19.375V15.625H0.625ZM18.125 1.625H1.875V13.125H18.125V1.625Z" fill="#606060" />
                      </svg>                      
                      <span class="dropdown-text execute-type-text"><%= tr('Execute and add') %></span>
                    </a>
                  </li>
                </ul>
              </div>
            </div>
          <% } %>
        </div>
      </div>
    </div>
  </script>

  <script type="text/template" id="variable_constructor">
    <span data-preserve="true" data-preserve-type="var" data-preserve-id="<%= id %>"
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
     >
      <div class="col-xs-12">
        <form class="form-horizontal">
          <div class="form-group">
            <div class="col-xs-12">
              <div class="input-group">
                <input class="form-control variable-input" style='color:#529653;'  type="text" id="<%= id %>" placeholder="<%= description %>" value="<%= default_variable %>" data-variable-constructor="true" <%= (typeof(append_mode) != "undefined") ? "data-append-array=\"true\"" : "" %> >
                
                <ul class="dropdown-menu input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown">
                  <li class="dropdown-border">
                    <a  style="display: flex; align-items: center;  justify-content: start;" tabindex="-1" href="#" data-toggle="modal" data-result-target="#<%= id %>" class="var" data-toggle="modal" data-target="#VariableModal" data-result-target="#<%= id %>" <%= (typeof(disable_locals) != "undefined") ? "disable_locals=\"true\"" : "" %> <%= (typeof(enable_globals) != "undefined") ? "":"disable_globals=true" %> >
                      <svg class="dropdown-icon" width="16" height="16"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"  style="margin-right:10px">
                        <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#fff" />
                        <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#fff" />
                      </svg>
                      <span class="tr"  style="font-size:12px;">Insert existing variable</span>
                    </a>
                  </li>
                </ul>

                <span class="input-group-addon input-description"><%= description %>
                  <% if(typeof(help) == "object"){ %>
                    <!--<i class="fa fa-question-circle help-input" data-toggle="tooltip" data-html="true" title="<%= _.escape(_.template($("#tooltip-input").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>-->

                    <i style="cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-html="true" title="<%= _.escape(_.template($("#help_popup").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>

                  <% } %>
                </span>
              </div>
            </div>

          </div>
        </form>
      </div>
    </span>
  </script>

  <script type="text/template" id="selector_menu">
    <ul tabindex="-1" class="dropdown-menu dropdown-menu-with-breaks dropdown-menu-css-options dropdown-black selector-menu" style="font-size:smaller;">
      <% if("css1" in selector && selector["css1"].length > 0) { %>
        <li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item" data-selected="true"><%= selector["css1"] %></a></li>
      <% }else{ %>  
        <li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item"><%= selector["css"] %></a></li>
      <% } %>
      <% if("css2" in selector && selector["css2"].length > 0) { %>
        <li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item"><%= selector["css2"] %></a></li>
      <% } %>

      <% if("css3" in selector && selector["css3"].length > 0) { %>
        <li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item"><%= selector["css3"] %></a></li>
      <% } %>

      <li class="dropdown-border">
        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#selector-input" class="res" style="display: flex; align-items: center;  justify-content: start;" >
          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
            <path d="M1.5 1.5v13h13v-13h-13zm12 12h-11v-3h11v3zm0-4h-11v-3h11v3zm-1.5-6a.5.5 0 110 1 .5.5 0 010-1z" fill="#fff" />
            <path d="M12 8.5a.5.5 0 100-1 .5.5 0 000 1zM12 12.5a.5.5 0 100-1 .5.5 0 000 1z" fill="#fff" />
          </svg>
            <span class="tr" style="font-size:12px;margin-right:10px">Load from file, user input, database</span>
        </a>
      </li>

      <li class="dropdown-border">
        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#selector-input" class="var" style="display: flex; align-items: center;  justify-content: start;" >
          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
            <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#fff" />
            <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#fff" />
          </svg>
            <span class="tr" style="font-size:12px;margin-right:10px">Insert variable</span>
        </a>
      </li>

      
    </ul>

  </script>

  <script type="text/template" id="resource_constructor">
    <span data-preserve="true" data-preserve-type="var" data-preserve-id="<%= id %>">
      <div class="col-xs-12">
        <form class="form-horizontal">
          <div class="form-group">
            <div class="col-xs-12">
              <div class="input-group">
                <input class="form-control resource-input" type="text" id="<%= id %>" placeholder="<%= description %>" value="" data-resource-constructor="true" />

                <ul class="dropdown-menu input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown">
                  <li>
                    <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#<%= id %>" class="res" data-toggle="modal" data-target="#RecourseModal" data-result-target="#<%= id %>">
                      <i class="fa fa-database"/>
                        <span class="tr">Select resource</span>
                    </a>
                  </li>
                </ul>

                <span class="input-group-addon input-description"><%= description %>
                  <% if(typeof(help) == "object"){ %>
                    <i class="fa fa-question-circle help-input" data-toggle="tooltip" data-html="true" title="<%= _.escape(_.template($("#tooltip-input").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>
                  <% } %>
                </span>
              </div>
            </div>
          </div>
        </form>
      </div>
    </span>
  </script>

  <script type="text/template" id="path">
    <div class="path" >
      <% if(selector["is_image"]){ %>


      <% }else{ %>
        <% if(typeof(disable_options) == "undefined"){ %>
          <span <%= (typeof(hide_options) != "undefined") ? 'style="display:none"':'' %> >
            <%= _.template($('#block_start').html())({id: "IfElementMissingSettings", name: tr("If element missing"), smaller_fonts: true, description: tr("")}) %>
            
              <%= _.template($('#checkbox').html())({id: "checkbox-wait-element", title: tr("Wait for element."), checked: (typeof(waitelement) != "boolean" || waitelement), dont_preserve: true, help: 
                {
                  description: tr("This setting allows you to decide whether to wait for the desired element if it is not found on the page"), 
                  examples:[
                    {code:tr("Activated"),description:tr("Wait a certain time for the element to appear. The exact amount of time by default is one minute, which can be changed by clicking on the hourglass icon below.")},
                    {code:tr("Deactivated"),description:tr("Action will finish instantly no matter if element is present on page or not.")}
                  ]
                }
              }) %>
              <%= _.template($('#checkbox').html())({id: "checkbox-fail-action", title: tr("Fail thread if element not found."), smaller_fonts: true, checked: (typeof(failaction) != "boolean" || failaction), dont_preserve: true, help: 
                {
                  description: tr("If thread must be stopped with error when specified element is not present on page. You can process this error later by using 'Ignore errors' action."), 
                  examples:[
                    {code:tr("Activated"),description:tr("If element is not found on page, thread will be stopped.")},
                    {code:tr("Deactivated"),description:tr("If element is not found on page, this action will be skipped, thread execution will continue.")}
                  ]
                }
              }) %>
            <%= _.template($('#block_end').html())() %>
          </span>
        <% } %>
        <% if (!PreviewModel.isDisabled) { %>
        <%= _.template($('#block_start').html())({id: "ElementPreviewSettings", name: tr("Element preview") + ' <i class="fa fa-spinner fa-spin hidden" style="line-height: inherit;"></i>', smaller_fonts: true, description: tr("")}) %>
          <div class="preview-container">
            <img id="previewImage" class="preview-image hidden" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" draggable="false">
            <div class="preview-buttons">
              <button type="button" id="updatePreview" tabindex="-1" class="btn btn-xs preview-button" title="<%= tr('Update preview') %>" data-action="update">
                <i class="fa fa-refresh" aria-hidden="true"></i>
              </button>
              <button type="button" id="deletePreview" tabindex="-1" class="btn btn-xs preview-button" title="<%= tr('Delete preview') %>" data-action="delete">
                <i class="fa fa-trash" aria-hidden="true"></i>
              </button>
              <button type="button" id="restorePreview" tabindex="-1" class="btn btn-xs preview-button hidden" title="<%= tr('Restore original') %>" data-action="restore">
                <i class="fa fa-undo" aria-hidden="true"></i>
              </button>
            </div>
          </div>
        <%= _.template($('#block_end').html())() %>
        <% } %>
      <% } %>   

      <div class="col-xs-12">
        <form class="form-horizontal" onsubmit="return false;">
          <div class="form-group">
            <div class="col-xs-12">


              <% if(selector["is_image"]){ %>
                <table id="ImageTable">
                  <tr>
                    <td align="center">
                      <a href="#" id="ImageDataRef">
                        <img id="ImageData" style="max-width:300px;"/>
                      </a>
                    </td>
                    <td style="width:100%;" valign="top">
                      <% if(typeof(disable_options) == "undefined"){ %>
                        
                        <span <%= (typeof(hide_options) != "undefined") ? 'style="display:none"':'' %> >

                          <%= _.template($('#checkbox').html())({id: "checkbox-wait-element", title: tr("Wait for element."), checked: (typeof(waitelement) != "boolean" || waitelement), dont_preserve: true, help: 
                            {
                              description: tr("This setting allows you to decide whether to wait for the desired element if it is not found on the page"), 
                              examples:[
                                {code:tr("Activated"),description:tr("Wait a certain time for the element to appear. The exact amount of time by default is one minute, which can be changed by clicking on the hourglass icon below.")},
                                {code:tr("Deactivated"),description:tr("Action will finish instantly no matter if element is present on page or not.")}
                              ]
                            }
                          }) %>
                
                          <%= _.template($('#checkbox').html())({id: "checkbox-fail-action", title: tr("Fail thread if element not found."), checked: (typeof(failaction) != "boolean" || failaction), dont_preserve: true, help: 
                            {
                              description: tr("If thread must be stopped with error when specified element is not present on page. You can process this error later by using 'Ignore errors' action."), 
                              examples:[
                                {code:tr("Activated"),description:tr("If element is not found on page, thread will be stopped.")},
                                {code:tr("Deactivated"),description:tr("If element is not found on page, this action will be skipped, thread execution will continue.")}
                              ]
                            }
                          }) %>
                
                        </span>
                      <% } %>

                    </td>
                  </tr>
                </table>
                

              <% } else { %>
                


                <div class="input-group">
                    <input type="text" class="form-control dropdown-menu-path" aria-label="..." id="selector-input" onblur="$('#wiki-selector img').css('opacity','0.45');$('#wiki-selector img').attr('src','wiki.png')" onfocus="$('#wiki-selector img').css('opacity','0.8');$('#wiki-selector img').attr('src','wiki_red.png')" />
                    
                    <%= _.template($('#selector_menu').html())({selector:selector}) %>

                    <ul tabindex="-1" class="dropdown-menu dropdown-menu-with-breaks dropdown-menu-match-xpath-at-css-options dropdown-black" style="font-size:smaller;">
      
                      <li class="dropdown-border">
                        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#selector-input" class="res" style="display: flex; align-items: center;  justify-content: start;" >
                          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                            <path d="M1.5 1.5v13h13v-13h-13zm12 12h-11v-3h11v3zm0-4h-11v-3h11v3zm-1.5-6a.5.5 0 110 1 .5.5 0 010-1z" fill="#fff" />
                            <path d="M12 8.5a.5.5 0 100-1 .5.5 0 000 1zM12 12.5a.5.5 0 100-1 .5.5 0 000 1z" fill="#fff" />
                          </svg>
                            <span class="tr" style="font-size:12px;margin-right:10px">Load from file, user input, database</span>
                        </a>
                      </li>
                
                      <li class="dropdown-border">
                        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#selector-input" class="var" style="display: flex; align-items: center;  justify-content: start;" >
                          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                            <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#fff" />
                            <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#fff" />
                          </svg>
                            <span class="tr" style="font-size:12px;margin-right:10px">Insert variable</span>
                        </a>
                      </li>
                
                      
                    </ul>

                    <span class="input-group-addon input-description">
                      <span class="tr">Element selector</span> ( <span class="tr">found</span> <a href="#" onclick="return false;" id="PathCount" class="text-info">0</a> ) 
                      <a id="wiki-selector" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=' + ((typeof(_K) == 'string' && _K == 'ru') ? 'ru:':'') + 'how_to_search_for_element');return false" href="#">
                        <img src="wiki.png" class="wiki-link tr" data-toggle="tooltip" data-placement="top" title="<%= tr("How to search for element") %>"/> 
                      </a>
                    </span>

                    <div class="input-group-btn">
                      <button tabindex="-1" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span id="selector"><%= selector["current"] %></span> <span class="caret"></span></button>
                      <ul class="dropdown-menu dropdown-menu-with-breaks dropdown-menu-right"">
                        <li><a tabindex="-1" id="css" style="cursor:pointer">
                          <strong>css</strong> - <span class="tr type-description">Find element with css selector. &gt;CSS&gt; .element-class - find by class</span>
                          <br/><span class="tr type-description">&gt;CSS&gt; #element-id - find by id, &gt;CSS&gt; [attribute*="value part"] - find element, with attribute, that contains "value part"</span>
                        </a></li>
                        <li><a tabindex="-1" id="match" style="cursor:pointer">
                            <strong>match</strong> - <span class="tr type-description">Find by markup part. &gt;MATCH&gt;title="Search" and &gt;MATCH&gt;&lt;div title</span>
                            <br/><span class="tr type-description">will find element with markup &lt;div title="Search"&gt;Text&lt;/div&gt;</span>
                        </a></li>
                        <li><a tabindex="-1" id="xpath" style="cursor:pointer">
                          <strong>xpath</strong> - <span class="tr type-description">Find by xpath. &gt;XPATH&gt; //*[@id='element-parent'] - find el by id</span>
                          <br/><span class="tr type-description">&gt;XPATH&gt; //*[contains(@attribute,'value part')] - find element, with attribute, that contains "value part"</span></a></li>
                        <li><a tabindex="-1" id="at" style="cursor:pointer">
                            <strong>at</strong> - <span class="tr type-description">Find by coordinates. Consider using actions which works with coordinates not at selector.</span>
                        </a></li>
                        <li><a tabindex="-1" id="none" style="cursor:pointer">
                          <strong>none</strong> - <span class="tr type-description">Find root element(body). This type of selector is useful if you make screenshot of whole page.</span>
                        </a></li>
                      </ul>
                    </div>

                </div>
                
                  
                

                
              <% } %>


            </div>
          </div>
        </form>
      </div>
    </div>

    <% if(typeof(is_multiple_elements) == "boolean" && is_multiple_elements){ %>
      <div id="selector-ai" data-generation="">
        <%= _.template($('#info').html())({description: 
          `
            <span class="tr">Selector for these elements was generated by ai. Elements description</span> - "<span id="selector-ai-name"></span>". 
            <span id="selector-ai-before-update">
              <span class="tr">Ai generated selectors are not always accurate, so you can tweak current selector manually by clicking on elements inside browser.</span>
              <span class="tr">Once you have verified that the selector is correct, click on following link</span> - 
                <a href="#" onclick="$('#selector-ai').hide();_SelectorModel.set('is_ai_generated', false);return false;" class="tr">keep current selector</a>.
              
            </span>
          `, color: "red"}) %>
      </div>
    <% } else { %>    
      <div id="selector-ai" data-generation="">
        <%= _.template($('#info').html())({description: 
          `
            <span class="tr">Selector for this element was generated by ai. Element description</span> - "<span id="selector-ai-name"></span>". 
            <span id="selector-ai-before-update">
              <span class="tr">Ai generated selectors are not always accurate, so you can</span>
                <a onclick="$('#selector-ai-before-update').hide();$('#selector-ai-after-update').show();BrowserAutomationStudio_UpdateSelector();return false;" href="#" class="tr">generate new selector manually</a>
                <span class="tr">or</span>
                <a href="#" onclick="$('#selector-ai').hide();_SelectorModel.set('is_ai_generated', false);return false;" class="tr">keep current selector</a>
              <span class="tr">if it fits you</span>.
            </span>
            <span id="selector-ai-after-update" class="tr">You can now select new element in browser window.</span>
          `, color: "red"}) %>
      </div>
    <% } %>  
    
      <% if(selector["is_image"]){ %>

          <%= _.template($('#block_start').html())({id: "SearchImageBlock", name: tr("Search image settings"), smaller_fonts: true, description: tr("")}) %>
            <%= _.template($('#input_constructor').html())({id:"Scroll", description:tr("Scroll to search for image"), default_selector: "string", disable_int:true, value_string: "scroll", variants: ["scroll", "no scroll"],  
              help: {description: tr("If page will be scrolled to find image. \"no scroll\" option can save time, but if element is located on page bottom, than it won't be found. If you are sure, that element is located inside viewport, use \"no scroll\", otherwise - \"scroll\"")}
            }) %>
            <%= _.template($('#input_constructor').html())({id:"Threshold", description:tr("How well the image must fit. 100 - exactly fits, 0 - does not fit at all."), default_selector: "int", disable_string:true, value_number:80, min_number:0, max_number:100, help: {description: tr("Finding image searches for best matching picture on a screen and checks matching quality. If this quality is good enough, searching will end with success, otherwise search will be performed again and again until desired quality will be achieved. This value sets quality threshold. 80 will do almost for every task, including deformated images. Use 0 if you want search image only once. Values close to 100 will find image exactly as sample.")}}) %>
            <%= _.template($('#input_constructor').html())({id:"ImageBase64", description:tr("Image data as base64"), default_selector: "string", disable_int:true, disable_editor:true, disable_string:true, use_textarea:true, size: 4, disable_type_chooser:true, textarea_height: 74, help: {description: tr("Image data in base64 format")} }) %>
          <%= _.template($('#block_end').html())() %>
        


      <% }else{ %>
        
        
      <% } %>    

  </script>

  <script type="text/template" id="tooltip-input">
    <div style='text-align:left;min-width:200px'>
      <strong><u><%= title %></u></strong>
      <% if(typeof(description) != "undefined"){ %>
        <div style='font-style: italic;font-size:small;margin-top:5px'><%= description %></div>
      <% } %>
      <% if(typeof(examples) != "undefined"){ %>
        <% for(let i = 0; i < examples.length; i++){%>
          <% let example = examples[i]; %>
          <% if(i == 0){ %>
            <div style='margin-top:5px;' class='tr'><strong><u><%= tr('Examples : ') %></u></strong></div>
          <% } %>
          <div style='font-size:small;' > <strong> <%= example["code"] %> </strong> 
            <% if(typeof(example["description"]) != "undefined"){ %>
              - <%= example["description"] %> 
            <% } %>
          </div>

        <% } %>
      <% } %>
    </div>
  </script>

  <script type="text/template" id="help_popup">
    <div class="help-popup-container" style="text-align: left">
      <h6 class="help-popup-header help-popup-header-first"><%= title %></h6>
      <% if (typeof(description) != "undefined") { %>
        <div class="help-popup-text"><%= description %></div>
      <% } %>
      <% if (typeof(examples) !== 'undefined' && examples.length) { %>
        <h6 class="help-popup-header help-popup-header-second"><%= tr('Examples: ') %></h6>
        <% examples.forEach((example) => { %>
          <div class="help-popup-example">
            <span class="help-popup-code"><%= example.code %></span> 
            <% if (typeof(example.description) !== 'undefined') { %>
              <span class="help-popup-text">- <%= example.description %></span>
            <% } %>
          </div>
        <% }) %>
      <% } %>
    </div>
  </script>

  <script type="text/template" id="input_constructor">
    <span 
     <% if(typeof(dont_preserve) != "boolean" || !dont_preserve){ %>
      data-preserve="true" 
     <% } %>
     data-preserve-type="constr" data-preserve-id="<%= id %>" 
        <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
        <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
      >
      <% if(typeof(dont_use_top) == "undefined"){ %>
        <div class="col-xs-12">
        <form class="form-horizontal">
          <div class="form-group">
          <% } %>
            <% if(typeof(dont_use_col) == "undefined"){ %>
            <div class="col-xs-12">
            <% } %>
              <% if(typeof(use_textarea) == "undefined"){ %>
               <div class="input-group" style="width:100%">
               

              <% } %>
                <<%= (typeof(use_textarea) == "undefined") ? "input type=\"text\"" : ("textarea style=\"resize: vertical;height:" + ((typeof(textarea_height) == "undefined") ? 146 : textarea_height ) + "px\"") %>  
                class="form-control input_selector_string" id="<%= id %>" <%= (default_selector == "int") ? "style=\"display:none\"" : "" %>
                placeholder="<%= je(description).replace(/\\n/g,"&#10;") %>" 
                <%= (typeof(replace_linebreaks) != "undefined") ? "data-replace-linebreaks='true' " : "" %>
                value="<%= (typeof(value_string) != "undefined") ? value_string : ((typeof(value_expression) != "undefined") ? eval(value_expression) : "") %>" <%= (typeof(use_textarea) == "undefined") ? "/>" : (">" + ((typeof(value_string) != "undefined") ? value_string : ((typeof(value_expression) != "undefined") ? eval(value_expression) : "")) + "\<\/textarea>") %>
                <input class="form-control input_selector_number" type="number" id="<%= id %>_number" <%= (default_selector != "int") ? "style=\"display:none\"" : "" %> placeholder="<%= je(description) %>" value="<%= (typeof(value_number) != "undefined") ? value_number : 1%>" <%= (typeof(value_number) != "undefined") ? "" : "data-no-default=\"true\""%>" step="<%= (typeof(step_number) != "undefined") ? step_number : 1%>" min="<%= (typeof(min_number) != "undefined") ? min_number : 0%>" max="<%= (typeof(max_number) != "undefined") ? max_number : 10000%>" />
                
                <% if(typeof(use_textarea) != "undefined" && (typeof(help) == "object" || typeof(modal_code_id) == "string")){ %>
                  <div style="position: relative;top: -25px;left: -10px;">
                    <div style="float: right; height: 0px;">
                      <% if(typeof(help) == "object"){ %>
                        <!--<i class="fa fa-question-circle help-input" data-toggle="tooltip" data-html="true" title="<%= _.escape(_.template($("#tooltip-input").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>-->
                        <i style="cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="textarea" data-html="true" title="<%= _.escape(_.template($("#help_popup").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>

                      <% } %>
                      <% if(typeof(modal_code_id) == "string"){ %>
                        <a onclick="bootbox.alert({message: $('#<%= modal_code_id %>').html(), size: 'large'});return false;" href="#"><i class="fa fa-question-circle help-input"></i>  </a>
                      <% } %>
                    </div>
                  </div>
                <% } %>

                <% if((typeof(variants) != "undefined" && variants != null) || typeof(disable_editor) == "undefined" || typeof(disable_resource) == "undefined" || typeof(disable_variable) == "undefined") { %>
                  <ul class="dropdown-menu dropdown-menu-with-breaks input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown" data-use-hotkeys="true">
                    <% if(typeof(variants) != "undefined") { %>
                      <% for(var i = 0;i<variants.length;i++) { %>
                        <% var variant = typeof(variants[i]) == "object" ? variants[i] : variants[i].toString() %>
                        <% var variant_value = typeof(variant) == "object" ? variant.value : variant.split('<br/>')[0] %>
                        <% var variant_type = (typeof(variant) == "object" ? variant.type : "") || "" %>
                        <% var variant_description = (typeof(variant) == "object" ? variant.description : variant.split('<br/>').slice(1).join('<br/>')) || "" %>
                        <li>
                          <a style="padding-top:5px;padding-bottom:5px;" tabindex="-1" href="#" data-toggle="modal"  data-variant="<%= variant_value %>" data-variant-type="<%= variant_type %>" data-result="<%= id %>" class="variant" >
                            <span><%= variant_value %><% if (variant_description!=="") { %><br/><% if (variant_description.indexOf("color:gray;font-size:small") < 0) { %><span style='color:gray;font-size:small'><% } %><%= variant_description %><% if (variant_description.indexOf("color:gray;font-size:small") < 0) { %></span><% } %><% } %></span>
                          </a>
                        </li>
                      <% } %>
                      <% if(typeof(disable_separator) == "undefined") { %>
                        
                      <% } %>
                    <% } %>

                    <% if(typeof(disable_editor) == "undefined") { %>
                      <li class="dropdown-border">
                        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#<%= id %>" class="edit" style="display: flex; align-items: center;  justify-content: start;">
                          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                            <path d="M15.989 3.388V.005h-3.382v1.23H7.38v6.457H3.382v-1.23H0v3.382h3.382v-1.23H7.38v6.15h5.227v1.23h3.382v-3.382h-3.382v1.23H8.302V8.615h4.305v1.23h3.382V6.463h-3.382v1.23H8.302V2.158h4.305v1.23h3.382zM2.46 8.922H.922V7.385H2.46v1.537z" fill="#fff" />
                          </svg>
                            <span class="tr" style="font-size:12px;margin-right:10px">Create value in visual constructor</span>
                            <span style="float:right;margin-left:auto;opacity: 0.5;">F6</span>
                        </a>
                      </li>
                    <% } %>
                    <% if(typeof(disable_resource) == "undefined") { %>
                      <li class="dropdown-border">
                        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#<%= id %>" class="res" style="display: flex; align-items: center;  justify-content: start;" >
                          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                            <path d="M1.5 1.5v13h13v-13h-13zm12 12h-11v-3h11v3zm0-4h-11v-3h11v3zm-1.5-6a.5.5 0 110 1 .5.5 0 010-1z" fill="#fff" />
                            <path d="M12 8.5a.5.5 0 100-1 .5.5 0 000 1zM12 12.5a.5.5 0 100-1 .5.5 0 000 1z" fill="#fff" />
                          </svg>
                            <span class="tr" style="font-size:12px;margin-right:10px">Load from file, user input, database</span>
                            <span style="float:right;margin-left:auto;opacity: 0.5;">F7</span>
                        </a>
                      </li>
                    <% } %>
                    <% if(typeof(disable_variable) == "undefined") { %>
                      <li class="dropdown-border">
                        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#<%= id %>" class="var" style="display: flex; align-items: center;  justify-content: start;" >
                          <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                            <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#fff" />
                            <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#fff" />
                          </svg>
                            <span class="tr" style="font-size:12px;margin-right:10px">Insert variable</span>
                            <span style="float:right;margin-left:auto;opacity: 0.5;">F8</span>
                        </a>
                      </li>
                    <% } %>
                  </ul>
                <% } %>

                <% if(typeof(use_textarea) == "undefined" && typeof(disable_label) == "undefined" && typeof(description) == "string" && description.length > 0){ %>
                  <span  tabindex="-1" class="input-group-addon input-description"><%= description %> 
                    <% if(typeof(help) == "object"){ %>
                      <!--<i class="fa fa-question-circle help-input" data-toggle="tooltip" data-html="true" title="<%= _.escape(_.template($("#tooltip-input").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>-->
                      <i style="cursor: pointer;" class="fa fa-question-circle help-input" data-toggle="popup" data-html="true" title="<%= _.escape(_.template($("#help_popup").html())({title:description,description:help["description"],examples:help["examples"]})) %>" ></i>
                    <% } %>
                     
                   </span>
                <% } %>

                
                
                <div 
                  class="input-group-btn dropdown-input-type" <%= (typeof(disable_type_chooser) != "undefined") ? "style=\"display:none\"" : "" %>>
                  <button  tabindex="-1" type="button" class="btn btn-default dropdown-toggle dropdown-input-type" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="selector" data-selector-id="<%= id %>"><%= default_selector %></span> <span class="caret"></span></button>
                  <ul class="dropdown-menu dropdown-menu-with-breaks dropdown-menu-right">
                    <% if(typeof(disable_string) == "undefined") { %>
                      <li><a class="string" class="tr" style="cursor: pointer;">
                        <strong>string</strong>
                        <span class="type-description">
                          <span class="tr">Field content will be treated as string. If you input test@gmail.com, result will be "test@gmail.com".</span>
                            <br/>
                          <span class="tr">Variables and resuorces will be replaced by values. If you input [[USERNAME]], result will be "my_username"</span>
                            <br/>
                          <span class="tr">[[USERNAME]]@gmail.com will give "my_username@gmail.com"</span>
                        </span>
                      </a></li>
                    <% } %>

                    <% if(typeof(disable_int) == "undefined") { %>
                      <li><a class="int" style="cursor: pointer;"><strong>int</strong>
                        <span class="tr type-description">Field content will be treated as number.</span></a></li>
                    <% } %>

                    <% if(typeof(disable_expression) == "undefined") { %>
                      <li><a class="expression" style="cursor: pointer;">
                        <strong>expression</strong>
                        <span class="type-description">
                            <span class="tr">Field content will be treated as javascript code. "test@gmail.com" will convert to "test@gmail.com".</span>
                             <br/> 
                            <span class="tr">Variables and resuorces will be replaced by values. If you input [[USERNAME]], result will be "my_username"</span>
                             <br/> 
                            <span class="tr">[[USERNAME]] + "@gmail.com" will give "my_username@gmail.com". 2 + 2 will give 4.</span>
                             <br/> 
                            <span class="tr">Javascript expressions can be complex. [[USERNAME]].split("_")[0] will give "my".</span>
                          </span></a></li>
                    <% } %>
                  </ul>
                </div>

              <% if(typeof(use_textarea) == "undefined"){ %>

                </div>
              <% } %>
            <% if(typeof(dont_use_col) == "undefined"){ %>
              </div>
            <% } %>

            <% if(typeof(dont_use_top) == "undefined"){ %>
            </div>

        </form>
      </div>
      <% } %>
    </span>

  </script>

  <script type="text/template" id="filter">
    <% if (typeof(hide) != "undefined" && hide) { %>
      <%= _.template($('#block_start').html())({
        id: "Filter" + id,
        name: name,
        description: (typeof(help) == "object" && help.description ? help.description : ""),
        visible_if_checked: typeof(visible_if_checked) == "string" ? visible_if_checked : undefined,
        visible_if_unchecked: typeof(visible_if_unchecked) == "string" ? visible_if_unchecked : undefined
      }) %>
    <% } %>
    <span data-preserve="true" data-preserve-type="filter" data-preserve-id="<%= id %>" 
        <%= ((typeof(hide) == "undefined" || !hide) && typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
        <%= ((typeof(hide) == "undefined" || !hide) && typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
      >
      <% if (typeof(hide) == "undefined" || !hide) { %>
        <div class="filter-header">
          <div class="filter-title">
            <div class="col-xs-12">
              <span> <%= name %></span> 
              <% if(typeof(help) == "object" && help){ %>
                <i style="margin-left:5px;cursor: pointer" class="fa fa-question-circle help-input" data-toggle="popup" data-additional-type="select" data-html="true" title="<%= _.escape(_.template($('#help_popup').html())({title:(help.title || name),description:help.description,examples:help.examples})) %>"></i>
              <% } %>
            </div>
          </div>
      <% } %>
          <div class="<%= (typeof(hide) == 'undefined' || !hide ? 'filter-controls' : 'filter-controls-hide') %>">
            <button type="button" class="btn btn-default btn-sm" onclick="_Filters.openConstructor('<%= id %>')">
              <i class="fa fa-filter" aria-hidden="true"></i> <span class="tr">Add filter</span>
            </button>
            <button type="button" class="btn btn-default btn-sm" onclick="_Filters.askClear('<%= id %>')">
              <i class="fa fa-eraser" aria-hidden="true"></i> <span class="tr">Remove all filters</span>
            </button>
          </div>
      <% if (typeof(hide) == "undefined" || !hide) { %>
        </div>
      <% } %>

      <div class="container-fluid">
        <div class="col-xs-12">
          <div class="filter-list" id="<%= id %>"></div>
        </div>
      </div>

      <ul class="dropdown-menu input-field-dropdown dropdown-black filter-contextmenu" id="filter-contextmenu-<%= id %>" style="display:none; position:absolute;">
        <li>
          <a href="#" class="filter-edit">
            <span class="tr">Edit</span>
          </a>
        </li>
        <li>
          <a href="#" class="filter-remove">
            <span class="tr">Remove</span>
          </a>
        </li>
      </ul>

      <% if(typeof(or_select) != "undefined" && or_select){ %>
        <span id="filter-logic-<%= id %>" style="display:none">
          <%= _.template($('#combobox').html())({
            id: "filter-logic-select-" + id,
            title: tr("Filter matching logic"),
            items: [
              { value: "and", selected: true, name: tr("Match all"), title: tr("All specified filters must be met (logical \"AND\")") },
              { value: "or", name: tr("Match any"), title: tr("It is sufficient for at least one of the specified filters to be met (logical \"OR\")")  }
            ],
            help: {
              description: tr("Determines how filters are applied to the data. Depending on the selected logic, the data must either match all filters simultaneously or at least one of them."),
              examples: [
                { code: tr("Match all"), description: tr("All specified filters must be met (logical \"AND\")") },
                { code: tr("Match any"), description: tr("It is sufficient for at least one of the specified filters to be met (logical \"OR\")") }
              ]
            }
          }) %>
        </span>
      <% } %>

      <div class="modal filter-modal" tabindex="-1" id="filter-modal-<%= id %>" role="dialog">
        <div class="modal-dialog modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-body">
              <button type="button" class="bootbox-close-button close" data-dismiss="modal" aria-hidden="true" style="margin-top: -10px;">×</button>
              <div class="container-fluid">
                <% if(scheme.match_select){ %>
                  <%= _.template($('#combobox_stretch').html())({
                    id: "filter-mode-" + id,
                    title: tr("Filter type"),
                    items: [
                      { value: "inclusive", selected: true, name: tr("Inclusive"), title: tr("Passes only the data that meets the specified filter conditions. Any data that does not match the conditions will be excluded.") },
                      { value: "exclusive", name: tr("Exclusive"), title: tr("Passes data that does not meet the specified filter conditions, and excludes any data that matches those conditions.") }
                    ],
                    dont_preserve: true,
                    help: {
                      description: tr("Defines the filter's behavior, determining which data will be included or excluded based on the specified conditions."),
                      examples: [
                        { code: tr("Inclusive"), description: tr("Passes only the data that meets the specified filter conditions. Any data that does not match the conditions will be excluded.") },
                        { code: tr("Exclusive"), description: tr("Passes data that does not meet the specified filter conditions, and excludes any data that matches those conditions.") }
                      ]
                    }
                  }) %>
                <% } %>
                <% if(scheme.fields && Array.isArray(scheme.fields) && scheme.fields.length){ %>
                  <%= _.template($('#combobox_stretch').html())({
                    id: "filter-field-" + id,
                    title: tr("Filter field"),
                    items: _Filters.prepareFields(scheme.fields),
                    dont_preserve: true,
                    onchange: `_Filters.onFieldChange('${id}')`,
                    help: {
                      description: tr("Determines the field containing the data that will be filtered."),
                      examples: _Filters.prepareFieldExamples(scheme.fields)
                    }
                  }) %>
                <% } %>
                <%= _.template($('#combobox_stretch').html())({
                  id: "filter-type-" + id,
                  title: tr("Filtering method"),
                  items: _Filters.prepareTypes(scheme.types || (scheme.types = _Filters.getAvailableTypes(scheme.fields))),
                  dont_preserve: true,
                  onchange: `_Filters.onTypeChange('${id}')`,
                  help: {
                    description: tr("Determines the method by which the filter will check the data for matching.") + (scheme.fields && Array.isArray(scheme.fields) && scheme.fields.length ? " " + tr("Available methods depend on the type of data in the selected field.") : ""),
                    examples: _Filters.prepareTypeExamples(scheme.types)
                  }
                }) %>
                <div id="filter-value-box-<%= id %>">
                  <%= _.template($('#input_constructor').html())({
                    id: "filter-value-" + id,
                    description: tr("Value"),
                    default_selector: "string",
                    min_number: Number.MIN_SAFE_INTEGER,
                    max_number: Number.MAX_SAFE_INTEGER,
                    dont_preserve: true,
                    help: {
                      description: tr("The value used to compare against the data. This value depends on the selected filtering method and will determine whether the data matches the filter criteria.")
                    }
                  }) %>
                </div>
              </div>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-danger standartbutton tr" id="filter-remove-<%= id %>" onclick="" style="display:none;">Remove filter</button>
              <button type="button" class="btn btn-primary standartbutton tr" id="filter-accept-<%= id %>" onclick="_Filters.create('<%= id %>')">Add filter</button>
              <button type="button" class="btn btn-default standartbutton tr" data-dismiss="modal">Cancel</button>
            </div>
          </div>
        </div>
      </div>
    </span>

    <% if (typeof(hide) != "undefined" && hide) { %>
      <%= _.template($('#block_end').html())() %>
    <% } %>

  </script>

  <script type="text/template" id="line">
    <div class="col-xs-12" 
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <form class="form-horizontal">
        <div class="form-group">
          <div class="col-xs-12">
            <div style="margin-top: 5px;margin-bottom: 5px;background-color: #555;height: 5px;margin-left: 1px;margin-right: 2px;border-radius: 1px;">&nbsp;</div>
          </div>
         </div>
       </form>
     </div>
  </script>

  <script type="text/template" id="space">
    <span 
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div style="height:0px;clear: both;margin-bottom:-4px">&nbsp;</div>

      <div style="height:10px" >
        
      </div>
    </span>
  </script>

  <script type="text/template" id="header">
    <span 
      <%= (typeof(visible_if_checked) == "string") ? "data-visible-if-checked='" + visible_if_checked + "' " : "" %>
      <%= (typeof(visible_if_unchecked) == "string") ? "data-visible-if-unchecked='" + visible_if_unchecked + "' " : "" %>
    >
      <div style="height:0px;clear: both;margin-bottom:-4px">&nbsp;</div>

      <div class="header-container">
        
        <div class="header-item"> <%= name %></div>
      </div>
    </span>

  </script>



  <script type="text/template" id="special_buttons">
    <div style="margin-left:15px">
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="CONTROL">Ctrl</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="MENU">Alt</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="SHIFT">Shift</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="BACK">Backspace</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="TAB">Tab</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="RETURN">Enter</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="ESCAPE">Escape</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="PRIOR">Page up</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="NEXT">Page down</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="END">End</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="HOME">Home</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="LEFT">Left</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="UP">Up</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="RIGHT">Right</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="DOWN">Down</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="INSERT">Insert</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="DELETE">Delete</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="MOUSESCROLLUP">Mouse wheel up</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="MOUSESCROLLDOWN">Mouse wheel down</button>
        <!--<button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="CANCEL">Cancel</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="CLEAR">Clear</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="CAPITAL">Caps Lock</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="SELECT">Select</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="PRINT">Print</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="EXECUTE">Execute</button>
        <button tabindex="-1" type="button" class="btn btn-default specialletter btn-xs" data-key="SNAPSHOT">Print screen</button>-->
    </div>
  </script>


  <script type="text/template" id="load">
    <div class="container-fluid load">
      <%= _.template($('#input_constructor').html())({id:"LoadUrl", description:tr("Url to load"), default_selector: "string", disable_int:true, help: {description: tr("Url to load. Protocol may be omitted."), examples:[{code:"google.com",description:tr("Load google.com")},{code:"instagram.com",description:tr("Load instagram.com")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"Referrer", description:tr("Referrer. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("Referrer used for current page load."), examples:[{code:"https://google.com",description:tr("Page is loaded by clicking on google search result.")},{code:tr("Empty string"),description:tr("Page is loaded by typing url in address bar.")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Loads specified url into browser. Examples: Load google.com, Load instagram.com.</div>
      <div class="tr tooltip-paragraph-last-fold">If you encounter errors during execution of this action, try to remove wait for full page load checkbox or wrap load action in ignore error block.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,waiter_enabled: true,use_timeout: true, visible:true, wiki: "how_to_load_url"}) %>
  </script>

  <script type="text/template" id="navigateback">
    
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Loads previous url from a history list.</div>
      <div class="tr tooltip-paragraph-fold">This is the same as clicking the "Back button" in the browser.</div>
      <div class="tr tooltip-paragraph-last-fold">If current page is first, this action will load empty page.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,waiter_enabled: true,use_timeout: true, visible:true}) %>
  </script>


  <script type="text/template" id="break">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Interrupt current loop immediately. This action works only if placed inside loop(foreach, for, while actions).</div>
      <div class="tr tooltip-paragraph-fold">After launch this action stops loop immediately, no more iterations are performance, and script execution point is moved to the next action after loop.</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">Common practice is to put break inside if action and therefore stop loop only under certain condition</span> (<a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=fortypical.png');return false" class="tr">screen</a>)</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

   <script type="text/template" id="continue">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Immediately finish current loop iteration and start next one. This action works only if placed inside loop(foreach, for, while actions).</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">Common practice is to put continue action inside if action and therefore stop current iteration only under certain condition</span> (<a href="#" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=continue.png');return false" class="tr">screen</a>)</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

  <script type="text/template" id="success">
    <div class="container-fluid success">
      <%= _.template($('#input_constructor').html())({id:"SuccessMessage", description:tr("Success Message"), default_selector: "string", disable_int:true, help: {description: tr("Thread final success message. This will be outputted to log and to script report.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Finish thread with success result.</div>
      <div class="tr tooltip-paragraph-fold">Every thread started by BAS has a result status, which may be success or fail.</div>
      <div class="tr tooltip-paragraph-fold">In case if all actions executed correctly, BAS sets success result for that thread.</div>
      <div class="tr tooltip-paragraph-fold">It is important to understand this action stops only current thread not full script.</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">You can set result status to success and finished thread beforehand with this action</span> (<a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=success.png');return false" class="tr">screen</a>)</div>
    </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:false, wiki:"how_to_end_script"}) %>
  </script>

  <script type="text/template" id="fail">
    <div class="container-fluid fail">
     <%= _.template($('#input_constructor').html())({id:"FailMessage", description:tr("Fail Message"), default_selector: "string", disable_int:true, help: {description: tr("Thread final fail message. This will be outputted to log and to script report.")}}) %>
     <%= _.template($('#checkbox').html())({id: "Check", title: tr("Dont restart thread.")}) %>
    </div>

     

      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Finish thread with fail result.</div>
        <div class="tr tooltip-paragraph-fold">Every thread started by BAS has a result status, which may be success or fail.</div>
        <div class="tr tooltip-paragraph-fold">In case if some action fails thread execution will be interrupted and thread status will be set to failure.</div>
        <div class="tooltip-paragraph-fold"><span class="tr">You may also interrupt thread and set fail message with this action</span> (<a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=fail.png');return false" class="tr">screen</a>)</div>
        <div class="tr tooltip-paragraph-last-fold">It is important to understand this action stops only current thread not full script.</div>
      </div>
     <%= _.template($('#back').html())({action:"executeandadd", visible:false, wiki:"how_to_end_script"}) %>

  </script>

  <script type="text/template" id="die">
    <div class="container-fluid fail">
     <%= _.template($('#input_constructor').html())({id:"FailMessage", description:tr("Fail Message"), default_selector: "string", disable_int:true, help: {description: tr("Thread final fail message. This will be outputted to log and to script report.")}}) %>

     <%= _.template($('#checkbox').html())({id: "Check", title: tr("Finish script instantly.")}) %>

    </div>
     
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">This action finishes whole script, not just single thread, use it in case of fatal error and if script can't be continued under no circumstances. For example, if API key to some service doesn't match.</div>
        <div class="tr tooltip-paragraph-fold">BAS also uses this action internally in case of resource absence, so if, for example, user didn't set any proxy file, script will finish instantly.</div>
        <div class="tr tooltip-paragraph-last-fold">There are two modes, how this action works. First mode is instant finish, this means that script will finish at the same second as you called that action, each thread will also stop instantly even if it was in the middle of some task. Second mode is graceful finish, in this case BAS will wait until all threads will finish their tasks. Second mode is useful in case if you don't want to lose important data, for example, phone numbers or emails.</div>
        <span class="short-description tr">This action finishes whole script, not just single thread, use it in case of fatal error and if script can't be continued under no circumstances.</span>
      </div>
     <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>

  </script>

  <script type="text/template" id="label">
    <div class="container-fluid fail">
     <%= _.template($('#input_constructor').html())({id:"Label", description:tr("Label"), default_selector: "string", disable_int:true, disable_expression:true, disable_resource: true, disable_editor: true, disable_variable:true}) %>
    </div>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Set label so execution point may be transfered to that label later.</div>
        <div class="tr tooltip-paragraph-fold">Labels helps to transfer execution point between two arbitrary places inside script.</div>
        <div class="tooltip-paragraph-fold"><span class="tr">To use labels you need first to "set label"(this action) inside place where you want to move later, then you need to use "move to label" action from anywhere in the script</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=skipwithlabel.png');return false">screen</a>)</div>
        <div class="tr tooltip-paragraph-fold">With labels you can jump inside loops, conditions, functions. If you jump inside loop, then [[CYCLE_INDEX]] variable might not be correct, and after loop body will be executed, execution point will be moved outside of the loop.</div>
        <div class="tr tooltip-paragraph-fold">One of typical use example for labels maybe setting label at the thread start and returning to it on some condition.</div>
        <div class="tr tooltip-paragraph-last-fold">It is not recommended to use labels very often, if you overdo with using labels your script may become unreadable and hard to modify. It is better to use functions instead, unless you absolutely need labels.</div>
      </div>
     <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>

  </script>

  <script type="text/template" id="goto">
    
    <div class="container-fluid executefunction" style="padding-bottom:5px;display:none">
      <div class="col-xs-12">
        <form class="form-horizontal" onsubmit="return false;">
          <div class="input-group">
            <span data-preserve="true" data-preserve-type="text" data-preserve-id="LabelName">
              <input class="form-control label-input" type="text" id="LabelName" placeholder="Label">
            </span>
  
            <span class="input-group-addon input-description">
              <span class="tr">Label</span> 
            </span>
            <div class="input-group-btn">
              <button tabindex="-1" type="button" class="btn btn-default lab" data-toggle="modal" data-target="#LabelModal" data-result-target="#LabelName" ><i class="fa fa-tag"></i></button>
            </div>
          </div>
        </form>
      </div>

      
    </div>

    <div class="container-fluid" id="LabelListInfo">

    </div>

    <div id="LabelList">

    </div>


    
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Move execution point to label previously set with "Set label" action.</div>
      <div class="tr tooltip-paragraph-fold">Labels helps to transfer execution point between two arbitrary places inside script.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">To use labels you need first to "set label" inside place where you want to move later, then you need to use "move to label"(this action) from anywhere in the script</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=skipwithlabel.png');return false">screen</a>)</div>
      <div class="tr tooltip-paragraph-fold">With labels you can jump inside loops, conditions, functions. If you jump inside loop, then [[CYCLE_INDEX]] variable might not be correct, and after loop body will be executed, execution point will be moved outside of the loop.</div>
      <div class="tr tooltip-paragraph-fold">One of typical use example for labels maybe setting label at the thread start and returning to it on some condition.</div>
      <div class="tr tooltip-paragraph-last-fold">It is not recommended to use labels very often, if you overdo with using labels your script may become unreadable and hard to modify. It is better to use functions instead, unless you absolutely need labels.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>

  </script>

  <script type="text/template" id="custom">
    <div class="container-fluid">
      <span data-preserve="true" data-preserve-type="constr" data-preserve-id="Code">
        <div id="Code" class="custom-code-editor" data-is-code-editor="true" />
      </span>
      <%= "<s" + "cript>" %>
        window.Code = {Editor: null, InitialValue: ""}

        require(['vs/editor/editor.main'], function() {
          window.Code.Editor = createCodeEditor(document.getElementById('Code'), {
            value: window.Code.InitialValue
          });
        });
      <%= "</" + "script>" %>
      <div style="text-align:center;align-items: center; display: flex !important; justify-content: center;">
          <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#Code" class="var" style="margin-right:15px">
            <span style="align-items: center; display: flex !important; justify-content: center;margin-top:5px">
              <svg class="dropdown-icon" width="16" height="16"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"  style="margin-right:10px">
                <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#337ab7" />
                <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#337ab7" />
              </svg>
              <span class="tr">Insert variable</span>
            </span>
          </a>
          <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#Code" class="res">
            <span style="align-items: center; display: flex !important; justify-content: center;margin-top:5px">
              <svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right:10px">
                <path d="M1.5 1.5v13h13v-13h-13zm12 12h-11v-3h11v3zm0-4h-11v-3h11v3zm-1.5-6a.5.5 0 110 1 .5.5 0 010-1z" fill="#337ab7" />
                <path d="M12 8.5a.5.5 0 100-1 .5.5 0 000 1zM12 12.5a.5.5 0 100-1 .5.5 0 000 1z" fill="#337ab7" />
              </svg>
              <span class="tr">Load from file, user input, database</span>
            </span>
          </a>
      </div>
      <span class="short-description tr">Execute javascript code. This code can work with variables but can't work with elements in web browser.</span>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, modal_code_id:"custom-help-" + (_K || "en")}) %>
  </script>

  <script type="text/template" id="custom-help-browser-common-ru">
    <div>Выполнить javascript внутри браузера. Это означает, что доступны document, window и другие javascript объекты браузера.</div>
    <div>Действие работает точно так же, как если бы вы вводили код в консоль браузера.</div>
    <div>Вы можете использовать переменные BAS в данном действии как для чтения, так и для записи. Кроме того они могут быть любого типа, в том числе объектами и массивами.</div>
    <div>Переменные используемые в коде автоматически обновляются после выполнения действия.</div>
    <div>Ресурсы не доступны для использования в данном действии.</div>
    <br />
    <div>Во время выполнения скрипта могут возникать разные ошибки. В случае ошибки BAS прекратит выполнение скрипта.</div>
    <div>Для того чтобы обработать подобные ситуации используйте действие <b>Игнорировать ошибки</b>.</div>
    <div>В таком случае вы сможете использовать переменные [[WAS_ERROR]] и [[LAST_ERROR]], чтобы узнать, была ли ошибка, и обработать её.</div>
    <br />
    <div>Пример #1. Изменение HTML определенного элемента:</div>
    <div><pre>document.getElementById("id").innerHTML = [[ELEMENT_HTML]];</pre></div>
    <br />
    <div>Пример #2. Получение HTML определенных элементов:</div>
    <div>
      <pre style="white-space: pre-line">
        [[ELEMENT1_HTML]] = document.getElementById("id1").innerHTML;
        [[ELEMENT2_HTML]] = document.getElementById("id2").innerHTML;        
      </pre>
    </div>
    <br />
    <div>Пример #3. Установка значений для элементов `input` и `textarea`:</div>
    <div>
      <pre style="white-space: pre-line">
        document.querySelector('textarea').value = [[TEXTAREA_VALUE]].join('\r\n');
        document.querySelector('input').value = [[INPUT_VALUE]];
      </pre>
    </div>
    <br />
    <div>В данном действии вы можете писать код с использованием <i>async</i> и <i>await</i>. Действие будет ожидать завершения асинхронных операций.</div>
    <div>При использовании асинхронного кода всегда дожидайтесь завершения функций с помощью <i>await</i>.</div>
    <div>В противном случае переменные, значение которых задается в коллбэках либо в функциях then/catch/finally у класса <i>Promise</i>, не будут синхронизированы с BAS.</div>
    <div>Если в таких участках кода вам не нужно обновлять переменные, вы можете не ждать их завершения.</div>
    <br />
    <div>Простой пример. Асинхронное ожидание в течение заданного времени (2 секунды):</div>
    <div>
      <pre>await new Promise((resolve) => { setTimeout(() => resolve(), 2000); });</pre>
    </div>
    <br />
    <div>Другой пример. Получение данных со стороннего сайта с помощью функции <i>fetch</i>:</div>
    <div><pre>async function getPost(id) {
  return await fetch(`https://jsonplaceholder.typicode.com/posts/` + id)
    .then((res) => res.json());
}
[[POST]] = await getPost(1);</pre></div>
  </script>

  <script type="text/template" id="custom-help-browser-common-en">
    <div>Execute javascript inside browser. This means that document, window and other browser javascript objects are available.</div>
    <div>Action works exactly the same as if you input code into browser console.</div>
    <div>You can use BAS variables in this action for both reading and writing. Moreover, they can be of any type, including objects and arrays.</div>
    <div>Variables used in the code are automatically updated after the action is performed.</div>
    <div>Resources are not available for use in this action.</div>
    <br />
    <div>During the execution of the script, various errors may occur. If an error occurs, BAS will stop the script execution.</div>
    <div>To handle such situations, use the <b>Ignore errors</b> action.</div>
    <div>In this case, you can use the [[WAS_ERROR]] and [[LAST_ERROR]] variables to find out if there was an error and process it.</div>
    <br />
    <div>Example #1. Changing the HTML of the specific element:</div>
    <div><pre>document.getElementById("id").innerHTML = [[ELEMENT_HTML]];</pre></div>
    <br />
    <div>Example #2. Getting the HTML of the specific elements:</div>
    <div>
      <pre style="white-space: pre-line">
        [[ELEMENT1_HTML]] = document.getElementById("id1").innerHTML;
        [[ELEMENT2_HTML]] = document.getElementById("id2").innerHTML;        
      </pre>
    </div>
    <br />
    <div>Example #3. Setting the values for the `input` and `textarea` elements:</div>
    <div>
      <pre style="white-space: pre-line">
        document.querySelector('textarea').value = [[TEXTAREA_VALUE]].join('\r\n');
        document.querySelector('input').value = [[INPUT_VALUE]];
      </pre>
    </div>
    <br />
    <div>In this action you can write code using <i>async</i> and <i>await</i>. The action will wait for asynchronous operations to complete.</div>
    <div>When using asynchronous code, always wait for functions to complete using <i>await</i>.</div>
    <div>Otherwise, variables whose value is set in callbacks or in the then/catch/finally functions of the <i>Promise</i> class will not be synchronized with the BAS.</div>
    <div>If you don't need to update variables in these sections of code, you don't have to wait for them to complete.</div>
    <br />
    <div>A simple example. Wait asynchronously for a specified time (2 seconds):</div>
    <div>
      <pre>await new Promise((resolve) => { setTimeout(() => resolve(), 2000); });</pre>
    </div>
    <br />
    <div>Another example. Getting data from a third-party site using the <i>fetch</i> function:</div>
    <div><pre>async function getPost(id) {
  return await fetch(`https://jsonplaceholder.typicode.com/posts/` + id)
    .then((res) => res.json());
}
[[POST]] = await getPost(1);</pre></div>
  </script>

  <script type="text/template" id="custom-help-browser-ru">
    <%= _.template($('#custom-help-browser-common-ru').html())({}) %>
    <br />
    <div>Используйте действие <b>Выполнить код</b>, если вы хотите выполнить javascript внутри потока.</div>
  </script>

  <script type="text/template" id="custom-help-browser-en">
    <%= _.template($('#custom-help-browser-common-en').html())({}) %>
    <br />
    <div>Use <b>Execute Code</b> action if you want to run javascript inside thread.</div>
  </script>

  <script type="text/template" id="custom-help-browserscriptelement-ru">
    <%= _.template($('#custom-help-browser-common-ru').html())({}) %>
    <br />
    Используйте переменную <strong>self</strong>, которая указывает на выбранный элемент.
    <br />
    <br />
    <div>Получить код элемента, который был выбран при создании этого действия:</div>
    <div>
      <pre style="white-space: pre-line">
        [[FOUND_ELEMENT_HTML]] = self.innerHTML;
      </pre>
    </div>
    <br />
    <div>Получить атрибут, имя которого находится в переменной [[ATTRIBUTE]], и сохранить его в переменную [[RESULT]].</div>
    <div>
      <pre style="white-space: pre-line">
        [[RESULT]] = self.getAttribute([[ATTRIBUTE]])
      </pre>
    </div>
    <br />
    <div>
      Если элемент не будет найден после первой попытки, BAS продолжит ожидать его на протяжении минуты. Если на протяжении 10 секунд элемент не будет найден, в лог будет добавлено сообщение, если элемент не появится на протяжении минуты, поток завершится с ошибкой. Вы можете обработать эту ошибку если уберете настройку "Остановить поток, если элемент не найден" (вверху страницы) или если обернете данное действие в блок игнорирования ошибок. Вы также можете настроить максимальное время ожидания если нажмете на иконку песочных часов.
    </div>
    <br />
    <div>Используйте действие <b>Выполнить код</b>, если вы хотите выполнить javascript внутри потока.</div>
  </script>

  <script type="text/template" id="custom-help-browserscriptelement-en">
    <%= _.template($('#custom-help-browser-common-en').html())({}) %>
    <br />
    Use <strong>self</strong> variable, which points to selected element.
    <br />
    <br />
    <div>Get code of element that was selected when creating this action:</div>
    <div>
      <pre style="white-space: pre-line">
        [[FOUND_ELEMENT_HTML]] = self.innerHTML;
      </pre>
    </div>
    <br />
    <div>Get attribute which name is located in [[ATTRIBUTE]] variable and save it to [[RESULT]] variable.</div>
    <div>
      <pre style="white-space: pre-line">
        [[RESULT]] = self.getAttribute([[ATTRIBUTE]])
      </pre>
    </div>
    <br />
    <div>
      If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.
    </div>
    <br />
    <div>Use <b>Execute Code</b> action if you want to run javascript inside thread.</div>
  </script>

  <script type="text/template" id="custom-help-interface-ru">
    <div>Выполнить javascript код в контексте веб интерфейса.</div>
    <div>Если веб интерфейс не включен, это действие не делает ничего.</div>
    <div>Веб интерфейс можно включить через <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://bablosoft.com/bas/interface');return false">кабинет</a> премиум аккаунта.</div>
    <div>Если вы хотите запустить код в контексте BAS, используйте действие "Выполнить код".</div>
    <div>BAS также предоставляет выполнять код с помощью node.js. для этого нужно использовать модуль "Встроенные языки".</div>
    <div>Здесь вы можете поместить любой javascript код, включая код, который использует внешние библиотеки.</div>
    <div>Есть возможность использовать переменные и ресурсы.</div>
    <br/>
    <div>Пример #1. Показать оповещение.</div>
    <div><pre>alert("Message")</pre></div>
      <br/>
    <div>Пример #2. Вывод переменной БАС в консоль браузера.</div>
    <pre>console.log([[TEST_VARIABLE]])</pre>
      <br/>
    <div>BAS использует <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://getuikit.com/docs/introduction');return false">uikit</a> для рендеринга контролов, и вы также можете использовать эту библиотеку.</div>
    <br/>
    <div>Пример #3. Показать уведомление через uikit.</div>
    <pre>UIkit.notification('My message');</pre>
      <br/>

    <div>Библиотека Jquery тоже поддерживается.</div>
    <br/>
    <div>Пример #4. изменить значение текстового поля.</div>
    <pre>$("#control-id").val("Input value");</pre>
      <br/>
  </script>

  <script type="text/template" id="custom-help-interface-en">
    <div>Run javascript code in web interface context.</div>
    <div>If web interface is not enabled, this action does nothing.</div>
    <div>Web interface can be enabled through you premium account <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://bablosoft.com/bas/interface');return false">cabinet</a>. </div>
    <div>If you want to run code in BAS context, use "Execute" action.</div>
    <div>BAS also gives possibility to run custom code with node.js. See "Embedded Language" module.</div>
    <div>You can put any javascript code here, including code, which uses external libraries.</div>
    <div>Variable and resources are also allowed.</div>
    <br/>
    <div>Example #1. Show alert message.</div>
    <div><pre>alert("Message")</pre></div>
      <br/>
    <div>Example #2. Output BAS variable to console.</div>
    <pre>console.log([[TEST_VARIABLE]])</pre>
      <br/>
    <div>BAS uses <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://getuikit.com/docs/introduction');return false">uikit</a> for rendering controls, you are free to use it.</div>
    <br/>
    <div>Example #3. Show notification.</div>
    <pre>UIkit.notification('My message');</pre>
      <br/>

    <div>Jquery is also available.</div>
    <br/>
    <div>Example #4. Set input value.</div>
    <pre>$("#control-id").val("Input value");</pre>
      <br/>
  </script>

  <script type="text/template" id="custom-help-en">
    <span style="font-size:small">
      Execute custom javascript code.<br/>
      If you want to run code with node.js, use "Embedded Language" module.<br/>
      This code may contain BAS variables and resources and BAS api calls.<br/>
      Browser context(document, window, navigator) is unavailable in this action. If you want to execute javascript in browser context, use "Javascript" action.<br/>
      You can find code online and paste it here. But setTimeout and setInterval can't be used, if you want to parallelize execution use "Call function in several threads".<br/>
      Example #1. Output text to log.
      <pre>log("Message")</pre>
      <br/>
Example #2. Execute code and save result to variable.
<pre>[[RESULT]] = 2 + 2</pre>
      <br/>
      Example #3. Check if page source has error message.
      <pre>[[HAS_ERROR_MESSAGE]] = [[SAVED_PAGE_HTML]].indexOf("Ip banned")</pre>
      
      BAS api calls may be used. Api list defined <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://raw.githubusercontent.com/bablosoft/BAS/master/Engine/text/apilist.txt');return false">here</a>
      <br/>
      <br/>
      Example #4. Get page source, check it, finish thread with ip banned.
      <br/>
      <pre>page().script("document.documentElement.outerHTML")!
[[SAVED_PAGE_HTML]] = _result()
if([[SAVED_PAGE_HTML]].indexOf("Ip banned"))
{
  fail("Proxy banned")
}</pre>
      <br/>
      If api call ends with exclamation mark it is considered asynchronous, and can't be used inside conditions, loops and functions. Standart conditions, loops and functions must be replaced with custom: _if, _do, _call. You can study api syntax if you look at source code generated by BAS in script tab (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=getpagesource.png');return false">screen</a>)
    </span>
  </script>

  <script type="text/template" id="custom-help-ru">
    <span style="font-size:small">
      Выполняет заданный javascript код.<br/>
      Если вы хотите запустить код на node.js, то нужно использовать модуль "Встроенные языки".<br/>
      Этот код может содержать переменные и ресурсы и вызовы BAS api.<br/>
      Контекст браузера и переменные document, window, navigator недоступны в этом действии. Если вы хотите выполнять код в контексте браузера, используйте действие "Яваскрипт".<br/>
      Вы можете искать код онлайн и использовать в этом действии. Функции setTimeout и setInterval нельзя использовать здесь, если вы хотите распараллелить выполнение действий, то нужно использовать действие "Вызов функции в несколько потоков".<br/>
      Пример #1. Вывести собщение в лог.
      <pre>log("Сообщение")</pre>
      <br/>
Пример #2. Выполнить код и сохранить результат в перемнную.
<pre>[[RESULT]] = 2 + 2</pre>
      <br/>
      Пример #3. Проверить, содержит ли страница сообщение об ошибке.
      <pre>[[HAS_ERROR_MESSAGE]] = [[SAVED_PAGE_HTML]].indexOf("Ip banned")</pre>
      
      BAS имеет собственный api, который может быть использован в этом действии. Список апи вызовов определен <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://raw.githubusercontent.com/bablosoft/BAS/master/Engine/text/apilist.txt');return false">здесь</a>
      <br/>
      <br/>
      Пример #4. Получить код страницы, проверить есть ли там сообщение об ошибке и остановить поток в этом случае.
      <br/>
      <pre>page().script("document.documentElement.outerHTML")!
[[SAVED_PAGE_HTML]] = _result()
if([[SAVED_PAGE_HTML]].indexOf("Ip banned"))
{
  fail("Proxy banned")
}</pre>
      <br/>
      Если вызов api заканчивается на восклицательный знак, то этот вызов считается асинхронным и не может быть использован внутри условий, циклов и функций. Стандартные условия, циклы и функции нужно заменить на специальные: _if, _do, _call. Вы можете изучить синтаксис api, если вы посмотрите исходный код, сгенерированный BAS на вкладке "Скрипт" (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=getpagesource.png');return false">скрин</a>)
    </span>
  </script>

   <!-- Tools templates -->

  <script type="text/template" id="randomint">
    <div class="container-fluid randomint">
      <%= _.template($('#input_constructor').html())({id:"MinValue", description:tr("Minimum Value"), default_selector: "int", disable_string:true, value_number:0, min_number:-999999, max_number:999999}) %>
      <%= _.template($('#input_constructor').html())({id:"MaxValue", description:tr("Maximum Value"), default_selector: "int", disable_string:true, value_number:100, min_number:-999999, max_number:999999}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save Result"), default_variable: "RANDOM_NUMBER"}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Generate a random integer in a given range.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <!-- Waiters templates -->

  <script type="text/template" id="waitfullload">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait until page is fully loaded.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="waitload">
    <div class="container-fluid load">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to specify conditions for selecting the URL that should be awaited for complete loading. They enable you to precisely indicate which URL's load should be awaited. If no filters are set, the action will wait for any URL to be loaded.")}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Wait", description:tr("Url"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait until the browser loads a URL matching the specified filters.</div>
      <div class="tr tooltip-paragraph-fold">This action waits until a URL matching the specified filters is fully loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action waits only for the main URL to load. If the page at this URL contains dynamically loaded resources (such as CSS, JavaScript, or other files), the action will not wait for their loading.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the action will wait until at least one URL is loaded.</div>
      <div class="tr tooltip-paragraph-fold">If the corresponding URL was loaded before this action started, the action will complete immediately.</div>
      <div class="tr tooltip-paragraph-fold">This action does not require allow cache as it uses a separate list of loaded URLs. URLs are added to this list after the corresponding request is completed.</div>
      <div class="tr tooltip-paragraph-fold">The list of loaded URLs can be cleared using the "<a href="#!/cleardata">Clear Cached Data</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">You can change the maximum waiting time by clicking the hourglass icon next to the "<b>Cancel</b>" button.</div>
      <div class="tr tooltip-paragraph-last-fold">To check if a URL has been loaded without waiting for it, use the "<a href="#!/isloaded">Is Loaded</a>" action from the "<b>Network</b>" module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="waiturl">
    <div class="container-fluid load">
      <%= _.template($('#input_constructor').html())({id:"Wait", description:tr("Url"), default_selector: "string", disable_int:true}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait until address bar contains specified URL.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="waitcontent">
    <div class="container-fluid load">
      <%= _.template($('#input_constructor').html())({id:"Wait", description:tr("Text"), default_selector: "string", disable_int:true}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait until specific text appears on the page.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="waitcss">
    <div class="container-fluid load">
      <%= _.template($('#input_constructor').html())({id:"Wait", description:tr("Selector"), default_selector: "string", disable_int:true}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait until specific CSS-selector returns a non-empty result.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="waitfiledownload">
     <div class="container-fluid load">
       <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To save file name"), default_variable: "DOWNLOADED_FILE_PATH"}) %>
      </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Wait for the end of the current download.</div>
    </div>
     <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="sleep">
    <div class="container-fluid sleep">
       <%= _.template($('#input_constructor').html())({id:"sleepfrom", visible_if_checked: "sleeprandom", description:tr("Sleep from value in milliseconds"), default_selector: "int", disable_string:true, min_number: 100, value_number: 1000,max_number: 99999999}) %>
       <%= _.template($('#input_constructor').html())({id:"sleepto", visible_if_checked: "sleeprandom", description:tr("Sleep to value in milliseconds"), default_selector: "int", disable_string:true, min_number: 100, value_number: 1000,max_number: 99999999}) %>

       <%= _.template($('#input_constructor').html())({id:"sleepfromto", visible_if_unchecked: "sleeprandom", description:tr("Sleep value in milliseconds"), default_selector: "int", disable_string:true, min_number: 100, value_number: 1000}) %>
       
       <%= _.template($('#checkbox').html())({id: "sleeprandom", title: tr("Sleep random time")}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Pauses current thread for the specified number of milliseconds.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="executefunction">
    <div class="container-fluid executefunction">
      <div class="col-xs-12" style="margin-bottom: 5px;">
        
        <div class="input-group">
          
          <span data-preserve="true" data-preserve-type="text" data-preserve-id="FunctionName">
            <input class="form-control function-input" type="text" id="FunctionName" placeholder="Function name">
            <ul class="dropdown-menu input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown">
              <li>
                <a tabindex="-1" href="#" class="func" data-result-target="#FunctionName">
                  <span class="tr">Select function</span>
                </a>
              </li>
            </ul>
          </span>        

          <span class="input-group-addon input-description tr">Function name</span>
        </div>
        
      </div>
      <div id="FunctionParameters">
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute function and proceed with next action.</div>

      <div class="tooltip-paragraph-fold"><span class="tr">Function must be defined beforehand. BAS allows define functions through "Function Tab"</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=functionstab.png');return false">screen</a>)</div>
      <div class="tr tooltip-paragraph-fold">Function name may be selected by pressing on <i class="fa fa-dot-circle-o"></i> button.</div>
      <div class="tr tooltip-paragraph-fold">Functions are containers, which holds action list. It helps to group several actions which does same task. For example, there can be function which logins to account, function that checks account balance, etc. It makes your code clear and well organized.</div> 
      <div class="tr tooltip-paragraph-fold">Functions may be executed(with this action), this means that every action inside it will be executed sequentially.</div>
      <div class="tr tooltip-paragraph-fold">Another advantage is that one function may be executed as many times as you want from any place in the script. This helps to avoid code duplication. If you want to update function, you need to do that only once, not in every place where it used.</div>
      <div class="tr tooltip-paragraph-last-fold">If you see, that your code gets bigger, good practice would be to select script part which does common task, and move it inside new function.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false, wiki: "functions"}) %>
  </script>

  <script type="text/template" id="getfunctionparameter">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"ParameterName",disable_editor:true, disable_variable:true, disable_resource:true, disable_separator:true, disable_type_chooser:true, description:tr("Parameter name"), variants: function_params, default_selector: "string", disable_int:true, disable_expression: true, help: {description: tr("Parameter name is used to identify parameter, could be any string.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save Result"), default_variable: "FUNCTION_PARAMETER", help: {description: tr("Variable which will contain parameter value.")}}) %>

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get specified parameter value for current function.</div>

      <div class="tr tooltip-paragraph-fold">Every function can have any number of parameters, each of them are identified by its name.</div>

      <div class="tr tooltip-paragraph-fold">Consider following example, you have a function which loads certain url parses its content and returns result. In that case, function will have one parameter - page url, you can name it whatever you want: "Url", "Page Url", etc. "Get Function Parameter" action is used to obtain actual url value(or any other parameter value) for current function run. These parameters may be different for each function run, for example, it may be called for different urls: "url1", "url2", etc any number of times from any place inside code. With the help of functions you can call your code as many times as you want without duplicating whole code.</div>
      <div class="tooltip-paragraph-fold tr">Actual parameter values are set inside "Call function" action.</div>
      <div class="tooltip-paragraph-fold tr">In order to change function parameter definitions or add a new one, use function manager, it is located in the bottom-left corner of the interface.</div>
      <div class="tooltip-paragraph-fold tr">This action will only works if execution point is inside function, if it is placed inside "Main" function, return value will be null.</div>
      <div class="tr tooltip-paragraph-last-fold">If parameter name doesn't exist, this action will return null.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="return">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"ReturnValue", description:tr("Return value"), default_selector: "string", help: {description: tr("Value, which contains result of function work. It will be placed into variable defined in \"Call function\" action, so it can be used after function is finished. If function does not provide any return value, leave this field empty")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Immediately interrupt current function call. This action works only if placed inside function.</div>

      <div class="tr tooltip-paragraph-fold">After launch this action stops function immediately, execution point is moved to the next action after "Call Function".</div>

      <div class="tr tooltip-paragraph-fold">Action will return data specified in "Return value" parameter into variable defined in "Call Function" action. This data contains result of function work.</div>

      <div class="tr tooltip-paragraph-last-fold">Consider following example, you have a function which loads certain url, parses its content and returns result. In that case, function will have one parameter - page url, and return value, which will contain page content. With help of "Return" action you can set page content as result of function work.</div>
      
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="recaptchav3">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Method", description:tr("Solve Method"), default_selector: "string", disable_int:true, value_string: "rucaptcha", variants: ["rucaptcha","2captcha","antigate","disable"], size: 3, help: {description: tr("Solve method is a string, you can set value directly or use variable or resource."), examples:[{code:"antigate",description:tr("Solve with http://anti-captcha.com/ service")},{code:"rucaptcha",description:tr("Solve with http://rucaptcha.com/ service")},{code:"2captcha",description:tr("Solve with http://2captcha.com/ service")},{code:"disable",description:tr("Stop intercepting recaptcha v3 requests. Site will get your real score. You can enable intercepting later again.")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"Rucaptcha", description:tr("Rucaptcha/2captcha Key. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("This is a key from service selected in 'Solve Method' field.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Action", description:tr("Action name"), default_selector: "string", disable_int:true, value_string: "*", variants: ["*"].concat(RecaptchaV3ActionList), help: {description: tr("Contains one or several recaptcha v3 actions. Several action may be separated by commas. When browser will execute one of following actions, user score request will be intercepted and sent to service selected in 'Solve Method' field. By default every request will be intercepted, tweak this field in order to send only important actions."), examples:[{code:"*",description:tr("Intercept all actions")},{code:"Action 1",description:tr("Intercept only 'Action 1', all other actions will return real browser score.")},{code:"Action 1,Action 2",description:tr("Intercept only 'Action 1' or 'Action 2', all other actions will return real browser score. NOTE: there should not be any spaces near comma.")}]}}) %>
      
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>

        <%= _.template($('#input_constructor').html())({id:"Server", description:tr("Server url. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("String which contains server url."), examples:[{code:"http://127.0.0.3:8083/"},{code:tr("Empty string"), description: tr("Use default server url, http://rucaptcha.com for rucaptcha, etc")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"Score", description:tr("Minimal score"), value_string:"0.3", default_selector: "expression", disable_int:true, disable_string:true, help: {description: tr("Minimal score to which the answer from service must meet. 0.1 - is the lowest score, 0.9 - is the highest. It depends on site, if it wants to accept certain score or not and what to do with low score browsers. 0.6 - is default value it must be acceptable for most of the sites."), examples:[{code:"0.3"},{code:"0.7"}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"SendProxy", description:tr("Send current proxy to solver service"), default_selector: "string", disable_int:true, value_string: "false", variants: ["true","false"], help: {description: tr("Forces person who solves recaptcha use proxy that you setted up with \"Proxy\" action."), examples:[{code:"true",description:tr("Send current proxy to server. Proxy value is obtained from \"Proxy\" action.")},{code:"false",description:tr("Don't send proxy. Default value.")}]}}) %>

      <%= _.template($('#block_end').html())() %>
      </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action solves google recaptcha 3.0.</div>
      <div class="tr tooltip-paragraph-fold">Recaptcha v3, unlike other captchas, doesn't show any image or challenges. It works silently without any user interactions. Therefore, it can be placed in several places on site, or even on each page. For each page or event where Recaptcha v3 is attached to it returns user score. User score reflects how likely the site visitor to be a bot.</div>
      <div class="tr tooltip-paragraph-fold">The site can use the result score as it sees fit. For example, site can show captcha if user score is lower than 0.4, other site may require phone verification if score is lower than 0.6 and block the user if it is lower than 0.3.</div>
      <div class="tr tooltip-paragraph-fold">This action intercepts user verification request and send it to specified service. When service will return result, it will replace browser real score with score obtained for one of the worker of selected service.</div>
      <div class="tr tooltip-paragraph-fold">IMPORTANT: This action doesn't solves any captcha by itself, instead it tells BAS to solve any following Recaptcha v3 with specified parameters. Therefore, it must be placed before any captcha methods are used.</div>
      <div class="tr tooltip-paragraph-fold">Each site has its own requirements and minimal scores, you can tweak expected minimal score by changing 'Minimal score' parameter.</div>
      <div class="tr tooltip-paragraph-fold">Recaptcha v3 may be placed on every page on site. Each page will have its own action. For example, there could be actions for visiting homepage, visiting FAQ page, and for creating new user. You can disable interception for minor actions and enable it for important one by changing 'Action name' parameter.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">In order to find exact action name on particular site, you need to visit site and trigger required action, message with action name will be shown afterwards.</span>(<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserautomationstudio_2019-09-12_19-21-35.png'); return false;">screen</a>). <span class="tr">Each used action will also be added to suggestions for 'Action name' parameter.</span></div>
      <div class="tr tooltip-paragraph-fold">All services requires service key which should be bought on service site and inputted into "Rucaptcha/2captcha Key" field.</div>
      <div class="tr tooltip-paragraph-last-fold">Alternatively to this action, you can try to bypass Recapthca V3. Here are things which influence on final score: mature profile with Gmail authorization and Google search history, good proxy, long history with site, that you are working with. Let us dwell on the last point more carefully. Recaptcha v3 track your activities on each site by logging every action you perform. For example, if you visit a store, do a search, visit support page and only after that will try to register account, it would be much less suspicious than trying to register account immediately, and it high likely to get a better score.</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">There is another type of recaptcha called invisible recaptcha. It works almost the same as Recaptcha v3, but instead of returning user score, it shows image if user seem to suspicious, this is equivalent of having low user score. BAS is capable of solving it also, check 'Solve Recaptcha 2.0' action.</span>(<a class="tr" href="#" onclick="BrowserAutomationStudio_OpenUrl('https://www.youtube.com/watch?v=ltWy6O9jsTo'); return false;">video</a>).</div>
    
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </div>
  </script>
  

  <script type="text/template" id="executefunctioninseveralthreads">
    <div class="container-fluid">
      <div class="col-xs-12" style="margin-bottom: 5px;">
        
        <div class="input-group">
          <span data-preserve="true" data-preserve-type="text" data-preserve-id="FunctionName">

            <input class="form-control function-input" type="text" id="FunctionName" placeholder="Function name">
            
            <ul class="dropdown-menu input-field-dropdown dropdown-align dropdown-black" data-toggle="dropdown">
              <li>
                <a tabindex="-1" href="#" class="func" data-result-target="#FunctionName">
                  <span class="tr">Select function</span>
                </a>
              </li>
            </ul>
          </span> 

          <span class="input-group-addon input-description tr">Function name</span>
        </div>
        
      </div>

      <%= _.template($('#input_constructor').html())({id:"ThreadNumber", description:tr("Thread number"), default_selector: "int", disable_string:true, disable_string:true, min_number: 1, value_number:10, help: {description: tr("Thread number as integer. BAS will create specified here number of threads after action start.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"SuccessNumber", description:tr("Success number"), default_selector: "int", disable_string:true, disable_string:true, min_number: 1, value_number:100, help: {description: tr("Maximum success number as integer. BAS will stop this action and all new thread created by it after maximum success number is reached.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"FailNumber", description:tr("Fail number"), default_selector: "int", disable_string:true, disable_string:true, min_number: 1, value_number:100, help: {description: tr("Maximum fail number as integer. BAS will stop this action and all new thread created by it after maximum fail number is reached.")}}) %>


    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute function specified number of times with specified number of threads. You can think of it as running another script inside current thread.</div>
      <div class="tr tooltip-paragraph-fold">After BAS encounters this action it starts specified number of threads and runs selected function inside them. Thread which called this actions stops until specified number of success or specified number of fails will be reached, but other threads continue execution.</div>
      <div class="tr tooltip-paragraph-fold">Recently started threads don't know about variables or browser state of thread, who started them, so data exchange between starter thread and recently created can only be performed with global variables or resources.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Example #1. You have a script which parses a list of links and want to get its content. Of cource, you can create a loop, iterate over them and parse. But in this case links will be processed one by one - sequentially. With this action you can process them in parallel. Create resource, write all links there and call parsing functions in several threads</span> (<span class="tr-en"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://www.youtube.com/watch?v=vgzMX3F-EQI');return false">video</a></span><span class="tr-ru"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://www.youtube.com/watch?v=Pal3HsU_UTA');return false">видео</a></span>)</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Example #2. You need call some function before script start and another after script finish. In that case you can set "Thread number", "Success number" and "Fail number" to 1 in main script. Create 3 functions: MainScript, OnStart and OnEnd and call OnStart and OnEnd with one thread, MainScript function should be called with thread and success and fail number same as whole script</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=onstartonend.png');return false">screen</a>)</div>
      <div class="tr tooltip-paragraph-last-fold">This action never fails even if fail number is reached, so you don't need to wrap it in ignore errors block.</div>
      <div class="tr tooltip-paragraph-last-fold">Call "End Script" inside specified function to stop this action manually.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>


  <script type="text/template" id="setheader">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Name", description:tr("Header Name"), default_selector: "string", disable_int:true, value_string: "User-Agent", variants: ["User-Agent","Accept-Language"], size: 3, help: {description: tr("Request header name. Header name must contain one or several words separated with dash."),examples:[{code:"User-Agent",description:tr("Set 'User-Agent' header.")},{code:"Accept-Language",description:tr("Set 'Accept-Language' header.")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Header Value"), default_selector: "string", disable_int:true, value_string: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0", help: {description: tr("Request header value. This could be arbitrary string.")}}) %>
      <%= _.template($('#targetfields').html())({}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set request header for subsequent browser requests.</div>
      <div class="tr tooltip-paragraph-fold">Current action is deprecated. To ensure header authenticity, it is recommended to use the "<a href="#!/FingerprintSwitcher_Apply">Apply fingerprint</a>" action. Additionally, the "<b>Referrer</b>" should be specified in the "<a href="#!/load">Load</a>" action for the required Urls.</div>
      <div class="tr tooltip-paragraph-fold">This action will set an extra HTTP header that will be sent with every browser request made after this action.</div>
      <div class="tr tooltip-paragraph-last-fold">To disable all headers set by this action, use the "<a href="#!/reset">Reset</a>" action. However, it clears all browser data, not just the headers.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="clickCaptchaBrowser">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({ id: 'imageData', description: tr('Captcha picture data encoded in base64'), value_string: '', default_selector: 'string', disable_int: true, help: {
        description: tr('Data in base64 format can be obtained from screenshot action or from read file action.')
      }}) %>
      <%= _.template($('#input_constructor').html())({ id: 'serviceName', description: tr('Service name'), variants: [ 'rucaptcha', '2captcha' ], value_string: 'rucaptcha', default_selector: 'string', disable_int: true, help: {
        description: tr('Captcha solving service name'),
        examples: [
          { code: 'rucaptcha', description: tr('Solve captcha using https://rucaptcha.com/ service') },
          { code: '2captcha', description: tr('Solve captcha using https://2captcha.com/ service') },
        ]
      }}) %>
      <%= _.template($('#input_constructor').html())({ id: 'serviceKey', description: tr('Service key'), disable_int: true, default_selector: 'string', help: { description: tr('Captcha solving service key. You can get it in your personal account of selected captcha solving service') } }) %>
      <%= _.template($('#input_constructor').html())({ description: tr('Captcha description. Can be empty.'), value_string: '', default_selector: 'string', disable_int: true, id: 'textInstructions', help: {
        description: tr('If captcha has any description, it can be added with this field.'),
        examples: [
          { code: tr('Select all images where there is a plane') },
          { code: tr('Select all images where there is a boat') }
        ]
      }}) %>
      <%= _.template($('#variable_constructor').html())({ id: 'clickCoordinatesList', description: tr('Click coordinates'), default_variable: 'COORDINATES_LIST', help: {
        description: tr('List containing the coordinates of the points to be clicked. Each item in this list contains <code>X</code> and <code>Y</code> coordinates of one particular point. For example, if the service returns a list of the form <code>[[1,2], [3,5]]</code>, then there are only two points to click. The first point is located at position 1 horizontally and at position 2 vertically. The second point is used in the same way. After getting such a list, you can process it with loops like <code>for</code> or <code>foreach</code>. Inside the loop, you need to call an action that will perform a click on the coordinates, such as the <code>Click</code> action.<br>For the <code>X</code> coordinate you can use a construction like this - <code>[[COORDINATES_LIST]][pointIndex][0]</code>.<br>For the <code>Y</code> coordinate you can use a construction like this - <code>[[COORDINATES_LIST]][pointIndex][1]</code>.'),
        examples: [
          { code: '[ [120, 59], [91, 5], [59, 12] ]', description: tr('There are three points to click on the coordinates - X1 = 120, Y1 = 59. X2 = 91, Y2 = 5. X3 = 59, Y3 = 12.') },
          { code: '[ [15, 380], [1, 1] ]', description: tr('There are two points to click on the coordinates - X1 = 15, Y1 = 380. X2 = 1, Y2 = 1.') },
          { code: '[ [12, 24] ]', description: tr('There is one point to click on the coordinates - X1 = 12, Y1 = 24.') },
        ]
      }}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({ description: tr('Task solution check interval'), default_selector: 'int', value_number: 5000, disable_string: true, id: 'taskWaitTimeout', help: {
          description: tr('Task solution check interval in milliseconds. With this parameter you can control the length of the pause between each new check of the captcha solution.'),
          examples: [
            { code: '600', description: tr('Wait for 600 milliseconds') },
            { code: '10000', description: tr('Wait for 10 seconds') },
            { code: '5000', description: tr('Wait for 5 seconds') }
          ]
        }}) %>
        <%= _.template($('#input_constructor').html())({ description: tr('Task solution check delay'), default_selector: 'int', value_number: 5000, disable_string: true, id: 'taskWaitDelay', help: {
          description: tr('Task solution check delay in milliseconds. With this parameter you can control the length of the pause between sending the task to the service and the start of waiting for a solution. Most often, captcha-solving services specify the required waiting time, in other cases you can specify any value convenient for you.'),
          examples: [
            { code: '600', description: tr('Wait for 600 milliseconds') },
            { code: '10000', description: tr('Wait for 10 seconds') },
            { code: '5000', description: tr('Wait for 5 seconds') }
          ]
        }}) %>
        <%= _.template($('#input_constructor').html())({ description: tr('Service URL'), default_selector: 'string', disable_int: true, value_string: '', id: 'serviceUrl', help: {
          description: tr('Service URL. Can be blank. You can use this option if the service you want is not on the list of available services. In this case, specify the name of the service that works on a similar API and use the address you need.'),
          examples: [
            { code: tr('Empty string'), description: tr('Use default service URL, http://rucaptcha.com for RuCaptcha, etc') },
            { code: 'http://127.0.0.1:8083', description: tr('Use custom service URL with port 8083') },
            { code: 'http://127.0.0.3:8080', description: tr('Use custom service URL with port 8080') },
          ]
        }}) %>
      <%= _.template($('#block_end').html())() %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Solve any type of captcha that requires clicking on images.</div>
      <div class="tr tooltip-paragraph-fold">For <code>ReCaptcha</code> and <code>HCaptcha</code> solving it is recommended to use the <code>Solve Recaptcha 2.0</code> and <code>Solve HCaptcha</code> actions from the browser context menu, if it's possible. It is easier to use, and the captcha can be solved faster. Also, these actions can perform automatic submit of the solution. Use this action if other options don't suit you for some reason.</div>
      <div class="tr tooltip-paragraph-fold">This action allows you to solve any captcha that requires you to click on images according to specific instructions. These can be <code>ReCaptcha</code>, <code>HCaptcha</code> and other types. To solve such captchas, you need to send an image to the service containing elements to be clicked. If there is a description on the captcha or next to it, it is recommended to send it along with the image to avoid incorrect solutions.</div>
      <div class="tr tooltip-paragraph-fold">This action doesn't perform automatic coordinate clicks, unlike the <code>Solve captcha with clicks</code> action from the browser context menu, which does everything without your interaction. It's much easier to use.</div>
      <div class="tr tooltip-paragraph-fold">After the service solves the captcha, you will receive a list of coordinates on which you should click. In order to perform clicks, this list must be passed through any loop, such as <code>for</code> or <code>foreach</code>, and at each iteration call the <code>Click</code> actiom for each pair of <code>X</code> and <code>Y</code> coordinates. After the clicks are done, you need to continue manually. That is, you have to do your own solution confirmation or move on to the next image.</div>
      <div class="tr tooltip-paragraph-fold">All services requires a service key which which must be obtained on the service website and entered in the <code>Service key</code> field.</div>
      <div class="tr tooltip-paragraph-fold">To perform clicks on the received coordinates, you need to take into account the position of the element whose screenshot you are sending relative to the page, as well as scrolling vertically and horizontally. Therefore, the simplest option would be to use a similar action for a specific element from the context menu of the browser, where clicks will be performed automatically.</div>
      <div class="tr tooltip-paragraph-fold">An important point - this action does not automatically confirm the solution of the captcha. You have to do it yourself. For example, if you solve <code>ReCaptcha2</code> using this method, you should click the checkbox yourself, and after clicking on the coordinates, click the <code>Next</code> or <code>Done</code> button.</div>
      <div class="tr tooltip-paragraph-fold">The <code>Task solution check interval</code> parameter is responsible for the frequency of sending requests to the service to check the captcha solution. The more you set the value, the longer BAS will wait before sending the next request. It is recommended to use a delay of at least 5 seconds.</div>
      <div class="tr tooltip-paragraph-fold">The <code>Task solution check delay</code> parameter is responsible for the duration of waiting before the BAS starts checking the captcha. First, the captcha sent to the service, then the BAS will wait for the specified time, after which the task status check itself will begin. Most services recommend waiting at least 5 seconds.</div>
      <div class="tr tooltip-paragraph-fold">If the required service is not in the list of available ones, but it works through an API similar to the selected service, then you can specify required server URL in the <code>Service URL</code> field located in the additional settings.</div>
      <div class="tr tooltip-paragraph-fold">If you use programs such as <code>CapMonster</code>, <code>XEvil</code> or similar software, you must fill in the <code>Service URL</code> field in accordance with the documentation for this software.</div>
      <div class="tr tooltip-paragraph-last-fold">Detailed documentation for solving such captchas can be found <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://2captcha.com/2captcha-api#coordinates');return false">here</a>.</div>
    </div>
    <%= _.template($('#back').html())({ action: 'executeandadd', visible: true, name: tr('Solve captcha with clicks') }) %>
  </script>

  <script type="text/template" id="solvecaptcha">
    <div class="container-fluid solvecaptcha">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Captcha picture data encoded in base64"), default_selector: "expression", disable_int:true, disable_string:true, help: {description: tr("Data in base64 format can be obtained from screenshot action or from read file action.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Method", description:tr("Solve Method"), default_selector: "string", disable_int:true, value_string: "manual", variants: ["manual","antigate","rucaptcha","2captcha","capmonster","dbc", "captchasniper"], size: 3, help: {description: tr("Solve method is a string, you can set value directly or use variable or resource."), examples:[{code:"manual",description:tr("Image is solved directly by person who uses BAS.")},{code:"antigate",description:tr("Solve with http://anti-captcha.com/ service")},{code:"rucaptcha",description:tr("Solve with http://rucaptcha.com/ service")},{code:"2captcha",description:tr("Solve with http://2captcha.com/ service")},{code:"capmonter",description:tr("Use capmonster")},{code:"dbc",description:tr("Use http://deathbycaptcha.com/ service")}]}}) %>
      
      <%= _.template($('#input_constructor').html())({id:"Antigate", description:tr("Antigate/Rucaptcha/2captcha/DBC Key. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("This key is needed only if you are using services to solve captcha. It is not needed in manual, capmonster and captchasniper modes. In case of deathbycaptcha this field must contain dbc_login:dbc:password.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Server", description:tr("Server url. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("String which contains server url."), examples:[{code:"http://127.0.0.3:8083/"},{code:tr("Empty string"), description: tr("Use default server url, http://rucaptcha.com for rucaptcha, etc")}]}
}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save Result"), default_variable: "CAPTCHA_RESULT", help: {description: tr("String with captcha result")}}) %>
    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action solves image captcha(not recaptcha) and works only if you have image data formatted as base64 string.</div>
      <div class="tr tooltip-paragraph-fold">Captcha text is saved to variable and can be used later.</div>
      <div class="tr tooltip-paragraph-fold">If you want to take captcha from element on screen, you should click on it and use "Solve Captcha" action.</div> 
      <div class="tr tooltip-paragraph-last-fold">If you want to solve recaptcha, click on recaptcha checkbox inside browser and choose "Solve Recaptcha 2.0" action.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true,wiki: "how_to_solve_captcha"}) %>
  </script>
  
  <script type="text/template" id="javascript">
      <div class="container-fluid javascript">
        <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_SCRIPT_RESULT", help: {description: tr("Variable with result of javascript execution. Type of variable is always string, if expression is evaluated to other type, it will be converted. If exception will occur during script execution, than empty string will return.")}}) %>
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Script Text"), default_selector: "string", disable_int:true, help: {description: tr("Script that will be executed in browser. Type of that value should be string. If you set type to expression, than script will be evaluated in BAS context first and than result of that evaluation will be send to browser. Using expression is usefull if you want to create script dynamically, but you need to use string type in most cases."), examples:[{code:"window.innerWidth",description:tr("Get window width")},{code:"document.readyState == \"complete\"",description:tr("Check if page is loading")}, {code:"let links = document.getElementsByTagName(\"a\"); links.length",description:tr("Find number of links on page")}, {code:"document.getElementById([[ID]]).click()",description:tr("Click on element with id from [[ID]] variable")}]}}) %>
        
      </div>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Execute javascript inside browser. This means that document, window and other browser javascript objects are available.</div>
        <div class="tr tooltip-paragraph-fold">Action works exactly the same as if you input code into browser console and output result into variable.</div>
        <div class="tr tooltip-paragraph-fold">You can also use resources and variables here but only in read mode. Following code will work document.getElementById([[ID]]).innerHTML, but you can't do like this <strike>[[RESULT]] = document.getElementById([[ID]]).innerHTML</strike>.</div> 
        <div class="tr tooltip-paragraph-fold">This action is deprecated. It is recommended to use the new <a href="#!/browserjavascript">Javascript</a> action.</div>
        <div class="tr tooltip-paragraph-last-fold">Use <a href="#!/custom">Execute Code</a> action if you want to run javascript inside thread.</div>
      </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_execute_javascript_on_page_and_save_result"}) %>
  </script>

  <script type="text/template" id="browserjavascript">
    <div class="container-fluid">
      <span data-preserve="true" data-preserve-type="constr" data-preserve-id="Code">
        <div id="Code" class="browser-code-editor" data-is-code-editor="true" />
      </span>
      <%= "<s" + "cript>" %>
        window.Code = {Editor: null, InitialValue: ""}
    
        require(['vs/editor/editor.main'], function() {
          window.Code.Editor = createCodeEditor(document.getElementById('Code'), {
            value: window.Code.InitialValue
          });
        });
      <%= "</" + "script>" %>
      <div style="text-align: center">
        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#Code" class="var"  disable_globals="true">
          
          <span style="align-items: center; display: flex !important; justify-content: center;margin-top:5px;">
            <svg class="dropdown-icon" width="16" height="16"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"  style="margin-right:10px">
              <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#337ab7" />
              <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#337ab7" />
            </svg>
            <span class="tr">Insert variable</span>
          </span>
        </a>
      </div>
      <span class="short-description tr">Execute javascript inside browser. This means that document, window and other browser javascript objects are available.</span>
    </div>
    <%= _.template($('#back').html())({ action: "executeandadd", visible: true, use_timeout: true, use_modal_template:true, modal_code_id: "custom-help-browser-" + (_K || "en") }) %>
  </script>

  <script type="text/template" id="onloadjavascript">
      <div class="container-fluid javascript">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Script Text"), default_selector: "string", disable_int:true, disable_editor:true, use_textarea:true, size: 8, disable_type_chooser:true, help: {description: tr("Script which must be executed at page start. May contain variables or resources."), examples:[{code:"window.secret = 123",description:tr("Set global variable in browser context")},{code:"Object.defineProperty(navigator,\"platform\", {  get: () => \"MacIntel\" });",description:tr("Set navigator.platform")}]}
}) %>
      </div>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">This action sets script which must be executed inside every page and every frame immediately after page is created. Unlike javascript action, script defined here is executed at the very beginning of page load, which gives possibility to change browser internals like window.navigator. Action should be called before page load.</div>
        <span class="short-description tr">This action sets script which must be executed inside every page and every frame immediately after page is created.</span>
      </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="parseline">
    <div class="container-fluid parseline">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Line"), default_selector: "string", disable_int:true, help: {description: tr("Line with several elements separated with \":\" or \",\" or \";\""), examples:[{code:"login:password"},{code:"id,name,login"}]}
}) %>
      <%= _.template($('#variable_constructor').html())({id:"VariablesList", description:tr("Variables To Save Result"), default_variable: "USERNAME,PASSWORD", append_mode:true, help: {description: tr("List of variables separated by commas. Results will be written into that variables.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Parses line, which contains several elements. Elements are separated with one of following symbols: ":", ";", ",".</div>
      <div class="tr tooltip-paragraph-fold">This action is deprecated. It is recommended to use the new <a href="#!/parse_csv_string">Parse CSV string</a> action.</div>
      <div class="tr tooltip-paragraph-fold">For example, if you apply this action to line email@gmail.com:mypass1 and set "Variables To Save Result" param to USERNAME,PASSWORD, than this action will set [[USERNAME]] variable to email@gmail.com and [[PASSWORD]] variable to mypass1.</div>
      <div class="tr tooltip-paragraph-fold">If "Variables To Save Result" will contain more variables, than number of elements in string, than extra variables will be left unchanged.</div>
      <div class="tr tooltip-paragraph-fold">Use "Parse String" action if you want to get list as a result.</div>
      <div class="tr tooltip-paragraph-last-fold">This action also may parse strings in csv format.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
    
  </script>

  <script type="text/template" id="reset">
      <span data-preserve="true" data-preserve-type="check" data-preserve-id="Check">
      </span>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Clear all browser data: proxy, user agent, headers, BAS cache filters, BAS cache data, cookies.</div>
        <div class="tr tooltip-paragraph-last-fold">Don't call this action on thread start, BAS will clear data at the beginning of thread automatically.</div>
      </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_clear_cookies_and_restart_browser"}) %>
  </script>

  <script type="text/template" id="openfile">
    <div class="container-fluid openfile">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("File path to set as result of open file dialog"), default_selector: "string", disable_int:true, help: {description: tr("This parameter is a string with file path. Slash type is not important. It also could be a json array with several files, see examples. In that case BAS acts like if user would selected several files."), examples:[{code:"C:\\file\\path.txt"},{code:"C:/file/path.txt"},{code:"[\"C:/file/path1.txt\", \"C:/file/path2.txt\"]"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Uploading file is performed in two steps: setting next open file dialog result with this action and clicking on element which triggers file upload, like "Upload" button.</div>
      <div class="tr tooltip-paragraph-fold">You must always call this action before starting upload, otherwise BAS won't know which file it need to send to browser.</div>
      <div class="tr tooltip-paragraph-last-fold">Use resource with type FilesFromDirectory to upload all files from folder and distribute them across threads.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_use_open_file_dialog"}) %>
  </script>


  <script type="text/template" id="dragfile">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("File path to start drag"), default_selector: "string", disable_int:true, help: {description: tr("This parameter is a string with file path. Slash type is not important."), examples:[{code:"C:\\file\\path.txt"},{code:"C:/file/path.txt"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action is alternative to "Open File Result" with only difference - it drag file into browser instead of opening dialog.</div>
      <div class="tr tooltip-paragraph-fold">Calling this action is the same as start dragging file into ordinary browser.</div>
      <div class="tr tooltip-paragraph-last-fold">Dont forget to drop it with Drop or Drop On Element action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="promptresult">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Prompt user input result"), default_selector: "string", disable_int:true, help: {description: tr("Any string")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Prompt window displays a dialog with an optional message prompting the user to input some text. It is outdated functionality and most sites don't use it any more. BAS allows to input text into that window automatically, to do that you must call this action before prompt window will appear.</div>
      <div class="tr tooltip-paragraph-fold">Principle is the same as in "Open File Result", first you call action which sets result and than trigger dialog, BAS will recognize it and input previously setted up value.</div>
      <div class="tr tooltip-paragraph-last-fold">Prompt window browser documentation <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt');return false">link</a>.</div>
      <span class="short-description tr">Prompt window displays a dialog with an optional message prompting the user to input some text. It is outdated functionality and most sites don't use it any more.</span>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpauth">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Login", description:tr("Http auth login"), default_selector: "string", disable_int:true, help: {description: tr("Site login, could be any string")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Password", description:tr("Http auth password"), default_selector: "string", disable_int:true, help: {description: tr("Site password, could be any string")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">HTTP authentication provides method for user to input site login and password. It is rarely used nowadays, but some sites still rely on it. During authentication process browser shows window and user must input authentication data there. This process can be automated, all you need to do is to call this action before window is triggered.</div>
      <div class="tr tooltip-paragraph-fold">Good idea would be to put it to the start of the script.</div>
      <div class="tr tooltip-paragraph-last-fold">In case if this action will be called after window popup, authentication process will fail.</div>
      <span class="short-description tr">HTTP authentication provides method for user to input site login and password. It is rarely used nowadays, but some sites still rely on it.</span>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="getcookiesforurl">
      <div class="container-fluid">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Url"), default_selector: "string", disable_int:true}) %>
        <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "COOKIES_FOR_URL"}) %>
      </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="savecookies">
    <div class="container-fluid">
          <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_COOKIES", help: {description: tr("Variable in which, after executing the action, a JSON string containing the retrieved cookies will be written.")}}) %>
          <%= _.template($('#input_constructor').html())({id:"Domain", description:tr("Domain"), default_selector: "string", disable_int:true, help: {description: tr("Domain or domain mask for which cookies should be retrieved. In the mask, the \"*\" character matches any number of characters, and \"?\" matches a single character (does not match a dot). Matching is case-insensitive. If the mask starts with \"^\", strict mode is enabled: the pattern is matched exactly, without adding \"*\" at the beginning and end. You can specify multiple domains (or masks) as a list or in a comma-separated string. If no value is specified, the action will retrieve cookies for all domains."), examples:[{code:"example.com"},{code:"site*.com"},{code:"^strict.net"},{code:"example.com,sub?.site.com"},{code:"[\"test.com\", \"*.domain.org\"]"},{code:tr("Empty string"),description:tr("Get cookies for all domains")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Save browser cookies into variable.</div>
      <div class="tr tooltip-paragraph-fold">This action will get cookies from the browser and save them as a JSON string to the specified variable.</div>
      <div class="tr tooltip-paragraph-fold">In the "<b>Domain</b>" parameter, you can specify one or more domains (or domain masks) for which to retrieve cookies. If no value is specified, all available cookies will be retrieved.</div>
      <div class="tr tooltip-paragraph-fold">Most of sites uses cookies to store user data, like user authorisation. This means, that by storing cookies after authorisation on some site and restore them later you can implement autologin.</div>
      <div class="tr tooltip-paragraph-fold">Cookie values is just a string, so you may save it to file, or database and use them later.</div>
      <div class="tr tooltip-paragraph-fold">However, not all websites use cookies for storing authentication; they may rely on localStorage or other mechanisms. Therefore, a more universal solution is to use <a href="#!/UseProfile">profiles</a>, which already include cookies, localStorage, and other data.</div>
      <div class="tr tooltip-paragraph-fold">The cookie JSON string is an object with a single property, "<b>cookies</b>" which is an array containing a list of all received cookies.</div>
      <div class="tr tooltip-paragraph-fold">Each individual element of this array is an object with the following properties:</div>
      <div class="tr tooltip-paragraph-fold"><b>name</b> - The name of the cookie.</div>
      <div class="tr tooltip-paragraph-fold"><b>value</b> - The value of the cookie.</div>
      <div class="tr tooltip-paragraph-fold"><b>domain</b> - The domain to which the cookie is assigned.</div>
      <div class="tr tooltip-paragraph-fold"><b>path</b> - The path for which the cookie is valid.</div>
      <div class="tr tooltip-paragraph-fold"><b>expires</b> - A floating-point number representing the cookies expiration time in Unix timestamp format, or <code>-1</code> if the cookie is session.</div>
      <div class="tr tooltip-paragraph-fold">The cookie expiration date can be determined by multiplying the value of the "<b>expires</b>" property by 1000 and using the resulting value in the "<a href="#!/datetime_msecondstodate">Milliseconds To Date</a>" action.</div>
      <div class="tr tooltip-paragraph-fold"><b>size</b> - An integer representing the size of the cookie in bytes.</div>
      <div class="tr tooltip-paragraph-fold"><b>httpOnly</b> - A flag indicating whether the cookie is accessible only via HTTP (true/false).</div>
      <div class="tr tooltip-paragraph-fold"><b>secure</b> - A flag indicating that the cookie is transmitted only over HTTPS (true/false).</div>
      <div class="tr tooltip-paragraph-fold"><b>session</b> - A flag indicating whether the cookie is a session cookie (true/false).</div>
      <div class="tr tooltip-paragraph-fold">And other more specific properties. A list of all properties and their descriptions can be found <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-Cookie'); return false;">here</a>.</div>
      <div class="tr tooltip-paragraph-last-fold">If you need to modify cookies or extract specific values from them, use actions from the "<b>JSON</b>" module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="restorecookies">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Cookies"), default_selector: "string", disable_int:true, help: {description: tr("A JSON string containing the cookies to be set in the browser. If the value is not specified and adding to existing cookies is disabled, the action will clear all cookies in the browser."), examples:[{code:tr("Empty string"),description:tr("Clear cookies")}]}}) %>
      <%= _.template($('#block_start').html())({id:"Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#checkbox').html())({id:"Append", title: tr("Add cookies to existing ones"), help: {title: tr("Add cookies to existing ones"), description: tr("If enabled, the specified cookies will be added to the existing cookies, rather than replacing them."), examples: [{code: tr("Activated"), description: tr("Add the specified cookies to existing ones")}, {code: tr("Deactivated"), description: tr("Replace existing cookies with the specified ones")}]}}) %>
      <%= _.template($('#block_end').html())() %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set cookies for browser.</div>
      <div class="tr tooltip-paragraph-fold">This action will overwrite the browser cookies with the values from the specified JSON string or add them to the existing ones if the corresponding parameter is activated in the additional settings.</div>
      <div class="tr tooltip-paragraph-fold">If the "<b>Cookies</b>" parameter is not specified and the "<b>Add cookies to existing ones</b>" parameter in the additional settings is not activated, this action will completely clear all cookies in the browser.</div>
      <div class="tr tooltip-paragraph-fold">Most of sites uses cookies to store user data, like user authorisation. This means, that by storing cookies after authorisation on some site and restore them later you can implement autologin.</div>
      <div class="tr tooltip-paragraph-fold">Cookie values is just a string, so you may save it to file, or database and use them later.</div>
      <div class="tr tooltip-paragraph-fold">However, not all websites use cookies for storing authentication; they may rely on localStorage or other mechanisms. Therefore, a more universal solution is to use <a href="#!/UseProfile">profiles</a>, which already include cookies, localStorage, and other data.</div>
      <div class="tr tooltip-paragraph-fold">The cookie JSON string is an object with a single property, "<b>cookies</b>" which is an array containing a list of all cookies.</div>
      <div class="tr tooltip-paragraph-fold">Each individual element of this array is an object with the following properties:</div>
      <div class="tr tooltip-paragraph-fold"><b>name</b> - The name of the cookie.</div>
      <div class="tr tooltip-paragraph-fold"><b>value</b> - The value of the cookie.</div>
      <div class="tr tooltip-paragraph-fold"><b>domain</b> - The domain to which the cookie is assigned.</div>
      <div class="tr tooltip-paragraph-fold"><b>path</b> - The path for which the cookie is valid.</div>
      <div class="tr tooltip-paragraph-fold"><b>expires</b> - A floating-point number representing the cookies expiration time in Unix timestamp format, or <code>-1</code> if the cookie is session.</div>
      <div class="tr tooltip-paragraph-fold"><b>size</b> - An integer representing the size of the cookie in bytes.</div>
      <div class="tr tooltip-paragraph-fold"><b>httpOnly</b> - A flag indicating whether the cookie is accessible only via HTTP (true/false).</div>
      <div class="tr tooltip-paragraph-fold"><b>secure</b> - A flag indicating that the cookie is transmitted only over HTTPS (true/false).</div>
      <div class="tr tooltip-paragraph-fold"><b>session</b> - A flag indicating whether the cookie is a session cookie (true/false).</div>
      <div class="tr tooltip-paragraph-last-fold">And other more specific properties. A list of all properties and their descriptions can be found <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-Cookie'); return false;">here</a>.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="scroll">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"X", description:tr("Scroll x position"), default_selector: "int", disable_string:true, help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Y", description:tr("Scroll y position"), default_selector: "int", disable_string:true, help: {description: tr("Integer value, offset from the top edge of the page"), examples:[{code:"0",description:tr("Scroll to top")},{code:"500",description:tr("Scroll page, so 500 px will be visible")},{code:"9999999",description:tr("Scroll to page bottom")}]}}) %>
      <%= _.template($('#checkbox').html())({id: "Check", title: tr("Use mouse wheel or touch")}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Scroll browser. The objective of this action is to make specified coordinates visible.</div>
      <div class="tr tooltip-paragraph-fold">It doesn't move left top corner of screen to desired position, just ensures that certian position is visible on screen. If coordinates are already visible, than this action will do nothing, otherwise it will scroll viewport in such way, that coordinates are located as close as possible to screen center.</div>
      <div class="tr tooltip-paragraph-fold">If you want to make certain element visible, use "Scroll to element" instead.</div> 
      <div class="tr tooltip-paragraph-fold">If "Use mouse wheel or touch" is checked, scrolling will be emulated as if it will be done by a real user. Mouse wheel will be used in desktop environment and touch screen in mobile. If checkbox is unchecked, scroll will be performed instantly.</div> 
      <div class="tr tooltip-paragraph-last-fold">If you want to scroll to page bottom, use following settings "Scroll x position" = 0, "Scroll y position" = 999999.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true, use_timeout: true, visible:true, wiki: "how_to_scroll_page"}) %>
  </script>

  <script type="text/template" id="html">
      <div class="container-fluid">
        <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_PAGE_HTML", help: {description: tr("Variable where page source will be saved.")} }) %>
      </div>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Get page source and save it to variable. This action saves current source with all changes but not the initial returned by server.</div>
        <div class="tr tooltip-paragraph-last-fold">You can parse it with regular expressions or xpath.</div>
      </div>

      <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_get_page_source"}) %>
  </script>

  <script type="text/template" id="renderscreen">
    <div class="container-fluid renderscreen">
      <%= _.template($('#input_constructor').html())({id:"X", description:"X", default_selector: "int", disable_string:true, value_number:0, help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Y", description:"Y", default_selector: "int", disable_string:true, value_number:0, help: {description: tr("Integer value, offset from the top edge of the page")}}) %>

      <%= _.template($('#input_constructor').html())({id:"Width", description:tr("Width"), default_selector: "int", disable_string:true, value_number:100, help: {description: tr("Image width. Can't be bigger that window width.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Height", description:tr("Height"), default_selector: "int", disable_string:true, value_number:100, help: {description: tr("Image height. Can't be bigger that window height.")}}) %>
 
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable to save as base64 png"), default_variable: "RENDER_RESULT", help: {description: tr("After action will finish, this variable will contain base64 encoded image data, you can use it as captcha or write to file.")}}) %>

 
    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action makes screenshot of selected screen part and saves it to png image encoded as base64 string.</div>
      <div class="tr tooltip-paragraph-fold">If selected area is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">X and Y coordinates are calculated in absolute displacement from page edges.</div> 
      <div class="tr tooltip-paragraph-fold">If you want to make screenshot of certain element, click on it and select "Screenshot" action.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to make screenshot of whole page, click on any browser element and use "Screenshot" action with &gt;CSS&gt; body selector.</div>
    </div>


    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_make_screenshot"}) %>
  </script>

<script type="text/template" id="cachemaskallow">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting requests whose data should be cached. They enable you to precisely specify which URLs' requests will be intercepted and stored, helping to limit the volume of cached data. If no filters are set, the function will save data for all requests of the selected type.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Save data for all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request for which data should be saved. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to save data for all request types."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Save data for all types of HTTP requests")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"limit", description:tr("Number of actuations"), default_selector:"int", disable_string:true, value_number:0, min_number:0, help: {description: tr("The maximum number of requests for which data will be saved.") + " " + tr("If not specified or set to zero, there will be no limit."), examples: [{code:2},{code:5},{code:0,description:tr("Don't limit the number of actuations")},{code:tr("Empty value"),description:tr("Don't limit the number of actuations")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_CACHE_ALLOW", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created filtering function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"CACHECTRL_762937805"},{code:"CACHECTRL_756637936"},{code:"CACHECTRL_1132544774"}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true, value_string: "*"}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Add page content to cache if URL matches specified filters. Works only on pages which will be loaded next after this action call.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a filtering function that will intercepts requests matching the specified filters and the selected request type, saving their data for further use.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will save the data of all requests of the selected type. Try to avoid this, and specify the most detailed filters possible to reduce the amount of cached data. Adding item to cache is resource consuming task, by limiting number of cache items you can optimize your script.</div>
      <div class="tr tooltip-paragraph-fold">All functions created by this action and the "<a href="#!/cachemaskdeny">Deny cache</a>" action are added to a common list. When a request is received, this list is checked in the order of addition.</div>
      <div class="tr tooltip-paragraph-fold">If no function matches the request, the request data is not saved. If exactly one matching function is found, its action (data is saved or not) is applied. If there are multiple matching functions, the one that was added last will be executed.</div>
      <div class="tr tooltip-paragraph-fold">By combining this action with the "<a href="#!/cachemaskdeny">Deny cache</a>" action, you can flexibly control which request data will be saved and which will not. This allows you to store only the necessary data, such as dynamic captcha data, an authorization token, and so on.</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-fold">You can also stop all filtering functions at once by using the "<a href="#!/clearmasks">Clear filters</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">In additional settings, you can set a limit on the number of function executions.</div>
      <div class="tr tooltip-paragraph-fold">The response data from the last request can be retrieved using the "<a href="#!/getfromcache">Get last item from cache</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">The list of all request data can be retrieved using the "<a href="#!/getallcache">Get all items from cache</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">All saved request data can be deleted using the "<a href="#!/cleardata">Clear Cached Data</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
  
  <script type="text/template" id="cachemaskdeny">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting requests whose data should not be cached. They enable you to precisely specify for which URLs data saving will be prevented, helping to avoid caching unnecessary information. If no filters are set, the function will block data saving for all requests of the selected type.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Prevent saving data for all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request for which to prevent data from being saved. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to prevent data from being saved for all request types."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Prevent saving data for all types of HTTP requests")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"limit", description:tr("Number of actuations"), default_selector:"int", disable_string:true, value_number:0, min_number:0, help: {description: tr("The maximum number of requests for which data saving will be prohibited.") + " " + tr("If not specified or set to zero, there will be no limit."), examples: [{code:2},{code:5},{code:0,description:tr("Don't limit the number of actuations")},{code:tr("Empty value"),description:tr("Don't limit the number of actuations")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_CACHE_DENY", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created filtering function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"CACHECTRL_307521151"},{code:"CACHECTRL_1820405423"},{code:"CACHECTRL_1164655934"}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Do not add page content to cache if URL matches specified filters. Works only on pages which will be loaded next after this action call.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a filtering function that will prevent data from being saved for requests matching the specified filters and the selected request type.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will block data saving for all requests of the selected type.</div>
      <div class="tr tooltip-paragraph-fold">All functions created by this action and the "<a href="#!/cachemaskallow">Allow cache</a>" action are added to a common list. When a request is received, this list is checked in the order of addition.</div>
      <div class="tr tooltip-paragraph-fold">If no function matches the request, the request data is not saved. If exactly one matching function is found, its action (data is saved or not) is applied. If there are multiple matching functions, the one that was added last will be executed.</div>
      <div class="tr tooltip-paragraph-fold">By combining this action with the "<a href="#!/cachemaskallow">Allow cache</a>" action, you can flexibly control which request data will be saved and which will not. This allows you to store only the necessary data, such as dynamic captcha data, an authorization token, and so on.</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-fold">You can also stop all filtering functions at once by using the "<a href="#!/clearmasks">Clear filters</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">In additional settings, you can set a limit on the number of function executions.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="cachemaskclear">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Clear all cache filters.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="restrictpopups">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Restrict all popups.</div>
      <div class="tr tooltip-paragraph-fold">This action prevents new tabs from being opened when clicking on a link with the <code>target="_blank"</code> attribute, opening a link while holding the Ctrl key, or using any other methods, including JavaScript.</div>
      <div class="tr tooltip-paragraph-fold">The restriction on creating new tabs also applies to the "<a href="#!/addtab">Add Tab</a>" action, which will return an error during the restriction period.</div>
      <div class="tr tooltip-paragraph-fold">You can restrict specific popup with "<a href="#!/requestmaskdeny">Deny request</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">To cancel this action, use the "<a href="#!/allowpopups">Allow popups</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="restrictdownloads">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Restrict all file downloads.</div>
      <div class="tr tooltip-paragraph-fold">This action blocks the ability to download any files in the browser, providing additional protection against potentially malicious or unwanted content.</div>
      <div class="tr tooltip-paragraph-fold">You can restrict specific download with "<a href="#!/requestmaskdeny">Deny request</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">To cancel this action, use the "<a href="#!/allowdownloads">Allow downloads</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="allowpopups">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Allow all popups.</div>
      <div class="tr tooltip-paragraph-fold">This action removes the restriction on creating new tabs that was previously set by the "<a href="#!/restrictpopups">Restrict popups</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">If the restriction on creating new tabs was not set, this action will do nothing.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="allowdownloads">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Allow all file downloads.</div>
      <div class="tr tooltip-paragraph-fold">This action removes the file download restriction set by the "<a href="#!/restrictdownloads">Restrict downloads</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">If the file download restriction was not set, this action will do nothing.</div>
      <div class="tr tooltip-paragraph-last-fold">You can wait for the file to download and get its path using the "<a href="#!/waitfiledownload">Wait File Download</a>" action from the "<b>Waiters</b>" module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="requestmaskdeny">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting URLs whose loading should be blocked. They enable you to precisely specify which addresses should have their requests prevented. If no filters are set, all requests matching the selected type will be blocked.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Block all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request that should be blocked. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to block all request types."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Block all types of HTTP requests")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_REQUEST_DENY", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created filtering function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"REQCTRL_323941945"},{code:"REQCTRL_1060399004"},{code:"REQCTRL_2076347053"}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Deny URL loading if URL matches specified filters. By default every URL is loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a filtering function that will block requests matching the specified filters and the selected request type.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will block all requests of the selected type.</div>
      <div class="tr tooltip-paragraph-fold">All functions created by this action and the "<a href="#!/requestmaskallow">Allow request</a>" action are added to a common list. When a request is created, this list is checked in the order of addition.</div>
      <div class="tr tooltip-paragraph-fold">If no function matches the request, it is executed without restrictions. If exactly one matching function is found, its action (allow or block) is applied. If there are multiple matching functions, the one that was added last will be executed.</div>
      <div class="tr tooltip-paragraph-fold">By combining this action with the "<a href="#!/requestmaskallow">Allow request</a>" action, you can flexibly control which requests are allowed and which are blocked, saving bandwidth and preventing the loading of unwanted content (such as advertisements).</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-last-fold">You can also stop all filtering functions at once by using the "<a href="#!/clearmasks">Clear filters</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="requestmaskallow">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting URLs for which the request is permitted. They enable you to precisely specify which addresses should be allowed to load. If no filters are set, the allow action will apply to all requests of the selected type.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Allow all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request that should be allowed. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to allow all request types."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Allow all types of HTTP requests")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_REQUEST_ALLOW", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created filtering function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"REQCTRL_639295180"},{code:"REQCTRL_829643785"},{code:"REQCTRL_2042021025"}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Allow URL loading if URL matches specified filters. By default every URL is loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a filtering function that will allow requests matching the specified filters and the selected request type.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will allow all requests of the selected type.</div>
      <div class="tr tooltip-paragraph-fold">All functions created by this action and the "<a href="#!/requestmaskdeny">Deny request</a>" action are added to a common list. When a request is created, this list is checked in the order of addition.</div>
      <div class="tr tooltip-paragraph-fold">If no function matches the request, it is executed without restrictions. If exactly one matching function is found, its action (allow or block) is applied. If there are multiple matching functions, the one that was added last will be executed.</div>
      <div class="tr tooltip-paragraph-fold">By combining this action with the "<a href="#!/requestmaskdeny">Deny request</a>" action, you can flexibly control which requests are allowed and which are blocked, saving bandwidth and preventing the loading of unwanted content (such as advertisements).</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-last-fold">You can also stop all filtering functions at once by using the "<a href="#!/clearmasks">Clear filters</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="requestmaskclear">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Clear all previously added request filters.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="clearmasks">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Clear all previously added cache and request filters.</div>
      <div class="tr tooltip-paragraph-fold">This action will completely and permanently stop all cache and request filtering functions previously created via the following actions: "<a href="#!/cachemaskallow">Allow cache</a>", "<a href="#!/cachemaskdeny">Deny cache</a>", "<a href="#!/requestmaskallow">Allow request</a>", or "<a href="#!/requestmaskdeny">Deny request</a>".</div>
      <div class="tr tooltip-paragraph-fold">To stop specific functions, use the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">Stopping a function removes all information about it, making it impossible to retrieve statistics for these functions after this action is performed.</div>
      <div class="tr tooltip-paragraph-last-fold">If no cache or request filtering functions have been created, this action will do nothing.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="cleardata">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Delete information about all loaded URLs from the cache.</div>
      <div class="tr tooltip-paragraph-fold">This action will completely and permanently delete all cached data resulting from running functions created using the "<a href="#!/cachemaskallow">Allow cache</a>" and "<a href="#!/cachemaskdeny">Deny cache</a>" actions.</div>
      <div class="tr tooltip-paragraph-last-fold">Also, this action will clear the list of loaded URLs, which is used in the "<a href="#!/getstatus">Get Status</a>" and "<a href="#!/isloaded">Is Loaded</a>" actions.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="loadcookiesfrombrowser">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Load cookies from browser to http client.</div>
      <div class="tr tooltip-paragraph-fold">Most of sites uses cookies to store user data, like user authorisation. This means, that by storing cookies after authorisation on some site and restore them later you can implement autologin.</div>
      <div class="tr tooltip-paragraph-last-fold">If login procedure is complicated, login may be performed with browser, and everything else with http client. To do that, after login with browser use this action and authorisation state will be transfered to http client.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="loadcookiesfromhttpclient">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Load cookies from http client to browser.</div>
      <div class="tr tooltip-paragraph-fold">This action will overwrite all cookies set in the browser with cookies received from the http client.</div>
      <div class="tr tooltip-paragraph-fold">This action is useful when performing certain operations is difficult with an HTTP client but easy in a browser.</div>
      <div class="tr tooltip-paragraph-last-fold">After performing the necessary actions, the updated cookies can be transferred back to the http client using the "<a href="#!/loadcookiesfrombrowser">Load cookies from browser</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="closebrowser">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Close browser which was created with 'Open Browser' action. This action is not mandatory for use to work with browser.</div>
      <div class="tooltip-paragraph-fold">
        <span class="tr">By default browser is created only after running first action that uses browser. After browser is created, it won't be deleted until thread end</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimedefault.png');return false">screen</a> ). <span class="tr">Running browser, especially in multithreaded mode, is task that consumes a lot of PC resources. So this approach may not be always effective. To avoid using browser, when you don't need it, you can explicitly specify browser lifetime with 'Open browser' and 'Close browser'</span>
  ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimemanual.png');return false">screen</a> ).
      </div>
      <div class="tooltip-paragraph-fold">
        <span class="tr">In case if script has at least one 'Open browser' or 'Close browser' action, then browser manual control mode is on. This means, that you must explicitly set all places where browser must be created and places where browser must be closed. If you try to use browser when it is yet not created or already closed, thread will fail with error</span> 
        ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimefail.png');return false">screen</a> ).
      </div>
      <div class="tr tooltip-paragraph-last-fold">It is very important to understand, that by default browser is created automatically and you don't need to call 'Open Browser' action, unless to want to control browser lifetime.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="openbrowser">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Create a browser if it has not already been created. This action is not mandatory for use to work with browser.</div>
      <div class="tooltip-paragraph-fold">
        <span class="tr">By default browser is created only after running first action that uses browser. After browser is created, it won't be deleted until thread end</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimedefault.png');return false">screen</a> ). <span class="tr">Running browser, especially in multithreaded mode, is task that consumes a lot of PC resources. So this approach may not be always effective. To avoid using browser, when you don't need it, you can explicitly specify browser lifetime with 'Open browser' and 'Close browser'</span>
  ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimemanual.png');return false">screen</a> ).
      </div>
      <div class="tooltip-paragraph-fold">
        <span class="tr">In case if script has at least one 'Open browser' or 'Close browser' action, then browser manual control mode is on. This means, that you must explicitly set all places where browser must be created and places where browser must be closed. If you try to use browser when it is yet not created or already closed, thread will fail with error</span> 
        ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=browserlifetimefail.png');return false">screen</a> ).
      </div>
      <div class="tr tooltip-paragraph-last-fold">It is very important to understand, that by default browser is created automatically and you don't need to call 'Open Browser' action, unless to want to control browser lifetime.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="getstatus">
    <div class="container-fluid getstatus">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting the URL whose HTTP request status should be retrieved. They enable you to precisely specify which URL's response status should be returned. If no filters are set, the status of the first loaded URL matching the selected request type will be returned.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_STATUS", help: {description: tr("Variable in which, after executing the action, the numeric HTTP status of the loaded Url request will be written, or <code>0</code> if the Url was not loaded."), examples: [{code:200,description:tr("The request has succeeded.")},{code:302,description:tr("The target page resides under different url.")},{code:404,description:tr("Page not found")},{code:0,description:tr("The Url has not yet been loaded or is currently being loaded")}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get request status for the URL matching the specified filters.</div>
      <div class="tr tooltip-paragraph-fold">This action will return the numeric HTTP request status for the loaded URL that matches the specified filters, or <code>0</code> if the URL has not yet been loaded or is currently being loaded.</div>
      <div class="tr tooltip-paragraph-fold">You can compare the status using the "<a href="#!/if">If</a>" action. For example, by using the expression <code>[[SAVED_STATUS]] == 200</code>, you can check whether the request was successful.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the action will return the status of the first loaded URL.</div>
      <div class="tr tooltip-paragraph-fold">This action does not require allow cache as it uses a separate list of loaded URLs. URLs are added to this list after the corresponding request is completed.</div>
      <div class="tr tooltip-paragraph-fold">The list of loaded URLs can be cleared using the "<a href="#!/cleardata">Clear Cached Data</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">List of all <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://httpstatuses.com/');return false">HTTP statuses</a>.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="isloaded">
    <div class="container-fluid isloaded">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions to determine whether a specific URL has finished loading. They enable you to precisely specify which URL should be checked for complete loading. If no filters are set, the check will be performed on any loaded URL.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_IS_LOADED", help: {description: tr("Variable in which, after executing the action, the value <code>1</code> or <code>0</code> will be written, depending on whether the Url was loaded or not."), examples: [{"code":1,description:tr("The Url is fully loaded")},{"code":0,description:tr("The Url has not yet been loaded or is currently being loaded")}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Check if a URL matching the specified filters has been loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action returns <code>1</code> if the URL matching the specified filters has been fully loaded, and <code>0</code> if it is not yet loaded or is currently being loaded. This result may be used with "<a href="#!/if">If</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the action will check if at least one URL has been loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action does not require allow cache as it uses a separate list of loaded URLs. URLs are added to this list after the corresponding request is completed.</div>
      <div class="tr tooltip-paragraph-fold">The list of loaded URLs can be cleared using the "<a href="#!/cleardata">Clear Cached Data</a>" action.</div>
      <div class="tr tooltip-paragraph-last-fold">To wait for a URL to load, use the "<a href="#!/waitload">Wait Url Loaded</a>" action from the "<b>Waiters</b>" module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
  
  <script type="text/template" id="getfromcache">
    <div class="container-fluid getfromcache">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting a specific cached request based on its address. They enable you to precisely specify which URL's latest cached response should be retrieved. If no filters are set, the latest cache item for any URL matching the selected request type will be returned.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Get cache item with any HTTP request type")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request for which to get a cache item. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to get a cache item of any type."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Get cache item with any HTTP request type")}]}}) %>
        <%= _.template($('#checkbox').html())({id:"waitItem", checked: true, title: tr("Wait for cache item"), help: {title: tr("Wait for cache item"), description: tr("If activated and the required cache item is missing, the action will wait for it to appear."), examples: [{code: tr("Activated"), description: tr("Wait for the item if it's absent")}, {code: tr("Deactivated"), description: tr("Return an empty string if the item is absent")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_CACHE", help: {description: tr("Variable in which, after the successful execution of the action, the retrieved data will be written.")}}) %>
      <%= _.template($('#checkbox').html())({id:"Check", title: tr("Encode in base64"), help: {title: tr("Encode in base64"), description: tr("If activated, then the retrieved data will not be decoded and will be stored in base64 string format. This is necessary for proper handling of binary files (e.g., audio, images, or video) that are not intended for text interpretation."), examples: [{code: tr("Activated"), description: tr("Save the retrieved data as a base64 string")}, {code: tr("Deactivated"), description: tr("Decode the retrieved data and save as a UTF-8 string")}]}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", disable_int:true}) %>
      </div>

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get the latest cache item for a URL that matches the specified filters.</div>
      <div class="tr tooltip-paragraph-fold">This action won't work by itself. In order to obtain cache items, you need to use "<a href="#!/cachemaskallow">Allow cache</a>" action first, it will specify pages, that will be cached. Then you need to load page, or do actions in browser, which will trigger page load, like inputting text or clicking mouse. Only after executing "<a href="#!/cachemaskallow">Allow cache</a>" and page is loaded, you can use this action to obtain cache values.</div>
      <div class="tr tooltip-paragraph-fold">Try not to allow caching of all requests in the "<a href="#!/cachemaskallow">Allow cache</a>" action. Instead, specify the most detailed filters possible to reduce the amount of cached data. Adding item to cache is resource consuming task, by limiting number of cache items you can optimize your script.</div>
      <div class="tr tooltip-paragraph-fold">This action retrieves the last cache item that matches the specified filters and selected request type, and stores the request response data in the specified variable.</div>
      <div class="tr tooltip-paragraph-fold">For proper handling of binary data, activate the "<b>Encode in base64</b>" parameter. In this case, the data will be stored as a base64 string.</div>
      <div class="tr tooltip-paragraph-fold">You can save the resulting base64 string to a file using the "<a href="#!/filesystem_writefile">Write File</a>" action from the "<b>Filesystem</b>" module by activating the corresponding parameter there.</div>
      <div class="tr tooltip-paragraph-fold">If the retrieved data is an image, you can use this base64 string in the "<a href="#!/solvecaptcha">Solve Captcha</a>" action or in the "<b>Image processing</b>" module.</div>
      <div class="tr tooltip-paragraph-fold">By default, if the required item is not in the cache, the action will wait for it to appear. You can disable this behavior by deactivating the corresponding parameter in the additional settings.</div>
      <div class="tr tooltip-paragraph-fold">You can change the maximum waiting time by clicking the hourglass icon next to the "<b>Cancel</b>" button.</div>
      <div class="tr tooltip-paragraph-fold">If waiting is enabled but the item does not appear within the specified time, the action will end with an error, which can be handled using the "<a href="#!/ignoreerrors">Ignore Errors</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">If waiting is disabled and the required item is not found, the action will return an empty string.</div>
      <div class="tr tooltip-paragraph-last-fold">By using the "<a href="#!/getallcache">Get all items from cache</a>" action, you can retrieve a list of all cache items. This list will include the complete request data, not just the response data.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_timeout: true, visible:true}) %>
  </script>

  <script type="text/template" id="getallcache">
    <div class="container-fluid getallcache">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to define conditions for selecting cached requests based on their address. These filters provide flexibility in retrieving cache entries by enabling you to specify exactly which URLs should have their cached data retrieved. If no filters are set, all cache items matching the selected request type will be retrieved.")}}) %>
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Get cache items with any types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request for which to get a cache items. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to get cache items of any type."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Get cache items with any types of HTTP requests")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "CACHE_LIST", help: {description: tr("This variable will contain list of cache items. Each cache item is object with information about request and response headers, received data, status, etc.")}}) %>
      <div style="display:none">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Match"), default_selector: "string", value_string: "*", disable_int:true, help: {description: tr("An url, cache for which you want to obtain. Url can contain * symbol, which will be replaced by any symbol sequence."), examples:[{code:"*",description:tr("Get all cache")},{code:"*url/part*",description:tr("Get cache for urls, which contain url/part")},{code:"http://site.com/script.js",description:tr("Get cache for specific url")}]}}) %>
      </div>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get all cache items for a URL that matches the specified filters.</div>
      <div class="tr tooltip-paragraph-fold">This action won't work by itself. In order to obtain cache items, you need to use "<a href="#!/cachemaskallow">Allow cache</a>" action first, it will specify pages, that will be cached. Then you need to load page, or do actions in browser, which will trigger page load, like inputting text or clicking mouse. Only after executing "<a href="#!/cachemaskallow">Allow cache</a>" and page is loaded, you can use this action to obtain cache values.</div>
      <div class="tr tooltip-paragraph-fold">Try not to allow caching of all requests in the "<a href="#!/cachemaskallow">Allow cache</a>" action. Instead, specify the most detailed filters possible to reduce the amount of cached data. Adding item to cache is resource consuming task, by limiting number of cache items you can optimize your script.</div>
      <div class="tr tooltip-paragraph-fold">This action retrieves all cache items that match the specified filters and the selected request type, and saves their list in the specified variable.</div>
      <div class="tr tooltip-paragraph-fold">The resulting list can be processed using actions from the "<b>List</b>" module.</div>
      <div class="tr tooltip-paragraph-fold">If you only need to retrieve the response data of the last cache item, use the "<a href="#!/getfromcache">Get last item from cache</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">Each cache item is an object with following properties:</div>
      <div class="tr tooltip-paragraph-fold"><b>status</b> - integer, contains HTTP request status.</div>
      <div class="tr tooltip-paragraph-fold"><b>request_headers</b> - list with request headers sent by browser.</div>
      <div class="tr tooltip-paragraph-fold"><b>response_headers</b> - list with response headers received from server.</div>
      <div class="tr tooltip-paragraph-fold"><b>body</b> - response body encoded with base64 encoding. Use "<a href="#!/base64">Base64 encode/decode</a>" to decode it.</div>
      <div class="tr tooltip-paragraph-fold"><b>url</b> - request url.</div>
      <div class="tr tooltip-paragraph-fold"><b>method</b> - request type.</div>
      <div class="tr tooltip-paragraph-fold"><b>post_data</b> - request post data encoded with base64.</div>
      <div class="tr tooltip-paragraph-fold"><b>is_error</b> - boolean value, indicates if there were error during request.</div>
      <div class="tr tooltip-paragraph-fold"><b>error</b> - error code as string.</div>
      <div class="tr tooltip-paragraph-fold"><b>is_finished</b> - boolean value, indicates, if request was finished.</div>
      <div class="tr tooltip-paragraph-last-fold">To retrieve the values you need from a cache item, use the actions from the "<b>JSON</b>" module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="redirectrequests">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to set conditions for determining to which requests the URL replacement will be applied. These filters provide flexibility in processing requests, enabling you to specify exactly for which URLs the replacement will be performed based on the specified conditions.") + " " + tr("If no filters are set, the replacement will be applied to all requests that match the selected type.")}}) %>

      <%= _.template($('#block_start').html())({id: "replaceMode_block", name: tr("Replace mode"), description: tr("")}) %>

        <span id="replaceExact_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces an exact match of the specified value with the new value.")}) %>
        </span>

        <span id="replaceRegexp_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces URL content based on the specified regular expression.")}) %>
        </span>

        <span id="replaceAll_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Completely replaces the request URL with the new value.")}) %>
        </span>

        <span id="insertBefore_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value before the specified value if found.")}) %>
        </span>

        <span id="insertAfter_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value after the specified value if found.")}) %>
        </span>

        <span id="replaceBetween_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces the content between two specified values if both are found.")}) %>
        </span>

        <%= _.template($('#combobox').html())({
          id: "replaceMode",
          items: [
            { value: "exact", name: tr("Replace exact value"), title: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
            { value: "regexp", name: tr("Replace with regex"), title: tr("If selected, the replacement will be performed based on the specified regular expression.") },
            { value: "all", selected: true, name: tr("Replace completely"), title: tr("If selected, the entire request URL will be completely replaced with the new value.") },
            { value: "before", name: tr("Insert before"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
            { value: "after", name: tr("Insert after"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
            { value: "between", name: tr("Replace between"), title: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
          ],
          help: {
            title: tr("Replace mode"),
            description: tr("Defines the method of replacing the URL in the browser request."),
            examples: [
              { code: tr("Replace exact value"), description: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
              { code: tr("Replace with regex"), description: tr("If selected, the replacement will be performed based on the specified regular expression.") },
              { code: tr("Replace completely"), description: tr("If selected, the entire request URL will be completely replaced with the new value.") },
              { code: tr("Insert before"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
              { code: tr("Insert after"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
              { code: tr("Replace between"), description: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
            ]
          }
        }) %>

      <%= _.template($('#block_end').html())() %>

      <span id="replaceExact">
        <%= _.template($('#input_constructor').html())({id:"exact", description:tr("Exact value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The exact value that needs to be replaced."), examples: [{"code":"https://example.com/login"},{"code":"/api/v1/orders/12345"},{"code":"?status=pending&user_id=789"},{"code":"/shop/product?id=567"}]}}) %>
        <%= _.template($('#checkbox').html())({id:"replaceAllExact", title: tr("Replace all matches"), help: {title: tr("Replace all matches"), description: tr("If activated, all occurrences of the exact value will be replaced."), examples: [{code: tr("Activated"), description: tr("Replace all occurrences of the exact value")}, {code: tr("Deactivated"), description: tr("Replace only the first occurrence of the exact value")}]}}) %>
      </span>

      <span id="replaceRegexp">
        <%= _.template($('#input_constructor').html())({id:"regexp", description:tr("Regular expression"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The regular expression that will be used for replacement. It supports both regular and named groups, allowing for flexible pattern matching in complex operations."), examples: [{"code":"https?:\\\\/\\\\/example\\.com\\\\/login"},{"code":"\\\\/api\\\\/v1\\\\/users\\\\/\\d+"},{"code":"\\\\/products\\\\/(\\d+)\\\\/details"},{"code":"\\\\/users\\\\/(?&lt;userId&gt;\\d+)\\\\/orders\\\\/(?&lt;orderId&gt;\\d+)"}]}}) %>
        <%= _.template($('#block_start').html())({id: "RegexpFlags", name: tr("Regex flags"), description: tr("")}) %>
          <%= _.template($('#input_constructor').html())({id:"ignoreСase", description:tr("Ignore case"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Ignore case sensitivity during the replacement")}, {value:"disable", description:tr("Consider case sensitivity during the replacement")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will ignore case sensitivity during the replacement."), examples: [{code: "enable", description: tr("Ignore case sensitivity during the replacement")}, {code: "disable", description: tr("Consider case sensitivity during the replacement")}]}}) %>
          <%= _.template($('#input_constructor').html())({id:"globalSearch", description:tr("Global search"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Replace all matching occurrences")}, {value:"disable", description:tr("Replace only the first matching occurrence")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will replace all matching occurrences."), examples: [{code: "enable", description: tr("Replace all matching occurrences")}, {code: "disable", description: tr("Replace only the first matching occurrence")}]}}) %>
        <%= _.template($('#block_end').html())() %>
      </span>

      <span id="insertBefore">
        <%= _.template($('#input_constructor').html())({id:"before", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value before which the new value needs to be inserted."), examples: [{"code":"?user_id="},{"code":"/products/"},{"code":"&category="}]}}) %>
      </span>

      <span id="insertAfter">
        <%= _.template($('#input_constructor').html())({id:"after", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value after which the new value needs to be inserted."), examples: [{"code":"/details"},{"code":"&page="},{"code":"?session_id="}]}}) %>
      </span>

      <span id="replaceBetween">
        <%= _.template($('#input_constructor').html())({id:"leftValue", description:tr("Left value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value located before the content that needs to be replaced."), examples: [{"code":"/start/"},{"code":"?page="},{"code":"&token="},{"code":"?from="}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"rightValue", description:tr("Right value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value positioned after the content that needs to be replaced."), examples: [{"code":"/end/"},{"code":"&sort="},{"code":"&user="},{"code":"&to="}]}}) %>
      </span>

      <%= _.template($('#input_constructor').html())({id:"newValue", description:tr("Replace to"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The new value that will be used for the replacement. If the replacement is done using a regular expression, both regular and named groups from the specified regular expression can be used in this value."), examples: [{"code":"https://new-example.com/home"},{"code":"/api/v2/users/$&"},{"code":"/new-products/$1/info"},{"code":"/clients/${userId}/purchases/${orderId}/summary"}]}}) %>

      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Applies the replacement to all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request to which the replacement should be applied. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to apply the replacement to all request types."), examples:[{code:"GET"},{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Applies the replacement to all types of HTTP requests")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"limit", description:tr("Number of actuations"), default_selector:"int", disable_string:true, value_number:0, min_number:0, help: {description: tr("The maximum number of requests for which the replacement will be applied.") + " " + tr("If not specified or set to zero, there will be no limit."), examples: [{code:2},{code:5},{code:0,description:tr("Don't limit the number of actuations")},{code:tr("Empty value"),description:tr("Don't limit the number of actuations")}]}}) %>
      <%= _.template($('#block_end').html())() %>

      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_REQUEST_REDIRECT", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created replacement function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"REQREDIR_1524510148"},{code:"REQREDIR_421979050"},{code:"REQREDIR_353397414"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Replace the browser request URL with another URL.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a replacement function that will partially or fully replace the URL of browser requests that match the specified filters and request type, using the provided replacement parameters.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will be applied to all requests matching the selected type.</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-fold">In additional settings, you can set a limit on the number of function executions.</div>
      <div class="tr tooltip-paragraph-last-fold">This function modifies the request URL before it is sent, ensuring that the change is invisible on the page—meaning the original URL will remain in the address bar and cache.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
    <script>
      		$(document).ready(function(){
            setTimeout(function(){
              let changeReplaceMode = function(e){
                let replaceMode = $('#replaceMode').val();
                $('#replaceExact, #replaceExact_info').toggle(replaceMode == "exact");
                $('#replaceRegexp, #replaceRegexp_info').toggle(replaceMode == "regexp");
                $('#replaceAll_info').toggle(replaceMode == "all");
                $('#insertBefore, #insertBefore_info').toggle(replaceMode == "before");
                $('#insertAfter, #insertAfter_info').toggle(replaceMode == "after");
                $('#replaceBetween, #replaceBetween_info').toggle(replaceMode == "between");
              };
              
              $('#replaceMode').on('change', changeReplaceMode);
              
              changeReplaceMode();
            }, 0);
          });
    </script>
  </script>

  <script type="text/template" id="replacerequestcontent">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to set conditions for determining to which requests the content replacement will be applied. These filters provide flexibility in processing requests, enabling you to specify exactly for which URLs the content replacement will be performed based on the specified conditions.") + " " + tr("If no filters are set, the replacement will be applied to all requests that match the selected type.")}}) %>

      <%= _.template($('#filter').html())({id:"contentFilters", name:tr("Filters for content"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("Request content filters allow you to set conditions for determining to which requests the content modification will be applied. These filters provide flexibility in processing requests, enabling you to specify exactly which requests will be modified based on the specified conditions.") + " " + tr("If no filters are set, the replacement will be applied to all requests that match the selected type.")}}) %>

      <%= _.template($('#block_start').html())({id: "replaceMode_block", name: tr("Replace mode"), description: tr("")}) %>

        <span id="replaceExact_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces an exact match of the specified value with the new value.")}) %></span>

        <span id="replaceRegexp_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces content based on the specified regular expression.")}) %></span>

        <span id="replaceAll_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Completely replaces the content of the request with the new value.")}) %>
        </span>

        <span id="insertBefore_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value before the specified value if found.")}) %></span>

        <span id="insertAfter_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value after the specified value if found.")}) %></span>

        <span id="replaceBetween_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces the content between two specified values if both are found.")}) %></span>

        <%= _.template($('#combobox').html())({
          id: "replaceMode",
          items: [
            { value: "exact", name: tr("Replace exact value"), title: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
            { value: "regexp", name: tr("Replace with regex"), title: tr("If selected, the replacement will be performed based on the specified regular expression.") },
            { value: "all", selected: true, name: tr("Replace completely"), title: tr("If selected, the entire content of the request will be completely replaced with the new value.") },
            { value: "before", name: tr("Insert before"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
            { value: "after", name: tr("Insert after"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
            { value: "between", name: tr("Replace between"), title: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
          ],
          help: {
            title: tr("Replace mode"),
            description: tr("Defines the method of replacing the content in the request body."),
            examples: [
              { code: tr("Replace exact value"), description: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
              { code: tr("Replace with regex"), description: tr("If selected, the replacement will be performed based on the specified regular expression.") },
              { code: tr("Replace completely"), description: tr("If selected, the entire content of the request will be completely replaced with the new value.") },
              { code: tr("Insert before"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
              { code: tr("Insert after"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
              { code: tr("Replace between"), description: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
            ]
          }
        }) %>

      <%= _.template($('#block_end').html())() %>

      <span id="replaceExact">
        <%= _.template($('#input_constructor').html())({id:"exact", description:tr("Exact value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The exact value that needs to be replaced."), examples: [{"code":"{\"username\":\"guest\"}"},{"code":"order_status=processing"},{"code":"\"session_token\":\"abcdef12345\""},{"code":"shipping_address=123_Main_St"}]}}) %>
        <%= _.template($('#checkbox').html())({id:"replaceAllExact", title: tr("Replace all matches"), help: {title: tr("Replace all matches"), description: tr("If activated, all occurrences of the exact value will be replaced."), examples: [{code: tr("Activated"), description: tr("Replace all occurrences of the exact value")}, {code: tr("Deactivated"), description: tr("Replace only the first occurrence of the exact value")}]}}) %>
      </span>

      <span id="replaceRegexp">
        <%= _.template($('#input_constructor').html())({id:"regexp", description:tr("Regular expression"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The regular expression that will be used for replacement. It supports both regular and named groups, allowing for flexible pattern matching in complex operations."), examples: [{"code":"\"username\":\"john_doe\""},{"code":"\"order_id\":\\d+"},{"code":"\"quantity\":\"(\\d+)\""},{"code":"\"price\":\"(?&lt;price&gt;\\d+\\.\\d{2})\""}]}}) %>
        <%= _.template($('#block_start').html())({id: "RegexpFlags", name: tr("Regex flags"), description: tr("")}) %>
          <%= _.template($('#input_constructor').html())({id:"ignoreСase", description:tr("Ignore case"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Ignore case sensitivity during the replacement")}, {value:"disable", description:tr("Consider case sensitivity during the replacement")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will ignore case sensitivity during the replacement."), examples: [{code: "enable", description: tr("Ignore case sensitivity during the replacement")}, {code: "disable", description: tr("Consider case sensitivity during the replacement")}]}}) %>
          <%= _.template($('#input_constructor').html())({id:"globalSearch", description:tr("Global search"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Replace all matching occurrences")}, {value:"disable", description:tr("Replace only the first matching occurrence")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will replace all matching occurrences."), examples: [{code: "enable", description: tr("Replace all matching occurrences")}, {code: "disable", description: tr("Replace only the first matching occurrence")}]}}) %>
          <%= _.template($('#input_constructor').html())({id:"multiline", description:tr("Multiline mode"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Enable multiline mode for regular expression")}, {value:"disable", description:tr("Disable multiline mode for regular expression")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will treat the content as multiple lines, allowing the start (^) and end ($) anchors to match the start and end of each line, rather than the entire content."), examples: [{code: "enable", description: tr("Enable multiline mode for regular expression")}, {code: "disable", description: tr("Disable multiline mode for regular expression")}]}}) %>
        <%= _.template($('#block_end').html())() %>
      </span>

      <span id="insertBefore">
        <%= _.template($('#input_constructor').html())({id:"before", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value before which the new value needs to be inserted."), examples: [{"code":"user_id="},{"code":"\"order\":\u007b\"id\":"},{"code":"data=\u007b"}]}}) %>
      </span>

      <span id="insertAfter">
        <%= _.template($('#input_constructor').html())({id:"after", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value after which the new value needs to be inserted."), examples: [{"code":"&order_id="},{"code":",\"timestamp\":"},{"code":"&confirmation="}]}}) %>
      </span>

      <span id="replaceBetween">
        <%= _.template($('#input_constructor').html())({id:"leftValue", description:tr("Left value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value located before the content that needs to be replaced."), examples: [{"code":"\"start_time\":\""},{"code":"user_id="},{"code":"\"action\":\""},{"code":"\"session_token\":\""}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"rightValue", description:tr("Right value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value positioned after the content that needs to be replaced."), examples: [{"code":"\",\"end_time\":\""},{"code":"&session_token="},{"code":"\",\"data\":\""},{"code":"\",\"expires\""}]}}) %>
      </span>

      <%= _.template($('#input_constructor').html())({id:"newValue", description:tr("Replace to"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The new value that will be used for the replacement. If the replacement is done using a regular expression, both regular and named groups from the specified regular expression can be used in this value."), examples: [{"code":"\"username\":\"jane_doe\""},{"code":"\"order_id\":54321"},{"code":"\"quantity\":\"$1\""},{"code":"\"price\":\"${price}\",\"discount\":\"10%\""}]}}) %>

      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Applies the replacement to all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request to which the replacement should be applied. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to apply the replacement to all request types."), examples:[{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Applies the replacement to all types of HTTP requests")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"limit", description:tr("Number of actuations"), default_selector:"int", disable_string:true, value_number:0, min_number:0, help: {description: tr("The maximum number of requests for which the replacement will be applied.") + " " + tr("If not specified or set to zero, there will be no limit."), examples: [{code:2},{code:5},{code:0,description:tr("Don't limit the number of actuations")},{code:tr("Empty value"),description:tr("Don't limit the number of actuations")}]}}) %>
      <%= _.template($('#block_end').html())() %>

      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_REQUEST_MODIFY", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created replacement function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"REQMOD_1161135056"},{code:"REQMOD_1515773787"},{code:"REQMOD_976271484"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Replace the contents of the browser request.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a replacement function that will partially or fully replace the content of browser requests that match the specified filters and request type, using the provided replacement parameters.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will be applied to all requests matching the selected type.</div>
      <div class="tr tooltip-paragraph-fold">This function also updates the "<b>content-length</b>" header when modifying the content to ensure it matches the new data.</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-fold">In additional settings, you can set a limit on the number of function executions.</div>
      <div class="tr tooltip-paragraph-last-fold">This function modifies the content of the request before it is sent, while the original value remains in the cache.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
    <script>
      		$(document).ready(function(){
            setTimeout(function(){
              let changeReplaceMode = function(e){
                let replaceMode = $('#replaceMode').val();
                $('#replaceExact, #replaceExact_info').toggle(replaceMode == "exact");
                $('#replaceRegexp, #replaceRegexp_info').toggle(replaceMode == "regexp");
                $('#replaceAll_info').toggle(replaceMode == "all");
                $('#insertBefore, #insertBefore_info').toggle(replaceMode == "before");
                $('#insertAfter, #insertAfter_info').toggle(replaceMode == "after");
                $('#replaceBetween, #replaceBetween_info').toggle(replaceMode == "between");
              };
              
              $('#replaceMode').on('change', changeReplaceMode);
              
              changeReplaceMode();
            }, 0);
          });
    </script>
  </script>

  <script type="text/template" id="replaceresponsecontent">
    <div class="container-fluid">
      <%= _.template($('#filter').html())({id:"urlFilters", name:tr("Filters for URL"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("URL filters allow you to set conditions for determining to which requests the content replacement in the server response will be applied. These filters provide flexibility in processing requests, enabling you to specify exactly for which URLs the content replacement in the server response will be performed based on the specified conditions.") + " " + tr("If no filters are set, the replacement will be applied to all requests that match the selected type.")}}) %>

      <%= _.template($('#filter').html())({id:"contentFilters", name:tr("Filters for content"), hide: true, or_select:true, scheme: {match_select: true, types: ['Equals', 'Starts', 'Ends', 'Contains', 'List', 'Mask', 'Regexp']}, help: {description: tr("Content filters allow you to define conditions for determining to which server responses the content replacement will be applied. These filters provide flexibility in processing requests, enabling you to specify exactly which server responses will have their content replaced based on the specified conditions.") + " " + tr("If no filters are set, the replacement will be applied to all requests that match the selected type.")}}) %>

      <%= _.template($('#block_start').html())({id: "replaceMode_block", name: tr("Replace mode"), description: tr("")}) %>

        <span id="replaceExact_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces an exact match of the specified value with the new value.")}) %>
        </span>

        <span id="replaceRegexp_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces content based on the specified regular expression.")}) %>
        </span>

        <span id="replaceAll_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Completely replaces the content of the server response with the new value.")}) %>
        </span>

        <span id="insertBefore_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value before the specified value if found.")}) %>
        </span>

        <span id="insertAfter_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Inserts the new value after the specified value if found.")}) %>
        </span>

        <span id="replaceBetween_info">
          <%= _.template($('#info').html())({color:"gray", description:tr("Replaces the content between two specified values if both are found.")}) %>
        </span>

        <%= _.template($('#combobox').html())({
          id: "replaceMode",
          items: [
            { value: "exact", name: tr("Replace exact value"), title: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
            { value: "regexp", name: tr("Replace with regex"), title: tr("If selected, the replacement will be performed based on the specified regular expression.") },
            { value: "all", selected: true, name: tr("Replace completely"), title: tr("If selected, the entire content of the server's response to the browser request will be completely replaced with the new value.") },
            { value: "before", name: tr("Insert before"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
            { value: "after", name: tr("Insert after"), title: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
            { value: "between", name: tr("Replace between"), title: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
          ],
          help: {
            title: tr("Replace mode"),
            description: tr("Defines the method of replacing content in the server response to the browser request."),
            examples: [
              { code: tr("Replace exact value"), description: tr("If selected, an exact match of the specified value will be searched for, and if found, it will be replaced with the new value.") },
              { code: tr("Replace with regex"), description: tr("If selected, the replacement will be performed based on the specified regular expression.") },
              { code: tr("Replace completely"), description: tr("If selected, the entire content of the server's response to the browser request will be completely replaced with the new value.") },
              { code: tr("Insert before"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted before it.") },
              { code: tr("Insert after"), description: tr("If selected, an exact match with the specified value will be searched for, and if found, the new value will be inserted after it.") },
              { code: tr("Replace between"), description: tr("If selected, an exact match of the two specified values will be searched for. If both values are found, the content between them will be replaced with the new value.") }
            ]
          }
        }) %>

      <%= _.template($('#block_end').html())() %>

      <span id="replaceExact">
        <%= _.template($('#input_constructor').html())({id:"exact", description:tr("Exact value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The exact value that needs to be replaced."), examples: [{"code":"username=guest"},{"code":"{\"action\":\"logout\",\"user\":\"john_doe\"}"},{"code":"session_id=abc123"},{"code":"&lt;div class=\"status\"&gt;active&lt;/div&gt;"}]}}) %>
        <%= _.template($('#checkbox').html())({id:"replaceAllExact", title: tr("Replace all matches"), help: {title: tr("Replace all matches"), description: tr("If activated, all occurrences of the exact value will be replaced."), examples: [{code: tr("Activated"), description: tr("Replace all occurrences of the exact value")}, {code: tr("Deactivated"), description: tr("Replace only the first occurrence of the exact value")}]}}) %>
      </span>

      <span id="replaceRegexp">
        <%= _.template($('#input_constructor').html())({id:"regexp", description:tr("Regular expression"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The regular expression that will be used for replacement. It supports both regular and named groups, allowing for flexible pattern matching in complex operations."), examples: [{"code":"\"status\":\"pending\""},{"code":"\"session_id\":\"[A-Za-z0-9]+\""},{"code":"total_price=(\\d+\\.\\d{2})"},{"code":"&lt;div class=\"order_id\"&gt;Order ID: (?&lt;orderId&gt;[A-Z0-9]+)&lt;/div&gt;"}]}}) %>
        <%= _.template($('#block_start').html())({id: "RegexpFlags", name: tr("Regex flags"), description: tr("")}) %>
          <%= _.template($('#input_constructor').html())({id:"ignoreСase", description:tr("Ignore case"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Ignore case sensitivity during the replacement")}, {value:"disable", description:tr("Consider case sensitivity during the replacement")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will ignore case sensitivity during the replacement."), examples: [{code: "enable", description: tr("Ignore case sensitivity during the replacement")}, {code: "disable", description: tr("Consider case sensitivity during the replacement")}]}}) %>
          <%= _.template($('#input_constructor').html())({id:"globalSearch", description:tr("Global search"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Replace all matching occurrences")}, {value:"disable", description:tr("Replace only the first matching occurrence")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will replace all matching occurrences."), examples: [{code: "enable", description: tr("Replace all matching occurrences")}, {code: "disable", description: tr("Replace only the first matching occurrence")}]}}) %>
          <%= _.template($('#input_constructor').html())({id:"multiline", description:tr("Multiline mode"), default_selector:"string", disable_int:true, value_string:"disable", variants:[{value:"enable", description:tr("Enable multiline mode for regular expression")}, {value:"disable", description:tr("Disable multiline mode for regular expression")}], help: {description: tr("If \"<b>enable</b>\" is selected, the regular expression will treat the content as multiple lines, allowing the start (^) and end ($) anchors to match the start and end of each line, rather than the entire content."), examples: [{code: "enable", description: tr("Enable multiline mode for regular expression")}, {code: "disable", description: tr("Disable multiline mode for regular expression")}]}}) %>
        <%= _.template($('#block_end').html())() %>
      </span>

      <span id="insertBefore">
        <%= _.template($('#input_constructor').html())({id:"before", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value before which the new value needs to be inserted."), examples: [{"code":"data="},{"code":"\"session_id\":\""},{"code":"\"order\":\u007b"}]}}) %>
      </span>

      <span id="insertAfter">
        <%= _.template($('#input_constructor').html())({id:"after", description:tr("Value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value after which the new value needs to be inserted."), examples: [{"code":"&total="},{"code":"\"timestamp\":"},{"code":"&confirmation="}]}}) %>
      </span>

      <span id="replaceBetween">
        <%= _.template($('#input_constructor').html())({id:"leftValue", description:tr("Left value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value located before the content that needs to be replaced."), examples: [{"code":"\"start_time\":\""},{"code":"order_id="},{"code":"\"token\":\""},{"code":"&lt;div class=\"info\"&gt;"}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"rightValue", description:tr("Right value"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The value positioned after the content that needs to be replaced."), examples: [{"code":"\",\"end_time\":\""},{"code":"&status="},{"code":"\",\"expires\""},{"code":"&lt;/div&gt;"}]}}) %>
      </span>

      <%= _.template($('#input_constructor').html())({id:"newValue", description:tr("Replace to"), default_selector:"string", disable_int:true, value_string:"", help: {description: tr("The new value that will be used for the replacement. If the replacement is done using a regular expression, both regular and named groups from the specified regular expression can be used in this value."), examples: [{"code":"\"status\":\"completed\""},{"code":"\"session_id\":\"newSession12345\""},{"code":"total_price=$1"},{"code":"&lt;div class=\"order_summary\"&gt;Order ID: ${orderId}, Status: Completed&lt;/div&gt;"}]}}) %>

      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"methods", description:tr("Request type"), default_selector:"string", disable_int: true, variants: [{value:"ALL", description:tr("Applies the replacement to all types of HTTP requests")},"GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"], value_string: "ALL", help: {description: tr("The type of HTTP request to which the replacement should be applied. You can specify multiple types as a list or a comma-separated string, or use the string \"<b>ALL</b>\" to apply the replacement to all request types."), examples:[{code:"GET"},{code:"POST"},{code:"PUT"},{code:"PUT, POST"},{code:"ALL",description:tr("Applies the replacement to all types of HTTP requests")}]}}) %>
        <%= _.template($('#input_constructor').html())({id:"limit", description:tr("Number of actuations"), default_selector:"int", disable_string:true, value_number:0, min_number:0, help: {description: tr("The maximum number of requests for which the replacement will be applied.") + " " + tr("If not specified or set to zero, there will be no limit."), examples: [{code:2},{code:5},{code:0,description:tr("Don't limit the number of actuations")},{code:tr("Empty value"),description:tr("Don't limit the number of actuations")}]}}) %>
      <%= _.template($('#block_end').html())() %>

      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Replacement ID"), default_variable: "REPLACEMENT_ID_RESPONSE_MODIFY", help: {description: tr("Variable in which, after successful execution of the action, the ID of the created replacement function will be written. Using this ID, you can stop the function or get its statistics."), examples:[{code:"RESPMOD_611904972"},{code:"RESPMOD_2033805619"},{code:"RESPMOD_61718335"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Replace the contents of the server response to a browser request.</div>
      <div class="tr tooltip-paragraph-fold">This action creates a replacement function that will partially or fully replace the content of server responses to browser requests that match the specified filters and request type, using the provided replacement parameters.</div>
      <div class="tr tooltip-paragraph-fold">If no filters are specified, the function will be applied to all requests matching the selected type.</div>
      <div class="tr tooltip-paragraph-fold">This function also updates the "<b>content-length</b>" header when modifying the content to ensure it matches the new data.</div>
      <div class="tr tooltip-paragraph-fold">The function can be stopped using the replacement ID obtained as a result of executing this action in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
      <div class="tr tooltip-paragraph-fold">This replacement ID can also be used in the "<a href="#!/getrulestats">Get replacement stats</a>" action to retrieve the function's execution statistics.</div>
      <div class="tr tooltip-paragraph-fold">In additional settings, you can set a limit on the number of function executions.</div>
      <div class="tr tooltip-paragraph-last-fold">This function modifies the content of the server response before it is sent to the browser, with the modified value being stored in the cache.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
    <script>
      		$(document).ready(function(){
            setTimeout(function(){
              let changeReplaceMode = function(e){
                let replaceMode = $('#replaceMode').val();
                $('#replaceExact, #replaceExact_info').toggle(replaceMode == "exact");
                $('#replaceRegexp, #replaceRegexp_info').toggle(replaceMode == "regexp");
                $('#replaceAll_info').toggle(replaceMode == "all");
                $('#insertBefore, #insertBefore_info').toggle(replaceMode == "before");
                $('#insertAfter, #insertAfter_info').toggle(replaceMode == "after");
                $('#replaceBetween, #replaceBetween_info').toggle(replaceMode == "between");
              };
              
              $('#replaceMode').on('change', changeReplaceMode);
              
              changeReplaceMode();
            }, 0);
          });
    </script>
  </script>

  <script type="text/template" id="disablerules">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"ids", description:tr("Replacement ID"), default_selector: "string", disable_int:true, variants: [{value:"ALL", description:tr("Stop executing all existing replacement and filtering functions")}], value_string: "", help: {description: tr("The ID of the replacement or filtering function that needs to be stopped. You can specify multiple IDs separated by commas or use a list. To stop all existing functions, use the value \"<b>ALL</b>\"."), examples:[{code:"CACHECTRL_873444945"},{code:"REQCTRL_265912258,REQREDIR_360998317"},{code:"[\"REQMOD_432143270\", \"RESPMOD_1016639777\"]"},{code:"ALL",description:tr("Stop executing all existing replacement and filtering functions")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Stop the replacement or filtering function by its ID.</div>
      <div class="tr tooltip-paragraph-fold">This action will completely and permanently stop the specified function created using one of the following actions: "<a href="#!/cachemaskallow">Allow cache</a>", "<a href="#!/cachemaskdeny">Deny cache</a>", "<a href="#!/requestmaskallow">Allow request</a>", "<a href="#!/requestmaskdeny">Deny request</a>", "<a href="#!/redirectrequests">Redirect browser requests</a>", "<a href="#!/replacerequestcontent">Replace request content</a>", or "<a href="#!/replaceresponsecontent">Replace response content</a>".</div>
      <div class="tr tooltip-paragraph-fold">To perform this action, you need the replacement ID obtained as a result of executing one of the actions mentioned above.</div>
      <div class="tr tooltip-paragraph-fold">This action can stop multiple functions at once; for this, a list of IDs must be provided instead of a single ID. You can use a string of IDs separated by commas as a list.</div>
      <div class="tr tooltip-paragraph-fold">By specifying the string "<b>ALL</b>" as the ID, you can stop all existing replacement and filtering functions.</div>
      <div class="tr tooltip-paragraph-fold">Using the "<a href="#!/getrulestats">Get replacement stats</a>" action, you can retrieve a list of all replacement IDs, as well as a separate list of only active replacement IDs.</div>
      <div class="tr tooltip-paragraph-fold">Stopping a function removes all information about it, making it impossible to retrieve its statistics after this action is performed.</div>
      <div class="tr tooltip-paragraph-last-fold">If the function with the specified ID does not exist, this action will do nothing.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="getrulestats">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"id", description:tr("Replacement ID"), default_selector: "string", disable_int:true, value_string: "", help: {description: tr("The ID of the replacement or filtering function for which the execution statistics need to be retrieved."), examples:[{code:"CACHECTRL_873444945"},{code:"REQREDIR_1625622088"},{code:"RESPMOD_360998317"},{code:tr("Empty string"),description:tr("Get only the list of all IDs and the list of active IDs")}]}}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveExecutionCount", description:tr("Number of executions"), default_variable: "REPLACEMENT_EXECUTION_COUNT", help: {description: tr("This variable will contain the number of executions of the specified function."), examples:[{code:2},{code:5},{code:0,description:tr("The specified function has not been executed yet")},{code:-1,description:tr("The replacement ID was not provided, or the function with the specified ID does not exist")}]}}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveIsActive", description:tr("Is active"), default_variable: "REPLACEMENT_IS_ACTIVE", help: {description: tr("This variable will be set to <code>true</code> or <code>false</code> depending on whether the specified function is currently active.") + " " + tr("A function is considered active if its number of executions is below the set maximum or if no execution limit is in place."), examples:[{code:true,description:tr("The function is currently active")},{code:false,description:tr("The replacement ID was not provided, the function with the specified ID does not exist, or it is currently inactive")}]}}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveAllIds", description:tr("List of all replacement IDs"), default_variable: "REPLACEMENT_ALL_IDS_LIST", help: {description: tr("This variable will contain a list of IDs for all existing replacement and filtering functions.") + " " + tr("The resulting list can be processed using actions from the \"<b>List</b>\" module."), examples:[{code:"[\"REQCTRL_873444945\"]"},{code:"[\"REQCTRL_1625622088\", \"REQMOD_265912258\"]"},{code:"[\"REQREDIR_360998317\", \"RESPMOD_1618135638\"]"}]}}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveActiveIds", description:tr("List of active replacement IDs"), default_variable: "REPLACEMENT_ACTIVE_IDS_LIST", help: {description: tr("This variable will contain a list of IDs for only the replacement and filtering functions that are currently active.") + " " + tr("The resulting list can be processed using actions from the \"<b>List</b>\" module."), examples:[{code:"[\"CACHECTRL_1061998576\"]"},{code:"[\"REQREDIR_1847555679\", \"REQMOD_432143270\"]"},{code:"[\"CACHECTRL_1016639777\", \"REQCTRL_2111627593\"]"}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get statistics on the execution of a replacement or filtering function by its ID.</div>
      <div class="tr tooltip-paragraph-fold">This action will retrieve the execution statistics of the specified function, created using one of the following actions: "<a href="#!/cachemaskallow">Allow cache</a>", "<a href="#!/cachemaskdeny">Deny cache</a>", "<a href="#!/requestmaskallow">Allow request</a>", "<a href="#!/requestmaskdeny">Deny request</a>", "<a href="#!/redirectrequests">Redirect browser requests</a>", "<a href="#!/replacerequestcontent">Replace request content</a>", or "<a href="#!/replaceresponsecontent">Replace response content</a>", and save the data into the specified variables.</div>
      <div class="tr tooltip-paragraph-fold">To retrieve the full statistics, you must provide the replacement ID obtained as a result of executing one of the actions mentioned above.</div>
      <div class="tr tooltip-paragraph-fold">If the replacement ID is not provided or a function with the specified ID does not exist, only the list of all replacement IDs and the list of active replacement IDs will be retrieved. The "<b>Number of executions</b>" will be set to <code>-1</code>, and "<b>Is active</b>" will be set to <code>false</code>.</div>
      <div class="tr tooltip-paragraph-last-fold">The retrieved ID lists can be processed using actions from the "<b>List</b>" module or directly used in the "<a href="#!/disablerules">Stop replacement</a>" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="result">
    <div class="container-fluid result">
       <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Result Data"), default_selector: "string", disable_int:true, help: {description: tr("Data. Can contain variables and resources."), examples:[{code:"[[USERNAME]]:[[PASSWORD]]",description:tr("Output created account")},{code:"[[AVATAR_URL]]",description:tr("Output avatar")}]}}) %>

       <%= _.template($('#combobox').html())({id: "Select", title: tr("Result Placeholder"), items: [
        {value: "1", "name": "1", selected: true},
        {value: "2", "name": "2"},
        {value: "3", "name": "3"},
        {value: "4", "name": "4"},
        {value: "5", "name": "5"},
        {value: "6", "name": "6"},
        {value: "7", "name": "7"},
        {value: "8", "name": "8"},
        {value: "9", "name": "9"}
       ]
      }) %>

      
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Output data to the results tab.</div>
      <div class="tr tooltip-paragraph-fold">This action suites best to output raw data, like accounts registered, posts parsed, etc.</div>
      <div class="tr tooltip-paragraph-fold">If you want to write message, with date and thread number, better to use "Log" action.</div>
      <div class="tr tooltip-paragraph-fold">Before running script you can create up to nine tabs for different purposes and give names for them, for example, one for accounts, one for posts, avatars, etc.</div>
      <div class="tr tooltip-paragraph-fold">"Result Placeholder" parameter sets tab number, numeration is starting from from 1.</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">If you want to output data to file only, use this</span> (<span class="tr-en"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=how_to_let_user_to_choose_output_file_name');return false">article</a></span><span class="tr-ru"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=ru:how_to_let_user_to_choose_output_file_name');return false">статью</a></span>)</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_output_script_result"}) %>
  </script>

  <script type="text/template" id="timeout">
    <div class="container-fluid result">
       <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Timeout in milliseconds"), default_selector: "int", disable_string:true, value_number: 60000, min_number: 1000}) %>
       <%= _.template($('#combobox').html())({id: "Type", title: tr("Timeout Type"), items: [
        {value: "general", "name": "General", selected: true},
        {value: "fullpageload", "name": "Full Page Load"},
        {value: "solver", "name": "Solver"},
      ]
      }) %>
    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">BAS limits execution time for every action. No action can last forever except sleep and manual captcha solving, but you can tweak limits.</div>
      <div class="tr tooltip-paragraph-fold">By default execution time for captcha solving in non manual mode is 120 seconds and 60 seconds for every other action.</div>
      <div class="tr tooltip-paragraph-fold">To change maximum captcha solving time run this action with "Solver" timeout type.</div> 
      <div class="tr tooltip-paragraph-fold">Or run this action with "General" timeout type to change maximum execution time for all other actions.</div>
      <div class="tr tooltip-paragraph-last-fold">BAS allows to set timeout for every action individually, to do that click on hourglass icon near cancel button inside action interface.</div>
    </div>


    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

<script type="text/template" id="globalset">
    <div class="container-fluid globalset">
      <%= _.template($('#variable_constructor').html())({id:"Name", description:tr("Variable Name"), default_variable: "", disable_locals: true, enable_globals:true, help: {description: tr("The name of the variable to be created or modified.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Value"), default_selector: "string", help: {description: tr("Variable value"), examples:[{code:"any string",description:tr("Any string will work")},{code:"[[LOGIN]]:[[PASSWORD]]",description:tr("Concat 2 variables")},{code:"10",description:tr("Any number. Works with int type")},{code:"1+1",description:tr("Any javascript code. Works with expression type")}]}}) %>
    </div>
     <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Create new or update existing global variable and set its value.</div>
      <div class="tr tooltip-paragraph-fold">Global variables are availabe during whole script execution in every thread.</div>
      <div class="tr tooltip-paragraph-fold">Global variable name should be in uppercase and should describe its purpose. Naming variable A1 or A2 could make your script very hard to read.</div>
      <div class="tr tooltip-paragraph-fold">You can use that global variable later inside any field by putting variable name into double square brackets like this: [[GLOBAL:NEW_VARIABLE]]. You don't need to type it manually, just click on any field, than on "Insert variable" and finally select specific variable.</div>
      <div class="tr tooltip-paragraph-fold">"Value" parameter by default is a string, but may also contain other variables, like this [[LOGIN]]@gmail.com, or resources. So this action also may concat strings([[PART1]][[PART2]]), update them, etc.</div>
      <div class="tr tooltip-paragraph-fold">By default "Value" parameter is a string, but you can change its type to int, so variable will be number.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Setting type to expression will set variable to result of JavaScript execution. This is very powerful mechanism. For example, to get current timestamp input Date.now() into "Value of variable" parameter</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=gettimestamp.png');return false">screen</a>)</div>

      <div class="tr tooltip-paragraph-fold">You can use JavaScript functions on BAS variables, for example, [[LINE]].split(":")[0] will split string into two pieces and take first.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to set multiline variable, use template action.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="globalget">
    <div class="container-fluid globalget">
      <%= _.template($('#input_constructor').html())({id:"Name", description:tr("Variable Name"), default_selector: "string", disable_int:true, disable_editor:true, disable_resource:true, disable_variable:true}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "GLOBAL_VARIABLE_RESULT"}) %>
    </div>
    <div class="tooltipinternal">Global variables are availabe during whole script run.</div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

<script type="text/template" id="httpclientproxy">
    <div class="container-fluid" >
      <%= _.template($('#input_constructor').html())({id:"ProxyText", description:tr("Proxy String"), default_selector: "string", disable_int:true, help: {description: tr("String with information about proxy. It may contain ip, port, proxy type in different formats. This string may also contain login and password, if it doesn't, auth can be set with \"Proxy Login\" and \"Proxy Password\" parameters."), examples:[{code:"210.10.10.10:1085"},{code:"username:password@210.10.10.10:1085"},{code:"socks5://210.10.10.10:1085"},{code:"socks:210.10.10.10:1085:username:password"},{code:"http:username:password:210.10.10.10:1085"},{code:"{{proxy}}", description: tr("Get from resource")},{code:tr("Empty string"),description:tr("Without proxy")}   ]}}) %>
      <div class="col-xs-12" style="display:none">
        <form class="form-horizontal">
          <div class="form-group">
            <hr style="margin-top:5px;margin-bottom:5px"/>
            <div style="margin-left:15px;"> 
              <table>
                <tr><td>
                  <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://luminati.io/?affiliate=ref_5b2a194821e9e462666c9e6f&cam=L_ofri');return false" class="tr"><img src="luminati.png"/> </a>
                </td><td>

                <span class="tr" style="font-size:small">Try Luminati proxies. <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://luminati.io/?affiliate=ref_5b2a194821e9e462666c9e6f&cam=L_ofri');return false" class="tr">Luminati</a> is world's largest
  proxy network. It offers more than 30 millions of mobile, residental and datacenter IPs which can be filtered over countries, cities, ASN and carriers.</span>
                </td></tr>
              </table>  
            </div>
            <hr style="margin-top:5px;margin-bottom:5px"/>
            
          </div>
        </form>
      </div>
      <%= _.template($('#input_constructor').html())({id:"ProxyType", description:tr("Proxy Type"), default_selector: "string", disable_int:true, value_string: "http", variants: ["http","socks5","auto"], help: {description: tr("socks5 and http proxy types are supported."), examples:[{code:"socks"},{code:"socks5",description:tr("Same as socks")},{code:"http"},{code:"https",description:tr("Same as http")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"ProxyLogin", description:tr("Proxy Login. Can be blank."), default_selector: "string", disable_int:true, help: {description: tr("Proxy login, overrides login set in proxy string. Useful if you have many proxy with same login and password.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ProxyPassword", description:tr("Proxy password. Can be blank."), default_selector: "string", disable_int:true, help: {description: tr("Proxy password, overrides password set in proxy string. Useful if you have many proxy with same login and password.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">By default http client works without proxy, this action sets proxy for http client.</div>
      <div class="tr tooltip-paragraph-fold">Use resources if you want to take them from file, url or database.</div>
      <div class="tr tooltip-paragraph-fold">You can change proxy once and it will be applied to every action which uses http client.</div> 
      <div class="tr tooltip-paragraph-last-fold">Proxy with empty parameter will reset it to default value(direct connection).</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
<script type="text/template" id="httpclientreset">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action will reset http client and all its settings.</div>
      <div class="tr tooltip-paragraph-fold">Use 'HTTP-Client Restore Cookies' action with empty value if you want to reset only cookies.</div>
      
      <div class="tr tooltip-paragraph-last-fold">It affect every setting and state that http client has: proxy, headers, content, status, cookies, etc.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
<script type="text/template" id="httpclientdownload">
    <div class="container-fluid httpclientdownload">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Url"), default_selector: "string", disable_int:true, help: 
        {
          description: tr("Request url"), examples:
          [
            {
              code:"https://google.com",description:tr("Url with scheme")
            },
            {
              code:"google.com",description:tr("Url without scheme")
            },
            {
              code:"https://www.google.com/search?q=cats",description:tr("Url with query string")
            },
            {
              code:"https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B",description:tr("Url with encoded query. To encode string use encodeURIComponent function.")
            }
          ]
        }}) %>
      <%= _.template($('#input_constructor').html())({id:"File", description:tr("File Path"), default_selector: "string", disable_int:true, help: 
{
  description: tr("A path to file which will be downloaded. If file exists, it will be overwritten. Putting here resource with type 'LinesFromFile' is almost always a bad idea, because resource will be converted to line from selected file, not to file name. If you want to get file name from resource, please use 'Resource Location' action and put result here."), examples:
  [
    {
      code:"c:/downloads/pic.png"
    },
    {
      code:"c:\\downloads\\pic.png"
    }
  ]
}
}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Download selected url and save responce to file.</div>
      <div class="tr tooltip-paragraph-fold">If you don't want to save data on disk, you should use 'GET' or 'POST' action.</div>
      <div class="tr tooltip-paragraph-fold">This action uses cookies and headers just like 'GET' and 'POST' actions.</div>
      <div class="tr tooltip-paragraph-fold">Special characters and non-latin query parts must be encoded with encodeURIComponent function. For example, instead of using https://www.google.com/search?q=коты, url must be https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B</div>
      <div class="tr tooltip-paragraph-fold">HTTP headers(like User-Agent) can be specified with 'HTTP-Client Set Header' action.</div>
      <div class="tr tooltip-paragraph-fold">'Download' action will not set any variable, to obtain responce you need to call 'Current Url', 'Status' or 'Get Header' after request is performed. And, of course, specified file will contain responce text.</div>
      <div class="tr tooltip-paragraph-fold">'Current Url' will get actual url after all redirects.</div>
      <div class="tr tooltip-paragraph-fold">'Status' returns HTTP status, for example, 200 - if request is performed correctly, 500 - in case of server error, etc.</div>
      <div class="tr tooltip-paragraph-fold">'Get Header' returns responce header, like 'Content-Type', 'Date', 'Set-Cookie'</div>
      <div class="tr tooltip-paragraph-last-fold">You can set max page loading time by clicking on hourglass icon near cancel button.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true}) %>
  </script>
<script type="text/template" id="httpclientget">
    <div class="container-fluid httpclientget">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Url"), default_selector: "string", disable_int:true, help: 
        {
          description: tr("Request url"), examples:
          [
            {
              code:"https://google.com",description:tr("Url with scheme")
            },
            {
              code:"google.com",description:tr("Url without scheme")
            },
            {
              code:"https://www.google.com/search?q=cats",description:tr("Url with query string")
            },
            {
              code:"https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B",description:tr("Url with encoded query. To encode string use encodeURIComponent function.")
            }
          ]
        }}) %>
      <%= _.template($('#input_constructor').html())({id:"Headers", description:tr("Headers, for example:\nUser-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0\nReferer: google.com"), default_selector: "string", disable_int:true, disable_editor:true, disable_expression:true, use_textarea:true, replace_linebreaks: true, size: 8, disable_type_chooser:true,textarea_height:80}) %>
      <%= _.template($('#input_constructor').html())({id:"Method", description:tr("Method"), default_selector: "string", disable_int:true, value_string: "GET", variants:["GET","HEAD","DELETE","TRACE","OPTIONS"], size:3, help: 
      {
        description: tr("Request method, you can put any string here.")
      }}) %>
      
      <%= _.template($('#checkbox').html())({id: "Check", checked: true, title: tr("Follow redirects")}) %>

    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Make http request using GET, HEAD, DELETE, TRACE or OPTIONS method,  
i.e. methods which don't send data.</div>
      <div class="tr tooltip-paragraph-fold">Special characters and non-latin query parts must be encoded with encodeURIComponent function. For example, instead of using https://www.google.com/search?q=коты, url must be https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B</div>
      <div class="tooltip-paragraph-fold"><span class="tr">If 'Record HTTP request' mode is enabled, then every request that browser does will be converted to actions using http client and added to scenario tab</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=recordhttprequests.png');return false">screen</a> ).</div>
      <div class="tr tooltip-paragraph-fold">HTTP headers(like User-Agent) can be specified in this action with 'Headers' parameter or with 'HTTP-Client Set Header' action. In first case headers will be modified only for current action, in second case headers will be modified for all following actions.</div>
      <div class="tr tooltip-paragraph-fold">By default http client will follow redirects. If you want, you can disable that behavior and process Location header yourself. To get responce header, use 'Get Header' action after request.</div>
      <div class="tr tooltip-paragraph-fold">'Get' action will not set any variable, to obtain responce you need to call 'Current Url', 'Content', 'Status' or 'Get Header' after request is performed.</div>
      <div class="tr tooltip-paragraph-fold">'Current Url' will get actual url after all redirects.</div>
      <div class="tr tooltip-paragraph-fold">'Content' will return page html.</div>
      <div class="tr tooltip-paragraph-fold">'Status' returns HTTP status, for example, 200 - if request is performed correctly, 500 - in case of server error, etc.</div>
      <div class="tr tooltip-paragraph-fold">'Get Header' returns responce header, like 'Content-Type', 'Date', 'Set-Cookie'</div>
      <div class="tr tooltip-paragraph-fold">HTTP client handles cookies automatically, so normally you don't need to process 'Set-Cookie' header.</div>
      <div class="tr tooltip-paragraph-fold">The fastest way to extract data from page source is xpath. 'Http Client' has set of actions to perform xpath queries. It is not recomended to use 'Content' action and regular expressions unless it is absolutely necessary.</div>
      <div class="tr tooltip-paragraph-fold">If server returns json data, use JSON.parse function to parse it.</div>

      <div class="tr tooltip-paragraph-last-fold">You can set max page loading time by clicking on hourglass icon near cancel button.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true, wiki: "how_to_make_get_request"}) %>
  </script>
  <script type="text/template" id="httpclientpost">
    <div class="container-fluid httpclientpost">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Url"), default_selector: "string", disable_int:true, help: 
        {
          description: tr("Request url"), examples:
          [
            {
              code:"https://google.com",description:tr("Url with scheme")
            },
            {
              code:"google.com",description:tr("Url without scheme")
            },
            {
              code:"https://www.google.com/search?q=cats",description:tr("Url with query string")
            },
            {
              code:"https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B",description:tr("Url with encoded query. To encode string use encodeURIComponent function.")
            }
          ]
        }}) %>

      <%= _.template($('#input_constructor').html())({id:"Headers", description:tr("Headers, for example:\nUser-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0\nReferer: google.com"), default_selector: "string", disable_int:true, disable_editor:true, disable_expression:true, use_textarea:true, replace_linebreaks: true, size: 8, disable_type_chooser:true,textarea_height:80}) %>


      <%= _.template($('#checkbox').html())({id: "Check2", title: tr("Post data constructor")}) %>




      <span data-visible-if-checked="Check2">
        <div class="col-xs-12">
         <form class="form-horizontal">
            <div class="form-group">
              <%= _.template($('#input_constructor').html())({id:"PostName", description:tr("Request Parameter Name"), default_selector: "string", disable_int:true, dont_use_top: true, help: 
                {
                  description: tr("Post parameter name. After setting this value you need to add it to 'Post Data' parameter by hitting '+ Add' button.")}
                }) %>
            </div>
          </form>
        </div>

        <div class="col-xs-12">
         <form class="form-horizontal">
            <div class="form-group">
              <%= _.template($('#input_constructor').html())({id:"PostValue", description:tr("Request Parameter Value"), default_selector: "string", disable_int:true, dont_use_top: true, help: 
                {
                  description: tr("Post parameter value. After setting this value you need to add it to 'Post Data' parameter by hitting '+ Add' button.")} }) %>
            </div>
          </form>
        </div>


        <div class="col-xs-12">
         <form class="form-horizontal">
            <div class="form-group">
              <button tabindex="-1" type="button" class="btn btn-default addtopost" > + <span class="tr">Add</span></button>
              <button tabindex="-1" type="button" class="btn btn-default addtopostfile" > + <span class="tr">Add As File</span></button>
              <button tabindex="-1" type="button" class="btn btn-default addtopostbase64" > + <span class="tr">Add As Base64 Data</span></button>
            </div>
          </form>
        </div>

        <%= _.template($('#input_constructor').html())({id:"PostDataArray", description:tr("Post Data"), default_selector: "expression", disable_int:true, disable_string:true, help: 
                {
                  description: tr("To add values into post data list, fill 'Request Parameter Name' and 'Request Parameter Value' and hit '+ Add' button. This list of key value parameters will be sended to server in form, which is defined in 'Content Type' parameter.")}}) %>

        <%= _.template($('#input_constructor').html())({id:"ContentType", description:tr("Content Type"), default_selector: "string", disable_int:true, value_string: "urlencode", variants:["urlencode","multipart","json"], size:3, help: 
{
  description: tr("Content type with 3 options available: urlencode, multipart, json"), examples:
  [
    {
      code:"urlencode",description:tr("Send data as key/value pairs.")
    },
    {
      code:"multipart",description:tr("Send data as key/value pairs. Values may have binary format, can be used to send files.")
    },
    {
      code:"json",description:tr("Send data in json format.")
    }
  ]
}
}) %>      
        
        
      </span>

      <span data-visible-if-unchecked="Check2">
        <%= _.template($('#input_constructor').html())({id:"PostDataRaw", description:tr("Post Data"), default_selector: "string", disable_int:true, disable_editor:true, disable_expression:true, use_textarea:true, replace_linebreaks: true, size: 8, disable_type_chooser:true,textarea_height:80, modal_code_id:"post-data-" + (_K || "en")}) %>
        <%= _.template($('#input_constructor').html())({id:"ContentTypeRaw", description:tr("Content-Type"), default_selector: "string", disable_int:true, value_string: "application/x-www-form-urlencoded", variants:["application/x-www-form-urlencoded","multipart/form-data","application/json"], size:3, help: 
{
  description: tr("'Contect-Type' header. This parameter indicates what type of content is located in 'Post Data' field."), examples:
  [
    {
      code:"application/x-www-form-urlencoded",description:tr("Data contains key/value pairs separated by &(ampersand). For example, key1=value1&key2=value2&key3=value3")
    },
    {
      code:"multipart/form-data",description:tr("Data contains key/value pairs, values may have binary format, can be used to send files. Boundary will be automatically detected from 'Post Data' field.")
    },
    {
      code:"application/json",description:tr("Send data in json format. For example, {\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":\"value3\"}")
    }
  ]
}
}) %>      
      </span>

    <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>

      

      <%= _.template($('#input_constructor').html())({id:"Encoding", description:tr("Encoding"), default_selector: "string", disable_int:true, value_string: "UTF-8", help: 
{
  description: tr("Post data encoding. This parameter determines encoding name which will be used to process post data. This parameter doesn't change Content-Type header, you must do it yourself."), examples:
  [
    {
      code:"UTF-8",description:tr("It is ok for most of cases.")
    },
    {
      code:"WINDOWS-1251",description:tr("Used on some Russian sites.")
    }
  ]
}
}) %>
      
      <%= _.template($('#input_constructor').html())({id:"Method", description:tr("Method"), default_selector: "string", disable_int:true, value_string: "POST", variants:["POST","PUT","PATCH"], size:3, help: 
{
  description: tr("Request method, you can put any string here.")
}}) %>

    <%= _.template($('#block_end').html())() %>

    <%= _.template($('#checkbox').html())({id: "Check", checked: true, title: tr("Follow redirects")}) %>

      

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Make http request using POST, PUT or PATCH method,  
i.e. methods which send data.</div>
      <div class="tr tooltip-paragraph-fold">Post data can be specified in 2 forms: raw(default) and with constructor. It is recommended to use raw form.</div>
      <div class="tr tooltip-paragraph-fold">With raw form you need to input post data as is. This means, that you can get post data from sniffer and put it inside 'Post data' field. Check help for this field, it contains a lot of examples. Another thing, which need to be done is setting up 'Content-Type' parameter, it can be obained as one of request headers. 'Content-Type' parameter indicates what type of content is located in 'Post Data' field, it could be json, form content, etc.</div>
      <div class="tr tooltip-paragraph-fold">Variables and resources may be embedded into 'Post data' field. If you need to put binary data, read it into variable with base64 encoding(for example by reading file in base64) and instead of using [[VARIABLE]] notation, use it with 'base64:' prefix, like this base64:[[VARIABLE]]. 'Post data' help contains more examples.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">If 'Record HTTP request' mode is enabled, then every request that browser does will be converted to actions using http client and added to scenario tab</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=recordhttprequests.png');return false">screen</a> ). <span class="tr">It is the easiest way to generate action with http requests.</span></div>
      <div class="tr tooltip-paragraph-fold">Special characters and non-latin query parts must be encoded with encodeURIComponent function. For example, instead of using https://www.google.com/search?q=коты, url must be https://www.google.com/search?q=%D0%BA%D0%BE%D1%82%D1%8B</div>
      
      <div class="tr tooltip-paragraph-fold">HTTP headers(like User-Agent) can be specified in this action with 'Headers' parameter or with 'HTTP-Client Set Header' action. In first case headers will be modified only for current action, in second case headers will be modified for all following actions.</div>
      <div class="tr tooltip-paragraph-fold">By default http client will follow redirects. If you want, you can disable that behavior and process Location header yourself. To get responce header, use 'Get Header' action after request.</div>
      <div class="tr tooltip-paragraph-fold">'Post' action will not set any variable, to obtain responce you need to call 'Current Url', 'Content', 'Status' or 'Get Header' after request is performed.</div>
      <div class="tr tooltip-paragraph-fold">'Current Url' will get actual url after all redirects.</div>
      <div class="tr tooltip-paragraph-fold">'Content' will return page html.</div>
      <div class="tr tooltip-paragraph-fold">'Status' returns HTTP status, for example, 200 - if request is performed correctly, 500 - in case of server error, etc.</div>
      <div class="tr tooltip-paragraph-fold">'Get Header' returns responce header, like 'Content-Type', 'Date', 'Set-Cookie'</div>
      <div class="tr tooltip-paragraph-fold">HTTP client handles cookies automatically, so normally you don't need to process 'Set-Cookie' header.</div>
      <div class="tr tooltip-paragraph-fold">The fastest way to extract data from page source is xpath. 'Http Client' has set of actions to perform xpath queries. It is not recomended to use 'Content' action and regular expressions unless it is absolutely necessary.</div>
      <div class="tr tooltip-paragraph-fold">If server returns json data, use JSON.parse function to parse it.</div>

      <div class="tr tooltip-paragraph-last-fold">You can set max page loading time by clicking on hourglass icon near cancel button.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd",use_timeout: true, visible:true, wiki: "how_to_make_post_request"}) %>
  </script>

  <script type="text/template" id="post-data-en">
    <div>This field must contain post data in raw form.</div>
    <div>You can take it from http sniffer like Wireshark, Microsoft Network Monitor, Fiddler or Burp ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=copydatafromfiddler.png');return false">screen</a> ).</div>
    <div>Post data can also be generated with 'Record HTTP Requests' mode automatically ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=recordhttprequests.png');return false">screen</a> ).</div>
    <div>After setting post data, don't forget to change 'Content-Type' field accordingly. It indicates what type of content is located in 'Post Data' field.</div>
    <div>Here are some examples for different content types:</div>
    <br/>
    <div>Content-Type: <strong>application/x-www-form-urlencoded</strong></div>
    <div>Data contains key/value pairs separated by &(ampersand). Each key and value must be urlencoded. You can do that by calling encodeURIComponent function.</div>
    <br/>
    <div>Example #1. One key and one value.</div>
    <div><pre>key1=value1</pre></div>
      <br/>
    <div>Example #2. Using variables.</div>
    <div><pre>key1=[[VALUE]]</pre></div>
      <br/>
    <div>Example #3. Several keys and values.</div>
    <div><pre>key1=value1&key2=value2</pre></div>
      <br/>
    <div>Example #4. Escape special symbol.</div>
    <div><pre>email=login%40gmail.com</pre></div>
    <div>You can't use symbol @, need to escape it first, so symbol @ becomes %40</div>
      <br/>

    <div>Content-Type: <strong>multipart/form-data</strong></div>
    <div>Data contains key/value pairs, values may have binary format, can be used to send files. Each key value pair is separated by boundary. Boundary will be automatically detected from 'Post Data' field.</div>
<br/>
    <div>Example #1. One key and one value.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key"; 

value including special symbols and binary data
--randomstringboundary--</pre></div>
      <br/>
    <div>Example #2. Using variables.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key"; 

[[VALUE]]
--randomstringboundary--</pre></div>
      <br/>
    <div>Example #3. Several keys and values.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key1"; 

value1
--randomstringboundary
Content-Disposition: form-data; name="key2"; 

value2
--randomstringboundary--</pre></div>

      <br/>

    <div>Example #4. Upload file.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.txt"
Content-Type: application/octet-stream

FILE CONTENT
--randomstringboundary--</pre></div>

  <br/>


  <div>Variables can be used.</div>

  <div>Example #5. Upload file from variable.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.txt"
Content-Type: application/octet-stream

[[VARIABLE]]
--randomstringboundary--</pre></div>

  <br/>

  <div>If file has binary format, you need to read it in base64 encoding and append 'base64:' before variable.</div>

  <div>Example #6. Upload binary file.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.bin"
Content-Type: application/octet-stream

base64:[[VARIABLE_WITH_BASE64_ENCODING]]
--randomstringboundary--</pre></div>


  <br/>

    <div>Content-Type: <strong>application/json</strong></div>
    <div>Send data in json format.</div>
<br/>
<div>Example #1. Sending static json.</div>
    <div><pre>{
  "key": "value"
}</pre></div>
      <br/>

<div>Example #2. Sending json with variable.</div>
    <div><pre>{
  "key": [[VARIABLE]]
}</pre></div>
      <br/>

  <br/>
  <div>Content-Type: <strong>text/plain</strong></div>
  <div>Upload text type.</div>
  <br/>

  <div>Example #1. Sending text file.</div>
    <div><pre>Text file content</pre></div>
      <br/>

  <div>Content-Type: <strong>application/pdf</strong></div>
    <div>Upload pdf.</div>
    <br/>

  <div>Pdf is binary format. Binary data is stored in base64 encoding. Variable with base64 encoding must contain 'base64' prefix.</div>
  <div>Example #1. Sending binary file.</div>
    <div><pre>base64:[[VARIABLE_WITH_BASE64_ENCODING]]</pre></div>
      <br/>

  <div>Any other valid content types are acceptable.</div>      

  </script>
  <script type="text/template" id="post-data-ru">
        <div>Это поле должно содержать данные запроса в необработанном(сыром) виде.</div>
    <div>Это означает, что вы можете копировать их прямо из http сниффера, такого как Wireshark, Microsoft Network Monitor, Fiddler или Burp ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=copydatafromfiddler.png');return false">скрин</a> ).</div>
    <div>Данные запроса также могут быть сгенерированы автоматически с помощью режима "Захват HTTP запросов" ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=recordhttprequests.png');return false">скрин</a> ).</div>
    <div>После заполнения данного поля не забудьте также задать поле 'Content-Type', там содержится формат данных, в котором представлены данные запроса.</div>
    <div>Вот несколько примеров данных и их формат:</div>
    <br/>
    <div>Content-Type: <strong>application/x-www-form-urlencoded</strong></div>
    <div>Данные содержат пары ключ/значение, разделенные символом & (амперсанд). Каждый ключ и каждое значение должны быть закодированы с помощью кодировки urlencoded. Вы можете сделать это используя функцию encodeURIComponent.</div>
    <br/>
    <div>Пример №1. Один ключ и одно значение.</div>
    <div><pre>key1=value1</pre></div>
      <br/>
    <div>Пример №2. Использование переменных.</div>
    <div><pre>key1=[[VALUE]]</pre></div>
      <br/>
    <div>Пример №3. Несколько ключей и значений.</div>
    <div><pre>key1=value1&key2=value2</pre></div>
      <br/>
    <div>Пример №4. Кодировка специальных символов.</div>
    <div><pre>email=login%40gmail.com</pre></div>
    <div>Вы не можете использовать символ @, сначала его нужно закодировать, после чего он превращается в %40</div>
      <br/>

    <div>Content-Type: <strong>multipart/form-data</strong></div>
    <div>Данные содержат пары ключ/значение, разделенные символом & (амперсанд). Каждый ключ и каждое значение должны разделены специальной границей. Граница будет автоматически определена исходя из содержания поля.</div>
<br/>
    <div>Пример №1. Один ключ и одно значение.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key"; 

Любые данные, в том числе и бинарные, и те, которые содержат специальные символы
--randomstringboundary--</pre></div>
      <br/>
    <div>Пример №2. Использование переменных.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key"; 

[[VALUE]]
--randomstringboundary--</pre></div>
      <br/>
    <div>Пример №3. Несколько ключей и значений.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="key1"; 

value1
--randomstringboundary
Content-Disposition: form-data; name="key2"; 

value2
--randomstringboundary--</pre></div>

      <br/>

    <div>Пример №4. Загрузка файла.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.txt"
Content-Type: application/octet-stream

FILE CONTENT
--randomstringboundary--</pre></div>

  <br/>


  <div>Внутри поля могут быть использованы переменные.</div>

  <div>Пример №5. Загрузить файл из переменной.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.txt"
Content-Type: application/octet-stream

[[VARIABLE]]
--randomstringboundary--</pre></div>

  <br/>

  <div>Если файл имеет бинарный формат, то вам нужно прочитать его в кодировке base64 и поставить префикс 'base64:' перед переменной.</div>

  <div>Пример №6. Загрузить бинарный файл.</div>
    <div><pre>--randomstringboundary
Content-Disposition: form-data; name="test"; filename="filename.bin"
Content-Type: application/octet-stream

base64:[[VARIABLE_WITH_BASE64_ENCODING]]
--randomstringboundary--</pre></div>


  <br/>

    <div>Content-Type: <strong>application/json</strong></div>
    <div>Отправить данные в формате json.</div>
<br/>
<div>Пример №1. Отправить статический json.</div>
    <div><pre>{
  "key": "value"
}</pre></div>
      <br/>

<div>Пример №2. Отправить json с переменной.</div>
    <div><pre>{
  "key": [[VARIABLE]]
}</pre></div>
      <br/>

  <br/>
  <div>Content-Type: <strong>text/plain</strong></div>
  <div>Загрузить текстовый файл.</div>
  <br/>

  <div>Пример №1. Отправка статического текстового файла.</div>
    <div><pre>Содержание файла</pre></div>
      <br/>

  <div>Content-Type: <strong>application/pdf</strong></div>
    <div>Загрузить pdf.</div>
    <br/>

  <div>Pdf - это файл в бинарном формате. Такие данные должны быть переданы в кодировке base64. Переменная, которая содержит эти данные должна иметь префикс 'base64:'.</div>
  <div>Пример №1. Отправка бинарного файла.</div>
    <div><pre>base64:[[VARIABLE_WITH_BASE64_ENCODING]]</pre></div>
      <br/>

  <div>Здесь описаны не все случаи, также поддерживаются любые другие форматы данных.</div>
  </script>


  <script type="text/template" id="httpclienturl">
    <div class="container-fluid httpclienturl">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_URL", help: 
{
  description: tr("This variable will contain current url for http client after action will end.")
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get current url of http client.</div>
      <div class="tr tooltip-paragraph-last-fold">Url may differ from last url used in 'GET' or 'POST' if there was redirects.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientcontent">
    <div class="container-fluid httpclientcontent">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_CONTENT", help: 
{
  description: tr("This variable will contain responce text without headers after action will end.")
}}) %>
      <%= _.template($('#input_constructor').html())({id:"Encoding", description:tr("Encoding"), default_selector: "string", disable_int:true, value_string: "auto", variants:["auto","utf-8","windows-1251","base64"], help: 
{
  description: tr("Encoding of responce text. This value can be 'auto', 'base64' or exact text, which contains encoding name. In 'auto' mode utf-8 encoding is assumed by default. If server specifies encoding in Content-Type header encoding, it will be used instead of utf-8. If this value will be set to excat encoding name, value in Content-Type header will be ignored. Setting exact value may be useful if encoding differs from utf-8 and server doesn't set it. 'base64' mode will return data encoded with base64. It is used if data is in binary format, like pictures, videos, etc.")
}
}) %>      

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get page source of the last request of http client.</div>
      <div class="tr tooltip-paragraph-fold">Page source is the same as one, which is displayed after you hit CTRL-U in a browser.</div>
      <div class="tr tooltip-paragraph-fold">The responce doesn't contain headers, to get headers you need to use 'Get Header' action.</div>
      <div class="tr tooltip-paragraph-fold">You need to set 'base64' encoding if you are getting binary data. Many actions accept data in base64 format.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">You can specify exact encoding name, see</span> <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('http://doc.qt.io/qt-5/qtextcodec.html#details');return false">list of suported encodings</a>.</div>
      
      
      <div class="tr tooltip-paragraph-last-fold">The fastest way to extract data from page source is xpath. 'Http Client' has set of actions to perform xpath queries. It is not recomended to use 'Content' action and regular expressions unless it is absolutely necessary.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientstatus">
    <div class="container-fluid httpclientstatus">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_STATUS", help: 
{
  description: tr("Variable, which will contain http status as integer."), examples:
  [
    {
      code:"200",description:tr("The request has succeeded.")
    },
    {
      code:"302",description:tr("The target page resides under different url.")
    },
    {
      code:"404",description:tr("Page not found")
    }
  ]
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get status of the last request of http client.</div>
      <div class="tr tooltip-paragraph-fold">You can compare status with 'If' action like this [[SAVED_STATUS]] == 200. This expression checks if request was successful.</div>
      
      <div class="tooltip-paragraph-last-fold"><span class="tr">List of</span> <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://httpstatuses.com/');return false">http statuses</a>.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientgetheader">
    <div class="container-fluid httpclientgetheader">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Header Name"), default_selector: "string", disable_int:true, help: 
{
  description: tr("Response header name. Header name must contain one or several words separated with dash. Character case is not important."), examples:
  [
    {
      code:"Location",description:tr("Get 'Location' header.")
    },
    {
      code:"Content-Type",description:tr("Get 'Content-Type' header.")
    },
    {
      code:"cOnTeNt-tYpE",description:tr("Also gets 'Content-Type' header.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_HEADER", help: 
{
  description: tr("A variable name, which will hold header value.")
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get response header of for last request.</div>
      <div class="tr tooltip-paragraph-fold">If request was performed with redirects, only headers for last redirect will be obtained. If you want to get headers for request in a middle of redirect chain, you need to disable 'Follow redirects' option for 'GET' and 'POST' action and perform redirects by yourself. To get url of next redirect, use 'Get Header' action with 'Location' parameter.</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">Headers can be shown in browser developer tools</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=showheaders.png');return false">screen</a> ).</div>
      
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientsetheader">
    <div class="container-fluid httpclientsetheader">
      <%= _.template($('#input_constructor').html())({id:"Name", description:tr("Header Name"), default_selector: "string", disable_int:true, value_string: "User-Agent", variants: ["User-Agent","Accept-Language"], size: 3, help: 
{
  description: tr("Request header name. Header name must contain one or several words separated with dash."), examples:
  [
    {
      code:"User-Agent",description:tr("Set 'User-Agent' header.")
    },
    {
      code:"Accept-Language",description:tr("Set 'Accept-Language' header.")
    },
    {
      code:"Referer",description:tr("Set referer.")
    }
  ]
}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Header Value"), default_selector: "string", disable_int:true, value_string: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0", help: 
{
  description: tr("Request header value. This could be arbitrary string.")
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set request header for subsequent requests with http client.</div>
      <div class="tr tooltip-paragraph-fold">You can set any valid header, like 'User-Agent', 'Referer', etc. However here is a list of headers that should not be set with this action: 'Connection', 'Host', 'Content-Type'. 'Content-Type' must be set in 'POST' action for a specific request. 'Accept-Encoding' can be set, but it is forbidden to put 'br' encoding in a list. 'br' encoding is not supported fro http client yet.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">To ensure, that headers are sent correctly use 'HTTP Sniffer' it is a window which automatically popups after any http request in record mode</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=httpsniffer.png');return false"> screen </a>).</div>
      <div class="tr tooltip-paragraph-last-fold">Use 'Clear Headers' action if you want to disable all headers set with this action.</div>
      
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientclearheader">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Clear all requests headers which was set with 'HTTP-Client Set Header' action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientgetcookiesforurl">
    <div class="container-fluid httpclientgetcookiesforurl">
        <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Url"), default_selector: "string", disable_int:true}) %>
        <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "COOKIES_FOR_URL"}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action is deprecated it is recommended to use 'HTTP-Client Save Cookies' action instead.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientsavecookies">
    <div class="container-fluid httpclientsavecookies">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_COOKIES", help: 
{
  description: tr("This variable will contain string with json. That json will hold list with all cookies for all domains. Json format is described below.")
  
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Save all http client cookies into variable.</div>

      <div class="tr tooltip-paragraph-fold">Result variable will contain string with json. That json will hold list with all cookies for all domains.</div>
      <div class="tr tooltip-paragraph-fold">Most of sites uses cookies to store user data, like user authorisation. This means, that by storing cookies after authorisation on some site and restore them later you can implement autologin.</div>
      <div class="tr tooltip-paragraph-fold">Cookie values is just a string, so you may save it to file, or database and use them later.</div>
      <div class="tr tooltip-paragraph-fold">Cookies from http client may be sent to browser even without this action by using 'Load cookies from http client' action. 'Load cookies from browser' will send cookies in opposite direction.</div>
      <div class="tr tooltip-paragraph-fold">Browser cookies and http client cookies shares same format.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Cookies string may be converted to object with JSON.parse function, like this [[JSON]] = JSON.parse([[SAVED_COOKIES]]). Result is a map with a single 'cookies' key, which holds a list, for example {"cookies": [COOKIE1,COOKIE2,COOKIE3,...]}.</span> ( <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=cookiesformat2.png');return false">screen</a> ).

      </div>

      <div class="tr tooltip-paragraph-fold">If you want to change cookies or extract them, you need to use javascript. Javascript code can be used in any field if you set field type to expression, or with 'Execute code' action.</div>
      
      <div class="tr tooltip-paragraph-fold">Each cookie is a map with following keys: value, name, domain, path, expires, httpOnly, secure.</div>
      <div class="tr tooltip-paragraph-fold">secure and httpOnly are boolean values.</div>
      <div class="tr tooltip-paragraph-fold">expires is datetime and serialized as the number of seconds since the UNIX epoch.</div>
      <div class="tr tooltip-paragraph-fold">Here are some javascript snipsets to work with cookies. All of them may be placed into 'Execute code' action. Before using it, you must parse cookies from string like this [[COOKIES]] = JSON.parse([[SAVED_COOKIES]])["cookies"]</div>
      <div class="tr tooltip-paragraph-fold">Find cookie by name: [[COOKIE]] = [[COOKIES]].filter(function(el){return el["name"] == "REPLACE WITH COOKIE NAME"})[0]</div>
      <div class="tr tooltip-paragraph-fold">Check if cookie exists: [[COOKIE_EXISTS]] = [[COOKIES]].filter(function(el){return el["name"] == "REPLACE WITH COOKIE NAME"}).length > 0</div>
      <div class="tr tooltip-paragraph-fold">Extract cookie value [[COOKIE_VALUE]] = [[COOKIE]]["value"]</div>
      <div class="tr tooltip-paragraph-fold">You can also set cookie value [[COOKIE]]["value"] = "My value". But changing parsed object won't change cookie inside http client, to do that you need to convert cookie to string(with JSON.stringify([[COOKIES]])) and use it with 'HTTP-Client Restore Cookies' action.</div>
      <div class="tr tooltip-paragraph-last-fold">[[COOKIES]] variable will hold a list of cookies, so it also may be processed with actions from 'List' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientrestorecookies">
    <div class="container-fluid httpclientrestorecookies">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Cookies"), default_selector: "string", disable_int:true, help: 
{
  description: tr("This field must contain string with cookies in json format. That json must hold list with all cookies for all domains. Json format is described below. Use empty string to clear cookies."), examples:
  [
    {
      code:tr("Empty string"),description:tr("Clear cookies")
    }
  ]
  
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set cookies for http client.</div>

      <div class="tr tooltip-paragraph-fold">'Cookies' parameter must contain string in json format with all cookies. This string can be obtained as 'HTTP-Client Save Cookies' action result and changed optionally.</div>
      
      <div class="tr tooltip-paragraph-fold">Most of sites uses cookies to store user data, like user authorisation. This means, that by storing cookies after authorisation on some site and restore them later you can implement autologin.</div>
      <div class="tr tooltip-paragraph-fold">Cookie values is just a string, so you may save it to file, or database and use them later.</div>
      <div class="tr tooltip-paragraph-fold">Cookies from http client may be sent to browser by using 'Load cookies from http client' action. 'Load cookies from browser' will send cookies in opposite direction.</div>
      <div class="tr tooltip-paragraph-fold">Browser cookies and http client cookies shares same format.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Cookies must be a map with a single 'cookies' key, which holds a list, for example {"cookies": [COOKIE1,COOKIE2,COOKIE3,...]}.</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=cookiesformat2.png');return false"> screen </a>).

      </div>

      <div class="tr tooltip-paragraph-fold">If you want to change cookies or extract them, you need to use javascript. Javascript code can be used in any field if you set field type to expression, or with 'Execute code' action.</div>
      
      <div class="tr tooltip-paragraph-fold">Each cookie is a map with following keys: value, name, domain, path, expires, httpOnly, secure.</div>
      <div class="tr tooltip-paragraph-fold">secure and httpOnly are boolean values.</div>
      <div class="tr tooltip-paragraph-fold">expires is datetime and serialized as the number of seconds since the UNIX epoch.</div>
      <div class="tr tooltip-paragraph-fold">Here are some javascript snipsets to work with cookies. All of them may be placed into 'Execute code' action. Before using it, you must parse cookies from string like this [[COOKIES]] = JSON.parse([[SAVED_COOKIES]])["cookies"]</div>
      <div class="tr tooltip-paragraph-fold">Find cookie by name: [[COOKIE]] = [[COOKIES]].filter(function(el){return el["name"] == "REPLACE WITH COOKIE NAME"})[0]</div>
      <div class="tr tooltip-paragraph-fold">Check if cookie exists: [[COOKIE_EXISTS]] = [[COOKIES]].filter(function(el){return el["name"] == "REPLACE WITH COOKIE NAME"}).length > 0</div>
      <div class="tr tooltip-paragraph-fold">Extract cookie value [[COOKIE_VALUE]] = [[COOKIE]]["value"]</div>
      <div class="tr tooltip-paragraph-fold">You can also set cookie value [[COOKIE]]["value"] = "My value".</div>
      <div class="tooltip-paragraph-fold"><span class="tr">After you finish manipulation with [[COOKIES]] array you need to convert it to string with JSON.stringify([[COOKIES]]) code</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=cookiesrestore2.png');return false"> screen </a>).</div>
      <div class="tr tooltip-paragraph-last-fold">[[COOKIES]] variable will hold a list of cookies, so it also may be processed with actions from 'List' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientfailonerror">
    <div class="container-fluid httpclientfailonerror">
      <%= _.template($('#input_constructor').html())({id:"SetFailed", description:tr("Set Fail On Error"), default_selector: "string", disable_int:true, value_string: "fail", variants: ["fail","continue"], size: 5}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action is deprecated it is recommended to use 'Ignore Errors' action instead.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientiserror">
    <div class="container-fluid httpclientiserror">
       <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "HTTP_CLIENT_WAS_ERROR"}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action is deprecated it is recommended to use 'Ignore Errors' action instead.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientgeterrorstring">
    <div class="container-fluid httpclientgeterrorstring">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "HTTP_CLIENT_ERROR_STRING"}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action is deprecated it is recommended to use 'Ignore Errors' action instead.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientxpathxml">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,
        variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"],
       help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}
}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_XML", help: 
{
  description: tr("Varibale, which will contain first element xml, which matches xpath query.")
}
}) %>

      <%= _.template($('#checkbox').html())({id: "Check", title: tr("Fail on error"), checked: true}) %>

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute xpath query and find xml of first matching element.</div>
      <div class="tr tooltip-paragraph-fold">This action, unlike 'Xpath Get Text', searches for element xml(html code).</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found, then thread will stop with fail message. If you want to continue thread, use 'Ignore errors' action or uncheck 'Fail on error'.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="httpclientxpathxmllist">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"], help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_XML_LIST", help: 
{
  description: tr("Varibale, which will contain list of all elements xml, which matches xpath query.")
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute xpath query and find xml of all elements matching query.</div>
      
      <div class="tr tooltip-paragraph-fold">This action, unlike 'Xpath Get Text List', searches for elements xml(html code).</div>
      <div class="tr tooltip-paragraph-fold">Result of this action is list, you can process it with 'List' module.</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found, then list will be empty.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
  
  <script type="text/template" id="httpclientxpathtext">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"], help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_TEXT", help: 
{
  description: tr("Varibale, which will contain first element text, which matches xpath query.")
}}) %>

  <%= _.template($('#checkbox').html())({id: "Check", title: tr("Fail on error"), checked: true}) %>


    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute xpath query and find text of first matching element.</div>
      <div class="tr tooltip-paragraph-fold">Result of this action is text. For example if element has &lt;div&gt;word&lt;/div&gt; markup, then its text is 'word'.</div>
      <div class="tr tooltip-paragraph-fold">If you want to get element markup, use 'Xpath Get Xml'.</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found, then thread will stop with fail message. If you want to continue thread, use 'Ignore errors' action or uncheck 'Fail on error'.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>


  <script type="text/template" id="httpclientxpathtextlist">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"], help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_TEXT_LIST", help: 
{
  description: tr("Varibale, which will contain list of all elements text, which matches xpath query.")
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute xpath query and find text of all elements matching query.</div>
      <div class="tr tooltip-paragraph-fold">This action searches for texts. For example if element has &lt;div&gt;word&lt;/div&gt; markup, then its text is 'word'.</div>

      <div class="tr tooltip-paragraph-fold">Result of this action is list, so you can process it with 'List' module.</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found, then list will be empty.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
  
  <script type="text/template" id="httpclientxpathcount">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"], help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_COUNT", help: 
{
  description: tr("This variable will be set to number of elements matching query."), examples:
  [
    {
      code:"0",description:tr("There are no elements which matches query.")
    },
    {
      code:"3",description:tr("There are 3 elements which matches query.")
    }
  ]
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute xpath query and get number of element which matches.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>
  
  <script type="text/template" id="httpclientxpathexists">
    <div class="container-fluid httpclientxpath">
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Xpath Query"), default_selector: "string", disable_int:true,variants: ["//title<br/><span style='color:gray;font-size:small'>" + tr("Get page title") + "</span>","//a<br/><span style='color:gray;font-size:small'>" + tr("Get all links") + "</span>","//img<br/><span style='color:gray;font-size:small'>" + tr("Find image") + "</span>","//img/@src<br/><span style='color:gray;font-size:small'>" + tr("Find image source") + "</span>","//*[@id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by id") + "</span>","//*[contains(@class,'CLASS')]<br/><span style='color:gray;font-size:small'>" + tr("Find element by class") + "</span>","//*[contains(@class,'CLASS') and @id='ID']<br/><span style='color:gray;font-size:small'>" + tr("Find element by class and id") + "</span>","//div[@id='ID_PARENT']/div[@id='ID_CHILD']<br/><span style='color:gray;font-size:small'>" + tr("Find element which contains parent") + "</span>"], help: 
{
  description: tr("Xpath query"), examples:
  [
    {
      code:"//title",description:tr("Get page title.")
    },
    
    {
      code:"//a",description:tr("Get all links.")
    },
    
    {
      code:"//img",description:tr("Find image.")
    },
    
    {
      code:"//img/@src",description:tr("Find image source(image url).")
    }
    ,
    
    {
      code:"//*[@id='ID']",description:tr("Find element by id.")
    },
    
    {
      code:"//*[contains(@class,'CLASS')]",description:tr("Find element by class. Element can have several classes, so need to use contains function.")
    }
    ,
    
    {
      code:"//*[contains(@class,'CLASS') and @id='ID']",description:tr("Find element by class and id.")
    },
    
    {
      code:"//div[@id='ID_PARENT']/div[@id='ID_CHILD']",description:tr("Find element which contains parent.")
    }
  ]
}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "XPATH_EXISTS", help: 
{
  description: tr("This variable will be to true or false depending if there is element, which matches query."), examples:
  [
    {
      code:"true",description:tr("There is at leaset one element which matches query.")
    },
    {
      code:"false",description:tr("There are no elements which matches query.")
    }
  ]
}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Check if there is at least one element matching xpath query.</div>
      <div class="tr tooltip-paragraph-fold">Html to apply query is obtained from last http responce.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to apply xpath query to custom string, you need to use 'Xpath' module.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="if">
    <div class="container-fluid if">
      <%= _.template($('#input_constructor').html())({id:"IfExpression", description:tr("If expression"), default_selector: "expression", disable_int:true, disable_string:true, help: {description: tr("If condition. This field can contain any JavaScript value including variables and resources."), examples:[{code:"true",description:tr("Always true.")},{code:"false",description:tr("Always false.")},{code:"[[VARIABLE]] == \"val\"",description:tr("Executes only if VARIABLE is equal to \"val\"")},{code:"[[VARIABLE]].indexOf(\"val\")<0",description:tr("Executes only if VARIABLE don't contain substring \"val\"")}]}}) %>
      <%= _.template($('#checkbox').html())({id: "IfElse", title: tr("Add else block")}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Check specified condition, if it's true execute some action sequence, if it's false execute another action sequence. Finally proceed with next actions.</div>
      <div class="tr tooltip-paragraph-fold">Even though description of this task may not sound very exciting, it is used very often to build custom logic.</div>
      <div class="tr tooltip-paragraph-fold">For example, if you want to check if element exists on page and depending on that condition make a log or stop a thread.</div>
      <div class="tr tooltip-paragraph-fold">It is very important to understand, that if expression is a custom JavaScript code. Here are some valid examples. 10 &gt; 2 is always true, "text".indexOf("te") &gt;= 0 is also true, while "text".indexOf("z") &gt; 0 is false.</div>
      <div class="tr tooltip-paragraph-fold">Expression also may contain variables and resources, their declarations are replaced with actual values, for example, [[PAGE_SOURCE]].length &gt; 100 is same "&lt;html&gt;&lt;body&gt;...".length &gt; 100. And some other valid examples: [[USER_ID]] == 123, {{login}} + "@gmail.com".</div>
      <div class="tr tooltip-paragraph-fold">You may use expression constructor in case if you don't know JavaScript. To do that click on "if expression" field and choose "create value in visual constructor".</div>
      <div class="tr tooltip-paragraph-fold">If "if expression" will be resolved to non-boolean type, its type will be converted to boolean. For example, number 100 will be converted to true, while 0 will be converted to false. Check JavaScript manual to understand how types are converted.</div>
      <div class="tr tooltip-paragraph-fold">In case if expression is false alternative action sequence may be specified through else checkbox.</div>
      <div class="tr tooltip-paragraph-last-fold">After action is created you need to add actions inside it, this actions will be executed only if condition is true.</div>
    </div>
    <%= _.template($('#back').html())({action:"add", visible:false, wiki: "is_it_possible_to_execute_certain_action_depending_on_condition_if_statement"}) %>
  </script>

  <script type="text/template" id="while">
    <div class="container-fluid while">
      <%= _.template($('#input_constructor').html())({id:"WhileExpression", description:tr("While expression"), default_selector: "expression", disable_int:true, disable_string:true, help: {description: tr("If condition. This field can contain any JavaScript value including variables and resources."), examples:[{code:"true",description:tr("Always true.")},{code:"false",description:tr("Always false.")},{code:"[[VARIABLE]] == \"val\"",description:tr("Continues only if VARIABLE is equal to \"val\"")},{code:"[[VARIABLE]].indexOf(\"val\")<0",description:tr("Continues only if VARIABLE don't contain substring \"val\"")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute defined list of actions while some condition is true.</div>
      <div class="tr tooltip-paragraph-fold">For example, take element from list and post it to the site, then delete element and repeat all these actions while list is not empty.</div>
      <div class="tr tooltip-paragraph-fold">If you know how many times loop should be repeated, then it is better to use for loop.</div>
      <div class="tr tooltip-paragraph-fold">If you want to iterate over list elements it is better to use foreach action.</div>
      <div class="tr tooltip-paragraph-fold">Be careful, if "while expression" will always be true then you may end up with infinite loop which may be the reason of problems in your script.</div>
      <div class="tr tooltip-paragraph-fold">While expression parameter could be any JavaScript code. It may also contain variables and resources. For example, [[POST_LENGTH]] &gt; 0. Or [[LIST]].length &gt; 0.</div>
      <div class="tr tooltip-paragraph-fold">Loop may be finished with break action at any time. If you call break action this interrupts loop immediately. A common practice would be to put break action inside if.</div>
      <div class="tr tooltip-paragraph-fold">Setting "while expression" to true will make loop run infinite amount of times, and this is necessary to finish it with break action.</div>
      <div class="tr tooltip-paragraph-fold">There is a special variable called [[CYCLE_INDEX]] available inside while loop and it always contains current iteration index and always have number type.</div>
      <div class="tr tooltip-paragraph-last-fold">Summarizing all the above, when BAS encounters while loop it checks condition, if it's true execute loop body then checks condition again and so on. It also updates [[CYCLE_INDEX]] on each iteration.</div>

    </div>
    <%= _.template($('#back').html())({action:"add", visible:false, wiki: "is_it_possible_to_use_loops"}) %>
  </script>

  <script type="text/template" id="for">
    <div class="container-fluid for">
      <%= _.template($('#input_constructor').html())({id:"ForFrom", description:tr("For from value"), default_selector: "expression", disable_string:true, help: {description: tr("Lower bound as integer value.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ForTo", description:tr("For to value"), default_selector: "expression", disable_string:true, help: {description: tr("Upper bound as integer value.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute defined list of actions specified number of times.</div>
      <div class="tr tooltip-paragraph-fold">You can define lower and upper bounds, for example, if you want to scroll page for three times, you should define lower bound as 1 and upper bound of 3.</div>
      <div class="tr tooltip-paragraph-fold">If you want to parse users on second page, need to set lower bound as 10 and upper bound as 20.</div>
      <div class="tr tooltip-paragraph-fold">Bounds also may be variables. Consider following example, you need to iterate over all pages and you don't know total amount of them. First you need to parse page amount and put it to variable and then use for loop with lower bound as one and upper bound equals to that variable.</div>
      <div class="tr tooltip-paragraph-fold">For loop may be interrupted at any time with break action. A common practice would be to put break action inside if.</div>
      <div class="tr tooltip-paragraph-fold">There is a special variable called [[CYCLE_INDEX]] available inside for loop and it always contains current iteration index and has number type.</div>
      <div class="tr tooltip-paragraph-last-fold">Summarizing all the above, when BAS encounters for loop it searches for loop body and repeat it number of times equal difference between upper and lower bound and update [[CYCLE_INDEX]] on each iteration.</div>
    </div>
    <%= _.template($('#back').html())({action:"add", visible:false, wiki: "is_it_possible_to_use_loops"}) %>
  </script>


  <script type="text/template" id="ignoreerrors">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Ignore errors inside one or several actions and continue script execution further.</div>
      <div class="tr tooltip-paragraph-fold">If something wrong will happen during action execution, BAS will stop thread immediately and assign fail result to it. This is not very convenient, because sometimes script must recover from error. That's where "ignore errors" comes in handy.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Usage is very simple, just wrap one or several actions inside ignore errors block. Following example will ignore all page load errors</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=ignoreerrorssimple.png');return false">screen</a>)</div>
      <div class="tooltip-paragraph-fold"><span class="tr">"Ignore errors" can contain several actions, if any of them will fail, all following will be skipped</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=ignoreerrorscomplex.png');return false">screen</a>)</div>
      <div class="tr tooltip-paragraph-fold">You can check [[WAS_ERROR]] variable, to detect if there was error during "Ignore Errors" block.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">You can also obtain error string from [[LAST_ERROR]] variable</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=checkerror.png');return false">screen</a>)</div>
      <div class="tr tooltip-paragraph-fold">Wrap ignore errors into while loop to run certain actions until all of them will be executed successfully.</div>
      <div class="tr tooltip-paragraph-last-fold">Using several actions inside ignore errors block could be very convenient, for example, you have split script in several stages: login, following, posting, then you can wrap each stage inside ignore errors block. If something goes wrong during following, then thread won't be stopped, user will get error message that something wrong with following, but there is no need to relogin with this account and script can try do posting.</div>
    </div>
    <%= _.template($('#back').html())({action:"add", visible:false, wiki: "how_to_catch_errors"}) %>
  </script>

  <script type="text/template" id="foreach">
    <div class="container-fluid foreach">
      <%= _.template($('#input_constructor').html())({id:"ForArray", description:tr("Foreach Array"), default_selector: "expression", disable_string:true, disable_int:true, help: {description: tr("This field contains list, list could be created with \"create list\" action, or obtain it through \"resources to a list\" action, also \"read file to list\" returns list. Besides variables you can put there array directly, for example, [4, 5, 6]. You can't put resource in this field, because resource is a string and this field requires list."), examples:[{code:"[4, 5, 6]",description:tr("Define list directly.")},{code:"[[SOME_LIST]]",description:tr("Get list from the variable.")}]}
}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Execute defined actions for every list element. Works only for lists.</div>
      <div class="tr tooltip-paragraph-fold">This action takes list as input parameter, then applies all child actions to each list element.</div>
      <div class="tr tooltip-paragraph-fold">For example, you have a list with all users which needs to be followed and you can achieve this by putting user list as input parameter of foreach action, and also by putting correct action sequence to follow user(probably action which press on follow button on site) as a child of foreach loop.</div>
      <div class="tr tooltip-paragraph-fold">There is a special variable called [[FOREACH_DATA]] which is available only inside foreach loop and which holds current list element.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Here is the most basic example of using foreach action - iterate over some list and an output every element to the log</span>. (<a href="#" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=foreachexample.png');return false" class="tr">screen</a>)</div>
      <div class="tr tooltip-paragraph-fold">To create or process list use list module.</div>
      <div class="tr tooltip-paragraph-fold">Input parameter "foreach array" holds any JavaScript code including variables and resources. So besides variables you can put there array directly, for example, [4, 5, 6].</div>
      <div class="tr tooltip-paragraph-last-fold">Summarising all the above, when BAS counters foreach loop it searches for loop body and repeat it for each list element, it also changes [[FOREACH_DATA]] on each loop iteration.</div>
    </div>
    <%= _.template($('#back').html())({action:"add", visible:false}) %>
  </script>

  <script type="text/template" id="setvariable">
    <div class="container-fluid setvariable">
      <%= _.template($('#variable_constructor').html())({id:"SetVariableName", description:tr("Name of variable"), default_variable: "NEW_VARIABLE", help: {description: tr("The name of the variable to be created or modified.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"SetVariableValue", description:tr("Value of variable"), default_selector: "string", help: {description: tr("Variable value"), examples:[{code:"any string",description:tr("Any string will work")},{code:"[[LOGIN]]:[[PASSWORD]]",description:tr("Concat 2 variables")},{code:"10",description:tr("Any number. Works with int type")},{code:"1+1",description:tr("Any javascript code. Works with expression type")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Create new or update existing variable and set its value.</div>
      <div class="tr tooltip-paragraph-fold">Variables are visible only inside current thread, use global variables if you want them to be visible inside whole script.</div>
      <div class="tr tooltip-paragraph-fold">Variable name should be in uppercase and should describe its purpose. Naming variable [[A1]] or [[A2]] could make your script very hard to read.</div>
      <div class="tr tooltip-paragraph-fold">You can use that variable later inside any field by putting variable name into double square brackets like this: [[NEW_VARIABLE]]. You don't need to type it manually, just click on any field, than on "Insert variable" and finally select specific variable.</div>
      <div class="tr tooltip-paragraph-fold">"Value of variable" parameter by default is a string, but may also contain other variables, like this [[LOGIN]]@gmail.com, or resources. So this action also may concat strings([[PART1]][[PART2]]), update them, etc.</div>
      <div class="tr tooltip-paragraph-fold">By default "Value of variable" parameter is a string, but you can change its type to int, so variable will be number.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Setting type to expression will set variable to result of JavaScript execution. This is very powerful mechanism. For example, to get current timestamp input Date.now() into "Value of variable" parameter</span> (<a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=gettimestamp.png');return false">screen</a>)</div>

      <div class="tr tooltip-paragraph-fold">You can use JavaScript functions on BAS variables, for example, [[LINE]].split(":")[0] will split string into two pieces and take first.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to set multiline variable, use template action.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_use_variables"}) %>
  </script>


  <script type="text/template" id="incvariable">
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"SetVariableName", description:tr("Name of variable"), default_variable: "", help: {description: tr("Variable name. This variable will be changed.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"IncVariableValue", description:tr("Increase variable value"), default_selector: "int", min_number: -9999999, value_number: 1, help: {description: tr("The integer to which the variable will be incremented. If the value has a non-numeric type, then it will be converted."), examples:[{code:"1",description:tr("Increment")},{code:"-1",description:tr("Decrement")},{code:"0",description:tr("Convert variable to integer")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Increase variable by the specified value.</div>
      <div class="tr tooltip-paragraph-fold">In other words, this action means [[VARIABLE]] = [[VARIABLE]] + num</div>
      <div class="tr tooltip-paragraph-fold">This action assumes that variable has number type, if it doesn't, type of variable will be automatically converted.</div>
      <div class="tr tooltip-paragraph-fold">Parameter "Increase variable value" could be negative, in that case variable will be decreased.</div>
      <div class="tr tooltip-paragraph-last-fold">Parameter "Increase variable value" also could be zero, this will only convert variable to number type.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>


  <script type="text/template" id="incglobalvariable">
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"SetVariableName", description:tr("Name of variable"), default_variable: "", enable_globals:true, disable_locals: true, help: {description: tr("Variable name. This variable will be changed.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"IncVariableValue", description:tr("Increase variable value"), default_selector: "int", min_number: -9999999, value_number: 1, help: {description: tr("The integer to which the variable will be incremented. If the value has a non-numeric type, then it will be converted."), examples:[{code:"1",description:tr("Increment")},{code:"-1",description:tr("Decrement")},{code:"0",description:tr("Convert variable to integer")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Increase global variable by the specified value.</div>
      <div class="tr tooltip-paragraph-fold">In other words, this action means [[GLOBAL:VARIABLE]] = [[GLOBAL:VARIABLE]] + num</div>
      <div class="tr tooltip-paragraph-fold">This action assumes that global variable has number type, if it doesn't, type of variable will be automatically converted.</div>
      <div class="tr tooltip-paragraph-fold">Parameter "Increase variable value" could be negative, in that case variable will be decreased.</div>
      <div class="tr tooltip-paragraph-last-fold">Parameter "Increase variable value" also could be zero, this will only convert variable to number type.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="url">
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"SaveUrl", description:tr("Variable To Save"), default_variable: "CURRENT_URL", help: {description: tr("Variable where browser url will be saved.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get current url from browser address bar.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki: "how_to_get_current_url"}) %>
  </script>

  <script type="text/template" id="screen">
    <div class="container-fluid">
      
      <%= _.template($('#variable_constructor').html())({id:"CursorX", description:tr("Cursor relative position X"), default_variable: "CURSOR_RELATIVE_X", help: {description: tr("Current cursor coordinates relative to screen position.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"CursorY", description:tr("Cursor relative position Y"), default_variable: "CURSOR_RELATIVE_Y", help: {description: tr("Current cursor coordinates relative to screen position.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"CursorAbsoluteX", description:tr("Cursor absolute position X"), default_variable: "CURSOR_ABSOLUTE_X", help: {description: tr("Current cursor coordinates relative to web page edge.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"CursorAbsoluteY", description:tr("Cursor absolute position Y"), default_variable: "CURSOR_ABSOLUTE_Y", help: {description: tr("Current cursor coordinates relative to web page edge.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"ScrollX", description:tr("Browser scroll X"), default_variable: "SCROLL_X", help: {description: tr("Current scroll value.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"ScrollY", description:tr("Browser scroll Y"), default_variable: "SCROLL_Y", help: {description: tr("Current scroll value.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Width", description:tr("Browser width"), default_variable: "BROWSER_WIDTH", help: {description: tr("Current browser viewport width, this doesn't include space which takes adress bar or native window. Works same as window.innerWidth.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Height", description:tr("Browser height"), default_variable: "BROWSER_HEIGHT", help: {description: tr("Current browser viewport height, this doesn't include space which takes adress bar or native window. Works same as window.innerHeight.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get current browser size, cursor and scroll position.</div>
      <div class="tr tooltip-paragraph-fold">In order to change browser resolution, use "Resize" action.</div>
      <div class="tr tooltip-paragraph-fold">In order to change current scroll, use "Scroll" action.</div>
      <div class="tr tooltip-paragraph-last-fold">In order to change cursor position, use "Move on element" action.</div>

    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="xml">
    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveXml", description:tr("Variable To Save"), default_variable: "SAVED_XML", help: {description: tr("This variable will contain html source of selected element as string")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get element html code and save it to variable.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Get Element Content")}) %>
  </script>

  <script type="text/template" id="linkurl">
    <div class="container-fluid xml">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"LinkURL", description:tr("Variable To Save"), default_variable: "LINK_URL", help: {description: tr("This variable will contain url of the nearest link after execution")}}) %>
    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get link URL and save it to variable.</div>
      <div class="tr tooltip-paragraph-fold">If element which matches selector is not link, nearest link will be selected.</div>
      <div class="tr tooltip-paragraph-fold">You can always tweak selection by using up and down keys. This is useful if several elements holds same coordinates.</div>
      <div class="tr tooltip-paragraph-fold">In case if link nearest to selected element can't be found, empty string will be returned.</div>

      <div class="tr tooltip-paragraph-last-fold">This action looks for "href" attribute on link element. Sometimes it may not be present, and sites processes link clicking by using javascript. In that case following action won't give any meaningful result.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Get link URL")}) %>
  </script>

  <script type="text/template" id="coordinates">
    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"X", description:tr("Relative X"), default_variable: "RELATIVE_X", help: {description: tr("Integer value, offset relative to current window position.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Y", description:tr("Relative Y"), default_variable: "RELATIVE_Y", help: {description: tr("Integer value, offset relative to current window position.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"AbsoluteX", description:tr("Absolute X"), default_variable: "ABSOLUTE_X", help: {description: tr("Integer value, offset relative to web page edge.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"AbsoluteY", description:tr("Absolute Y"), default_variable: "ABSOLUTE_Y", help: {description: tr("Integer value, offset relative to web page edge.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Width", description:tr("Width"), default_variable: "WIDTH", help: {description: tr("Integer value, element width.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"Height", description:tr("Height"), default_variable: "HEIGHT", help: {description: tr("Integer value, element height.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get coordinates of element relative to current window position.</div>
      <div class="tr tooltip-paragraph-fold">For example, if element coordinates is 200,200 and window position is 50,50, then this action will return 150, 150. In case if window position is 0,0, than this action will return absolute element coordinates.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true,name:tr("Get Coordinates")}) %>
  </script>

  <script type="text/template" id="script">
    <div class="container-fluid script">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveScript", description:tr("Variable To Save"), default_variable: "SAVED_SCRIPT_RESULT", help: {description: tr("Variable with result of javascript execution. Type of variable is always string, if expression is evaluated to other type, it will be converted. If exception will occur during script execution, than empty string will return.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ScriptValue", description:tr("Script Text"), default_selector: "string", disable_int:true, help: {description: tr("Script that will be executed on found element. You can use self variable, which points to found element. Type of that value should be string. If you set type to expression, than script will be evaluated in BAS context first and than result of that evaluation will be send to browser. Using expression is usefull if you want to create script dynamically, but you need to use string type in most cases."), examples:[{code:"self.value",description:tr("Get input field value")},{code:"self.click()",description:tr("Pure javascript click")}, {code:"self.getBoundingClientRect().top",description:tr("Get element top coordinate")}, {code:"var text = self.innerHTML; text.match(/\d+/)[0]",description:tr("Extract digits from element text.")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Find element and execute javascript on it.</div>
      <div class="tr tooltip-paragraph-fold">This action is deprecated. It is recommended to use the new "Execute Javascript On Element" action. Click on any element and select "Execute Javascript On Element" in order to use it.</div>
      <div class="tr tooltip-paragraph-fold">Use self variable, which points to selected element.</div>
      <div class="tr tooltip-paragraph-fold">document, window and other browser javascript objects are available.</div> 
      <div class="tr tooltip-paragraph-fold">Action works exactly the same as if you input code into browser console and output result into variable.</div>
      <div class="tr tooltip-paragraph-fold">You can also use resources and variables here but only in read mode. Following code will work self.getAttribute([[ATTRIBUTE]]), but you can't do like this <strike>[[RESULT]] = self.getAttribute([[ATTRIBUTE]])</strike>.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Execute Javascript On Element (deprecated)"), wiki: "how_to_execute_javascript_on_page_and_save_result"}) %>
  </script>

  <script type="text/template" id="browserscript">
    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>
      <span data-preserve="true" data-preserve-type="constr" data-preserve-id="Code">
        <div id="Code" class="browser-code-editor" data-is-code-editor="true" style="height: calc(100vh - 185px);margin-left: 16px;margin-right: 15px;" />
      </span>
      <%= "<s" + "cript>" %>
        window.Code = {Editor: null, InitialValue: ""}
    
        require(['vs/editor/editor.main'], function() {
          window.Code.Editor = createCodeEditor(document.getElementById('Code'), {
            value: window.Code.InitialValue
          });
        });
      <%= "</" + "script>" %>
      <div style="text-align: center">
        <a tabindex="-1" href="#" data-toggle="modal" data-result-target="#Code" class="var"  disable_globals="true">
          <span style="align-items: center; display: flex !important; justify-content: center;margin-top:5px;">

            <svg class="dropdown-icon" width="16" height="16"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"  style="margin-right:10px">
              <path d="M7.5 12h1V9.5H11v-1H8.5V6h-1v2.5H5v1h2.5V12z" fill="#337ab7" />
              <path d="M.5 2v12h15V2H.5zm14 11h-13V5h13v8z" fill="#337ab7" />
            </svg>
            <span class="tr">Insert variable</span>
          </span>
        </a>
      </div>
      <span class="short-description tr">Find element and execute javascript on it.</span>
    </div>
    <%= _.template($('#back').html())({ action: "executeandadd", visible: true, use_timeout: true, use_modal_template:true, name: tr("Execute Javascript On Element"), modal_code_id: "custom-help-browserscriptelement-" + (_K || "en") }) %>
    <script>
      $("#IfElementMissingSettingsCheck").change(function() {
        if(this.checked)
        {
          $(".browser-code-editor").css("height", "calc(100vh - 245px)")
        }else
        {
          $(".browser-code-editor").css("height", "calc(100vh - 185px)")
        }
      })
    </script>
  </script>

  <script type="text/template" id="text">
    <div class="container-fluid text">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"SaveText", description:tr("Variable To Save"), default_variable: "SAVED_TEXT", help: {description: tr("This variable will contain text of selected element as string")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get element text, visible on screen.</div>
      <div class="tr tooltip-paragraph-fold">For example, if you apply that action to whole page, you will get page text without markup.</div>
      <div class="tr tooltip-paragraph-fold">This action can be applied to textarea or input to get its value.</div> 
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Get Element Text")}) %>
  </script>

  <script type="text/template" id="clickelement">
    <div class="container-fluid clickelement">
      <%= _.template($('#path').html())({selector:selector}) %>
      <span class="disable-if-find-by-image">
        <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), smaller_fonts: true, description: tr("")}) %>
          <%= _.template($('#checkbox').html())({id: "Check", title: tr("Disable mouse emulation."), additional_classes: "disable-if-find-by-image", help: {description: tr("Disabling mouse emulation will make this action identical to executing click javascript function on element.")}}) %>
        <%= _.template($('#block_end').html())() %>
      </span>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Click on given element.</div> 
      <div class="tr tooltip-paragraph-fold">Target coordinates are always random but they are located close to center.</div>
      <% if(_SelectorModel.get("is_image") == false){ %>
        <div class="tr tooltip-paragraph-fold">Disabling mouse emulation will make this action identical to executing click javascript function on element.</div>
      <% } %>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">If you are clicking on some element, which causes page load, you should select "wait for full page load". Using this option will make browser wait for page load after click.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,use_timeout: true, visible:true, name: tr("Click On Element"), wiki: "how_to_click_on_buttons_and_links"}) %>
  </script>

  <script type="text/template" id="moveelement">
    <div class="container-fluid moveelement">
      <%= _.template($('#path').html())({selector:selector}) %>
    </div>
    
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Move mouse pointer on element.</div> 
      <div class="tr tooltip-paragraph-fold">Target coordinates are always random but they are located close to center.</div>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_move: true, use_emulation: true, name: tr("Move On Element"), wiki: "how_to_click_on_buttons_and_links"}) %>
  </script>

  <script type="text/template" id="mousesettings">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Speed", description:tr("Speed"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "100", help: {description: tr("Mouse movement speed as floating point value, if you change this, don't forget to change gravity and deviation proportionally.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Gravity", description:tr("Gravity"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "6", help: {description: tr("Floating point value which sets force of cursor attraction to strait line between starting and ending points. If you set this value too big, cursor will move by straight line, if you set it too low, cursor will move chaotically on the screen.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Deviation", description:tr("Deviation"), default_selector: "expression", disable_int:true, disable_string:true, value_string: "2.5", help: {description: tr("Floating point value which sets force of cursor deviation from strait line between starting and ending points. Think of it as a wind, which blows cursor away from the line - the shortest path between two points.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This is mouse movement settings. You set it either globally(through this action) or for each action individually by clicking on settings icon near cancel button inside any action, that uses mouse.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="notification">
    <div class="container-fluid dragelement">
     <%= _.template($('#input_constructor').html())({id:"AllowNotifications", description:tr("Allow notifications"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true", "false"], help: {description: tr("Allow or deny notifications."), examples:[{code:"true",description:tr("Always allow notification for all subsequent requests.")},{code:"false",description:tr("Always deny notification for all subsequent requests.")}]}}) %>
    </div>
    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Allow or deny browser notifications.</div> 
      <div class="tooltip-paragraph-fold"><span class="tr">In a normal browser notifications are displayed on a user desktop. Before start receiving them user must enable notifications. Using this action is the same as enabling or disabling notifications depending on input parameter.</span> <a href="#" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=allownotifications.png');return false" class="tr">screen1</a>, <a href="#" onclick="BrowserAutomationStudio_OpenUrl('http://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=notificationexample.png');return false" class="tr">screen2</a>. </div>
      <div class="tr tooltip-paragraph-fold">By default notifications are disabled.</div>
      <div class="tr tooltip-paragraph-fold">If you want to enable notifications only for certain sites, use this action several times before each site is loaded.</div>
      <div class="tr tooltip-paragraph-fold">This action must be called before any page which shows notifications is loaded.</div>
      <div class="tr tooltip-paragraph-last-fold">IMPORTANT: Notifications are often used together with service workers and service worker works only with profiles enabled. So you may want to use local profile together with this action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="mouseclicksettings">
    <div class="container-fluid">
      <%= _.template($('#combobox').html())({id: "Select", title: tr("Mouse click type"), items: [
        {value: "left", "name": tr("Left click"), selected: true},
        {value: "right", "name": tr("Right click")},
        {value: "double", "name": tr("Double click")},
      ]
      }) %>
    </div>
  </script>

  <script type="text/template" id="browsersettings">
    <div class="container-fluid">

      <%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("Components")}) %>

     
       <%= _.template($('#input_constructor').html())({id:"Widevine", description:tr("Widevine"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable"], help: { description: tr("Enable or disable Widevine plugin."), examples:[{code:"enable",description:tr("Use Widevine")},{code:"disable",description:tr("Don't use Widevine")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>
 
       <%= _.template($('#input_constructor').html())({id:"SafeBrowsing", description:tr("Safe Browsing"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable"], help: { description: tr("Enable Safe Browsing. It is technology embedded in Chrome, helps to protect users from malicious web sites. Its absence can be detected."), examples:[{code:"enable",description:tr("Enable Safe Browsing")},{code:"disable",description:tr("Disable Safe Browsing")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>
      
       <%= _.template($('#input_constructor').html())({id:"Components", description:tr("Components"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable"], help: { description: tr("Enable Chrome components. Increase profile size, but its absence can be detected."), examples:[{code:"enable",description:tr("Enable components")},{code:"disable",description:tr("Disable components")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>


       <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("WebRTC")}) %>

      <%= _.template($('#input_constructor').html())({id:"Webrtc", description:tr("WebRTC"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable", "replace"], help: { description: tr("WebRTC may show your real ip even if you are using proxy"), examples:[{code:"enable",description:tr("Use WebRTC")},{code:"disable",description:tr("Don't use WebRTC")},{code:"replace",description:tr("Replace ips exposed by WebRTC with values from 'WebRTC ip list' field.")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"WebrtcIps", description:tr("WebRTC ip list"), default_selector: "string", disable_int:true, disable_editor:true, disable_string:true, use_textarea:true, size: 8, disable_type_chooser:true,textarea_height:60, help: {description: tr("Replace ips exposed by WebRTC with values from this field. Works only if 'WebRTC' parameter is set to 'replace'. Each line must contain single ip. This setting is for debugging purposes only, the proper way to set is using 'Proxy' action."), examples:[{code:"192.168.0.1",description:tr("Local address")},{code:"142.1.2.3",description:tr("Remote address")},{code:"Clear",description:tr("Remove all ips")},{code:tr("Empty string"),description:tr("Don't change")}]}}) %>


      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("Canvas")}) %>

      <%= _.template($('#info').html())({description: `<span class="tr">Use <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://fp.bablosoft.com'); return false;">FingerprintSwitcher</a> service and <a href="#!/FingerprintSwitcher_Get">Get Fingerprint</a> action to add noise to canvas.</span>`, color: "gray"}) %>
      

      <%= _.template($('#input_constructor').html())({id:"Canvas", description:tr("Canvas"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable", "noise"], help: { description: tr("Canvas is html element with graphics like: shapes, images, text, etc. Different browsers and operation systems render canvas content slightly different. These differences may be exploited by sites to identify you among other users. BAS allows you protect you by disabling canvas or add custom noise to canvas content."), examples:[{code:"enable",description:tr("Use canvas")},{code:"disable",description:tr("Don't use canvas")},{code:"noise",description:tr("Add random noise to canvas. For debug purpose only, use FingerprintSwitcher to change it.")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>

      
      <%= _.template($('#input_constructor').html())({id:"CanvasNoise", description:tr("Canvas noise pattern"), default_selector: "string", disable_int:true, value_string: "", help: { description: tr("This setting is for debugging purposes only, the proper way to set is using FingerprintSwitcher")}}) %>


      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("WebGL")}) %>

      <%= _.template($('#info').html())({description: `<span class="tr">Use <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://fp.bablosoft.com'); return false;">FingerprintSwitcher</a> service and <a href="#!/FingerprintSwitcher_Get">Get Fingerprint</a> action to add noise to WebGL.</span>`, color: "gray"}) %>


      <%= _.template($('#input_constructor').html())({id:"Webgl", description:tr("WebGL"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable", "noise"], help: { description: tr("WebGl also may identify you among other users in pretty same ways as canvas."), examples:[{code:"enable",description:tr("Use WebGL")},{code:"disable",description:tr("Don't use WebGL")},{code:"noise",description:tr("Add random noise to WebGL picture. For debug purpose only, use FingerprintSwitcher to change it.")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>
      

      <%= _.template($('#input_constructor').html())({id:"WebglNoise", description:tr("WebGL noise pattern"), default_selector: "string", disable_int:true, value_string: "", help: { description: tr("This setting is for debugging purposes only, the proper way to set is using FingerprintSwitcher")}}) %>

      <%= _.template($('#input_constructor').html())({id:"WebglVendor", description:tr("WebGL vendor"), default_selector: "string", disable_int:true, value_string: "", help: { description: tr("WebGL vendor can expose your real hardware through javascript, so it is good idea to change it. Empty string will leave your real settings. This setting is for debugging purposes only, the proper way to set is using FingerprintSwitcher"), examples:[{code:"Google Inc.",description:tr("Vendor example")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"WebglRenderer", description:tr("WebGL renderer"), default_selector: "string", disable_int:true, value_string: "", help: { description: tr("WebGL renderer can expose your real hardware through javascript, so it is good idea to change it. Empty string will leave your real settings. This setting is for debugging purposes only, the proper way to set is using FingerprintSwitcher"), examples:[{code:"Google Inc.",description:tr("ANGLE (NVIDIA GeForce GTX 550 Ti Direct3D11 vs_5_0 ps_5_0)")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>


      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("Audio")}) %>

      <%= _.template($('#info').html())({description: `<span class="tr">Use <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://fp.bablosoft.com'); return false;">FingerprintSwitcher</a> service and <a href="#!/FingerprintSwitcher_Get">Get Fingerprint</a> action to add noise to audio.</span>`, color: "gray"}) %>


      <%= _.template($('#input_constructor').html())({id:"Audio", description:tr("Audio"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable", "noise"], help: { description: tr("Site may identify user by generating sound and reading it as a data. Different browsers and operating systems will do that operation with slightly different results. BAS allows to protect you by disallowing browser to obtain sound data or by adding custom noise to result."), examples:[{code:"enable",description:tr("Enable audio api")},{code:"disable",description:tr("Disable audio api methods used for fingerprinting")},{code:"noise",description:tr("Add random noise to generated sound. For debug purpose only, use FingerprintSwitcher to change it.")}, {code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>
      

      <%= _.template($('#input_constructor').html())({id:"AudioNoise", description:tr("Audio noise pattern"), default_selector: "string", disable_int:true, value_string: "", help: { description: tr("This setting is for debugging purposes only, the proper way to set is using FingerprintSwitcher")}}) %>


      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

       <%= _.template($('#header').html())({name:tr("Network")}) %>

 
       <%= _.template($('#input_constructor').html())({id:"QUIC", description:tr("Enable QUIC protocol"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable"], help: { description: tr("Unlike HTTP, QUIC protocol is build on top of UDP. Not all proxies supports UDP. It means that enabling QUIC can cause problems when working with certain proxies. It is recommended to enable this option only if sure, that your proxy supports it. Disabled by default."), examples:[{code:"enable",description:tr("Enable QUIC")},{code:"disable",description:tr("Disable QUIC")},{code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>

       <%= _.template($('#input_constructor').html())({id:"Tunneling", description:tr("Enable tunneling"), default_selector: "string", disable_int:true, value_string: "", variants: ["enable", "disable"], help: { description: tr("This setting allows to completely turn off the built-in tunneling system. When tunneling is disabled, any applied proxy won't work. Useful if you are using a VPN or want a direct connection. Tunneling is enabled by default. Changing this option immediately restarts the browser. Disable tunneling only when you're certain no proxy will be needed and want to use native network stack."), examples:[{code:"enable",description:tr("Enable tunneling. Default option.")},{code:"disable",description:tr("Disable tunneling, native network stack will be used, applying proxy won't take any effect.")},{code:tr("Empty string"),description:tr("Don't change this setting")}]}}) %>
      
      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

       <%= _.template($('#header').html())({name:tr("Rendering")}) %>

      <%= _.template($('#input_constructor').html())({id:"MaxFPS", description:tr("Maximum FPS"), default_selector: "int", disable_string:true, value_number: 0, variants: ["0<br/><span style='color:gray;font-size:small'>" + tr("Don't change") + "</span>", "30", "60"], help: { description: tr("Maximum times browser content can be rendered per one second. The lower this value, the lower the CPU usage will be. Setting it too low may affect site operability. Reducing it below 30 may lead to unpredictable consequences. Minimum value is 10."), examples:[{code:"30",description:tr("Limit FPS to 30")},{code:"0",description:tr("Don't change FPS")}]}}) %>

      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("Extensions")}) %>

      <%= _.template($('#input_constructor').html())({id:"Extensions", description:tr("Each line must contain either file path or extension id or extension url, examples:\nc:/path/to/extension/\nhttps://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif\npadekgcemlokbadohgkifijomclgjgif"), default_selector: "string", disable_int:true, disable_editor:true, disable_string:true, use_textarea:true, size: 8, disable_type_chooser:true,textarea_height:80, help: {description: tr("Chrome extension can be used in BAS by inputting either extension id or extension url or extension path into this field. The easiest way to start using extension is to copy paste url from chrome web store."), examples:[{code:"https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif",description:tr("Load extension by url")},{code:"padekgcemlokbadohgkifijomclgjgif",description:tr("Load extension by id")},{code:"c:/extensions/background",description:tr("Load extension from specified folder. File c:/extensions/background/manifest.json must exists")},{code:"Clear",description:tr("Remove all extensions")},{code:tr("Empty string"),description:tr("Don't change")}]}}) %>

      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

      <%= _.template($('#header').html())({name:tr("Browser version")}) %>
 
       <%= _.template($('#input_constructor').html())({id:"BrowserVersion", description:tr("Browser version"), default_selector: "string", disable_int:true, value_string: "",
       variants:
       [
        "default<br/><span style='color:gray;font-size:small'>" + tr("Use latest Chrome version") + "</span>", 
        "random<br/><span style='color:gray;font-size:small'>" + tr("Select random Chrome version of all available") + "</span>",
        "111.0.5563.65<br/><span style='color:gray;font-size:small'>" + tr("Select specific version based on full vesrion string") + "</span>",
        "111<br/><span style='color:gray;font-size:small'>" + tr("Select specific version based on major version string") + "</span>",
        "1<br/><span style='color:gray;font-size:small'>" + tr("Select specific version based on version id") + "</span>",
       ], 
       help: { description: tr("Changes browser version for current thread. This setting will restart browser and therefore reset all settings, so it is better to use it when thread starts."), examples:[
        {code:"default",description:tr("Use latest Chrome version")},
        {code:"random",description:tr("Select random Chrome version of all available")},
        {code:"111.0.5563.65",description:tr("Select specific version based on full vesrion string")},
        {code:"111",description:tr("Select specific version based on major version string")},
        {code:"1",description:tr("Select specific version based on version id")},
        {code:tr("Empty string"),description:tr("Don't change this setting")}
       ]}}) %>

       <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

       <%= _.template($('#header').html())({name:tr("Command line")}) %>

       <%= _.template($('#info').html())({description: `<span class="tr">List of command line parameters can be found</span> <a href="#" class="tr" onclick="BrowserAutomationStudio_OpenUrl('https://peter.sh/experiments/chromium-command-line-switches/'); return false;">here</a>.`, color: "gray"}) %>

       <%= _.template($('#input_constructor').html())({id:"CommandLine", description:tr("Each line must contain one command line parameter, which will be used to start browser. It can be just single key or a key and a value.\nExamples:\n--disable-component-update\n--lang=ru-RU"), default_selector: "string", disable_int:true, disable_editor:true, disable_string:true, use_textarea:true, size: 8, disable_type_chooser:true,textarea_height:80, help: {description: tr("This field may contain additional command line parameters used to start browser. They can also be specified by changing chrome_command_line.txt file inside apps/BASVERSION folder. If same key will be specified in both places, preference will be given to this field. Previous command line parameter list will be overridden by this value."), examples:[{code:"--key",description:tr("Send key only")},{code:"--key=value",description:tr("Send key and value")},{code:"Clear",description:tr("Remove all command line params")},{code:tr("Empty string"),description:tr("Don't change")}]}}) %>

      <%= _.template($('#space').html())({}) %><%= _.template($('#line').html())({}) %><%= _.template($('#space').html())({}) %>

       <%= _.template($('#header').html())({name:tr("Profile")}) %>

       <%= _.template($('#input_constructor').html())(
        {
          id:"Path", 
          description:tr("Profile folder path"), 
          default_selector: "string", 
          disable_int:true, 
          value_string: "", 
          variants: 
          [
            "c:/path/to/profile<br/><span style='color:gray;font-size:small'>" + tr("Exact profile location") + "</span>",
            "temporary<br/><span style='color:gray;font-size:small'>" + tr("New temporary profile") + "</span>",
          ], 
          help: 
          {
            description: tr("String with profile folder. Slash type is not important. If folder doesn't exist, it will be created. If folder already exists, BAS will use it as profile and restore all data from it like cookies, localstorage, etc. By default browser stores all profile data in temporary folder, you can use \"temporary\" keyword to switch to new temporary profile."), 
            examples:
            [
              {
                code:tr("Empty string"),
                description:tr("Don't change")
              }, 
              {
                code:tr("temporary"),
                description:tr("Switch to new temporary profile")
              } ,
              {
                code:"c:/path/to/profile"
              },
              {
                code:"c:\\path\\to\\profile"
              }
            ]
          }
        }) %>
         <%= _.template($('#input_constructor').html())({id:"LoadFPFromFolder", description:tr("Always load fingerprint from profile folder"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("In case if profile folder already exists and has fingerprint data, tells BAS to apply fingerpint used latest for that profile.")}}) %>

         <%= _.template($('#input_constructor').html())({id:"Key", description:tr("FingerprintSwitcher key. Can be empty"), default_selector: "string", disable_int:true,
         variants: ["business<br/><span style='color:gray;font-size:small'>" + tr("Use FingerprintBusiness license.") + "</span><br/><span style='color:gray;font-size:small'>" + tr("It can help to embed fingerprints inside compiled script.") + "</span>"],
          help: 
          {
            description: tr("Fingerprints are obtained from the FingerprintSwitcher service. To use this service, you need to purchase a key. Key verification is required when using profile which has fingerprint data. If you don't change profile folder or it doesn't contain fingerprint data, you can leave this field blank. You can also leave this field blank if the fingerprint was obtained using the free version (without a key). However, if the fingerprint was obtained with the paid version, you must provide a valid key to apply it. To use the free version, simply leave this field blank."), examples:
            [
              {
                code:"pGGeNdza2e0gIw48oa",description:tr("Key example, it is required if fingerprint was obtained with paid version.")
              },
              {
                code:"business",description:tr("Use FingerprintBusiness license. It can help to embed fingerprints inside compiled script. Check following") + " " + `<a href='#' style="color:rgba(157, 153, 108, 1.0)" onclick="BrowserAutomationStudio_OpenUrl('` + tr('https://wiki.bablosoft.com/doku.php?id=fingerprintbusiness') + `');return false">` + tr('link') + `</a>` + " " + tr("for more info.")
              },
              
              {
                code:tr("Empty string"),description:tr("Use a free version. Only if fingerprint was obtained with free version.")
              }
            ]
          } }) %>

          <%= _.template($('#info').html())({color: "gray", description: `<span class="tr">This action works with</span> 
          <a href="#"  onclick="BrowserAutomationStudio_OpenUrl('https://fp.bablosoft.com'); return false;">
            <span class="tr">Fingerprint switcher service</span></a>. 
          <span class="tr">You can get a key there</span>. `}) %>

         <%= _.template($('#input_constructor').html())({id:"LoadProxyFromFolder", description:tr("Always load proxy from profile folder"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("In case if profile folder already exists and has proxy data, tells BAS to apply proxy used latest for that profile.")}}) %>

       <%= _.template($('#space').html())({}) %>

    </div>


    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Changes browser settings: network, canvas, webgl, etc. Use "Get Fingerprint" action to change browser fingerprint.</div>
      <div class="tr tooltip-paragraph-fold">Empty string or 0 means, that value wont be changed.</div>
      <div class="tr tooltip-paragraph-fold">"Components", "Extensions", "Widevine", "Command line", "Browser version" or "Profile" options will restart browser process and thereby reset all settings(proxies, headers, etc), so the best place to use this action is thread start.</div> 
      <div class="tooltip-paragraph-fold"><span class="tr">Chrome extension can be used in BAS by inputting either extension id or extension url or extension path into "Extensions" field. Extension id is a unique string with 32 length, for example, padekgcemlokbadohgkifijomclgjgif. Extension url is the main url of extension in</span> <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://chrome.google.com/webstore/category/extensions');return false" class="tr">chrome web store</a>. <span class="tr">It has chrome.google.com domain, for example: https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif. Extension path is path to unpacked extension. Each path must contain extracted extension, a folder with manifest.json and other files. See</span> <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=using_extensions');return false" class="tr-en">this link</a><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=ru:using_extensions');return false" class="tr-ru">эту ссылку</a>, <span class="tr">for information about unpacking extensions and other info about using them</span>.</div>

      <div class="tr tooltip-paragraph-fold">Each BAS version may be shipped with one or several browser versions. This action can change browser version used in current thread. Use "Browser version" param to do that.</div>
      <div class="tr tooltip-paragraph-fold">In order to get Chrome version, which is used for current thread, use "Get current browser version" action.</div>
      <div class="tr tooltip-paragraph-fold">In order to get all available versions for current BAS build, use "Get list of available browser versions" action.</div>
      <div class="tr tooltip-paragraph-fold">One of use case for changing browser version would be to select random version with this action first. You can use "random" string as input parameter. Then get fingerprint which was obtained from browser with same version. Use "Get fingerprint" action with "Minimum browser version" and "Maximum browser version" parameters. This way used actual browser version will always match browser version of fingerprint, and these versions won't be the same for each thread.</div>

      <div class="tr tooltip-paragraph-last-fold">If you want to change settings for every thread, it is better to use settings tab.</div>
    </div>


    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="getbrowserversionlist">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Format", description:tr("Format"), default_selector: "string", disable_int:true, value_string: "default", variants: 
      [
        "default<br/><span style='color:gray;font-size:small'>" + tr("Returns list of strings") + "</span>",
        "extended<br/><span style='color:gray;font-size:small'>" + tr("Returns list of objects") + "</span>"
      ], help: {description: tr("Format of returned result. Results are always sorted descending by version, i.e. the latest version will appear first in the list."), examples:[
        {code:("default"), description:(tr("returns list of strings, for example") + (" <code style=\"font-size:85%\">[\"113.0.5563.65\", \"111.0.5563.65\", ...]</code>"))},
        {code:("extended"), description:(tr("returns list of object, each object has info about specific version, for example") + ("<code style=\"font-size:85%\">[{\"id\": 1, \"browser_version\": \"113.0.5563.65\", ...}]</code>. ") + tr("More info about each property of these objects can be found below."))}
      ]}}) %>
    
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable to save the result"), default_variable: "AVAILABLE_CHROME_VERSIONS", help: {description: tr("Variable in which, after successful execution of the action, the list of all available Chrome versions will be stored. Results are always sorted descending by version, i.e. the latest version will appear first in the list."), examples:[
        {code:("default"), description:(tr("returns list of strings, for example") + (" <code style=\"font-size:85%\">[\"113.0.5563.65\", \"111.0.5563.65\", ...]</code>"))},
        {code:("extended"), description:(tr("returns list of object, each object has info about specific version, for example") + ("<code style=\"font-size:85%\">[{\"id\": 1, \"browser_version\": \"113.0.5563.65\", ...}]</code>. ") + tr("More info about each property of these objects can be found below."))}
      ]} }) %>
    
    </div>
    
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get list of all available Chrome versions.</div>
      <div class="tr tooltip-paragraph-fold">Each BAS version may be shipped with one or several browser versions. This action can obtain list of all available versions programmatically. You can get this list manually as well by visiting Menu -&gt; Help -&gt; About Engine.</div>
      <div class="tr tooltip-paragraph-fold">In order to get Chrome version, which is used for current thread, use "Get current browser version" action.</div>
      <div class="tr tooltip-paragraph-fold">If you want to switch browser version for current thread, use "Browser Settings" action with "Browser Version" parameter.</div>
      <div class="tr tooltip-paragraph-fold">One of possible use case would be to get list of all versions with this action, select certain version with "Browser Settings" action and then use "Get fingerprint" action with "Minimum browser version" and "Maximum browser version" parameters which matches previously selected browser version. This way used actual browser version will always match browser version of fingerprint, and these versions won't be the same for each thread. With this example you are free to use any algorithm for browser version selection, it could be just random value, or selection based on probability, for example, latest version may be selected more often than outdated.</div>
      <div class="tr tooltip-paragraph-fold">Depending on selected format this action will return either list of strings or list of objects.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">With "default" format output will contain list of strings with full browser versions, for example</span> <code style="font-size:85%">["113.0.5563.65", "111.0.5563.65", ...]</code></div> 
      <div class="tooltip-paragraph-fold"><span class="tr">With "extended" format output will contain list of object, each object has info about specific version, for example</span> <code style="font-size:85%">[{"id": 1, "browser_version": "113.0.5563.65", ...}]</code></div>
      <div class="tr tooltip-paragraph-fold">Here is a list of properties for these objects:</div>
      <div class="tr tooltip-paragraph-fold">"browser_version" - full browser version, for example 111.0.5563.65. Can be used later to switch current thread to this version.</div>
      <div class="tr tooltip-paragraph-fold">"id" - internal identifier of Chrome build, for example, 1, 2, 3, ...</div>
      <div class="tr tooltip-paragraph-fold">"bas_version" - BAS version in which corresponding Chrome version was introduced, for example, 25.5.1.</div>
      <div class="tr tooltip-paragraph-fold">"architecture" - browser architecture, can be "x64" or "x86".</div>
      <div class="tr tooltip-paragraph-fold">Result obtained with "extended" format can be parsed with JSON module, while "default" format is easier to parse with List module.</div>
      <div class="tr tooltip-paragraph-last-fold">Results are always sorted descending by version, i.e. the latest version will appear first in the list.</div>
    
      
    </div>
    
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="getcurrentbrowserversion">
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"Save2", description:tr("Browser version string"), default_variable: "BROWSER_VERSION_STRING", help: {description: tr("Variable in which, after successful execution of the action, Chrome version will be stored. Version string is obtained for current thread. Other threads can use different versions. It can be changed by using \"Browser settings\" action."), examples:[
        {
          code:("111.0.5563.65"), description: tr("current thread uses 111.0.5563.65 Chrome version.")
        },
        {
          code:("113.0.5563.65"), description: tr("current thread uses 113.0.5563.65 Chrome version.")
        }

      ]} }) %>
    </div>
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Browser version id"), default_variable: "BROWSER_VERSION_ID", help: {description: tr("Variable in which, after successful execution of the action, internal identifier of browser build will be stored. Version id is obtained for current thread. Other threads can use different versions. IDs are always integers starting from 1."), examples:[
        {code:("1, 2, 3 ...")}
      ]} }) %>
    </div>
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"Save3", description:tr("Browser architecture"), default_variable: "BROWSER_ARCHITECTURE", help: {description: tr("Variable in which, after successful execution of the action, browser architecture will be stored."), examples:[
        {
          code:("x64")
        },
        {
          code:("x86")
        }
      ]} }) %>
    </div>

    
    
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get info about current Chrome version.</div>
      <div class="tr tooltip-paragraph-fold">Each BAS distribution may be shipped with one or several browser versions. This action can obtain Chrome version used in current thread. Other threads can use different versions.</div>
      <div class="tr tooltip-paragraph-fold">By default BAS will choose latest browser version available.</div>
      <div class="tr tooltip-paragraph-fold">In order to get all available versions for current BAS build, use "Get list of available browser versions" action.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to switch browser version for current thread, use "Browser Settings" action with "Browser Version" parameter.</div>
    
      
    </div>
    
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="dragelement">
    <div class="container-fluid dragelement">
      <%= _.template($('#path').html())({selector:selector}) %>
    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Start drag from given element.</div>

      <div class="tr tooltip-paragraph-fold">Target coordinates are always random but they are located close to center.</div>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
      <div class="tr tooltip-paragraph-last-fold">If you used this action, you must also call "Drop" or "Drop On Element" action.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_move: true, use_emulation: true, name: tr("Drag On Element")}) %>
  </script>


  <script type="text/template" id="dropelement">
    <div class="container-fluid dropelement">
      <%= _.template($('#path').html())({selector:selector}) %>

    </div>
    <%= _.template($('#movefields').html())({}) %>
    
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Drop to given element.</div>

      <div class="tr tooltip-paragraph-fold">Target coordinates are always random but they are located close to center.</div>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
      <div class="tr tooltip-paragraph-last-fold">Before using this action, you must also call "Drag" or "Drag On Element" action.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_move: true, name: tr("Drop On Element")}) %>
  </script>

  <script type="text/template" id="moveandclickelement">
    <div class="container-fluid moveandclickelement">
      <%= _.template($('#path').html())({selector:selector}) %>
      
      <%= _.template($('#checkbox').html())({id: "Check2", title: tr("Hold ctrl key. Open link in a new tab.")}) %>

      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), smaller_fonts: true, description: tr("")}) %>
        <%= _.template($('#mouseclicksettings').html())() %>  
        <%= _.template($('#checkbox').html())({id: "Check", title: tr("Disable mouse emulation."), additional_classes: "disable-if-find-by-image", help: {description: tr("Disabling mouse emulation will make this action identical to executing click javascript function on element.")}}) %>
        
      <%= _.template($('#block_end').html())() %>
      

    </div>

    

    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({additionalEmulation: true}) %>

    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Move mouse and click on given element.</div>
      <div class="tr tooltip-paragraph-fold">Target coordinates are always random but they are located close to center.</div>
      <% if(_SelectorModel.get("is_image") == false){ %>
        <div class="tr tooltip-paragraph-fold">Disabling mouse emulation will make this action identical to executing click javascript function on element.</div>
      <% } %>
      
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-fold">If you are clicking on some element, which causes page load, you should select "wait for full page load". Using this option will make browser wait for page load after click.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
      </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,use_timeout: true, use_move: true, use_emulation: true, visible:true, name: tr("Move And Click On Element"), wiki: "how_to_click_on_buttons_and_links"}) %>
  </script>

  <script type="text/template" id="clear">
    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>

    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({additionalEmulation: true}) %>
    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Clear edit. Works only on edit.</div>
      <div class="tr tooltip-paragraph-fold">This action is equivalent to typing &lt;CONTROL&gt;A&lt;BACK&gt;.</div>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_move: true, use_emulation: true, name: tr("Clear Edit"), wiki: "how_to_click_on_buttons_and_links"}) %>
  </script>

  <script type="text/template" id="typeelement">

    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>

      <%= _.template($('#input_constructor').html())({id:"TypeData", description:tr("Text to type"), default_selector: "string", disable_int:true, help: {description: tr("This could be any character sequence."), examples:[{code:"hello world!",description:tr("Input hello world!")},{code:"&lt;CONTROL&gt;V",description:tr("Paste text")},{code:"&lt;CONTROL&gt;A&lt;DELETE&gt;",description:tr("Clear input")},{code:"&lt;ESCAPE&gt;",description:tr("Press escape")}]}}) %>
      
      <%= _.template($('#block_start').html())({id: "SpecialKeys", name: tr("Special keys"), smaller_fonts: true, description: tr("")}) %>
        <%= _.template($('#special_buttons').html())({}) %>
      <%= _.template($('#block_end').html())() %>


      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), smaller_fonts: true, description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"TypeInterval", description:tr("Interval in milliseconds"), default_selector: "int", disable_string:true, value_number: 100, step_number: 100, min_number: 0, max_number:10000, help: {description: tr("Interval between each key press in milliseconds. BAS uses different interval for every key which is close to this parameter. For example, if you set interval to 100, that could result following sequence: key #1, wait 91 millisecond, key #2, wait 117 millisecond, key #3, etc"), examples:[{code:"100",description:tr("Default value. Human like input emulation.")},{code:"0",description:tr("Text is entered instantly.")}]}}) %>
        <%= _.template($('#checkbox').html())({id: "Check", additional_classes: "disable-if-find-by-image", title: tr("Disable mouse and keyboard emulation."), help: {description: tr("Click and input text using javascript. Not recommended to use.")}}) %>
      <%= _.template($('#block_end').html())() %>

      

    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({additionalEmulation: true}) %>

    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Type text inside element.</div>
      <div class="tr tooltip-paragraph-fold">This action is capable to input any characters including special keys like enter, backspace, insert, delete, etc.</div>
      <div class="tr tooltip-paragraph-fold">If you want to type big text, use 0 interval or "Set Clipboard" and type &lt;CONTROL&gt;V text.</div>
      <% if(_SelectorModel.get("is_image") == false){ %>
        <div class="tr tooltip-paragraph-fold">Disabling mouse move emulation will make it action act same as executing self.value = "value".</div> 
      <% } %>
      
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse will be moved to random point close to center before input.</div> 
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>


    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_waiter:true, use_move: true, use_emulation: true, name: tr("Type Text"), wiki: "how_to_type_text"}) %>
  </script>

  <script type="text/template" id="exist">
    <div class="container-fluid exist">
      <%= _.template($('#path').html())({selector:selector, hide_options:true, waitelement: false, failaction: false}) %>

      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "IS_EXISTS", help: {description: tr("Check result with boolean type. Could be true or false. Use \"if\" action to process it."), examples:[{code:"true",description:tr("Element found")},{code:"false",description:tr("Element not found")}]}}) %>
      <%= _.template($('#checkbox').html())({id: "Check", additional_classes: "disable-if-find-by-image", title: tr("Also check if visible on a screen")}) %>


    </div>


    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Checks if element exists on page.</div>
      <div class="tr tooltip-paragraph-fold">This action returns instantly.</div>
      <div class="tr tooltip-paragraph-fold">It writes result to variable which is true or false, use "if" action to process it.</div> 
      <div class="tr tooltip-paragraph-last-fold">If "Check if visible on a screen" is checked, action returns true only if element exists and visible on screen.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, name: tr("Is Element Exists"), wiki: "how_to_check_if_page_element_exists"}) %>
  </script>

  <script type="text/template" id="style">
    <div class="container-fluid style">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_STYLE", help: {description: tr("Computed style as a string.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Style To Check"), default_selector: "string", disable_int:true, help: {description: tr("Css value to check. Internally this action calls window.getComputedStyle(self)."), examples:[{code:"display",description:tr("Check visibility")},{code:"width",description:tr("Get width")}]}}) %>
    </div>
    <div class="tooltipinternal ">
      <div class="tr tooltip-paragraph-first-fold">Get element css style.</div>
      <div class="tr tooltip-paragraph-fold">Use "display" to check if element is visible, "width" to check element width etc.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_timeout:true, name: tr("Get Element Style")}) %>
  </script>

  <script type="text/template" id="check">
    <div class="container-fluid check">
      <%= _.template($('#path').html())({selector:selector}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Check cehckbox. Works only on checkboxes.</div>
    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_move: true, use_emulation: true, name: tr("Set Checkbox")}) %>
  </script>

  <script type="text/template" id="waitelement">
    <span class="path2">
      <div class="container-fluid waitelement">
       <%= _.template($('#path').html())({selector:selector, disable_options:true}) %>
       <%= _.template($('#checkbox').html())({id: "Check", title: tr("Also check if visible on a screen"), additional_classes: "disable-if-find-by-image"}) %>
      </div>
      <div class="tooltipinternal">
        <div class="tr tooltip-paragraph-first-fold">Wait while matching query element exists on page.</div>
        <div class="tr tooltip-paragraph-fold">If "Check if visible on a screen" is checked, action ends only if element exists and visible on screen.</div>
        <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
      </div>
      <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Wait While Element Exists")}) %>
    </span>
  </script>

  <script type="text/template" id="focus">
    <div class="container-fluid focus">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#checkbox').html())({id: "Check", title: tr("Use mouse wheel or touch")}) %>
    </div>
    <%= _.template($('#scrollparamsfields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action ensures that certian element is visible on screen.</div>
      <div class="tr tooltip-paragraph-fold">If element is already visible, than this action will do nothing, otherwise it will scroll viewport in such way, that element are located as close as possible to screen center.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_scroll_params: true, use_emulation: true, name: tr("Scroll To Element")}) %>
  </script>

  <script type="text/template" id="set">
    <div class="container-fluid set">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Set String"), default_selector: "string", disable_int:true, help: {description: tr("String which contains exact value present in combobox")}}) %>
    </div>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set combobox value to desired string. Works only on comboboxes(not text input).</div>
      <div class="tr tooltip-paragraph-fold">In case if combobox don't contain default markup, this function won't work. In that case, use "Set Combobox Index" action instead.</div>
      <div class="tr tooltip-paragraph-fold">You can use "type text" action to set combobox value. Click on combobox inside browser and select "Type Text" option, than input desired value or several first letters with &lt;RETURN&gt; at the end. For example, if combobox contains two values: male and female, you can select male by typing male&lt;RETURN&gt; or ma&lt;RETURN&gt;.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_emulation: true, name: tr("Set Combobox Value"), wiki: "how_to_set_combobox"}) %>
  </script>

  <script type="text/template" id="set_integer">
    <div class="container-fluid set_integer">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Set Index"), default_selector: "int", disable_string:true, help: {description: tr("Integer which contains combobox index starting from zero")}}) %>
    </div>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set combobox index to desired int. Works only on comboboxes(not text input).</div>
      <div class="tr tooltip-paragraph-fold">You can use "type text" action to set combobox value. Click on combobox inside browser and select "Type Text" option, than input desired value or several first letters with &lt;RETURN&gt; at the end. For example, if combobox contains two values: male and female, you can select male by typing male&lt;RETURN&gt; or ma&lt;RETURN&gt;.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_emulation: true, name: tr("Set Combobox Index"), wiki: "how_to_set_combobox"}) %>
  </script>

  <script type="text/template" id="set_random">
    <div class="container-fluid set_random">
      <%= _.template($('#path').html())({selector:selector}) %>
    </div>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set combobox index to random int. Works only on comboboxes(not text input).</div>
      <div class="tr tooltip-paragraph-fold">In case if combobox don't contain default markup, this function won't work. In that case, use "Set Combobox Index" action instead.</div>
      <div class="tr tooltip-paragraph-fold">You can use "type text" action to set combobox value. Click on combobox inside browser and select "Type Text" option, than input desired value or several first letters with &lt;RETURN&gt; at the end. For example, if combobox contains two values: male and female, you can select male by typing male&lt;RETURN&gt; or ma&lt;RETURN&gt;.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, use_emulation: true, name: tr("Set Combobox To Random"), wiki: "how_to_set_combobox"}) %>
  </script>

  <script type="text/template" id="attr">
    <div class="container-fluid attr">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "SAVED_ATTRIBUTE", help: {description: tr("This variable will contain element attribute value as a string")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Attribute Name"), default_selector: "string", disable_int:true, help: {description: tr("Attribute name as a string."), examples:[{code:"id",description:tr("Get element id")},{code:"style",description:tr("Get element styles")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get html attribute of selected element.</div>
      <div class="tr tooltip-paragraph-fold">For example, if element is a link and has following markup &lt;a href="https://google.com"&gt;google&lt;/a&gt;, than you can find reference by getting attribute href.</div>
      <div class="tr tooltip-paragraph-fold">If element has markup &lt;div id="message"&gt;text&lt;/a&gt;, you can get id by selecting attribute id.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_timeout:true, name: tr("Get Element Attribute")}) %>
  </script>

  <script type="text/template" id="set_attr">
    <div class="container-fluid attr">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#input_constructor').html())({id:"Name", description:tr("Attribute Name"), default_selector: "string", disable_int:true, help: {description: tr("Attribute name as a string.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Value", description:tr("Attribute Value"), default_selector: "string", disable_int:true, help: {description: tr("This variable contains element attribute value as a string")}}) %>

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Set html attribute of given element.</div>
      <div class="tr tooltip-paragraph-fold">For example, you can change id of element with markup &lt;div id="message-old"&gt;text&lt;/a&gt; if you use this action with parameters id and message-new.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_timeout:true, name: tr("Set Element Attribute")}) %>
  </script>

  <script type="text/template" id="captcha">
    <div class="container-fluid captcha">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "CAPTCHA_RESULT", help: {description: tr("String with captcha result")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Method", description:tr("Solve Method"), default_selector: "string", disable_int:true, value_string: "manual", variants: ["manual","antigate","rucaptcha","2captcha","xevil","capmonster","dbc","captchasniper"], size: 3, help: {description: tr("Solve method is a string, you can set value directly or use variable or resource."), examples:[{code:"manual",description:tr("Image is solved directly by person who uses BAS.")},{code:"antigate",description:tr("Solve with http://anti-captcha.com/ service")},{code:"rucaptcha",description:tr("Solve with http://rucaptcha.com/ service")},{code:"2captcha",description:tr("Solve with http://2captcha.com/ service")},{code:"capmonster",description:tr("Use capmonster")},{code:"dbc",description:tr("Use http://deathbycaptcha.com/ service")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"Antigate", description:tr("Antigate/Rucaptcha/2captcha/DBC Key. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("This key is needed only if you are using services to solve captcha. It is not needed in manual, capmonster and captchasniper modes. In case of deathbycaptcha this field must contain dbc_login:dbc:password.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Server", description:tr("Server url. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("String which contains server url."), examples:[{code:"http://127.0.0.3:8083/"},{code:tr("Empty string"), description: tr("Use default server url, http://rucaptcha.com for rucaptcha, etc")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action solves image captcha(not recaptcha). Image is obtained as result of element render.</div>
      <div class="tr tooltip-paragraph-fold">Captcha text is saved to variable and can be used later.</div>
      <div class="tr tooltip-paragraph-fold">If you want take image from cache, from file or from any base64 string, you should use "Solve Captcha" action from "Browser" module.</div>
      <div class="tr tooltip-paragraph-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">If you want to solve recaptcha, click on recaptcha checkbox inside browser and choose "Solve Recaptcha 2.0" action.</div> 
      <div class="tr tooltip-paragraph-fold">Rendering element can leave additional image border or slightly change color of some pixels due to render inaccuracies, and thus this method is good only if your captcha will be solved by human. In case of automatic machine solver it is important to get captcha picture execatly the same as generated on server, thats why if you use capmonster, captchasniper or xevil, this action will take image from cache. Taking image from cache is not automatic, at first run you will get error which gives captcha url and name of action that you need to use, which is "Allow cache". It is important to partition constant url part and part which is always changes. You should replace changing part with * and leave as is constant part. For example, if you have /image?id=1234, than cache mask would be /image?id=*. Of cource, you can add every url to cache by using * mask, but that would increase memory consumption and may cause other bugs.</div>
      <div class="tr tooltip-paragraph-last-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Solve Captcha"),wiki: "how_to_solve_captcha"}) %>
  </script>
  
  <script type="text/template" id="clickextensionbutton">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"ExtensionId", description:tr("Extension id or name"), default_selector: "string", disable_int:true, help: {description: tr("Extension id or name. It is not necessary to input whole id or whole name, only its part is allowed."), examples:[{code:"padekgcemlokbadohgkifijomclgjgif",description:tr("Trigger extension with id padekgcemlokbadohgkifijomclgjgif.")},{code:"padekgcem",description:tr("Trigger extension, which id contains padekgcem.")},{code:"Proxy SwitchyOmega",description:tr("Trigger extension by name.")},{code:"Proxy",description:tr("Trigger extension by name part.")}]}}) %>

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Click on extension button.</div>
      <div class="tooltip-paragraph-fold"><span class="tr">Executing this action is same as clicking on following</span> <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/lib/exe/fetch.php?cache=&media=chrome_2021-05-15_12-50-15.png');return false" class="tr">button</a>.</div>
      <div class="tr tooltip-paragraph-fold">Extension must be installed first before this action can be used. Use "Browser settings" action to install extension.</div>
      <div class="tooltip-paragraph-last-fold"><span class='tr'>More information about using extensions can be found on this this</span> <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=using_extensions');return false" class="tr-en">page</a><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=ru:using_extensions');return false" class="tr-ru">странице</a>.</div> 
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, waiter_enabled: true, use_waiter: true, use_timeout:true}) %>
  </script>

  <script type="text/template" id="touch">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Enable", description:tr("Use touch screen"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("Enable touch screen for current browser session."), examples:[{code:"true",description:tr("Enable touch screen")},{code:"false",description:tr("Desktop mode")}]}}) %>

      
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Enable touch screen.</div>
      <div class="tr tooltip-paragraph-fold">Touch screen will be enabled automatically after changing fingerprint, so this action is not required to call explicitly.</div>
      <div class="tr tooltip-paragraph-fold">In touch mode browser will behave exactly the same as mobile browser: mouse movement events won't be sent, click events will be replaced with touch events, lots of browser internal methods will be modified, etc.</div>
      <div class="tr tooltip-paragraph-fold">Special keys like TAB, CTRL or arrows will remain functional, but browser won't receive any notifications about these events.</div> 
      <div class="tr tooltip-paragraph-last-fold">Mouse wheel will be replaced with swipes.</div> 
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="screenshot">
    <div class="container-fluid">
      <%= _.template($('#path').html())({selector:selector}) %>
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable to save screenshot as base64"), default_variable: "SCREENSHOT_BASE64", help: {description: tr("After action will finish, this variable will contain base64 encoded image data, you can use it as captcha or write to file.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">This action makes screenshot of selected element and saves it to png image encoded as base64 string.</div>
      <div class="tr tooltip-paragraph-last-fold">If element is not visible, page will be scrolled.</div> 
      <div class="tr tooltip-paragraph-fold">If element won't be found instantly, BAS will wait while it will appear for one minute. If element won't be found for 10 seconds, notice will be written to log and if it won't be found for a minute, BAS will stop thread with error. You can handle this error if you uncheck "Fail thread if element not found" checkbox(at page top) or if you wrap this action in ignore error. You can also set max wait time by clicking on hourglass icon near cancel button.</div>

      </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true,use_timeout: true, name: tr("Screenshot")}) %>
  </script>


  <script type="text/template" id="length">
    <span class="path2">

    

    <div class="container-fluid length">
      <%= _.template($('#variable_constructor').html())({id:"Save", description:tr("Variable To Save"), default_variable: "ELEMENT_LENGTH", help: {description: tr("After action will finish this variable will contain number of elements matching selector.")}}) %>

      <%= _.template($('#path').html())({selector:selector, disable_options:true, is_multiple_elements: true}) %>

    </div>


    <%= _.template($('#multiselect').html())() %>
    </span>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get elements number matching query.</div>
      <div class="tr tooltip-paragraph-fold">To generate query, click on element inside browser and select "Get Element Count" action. BAS will automatically guess, which elements are similar to element that you have chosen and select them. This prediction won't always be correct, so you can tweak it in following way. Add element, which selection must include by selecting it and clicking with left button. This will create green background for element, it always will be included into selection. Alternatively click on element, which was inсluded into selection(elements with blue background). This will create red background for element, it always will be excluded from selection. By сonstantly clarifying which elements will be in the cycle and which will not, you can gradually achieve an acceptable result.</div>

      <div class="tr tooltip-paragraph-fold">This action always returns immediately and doesn't wait in case if element doesn't exist.</div>
      <div class="tr tooltip-paragraph-fold">In case of absence of an element it returns zero.</div> 
      <div class="tr tooltip-paragraph-last-fold">You can iterate through all elements which match certain selector, for example selector by class "c". To do that you should get number of elements with this action, than start for loop from 0 to element length - 1. And finally select element with &gt;CSS&gt; .c &gt;AT&gt; [[CYCLE_INDEX]] inside loop.</div> 
      
    </div>

    <%= _.template($('#back').html())({action:"executeandadd", visible:true, name: tr("Get Element Count")}) %>

  </script>

  <script type="text/template" id="loopelement">
    <span class="path2">

    <div class="container-fluid loopelement">
      <%= _.template($('#path').html())({selector:selector,disable_options:true, is_multiple_elements: true}) %>
    </div>

    <%= _.template($('#multiselect').html())() %>
    </span>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Starts loop which iterates over all elements matching query.</div>
      <div class="tr tooltip-paragraph-fold">To start loop, click on element inside browser and choose Start Loop action. BAS will automatically guess, which elements are similar to element that you have chosen and create loop over them. This prediction won't always be correct, so you can tweak it in following way. Add element, which loop must include by selecting it and clicking with left button. This will create green background for element, it always will be included into loop. Alternatively click on element, which was inсluded into loop(elements with blue background). This will create red background for element, it always will be excluded from loop. By сonstantly clarifying which elements will be in the cycle and which will not, you can gradually achieve an acceptable result.</div>
      <div class="tr tooltip-paragraph-fold">You also can write selector manually. For example, selector &gt;CSS&gt; a will find all links on page, &gt;CSS&gt; .my-class will find elements by class, etc.</div>
      <div class="tr tooltip-paragraph-fold">Clicking ok button will create a loop. Than you need to put some actions inside loop body, every action which you will put there will be executed for each element matching query. To add action click on any element inside browser and select action, which you want to perform. Select "Element from the loop" in order to execute action for each element in the loop. BAS creates selector for your action automatically.</div>
      <div class="tr tooltip-paragraph-fold">You can also iterate over element with "Get Elements Count" action.</div> 
      <div class="tr tooltip-paragraph-fold">Selectors created by BAS usually looks like this [[FOR_EACH_CSS]]&gt;AT&gt;[[CYCLE_INDEX]] and you can update them. For example, if you want to get subelement, change selector like this [[FOR_EACH_CSS]]&gt;AT&gt;[[CYCLE_INDEX]]&gt;CSS&gt; your subselector.</div>
      <div class="tr tooltip-paragraph-fold">Not only element actions may be used inside loop, but any other action like: log, writing to file, etc.</div>
      <div class="tr tooltip-paragraph-last-fold">This type of cycle has small delay between each step, so if you want to parse page very fast, get page source and use xpath or regular expression.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false,use_timeout: true, name: tr("Start Loop"), wiki: "how_to_iterate_over_elements"}) %>
  </script>

  <script type="text/template" id="move">
    <div class="container-fluid move">
      <%= _.template($('#input_constructor').html())({id:"MoveX", description:tr("Move x position"), default_selector: "int", disable_string:true, value_number: model['x'], help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"MoveY", description:tr("Move y position"), default_selector: "int", disable_string:true, value_number: model['y'], help: {description: tr("Integer value, offset from the top edge of the page")}}) %>
    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Move cursor to given coordinates.</div>
      <div class="tr tooltip-paragraph-fold">If you want to move on element, select it inside browser and choose "Move On Element".</div>
      <div class="tr tooltip-paragraph-fold">This action works with absolute coordinates.</div> 
      <div class="tr tooltip-paragraph-fold">If coordinates is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-last-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_move: true, use_emulation: true, name: tr("Move"), wiki: "how_to_move_mouse"}) %>
  </script>

  <script type="text/template" id="click">
    <div class="container-fluid click">
      <%= _.template($('#input_constructor').html())({id:"ClickX", description:tr("Click x position"), default_selector: "int", disable_string:true, value_number: model['x'], help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ClickY", description:tr("Click y position"), default_selector: "int", disable_string:true, value_number: model['y'], help: {description: tr("Integer value, offset from the top edge of the page")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Click on given coordinates.</div>
      <div class="tr tooltip-paragraph-fold">If you want to click on element, select it inside browser and choose "Click On Element".</div>
      <div class="tr tooltip-paragraph-fold">This action works with absolute coordinates.</div> 
      <div class="tr tooltip-paragraph-fold">If coordinates is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-last-fold">If you are clicking on some element, which causes page load, you should select "wait for full page load". Using this option will make browser wait for page load after click.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,use_timeout:true, visible:true, name: tr("Click"), wiki:"how_to_click_on_x_y_coordinates"}) %>
  </script>

  <script type="text/template" id="drag">
    <div class="container-fluid move">
      <%= _.template($('#input_constructor').html())({id:"X", description:tr("Drag x position"), default_selector: "int", disable_string:true, value_number: model['x'], help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Y", description:tr("Drop y position"), default_selector: "int", disable_string:true, value_number: model['y'], help: {description: tr("Integer value, offset from the top edge of the page")}}) %>
    </div>
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Start drag from given coordinates.</div>
      <div class="tr tooltip-paragraph-fold">If you want to drag from element, select it inside browser and choose "Drag On Element".</div>
      <div class="tr tooltip-paragraph-fold">This action works with absolute coordinates.</div> 
      <div class="tr tooltip-paragraph-fold">If coordinates is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-fold">If you used this action, you must also call "Drop" or "Drop On Element" action.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to drag file from outside of browser, use "Start Drag File" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_move: true, use_emulation: true, name: tr("Drag")}) %>
  </script>

  <script type="text/template" id="drop">
    <div class="container-fluid move">
      <%= _.template($('#input_constructor').html())({id:"X", description:tr("Drop x position"), default_selector: "int", disable_string:true, value_number: model['x'], help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Y", description:tr("Drop y position"), default_selector: "int", disable_string:true, value_number: model['y'], help: {description: tr("Integer value, offset from the top edge of the page")}}) %>
    </div>
    <%= _.template($('#movefields').html())({}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Drop to given coordinates.</div>
      <div class="tr tooltip-paragraph-fold">If you want to drop to element, select it inside browser and choose "Drop On Element".</div>
      <div class="tr tooltip-paragraph-fold">This action works with absolute coordinates.</div> 
      <div class="tr tooltip-paragraph-fold">If coordinates is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-last-fold">Before using this action, you must also call "Drag" or "Drag On Element" action.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_move: true, name: tr("Drop")}) %>
  </script>

  <!-- Tabs templates -->

  <script type="text/template" id="addtab">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Url", description:tr("Url"), default_selector: "string", disable_int:true, help: {description: tr("Url to load. Protocol may be omitted."), examples:[{code:"google.com",description:tr("Load google.com")},{code:"instagram.com",description:tr("Load instagram.com")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"IsSilent", description:tr("Load silently"), default_selector: "string", disable_int:true, value_string: "false", variants: ["true","false"], help: {description: tr("Adding tab silently means, that new tab will be added and specified url will be loaded only when the tab becomes active for the first time."),examples:[{code:"true",description:tr("Create new tab, load specified url only when tab gets switched to.")},{code:"false",description:tr("Create new tab, switch to it and load it immediately.")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"Referrer", description:tr("Referrer. Can be blank"), default_selector: "string", disable_int:true, help: {description: tr("Referrer used for current page load."), examples:[{code:"https://google.com",description:tr("Page is loaded by clicking on google search result.")},{code:tr("Empty string"),description:tr("Page is loaded by typing url in address bar.")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Add a new tab with the specified Url.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true, waiter_enabled: true, use_timeout:true, visible:true, name: tr("Add Tab")}) %>
  </script>

  <script type="text/template" id="selecttab">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Index", description:tr("Tab Index"), default_selector: "int", disable_string:true, value_number: model['index'], min_number:0, max_number:999999}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Switch to the tab with the specified index.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, name: tr("Select Tab")}) %>
  </script>

  <script type="text/template" id="tabinfo">
    <div class="container-fluid">
      <%= _.template($('#variable_constructor').html())({id:"UrlList", description:tr("Url list"), default_variable: "URL_LIST", help: {description: tr("List of urls. Each url corresponds to one tab.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"TotalTabs", description:tr("Number of tabs"), default_variable: "TOTAL_TABS", help: {description: tr("Total number of tabs.")}}) %>
      <%= _.template($('#variable_constructor').html())({id:"CurrentIndex", description:tr("Current tab index"), default_variable: "TAB_INDEX", help: {description: tr("Index of current tab. Index starts with 0.")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Get list of tabs, index of current tab and save it to variables.</div>
      <div class="tr tooltip-paragraph-fold">Variable [[URL_LIST]] will contain list of urls. Each url corresponds to one tab. Use "List" module to process it. For example, action "First Element" can get url of first tab, action "Get Element" can get url of specified tab.</div>
      <div class="tr tooltip-paragraph-last-fold">Variable [[TAB_INDEX]] will hold index of active tab. Index starts from 0, so first tab will have index 0, second tab - index 1, etc.</div> 
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",visible:true, name: tr("Get information about tabs")}) %>
  </script>

  <script type="text/template" id="closetab">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"Index", description:tr("Tab Index"), default_selector: "int", disable_string:true, value_number: model['index'], min_number:1, max_number:999999}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Close tab with the specified index.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd",visible:true, name: tr("Close Tab")}) %>
  </script>

  <script type="text/template" id="threadnumber">
    <div class="container-fluid threadnumber">
      <%= _.template($('#input_constructor').html())({id:"ThreadNumber", description:tr("Thread number"), default_selector: "int", disable_string:true, disable_string:true, disable_variable:true, min_number: 1}) %>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

  <script type="text/template" id="failnumber">
    <div class="container-fluid failnumber">
      <%= _.template($('#input_constructor').html())({id:"FailNumber", description:tr("Fail number"), default_selector: "int", disable_string:true, disable_string:true, disable_variable:true, min_number: 1}) %>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

  <script type="text/template" id="successnumber">
    <div class="container-fluid successnumber">
      <%= _.template($('#input_constructor').html())({id:"SuccessNumber", description:tr("Success number"), default_selector: "int", disable_string:true, disable_string:true, disable_variable:true, min_number: 1}) %>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

  <script type="text/template" id="moveandclick">
    <div class="container-fluid moveandclick">
      <%= _.template($('#input_constructor').html())({id:"X", description:tr("Move and click x position"), default_selector: "int", disable_string:true, value_number: model['x'], help: {description: tr("Integer value, offset from the left edge of the page")}}) %>
      <%= _.template($('#input_constructor').html())({id:"Y", description:tr("Move and click y position"), default_selector: "int", disable_string:true, value_number: model['y'], help: {description: tr("Integer value, offset from the top edge of the page")}}) %>
      
      <%= _.template($('#checkbox').html())({id: "Check2", title: tr("Hold ctrl key. Open link in a new tab.")}) %>

      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), smaller_fonts: true, description: tr("")}) %>
        <%= _.template($('#mouseclicksettings').html())() %>
      <%= _.template($('#block_end').html())() %>
    </div>
    
    <%= _.template($('#movefields').html())({}) %>
    <%= _.template($('#emulationfields').html())({additionalEmulation: true}) %>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Move mouse and click on given coordinates.</div>
      <div class="tr tooltip-paragraph-fold">If you want to click on element, select it inside browser and choose "Move And Click On Element".</div>
      <div class="tr tooltip-paragraph-fold">This action works with absolute coordinates.</div> 
      <div class="tr tooltip-paragraph-fold">If coordinates is not visible, page will be scrolled.</div>
      <div class="tr tooltip-paragraph-fold">Mouse move trajectory is always random and reminds one made by human, you can twaek move parameters with settings button located near cancel.</div>
      <div class="tr tooltip-paragraph-last-fold">If you are clicking on some element, which causes page load, you should select "wait for full page load". Using this option will make browser wait for page load after click.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", use_waiter:true,use_timeout: true, use_move: true, use_emulation: true, visible:true, name: tr("Move And Click"), wiki: "how_to_click_on_x_y_coordinates"}) %>
  </script>

  <script type="text/template" id="type">
    <div class="container-fluid type">
      <%= _.template($('#input_constructor').html())({id:"TypeData", description:tr("Text to type"), default_selector: "string", disable_int:true, help: {description: tr("This could be any character sequence."), examples:[{code:"hello world!",description:tr("Input hello world!")},{code:"&lt;CONTROL&gt;V",description:tr("Paste text")},{code:"&lt;CONTROL&gt;A&lt;DELETE&gt;",description:tr("Clear input")},{code:"&lt;ESCAPE&gt;",description:tr("Press escape")}]}}) %>
      <%= _.template($('#block_start').html())({id: "SpecialKeys", name: tr("Special keys"), description: tr("")}) %>
        <%= _.template($('#special_buttons').html())({}) %>
      <%= _.template($('#block_end').html())() %>
      
      <%= _.template($('#block_start').html())({id: "Advanced", name: tr("Additional settings"), description: tr("")}) %>
        <%= _.template($('#input_constructor').html())({id:"TypeInterval", description:tr("Interval in milliseconds"), default_selector: "int", disable_string:true, value_number: 100, step_number: 100, min_number: 0, max_number:10000, help: {description: tr("Interval between each key press in milliseconds. BAS uses different interval for every key which is close to this parameter. For example, if you set interval to 100, that could result following sequence: key #1, wait 91 millisecond, key #2, wait 117 millisecond, key #3, etc"), examples:[{code:"100",description:tr("Default value. Human like input emulation.")},{code:"0",description:tr("Text is entered instantly.")}]}}) %>
      <%= _.template($('#block_end').html())() %>
      

    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Type text inside element with focus.</div>
      <div class="tr tooltip-paragraph-fold">If you want to type inside specific element, click on it and choose "Type Text".</div>
      <div class="tr tooltip-paragraph-fold">This action is capable to input any characters including special keys like enter, backspace, insert, delete, etc.</div> 
      <div class="tr tooltip-paragraph-last-fold">If you want to type big text, use 0 interval or "Set Clipboard" and type &lt;CONTROL&gt;V text.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, use_waiter:true, use_timeout: true, name: tr("Type Text"), wiki: "how_to_type_text"}) %>
  </script>

  <script type="text/template" id="resize">
    <div class="container-fluid">
      <%= _.template($('#input_constructor').html())({id:"ResizeX", description:tr("Width"), default_selector: "int", disable_string:true,value_number: 1024, step_number: 1, min_number: 100, max_number:10000, help: {description: tr("Browser width in pixels")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ResizeY", description:tr("Height"), default_selector: "int", disable_string:true,value_number: 768, step_number: 1, min_number: 100, max_number:10000, help: {description: tr("Browser height in pixels")}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Changes browser resolution. Standart value is 1024x600. If you want to get typical resolutions for different platforms, use service <a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://fp.bablosoft.com'); return false;">fingerprint switcher</a>.</div>
      <span class="short-description tr">Changes browser resolution. Standart value is 1024x600.</span>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:false}) %>
  </script>

  <script type="text/template" id="proxy">
    <div class="container-fluid" >
      <%= _.template($('#input_constructor').html())({id:"ProxyText", description:tr("Proxy String"), default_selector: "string", disable_int:true, help: {description: tr("String with information about proxy. It may contain ip, port, proxy type in different formats. This string may also contain login and password, if it doesn't, auth can be set with \"Proxy Login\" and \"Proxy Password\" parameters."), examples:[{code:"210.10.10.10:1085"},{code:"username:password@210.10.10.10:1085"},{code:"socks5://210.10.10.10:1085"},{code:"socks:210.10.10.10:1085:username:password"},{code:"http:username:password:210.10.10.10:1085"},{code:"{{proxy}}", description: tr("Get from resource")},{code:tr("Empty string"),description:tr("Without proxy")}   ]}}) %>


      <%= _.template($('#input_constructor').html())({id:"ProxyType", description:tr("Proxy Type"), default_selector: "string", disable_int:true, value_string: "http", variants: ["http","socks5","auto<br/><span style='color:gray;font-size:small'>" + tr("Proxy type will be extracted from proxy line") + "</span>"], help: {description: tr("socks5 and http proxy types are supported."), examples:[{code:"socks"},{code:"socks5",description:tr("Same as socks")},{code:"http"},{code:"https",description:tr("Same as http")}]}}) %>
      <%= _.template($('#input_constructor').html())({id:"ProxyLogin", description:tr("Proxy Login. Can be blank."), default_selector: "string", disable_int:true, help: {description: tr("Proxy login, overrides login set in proxy string. Useful if you have many proxy with same login and password.")}}) %>
      <%= _.template($('#input_constructor').html())({id:"ProxyPassword", description:tr("Proxy password. Can be blank."), default_selector: "string", disable_int:true, help: {description: tr("Proxy password, overrides password set in proxy string. Useful if you have many proxy with same login and password.")}}) %>


    <%= _.template($('#block_start').html())({id: "SecuritySettings", name: tr("Security settings"), description: tr("Options below will help you to adjust different browser settings to match new proxy, for example: timezone and geolocation. Default settings will work fine.")}) %>

      <%= _.template($('#input_constructor').html())({id:"ChangeTimezone", description:tr("Change timezone"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("Change browser timezone according to proxy ip. For example, if proxy is located in United Kingdom, then browser timezone offset will be equal to 0(UTC+00:00). You can set timezone to custom value with 'Timezone' module."),examples:[{code:"true",description:tr("Change timezone.")},{code:"false",description:tr("Don't change timezone.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"ChangeGeolocation", description:tr("Change geolocation"), default_selector: "string", disable_int:true, value_string: "false", variants: ["true","false"], help: {description: tr("Change browser geolocation according to proxy ip. Location will be set to a point which is close to proxy longitude/latitude. You can set geolocation to custom value with 'Timezone' module."),examples:[{code:"true",description:tr("A browser request to access your geolocation will be accepted. Browser location will be set to proxy location.")},{code:"false",description:tr("Don't change geolocation. A browser request to access your geolocation will be rejected.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"ChangeBrowserLanguage", description:tr("Change browser language"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("Change browser language according to country of proxy. This setting will change 'Accept-Language' header as well as navigator.language and navigator.languages javascript properties. By default language value will be equal to language and country code separated with dash, for example 'de-DE' for Germany. This value is valid, but most browsers uses more complicated strings. If you want to make BAS look like real browser, use FingerprintSwitcher service, it will set language to more natural value, for example for iPhone from Germany it will equal 'de, en;q=0.8, *;q=0.01'. You can also set this value explicitly by using 'Set Header' action"),examples:[{code:"true",description:tr("Change browser language according to proxy country.")},{code:"false",description:tr("Don't change browser language, default will be 'en-US,en;q=0.9'.")}]}}) %>

    <%= _.template($('#block_end').html())() %>


    <%= _.template($('#block_start').html())({id: "WebRTC", name: tr("WebRTC settings"), description: tr("The options below allow you to set a IPs exposed through WebRTC. Default settings will work fine.")}) %>

      <%= _.template($('#input_constructor').html())({id:"ChangeWebrtcIp", description:tr("WebRTC mode"), default_selector: "string", disable_int:true, value_string: "replace", variants: ["disable<br/><span style='color:gray;font-size:small'>" + tr("Disable WebRTC") + "</span>","enable<br/><span style='color:gray;font-size:small'>" + tr("Enable WebRTC, route all requests through proxy. Requires proxy to support UDP") + "</span>","replace<br/><span style='color:gray;font-size:small'>" + tr("Enable WebRTC, replace exposed IPs with specified values") + "</span>"], help: {description: tr("This option defines how WebRTC replacement will work. If you want to change it without setting proxy, please use 'Browser Settings' action."),examples:[{code:"disable",description:tr("Disable WebRTC API completely")},{code:"enable",description:tr("Enable WebRTC with all requests routed through the proxy. Ensure the proxy supports UDP for requests to complete successfully.")},{code:"replace",description:tr("Enable WebRTC, replace exposed IPs with values specified below.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"PublicIPv4", description:tr("Public IPv4"), default_selector: "string", disable_int:true, value_string: "auto", variants: ["auto<br/><span style='color:gray;font-size:small'>" + tr("Detect external IPv4 automatically") + "</span>", "disable"], help: {description: tr("Specify the external IPv4 address which will be exposed through WebRTC. This option is applicable only when the 'WebRTC mode' is set to 'replace'. It is highly recommended to use the default value, 'auto', but you can also provide an exact IP address if needed. If you want to change it without setting proxy, please use 'Browser Settings' action."),examples:[{code:"auto",description:tr("Detect external IPv4 automatically based on settings located in 'IP detection tab'")},{code:"123.123.123.123",description:tr("Exact IPv4 address may be specified.")},{code:"disable",description:tr("Don't expose public IPv4 through WebRTC.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"PublicIPv6", description:tr("Public IPv6"), default_selector: "string", disable_int:true, value_string: "auto", variants: ["auto<br/><span style='color:gray;font-size:small'>" + tr("Detect external IPv6 automatically") + "</span>", "disable"], help: {description: tr("Specify the external IPv6 address which will be exposed through WebRTC. This option is applicable only when the 'WebRTC mode' is set to 'replace'. It is highly recommended to use the default value, 'auto', but you can also provide an exact IP address if needed. If you want to change it without setting proxy, please use 'Browser Settings' action."),examples:[{code:"auto",description:tr("Detect external IPv6 automatically based on settings located in 'IP detection tab'. If proxy doesn't support IPv6, no address will be exposed.")},{code:"2001:0db8:85a3:0000:0000:8a2e:0370:7334",description:tr("Exact IPv6 address may be specified.")},{code:"disable",description:tr("Don't expose public IPv6 through WebRTC.")} ]}}) %>

      <%= _.template($('#input_constructor').html())({id:"PrivateIPv4", description:tr("Private IPv4"), default_selector: "string", disable_int:true, value_string: "local", variants: ["local<br/><span style='color:gray;font-size:small'>" + tr("Replace with local name, like 3cd88d80-5c8a-40c4-85e8-30b4078e78ec.local") + "</span>", "private class a<br/><span style='color:gray;font-size:small'>" + tr("10.0.0.0 - 10.255.255.255") + "</span>", "private class b<br/><span style='color:gray;font-size:small'>" + tr("172.16.0.0 - 172.31.255.255") + "</span>", "private class c<br/><span style='color:gray;font-size:small'>" + tr("192.168.0.0 - 192.168.255.255") + "</span>", "disable"], help: {description: tr("Specify the internal IPv4 address which will be exposed through WebRTC. This option is applicable only when the 'WebRTC mode' is set to 'replace'. If you want to change it without setting proxy, please use 'Browser Settings' action."),examples:[{code:"local",description:tr("Replace an exposed internal IPv4 address revealed by WebRTC with a randomly generated local address, like this: 3cd88d80-5c8a-40c4-85e8-30b4078e78ec.local")},{code:"private class a",description:tr("10.0.0.0 - 10.255.255.255")},{code:"private class b",description:tr("172.16.0.0 - 172.31.255.255")},{code:"private class c",description:tr("192.168.0.0 - 192.168.255.255")},{code:"123.123.123.123",description:tr("Exact IPv4 address may be specified.")},{code:"disable",description:tr("Don't expose private IPv4 through WebRTC.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"PrivateIPv6", description:tr("Private IPv6"), default_selector: "string", disable_int:true, value_string: "local", variants: ["local<br/><span style='color:gray;font-size:small'>" + tr("Replace with local name, like 3cd88d80-5c8a-40c4-85e8-30b4078e78ec.local") + "</span>", "unique local address<br/><span style='color:gray;font-size:small'>" + tr("FD00:0000:0000:0000:0000:0000:0000:0000 - FDFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") + "</span>", "disable"], help: {description: tr("Specify the internal IPv6 address which will be exposed through WebRTC. This option is applicable only when the 'WebRTC mode' is set to 'replace'. If you want to change it without setting proxy, please use 'Browser Settings' action."),examples:[{code:"local",description:tr("Replace an exposed internal IPv6 address revealed by WebRTC with a randomly generated local address, like this: 3cd88d80-5c8a-40c4-85e8-30b4078e78ec.local")},{code:"unique local address",description:tr("FD00:0000:0000:0000:0000:0000:0000:0000 - FDFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")}, {code:"fd01:0db8:85a3:0000:0000:8a2e:0370:7334",description:tr("Exact IPv6 address may be specified.")},{code:"disable",description:tr("Don't expose private IPv6 through WebRTC.")}]}}) %>

      

    <%= _.template($('#block_end').html())() %>

      <%= _.template($('#block_start').html())({id: "DNS", name: tr("Custom DNS"), description: tr("Below are the available options for Chromium's built-in custom DNS implementation. In real browser, this feature is enabled by default, and it is recommended to keep it enabled to improve privacy and authenticity.")}) %>

      <%= _.template($('#input_constructor').html())({id:"DNSMode", description:tr("DNS mode"), default_selector: "string", disable_int:true, value_string: "System DNS. Through proxy", variants: ["Custom DNS. Directly<br/><span style='color:gray;font-size:small'>" + tr("Recomended if you want to use custom DNS") + "</span>","Custom DNS. Through proxy<br/><span style='color:gray;font-size:small'>" + tr("Proxy must support UDP") + "</span>", "System DNS. Through proxy<br/><span style='color:gray;font-size:small'>" + tr("Safe option") + "</span>"], help: {description: tr("By default, the browser uses a custom DNS implementation that supports additional DNS features. If these features are missing, websites may detect the absence. Rather than relying on native OS DNS functions (like getaddrinfo), the custom DNS sends requests directly via UDP or TCP. BAS provides an option to enable this custom DNS feature, allowing you to route DNS traffic through a proxy or send UDP packets directly. Enabling custom DNS also requires specifying a DNS server IP. Although custom DNS is generally more difficult for websites to detect, they may still recognize that you are using a DNS server different from your ISP's default."),examples:[{code:"Custom DNS. Directly",description:tr("This is recomended option if you want to use custom DNS. Use Chrome's built-in custom DNS implementation to make DNS requests locally (via UDP or TCP), while routing all other traffic through the proxy.")},{code:"Custom DNS. Through proxy",description:tr("Use Chrome's built-in custom DNS implementation to make DNS requests through proxy. Proxy must support UDP.")},{code:"System DNS. Through proxy",description:tr("Use the system DNS implementation. All DNS queries will be handled by the proxy server, which uses its own DNS. The hostname is sent to the proxy as part of this process.")}]}}) %>

      <%= _.template($('#input_constructor').html())({id:"CustomDNSIP", description:tr("DNS IP(only for custom DNS)"), default_selector: "string", disable_int:true, value_string: "1.1.1.1", help: {description: tr("Using the custom Chrome DNS implementation requires specifying a DNS IP address. Unlike the default method - where the hostname is sent to the proxy and the proxy performs the DNS lookup - this approach resolves IP addresses locally, making it necessary to configure a DNS server IP for the browser. A valid DNS IP address is required when using the 'Custom DNS' mode for proper DNS resolution. If 'System DNS' mode is selected, this setting will have no effect."),examples:[{code:"1.1.1.1",description:tr("Cloudflare DNS.")}]}}) %>

    <%= _.template($('#block_end').html())() %>

    <%= _.template($('#block_start').html())({id: "IPDetection", name: tr("IP detection"), description: tr("The options below allow you to set a custom URL for external IP detection. By default, the ip4.bablosoft.com and ip6.bablosoft.com urls will be used, which is reliable for most cases.")}) %>

        <%= _.template($('#input_constructor').html())({id:"DetectExternalIp", description:tr("Detect external IPv4"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("Detect proxy's IPv4 by querying external service. BAS will use an ip4.bablosoft.com url to detect external IPv4 and will set timezone, geolocation and IPv4 exposed by WebRTC according to correct IPv4 value."),examples:[{code:"true",description:tr("Use external IPv4 obtained by service.")},{code:"false",description:tr("Don't use external service, disable possibility to obtain IPv6 through WebRTC.")}]}}) %>

        <%= _.template($('#input_constructor').html())({id:"ServiceURL", description:tr("Service URL"), default_selector: "string", disable_int:true, value_string: "", help: {description: tr("This service URL is used to detect the external IPv4 address. The URL will be queried through the currently installed proxy, and the response must contain the external IPv4 address."),examples:[{code:tr("Empty string"),description:tr("Default service http://ip4.bablosoft.com/ will be used.")},{code:"http://url.com/",description:tr("Custom URL to detect external IPv4.")}]}}) %>

        <%= _.template($('#input_constructor').html())({id:"IpExtractionMethod", description:tr("IPv4 extraction method"), default_selector: "string", disable_int:true, value_string: "raw", variants: [{value:"raw",description:tr("Treat the entire response as an IPv4 address")}, {value:"regexp",description:tr("Use regexp to extract IPv4 from response")}, {value:"jsonpath",description:tr("Use JSONPath to extract IPv4 from response")}, {value:"xpath",description:tr("Use XPath to extract IPv4 from response")}], help: {description: tr("After receiving a response from the service URL, the IPv4 address will be extracted from the response. This parameter specifies the method for extracting the IPv4 address. The 'IPv4 extraction param' must also be specified in combination with this parameter. Depending on the method used, the param will be treated differently. For example, if the 'regexp' method is used, the param must contain a regular expression, and so on."),examples:[{code:"raw",description:tr("The entire response will be treated as the IPv4 address without any processing. Use this parameter if the service URL returns only the IPv4 address without any additional information.")}, {code:"regexp",description:tr("Use regular expression to extract IPv4 address from response.")}, {code:"jsonpath",description:tr("Use JSONPath to extract IPv4 address from response. Useful if response has JSON format.")}, {code:"xpath",description:tr("Use Xpath to extract IPv4 address from response. Useful if response has HTML or XML format.")} ]}}) %>

        <%= _.template($('#input_constructor').html())({id:"IpExtractionParam", description:tr("IPv4 extraction param"), default_selector: "string", disable_int:true, value_string: "", variants: [{value:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}",description:tr("Standard regexp to extract IPv4")}], help: {description: tr("After receiving a response from the service URL, the IPv4 address will be extracted from the response. This parameter specifies the param for extracting the IPv4 address. This param will be treated differently depending on 'IPv4 extraction method'. For example, if the 'regexp' method is used, this param must contain a regular expression, and so on."),examples:[{code:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}",description:tr("Use specified regular expression to extract IPv4 from response. In order to work correctly, 'regexp' must be specified as 'IPv4 extraction method'.")}, {code:"Your ip: (?P&lt;result&gt;.*)",description:tr("By default regexp will extract whole match. If you want to extract only certain part of the match, place it within in the group with name 'result'.")}, {code:"$.result.ip",description:tr("Use JSONPath to extract IPv4 address from response. This JSONPath will extract data from JSON like this {\"result\": {\"ip\": \"111.111.111.111\"}}. In order to work correctly, 'jsonpath' must be specified as 'IPv4 extraction method'.")}, {code:"//result/ip",description:tr("Use Xpath to extract IPv4 address from response. This Xpath will extract data from HTML like this &lt;result&gt;&lt;ip&gt;111.111.111.111&lt;/ip&gt;&lt;/result&gt;. In order to work correctly, 'xpath' must be specified as 'IPv4 extraction method'.")} ]}}) %>

        <%= _.template($('#block_start').html())({id: "IPv6", name: tr("IPv6"), description: tr("Verify if the proxy supports an IPv6 interface and, if available, detect the external IPv6 address.")}) %>

          <%= _.template($('#input_constructor').html())({id:"DetectExternalIpV6", description:tr("Detect external IPv6"), default_selector: "string", disable_int:true, value_string: "true", variants: ["true","false"], help: {description: tr("Detect proxy's IPv6 by querying external service. BAS will use an ip6.bablosoft.com url to detect external IPv6 and will set IPv6 exposed by WebRTC according to detected value."),examples:[{code:"true",description:tr("Use external IPv6 obtained by service.")},{code:"false",description:tr("Don't use external service, don't expose IPv6 through WebRTC.")}]}}) %>

          <%= _.template($('#input_constructor').html())({id:"ServiceURLV6", description:tr("Service URL"), default_selector: "string", disable_int:true, value_string: "", help: {description: tr("This service URL is used to detect the external IPv6 address. The URL will be queried through the currently installed proxy, and the response must contain the external IPv6 address."),examples:[{code:tr("Empty string"),description:tr("Default service http://ip6.bablosoft.com/ will be used.")},{code:"http://url.com/",description:tr("Custom URL to detect external IPv6.")}]}}) %>

          <%= _.template($('#input_constructor').html())({id:"IpExtractionMethodV6", description:tr("IPv6 extraction method"), default_selector: "string", disable_int:true, value_string: "raw", variants: [{value:"raw",description:tr("Treat the entire response as an IPv6 address")}, {value:"regexp",description:tr("Use regexp to extract IPv6 from response")}, {value:"jsonpath",description:tr("Use JSONPath to extract IPv6 from response")}, {value:"xpath",description:tr("Use XPath to extract IPv6 from response")}], help: {description: tr("After receiving a response from the service URL, the IPv6 address will be extracted from the response. This parameter specifies the method for extracting the IPv6 address. The 'IPv6 extraction param' must also be specified in combination with this parameter. Depending on the method used, the param will be treated differently. For example, if the 'regexp' method is used, the param must contain a regular expression, and so on."),examples:[{code:"raw",description:tr("The entire response will be treated as the IPv6 address without any processing. Use this parameter if the service URL returns only the IPv6 address without any additional information.")}, {code:"regexp",description:tr("Use regular expression to extract IPv6 address from response.")}, {code:"jsonpath",description:tr("Use JSONPath to extract IPv6 address from response. Useful if response has JSON format.")}, {code:"xpath",description:tr("Use Xpath to extract IPv6 address from response. Useful if response has HTML or XML format.")} ]}}) %>

          <%= _.template($('#input_constructor').html())({id:"IpExtractionParamV6", description:tr("IPv6 extraction param"), default_selector: "string", disable_int:true, value_string: "", variants: [{value:"[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}|(([0-9a-fA-F]{1,4}:){1,7}:)|(:([0-9a-fA-F]{1,4}:){1,7})|::",description:tr("Standard regexp to extract IPv6")}], help: {description: tr("After receiving a response from the service URL, the IPv6 address will be extracted from the response. This parameter specifies the param for extracting the IPv6 address. This param will be treated differently depending on 'IPv6 extraction method'. For example, if the 'regexp' method is used, this param must contain a regular expression, and so on."),examples:[{code:"[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}|(([0-9a-fA-F]{1,4}:){1,7}:)|(:([0-9a-fA-F]{1,4}:){1,7})|::",description:tr("Use specified regular expression to extract IPv6 from response. In order to work correctly, 'regexp' must be specified as 'IPv6 extraction method'.")}, {code:"Your ip: (?P&lt;result&gt;.*)",description:tr("By default regexp will extract whole match. If you want to extract only certain part of the match, place it within in the group with name 'result'.")}, {code:"$.result.ip",description:tr("Use JSONPath to extract IPv6 address from response. This JSONPath will extract data from JSON like this {\"result\": {\"ip\": \"2001:0db8:85a3:0000:0000:8a2e:0370:7334\"}}. In order to work correctly, 'jsonpath' must be specified as 'IPv6 extraction method'.")}, {code:"//result/ip",description:tr("Use Xpath to extract IPv6 address from response. This Xpath will extract data from HTML like this &lt;result&gt;&lt;ip&gt;2001:0db8:85a3:0000:0000:8a2e:0370:7334&lt;/ip&gt;&lt;/result&gt;. In order to work correctly, 'xpath' must be specified as 'IPv6 extraction method'.")} ]}}) %>

        <%= _.template($('#block_end').html())() %>

    <%= _.template($('#block_end').html())() %>

      <%= _.template($('#ip_information').html())() %>

      <%= _.template($('#targetfields').html())({}) %>
    </div>

    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">By default browser works without proxy, this action sets browser proxy.</div>
      <div class="tr tooltip-paragraph-fold">Use resources if you want to take them from file, url or database.</div>
      <div class="tr tooltip-paragraph-fold">You can change proxy before or after browser created or page is loaded.</div> 
      <div class="tr tooltip-paragraph-fold">Proxy with empty parameter will reset it to default value(direct connection).</div>
      <div class="tr tooltip-paragraph-last-fold">'Security settings' will help you to adjust different browser settings to match new proxy, for example: timezone and geolocation. This will make your application less detectable, check information for each individual setting to understand what are they needed for. Default settings will work fine.</div>
    </div>

    <%= _.template($('#back').html())({action:"executeandadd",visible:true, wiki: "how_to_set_proxy"}) %>
  </script>

  _MACRO_INSERT_INTERFACE_

  <script type="text/template" id="log">
    <div class="container-fluid log">
      <%= _.template($('#input_constructor').html())({id:"LogText", description:tr("Data to Log"), default_selector: "string", help: {description: tr("Message text. Can contain variables and resources."), examples:[{code:"Script started",description:tr("Output string")},{code:"Account registered [[USERNAME]]:[[PASSWORD]]",description:tr("Message about account creation success")},{code:"Posting message {{post_data}}",description:tr("Output resource")}]}}) %>
    </div>
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Write message to log. This message will be shown to user and should inform him about events occurring during script execution.</div>
      <div class="tr tooltip-paragraph-fold">Log messages is also written to file.</div>
      <div class="tr tooltip-paragraph-fold">BAS will append some information to message: date, thread number, action id. Thats why this action is not good if you want to output raw data, account list for example. Use "Result" action to do that.</div>
      <div class="tr tooltip-paragraph-last-fold">If you want to change message color, use "Execute code" action and api call log_html(html, text).</div>
      <div class="tooltip-paragraph-last-fold"><span class="tr">If you want to output data to file only, use this</span> (<span class="tr-en"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=how_to_let_user_to_choose_output_file_name');return false">article</a></span><span class="tr-ru"><a href="#" onclick="BrowserAutomationStudio_OpenUrl('https://wiki.bablosoft.com/doku.php?id=ru:how_to_let_user_to_choose_output_file_name');return false">статью</a></span>)</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true, wiki:"how_to_log_data"}) %>
  </script>

  <script type="text/template" id="clearlog">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Clear log window and log file.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>

  <script type="text/template" id="solverfailed">
    <div class="tooltipinternal">
      <div class="tr tooltip-paragraph-first-fold">Use this action if last captcha was solved wrong.</div>
      <div class="tr tooltip-paragraph-fold">It will be reported to service and money won't be removed from the balance.</div>
      <div class="tr tooltip-paragraph-last-fold">If last captcha was solved without service(with software or in manual mode) this action will do nothing.</div>
    </div>
    <%= _.template($('#back').html())({action:"executeandadd", visible:true}) %>
  </script>


  <script type="text/template" id="log_code">
      log(<%= text %>)
  </script>

  <script type="text/template" id="clearlog_code">
      clear_log()
  </script>

  <script type="text/template" id="solverfailed_code">
      solver_failed()
  </script>

  <script type="text/template" id="httpclientproxy_code">
      var hash = proxy_parse(<%= ProxyText %>)
      if(<%= ProxyType %> != "auto" ){
        hash["IsHttp"] = <%= ProxyType %> == "http"
      }
      var login = <%= ProxyLogin %>
      var password = <%= ProxyPassword %>
      if(login.length > 0 && password.length > 0 )
      {
        hash["name"] = login
        hash["password"] = password
      }
      _switch_http_client_main()
      http_client_set_proxy(hash["server"], hash["Port"], hash["IsHttp"], hash["name"], hash["password"])
  </script>
  <script type="text/template" id="httpclientreset_code">
    _switch_http_client_main()
    new_http_client()
  </script>
  <script type="text/template" id="httpclientdownload_code">
    _switch_http_client_main()
    <%= timeout_general() %>
    http_client_download(<%= value %>, <%= file %>)!
  </script>
  <script type="text/template" id="httpclientget_code">
    _switch_http_client_main()
    <% if(follow){ %>
      <%= timeout_general() %>
      http_client_get2(<%= value %>,{method:(<%= method %>),headers:(<%= headers %>)})!
    <% } else {%>
      <%= timeout_general() %>
      http_client_get_no_redirect2(<%= value %>,{method:(<%= method %>),headers:(<%= headers %>)})!
    <% }%>
  </script>
  <script type="text/template" id="httpclientpost_code">
    _switch_http_client_main()
    <% if(follow){ %>
      <%= timeout_general() %>
      <% if(!useconstructor){ %>
        http_client_post(<%= value %>, ["data", <%= postdataraw %>], {"content-type":"custom/" + (<%= contenttyperaw %>), "encoding":(<%= encoding %>), "method":(<%= method %>),headers:(<%= headers %>)})!
      <% } else {%>
        http_client_post(<%= value %>, <%= params %>, {"content-type":(<%= contenttype %>), "encoding":(<%= encoding %>), "method":(<%= method %>),headers:(<%= headers %>)})!
      <% }%>
    <% } else {%>
      <%= timeout_general() %>
      <% if(!useconstructor){ %>
        http_client_post_no_redirect(<%= value %>, ["data", <%= postdataraw %>], {"content-type":"custom/" + (<%= contenttyperaw %>), "encoding":(<%= encoding %>), "method":(<%= method %>),headers:(<%= headers %>)})!
      <% } else {%>
        http_client_post_no_redirect(<%= value %>, <%= params %>, {"content-type":(<%= contenttype %>), "encoding":(<%= encoding %>), "method":(<%= method %>),headers:(<%= headers %>)})!
      <% }%> 
    <% }%>
  </script>
  <script type="text/template" id="parseline_code">
    var csv_parse_result = csv_parse(<%= value %>)
    <% for(var i = 0;i < list.length; i++){ %>
      VAR_<%= list[i] %> = csv_parse_result[<%= i %>]
      if(typeof(VAR_<%= list[i] %>) == 'undefined' || !VAR_<%= list[i] %>)
      {
        VAR_<%= list[i] %> = ""
      }
    <% } %>
    
  </script>

  
  <script type="text/template" id="httpclienturl_code">
    _switch_http_client_main()
    <%= variable %> = http_client_url()
  </script>
  <script type="text/template" id="httpclientcontent_code">
    _switch_http_client_main()
    <%= variable %> = http_client_encoded_content(<%= encoding %>)
  </script>
  <script type="text/template" id="httpclientstatus_code">
    _switch_http_client_main()
    <%= variable %> = http_client_status()
  </script>
  <script type="text/template" id="httpclientgetheader_code">
    _switch_http_client_main()
    <%= variable %> = http_client_header(<%= value %>)
  </script>
  <script type="text/template" id="httpclientsetheader_code">
    _switch_http_client_main()
    http_client_set_header(<%= name %>, <%= value %>)
  </script>
  <script type="text/template" id="httpclientclearheader_code">
    _switch_http_client_main()
    http_client_clear_header()
  </script>
  <script type="text/template" id="httpclientgetcookiesforurl_code">
    _switch_http_client_main()
    <%= variable %> = http_client_get_cookies(<%= value %>)
  </script>
  <script type="text/template" id="httpclientsavecookies_code">
    _switch_http_client_main()  
    <%= variable %> = http_client_save_cookies()
  </script>
  <script type="text/template" id="httpclientrestorecookies_code">
    _switch_http_client_main()
    http_client_restore_cookies(<%= value %>)
  </script>
  <script type="text/template" id="httpclientfailonerror_code">
    _switch_http_client_main()
    http_client_set_fail_on_error(<%= value %> == "fail")
  </script>
  <script type="text/template" id="httpclientiserror_code">
    _switch_http_client_main()
    <%= variable %> = http_client_was_error()
  </script>
  <script type="text/template" id="httpclientgeterrorstring_code">
    _switch_http_client_main()
    <%= variable %> = http_client_error_string()
  </script>
  <script type="text/template" id="httpclientxpathxml_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_xml(<%= value %>,!(<%= fail %>))
  </script>
  <script type="text/template" id="httpclientxpathxmllist_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_xml_list(<%= value %>,true)
  </script>
  <script type="text/template" id="httpclientxpathtext_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_text(<%= value %>,!(<%= fail %>))
  </script>
  <script type="text/template" id="httpclientxpathtextlist_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_text_list(<%= value %>,true)
  </script>
  <script type="text/template" id="httpclientxpathcount_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_count(<%= value %>)
  </script>
  <script type="text/template" id="httpclientxpathexists_code">
    _switch_http_client_main()
    <%= variable %> = http_client_xpath_exist(<%= value %>)
  </script>


  <script type="text/template" id="executefunction_code">
    <% var keys = Object.keys(args) %>
    _call_function(<%= name %>,{<% for(var i = 0;i<keys.length; i++){  %> <%= JSON.stringify(keys[i]) %> : (<%= args[ keys[i] ] %>) <% if(i < keys.length -1){ %>,<% } %> <% } %>})!
    <% if(has_return) { %>
      <%= variable %> = _result_function()
    <% } else { %>
      _result_function()
    <% } %>

  </script>

  <script type="text/template" id="getfunctionparameter_code">
    <%= variable %> = _function_argument(<%= param_name %>)
  </script>

  <script type="text/template" id="recaptchav3_code">
    _recaptchav3(<%= action %>, <%= method %>, <%= rucaptcha %>, <%= serverurl %>, <%= score %>, <%= proxy %> == "true")!
  </script>

  <script type="text/template" id="return_code">
    _function_return(<%= val %>)
  </script>

  <script type="text/template" id="executefunctioninseveralthreads_code">
      _call_section(<%= name %>,<%= thread %>,<%= success %>,<%= fail %>)!
  </script>

  <script type="text/template" id="xml_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.xml()!
      <%= variable %> = _result()
  </script>
  
  <script type="text/template" id="linkurl_code">
    /*Browser*/
    <%= waiter %>
    <%= path %>.script("_BAS_HIDE(BrowserAutomationStudio_GetLinkUrl)(self)")!
    <%= variable %> = _result()
  </script>

  <script type="text/template" id="coordinates_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.script("(function(){var rect = _BAS_HIDE(BrowserAutomationStudio_GetBoundingClientRect)(self);return (rect.left + positionx) + '|' + (rect.top + positiony) + '|' + (rect.right - rect.left) + '|' + (rect.bottom - rect.top) + '|' + (rect.left + positionx + scrollx) + '|' + (rect.top + positiony + scrolly)})();")!
      if(_result().length > 0)
      {
        var split = _result().split("|")
        <%= x %> = parseInt(split[0])
        <%= y %> = parseInt(split[1])
        <%= width %> = parseInt(split[2])
        <%= height %> = parseInt(split[3])
        <%= absolute_x %> = parseInt(split[4])
        <%= absolute_y %> = parseInt(split[5])
      }
  </script>


  <script type="text/template" id="restrictpopups_code">
      /*Browser*/
      _restrict_popups()!
  </script>

  <script type="text/template" id="allowpopups_code">
      /*Browser*/
      _allow_popups()!
  </script>

  <script type="text/template" id="restrictdownloads_code">
      /*Browser*/
      _restrict_downloads()!
  </script>

  <script type="text/template" id="allowdownloads_code">
      /*Browser*/
      _allow_downloads()!
  </script>

  <script type="text/template" id="captcha_code">
      /*Browser*/
      solver_properties_clear(<%= method %>)

      BAS_SolveRecaptcha_Serverurl = <%= serverurl %>

      if(BAS_SolveRecaptcha_Serverurl.length > 0 && BAS_SolveRecaptcha_Serverurl.substr(BAS_SolveRecaptcha_Serverurl.length - 1) != "/")
        BAS_SolveRecaptcha_Serverurl += "/"

      if(<%= method %> == "rucaptcha")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("rucaptcha","serverurl",BAS_SolveRecaptcha_Serverurl)
        rucaptcha(<%= antigate %>)
      }
      if(<%= method %> == "antigate")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("antigate","serverurl",BAS_SolveRecaptcha_Serverurl)
       antigate(<%= antigate %>)
      }
      if(<%= method %> == "dbc")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("dbc","serverurl",BAS_SolveRecaptcha_Serverurl)
        dbc(<%= antigate %>)
      }
      if(<%= method %> == "2captcha")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("2captcha","serverurl",BAS_SolveRecaptcha_Serverurl)
        twocaptcha(<%= antigate %>)
      }
      if(<%= method %> == "capmonster" || <%= method %> == "capmonsterimage" || <%= method %> == "capmonsteraudio")
      {
        solver_property("capmonster","serverurl",BAS_SolveRecaptcha_Serverurl)
        capmonster(<%= antigate %>)
      }
      if(<%= method %> == "xevil")
      {
        solver_property("xevil","serverurl",((BAS_SolveRecaptcha_Serverurl).length == 0) ? "http://rucaptcha.com/" : (BAS_SolveRecaptcha_Serverurl))
        xevil(<%= antigate %>)
      }


      <%= waiter %>
      <%= path %>.exist()!
      _if(_result() == "1", function(){
        _if_else(<%= method %> == "xevil" || <%= method %> == "capmonster" || <%= method %> == "capmonsterimage" || <%= method %> == "capmonsteraudio" || <%= method %> == "captchasniper", function(){
          <%= path %>.attr("src")!
          <%= variable %> = _result()
          _if(<%= variable %>.length == 0, function(){
            <%= path %>.css("img").attr("src")!
            <%= variable %> = _result()
          })!

          if(<%= variable %>.length == 0)
          {
            fail(tr("Image tag not found. Is this element captcha?"))
          }

          wait_load(<%= variable %>)!

          cache_get_base64(<%= variable %>)!

          if(_result().length == 0)
          {
            fail(tr("Url ") + <%= variable %> + tr(" is not present in cache. Please enable cache before page load with Allow cache action"))
          }

          _if_else(<%= method %> == "captchasniper", function(){
            _switch_http_client_internal()
            http_client_post(BAS_SolveRecaptcha_Serverurl, ["file","base64://" + _result()], {"content-type":("multipart"), "encoding":("UTF-8"), "method":("POST")})!
            {var split = http_client_content().split("|");<%= variable %> = split[split.length-1]}
            _switch_http_client_main()
          }, function(){
              <%= timeout_solver() %>
              solve_base64((<%= method %> == "xevil") ? "xevil" : "capmonster", _result())!
              <%= variable %> = _result()
          })!

        },function(){
          <%= path %>.render_base64()!
          <%= timeout_solver() %>
          solve_base64(<%= method %>, _result())!
          <%= variable %> = _result()

        })!
    })!

      
  </script>

  <script type="text/template" id="screenshot_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.exist()!
      _if(_result() == "1", function(){
          <%= path %>.render_base64()!
          <%= variable %> = _result()
      })!
  </script>


  <script type="text/template" id="randomint_code">
      <%= variable %> = Math.floor(Math.random() * (parseInt(<%= max %>) - parseInt(<%= min %>) + 1)) + parseInt(<%= min %>)
  </script>



  

  _MACRO_INSERT_CODE_

  <script type="text/template" id="exist_code">
      /*Browser*/
      <% if(imagesearch){ %>
        <%= waiter %>        
      <% }else if(query){ %>
        ;_SELECTOR=<%=query%>;
      <% } %>

      <%= path %>.exist()!
      <%= variable %> = _result() == 1
      <% if(isvisible){ %>
        _if(<%= variable %>, function(){
          <%= path %>.script("_BAS_HIDE(BrowserAutomationStudio_IsVisible)(self)")!
          <%= variable %> = _result().indexOf("true")>=0
        })!
      <% } %>

  </script>

  <script type="text/template" id="restorecookies_code">
      /*Browser*/

      VALUE = <%= value %>
      COOKIES = ""
      if(VALUE.length > 0)
      {
        COOKIES = JSON.parse(VALUE)["cookies"]
        if(typeof(COOKIES) == "undefined")
          COOKIES = ""
        else
          COOKIES = JSON.stringify(COOKIES)
      }


      restore_cookies(COOKIES,<%= append %>)!
  </script>

  <script type="text/template" id="loadcookiesfromhttpclient_code">
      /*Browser*/
      _switch_http_client_main()
      VALUE = http_client_save_cookies()
      COOKIES = ""
      if(VALUE.length > 0)
      {
        COOKIES = JSON.parse(VALUE)["cookies"]
        if(typeof(COOKIES) == "undefined")
          COOKIES = ""
        else
          COOKIES = JSON.stringify(COOKIES)
      }

      
      restore_cookies(COOKIES, false)!
  </script>

  <script type="text/template" id="loadcookiesfrombrowser_code">
      /*Browser*/
      save_cookies()!
      _switch_http_client_main()
      http_client_restore_cookies(JSON.stringify({cookies:JSON.parse(_result())}))
  </script>

  <script type="text/template" id="closebrowser_code">
      /*Browser*/
      /*ManualBrowser*/
      close_browser()
  </script>

  <script type="text/template" id="openbrowser_code">
      /*Browser*/
      /*ManualBrowser*/
      open_browser()!
  </script>

  <script type="text/template" id="setheader_code">
    header(<%= name %>, <%= value %>)!
    sleep(1000)!
  </script>

  <script type="text/template" id="clickCaptchaBrowser_code">
    /*Browser*/
    _call_function(BASCaptchaSolver.solveCoordinatesCaptcha, {
      textInstructions: <%= textInstructions %>,
      taskWaitTimeout: <%= taskWaitTimeout %>,
      taskWaitDelay: <%= taskWaitDelay %>,
      serviceName: <%= serviceName %>,
      serviceUrl: <%= serviceUrl %>,
      serviceKey: <%= serviceKey %>,
      imageData: <%= imageData %>,
    })!
    <%= clickCoordinatesList %> = _result_function();
  </script>

  <script type="text/template" id="solvecaptcha_code">
      /*Browser*/
      solver_properties_clear(<%= method %>)

      BAS_SolveRecaptcha_Serverurl = <%= serverurl %>;
      if(BAS_SolveRecaptcha_Serverurl.length > 0 && BAS_SolveRecaptcha_Serverurl.substr(BAS_SolveRecaptcha_Serverurl.length - 1) != "/")
        BAS_SolveRecaptcha_Serverurl += "/"

      if(<%= method %> == "rucaptcha")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("rucaptcha","serverurl",BAS_SolveRecaptcha_Serverurl)
        rucaptcha(<%= antigate %>)
      }
      if(<%= method %> == "antigate")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("antigate","serverurl",BAS_SolveRecaptcha_Serverurl)
        antigate(<%= antigate %>)
      }
      if(<%= method %> == "dbc")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("dbc","serverurl",BAS_SolveRecaptcha_Serverurl)
        dbc(<%= antigate %>)
      }
      if(<%= method %> == "2captcha")
      {
        if(BAS_SolveRecaptcha_Serverurl)
          solver_property("2captcha","serverurl",BAS_SolveRecaptcha_Serverurl)
        twocaptcha(<%= antigate %>)
      }
      if(<%= method %> == "capmonster" || <%= method %> == "capmonsterimage" || <%= method %> == "capmonsteraudio")
      {
        solver_property("capmonster","serverurl",BAS_SolveRecaptcha_Serverurl)
        capmonster(<%= antigate %>)
      }

      _if_else(<%= method %> == "captchasniper", function(){
        _switch_http_client_internal()
        http_client_post(BAS_SolveRecaptcha_Serverurl, ["file","base64://" + <%= value %>], {"content-type":("multipart"), "encoding":("UTF-8"), "method":("POST")})!
        {var split = http_client_content().split("|");<%= variable %> = split[split.length-1]}
        _switch_http_client_main()
      }, function(){
        <%= timeout_solver() %>
        solve_base64(<%= method %>,<%= value %>)!
        <%= variable %> = _result()
      })!


      
  
  </script>

  <script type="text/template" id="timeout_code">
      <% if(type == "general"){ %>
        general_timeout(<%= timeout %>)
      <% }else if(type == "fullpageload"){ %>
        async_load_timeout(<%= timeout %>)
      <% }else{ %>
        solver_timeout(<%= timeout %>)
      <% } %>
  </script>

  <script type="text/template" id="savecookies_code">
      /*Browser*/
      save_cookies(<%= domain %>)!
      <%= variable %> = "{\"cookies\":" + _result() + "}"
  </script>

  <script type="text/template" id="style_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.script('_BAS_SAFE(Window.getComputedStyle)(self)[' + JSON.stringify(<%= style %>) + ']')!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="typeelement_code">
      /*Browser*/
      <%= waiter %>
      <% if(!disableemulation){ %>
        _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
          _Idle.emulate(<%= emulation_settings %>)!
        })!
        _if_else(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %> && <% if(additional_emulation !== '""'){ %>_is_true(<%= additional_emulation %>)<% }else{ %>_Idle.additionalEmulationEnabled()<% } %>, function(){
          _Idle.typeOn(<%= BrowserAutomationStudio_GetEmulationTarget() %>,<%= text %>,{interval: <%= interval %>, moveSettings: <%= move_settings %><% if(additional_emulation !== '""'){ %>, additionalEmulation: (<%= additional_emulation %>)<% } %>})!
        }, function(){
          <% if(_SelectorModel.get("is_image")){ %>
            <%= path %>.random_point()!
          <% }else{ %>
            _call(_random_point, {})!
          <% } %>
          _if(_result().length > 0, function(){
            move(<%= move_settings %>)!
            <%= path %>.clarify(X,Y)!
            _call(_clarify,<%= move_settings %>)!
            mouse(X,Y)!
            <%= timeout_general() %>
            _type(<%= text %>,<%= interval %>)!
          })!
        })!
      <% }else{ %>
        <%= path %>.script("self.value=(" + JSON.stringify(<%= text %>) + ")")!
      <% } %>
  </script>

  <script type="text/template" id="clear_code">
      /*Browser*/
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      _if_else(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %> && <% if(additional_emulation !== '""'){ %>_is_true(<%= additional_emulation %>)<% }else{ %>_Idle.additionalEmulationEnabled()<% } %>, function(){
        _Idle.typeOn(<%= BrowserAutomationStudio_GetEmulationTarget() %>,"<CONTROL>a<BACK>",{interval: 30, moveSettings: <%= move_settings %><% if(additional_emulation !== '""'){ %>, additionalEmulation: (<%= additional_emulation %>)<% } %>})!
      }, function(){
        <% if(_SelectorModel.get("is_image")){ %>
          <%= path %>.random_point()!
        <% }else{ %>
          _call(_random_point, {})!
        <% } %>
        _if(_result().length > 0, function(){
          move(<%= move_settings %>)!
          <%= path %>.clarify(X,Y)!
          _call(_clarify,<%= move_settings %>)!
          mouse(X,Y)!
          _type("<CONTROL>a<BACK>", 30)!
        })!
      })!
  </script>

  <script type="text/template" id="clickelement_code">
      /*Browser*/
      <%= waiter %>
      <% if(!disableemulation){ %>
        <% if(_SelectorModel.get("is_image")){ %>
          <%= path %>.random_point()!
        <% }else{ %>
          _call(_random_point, {})!
        <% } %>
        _if(_result().length > 0, function(){
          X = parseInt(_result().split(",")[0])
          Y = parseInt(_result().split(",")[1])
          mouse(X,Y)!
        })!
      <% }else{ %>
        <%= path %>.script("_BAS_SAFE($HTMLElement.click)(self)")!
      <% } %>
  </script>

  <script type="text/template" id="check_code">
      /*Browser*/
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      <% if(_SelectorModel.get("is_image")){ %>
        <%= path %>.random_point()!
      <% }else{ %>
        _call(_random_point, {})!
      <% } %>
      _if(_result().length > 0, function(){
        move(<%= move_settings %>)!
        <%= path %>.clarify(X,Y)!
        _call(_clarify,<%= move_settings %>)!
        mouse(X,Y)!
      })!
  </script>

  <script type="text/template" id="focus_code">
      /*Browser*/
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      <%= timeout_general() %>
      <% if(native_emulation){ %>
        _scrollTo(<%= path %>,<%= scroll_params %>)!
      <% }else{ %>
        <%= path %>.focus()!
      <% } %>
  </script>

  <script type="text/template" id="reset_code">
        new_browser()!
  </script>

  <script type="text/template" id="moveelement_code">
      /*Browser*/
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      <% if(_SelectorModel.get("is_image")){ %>
          <%= path %>.random_point()!
        <% }else{ %>
          _call(_random_point, {})!
        <% } %>
      _if(_result().length > 0, function(){
        move(<%= move_settings %>)!
        <%= path %>.clarify(X,Y)!
        _call(_clarify,<%= move_settings %>)!
      })!
  </script>

  <script type="text/template" id="moveandclickelement_code">
      /*Browser*/
      <%= waiter %>
      <% if(!disableemulation){ %>
        _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
          _Idle.emulate(<%= emulation_settings %>)!
        })!
        _if_else(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %> && <% if(additional_emulation !== '""'){ %>_is_true(<%= additional_emulation %>)<% }else{ %>_Idle.additionalEmulationEnabled()<% } %>, function(){
          _Idle.moveAndClickOn(<%= BrowserAutomationStudio_GetEmulationTarget() %>,{holdCtrl: <%= holdctrl %>, clickType: <%= click_type %>, wait: <%= wait %>, moveSettings: <%= move_settings %><% if(additional_emulation !== '""'){ %>, additionalEmulation: (<%= additional_emulation %>)<% } %>})!
        }, function(){
          <% if(_SelectorModel.get("is_image")){ %>
            <%= path %>.random_point()!
          <% }else{ %>
            _call(_random_point, {})!
          <% } %>
          _if(_result().length > 0, function(){
            move(<%= move_settings %>)!
            <%= path %>.clarify(X,Y)!
            _call(_clarify,<%= move_settings %>)!           
            <%= BrowserAutomationStudio_MouseCustom("X","Y") %>
          })!
        })!
      <% }else{ %>
        <%= path %>.script("_BAS_SAFE($HTMLElement.click)(self)")!
      <% } %>
  </script>

  <script type="text/template" id="dragelement_code">
      /*Browser*/
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      <% if(_SelectorModel.get("is_image")){ %>
          <%= path %>.random_point()!
        <% }else{ %>
          _call(_random_point, {})!
        <% } %>
      _if(_result().length > 0, function(){
        move(<%= move_settings %>)!
        <%= path %>.clarify(X,Y)!
        _call(_clarify,<%= move_settings %>)!           
        mouse_down(X,Y)!
      })!
  </script>

  <script type="text/template" id="dropelement_code">
      /*Browser*/
      <%= waiter %>
      <% if(_SelectorModel.get("is_image")){ %>
          <%= path %>.random_point()!
        <% }else{ %>
          _call(_random_point, {})!
        <% } %>
      _if(_result().length > 0, function(){
        move(<%= move_settings %>)!
        <%= path %>.clarify(X,Y)!
        _call(_clarify,<%= move_settings %>)!           
        mouse_up(X,Y)!
      })!
  </script>

  <script type="text/template" id="text_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.text()!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="length_code">
      /*Browser*/
      <% if(query){ %>
        ;_SELECTOR=<%=query%>;
      <% } %>
      <%= path %>.length()!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="script_code">
      <%= waiter %>
      <%= path %>.script(<%= script %>)!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="browserscript_code">
    <%= waiter %>
    <%= path %>.script2(<%= '"' + je(source) + '"' %>,JSON.stringify(_read_variables(<%= variables %>)))!
    var _parse_result = JSON.parse(_result())
    _write_variables(JSON.parse(_parse_result.variables))
    if(!_parse_result.is_success)
      fail(_parse_result.error)
  </script>

  <script type="text/template" id="javascript_code">
      page().script(<%= value %>)!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="browserjavascript_code">
      <%= timeout_general()  %>
      page().script2(<%= '"' + je(source) + '"' %>,JSON.stringify(_read_variables(<%= variables %>)))!
      var _parse_result = JSON.parse(_result())
      _write_variables(JSON.parse(_parse_result.variables))
      if(!_parse_result.is_success)
        fail(_parse_result.error)
  </script>

  <script type="text/template" id="onloadjavascript_code">
      /*Browser*/
      onloadjavascript(<%= value %>)!
  </script>

  
  <script type="text/template" id="set_code">
      <%= waiter %>
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      get_element_selector(_SELECTOR, false).script2("[[RESULT]] = _BAS_HIDE(BrowserAutomationStudio_GetSelectIndex)(self, " + JSON.stringify(<%= set %>) + ")",JSON.stringify({}))!
      _SELECT_INDEX = JSON.parse(JSON.parse(_result()).variables)["RESULT"]
      _call(_random_point, {})!
      _if(_result().length > 0 && _SELECT_INDEX >= 0, function(){
        move({})!
        <%= path %>.clarify(X,Y)!
        _call(_clarify,{})!
        mouse(X,Y)!
        <%= timeout_general() %>
        sleep(rand(2000,3000))!
        _set_combobox_index(_SELECT_INDEX)!
        sleep(rand(1000,1200))!
      })!
  </script>

  <script type="text/template" id="waitelement_code">
      /*Browser*/
      <%= waiter %>
  </script>

  <script type="text/template" id="waitfullload_code">
      /*Browser*/
      <%= timeout_waiter() %>
      wait_async_load()!
  </script>

  <script type="text/template" id="set_integer_code">
    <%= waiter %>
    _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
      _Idle.emulate(<%= emulation_settings %>)!
    })!
    _call(_random_point, {})!
    move({})!
    <%= path %>.clarify(X,Y)!
    _call(_clarify,{})!
    mouse(X,Y)!
    <%= timeout_general() %>
    sleep(rand(2000,3000))!
    _set_combobox_index(<%= set %>)!
    sleep(rand(1000,1200))!
  </script>

  <script type="text/template" id="set_random_code">
    <%= waiter %>
    _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
      _Idle.emulate(<%= emulation_settings %>)!
    })!
    get_element_selector(_SELECTOR, false).script2("[[RESULT]] = _BAS_HIDE(BrowserAutomationStudio_GetSelectIndex)(self)",JSON.stringify({}))!
    _SELECT_INDEX = JSON.parse(JSON.parse(_result()).variables)["RESULT"]
    _call(_random_point, {})!
    _if(_result().length > 0 && _SELECT_INDEX >= 0, function(){
      move({})!
      <%= path %>.clarify(X,Y)!
      _call(_clarify,{})!
      mouse(X,Y)!
      <%= timeout_general() %>
      sleep(rand(2000,3000))!
      _set_combobox_index(_SELECT_INDEX)!
      sleep(rand(1000,1200))!
    })!
  </script>

  <script type="text/template" id="attr_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.attr(<%= attr %>)!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="set_attr_code">
      /*Browser*/
      <%= waiter %>
      <%= path %>.set_attr(<%= name %>, <%= value %>)!
  </script>

  <script type="text/template" id="clickextensionbutton_code">
    _click_extension_button(<%= extension_id %>)!
  </script>

  <script type="text/template" id="url_code">
      /*Browser*/
      url()!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="screen_code">
    _get_browser_screen_settings()!
    ;(function(){
      var result = JSON.parse(_result())
      <%= scroll_x %> = result["ScrollX"]
      <%= scroll_y %> = result["ScrollY"]
      <%= cursor_x %> = result["CursorX"]
      <%= cursor_y %> = result["CursorY"]
      <%= cursor_absolute_x %> = result["CursorX"] + result["ScrollX"]
      <%= cursor_absolute_y %> = result["CursorY"] + result["ScrollY"]
      <%= width %> = result["Width"]
      <%= height %> = result["Height"]
    })();
  </script>

  <script type="text/template" id="touch_code">
    _browser_mode((<%= enable %>) == "true" ? "mobile" : "desktop")!
  </script>

  <script type="text/template" id="setvariable_code">
      <%= variable_name %> = <%= variable_value %>
  </script>

  <script type="text/template" id="incvariable_code">
      <%= variable_name %> = parseInt(<%= variable_name %>) + parseInt(<%= variable_value %>)
  </script>

  <script type="text/template" id="incglobalvariable_code">
      PSet("basglobal", <%= variable_name %>, parseInt(JSON.parse(P("basglobal", <%= variable_name %>) || "0")) + parseInt(<%= variable_value %>))
  </script>

  <script type="text/template" id="resource_code">
      RS("<%= je(resource) %>", <%= notreuse %>, <%= onlyfail %>)!
      <%= variable %> = _result().get()
  </script>

  <script type="text/template" id="click_code">
      /*Browser*/
      mouse(<%= x %>,<%= y %>)!
  </script>

  <script type="text/template" id="navigateback_code">
      navigate_back(true)!

  </script>

  <script type="text/template" id="move_code">
      /*Browser*/
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      move(<%= x %>,<%= y %>, <%= move_settings %>)!
  </script>

  <script type="text/template" id="addtab_code">
    <% if(notinstant){ %>
      <%= timeout_general()  %>
    <% } %>
    _popupcreate2(<%= is_silent %> == "true", <%= url %>, <%= referrer %>, <%= (notinstant) ? "false" : "true" %>)!
  </script>

  <script type="text/template" id="closetab_code">
      /*Browser*/
      popupclose(<%= index %>)!
  </script>

  <script type="text/template" id="selecttab_code">
      /*Browser*/
      popupselect(<%= index %>)!
  </script>

  <script type="text/template" id="tabinfo_code">
    /*Browser*/
    _popupinfo()!
    var json = JSON.parse(_result())
    <%= index %> = json["index"]
    <%= urls %> = json["urls"]
    <%= total %> = json["urls"].length
  </script>

  <script type="text/template" id="moveandclick_code">
      /*Browser*/
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      _if_else(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %> && <% if(additional_emulation !== '""'){ %>_is_true(<%= additional_emulation %>)<% }else{ %>_Idle.additionalEmulationEnabled()<% } %>, function(){
        _Idle.moveAndClickOn(<%= BrowserAutomationStudio_GetEmulationTarget(x,y) %>,{holdCtrl: <%= holdctrl %>, clickType: <%= click_type %>, wait: <%= wait %>, moveSettings: <%= move_settings %><% if(additional_emulation !== '""'){ %>, additionalEmulation: (<%= additional_emulation %>)<% } %>})!
      }, function(){
        move(<%= x %>,<%= y %>, <%= move_settings %>)!
        <%= BrowserAutomationStudio_MouseCustom(x,y) %>
      })!
  </script>

  <script type="text/template" id="drag_code">
      /*Browser*/
      _if(typeof _Idle != "undefined"<% if(emulation_time !== '""'){ %> && !_is_false(<%= emulation_time %>)<% } %>, function(){
        _Idle.emulate(<%= emulation_settings %>)!
      })!
      move(<%= x %>,<%= y %>, <%= move_settings %>)!
      mouse_down(<%= x %>,<%= y %>)!
  </script>

  <script type="text/template" id="drop_code">
      /*Browser*/
      var move_settings = <%= move_settings %>;
      move_settings["do_mouse_up"] = "true"
      move(<%= x %>,<%= y %>, move_settings)!
  </script>

  <script type="text/template" id="load_code">
      <% if(notinstant){ %>
        <%= timeout_general()  %>
      <% } %>
      _load(<%= url %>, <%= referrer %>, <%= (notinstant) ? "false" : "true" %>)!
  </script>

  <script type="text/template" id="mousesettings_code">
      /*Browser*/
      _default_move_params({speed: <%= speed %>,gravity: <%= gravity %>,deviation: <%= deviation %>})
  </script>

  <script type="text/template" id="notification_code">
      /*Browser*/
      _enable_notifications(<%= enable %> == "true")!
  </script>

  <script type="text/template" id="browsersettings_code">
      _require_extensions(<%= Extensions %>)!

      _BrowserAutomationStudio_Settings = BrowserAutomationStudio_ParseBrowserSettings(
        {
          Widevine: (<%= Widevine %>),
          SafeBrowsing: (<%= SafeBrowsing %>),
          Components: (<%= Components %>),
          Extensions: (_result()),
          CommandLine: (<%= CommandLine %>),
          Webrtc: (<%= Webrtc %>),
          WebrtcIps: (<%= WebrtcIps %>),
          Canvas: (<%= Canvas %>),
          CanvasNoise: (<%= CanvasNoise %>),
          Audio: (<%= Audio %>),
          AudioNoise: (<%= AudioNoise %>),
          QUIC: (<%= QUIC %>),
          MaxFPS: (<%= MaxFPS %>),
          Webgl: (<%= Webgl %>),
          WebglNoise: (<%= WebglNoise %>),
          BrowserVersion: (<%= BrowserVersion %>),
          WebglVendor: (<%= WebglVendor %>),
          WebglRenderer: (<%= WebglRenderer %>),
          Tunneling: (<%= Tunneling %>),
        }
      );
      
      _if_else((<%= profile %>).length > 0, function(){
        _call(BrowserAutomationStudio_ChangeProfile,[{
          profile: (<%= profile %>),
          load_proxy: (<%= load_proxy %>),
          load_fp: (<%= load_fp %>),
          settings: _BrowserAutomationStudio_Settings,
          key: (<%= Key %>),
        }])!
      }, function(){
        _settings(_BrowserAutomationStudio_Settings)!
      })!
      
  </script>

  <script type="text/template" id="getbrowserversionlist_code">
    <%= variable %> = _get_all_browser_version_info(<%= format %>)
  </script>

  <script type="text/template" id="getcurrentbrowserversion_code">
    {
      var info = _get_current_browser_version_info("extended")
      <%= variable %> = info.id
      <%= variable2 %> = info.browser_version
      <%= variable3 %> = info.architecture
    }
  </script>

  <script type="text/template" id="resize_code">
      /*Browser*/
      resize(<%= width %>, <%= height %>)!
  </script>

  <script type="text/template" id="sleep_fromto_code">
      sleep(rand(<%= from %>,<%= to %>))!
  </script>

  <script type="text/template" id="sleep_code">
      sleep(<%= t %>)!
  </script>


  <script type="text/template" id="result_code">
    result(<%= value %>, <%= number %>)
  </script>

  <script type="text/template" id="globalset_code">
    var val = JSON.stringify(<%= value %>);
    PSet("basglobal", <%= key %>, val)
  </script>

  <script type="text/template" id="globalget_code">
    var text = P("basglobal", <%= key %>)
    if(text.length == 0)
      text="\"\""
    <%= variable %> = JSON.parse(text)
  </script>


  <script type="text/template" id="cachemaskallow_code">
    /*Browser*/
    cache_allow(<%= urlFilters %>, (<%= limit %>))!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="cachemaskdeny_code">
    /*Browser*/
    cache_deny(<%= urlFilters %>, (<%= limit %>))!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="requestmaskallow_code">
    /*Browser*/
    request_allow(<%= urlFilters %>)!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="requestmaskdeny_code">
    request_deny(<%= urlFilters %>)!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="cleardata_code">
    /*Browser*/
    cache_data_clear()!
  </script>

  <script type="text/template" id="clearmasks_code">
    /*Browser*/
    cache_masks_clear()!
  </script>

  <script type="text/template" id="getstatus_code">
    /*Browser*/
    cache_get_status(<%= urlFilters %>)!
    <%= variable %> = _result()
  </script>

  <script type="text/template" id="isloaded_code">
    /*Browser*/
    is_load(<%= urlFilters %>)!
    <%= variable %> = _result()
  </script>

  <script type="text/template" id="getfromcache_code">
    /*Browser*/
    <% if(waitItem){ %>
      <%= timeout_waiter() %>
      wait_load(<%= urlFilters %>)!
    <% } %>
    <% if(base64){ %>
      cache_get_base64(<%= urlFilters %>)!
      <%= variable %> = _result()
    <% }else{ %>
      cache_get_string(<%= urlFilters %>)!
      <%= variable %> = _result()
    <% } %>
  </script>

  <script type="text/template" id="getallcache_code">
    /*Browser*/
    _cache_get_all(<%= urlFilters %>)!
    <%= variable %> = JSON.parse(_result())
  </script>

  <script type="text/template" id="redirectrequests_code">
    /*Browser*/
    _redirect_requests(<%= urlFilters %>, {mode: "<%= replaceMode %>"<%if(replaceMode != "all"){%>, search: (<%= searchValue %>)<%if(replaceMode == "between"){%>, search2: (<%= searchValue2 %>)<%}%><%if(["exact", "regexp"].includes(replaceMode)){%>, flags: {global: (<%= replaceMode == "regexp" ? globalSearch : replaceAllExact %>)<%if(replaceMode == "regexp"){%>, ignore_case: (<%= ignoreСase %>)<%}%>}<%}%><%}%>, new_value: (<%= newValue %>)}, (<%= limit %>))!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="replacerequestcontent_code">
    /*Browser*/
    _replace_request_content(<%= urlFilters %>, <%= contentFilters %>, {mode: "<%= replaceMode %>"<%if(replaceMode != "all"){%>, search: (<%= searchValue %>)<%if(replaceMode == "between"){%>, search2: (<%= searchValue2 %>)<%}%><%if(["exact", "regexp"].includes(replaceMode)){%>, flags: {global: (<%= replaceMode == "regexp" ? globalSearch : replaceAllExact %>)<%if(replaceMode == "regexp"){%>, ignore_case: (<%= ignoreСase %>), multiline: (<%= multiline %>)<%}%>}<%}%><%}%>, new_value: (<%= newValue %>)}, (<%= limit %>))!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="replaceresponsecontent_code">
    /*Browser*/
    _replace_response_content(<%= urlFilters %>, <%= contentFilters %>, {mode: "<%= replaceMode %>"<%if(replaceMode != "all"){%>, search: (<%= searchValue %>)<%if(replaceMode == "between"){%>, search2: (<%= searchValue2 %>)<%}%><%if(["exact", "regexp"].includes(replaceMode)){%>, flags: {global: (<%= replaceMode == "regexp" ? globalSearch : replaceAllExact %>)<%if(replaceMode == "regexp"){%>, ignore_case: (<%= ignoreСase %>), multiline: (<%= multiline %>)<%}%>}<%}%><%}%>, new_value: (<%= newValue %>)}, (<%= limit %>))!
    <%= variable %> = _result();
  </script>

  <script type="text/template" id="disablerules_code">
    /*Browser*/
    <% if(ids == '"ALL"'){ %>
      _disable_all_rules()!
    <% }else{ %>
      _disable_rules(<%= ids %>)!
    <% } %>
  </script>

  <script type="text/template" id="getrulestats_code">
    /*Browser*/
    _get_rule_stats(<%= id %>)!
    var replaceStats = JSON.parse(_result());
    <%= variableExecutionCount %> = replaceStats["execution_count"];
    <%= variableIsActive %> = replaceStats["is_active"];
    <%= variableAllIds %> = replaceStats["all_ids"];
    <%= variableActiveIds %> = replaceStats["active_ids"];
  </script>

  <script type="text/template" id="renderscreen_code">
      /*Browser*/
      render(<%= x %>,<%= y %>,<%= width %>,<%= height %>)!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="scroll_code">
      /*Browser*/
      <%= timeout_general() %>
      <% if(native_emulation){ %>
        _scroll_to(<%= y %>)!
      <% }else{ %>
        scroll(<%= x %>,<%= y %>)!
      <% } %>
  </script>

  <script type="text/template" id="waitload_code">
      /*Browser*/
      <%= timeout_waiter() %>
      wait_load(<%= urlFilters %>)!
  </script>

  <script type="text/template" id="waiturl_code">
      /*Browser*/
      <%= timeout_waiter() %>
      wait_url(<%= waiter %>)!
  </script>

  <script type="text/template" id="openfile_code">
      /*Browser*/
      open_file_dialog(<%= value %>)!
  </script>

  <script type="text/template" id="dragfile_code">
      /*Browser*/
      drag_file(<%= value %>)!
  </script>

  <script type="text/template" id="promptresult_code">
      /*Browser*/
      prompt_result(<%= value %>)!
  </script>

  <script type="text/template" id="httpauth_code">
      /*Browser*/
      http_auth_result(<%= login %>,<%= password %>)!
  </script>

  <script type="text/template" id="waitcontent_code">
      /*Browser*/
      <%= timeout_waiter() %>
      wait_content(<%= waiter %>)!
  </script>

  <script type="text/template" id="waitfiledownload_code">
      /*Browser*/
      <%= timeout_waiter() %>
      _wait_download()!
      _get_downloaded_filename()!
      <%= variable %> = JSON.parse(native("filesystem", "fileinfo", _result()))["directory"] + "/" + _result()
  </script>
  

  <script type="text/template" id="waitcss_code">
      /*Browser*/
      <%= timeout_waiter() %>
      wait_css(<%= waiter %>)!
  </script>

  <script type="text/template" id="type_code">
      /*Browser*/
      <%= timeout_general() %>
      _type(<%= text %>,<%= interval %>)!
  </script>

  <script type="text/template" id="html_code">
      /*Browser*/
      page().script("_BAS_HIDE(BrowserAutomationStudio_GetPageContent)()")!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="if_code">
      _if(<%= expression %>,function(){
        section_insert()
      })!
      <% if(do_delete.length > 0){ %>
        delete <%= do_delete %>;
      <% } %>
  </script>

  <script type="text/template" id="proxy_code">
      var hash = proxy_parse(<%= ProxyText %>)
      if(<%= ProxyType %> != "auto" ){
        hash["IsHttp"] = <%= ProxyType %> == "http"
      }
      var login = <%= ProxyLogin %>
      var password = <%= ProxyPassword %>
      if(login.length > 0 && password.length > 0 )
      {
        hash["name"] = login
        hash["password"] = password
      }
      if(_get_profile().length > 0)
      {
        if(hash["server"].length == 0)
        {
          native("filesystem", "removefile", _get_profile() + "/proxy.txt")
        }else
        {
          var PortNumber = hash["Port"]
          hash["Port"] = hash["Port"].toString()
          hash["DetectExternalIp"] = <%= DetectExternalIp %> == "true";
          hash["ChangeGeolocation"] = <%= ChangeGeolocation %> == "true";
          hash["ChangeWebrtcIp"] = <%= ChangeWebrtcIp %>;

          if(hash["ChangeWebrtcIp"] == "true"){hash["ChangeWebrtcIp"] = "replace"};
          if(hash["ChangeWebrtcIp"] == "false"){hash["ChangeWebrtcIp"] = "ignore"}

          hash["ChangeTimezone"] = <%= ChangeTimezone %> == "true";
          hash["ChangeBrowserLanguage"] = <%= ChangeBrowserLanguage %> == "true";
          hash["ip_info_method"] = <%= ip_info_method %>;
          if(hash["ip_info_method"] == "custom function")
          {
            hash["ip_info_method"] = "database"
          }
          hash["ip_api_key"] = <%= ip_api_key %>;
          hash["ServiceURL"] = <%= ServiceURL %>;
          hash["IpExtractionParam"] = <%= IpExtractionParam %>;
          hash["IpExtractionMethod"] = <%= IpExtractionMethod %>;

          hash["PublicIPv4"] = <%= PublicIPv4 %>;
          hash["PublicIPv6"] = <%= PublicIPv6 %>;
          hash["PrivateIPv4"] = <%= PrivateIPv4 %>;
          hash["PrivateIPv6"] = <%= PrivateIPv6 %>;
          hash["DetectExternalIpV6"] = <%= DetectExternalIpV6 %> == "true";
          hash["ServiceURLV6"] = <%= ServiceURLV6 %>;
          hash["IpExtractionMethodV6"] = <%= IpExtractionMethodV6 %>;
          hash["IpExtractionParamV6"] = <%= IpExtractionParamV6 %>;

          hash["DNSMode"] = <%= DNSMode %>;
          hash["CustomDNSIP"] = <%= CustomDNSIP %>;
          
          native("filesystem", "writefile", JSON.stringify({path: _get_profile() + "/proxy.txt",value: JSON.stringify(hash),base64:false,append:false}))
          hash["Port"] = PortNumber
        }
      }
      set_proxy_prepare(<%= DNSMode %>, <%= CustomDNSIP %>)!
      set_proxy(hash["server"], hash["Port"], hash["IsHttp"], hash["name"], hash["password"])!
      sleep(1000)!
      set_proxy_extended(<%= DetectExternalIp %> == "true", <%= ChangeGeolocation %> == "true", <%= ChangeWebrtcIp %>, <%= ChangeTimezone %> == "true", <%= ChangeBrowserLanguage %> == "true", <%= ip_info_method %>, <%= ip_api_key %>, <%= function_name %>, <%= ServiceURL %>, <%= IpExtractionMethod %>, <%= IpExtractionParam %>, <%= PublicIPv4 %>, <%= PublicIPv6 %>, <%= PrivateIPv4 %>, <%= PrivateIPv6 %>, <%= DetectExternalIpV6 %> == "true", <%= ServiceURLV6 %>, <%= IpExtractionMethodV6 %>, <%= IpExtractionParamV6 %>, <%= DNSMode %>, <%= CustomDNSIP %>)!
      sleep(1000)!
  </script>

  <script type="text/template" id="for_code">
      _do(function(){
        _set_action_info({ name: "For" });
        VAR_CYCLE_INDEX = _iterator() - 1 + parseInt(<%= expression_from %>)
        if(VAR_CYCLE_INDEX > parseInt(<%= expression_to %>))_break();
        section_insert()
      })!
  </script>

  <script type="text/template" id="ignoreerrors_code">
    _call(function()
    {
      _set_action_info({ name: "Ignore Errors" });
      _on_fail(function(){
         VAR_LAST_ERROR = _result()
         VAR_ERROR_ID = ScriptWorker.GetCurrentAction()
         VAR_WAS_ERROR = false
         _break(1,true)
       })
       CYCLES.Current().RemoveLabel("function")
       section_insert()
    },null)!

  </script>

  <script type="text/template" id="foreach_code">
      _do_with_params({"foreach_data":(<%= for_array %>)},function(){
        _set_action_info({ name: "Foreach" });
        VAR_CYCLE_INDEX = _iterator() - 1
        if(VAR_CYCLE_INDEX > _cycle_param("foreach_data").length - 1)_break();
        VAR_FOREACH_DATA = _cycle_param("foreach_data")[VAR_CYCLE_INDEX]
        section_insert()
      })!
  </script>

  <script type="text/template" id="loopelement_code">
      /*Browser*/
      ;_SELECTOR=<%=query%>;
      <%= path %>.length()!
      
      _do_with_params({"element_length":_result(),"querycss":(<%= querycss %>),"querymatch":<%= querymatch %> <%if(queryxpath){%>, "queryxpath": (<%= queryxpath %>) <% } %> },function(){
        _set_action_info({ name: "Start Loop" });
        VAR_CYCLE_INDEX = _iterator() - 1
        VAR_FOR_EACH_CSS = _cycle_param("querycss")
        VAR_FOR_EACH_MATCH = _cycle_param("querymatch")
        <% if(queryxpath){ %>
          VAR_FOR_EACH_XPATH = _cycle_param("queryxpath")
        <% } %>

        if(VAR_CYCLE_INDEX >= parseInt(_cycle_param("element_length")))_break();
        section_insert()
      })!
      VAR_CYCLE_INDEX = 0;
  </script>

  <script type="text/template" id="while_code">
      _do(function(){
        _set_action_info({ name: "While" });
        VAR_CYCLE_INDEX = _iterator() - 1
        <%= additional %>
        BREAK_CONDITION = <%= expression %>;
        if(!BREAK_CONDITION)_break();
        section_insert()
      })!
  </script>

  
  <script type="text/template" id="getcookiesforurl_code">
      /*Browser*/
      get_cookies(<%= value %>)!
      <%= variable %> = _result()
  </script>

  <script type="text/template" id="break_code">
      _break("function")
  </script>

  <script type="text/template" id="continue_code">
      _next("function")
  </script>

  <script type="text/template" id="success_code">
      success(<%= message %>)
  </script>

  <script type="text/template" id="fail_code">
      fail_user(<%= message %>,<%= dontrestart %>)
  </script>

  <script type="text/template" id="die_code">
      die(<%= message %>,<%= instant %>)
  </script>

  <script type="text/template" id="label_code">
      _set_goto_label(<%= label %>)!
  </script>

  <script type="text/template" id="goto_code">
      _goto(<%= label %>)!
  </script>

  <script type="text/template" id="custom_code">
      <%= code %>
  </script>

  <!-- ========= -->
  <!-- Libraries -->
  <!-- ========= -->
  <script type="text/javascript"> window.Toolbox = {}; </script>
  <script src="jquery-2.1.3.min.js" type="text/javascript"></script>
  <script src="slimselect.min.js" type="text/javascript"></script>
  <script src="jquery.mousewheel.js" type="text/javascript"></script>
  <script src="lodash.js" type="text/javascript"></script>
  <script src="backbone.js" type="text/javascript"></script>
  <script src="vendor/mitt/mitt.min.js"></script>
  <script src="vendor/md5/md5.min.js"></script>
  <script src="bootstrap.min.js"></script>
  <script src="bootbox.min.js"></script>
  <script src="../actions/actions.js"></script>
  <script src="translate.js"></script>
  <script src="expressioneditor.js"></script>
  <script src="rappid.js"></script>
  <script src="tooledViewPlugin.js"></script>
  <script src="preservemainpage.js"></script>
  <script src="./search/internal/library.min.js"></script>
  <script src="./search/internal/mark.min.js"></script>
  <script src="databasefilter.js"></script>
  <script src="filters.js"></script>
  <script src="sortable.js"></script>
  <script src="./utils/cursorposition.js"></script>
  <script src="./utils/extractVariables.js"></script>
  <script src="utils/createCodeEditor.js"></script>
  <script src="utils/overlay.js"></script>
  <script src="toastr.min.js"></script>
  <script src="embeddedmodel.js"></script>
  <script src="diff_match_patch.js"></script>
  <script src="vs/loader.js"></script>
  <script src="unfold-tooltip.js"></script>
  <script src="multiselectmanager.js"></script>
  <script src="components/tooltips.js"></script>
  <script src="preview/previewUtils.js"></script>
  <script src="preview/previewModel.js"></script>
  <script src="conditionalvisibility.js"></script>
  <script src="selectmanager.js"></script>


  <!-- Actions Search (scripts) -->
  <script src="./search/internal/worker/index.js"></script>
  <script src="./search/internal/items/video.js"></script>
  <script src="./search/internal/items/wiki.js"></script>
  <script src="./search/internal/documents.js"></script>
  <script src="./search/internal/engine.js"></script>
  <script src="./search/internal/helper.js"></script>
  <script src="./search/search.js"></script>

  <!-- Modal Dialogs (scripts) -->
  <script src="./dialogs/internal/index.js"></script>
  <script src="./dialogs/internal/translate.js"></script>
  <script src="./dialogs/internal/options.js"></script>
  <script src="./dialogs/internal/insert.js"></script>
  <script src="./dialogs/internal/menus.js"></script>
  <script src="./dialogs/internal/utils.js"></script>
  <script src="./dialogs/internal/store.js"></script>
  <script src="./dialogs/template/index.js"></script>
  <script src="./dialogs/dialogs.js"></script>
  <script src="./dialogs/functionsDialog.js"></script>
  <script src="./dialogs/resourcesDialog.js"></script>
  <script src="./dialogs/variablesDialog.js"></script>

  <script type="text/javascript"> _L = $.extend(_L, _AL)</script>
  <script type="text/javascript"> _MACRO_INSERT_LOCALIZE_ </script>
  <script type="text/javascript"> _MACRO_INSERT_ACTIONS_ </script>

  <!-- ========= -->
  <!--   Styles  -->
  <!-- ========= -->
  <link rel="stylesheet" href="bootstrap.min.css">
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="font-awesome.min.css">
  <link rel="stylesheet" href="expressioneditor.css">
  <link rel="stylesheet" href="rappid.css">
  <link rel="stylesheet" href="bootstrap-checkbox.css">
  <link rel="stylesheet" href="toastr.min.css">
  <link rel="stylesheet" href="nice-forms.css">
  <link rel="stylesheet" href="slimselect.css">

  <!-- Modal Dialogs (styles) -->
  <link rel="stylesheet" href="./dialogs/dialogs.css">

  <!-- Actions Search (styles) -->
  <link rel="stylesheet" href="./search/search.css">

  <!-- =============== -->
  <!-- Javascript code -->
  <!-- =============== -->
  <script type="text/javascript">
    var _Filter = new Filter();
    var _Filters = new Filters();

    bootbox.setLocale(_K);

    function OnInputKeyPress(e)
    {
      var charCode = !e.charCode ? e.which : e.charCode;
      var IsGoodchar =  (charCode == ','.charCodeAt(0) && $(e.target).is("[data-append-array]")) || charCode >= 'A'.charCodeAt(0) && charCode <= 'Z'.charCodeAt(0) || charCode >= 'a'.charCodeAt(0) && charCode <= 'z'.charCodeAt(0) || charCode == '_'.charCodeAt(0) || charCode >= '0'.charCodeAt(0) && charCode <= '9'.charCodeAt(0)
      if(!IsGoodchar)
          e.preventDefault();
    }

    var TaskModel = Backbone.Model.extend({
        defaults: {
            name: "",
            description: "",
            ref: ""
        }
    });
    var ResourceModel = Backbone.Model.extend({
        defaults: {
            name: "",
            description: "",
            type: ""
        }
    });
    var VariableModel = Backbone.Model.extend({
        defaults: {
            name: "",
            global: false
        }
    });
    var FunctionModel = Backbone.Model.extend({
        defaults: {
            name: "",
            properties: null
        }
    });
    var LabelModel = Backbone.Model.extend({
        defaults: {
            name: ""
        }
    });
    var GobalModel = Backbone.Model.extend({
        defaults: {
            state: "main",
            isedit: false,
            x: "",
            y: "",
            index: 0
        },
        GetPageInfo: function()
        {
          var state = this.get("state")
          var task = _TaskCollection.find(function(item){
            return item.get("ref") == state
          });
          if(task)
            return task.get("name")

          return null;
          
        },
        GetGroupInfo: function()
        {
          var state = this.get("state")

          var CurrentGroupName = null
          var CurrentGroupIcon = null
          var CurrentGroupDescription = null

          for(var i=0; i<_TaskCollection.length; i++)
          {
            var el = _TaskCollection.models[i]
            if(el.get("type") == "group")
            {
              CurrentGroupName = el.get("name")
              CurrentGroupIcon = el.get("icon")
              CurrentGroupDescription = el.get("description")
            }if(el.get("ref") == state)
            {
              return {name: CurrentGroupName, icon: CurrentGroupIcon, description: CurrentGroupDescription}
            }
          }

          return null;
          
        },
    });

    var SelectorModel = Backbone.Model.extend({
        defaults: {
            css: "",
            css1: "",
            css2: "",
            css3: "",
            match: "",
            xpath: "",
            mousex: 0,
            mousey: 0,
            current: "css",
            is_editing: false,
            is_image:false,
            image_data:"",
            version: "1.0",
            is_ai_generated: false,
            ai_generated_name: ""
        }
    });

    function BrowserAutomationStudio_HasPathChoice()
    {
      var m = _SelectorModel.toJSON()
      return m["current"] == "css" && m["is_editing"] == false && (("css1" in m && m["css1"].length > 0) + ("css2" in m && m["css2"].length > 0) + ("css3" in m && m["css3"].length > 0) > 1)
    }

    

    var TaskCollection = Backbone.Collection.extend({
        model: TaskModel
    });
    var ResourceCollection = Backbone.Collection.extend({
        model: ResourceModel
    });
    var VariableCollection = Backbone.Collection.extend({
        model: VariableModel
    });
    var GlobalVariableCollection = Backbone.Collection.extend({
        model: VariableModel
    });
    var FunctionCollection = Backbone.Collection.extend({
        model: FunctionModel
    });
    var LabelCollection = Backbone.Collection.extend({
        model: LabelModel
    });

    var MainView = Backbone.View.extend({
      el: '#container',

      currentInputLabel: "none",

      events: {
        "click #ok": "accept",
        "click #WaitingDisable": "interrupt",
        //"mouseover .toolbutton": "showtooltip",
        "click #backtomain": "backtomain",
        "click #backtomainfromtopmenu": "backtomainfromtopmenu",
        "click #backtohomefromtopmenu": "backtohomefromtopmenu",
        "show.bs.modal #LabelModal": "labeladdstart",
        "mousedown .var": "varaddstarttrigger",
        "mousedown .res": "resaddstarttrigger",
        "mousedown .func": "funcaddstarttrigger",
        "click #PathCount": "nextpath",

        "click .labelok": "labeladd",
        "click .timeoutok": "timeoutadd",
        "click .timeoutdefault": "timeoutdefault",
        "click .groupshow": "groupshow",
        "click .returntomain": "returntomain",
        "click #showhistory": "showhistory",
        "click #showbookmarks": "showbookmarks",
        "mouseup #showhistory": "showhistorymouseup",
        "mouseup #showbookmarks": "showbookmarksmouseup",

        "mousedown .edit": "editstart",
        "click .specialletter": "specialletter",
        "click .execute-type-item": "clickExecuteType",
        "click #css":"css",
        "click #match":"match",
        "click #xpath":"xpath",
        "click #at":"at",
        "click #none":"none",
        "click .string": "string",
        "click .expression": "expression",
        "click .int": "int",
        "mousedown .variant": "selectvariant",
        "click .addtopost": "addpostdata",
        "click .addtopostfile": "addpostdatafile",
        "click .addtopostbase64": "addpostdatabase64",

        "click #use-waiter": "usewaiterchange",
        "click #use-timeout": "usetimeoutchange",
        "click #use-target": "usetargetchange",
        "click #use-move": "usemovechange",
        "click #use-emulation": "useemulationchange",
        "click #use-scroll-params": "usescrollparamschange",

        "click #searchclear": "searchclearclick",
        "click #searchinput": "searchinputclick",
        "focus #searchinput": "searchinputfocus",
        "blur #searchinput": "searchinputblur",
        "input #searchinput": "searchinput",
        
        "focus .dropdown-menu-path": "dropdownmenupathfocus",
        "blur .dropdown-menu-path": "dropdownmenupathblur",
        "click .dropdown-menu-path": "stoppropagation",
        "keyup .dropdown-menu-path": "pathchanged",
        "mousedown .dropdown-menu-css-item": "dropdownmenupathselectitem",

        "change #Table": "tablechange",
        "mouseenter .tool": "toolmouseenter",
        "mouseleave .tool": "toolmouseleave",

        "focus .input_selector_string": "input_selector_focus",
        "blur .input_selector_string": "input_selector_blur",

        "focus .input_selector_number": "input_selector_focus",
        "blur .input_selector_number": "input_selector_blur",

        "focus .variable-input": "input_selector_focus",
        "blur .variable-input": "input_selector_blur",

        "focus .function-input": "input_selector_focus",
        "blur .function-input": "input_selector_blur",

        "focus .resource-input": "input_selector_focus",
        "blur .resource-input": "input_selector_blur",

        "change #checkbox-image-show-data": "toggleimageshowdata",
        "change #ImageBase64": "imagebase64changed",
        "click #ImageDataRef": "showimage",
        
        "click .preview-button": function ({ target }) {
          const $button = target.closest('.preview-button');
          switch ($button.dataset.action) {
            case 'delete':
              PreviewModel.deleteImage();
              break;
            case 'update':
              PreviewModel.updateImage();
              break;
            case 'restore':
              PreviewModel.restoreImage();  
              break;
          }
        },

        "input .variable-input": function({ target }) {
          target.value = target.value
            .replace(target.matches('[data-append-array]') ? /[^\w,]/g : /[^\w]/g, "")
            .toUpperCase();
        },
     },

      nextpath: function(event)
      {
        var Total = parseInt($("#PathCount").text())
        if(Total > 0 && $("#selector-input").length > 0 && $("#selector-input").val().length > 0)
        {
          BrowserAutomationStudio_IncrementHighlightIndex()
        }
      },

      showimage: function(event)
      {
        event.preventDefault();
        event.stopPropagation();
        var dialog = bootbox.alert({
          message: $("<img/>").attr("src",$("#ImageData").attr("src")).attr("class","img-responsive")[0].outerHTML
   
        });
      },

      imagebase64changed:function()
      {
        var data = $("#ImageBase64").val()
        $("#ImageData").attr("src","data:image/png;base64," + data)
      },

      toggleimageshowdata:function()
      {
        if($("#checkbox-image-show-data").prop("checked"))
        {
          $("#ImageBase64Container").show()
        }else
        {
          $("#ImageBase64Container").hide()
        }
      },

      pathchanged:function()
      {
        _MultiSelectManager.PathManualyEdited()
        BrowserAutomationStudio_TestPathInternal();
      },


      input_selector_focus:function(event)
      {
        $(event.target).siblings(".input-field-dropdown").show();
        $(event.target).trigger('show.bs.dropdown');
      },

      input_selector_blur:function(event)
      {
        $(event.target).siblings(".input-field-dropdown").hide();
        $(event.target).trigger('hide.bs.dropdown');
      },


      toolmouseenter:function(event)
      {
        $(event.target).closest(".tool").addClass("toolhover")
      },

      toolmouseleave:function(event)
      {
        $(event.target).closest(".tool").removeClass("toolhover")
      },

      showhistory:function(event)
      {
        event.preventDefault();
        event.stopPropagation();
        BrowserAutomationStudio_ShowHideHistory();
      },

      showbookmarks:function(event)
      {
        event.preventDefault();
        event.stopPropagation();
        BrowserAutomationStudio_ShowHideBookmarks();
      },

      showhistorymouseup:function(event)
      {
        $("#showhistory").blur();
      },

      showbookmarksmouseup:function(event)
      {
        $("#showbookmarks").blur();
      },

      returntomain:function(event)
      {
        event.preventDefault();
        event.stopPropagation();
        BrowserAutomationStudio_ReturnToMainFunction();
      },

      groupshow:function(event)
      {
        event.preventDefault();
        event.stopPropagation();
        if($(event.target).closest(".panelgrid").hasClass("panelunused"))
        {
          var ModuleName = $(event.target).closest(".panelgrid").attr("data-task-name")
          var ModuleDescription = $(event.target).closest(".panelgrid").find(".panelgridtitleinner").text()
          //Clicked on unused module
          BrowserAutomationStudio_AskEnableModule(ModuleName, ModuleDescription)
          return
        }
        if(CurrentGroup == "")
        {
          var group = $(event.target).closest("a").attr("data-group")
          if(group == "ai")
          {
            BrowserAutomationStudio_StartHelper();
            return;
          }
          BrowserAutomationStudio_GotoGroup(group);
        }else
        {
          BrowserAutomationStudio_ReturnToMainFunction();
        }

      },

      tablechange:function(event)
      {
        $("*[data-table-id]").hide()
        $("*[data-table-id=" + $("#Table").val() + "]").show()
        _Filter.Clear()
      },

     
      interrupt: function(event)
      {
        event.preventDefault();
        $("#InterruptMessage").show();
        $("#WaitingDisable").hide();
        BrowserAutomationStudio_Interrupt()
      },

      stoppropagation: function(event)
      {
        event.stopPropagation();
      },

      dropdownmenupathselectitem: function(event)
      {
          event.preventDefault();
          event.stopPropagation();

          $(".dropdown-menu-css-item").removeAttr("data-selected")
          $(event.target).closest("a").attr("data-selected","true")

          $(".dropdown-menu-path").val($(event.target).closest("a").text())
          $(".dropdown-menu-path").blur();
          $(".dropdown-menu-css-options").hide()
          $(".dropdown-menu-match-xpath-at-css-options").hide()
          BrowserAutomationStudio_TestPathInternal()
      },

      dropdownmenupathblur: function(event)
      {
          $(".dropdown-menu-css-options").hide()  
          $(".dropdown-menu-match-xpath-at-css-options").hide()
      },

      dropdownmenupathfocus: function(event)
      {
        var current = _SelectorModel.get("current")
        if(current == "css")
        {
          $(".dropdown-menu-css-options").show()
          
        }else if(current == "match" || current == "xpath" || current == "at")
        {
          $(".dropdown-menu-match-xpath-at-css-options").show()
        }      
      },

      searchinput: _.debounce(function (event) {
        const query = $(event.target).val().trim();

        if (query) {
          _SearchManager.search(query);
        } else {
          _SearchManager.recent();
        }
      }, 500),

      searchinputclick: function(event)
      {
        _SearchManager.show();
      },

      searchclearclick: function(event)
        {
        _SearchManager.hide();
      },

      searchinputfocus: function(event)
      {
        $(event.target).attr("placeholder", 
          tr("Search by action name, name part or keyword. Examples: 'Ignore Errors', 'phone'."));
      },

      searchinputblur: function(event)
      {
        $(event.target).attr("placeholder", 
          tr("What to search?"));
      },

      usewaiterchange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a")
        var new_state = el.attr("data-enabled") != "true"
        el.attr("data-enabled",((new_state) ? "true" : "false") );
        el.removeClass().addClass(((new_state) ? "use-waiter-enabled" : "use-waiter-disabled") );
      },

      usetimeoutchange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a");
        $('#TimeoutModal').modal() 
        $("#TimeoutValue").val(el.attr("data-value"))
      },

      usetargetchange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a")
        var new_state = el.attr("data-enabled") != "true"
        el.attr("data-enabled",((new_state) ? "true" : "false") );
        el.removeClass().addClass(((new_state) ? "use-target-enabled" : "use-target-disabled") );
        if(new_state)
        {
          $("#target-data").show()
        }else
        {
          $("#target-data").hide()
        }
      },

      usemovechange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a")
        var new_state = el.attr("data-enabled") != "true"
        el.attr("data-enabled",((new_state) ? "true" : "false") );
        el.removeClass().addClass(((new_state) ? "use-move-enabled" : "use-move-disabled") );
        if(new_state)
        {
          $("#move-data").show()
        }else
        {
          $("#move-data").hide()
        }
      },

      useemulationchange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a")
        var new_state = el.attr("data-enabled") != "true"
        el.attr("data-enabled",((new_state) ? "true" : "false") );
        el.removeClass().addClass(((new_state) ? "use-emulation-enabled" : "use-emulation-disabled") );
        if(new_state)
        {
          $("#emulation-data").show()
        }else
        {
          $("#emulation-data").hide()
        }
      },

      usescrollparamschange: function(event)
      {
        event.preventDefault();
        var el = $(event.target).closest("a")
        var new_state = el.attr("data-enabled") != "true"
        el.attr("data-enabled",((new_state) ? "true" : "false") );
        el.removeClass().addClass(((new_state) ? "use-scroll-params-enabled" : "use-scroll-params-disabled") );
        if(new_state)
        {
          $("#scroll-params-data").show()
        }else
        {
          $("#scroll-params-data").hide()
        }
      },

      editstart: function(event)
      {
        event.preventDefault();

        $("#containerdata").hide()
        var target = $(event.target).closest("a")
        var selector = target.attr("data-result-target")
        ToolboxMaximizeCallback = function()
        {
          $(".modal-backdrop").hide()
          $("#expressioneditor-container").show()
          document.documentElement.style.zoom = '100%';

          //Get original value
          var value = null
          var data = null
          {
            var Loader = new ResourceLoader()
            Loader.SetIsPrerender(true)
            var id = target.closest("*[data-preserve-id]").attr("data-preserve-id")
            //console.log(id)
            var V = GetInputConstructorValue(id,Loader)
            data = target.closest("*[data-preserve-id]").attr("data-preserve-json")
            if(typeof(data) == "undefined")
              data = ""

            value = V["updated"]
          }
          _ExpressionEditor = new ExpressionEditor(function(Result){
            $("#containerdata").show()
            BrowserAutomationStudio_Minimize()
            $(".modal-backdrop").show()
            $("#expressioneditor-container").hide()
            document.documentElement.style.zoom = _Z + '%'
            if(Result["ok"])
            {
              target.closest("*[data-preserve-id]").attr("data-preserve-json",Result["data"])
              $(selector).val(Result["res"])
              $(selector).closest(".input-group").find(".selector").html("expression")
              $(selector).closest(".input-group").find(".input_selector_number").hide()
              $(selector).closest(".input-group").find(".input_selector_string").show()
            }
          },value,data)
        };
        BrowserAutomationStudio_Maximize();
      },

      backtomain: function()
      {
        $('.modal').modal('hide');
        BrowserAutomationStudio_EditCancel();
      },

      backtomainfromtopmenu: function(event)
      {
        $('.modal').modal('hide');
        var target = $(event.target).closest("a")
        var GroupName = target.attr("data-group-name")
        _PreserveMainPosition.SetScroll(0);
        _PreserveMainPosition.SetGroup(GroupName);
        BrowserAutomationStudio_EditCancel();
      },

      backtohomefromtopmenu: function()
      {
        $('.modal').modal('hide');
        _PreserveMainPosition.SetScroll(0);
        _PreserveMainPosition.SetGroup("");
        BrowserAutomationStudio_EditCancel();
      },
      
      addpostdata: function(event)
      {
        var loader = new ResourceLoader();
        loader.SetIsPrerender(true)
        var Name = GetInputConstructorValue("PostName",loader)["updated"]
        var Value = GetInputConstructorValue("PostValue",loader)["updated"]

        var Data = $("#PostDataArray").val()
        if(Name.length > 0 && Value.length > 0)
        {
          if(Data.length === 0)
          {
            $("#PostDataArray").val(Name  + "," + Value);
          }else
          {
            $("#PostDataArray").val(Data + "," + Name  + "," + Value)
          }
          $("#PostName").val("")
          $("#PostValue").val("")
        }
        
      },

      addpostdatafile: function(event)
      {
        $("#PostValue").val("file://" + $("#PostValue").val());
        this.addpostdata(null)
      },

      addpostdatabase64: function(event)
      {
        $("#PostValue").val("base64://" + $("#PostValue").val());
        this.addpostdata(null)
      },

      selectvariant: function(event)
      {
        var target = $(event.target).closest("a");
        var variant = target.attr("data-variant");
        var variant_type = target.attr("data-variant-type");
        var result = $("#" + target.attr("data-result"));
        function _set_variant(value, type){
          if(type=="string" || type=="expression"){
            result.closest(".input-group").find(".selector").html(type);
            result.closest(".input-group").find(".input_selector_number").hide();
            result.closest(".input-group").find(".input_selector_string").show();
            result.closest(".input-group").find(".input_selector_string").val(value);
          }else{
            result.closest(".input-group").find(".selector").html("int");
            result.closest(".input-group").find(".input_selector_number").show();
            result.closest(".input-group").find(".input_selector_string").hide();
            result.closest(".input-group").find(".input_selector_number").val(value);
          };
        };
        if(variant_type && result.closest(".input-group").find("." + variant_type).length > 0){
          _set_variant(variant, variant_type);
        }else{
          if(result.closest(".input-group").find(".string").length > 0){
            _set_variant(variant, "string");
          }else{
            if(result.closest(".input-group").find(".int").length > 0){
              _set_variant(variant, "int");
            }else{
              _set_variant(variant, "expression");
            };
          };
        };
      },

      string: function(event)
      {
        $(event.target).closest(".input-group").find(".selector").html("string")
        $(event.target).closest(".input-group").find(".input_selector_number").hide()
        $(event.target).closest(".input-group").find(".input_selector_string").show()
      },

      int: function(event)
      {
        $(event.target).closest(".input-group").find(".selector").html("int")
        $(event.target).closest(".input-group").find(".input_selector_number").show()
        $(event.target).closest(".input-group").find(".input_selector_string").hide()
      },

      expression: function(event)
      {
        $(event.target).closest(".input-group").find(".selector").html("expression")
        $(event.target).closest(".input-group").find(".input_selector_number").hide()
        $(event.target).closest(".input-group").find(".input_selector_string").show()
      },

      updatepath: function()
      {
        if(_SelectorModel.get("is_image"))
        {
          $(".disable-if-find-by-image").hide()
        }else
        {
          var current = _SelectorModel.get("current")
          
          if(current == "css")
            this.css()
          else if(current == "match")
            this.match()
          else if(current == "xpath")
            this.xpath()
          else if(current == "at")
            this.at()
          else if(current == "none")
            this.none()
        }
      },

      css:function(event)
      {
        
        $("#selector").html("css")
        $("#selector-input").removeAttr("disabled").val(_SelectorModel.get("css"))
        _SelectorModel.set("current","css")
        BrowserAutomationStudio_TestPathInternal();
        
        $(".dropdown-menu-css-item").removeAttr("data-selected")
        $(".dropdown-menu-css-item").first().attr("data-selected","true")

      },

      match:function(event)
      {
        $("#selector").html("match")
        $("#selector-input").removeAttr("disabled").val(_SelectorModel.get("match"))
        _SelectorModel.set("current","match")
        BrowserAutomationStudio_TestPathInternal();

        $(".dropdown-menu-css-item").removeAttr("data-selected")
        $(".dropdown-menu-css-item").first().attr("data-selected","true")
      },

      xpath:function(event)
      {
        $("#selector").html("xpath")
        $("#selector-input").removeAttr("disabled").val(_SelectorModel.get("xpath"))
        _SelectorModel.set("current","xpath")
        BrowserAutomationStudio_TestPathInternal();

        $(".dropdown-menu-css-item").removeAttr("data-selected")
        $(".dropdown-menu-css-item").first().attr("data-selected","true")
      },

      at:function(event)
      {
        $("#selector").html("at")
        $("#selector-input").removeAttr("disabled").val(_SelectorModel.get("mousex") + ", " + _SelectorModel.get("mousey"))
        _SelectorModel.set("current","at")
        BrowserAutomationStudio_TestPathInternal();

        $(".dropdown-menu-css-item").removeAttr("data-selected")
        $(".dropdown-menu-css-item").first().attr("data-selected","true")
      },

      none:function(event)
      {
        $("#selector").html("none")
        $("#selector-input").attr("disabled","disabled").val("")

        _SelectorModel.set("current","none")
        BrowserAutomationStudio_TestPathInternal();

        $(".dropdown-menu-css-item").removeAttr("data-selected")
        $(".dropdown-menu-css-item").first().attr("data-selected","true")
      },

      clickExecuteType:function(event)
      {
        const $executeTypeItem = $(event.target).closest('a');
        const data = $executeTypeItem.data();
        const html = $executeTypeItem.html();
        event.preventDefault();

        $('#executeTypeValue').data('action', data.action).html(html);
      },

      specialletter: function(event)
      {
        InsertAtCaret("TypeData","<" + $(event.target).attr("data-key") + ">");
      },

      funcaddstarttrigger: function({ target })
      {
        BasFunctionsDialog.create($(target).closest('a'));
      },

      resaddstarttrigger: function({ target })
      {
        BasResourcesDialog.create($(target).closest('a'));
      },

      varaddstarttrigger: function({ target })
      {
        BasVariablesDialog.create($(target).closest('a'));
      },

      funcchange: function(FuncName)
      {
        var Parameters = _FunctionCollection.toJSON().find(function(Func){
          if(Func.name == FuncName)
            return Func

        });

        if(typeof(Parameters) == "undefined" || !Parameters)
        {
          return
        }

        $("#FunctionParameters").html("")
        $("#FunctionParametersNoReturn").html("")
        Parameters.properties.p.forEach(function(Param){
          var Type = Param.type

          
          var Settings = {id:"ParamId_" + tohex(Param.name), description:Param.name}
          if(Type == "String")
          {
            Settings["default_selector"] = "string"
            Settings["disable_int"] = true
            Settings["disable_expression"] = true
            Settings["value_string"] = Param.defaults
          }
          if(Type == "Number")
          {
            Settings["default_selector"] = "int"
            Settings["disable_string"] = true
            //Settings["disable_expression"] = true
            Settings["min_number"] = Number.MIN_SAFE_INTEGER
            Settings["max_number"] = Number.MAX_SAFE_INTEGER
            Settings["value_number"] = 0

            try
            {
              if(Param.defaults.length > 0 )
              {
                Settings["value_number"] = parseInt(Param.defaults)
              }
            }catch(e)
            {

            }
            
          }
          if(Type == "Boolean")
          {
            Settings["default_selector"] = "string"
            Settings["disable_int"] = true
            Settings["variants"] = ["true", "false"]
            Settings["value_string"] = "true"
            if(Param.defaults.length > 0)
            {
              Settings["value_string"] = Param.defaults
            }

          }
          if(Type == "Expression")
          {
            Settings["default_selector"] = "expression"
            Settings["disable_int"] = true
            Settings["disable_string"] = true
            Settings["value_string"] = Param.defaults
            
          }
          if(Type == "StringOrExpression")
          {
            Settings["default_selector"] = "string"
            Settings["disable_int"] = true
            Settings["value_string"] = Param.defaults
          }
          if(Type == "NumberOrExpression")
          {
            Settings["default_selector"] = "int"
            Settings["disable_string"] = true
            Settings["min_number"] = Number.MIN_SAFE_INTEGER
            Settings["max_number"] = Number.MAX_SAFE_INTEGER
            Settings["value_number"] = 0

            try
            {
              if(Param.defaults.length > 0 )
              {
                Settings["value_number"] = parseInt(Param.defaults)
              }
            }catch(e)
            {

            }
          }

          Settings["help"] = {description: Param.description}
          var Template = _.template($('#input_constructor').html())(Settings)
          $("#FunctionParameters").append(Template)
          $("#FunctionParametersNoReturn").append(Template)

        })

        if(Parameters.properties.hr)
        {
          var Template = _.template($('#variable_constructor').html())({
            id:"Save", 
            description: tr("Return value"), 
            default_variable: Parameters.properties.rv,
            help: {description: Parameters.properties.rd}
          })
          $("#FunctionParameters").append(Template)
        }
        Toolbox.setupTooltips();
        $("#FunctionParameters .variable-input, #FunctionParameters .function-input").keypress(OnInputKeyPress)
      },

      labeladdstart: function(event)
      {
        var json = _LabelCollection.toJSON();

        $('#LabelNameInput').html("")
        if(json.length == 0)
        {
          $("#NoLabelFound").show()
          $("#LabelNameInput").hide()
          $(".labelok").hide()

        }else
        {
          $("#NoLabelFound").hide()
          $("#LabelNameInput").show()
          $(".labelok").show()
          json = jsort(json);
          for(var i = 0;i<json.length;i+=1)
          {
            $('#LabelNameInput')
             .append($("<option></option>")
             .attr("value",json[i]["name"])
             .text(json[i]["name"]));
           }
         }

        $('#LabelNameInput').focus()
        this.currentInputLabel = $(event.relatedTarget).attr("data-result-target")

      },
      
      labeladd: function(event)
      {
        var el = $(this.currentInputLabel)

        var name = $("#LabelNameInput").val();
        if(name.length > 0)
        {
          el.val($("#LabelNameInput").val())
        }
      },

      timeoutadd: function(event)
      {
        var timeout_value = $("#TimeoutValue").val()

        $("#use-timeout").attr("data-value", (typeof(timeout_value) != "undefined" && timeout_value > 0) ? timeout_value : "0")
                        .attr("class", ((typeof(timeout_value) != "undefined" && timeout_value > 0) ? "" : "use-timeout-disabled") + " trtitle")
                        .attr("data-enabled", (typeof(timeout_value) != "undefined" && timeout_value > 0) ? "true" : "false")

        $("#timeout-val").html((typeof(timeout_value) != "undefined" && timeout_value > 0) ? ("" + timeout_value) : "")
        if(typeof(timeout_value) != "undefined" && timeout_value > 0)
        {
         $("#timeout-is-default").hide()
        }else
        {
          $("#timeout-is-default").show()
        }


      },

      timeoutdefault: function(event)
      {
        $("#TimeoutValue").val(0)

        this.timeoutadd(null);

      },

      accept: function()
      {
          const previewState = PreviewModel.state();
          if (!PreviewModel.isDisabled && previewState.isUpdating) {
            const dialog = bootbox.dialog({
              message: `<div class="text-center"><i class="fa fa-spin fa-spinner"></i>${tr("Updating")}...</div>`,
              closeButton: false, 
              animate: false,
            });

            PreviewModel.waitForUpdate().then((result) => {
              dialog.modal("hide");
              _MainView.accept();
            });
            return;
          }
          var State = this.model.get("state");
          var loader = new ResourceLoader();

          var action = $("#executeTypeValue").data("action")

          BrowserAutomationStudio_LastExecuteType = action

          if(typeof(action) == "undefined")
          {
            action = 2
          }else if(action == "execute")
          {
            action = 0
          }else if(action == "add")
          {
            action = 1
          }else if(action == "executeandadd")
          {
            action = 2
          }


          var DisableIfAdd = true
          if(_GobalModel.get("isedit"))
          {
            DisableIfAdd = action == 1
            action = 1
          }




          if(State == "load")
          {
            var val = GetInputConstructorValue("LoadUrl",loader)
            var referrer = GetInputConstructorValue("Referrer",loader)

            if(val["original"].length == 0)
            {
              Invalid("Url is empty");
              return;
            }

               try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({url:val["updated"],referrer:referrer["updated"],notinstant:BrowserAutomationStudio_UsesWaitCode()})
                code = Normalize(code,0)

                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
        
          }else if(State == "navigateback")
          {
            
            try{
              var is_instant = true
              var usewaiter = $("#use-waiter")

              if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true")  
              {
                is_instant = false
              }

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({is_instant: is_instant}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)

              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {

            }
            
          }else if(State == "httpclientxpathxml")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            var fail = $("#Check").is(':checked')


            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"], fail:fail})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientxpathxmllist")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "waitelement")
          {
             var CheckIsvisible = $("#Check").is(':checked')
             try{
              var path = GetPath(loader,true,CheckIsvisible)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "httpclientxpathtext")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            var fail = $("#Check").is(':checked')


            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"], fail:fail})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientxpathtextlist")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientxpathcount")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientxpathexists")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Query is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientfailonerror")
          {
            var Value = GetInputConstructorValue("SetFailed",loader)

            if(Value["original"].length <= 0)
            {
              Invalid("Value is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
            
          }else if(State == "httpclienturl")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientcontent")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Encoding = GetInputConstructorValue("Encoding", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save, encoding: Encoding["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientiserror")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientgeterrorstring")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientstatus")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientgetheader")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Header is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientsetheader")
          {
            var Name = GetInputConstructorValue("Name",loader)
            var Value = GetInputConstructorValue("Value",loader)

            if(Name["original"].length <= 0)
            {
              Invalid("Name is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({name:Name["updated"],value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("" , BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "httpclientgetcookiesforurl")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Url is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientrestorecookies")
          {
            var Value = GetInputConstructorValue("Value",loader)

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "httpclientsavecookies")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "httpclientclearheader")
          {

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("" , BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "httpclientget")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var Method = GetInputConstructorValue("Method",loader)
            var Headers = GetInputConstructorValue("Headers",loader)
            var follow = $("#Check").is(':checked')

            if(Value["original"].length <= 0)
            {
              Invalid("Url is empty");
              return;
            }

            if(Method["original"].length <= 0)
            {
              Invalid("Method is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({follow:follow,value:Value["updated"],method:Method["updated"], headers: Headers["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
            
          }else if(State == "httpclientpost")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var follow = $("#Check").is(':checked')
            var UseConstructor = $("#Check2").is(':checked')
            var Encoding = GetInputConstructorValue("Encoding",loader)
            var Method = GetInputConstructorValue("Method",loader)
            var ContentType = GetInputConstructorValue("ContentType",loader)
            var PostDataArray = GetInputConstructorValue("PostDataArray",loader)
            var Headers = GetInputConstructorValue("Headers",loader)

            var PostDataRaw = GetInputConstructorValue("PostDataRaw",loader)
            var ContentTypeRaw = GetInputConstructorValue("ContentTypeRaw",loader)


            if(Value["original"].length <= 0)
            {
              Invalid("Url is empty");
              return;
            }

            if(Encoding["original"].length <= 0)
            {
              Invalid("Encoding is empty");
              return;
            }

            if(Method["original"].length <= 0)
            {
              Invalid("Method is empty");
              return;
            }

            if(ContentType["original"].length <= 0)
            {
              Invalid("ContentType is empty");
              return;
            }


             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({
                follow:follow,
                value:Value["updated"],
                contenttype:ContentType["updated"],
                encoding:Encoding["updated"],
                method:Method["updated"],
                useconstructor:UseConstructor,
                postdataraw:PostDataRaw["updated"].replace(/base64:/g,"_browserautomationstudio_base64:"),
                contenttyperaw:ContentTypeRaw["updated"],
                params:"[" + PostDataArray["updated"] + "]",
                headers: Headers["updated"]
              })
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
          }else if(State == "parseline")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var List = $("#VariablesList").val().toUpperCase()
            
            if(Value["original"].length <= 0)
            {
              Invalid("Value is empty");
              return;
            }

            if(List.length <= 0)
            {
              Invalid("Variables list is empty");
              return;
            }

            List = List.replace(/\s/g,"")
            List = List.split(",")
            List = _.compact(List);
            if(List.length > 0)
            {
              /*List[0] = List[0].replace(/[\\[\\]]/g,"")
              List[List.length - 1] = List[List.length - 1].replace(/[\\[\\]]/g,"")*/
            }else
            {
              Invalid("Variables list is empty");
              return; 
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({list:List,value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
           
          }else if(State == "httpclientproxy")
          {
              var ProxyText = GetInputConstructorValue("ProxyText",loader)
              var ProxyType = GetInputConstructorValue("ProxyType", loader)
              var ProxyLogin = GetInputConstructorValue("ProxyLogin",loader)
              if(ProxyLogin["updated"] == "")
                ProxyLogin["updated"] = '""'
              var ProxyPassword = GetInputConstructorValue("ProxyPassword",loader)
              if(ProxyPassword["updated"] == "")
                ProxyPassword["updated"] = '""'
              var IsEmptyProxy = false
              if(ProxyText["updated"] == "")
              {
                ProxyText["updated"] = '""'
                IsEmptyProxy = true
              }

              try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({ProxyText:ProxyText["updated"], ProxyType:ProxyType["updated"],ProxyLogin:ProxyLogin["updated"],ProxyPassword:ProxyPassword["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e){}


          }
          else if(State == "httpclientreset")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "solverfailed")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }
          else if(State == "httpclientdownload")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var File = GetInputConstructorValue("File",loader)


            if(Value["original"].length <= 0)
            {
              Invalid("Url is empty");
              return;
            }
            if(File["original"].length <= 0)
            {
              Invalid("File is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({file:File["updated"],value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
            
          }else if(State == "globalset")
          {
            var Name = this.$el.find("#Name").val().toUpperCase();
            var Value = GetInputConstructorValue("Value",loader)

            if(Name.length <= 0)
            {
              Invalid("Key is empty");
              return;
            }
            if(Value["original"].length <= 0)
            {
              Invalid("Value is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({key:JSON.stringify(Name),value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "globalget")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Name = GetInputConstructorValue("Name", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Name["original"].length == 0)
            {
              Invalid("Key is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,key: Name["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "result")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var num = $("#Select").val()

            if(Value["original"].length <= 0)
            {
              Invalid("Data is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({number:parseInt(num)-1,value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "cachemaskallow" || State == "cachemaskdeny")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var limit = GetInputConstructorValue("limit",loader);

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Replacement ID"));
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters,limit:limit["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "requestmaskallow" || State == "requestmaskdeny")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Replacement ID"));
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "cleardata")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "loadcookiesfrombrowser")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "loadcookiesfromhttpclient")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "closebrowser")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}
          }else if(State == "openbrowser")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}
          }else if(State == "clearmasks")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "getstatus" || State == "isloaded")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified("Variable To Save");
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "getfromcache")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified("Variable To Save");
              return;
            }

            var waitItem = $("#waitItem").is(':checked')
            var base64 = $("#Check").is(':checked')
            
            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters,waitItem:waitItem,base64:base64})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "getallcache")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified("Variable To Save");
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "redirectrequests")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var replaceMode = $("#replaceMode").val();

            var exact = GetInputConstructorValue("exact",loader);
            if(replaceMode == "exact" && exact["original"].length == 0){
              ParameterNotSpecified("Exact value");
              return;
            }
            var replaceAllExact = $("#replaceAllExact").is(':checked');

            var regexp = GetInputConstructorValue("regexp",loader);
            if(replaceMode == "regexp" && regexp["original"].length == 0){
              ParameterNotSpecified("Regular expression");
              return;
            }
            var ignoreСase = GetInputConstructorValue("ignoreСase",loader);
            if(replaceMode == "regexp" && ignoreСase["original"].length == 0){
              ParameterNotSpecified("Ignore case");
              return;
            }
            var globalSearch = GetInputConstructorValue("globalSearch",loader);
            if(replaceMode == "regexp" && globalSearch["original"].length == 0){
              ParameterNotSpecified("Global search");
              return;
            }

            var before = GetInputConstructorValue("before",loader);
            if(replaceMode == "before" && before["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var after = GetInputConstructorValue("after",loader);
            if(replaceMode == "after" && after["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var leftValue = GetInputConstructorValue("leftValue",loader);
            if(replaceMode == "between" && leftValue["original"].length == 0){
              ParameterNotSpecified("Left value");
              return;
            }
            var rightValue = GetInputConstructorValue("rightValue",loader);
            if(replaceMode == "between" && rightValue["original"].length == 0){
              ParameterNotSpecified("Right value");
              return;
            }

            var searchValue = ''
            if(replaceMode == "exact"){
              searchValue = exact["updated"]
            }if(replaceMode == "regexp"){
              searchValue = regexp["updated"]
            }else if(replaceMode == "before"){
              searchValue = before["updated"]
            }else if(replaceMode == "after"){
              searchValue = after["updated"]
            }else if(replaceMode == "between"){
              searchValue = leftValue["updated"]
            }

            var newValue = GetInputConstructorValue("newValue",loader);

            var limit = GetInputConstructorValue("limit",loader);

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Replacement ID"));
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters,replaceMode:replaceMode,searchValue:searchValue,replaceAllExact:replaceAllExact,ignoreСase:ignoreСase["updated"],globalSearch:globalSearch["updated"],searchValue2:rightValue["updated"],newValue:newValue["updated"],limit:limit["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "replacerequestcontent")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var contentFilters = _Filters.getFiltersValue("contentFilters");

            var replaceMode = $("#replaceMode").val();

            var exact = GetInputConstructorValue("exact",loader);
            if(replaceMode == "exact" && exact["original"].length == 0){
              ParameterNotSpecified("Exact value");
              return;
            }
            var replaceAllExact = $("#replaceAllExact").is(':checked');

            var regexp = GetInputConstructorValue("regexp",loader);
            if(replaceMode == "regexp" && regexp["original"].length == 0){
              ParameterNotSpecified("Regular expression");
              return;
            }
            var ignoreСase = GetInputConstructorValue("ignoreСase",loader);
            if(replaceMode == "regexp" && ignoreСase["original"].length == 0){
              ParameterNotSpecified("Ignore case");
              return;
            }
            var globalSearch = GetInputConstructorValue("globalSearch",loader);
            if(replaceMode == "regexp" && globalSearch["original"].length == 0){
              ParameterNotSpecified("Global search");
              return;
            }
            var multiline = GetInputConstructorValue("multiline",loader);
            if(replaceMode == "regexp" && multiline["original"].length == 0){
              ParameterNotSpecified("Multiline mode");
              return;
            }

            var before = GetInputConstructorValue("before",loader);
            if(replaceMode == "before" && before["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var after = GetInputConstructorValue("after",loader);
            if(replaceMode == "after" && after["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var leftValue = GetInputConstructorValue("leftValue",loader);
            if(replaceMode == "between" && leftValue["original"].length == 0){
              ParameterNotSpecified("Left value");
              return;
            }
            var rightValue = GetInputConstructorValue("rightValue",loader);
            if(replaceMode == "between" && rightValue["original"].length == 0){
              ParameterNotSpecified("Right value");
              return;
            }

            var searchValue = ''
            if(replaceMode == "exact"){
              searchValue = exact["updated"]
            }if(replaceMode == "regexp"){
              searchValue = regexp["updated"]
            }else if(replaceMode == "before"){
              searchValue = before["updated"]
            }else if(replaceMode == "after"){
              searchValue = after["updated"]
            }else if(replaceMode == "between"){
              searchValue = leftValue["updated"]
            }

            var newValue = GetInputConstructorValue("newValue",loader);

            var limit = GetInputConstructorValue("limit",loader);

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Replacement ID"));
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters,contentFilters:contentFilters,replaceMode:replaceMode,searchValue:searchValue,replaceAllExact:replaceAllExact,ignoreСase:ignoreСase["updated"],globalSearch:globalSearch["updated"],multiline:multiline["updated"],searchValue2:rightValue["updated"],newValue:newValue["updated"],limit:limit["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "replaceresponsecontent")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            var methods = GetInputConstructorValue("methods",loader);
            if(methods["original"].length == 0){
              ParameterNotSpecified("Request type");
              return;
            }

            urlFilters = urlFilters.slice(0,-1) + `,methods:(${methods["updated"]})}`;

            var contentFilters = _Filters.getFiltersValue("contentFilters");

            var replaceMode = $("#replaceMode").val();

            var exact = GetInputConstructorValue("exact",loader);
            if(replaceMode == "exact" && exact["original"].length == 0){
              ParameterNotSpecified("Exact value");
              return;
            }
            var replaceAllExact = $("#replaceAllExact").is(':checked');

            var regexp = GetInputConstructorValue("regexp",loader);
            if(replaceMode == "regexp" && regexp["original"].length == 0){
              ParameterNotSpecified("Regular expression");
              return;
            }
            var ignoreСase = GetInputConstructorValue("ignoreСase",loader);
            if(replaceMode == "regexp" && ignoreСase["original"].length == 0){
              ParameterNotSpecified("Ignore case");
              return;
            }
            var globalSearch = GetInputConstructorValue("globalSearch",loader);
            if(replaceMode == "regexp" && globalSearch["original"].length == 0){
              ParameterNotSpecified("Global search");
              return;
            }
            var multiline = GetInputConstructorValue("multiline",loader);
            if(replaceMode == "regexp" && multiline["original"].length == 0){
              ParameterNotSpecified("Multiline mode");
              return;
            }

            var before = GetInputConstructorValue("before",loader);
            if(replaceMode == "before" && before["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var after = GetInputConstructorValue("after",loader);
            if(replaceMode == "after" && after["original"].length == 0){
              ParameterNotSpecified("Value");
              return;
            }

            var leftValue = GetInputConstructorValue("leftValue",loader);
            if(replaceMode == "between" && leftValue["original"].length == 0){
              ParameterNotSpecified("Left value");
              return;
            }
            var rightValue = GetInputConstructorValue("rightValue",loader);
            if(replaceMode == "between" && rightValue["original"].length == 0){
              ParameterNotSpecified("Right value");
              return;
            }

            var searchValue = ''
            if(replaceMode == "exact"){
              searchValue = exact["updated"]
            }if(replaceMode == "regexp"){
              searchValue = regexp["updated"]
            }else if(replaceMode == "before"){
              searchValue = before["updated"]
            }else if(replaceMode == "after"){
              searchValue = after["updated"]
            }else if(replaceMode == "between"){
              searchValue = leftValue["updated"]
            }

            var newValue = GetInputConstructorValue("newValue",loader);

            var limit = GetInputConstructorValue("limit",loader);

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Replacement ID"));
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,urlFilters:urlFilters,contentFilters:contentFilters,replaceMode:replaceMode,searchValue:searchValue,replaceAllExact:replaceAllExact,ignoreСase:ignoreСase["updated"],globalSearch:globalSearch["updated"],multiline:multiline["updated"],searchValue2:rightValue["updated"],newValue:newValue["updated"],limit:limit["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "disablerules")
          {
            var Ids = GetInputConstructorValue("ids",loader)
            if(Ids["original"].length <= 0)
            {
              ParameterNotSpecified(tr("Replacement ID"));
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({ids:Ids["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "getrulestats")
          {
            var Id = GetInputConstructorValue("id",loader)

            var SaveExecutionCount = this.$el.find("#SaveExecutionCount").val().toUpperCase();
            if(SaveExecutionCount.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Number of executions"));
              return;
            }

            var SaveIsActive = this.$el.find("#SaveIsActive").val().toUpperCase();
            if(SaveIsActive.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("Is active"));
              return;
            }

            var SaveAllIds = this.$el.find("#SaveAllIds").val().toUpperCase();
            if(SaveAllIds.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("List of all replacement IDs"));
              return;
            }

            var SaveActiveIds = this.$el.find("#SaveActiveIds").val().toUpperCase();
            if(SaveActiveIds.length == 0)
            {
              ParameterNotSpecified(tr("Variable") + " -> " + tr("List of active replacement IDs"));
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variableExecutionCount:"VAR_" + SaveExecutionCount,variableIsActive:"VAR_" + SaveIsActive,variableAllIds:"VAR_" + SaveAllIds,variableActiveIds:"VAR_" + SaveActiveIds,id:Id["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "html")
          {
            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "getcookiesforurl")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Url is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "restorecookies")
          {
            var Value = GetInputConstructorValue("Value",loader)
            var Append = $("#Append").is(':checked')

            if(Value["updated"].length <= 0)
            {
              Value["updated"] = "\"\""
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"],append:Append})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "savecookies")
          {
            var Domain = GetInputConstructorValue("Domain",loader)

            var Save = this.$el.find("#Save").val().toUpperCase();
            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,domain:Domain["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "openfile")
          {
            var Value = GetInputConstructorValue("Value",loader)

            if(Value["original"].length <= 0)
            {
              Invalid("File is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "dragfile")
          {
            var Value = GetInputConstructorValue("Value",loader)

            if(Value["original"].length <= 0)
            {
              Invalid("File is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "promptresult")
          {
            var Value = GetInputConstructorValue("Value",loader)

            if(Value["original"].length <= 0)
            {
              Invalid("Value is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "httpauth")
          {
            var Login = GetInputConstructorValue("Login",loader)
            var Password = GetInputConstructorValue("Password",loader)
            

            if(Login["original"].length <= 0)
            {
              Invalid("Login is empty");
              return;
            }

            if(Password["original"].length <= 0)
            {
              Invalid("Password is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({login:Login["updated"],password:Password["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "javascript")
          {
            loader.SetIsJsonStringify(true);
            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Javascript is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "browserjavascript")
          {
            var source = window.Code.Editor.getValue();

            if(source.length === 0) {
              Invalid("Code is empty");
              return;
            }

            if(source.indexOf("GLOBAL:") >= 0) {
              Invalid("Global variables are not allowed");
              return;
            }

            var prepared = ExtractVariables(source);

            try {
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({
                variables: JSON.stringify(prepared),
                source: source,
              });
              code = Normalize(code,0);
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            } catch(e) { }
          }else if(State == "onloadjavascript")
          {
            var Value = GetInputConstructorValue("Value", loader);

             try{
              var TargetCode = BrowserAutomationStudio_GetTargetCode(loader)
              var code = loader.GetAdditionalData() + TargetCode + _.template($('#' + State + "_code").html())({value: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "reset")
          {
             try{

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}

          }else if(State == "clickCaptchaBrowser")
          {
            const clickCoordinatesList = this.$el.find('#clickCoordinatesList').val().toUpperCase();
            const textInstructions = GetInputConstructorValue('textInstructions', loader);
            const taskWaitTimeout = GetInputConstructorValue('taskWaitTimeout', loader);
            const taskWaitDelay = GetInputConstructorValue('taskWaitDelay', loader);
            const serviceName = GetInputConstructorValue('serviceName', loader);
            const serviceKey = GetInputConstructorValue('serviceKey', loader);
            const serviceUrl = GetInputConstructorValue('serviceUrl', loader);
            const imageData = GetInputConstructorValue('imageData', loader);

            if (!clickCoordinatesList.length) {
              return Invalid(tr('The "Click coordinates" variable must not be empty'));
            } else if (!taskWaitTimeout.original.length) {
              return Invalid(tr('The "Task solution check interval" parameter is empty'));
            } else if (!taskWaitDelay.original.length) {
              return Invalid(tr('The "Task solution check delay" parameter is empty'));
            } else if (!serviceName.original.length) {
              return Invalid(tr('The "Service name" parameter is empty'));
            } else if (!serviceKey.original.length) {
              return Invalid(tr('The "Service key" parameter is empty'));
            } else if (!imageData.original.length) {
              return Invalid(tr('The "Captcha picture data encoded in base64" parameter is empty'));
            }

            try {
              const code = Normalize(loader.GetAdditionalData() + _.template($('#clickCaptchaBrowser_code').html())({
                clickCoordinatesList: `VAR_${clickCoordinatesList}`,
                textInstructions: textInstructions.updated,
                taskWaitTimeout: taskWaitTimeout.updated,
                taskWaitDelay: taskWaitDelay.updated,
                serviceName: serviceName.updated,
                serviceKey: serviceKey.updated,
                serviceUrl: serviceUrl.updated,
                imageData: imageData.updated,
              }), 0);
              BrowserAutomationStudio_Append('', BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            } catch (e) { console.log('Error while adding action:', e) }
          }else if(State == "solvecaptcha")
          {
            
            var Method = GetInputConstructorValue("Method", loader);
            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            var Antigate = GetInputConstructorValue("Antigate", loader);
            var Server = GetInputConstructorValue("Server", loader);

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Captcha is empty");
              return;
            }
            if(Method["original"].length == 0)
            {
              Invalid("Method is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,value: Value["updated"],method: Method["updated"], antigate: Antigate["updated"], serverurl: Server["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "randomint")
          {
            
            var MinValue = GetInputConstructorValue("MinValue", loader);
            var MaxValue = GetInputConstructorValue("MaxValue", loader);
            var Save = this.$el.find("#Save").val().toUpperCase();
            
            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(MinValue["original"].length == 0)
            {
              Invalid("MinValue is empty");
              return;
            }
            if(MaxValue["original"].length == 0)
            {
              Invalid("MaxValue is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,min: MinValue["updated"],max: MaxValue["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "setheader")
          {
            var Name = GetInputConstructorValue("Name",loader)
            var Value = GetInputConstructorValue("Value",loader)

            if(Name["original"].length <= 0)
            {
              Invalid("Name is empty");
              return;
            }

            
             try{
              var TargetCode = BrowserAutomationStudio_GetTargetCode(loader)
              var code = loader.GetAdditionalData() + TargetCode + _.template($('#' + State + "_code").html())({name:Name["updated"],value:Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("" , BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
            
          }else if(State == "custom")
          {
            var val = GetInputConstructorValue("Code",loader)

            if(val["original"].length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({code:val["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Code is empty");
              return;
            }
          }else if(State == "break")
          {

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "continue")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "success")
          {
            var val = GetInputConstructorValue("SuccessMessage",loader)

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({message:val["updated"]})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "fail")
          {
            var val = GetInputConstructorValue("FailMessage",loader)
            var Check = $("#Check").is(':checked')


             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({message:val["updated"],dontrestart: Check})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "die")
          {
            var val = GetInputConstructorValue("FailMessage",loader)
            var Check = $("#Check").is(':checked')


             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({message:val["updated"],instant: Check})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "label")
          {
            var val = GetInputConstructorValue("Label",loader)
            if(!val["original"].match(/^[a-zA-Z0-9а-яА-Я_ ]+$/))
            {
                Invalid(tr("Label can contain only letters, digits, underscore and spaces"));
                return;
            }
            if(val["original"].length <= 0)
            {
                Invalid("Label is empty");
                return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({label:val["updated"]})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "goto")
          {
            var val = $("#LabelName").val()
            if(val.length <= 0)
            {
                Invalid("Label is empty");
                return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({label:JSON.stringify(val)})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

            }catch(e)
            {}

          }else if(State == "sleep")
          {
            if($("#sleeprandom").is(':checked'))
            {
              var from = GetInputConstructorValue("sleepfrom",loader)
              var to = GetInputConstructorValue("sleepto",loader)
              if(from["original"].length <= 0)
              {
                Invalid("Sleep from time is empty");
                return;
              }

              if(to["original"].length <= 0)
              {
                Invalid("Sleep to time is empty");
                return;
              }


              try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_fromto_code").html())({from:from["updated"], to:to["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e){}
            }else
            {
              var t = GetInputConstructorValue("sleepfromto",loader)

              if(t["original"].length <= 0)
              {
                Invalid("Sleep time is empty");
                return;
              }

              try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({t:t["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e){}
            }

          }else if(State == "proxy")
          {
              var ProxyText = GetInputConstructorValue("ProxyText",loader)
              var ProxyType = GetInputConstructorValue("ProxyType", loader)
              var ProxyLogin = GetInputConstructorValue("ProxyLogin",loader)
              
              var ChangeTimezone = GetInputConstructorValue("ChangeTimezone",loader)
              var ChangeGeolocation = GetInputConstructorValue("ChangeGeolocation",loader)
              var ChangeWebrtcIp = GetInputConstructorValue("ChangeWebrtcIp",loader)
              var DetectExternalIp = GetInputConstructorValue("DetectExternalIp",loader)
              var ChangeBrowserLanguage = GetInputConstructorValue("ChangeBrowserLanguage",loader)

              var IpInfoMethod = GetInputConstructorValue("IpInfoMethod", loader);
              var IpApiKey = GetInputConstructorValue("IpApiKey", loader);
              var FunctionName = this.$el.find("#FunctionName").val();

              var ServiceURL = GetInputConstructorValue("ServiceURL", loader);
              var IpExtractionParam = GetInputConstructorValue("IpExtractionParam", loader);
              var IpExtractionMethod = GetInputConstructorValue("IpExtractionMethod", loader);

              var PublicIPv4 = GetInputConstructorValue("PublicIPv4", loader);
              var PublicIPv6 = GetInputConstructorValue("PublicIPv6", loader);
              var PrivateIPv4 = GetInputConstructorValue("PrivateIPv4", loader);
              var PrivateIPv6 = GetInputConstructorValue("PrivateIPv6", loader);
              var DetectExternalIpV6 = GetInputConstructorValue("DetectExternalIpV6", loader);
              var ServiceURLV6 = GetInputConstructorValue("ServiceURLV6", loader);
              var IpExtractionMethodV6 = GetInputConstructorValue("IpExtractionMethodV6", loader);
              var IpExtractionParamV6 = GetInputConstructorValue("IpExtractionParamV6", loader);

              var DNSMode = GetInputConstructorValue("DNSMode", loader);
              var CustomDNSIP = GetInputConstructorValue("CustomDNSIP", loader);

              var CallsFunctionCode = ""

              if(FunctionName.length == 0)
              {
                FunctionName = "null"
              }else
              {
                CallsFunctionCode = "\/*CallsFunction:" + FunctionName + "*\/\n"
              }


              if(ProxyLogin["updated"] == "")
                ProxyLogin["updated"] = '""'
              var ProxyPassword = GetInputConstructorValue("ProxyPassword",loader)
              if(ProxyPassword["updated"] == "")
                ProxyPassword["updated"] = '""'
              var IsEmptyProxy = false
              if(ProxyText["updated"] == "")
              {
                ProxyText["updated"] = '""'
                IsEmptyProxy = true
              }
              /*if(ProxyText["original"].length <= 0)
              {
                Invalid("Proxy is empty");
                return;
              }*/

              try{
                var TargetCode = BrowserAutomationStudio_GetTargetCode(loader)
                var code = loader.GetAdditionalData() + TargetCode + _.template($('#' + State + "_code").html())(
                  {
                    ProxyText:ProxyText["updated"], 
                    ProxyType:ProxyType["updated"],
                    ProxyLogin:ProxyLogin["updated"],
                    ProxyPassword:ProxyPassword["updated"], 
                    ChangeTimezone:ChangeTimezone["updated"], 
                    ChangeGeolocation:ChangeGeolocation["updated"], 
                    ChangeWebrtcIp:ChangeWebrtcIp["updated"], 
                    DetectExternalIp:DetectExternalIp["updated"], 
                    ChangeBrowserLanguage: ChangeBrowserLanguage["updated"],
                    ServiceURL: ServiceURL["updated"],
                    IpExtractionParam: IpExtractionParam["updated"],
                    IpExtractionMethod: IpExtractionMethod["updated"],
                    ip_info_method: IpInfoMethod["updated"],
                    ip_api_key: IpApiKey["updated"],

                    PublicIPv4: PublicIPv4["updated"],
                    PublicIPv6: PublicIPv6["updated"],
                    PrivateIPv4: PrivateIPv4["updated"],
                    PrivateIPv6: PrivateIPv6["updated"],
                    DetectExternalIpV6: DetectExternalIpV6["updated"],
                    ServiceURLV6: ServiceURLV6["updated"],
                    IpExtractionMethodV6: IpExtractionMethodV6["updated"],
                    IpExtractionParamV6: IpExtractionParamV6["updated"],

                    DNSMode: DNSMode["updated"],
                    CustomDNSIP: CustomDNSIP["updated"],

                    function_name: FunctionName,
                  })
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + CallsFunctionCode + code, action, DisableIfAdd);
              }catch(e){}


          }else if(State == "waitload")
          {
            var urlFilters = _Filters.getFiltersValue("urlFilters");

            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({urlFilters:urlFilters})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "waiturl" || State == "waitcontent" || State == "waitcss")
          {
            var val = GetInputConstructorValue("Wait",loader)

            if(val["original"].length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({waiter:val["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Waiter is empty");
              return;
            }
          }else if(State == "waitfullload")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "if")
          {
            var val = GetInputConstructorValue("IfExpression",loader)
            var ElseEnabled = $("#IfElse").is(":checked")

            if(val["original"].length > 0)
            {
               var UpdatedVal = val["updated"];

               if ((/^VAR_\w+$/).test(UpdatedVal.trim())) {
                 UpdatedVal = `typeof(${UpdatedVal}) !== "undefined" ? (${UpdatedVal}) : undefined`;
               }

               try{
                if(!ElseEnabled)
                {
                  var code = loader.GetAdditionalData() + `\n_set_if_expression(${JSON.stringify(utf8_to_b64(val.original))});\n`;
                  code += _.template($('#' + State + "_code").html())({expression:UpdatedVal, do_delete: ""})
                  code = Normalize(code,0)
                  BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);
                }else
                {
                  var v = "_cycle_params().if_else"
                  var slave_id = Math.floor(Math.random() * (1000000000 - 100)) + 100
                  var master_id = Math.floor(Math.random() * (1000000000 - 100)) + 100

                  if(_GobalModel.get("isedit"))
                  {
                    if(CurrentDat && CurrentDat["slave"])
                      slave_id = parseInt(CurrentDat["slave"])

                    if(CurrentDat && CurrentDat["master"])
                      master_id = parseInt(CurrentDat["master"])

                    if(CurrentDat && CurrentDat["if_var"])
                      v = CurrentDat["if_var"]
                  }


                  var code = loader.GetAdditionalData() + "\n" +  v + " = " + UpdatedVal + ";\n"
                  code += `_set_if_expression(${JSON.stringify(utf8_to_b64(val.original))});\n`

                  code += _.template($('#' + State + "_code").html())({expression:v, do_delete: ""})
                  code = Normalize(code,0)
                  BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls({role: "master", slave: slave_id, master: master_id, if_var: v}) + code, 1, false, master_id.toString());

                  if(!_GobalModel.get("isedit"))
                  {
                    code = _.template($('#' + State + "_code").html())({expression:"!" + v, do_delete: v})
                    code = Normalize(code,0)
                    BrowserAutomationStudio_Append("Else", BrowserAutomationStudio_SaveControls({role: "slave", slave: slave_id, master: master_id, if_var: v}) + code, 1, false, slave_id.toString());
                  }
                }
              }catch(e)
              {}
            }else
            {
              Invalid("Expression is empty");
              return;
            }
          }else if(State == "while")
          {
            var val = GetInputConstructorValue("WhileExpression",loader)
            if(val["original"].length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({expression:val["updated"],additional:loader.GetAdditionalData()})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);
                if(!_GobalModel.get("isedit"))
                {
                  var LogText = tr("Current loop repetition") + " : [[CYCLE_INDEX]]"
                  var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                  var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current loop repetition") + " : \" + VAR_CYCLE_INDEX"})
                  ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                  BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);
                }

              }catch(e)
              {}
            }else
            {
              Invalid("Expression is empty");
              return;
            }
          }else if(State == "for")
          {
            var from = GetInputConstructorValue("ForFrom",loader)
            var to = GetInputConstructorValue("ForTo",loader)
            if(from["original"].length == 0)
            {
              Invalid("From is empty");
              return;
            }
            if(to["original"].length == 0)
            {
              Invalid("To is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({expression_from:from["updated"],expression_to:to["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);
              if(!_GobalModel.get("isedit"))
              {
                var LogText = tr("Current loop repetition") + " : [[CYCLE_INDEX]]"
                var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current loop repetition") + " : \" + VAR_CYCLE_INDEX"})
                ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);
              }

            }catch(e)
            {}
          }else if(State == "ignoreerrors")
          {
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

              if(!_GobalModel.get("isedit"))
              {
                BrowserAutomationStudio_Append("\u007b\u0022c\u0022:\u00225\u0022\u007d", `/*Dat:eyJzIjoiaWYiLCJ2IjoxLCJmIjpbXSwidXciOiIwIiwidXQiOiIwIiwidXRvIjoiMCIsInVtIjoiMCIsImQiOlt7ImlkIjoiSWZFeHByZXNzaW9uIiwidHlwZSI6ImNvbnN0ciIsImRhdGEiOiJbW1dBU19FUlJPUl1dIiwiY2xhc3MiOiJleHByZXNzaW9uIn0seyJpZCI6IklmRWxzZSIsInR5cGUiOiJjaGVjayIsImRhdGEiOmZhbHNlfV19*/
                _if(VAR_WAS_ERROR,function(){
                section_insert()
                })!`, 1, false);

                var LogText = tr("Error occurred") + " : [[LAST_ERROR]]"
                var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Error occurred") + " : \" + VAR_LAST_ERROR"})
                ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                BrowserAutomationStudio_Append("\u007b\u0022c\u0022:\u00225\u0022\u007d", ControlsAdditional + CodeAdditional, 1);
              }


            }catch(e)
            {}
          }else if(State == "foreach")
          {
            var ForArray = GetInputConstructorValue("ForArray",loader)
            if(ForArray["original"].length == 0)
            {
              Invalid("Array is empty");
              return;
            }
             try{

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({for_array:ForArray["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);

              if(!_GobalModel.get("isedit"))
              {
                var LogText = tr("Current data") + " : [[FOREACH_DATA]]"
                var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current data") + " : \" + VAR_FOREACH_DATA"})
                ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);

                var LogText = tr("Current loop repetition") + " : [[CYCLE_INDEX]]"
                var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current loop repetition") + " : \" + VAR_CYCLE_INDEX"})
                ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);
              }

            }catch(e)
            {}
          }else if(State == "resize")
          {
            var width = GetInputConstructorValue("ResizeX",loader)
            var height = GetInputConstructorValue("ResizeY",loader)

            if(width["original"].length == 0)
            {
              Invalid("Width is empty");
              return;
            }


            if(height["original"].length == 0)
            {
              Invalid("Height is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({width:width["updated"],height:height["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "type")
          {
            var TypeData = GetInputConstructorValue("TypeData",loader);
            var TypeInterval = GetInputConstructorValue("TypeInterval",loader);

            if(TypeInterval["original"].length == 0)
            {
              Invalid("interval is empty");
              return;
            }
            if(TypeData["original"].length == 0)
            {
              Invalid("Type data is empty");
              return;
            }

            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({text:TypeData["updated"],interval:TypeInterval["updated"]}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "typeelement")
          {
            var TypeData = GetInputConstructorValue("TypeData",loader);
            var TypeInterval = GetInputConstructorValue("TypeInterval",loader);
            var Check = $("#Check").is(':checked')

            if(TypeInterval["original"].length == 0)
            {
              Invalid("interval is empty");
              return;
            }
            if(TypeData["original"].length == 0)
            {
              Invalid("Type data is empty");
              return;
            }

            try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var AdditionalEmulation = GetInputConstructorValue("additionalEmulation",loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({text:TypeData["updated"],move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings, additional_emulation: AdditionalEmulation["updated"],interval:TypeInterval["updated"],path: path["path"],waiter: path["waiter"], disableemulation: Check}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "set")
          {
            var Value = GetInputConstructorValue("Value",loader);


            if(Value["original"].length == 0)
            {
              Invalid("Set value is empty");
              return;
            }

            try{
              var path = GetPath(loader,false,true)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({set:Value["updated"],path: path["path"],waiter: path["waiter"], emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "set_integer")
          {
            var Value = GetInputConstructorValue("Value",loader);


            if(Value["original"].length == 0)
            {
              Invalid("Set value is empty");
              return;
            }

            try{
              var path = GetPath(loader,false,true)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({set:Value["updated"],path: path["path"],waiter: path["waiter"], emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "set_random")
          {

            try{
              var path = GetPath(loader,false,true)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"],waiter: path["waiter"], emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }
          _MACRO_INSERT_SELECT_
          else if(State == "log")
          {
            var val = GetInputConstructorValue("LogText", loader)

            if(val["original"].length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({text:val["updated"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Log data is empty");
              return;
            }
          }else if(State == "clearlog")
          {

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "timeout")
          {
            var val = GetInputConstructorValue("Value", loader)
            var type = this.$el.find("#Type").val();

            if(val["original"].length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({timeout:val["updated"], type: type})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Value empty");
              return;
            }
          }else if(State == "url")
          {
            var Variable = this.$el.find("#SaveUrl").val().toUpperCase();

            if(Variable.length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Variable is empty");
              return;
            }
          }else if(State == "screen")
          {
            var CursorX = this.$el.find("#CursorX").val().toUpperCase();
            var CursorY = this.$el.find("#CursorY").val().toUpperCase();
            var CursorAbsoluteX = this.$el.find("#CursorAbsoluteX").val().toUpperCase();
            var CursorAbsoluteY = this.$el.find("#CursorAbsoluteY").val().toUpperCase();
            var ScrollX = this.$el.find("#ScrollX").val().toUpperCase();
            var ScrollY = this.$el.find("#ScrollY").val().toUpperCase();
            var Width = this.$el.find("#Width").val().toUpperCase();
            var Height = this.$el.find("#Height").val().toUpperCase();

            if(CursorX.length <= 0)
            {
              Invalid("CursorX is empty");
              return;
            }

            if(CursorY.length <= 0)
            {
              Invalid("CursorY is empty");
              return;
            }

            if(CursorAbsoluteX.length <= 0)
            {
              Invalid("CursorAbsoluteX is empty");
              return;
            }

            if(CursorAbsoluteY.length <= 0)
            {
              Invalid("CursorAbsoluteY is empty");
              return;
            }

            if(ScrollX.length <= 0)
            {
              Invalid("ScrollX is empty");
              return;
            }

            if(ScrollY.length <= 0)
            {
              Invalid("ScrollY is empty");
              return;
            }

            if(Width.length <= 0)
            {
              Invalid("Width is empty");
              return;
            }

            if(Height.length <= 0)
            {
              Invalid("Height is empty");
              return;
            }

            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())(
                {
                  cursor_x:"VAR_" + CursorX,
                  cursor_y:"VAR_" + CursorY,
                  cursor_absolute_x:"VAR_" + CursorAbsoluteX,
                  cursor_absolute_y:"VAR_" + CursorAbsoluteY,
                  scroll_x:"VAR_" + ScrollX,
                  scroll_y:"VAR_" + ScrollY,
                  width:"VAR_" + Width,
                  height:"VAR_" + Height
                })
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
          }else if(State == "touch")
          {
            var Enable = GetInputConstructorValue("Enable",loader);


            if(Enable["original"].length == 0)
            {
              Invalid("Enable field is empty");
              return;
            }

            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())(
                {
                  enable:Enable["updated"]
                })
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
          }else if(State == "executefunction")
          {
            var FunctionName = $("#FunctionName").val();

            var Arguments = {}

            _.each(this.$el.find("#FunctionParameters").find("[data-preserve-type=constr]"), function(Element) {
              var IdHex = $(Element).attr("data-preserve-id")
              var Id = fromhex(IdHex.replace("ParamId_",""))
              Arguments[Id] = GetInputConstructorValue(IdHex, loader)["updated"]
            })

            var HasReturnValue = this.$el.find("#Save").length > 0 
            var ReturnVariableName = ""
            if(HasReturnValue)
              ReturnVariableName = this.$el.find("#Save").val().toUpperCase();

            if(FunctionName.length > 0)
            {
               try{
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({name:FunctionName, args: Arguments,variable:"VAR_" + ReturnVariableName, has_return: HasReturnValue})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);
              }catch(e)
              {}
            }else
            {
              Invalid("Function is empty");
              return;
            }
          }else if(State == "executefunctioninseveralthreads")
          {
            var FunctionName = $("#FunctionName").val();
            var ThreadNumber = GetInputConstructorValue("ThreadNumber", loader)
            var SuccessNumber = GetInputConstructorValue("SuccessNumber", loader)
            var FailNumber = GetInputConstructorValue("FailNumber", loader)


            if(FunctionName.length <= 0)
            {
              Invalid("Function is empty");
              return;
            }

             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({name:FunctionName, thread: ThreadNumber["updated"], success: SuccessNumber["updated"], fail: FailNumber["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 1, false);
            }catch(e)
            {}
          
          }else if(State == "recaptchav3")
          {
            var Method = GetInputConstructorValue("Method", loader);
            var Rucaptcha = GetInputConstructorValue("Rucaptcha", loader);
            var Server = GetInputConstructorValue("Server", loader);
            var Action = GetInputConstructorValue("Action", loader);
            var Score = GetInputConstructorValue("Score", loader);
            var SendProxy = GetInputConstructorValue("SendProxy", loader);

            if(Method["original"].length == 0)
            {
              Invalid("Method is empty");
              return;
            }
            
            if(Action["original"].length == 0)
            {
              Invalid("Action is empty");
              return;
            }

            if(Action["original"].length == 0)
            {
              Invalid("SendProxy is empty");
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() + _.template($("#recaptchav3_code").html())({proxy: SendProxy["updated"], score: Score["updated"], action: Action["updated"], method: Method["updated"], rucaptcha: Rucaptcha["updated"], serverurl: Server["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          
          }else if(State == "setvariable")
          {
            var VariableName = this.$el.find("#SetVariableName").val().toUpperCase();
            var VariableValue = GetInputConstructorValue("SetVariableValue", loader)


            if(VariableName.length == 0)
            {
              Invalid("Variable name is empty");
              return;
            }

            if(!VariableValue["isString"] && VariableValue["original"].length == 0)
            {
              Invalid("Variable value is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable_name:"VAR_" + VariableName,variable_value:VariableValue["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "incvariable")
          {
            var VariableName = this.$el.find("#SetVariableName").val().toUpperCase();
            var VariableValue = GetInputConstructorValue("IncVariableValue", loader)


            if(VariableName.length == 0)
            {
              Invalid("Variable name is empty");
              return;
            }

            if(VariableValue["original"].length == 0)
            {
              Invalid("Variable value is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable_name:"VAR_" + VariableName,variable_value:VariableValue["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "getfunctionparameter")
          {
            var Save = this.$el.find("#Save").val().toUpperCase();
            var ParameterName = GetInputConstructorValue("ParameterName", loader)


            if(Save.length == 0)
            {
              Invalid("Result variable is empty");
              return;
            }

            if(ParameterName["original"].length == 0)
            {
              Invalid("Parameter name is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,param_name:ParameterName["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "return")
          {
            var ReturnValue = GetInputConstructorValue("ReturnValue", loader)
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({val:ReturnValue["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "incglobalvariable")
          {
            var VariableName = this.$el.find("#SetVariableName").val().toUpperCase();
            var VariableValue = GetInputConstructorValue("IncVariableValue", loader)


            if(VariableName.length == 0)
            {
              Invalid("Variable name is empty");
              return;
            }

            if(VariableValue["original"].length == 0)
            {
              Invalid("Variable value is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable_name:JSON.stringify(VariableName),variable_value:VariableValue["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "xml")
          {
            var Variable = this.$el.find("#SaveXml").val().toUpperCase();

            if(Variable.length > 0)
            {
               try{
                var path = GetPath(loader)
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Variable is empty");
              return;
            }
          }else if(State == "linkurl")
          {
            var Variable = this.$el.find("#LinkURL").val().toUpperCase();

            if(Variable.length > 0)
            {
               try{
                var path = GetPath(loader)
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Variable is empty");
              return;
            }
          }else if(State == "coordinates")
          {
            var X = this.$el.find("#X").val().toUpperCase();
            var Y = this.$el.find("#Y").val().toUpperCase();
            var AbsoluteX = this.$el.find("#AbsoluteX").val().toUpperCase();
            var AbsoluteY = this.$el.find("#AbsoluteY").val().toUpperCase();
            var Width = this.$el.find("#Width").val().toUpperCase();
            var Height = this.$el.find("#Height").val().toUpperCase();


            if(X.length == 0)
            {
              Invalid("X is empty");
              return;
            }

            if(Y.length == 0)
            {
              Invalid("Y is empty");
              return;
            }

            if(Width.length == 0)
            {
              Invalid("Width is empty");
              return;
            }

            if(Height.length == 0)
            {
              Invalid("Height is empty");
              return;
            }

            try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({
                x:"VAR_" + X,
                y:"VAR_" + Y,
                absolute_x:"VAR_" + AbsoluteX,
                absolute_y:"VAR_" + AbsoluteY,
                width:"VAR_" + Width,
                height:"VAR_" + Height,
                path: path["path"],
                waiter: path["waiter"],
              })
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
            
          }else if(State == "exist")
          {
            var Variable = this.$el.find("#Save").val().toUpperCase();
            var CheckIsvisible = $("#Check").is(':checked')

            if(Variable.length > 0)
            {
               try{
                var path = GetPath(loader)
                var imagesearch = false 
                if(typeof(path["imagesearch"]) != "undefined")
                {
                  imagesearch = path["imagesearch"]
                }
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"], imagesearch: imagesearch, isvisible: CheckIsvisible, query: path["query"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Variable is empty");
              return;
            }
          }else if(State == "clickelement")
          {
             var Check = $("#Check").is(':checked')

             try{
              var path = GetPath(loader,false,true)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"],waiter: path["waiter"], disableemulation: Check}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "check")
          {
             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "focus")
          {
             try{
              var path = GetPath(loader)
              var NativeEmulation = $("#Check").is(':checked')
              var ScrollParams = BrowserAutomationStudio_GetScrollParams(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"], emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,waiter: path["waiter"],native_emulation:NativeEmulation,scroll_params:ScrollParams})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "moveelement")
          {
             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }
          else if(State == "dragelement")
          {
             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }
          else if(State == "dropelement")
          {
             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({move_settings: MoveSettings,path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "moveandclickelement")
          {
            var Check = $("#Check").is(':checked')
            var Check2 = $("#Check2").is(':checked')
            var ClickType = $("#Select").val()

             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var AdditionalEmulation = GetInputConstructorValue("additionalEmulation",loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"],waiter: path["waiter"], holdctrl: Check2, click_type: "\"" + ClickType + "\"", wait: BrowserAutomationStudio_UsesWaitCode(), disableemulation: Check, move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings, additional_emulation: AdditionalEmulation["updated"]}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)

              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "clear")
          {
             try{
              var path = GetPath(loader,false,true)
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader)
              var AdditionalEmulation = GetInputConstructorValue("additionalEmulation",loader)

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings, additional_emulation: AdditionalEmulation["updated"],path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "script")
          {
            var Variable = this.$el.find("#SaveScript").val().toUpperCase();
            var Script = GetInputConstructorValue("ScriptValue", loader);
            if(Variable.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Script["original"].length == 0)
            {
              Invalid("Script is empty");
              return;
            }

             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"],script: Script["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "browserscript")
          {
            var source = window.Code.Editor.getValue();

            if(source.length === 0) {
              Invalid("Code is empty");
              return;
            }

            if(source.indexOf("GLOBAL:") >= 0) {
              Invalid("Global variables are not allowed");
              return;
            }

            var prepared = ExtractVariables(source);

            try {
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({
                variables: JSON.stringify(prepared),
                source: source,
                path: path["path"],
                waiter: path["waiter"]
              });
              code = Normalize(code,0);
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            } catch(e) { }
          }else if(State == "captcha")
          {
            var Variable = this.$el.find("#Save").val().toUpperCase();
            var Method = GetInputConstructorValue("Method", loader);
            var Antigate = GetInputConstructorValue("Antigate", loader);
            var Server = GetInputConstructorValue("Server", loader);
            if(Variable.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Method["original"].length == 0)
            {
              Invalid("Method is empty");
              return;
            }

             try{

              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"],method: Method["updated"], antigate: Antigate["updated"], serverurl: Server["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "screenshot")
          {
            var Variable = this.$el.find("#Save").val().toUpperCase();
            if(Variable.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            
             try{

              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "attr")
          {

            var Save = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Attr is empty");
              return;
            }
             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,path: path["path"],waiter: path["waiter"],attr: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "length")
          {
            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var path = GetPath(loader,true)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save,path: path["path"],waiter: path["waiter"], query: path["query"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "waitfiledownload")
          {
            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Save})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "loopelement")
          {
             try{
              var path = GetPath(loader, true)

              if(path.query.length == 0)
              {
                Invalid("Query is empty");
                return;
              }

              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"],waiter: path["waiter"], query: path["query"], querycss: path["querycss"], querymatch: path["querymatch"], queryxpath: path["queryxpath"]})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, 2, false);


              if(!_GobalModel.get("isedit"))
              {
                
                var LogText = tr("Current loop repetition") + " : [[CYCLE_INDEX]]"
                var ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                var CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current loop repetition") + " : \" + VAR_CYCLE_INDEX"})
                ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);

                var Used = false;
                if($("#selector").html() == "css")
                {
                  ControlsAdditional = {"s":"xml","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"SaveXml","type":"var","data":"CURRENT_ELEMENT_XML"}],"p":{"is_image":false,"css":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","version":"1.0","css1":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","css2":"","css3":"","current":"css","match":"[[FOR_EACH_MATCH]]>AT>[[CYCLE_INDEX]]","xpath":"[[FOR_EACH_XPATH]]>AT>[[CYCLE_INDEX]]","at":"0, 0","we":true,"fa":true}}

                  CodeAdditional = `/*Browser*/
                    _SELECTOR = VAR_FOR_EACH_CSS + "\\u003eAT\\u003e" + VAR_CYCLE_INDEX;
                    wait_element(_SELECTOR)!
                    get_element_selector(_SELECTOR, false).xml()!
                    VAR_CURRENT_ELEMENT_XML = _result()`
                  Used = true
                }else if($("#selector").html() == "xpath")
                {
                  ControlsAdditional = {"s":"xml","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"SaveXml","type":"var","data":"CURRENT_ELEMENT_XML"}],"p":{"is_image":false,"css":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","version":"1.0","css1":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","css2":"","css3":"","current":"xpath","match":"[[FOR_EACH_MATCH]]>AT>[[CYCLE_INDEX]]","xpath":"[[FOR_EACH_XPATH]]>AT>[[CYCLE_INDEX]]","at":"0, 0","we":true,"fa":true}}

                  CodeAdditional = `/*Browser*/
                    _SELECTOR = VAR_FOR_EACH_XPATH + "\\u003eAT\\u003e" + VAR_CYCLE_INDEX;
                    wait_element(_SELECTOR)!
                    get_element_selector(_SELECTOR, false).xml()!
                    VAR_CURRENT_ELEMENT_XML = _result()`
                  Used = true
                }else if($("#selector").html() == "match")
                {
                  ControlsAdditional = {"s":"xml","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"SaveXml","type":"var","data":"CURRENT_ELEMENT_XML"}],"p":{"is_image":false,"css":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","version":"1.0","css1":"[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]","css2":"","css3":"","current":"match","match":"[[FOR_EACH_MATCH]]>AT>[[CYCLE_INDEX]]","xpath":"[[FOR_EACH_XPATH]]>AT>[[CYCLE_INDEX]]","at":"0, 0","we":true,"fa":true}}

                  CodeAdditional = `/*Browser*/
                    _SELECTOR = VAR_FOR_EACH_MATCH + "\\u003eAT\\u003e" + VAR_CYCLE_INDEX;
                    wait_element(_SELECTOR)!
                    get_element_selector(_SELECTOR, false).xml()!
                    VAR_CURRENT_ELEMENT_XML = _result()`
                  Used = true
                }
                if(Used)
                {
                  ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                  BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);

                  LogText = tr("Current element xml") + " : [[CURRENT_ELEMENT_XML]]"
                  ControlsAdditional = {"s":"log","v":1,"f":[],"uw":"0","ut":"0","uto":"0","um":"0","d":[{"id":"LogText","type":"constr","data":LogText,"class":"string"}]}
                  CodeAdditional = _.template($("#log_code").html())({text:"\"" + tr("Current element xml") + " : \" + VAR_CURRENT_ELEMENT_XML"})
                  ControlsAdditional = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsAdditional)) + "*/"
                  BrowserAutomationStudio_Append("", ControlsAdditional + CodeAdditional, 1);
                }
              }
            }catch(e)
            {}

          }else if(State == "set_attr")
          {
            var Name = GetInputConstructorValue("Name", loader);
            var Value = GetInputConstructorValue("Value", loader);

            if(Name["original"].length == 0)
            {
              Invalid("Name is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Value is empty");
              return;
            }
             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({path: path["path"],waiter: path["waiter"],value: Value["updated"],name: Name["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "clickextensionbutton")
          {
            var ExtensionId = GetInputConstructorValue("ExtensionId", loader);

            if(ExtensionId["original"].length == 0)
            {
              Invalid("ExtensionId is empty");
              return;
            }
             try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({extension_id: ExtensionId["updated"]}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "style")
          {
            var Variable = this.$el.find("#Save").val().toUpperCase();
            var Value = GetInputConstructorValue("Value", loader);
            if(Variable.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }
            if(Value["original"].length == 0)
            {
              Invalid("Style is empty");
              return;
            }

             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"],style: Value["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "text")
          {
            var Variable = this.$el.find("#SaveText").val().toUpperCase();

            if(Variable.length > 0)
            {
               try{
                var path = GetPath(loader)
                var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable,path: path["path"],waiter: path["waiter"]})
                code = Normalize(code,0)
                BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
              }catch(e)
              {}
            }else
            {
              Invalid("Variable is empty");
              return;
            }
          }else if(State == "restrictpopups")
          {
             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "allowpopups")
          {
            try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "restrictdownloads")
          {
             try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "allowdownloads")
          {
            try{
              var path = GetPath(loader)
              var code = loader.GetAdditionalData() + _.template($('#' + State + "_code").html())({})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "click")
          {
            var MoveX = GetInputConstructorValue("ClickX", loader);
            var MoveY = GetInputConstructorValue("ClickY", loader);

            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({x:MoveX["updated"],y:MoveY["updated"]}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "move")
          {
            var MoveX = GetInputConstructorValue("MoveX", loader);
            var MoveY = GetInputConstructorValue("MoveY", loader);

            try{
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader, MoveX["updated"], MoveY["updated"])
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,x:MoveX["updated"],y:MoveY["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "drag")
          {
            var MoveX = GetInputConstructorValue("X", loader);
            var MoveY = GetInputConstructorValue("Y", loader);

            try{
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader, MoveX["updated"], MoveY["updated"])
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings,x:MoveX["updated"],y:MoveY["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "drop")
          {
            var MoveX = GetInputConstructorValue("X", loader);
            var MoveY = GetInputConstructorValue("Y", loader);

            try{
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({move_settings: MoveSettings,x:MoveX["updated"],y:MoveY["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }
          else if(State == "mousesettings")
          {
            var Speed = GetInputConstructorValue("Speed", loader);
            var Gravity = GetInputConstructorValue("Gravity", loader);
            var Deviation = GetInputConstructorValue("Deviation", loader);

            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({speed:Speed["updated"],gravity:Gravity["updated"],deviation:Deviation["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "notification")
          {
            var Enable = GetInputConstructorValue("AllowNotifications", loader);

            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({enable:Enable["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }
          else if(State == "browsersettings")
          {
            
            var Widevine = GetInputConstructorValue("Widevine", loader);
            var SafeBrowsing = GetInputConstructorValue("SafeBrowsing", loader);
            var Components = GetInputConstructorValue("Components", loader);
            var Webrtc = GetInputConstructorValue("Webrtc", loader);
            var Canvas = GetInputConstructorValue("Canvas", loader);
            var CanvasNoise = GetInputConstructorValue("CanvasNoise", loader);
            var WebrtcIps = GetInputConstructorValue("WebrtcIps", loader);
            var Webgl = GetInputConstructorValue("Webgl", loader);
            var WebglNoise = GetInputConstructorValue("WebglNoise", loader);
            var Audio = GetInputConstructorValue("Audio", loader);
            var AudioNoise = GetInputConstructorValue("AudioNoise", loader);
            var QUIC = GetInputConstructorValue("QUIC", loader);
            var MaxFPS = GetInputConstructorValue("MaxFPS", loader);
            var WebglVendor = GetInputConstructorValue("WebglVendor", loader);
            var WebglRenderer = GetInputConstructorValue("WebglRenderer", loader);
            var ProxyTunneling = GetInputConstructorValue("ProxyTunneling", loader);
            var SkipFrames = GetInputConstructorValue("SkipFrames", loader);
            var Extensions = GetInputConstructorValue("Extensions", loader);
            var CommandLine = GetInputConstructorValue("CommandLine", loader);
            var Tunneling = GetInputConstructorValue("Tunneling", loader);
            var BrowserVersion = GetInputConstructorValue("BrowserVersion", loader);
            var Path = GetInputConstructorValue("Path", loader);
            var LoadFPFromFolder = GetInputConstructorValue("LoadFPFromFolder", loader);
            var LoadProxyFromFolder = GetInputConstructorValue("LoadProxyFromFolder", loader);
            var Key = GetInputConstructorValue("Key", loader);
            

            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())(
                {
                  Widevine:Widevine["updated"],
                  SafeBrowsing:SafeBrowsing["updated"],
                  Components:Components["updated"],
                  ProxyTunneling:ProxyTunneling["updated"],
                  SkipFrames:SkipFrames["updated"],
                  Extensions:Extensions["updated"],
                  CommandLine:CommandLine["updated"],
                  Tunneling:Tunneling["updated"],
                  BrowserVersion:BrowserVersion["updated"],
                  profile:Path["updated"], 
                  load_fp: LoadFPFromFolder["updated"], 
                  load_proxy: LoadProxyFromFolder["updated"],
                  Webrtc:Webrtc["updated"],
                  WebrtcIps:WebrtcIps["updated"],
                  Canvas:Canvas["updated"],
                  CanvasNoise:CanvasNoise["updated"],
                  Audio:Audio["updated"],
                  AudioNoise:AudioNoise["updated"],
                  QUIC:QUIC["updated"],
                  MaxFPS:MaxFPS["updated"],
                  Webgl:Webgl["updated"],
                  WebglNoise:WebglNoise["updated"],
                  WebglVendor:WebglVendor["updated"],
                  WebglRenderer:WebglRenderer["updated"],
                  Key:Key["updated"],
                })
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}
          }else if(State == "getbrowserversionlist")
          {
            
            var Format = GetInputConstructorValue("Format", loader);
            var Save = this.$el.find("#Save").val().toUpperCase();

            if(Format["original"].length == 0)
            {
              Invalid("Format is empty");
              return;
            }

            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }


            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + '_code').html())({format:Format["updated"], variable:"VAR_" + Save});
              code = Normalize(code,0);
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}
          }else if(State == "getcurrentbrowserversion")
          {
            var Save = this.$el.find("#Save").val().toUpperCase();
            var Save2 = this.$el.find("#Save2").val().toUpperCase();
            var Save3 = this.$el.find("#Save3").val().toUpperCase();


            if(Save.length == 0)
            {
              Invalid("Variable is empty");
              return;
            }

            if(Save2.length == 0)
            {
              Invalid("Variable2 is empty");
              return;
            }


            if(Save3.length == 0)
            {
              Invalid("Variable3 is empty");
              return;
            }



            try{
              var code = loader.GetAdditionalData() + _.template($('#' + State + '_code').html())({variable:"VAR_" + Save, variable2:"VAR_" + Save2, variable3:"VAR_" + Save3});
              code = Normalize(code,0);
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd, "", true);
            }catch(e)
            {}
            
          }
          else if(State == "scroll")
          {
            var X = GetInputConstructorValue("X", loader);
            var Y = GetInputConstructorValue("Y", loader);
            var NativeEmulation = $("#Check").is(':checked');


            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({x:X["updated"],y:Y["updated"],native_emulation:NativeEmulation}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "renderscreen")
          {
            var X = GetInputConstructorValue("X", loader);
            var Y = GetInputConstructorValue("Y", loader);
            var Width = GetInputConstructorValue("Width", loader);
            var Height = GetInputConstructorValue("Height", loader);
            var Variable = this.$el.find("#Save").val().toUpperCase();
            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({variable:"VAR_" + Variable, x:X["updated"],y:Y["updated"],width:Width["updated"],height:Height["updated"]})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "moveandclick")
          {
            var MoveX = GetInputConstructorValue("X", loader);
            var MoveY = GetInputConstructorValue("Y", loader);
            var Check2 = $("#Check2").is(':checked')
            var ClickType = $("#Select").val()

            try{
              var MoveSettings = BrowserAutomationStudio_GetMoveJson(loader)
              var EmulationTime = GetInputConstructorValue("time",loader)
              var EmulationSettings = BrowserAutomationStudio_GetEmulationData(loader, MoveX["updated"], MoveY["updated"])
              var AdditionalEmulation = GetInputConstructorValue("additionalEmulation",loader)
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({holdctrl: Check2, click_type: "\"" + ClickType + "\"", wait: BrowserAutomationStudio_UsesWaitCode(), move_settings: MoveSettings, emulation_time: EmulationTime["updated"], emulation_settings: EmulationSettings, additional_emulation: AdditionalEmulation["updated"],x:MoveX["updated"],y:MoveY["updated"]}) + BrowserAutomationStudio_GetWaitCode()
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "addtab")
          {
            var Url = GetInputConstructorValue("Url", loader);
            var IsSilent = GetInputConstructorValue("IsSilent", loader);
            var Referrer = GetInputConstructorValue("Referrer",loader)
            
            if(Url["original"].length == 0)
            {
              Invalid("Url is empty");
              return;
            }
            if(IsSilent["original"].length == 0)
            {
              Invalid("IsSilent is empty");
              return;
            }
            
            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({referrer:Referrer["updated"], url:Url["updated"], notinstant: BrowserAutomationStudio_UsesWaitCode(), is_silent: IsSilent["updated"]}) /*+ BrowserAutomationStudio_GetWaitCode()*/
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "selecttab")
          {
            var Index = GetInputConstructorValue("Index", loader);
            if(Index["original"].length == 0)
            {
              Invalid("Index is empty");
              return;
            }
            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({index:Index["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "tabinfo")
          {
            var UrlList = this.$el.find("#UrlList").val().toUpperCase();
            var TotalTabs = this.$el.find("#TotalTabs").val().toUpperCase();
            var CurrentIndex = this.$el.find("#CurrentIndex").val().toUpperCase();
            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({urls:"VAR_" + UrlList, index:"VAR_" + CurrentIndex, total: "VAR_" + TotalTabs})

              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}

          }else if(State == "closetab")
          {
            var Index = GetInputConstructorValue("Index", loader);
            if(Index["original"].length == 0)
            {
              Invalid("Index is empty");
              return;
            }
            try{
              var code = loader.GetAdditionalData() +  _.template($('#' + State + "_code").html())({index:Index["updated"]})
              code = Normalize(code,0)
              BrowserAutomationStudio_Append("", BrowserAutomationStudio_SaveControls() + code, action, DisableIfAdd);
            }catch(e)
            {}
          }else if(State == "threadnumber")
          {
            var ThreadNumber = GetInputConstructorValue("ThreadNumber", loader)["original"];
            if(ThreadNumber.toString().length == 0)
              ThreadNumber = "1"
            try{BrowserAutomationStudio_Append("_threadnumber_", ThreadNumber, action);}catch(e){}
          }else if(State == "successnumber")
          {
            var SuccessNumber = GetInputConstructorValue("SuccessNumber", loader)["original"];
            if(SuccessNumber.toString().length == 0)
              SuccessNumber = "1"
            try{BrowserAutomationStudio_Append("_successnumber_", SuccessNumber.toString(), action);}catch(e){}
          }else if(State == "failnumber")
          {
            var FailNumber = GetInputConstructorValue("FailNumber", loader)["original"];
            if(FailNumber.toString().length == 0)
              FailNumber = "1"
            try{BrowserAutomationStudio_Append("_failnumber_", FailNumber.toString(), action);}catch(e){}
          }

          PreviewModel.reset();
          _Router.navigate("", true);
      },

      initialize: function(){
        this.templates =
        {
          "main" : _.template($('#main').html()),
          "___none" : _.template($('#___none').html()),
          "load" : _.template($('#load').html()),
          "navigateback" : _.template($('#navigateback').html()),
          "type" : _.template($('#type').html()),
          "waitload" : _.template($('#waitload').html()),
          "waiturl" : _.template($('#waiturl').html()),
          "waitfullload" : _.template($('#waitfullload').html()),
          "waitcontent" : _.template($('#waitcontent').html()),
          "waitcss" : _.template($('#waitcss').html()),
          "sleep" : _.template($('#sleep').html()),
          "resize" : _.template($('#resize').html()),
          "proxy" : _.template($('#proxy').html()),
          "click" : _.template($('#click').html()),
          "move" : _.template($('#move').html()),
          "moveandclick" : _.template($('#moveandclick').html()),
          "threadnumber" : _.template($('#threadnumber').html()),
          "failnumber" : _.template($('#failnumber').html()),
          "successnumber" : _.template($('#successnumber').html()),
          "log" : _.template($('#log').html()),
          "clearlog" : _.template($('#clearlog').html()),
          "url" : _.template($('#url').html()),
          "screen" : _.template($('#screen').html()),
          "touch" : _.template($('#touch').html()),
          "xml" : _.template($('#xml').html()),
          "linkurl" : _.template($('#linkurl').html()),
          "coordinates" : _.template($('#coordinates').html()),
          "text" : _.template($('#text').html()),
          "setvariable": _.template($('#setvariable').html()),
          "if": _.template($('#if').html()),
          "while": _.template($('#while').html()),
          "for": _.template($('#for').html()),
          "foreach": _.template($('#foreach').html()),
          "executefunction": _.template($('#executefunction').html()),
          "getfunctionparameter": _.template($('#getfunctionparameter').html()),
          "recaptchav3": _.template($('#recaptchav3').html()),
          "return": _.template($('#return').html()),
          "break": _.template($('#break').html()),
          "continue": _.template($('#continue').html()),
          "fail": _.template($('#fail').html()),
          "success": _.template($('#success').html()),
          "custom": _.template($('#custom').html()),
          "script": _.template($('#script').html()),
          "clickelement": _.template($('#clickelement').html()),
          "moveelement": _.template($('#moveelement').html()),
          "moveandclickelement": _.template($('#moveandclickelement').html()),
          "clear": _.template($('#clear').html()),
          "typeelement": _.template($('#typeelement').html()),
          "exist": _.template($('#exist').html()),
          "style": _.template($('#style').html()),
          "check": _.template($('#check').html()),
          "focus": _.template($('#focus').html()),
          "set": _.template($('#set').html()),
          "set_integer": _.template($('#set_integer').html()),
          "set_random": _.template($('#set_random').html()),
          "attr": _.template($('#attr').html()),
          "set_attr": _.template($('#set_attr').html()),
          "clickextensionbutton": _.template($('#clickextensionbutton').html()),
          "captcha": _.template($('#captcha').html()),
          "screenshot": _.template($('#screenshot').html()),
          "length": _.template($('#length').html()),
          "loopelement": _.template($('#loopelement').html()),
          "clickCaptchaBrowser": _.template($('#clickCaptchaBrowser').html()),
          "solvecaptcha": _.template($('#solvecaptcha').html()),
          "javascript": _.template($('#javascript').html()),
          "reset": _.template($('#reset').html()),
          "openfile": _.template($('#openfile').html()),
          "dragfile": _.template($('#dragfile').html()),
          //"getcookiesforurl": _.template($('#getcookiesforurl').html()),
          "savecookies": _.template($('#savecookies').html()),
          "restorecookies": _.template($('#restorecookies').html()),
          "scroll": _.template($('#scroll').html()),
          "html": _.template($('#html').html()),
          "renderscreen": _.template($('#renderscreen').html()),
          "cachemaskallow": _.template($('#cachemaskallow').html()),
          "cachemaskdeny": _.template($('#cachemaskdeny').html()),
          "cachemaskclear": _.template($('#cachemaskclear').html()),
          "requestmaskallow": _.template($('#requestmaskallow').html()),
          "requestmaskdeny": _.template($('#requestmaskdeny').html()),
          "requestmaskclear": _.template($('#requestmaskclear').html()),
          "cleardata": _.template($('#cleardata').html()),
          "clearmasks": _.template($('#clearmasks').html()),
          "getstatus": _.template($('#getstatus').html()),
          "isloaded": _.template($('#isloaded').html()),
          "getfromcache": _.template($('#getfromcache').html()),
          "getallcache": _.template($('#getallcache').html()),
          "redirectrequests": _.template($('#redirectrequests').html()),
          "replacerequestcontent": _.template($('#replacerequestcontent').html()),
          "replaceresponsecontent": _.template($('#replaceresponsecontent').html()),
          "disablerules": _.template($('#disablerules').html()),
          "getrulestats": _.template($('#getrulestats').html()),
          "result": _.template($('#result').html()),
          "globalset": _.template($('#globalset').html()),
          "globalget": _.template($('#globalget').html()),
          "httpclientproxy": _.template($('#httpclientproxy').html()),
          "httpclientreset": _.template($('#httpclientreset').html()),
          "httpclientdownload": _.template($('#httpclientdownload').html()),
          "httpclientget": _.template($('#httpclientget').html()),
          "httpclientpost": _.template($('#httpclientpost').html()),
          "httpclienturl": _.template($('#httpclienturl').html()),
          "httpclientcontent": _.template($('#httpclientcontent').html()),
          "httpclientstatus": _.template($('#httpclientstatus').html()),
          "httpclientgetheader": _.template($('#httpclientgetheader').html()),
          "httpclientsetheader": _.template($('#httpclientsetheader').html()),
          "httpclientclearheader": _.template($('#httpclientclearheader').html()),
          //"httpclientgetcookiesforurl": _.template($('#httpclientgetcookiesforurl').html()),
          "httpclientsavecookies": _.template($('#httpclientsavecookies').html()),
          "httpclientrestorecookies": _.template($('#httpclientrestorecookies').html()),
          "httpclientfailonerror": _.template($('#httpclientfailonerror').html()),
          "httpclientiserror": _.template($('#httpclientiserror').html()),
          "httpclientgeterrorstring": _.template($('#httpclientgeterrorstring').html()),
          "httpclientxpathxml": _.template($('#httpclientxpathxml').html()),
          "httpclientxpathxmllist": _.template($('#httpclientxpathxmllist').html()),
          "httpclientxpathtext": _.template($('#httpclientxpathtext').html()),
          "httpclientxpathtextlist": _.template($('#httpclientxpathtextlist').html()),
          "httpclientxpathcount": _.template($('#httpclientxpathcount').html()),
          "httpclientxpathexists": _.template($('#httpclientxpathexists').html()),
          "parseline": _.template($('#parseline').html()),
          "waitelement": _.template($('#waitelement').html()),
          "timeout": _.template($('#timeout').html()),
          "promptresult": _.template($('#promptresult').html()),
          "httpauth": _.template($('#httpauth').html()),
          "solverfailed": _.template($('#solverfailed').html()),
          "browserjavascript": _.template($('#browserjavascript').html()),
          "browserscript": _.template($('#browserscript').html()),
          "onloadjavascript": _.template($('#onloadjavascript').html()),
          "incvariable": _.template($('#incvariable').html()),
          "incglobalvariable": _.template($('#incglobalvariable').html()),
          "ignoreerrors": _.template($('#ignoreerrors').html()),
          "die": _.template($('#die').html()),
          "randomint": _.template($('#randomint').html()),
          "addtab": _.template($('#addtab').html()),
          "selecttab": _.template($('#selecttab').html()),
          "tabinfo": _.template($('#tabinfo').html()),
          "closetab": _.template($('#closetab').html()),
          "drag": _.template($('#drag').html()),
          "drop": _.template($('#drop').html()),
          "dragelement": _.template($('#dragelement').html()),
          "dropelement": _.template($('#dropelement').html()),
          "waitfiledownload": _.template($('#waitfiledownload').html()),
          "loadcookiesfrombrowser": _.template($('#loadcookiesfrombrowser').html()),
          "loadcookiesfromhttpclient": _.template($('#loadcookiesfromhttpclient').html()),
          "closebrowser": _.template($('#closebrowser').html()),
          "openbrowser": _.template($('#openbrowser').html()),
          "goto": _.template($('#goto').html()),
          "label": _.template($('#label').html()),
          "restrictpopups": _.template($('#restrictpopups').html()),
          "allowpopups": _.template($('#allowpopups').html()),
          "restrictdownloads": _.template($('#restrictdownloads').html()),
          "allowdownloads": _.template($('#allowdownloads').html()),
          "setheader": _.template($('#setheader').html()),
          "mousesettings": _.template($('#mousesettings').html()),
          "notification": _.template($('#notification').html()),

          "browsersettings": _.template($('#browsersettings').html()),
          "getbrowserversionlist": _.template($('#getbrowserversionlist').html()),
          "getcurrentbrowserversion": _.template($('#getcurrentbrowserversion').html()),
          "executefunctioninseveralthreads": _.template($('#executefunctioninseveralthreads').html())
          _MACRO_INSERT_TEMPLATES_
        }
        this.model.bind('change:state', (_, state) => {
          if (state === 'main') _Router.navigate('');
          state !== '___none' && BrowserAutomationStudio_TriggerEvent('toolbox.stateChanged', state);
        });
        this.model.bind('change', this.render, this);

        try{
          BrowserAutomationStudio_Initialized();
        }catch(e)
        {}
        this.render();
      },

      render: function(){
        SelectCloseAll();
        this.trigger("before:render");
        _PreserveMainPosition.BeforUrlChanged(this.model.get("state"))
        _MultiSelectManager.BeforUrlChanged(this.model.get("state"))
        var d = this.collection.toJSON();
        if(_Schema && _Schema.length == 0)
        {
          d = d.filter(function(el){
            return !el["show_only_with_database"]
          });
        }
        d = d.filter(function(el) {
          return !["javascript"].includes(el["ref"]);
        });

        var interfacedata = ""
        try
        {
          interfacedata = this.templates[this.model.get("state")]({data:d,unused:_U,model:this.model.toJSON(),selector:_SelectorModel.toJSON(),function_params:CurrentParameters});
        }catch(e)
        {

        }
        if(interfacedata==="")
        {
          interfacedata = '<div style="padding-right:15px;padding-left:15px;">' + tr("Action interface \"") + (_GobalModel.GetPageInfo() || this.model.get("state")) + tr("\" is missing or damaged.") + '<hr style="margin-top:5px;margin-bottom:5px"/><a tabindex="-1" class="btn btn-danger standartbutton tr" href="#!/" id="backtomain">Back</a></div>';
        }

        //Reserve place for action header
        if(this.model.get("state") !== "main")
        {
          interfacedata = "<div id=\"breadcrumbcontainer\" style='height: 36px;'>&nbsp;</div>" + interfacedata
        }

        $("#containerdata").html(interfacedata)
        _Filter.InstallEvents()
        $(".variable-input, .function-input").keypress(OnInputKeyPress)
        tr()
        InitUnfoldTooltip()
        this.updatepath()

        $(".search").css("height", window.innerHeight * (100.0 / _Z) - 40 + "px");
        $(".actions").css("height", window.innerHeight * (100.0 / _Z) - 40 + "px");
        $(".leftactionpanel").css("height", window.innerHeight * (100.0 / _Z) - 45 + "px")
        $(".leftactionpaneltitlebody").css("min-height", window.innerHeight * (100.0 / _Z) - 95 + "px")
        $(".actions").css("overflow-y","auto")
        $(".leftactionpanel").css("overflow-y","auto")
        $(".leftactionpanel").css("overflow-x","hidden")
        

        Toolbox.setupTooltips();

        _PreserveMainPosition.AfterUrlChanged(this.model.get("state"))
        _MultiSelectManager.AfterUrlChanged(this.model.get("state"))

        if(CurrentTab == "history")
        {
          BrowserAutomationStudio_RenderHistory();
        }else if (CurrentTab == "bookmarks")
        {
          BrowserAutomationStudio_RenderBookmarks();
        }

        BrowserAutomationStudio_InstallBookmarks();

        BrowserAutomationStudio_TestPathInternal();

        BrowserAutomationStudio_SetExecuteType();

        BasDialogsLib.dropdowns.initialize();

        _SearchManager.initialize();

        SetupConditionalVisibility();

        SelectInitialize();

        $("body").show();
      },

      /*showtooltip: function(e)
      {
        var name = $(e.target).attr("data-name")
        var description = $(e.target).attr("data-description")
        if(typeof(name) != "undefined" && typeof(description) != "undefined")
        {
          $("#tooltip").html("<strong>" + name + "</strong> : " + description)
        }
      },*/
    });

    var Router = Backbone.Router.extend({
        routes: {
            "": "main",
            "!/": "main",
            "!/ok": "ok",
            "!/___none": "___none",
            "!/load": "load",
            "!/navigateback": "navigateback",
            "!/timeout": "timeout",
            "!/type": "type",
            "!/waitload": "waitload",
            "!/waitfullload": "waitfullload",
            "!/waiturl": "waiturl",
            "!/waitcontent": "waitcontent",
            "!/waitcss": "waitcss",
            "!/sleep": "sleep",
            "!/resize": "resize",
            "!/proxy": "proxy",
            "!/move": "move",
            "!/click": "click",
            "!/moveandclick": "moveandclick",
            "!/threadnumber": "threadnumber",
            "!/successnumber": "successnumber",
            "!/failnumber": "failnumber",
            "!/log": "log",
            "!/clearlog": "clearlog",
            "!/url": "url",
            "!/screen": "screen",
            "!/touch": "touch",
            "!/xml": "xml",
            "!/linkurl": "linkurl",
            "!/coordinates": "coordinates",
            "!/text": "text",
            "!/setvariable": "setvariable",
            "!/if": "if",
            "!/while": "while",
            "!/for": "for",
            "!/foreach": "foreach",
            "!/executefunction": "executefunction",
            "!/getfunctionparameter": "getfunctionparameter",
            "!/recaptchav3": "recaptchav3",
            "!/return": "return",
            "!/break": "break",
            "!/continue": "continue",
            "!/fail": "fail",
            "!/success": "success",
            "!/custom": "custom",
            "!/script": "script",
            "!/clickelement": "clickelement",
            "!/moveelement": "moveelement",
            "!/moveandclickelement": "moveandclickelement",
            "!/clear": "clear",
            "!/typeelement": "typeelement",
            "!/exist": "exist",
            "!/style": "style",
            "!/check": "check",
            "!/focus": "focus",
            "!/set": "set",
            "!/set_integer": "set_integer",
            "!/set_random": "set_random",
            "!/attr": "attr",
            "!/set_attr": "set_attr",
            "!/clickextensionbutton": "clickextensionbutton",
            "!/captcha": "captcha",
            "!/screenshot": "screenshot",
            "!/length": "length",
            "!/loopelement": "loopelement",
            "!/clickCaptchaBrowser": "clickCaptchaBrowser",
            "!/solvecaptcha": "solvecaptcha",
            "!/javascript": "javascript",
            "!/reset": "reset",
            "!/openfile": "openfile",
            "!/dragfile": "dragfile",
            //"!/getcookiesforurl": "getcookiesforurl",
            "!/savecookies": "savecookies",
            "!/restorecookies": "restorecookies",
            "!/scroll": "scroll",
            "!/html": "html",
            "!/renderscreen": "renderscreen",
            "!/cachemaskallow": "cachemaskallow",
            "!/cachemaskdeny": "cachemaskdeny",
            "!/cachemaskclear": "cachemaskclear",
            "!/requestmaskallow": "requestmaskallow",
            "!/requestmaskdeny": "requestmaskdeny",
            "!/requestmaskclear": "requestmaskclear",
            "!/cleardata": "cleardata",
            "!/clearmasks": "clearmasks",
            "!/getstatus": "getstatus",
            "!/isloaded": "isloaded",
            "!/getfromcache": "getfromcache",
            "!/getallcache": "getallcache",
            "!/redirectrequests": "redirectrequests",
            "!/replacerequestcontent": "replacerequestcontent",
            "!/replaceresponsecontent": "replaceresponsecontent",
            "!/disablerules": "disablerules",
            "!/getrulestats": "getrulestats",
            "!/result": "result",
            "!/globalset": "globalset",
            "!/globalget": "globalget",
            "!/httpclientproxy": "httpclientproxy",
            "!/httpclientreset": "httpclientreset",
            "!/httpclientdownload": "httpclientdownload",
            "!/httpclientget": "httpclientget",
            "!/httpclientpost": "httpclientpost",
            "!/httpclienturl": "httpclienturl",
            "!/httpclientcontent": "httpclientcontent",
            "!/httpclientstatus": "httpclientstatus",
            "!/httpclientgetheader": "httpclientgetheader",
            "!/httpclientsetheader": "httpclientsetheader",
            "!/httpclientclearheader": "httpclientclearheader",
            //"!/httpclientgetcookiesforurl": "httpclientgetcookiesforurl",
            "!/httpclientsavecookies": "httpclientsavecookies",
            "!/httpclientrestorecookies": "httpclientrestorecookies",
            "!/httpclientfailonerror": "httpclientfailonerror",
            "!/httpclientiserror": "httpclientiserror",
            "!/httpclientgeterrorstring": "httpclientgeterrorstring",
            "!/httpclientxpathxml": "httpclientxpathxml",
            "!/httpclientxpathxmllist": "httpclientxpathxmllist",
            "!/httpclientxpathtext": "httpclientxpathtext",
            "!/httpclientxpathtextlist": "httpclientxpathtextlist",
            "!/httpclientxpathcount": "httpclientxpathcount",
            "!/httpclientxpathexists": "httpclientxpathexists",
            "!/parseline": "parseline",
            "!/waitelement": "waitelement",
            "!/promptresult": "promptresult",
            "!/httpauth": "httpauth",
            "!/solverfailed": "solverfailed",
            "!/browserjavascript": "browserjavascript",
            "!/browserscript": "browserscript",
            "!/onloadjavascript": "onloadjavascript",
            "!/incvariable": "incvariable",
            "!/incglobalvariable": "incglobalvariable",
            "!/ignoreerrors": "ignoreerrors",
            "!/die": "die",
            "!/addtab": "addtab",
            "!/selecttab": "selecttab",
            "!/tabinfo": "tabinfo",
            "!/closetab": "closetab",
            "!/randomint": "randomint",
            "!/drag": "drag",
            "!/drop": "drop",
            "!/dragelement": "dragelement",
            "!/dropelement": "dropelement",
            "!/waitfiledownload": "waitfiledownload",
            "!/loadcookiesfrombrowser": "loadcookiesfrombrowser",
            "!/loadcookiesfromhttpclient": "loadcookiesfromhttpclient",
            "!/closebrowser": "closebrowser",
            "!/openbrowser": "openbrowser",
            "!/label": "label",
            "!/goto": "goto",
            "!/restrictpopups": "restrictpopups",
            "!/allowpopups": "allowpopups",
            "!/restrictdownloads": "restrictdownloads",
            "!/allowdownloads": "allowdownloads",
            "!/setheader": "setheader",
            "!/mousesettings": "mousesettings",
            "!/notification": "notification",

            "!/browsersettings": "browsersettings",
            "!/getbrowserversionlist": "getbrowserversionlist",
            "!/getcurrentbrowserversion": "getcurrentbrowserversion",
            "!/executefunctioninseveralthreads": "executefunctioninseveralthreads"
            _MACRO_INSERT_ROUTER_DEF_
        },

        main: function () {
          CurrentGroup = ""
          _GobalModel.set({ state: "main" });
          
        },
        timeout: function () {
          _GobalModel.set({ state: "timeout" });
        },
        ___none: function () {
          _GobalModel.set({ state: "___none" });
        },
        load: function () {
          _GobalModel.set({ state: "load" });
        },
        navigateback: function () {
          _GobalModel.set({ state: "navigateback" });
        },
        type: function () {
          _GobalModel.set({ state: "type" });
        },
        waitload: function () {
          _GobalModel.set({ state: "waitload" });
        },
        waitfullload: function () {
          _GobalModel.set({ state: "waitfullload" });
        },
        waiturl: function () {
          _GobalModel.set({ state: "waiturl" });
        },
        waitcontent: function () {
          _GobalModel.set({ state: "waitcontent" });
        },
        waitcss: function () {
          _GobalModel.set({ state: "waitcss" });
        },
        sleep: function () {
          _GobalModel.set({ state: "sleep" });
        },
        resize: function () {
          _GobalModel.set({ state: "resize" });
        },
        proxy: function () {
          _GobalModel.set({ state: "proxy" });
        },
        move: function () {
          _GobalModel.set({ state: "move" });
        },
        click: function () {
          _GobalModel.set({ state: "click" });
        },
        moveandclick: function () {
          _GobalModel.set({ state: "moveandclick" });
        },
        threadnumber: function () {
          _GobalModel.set({ state: "threadnumber" });
        },
        successnumber: function () {
          _GobalModel.set({ state: "successnumber" });
        },
        failnumber: function () {
          _GobalModel.set({ state: "failnumber" });
        },
        log: function () {
          _GobalModel.set({ state: "log" });
        },
        clearlog: function () {
          _GobalModel.set({ state: "clearlog" });
        },
        url: function () {
          _GobalModel.set({ state: "url" });
        },
        screen: function () {
          _GobalModel.set({ state: "screen" });
        },
        touch: function () {
          _GobalModel.set({ state: "touch" });
        },
        xml: function () {
          _GobalModel.set({ state: "xml" });
        },
        linkurl: function () {
          _GobalModel.set({ state: "linkurl" });
        },
        coordinates: function () {
          _GobalModel.set({ state: "coordinates" });
        },
        text: function () {
          _GobalModel.set({ state: "text" });
        },
        setvariable: function () {
          _GobalModel.set({ state: "setvariable" });
        },
        if: function () {
          _GobalModel.set({ state: "if" });
        },
        while: function () {
          _GobalModel.set({ state: "while" });
        },
        for: function () {
          _GobalModel.set({ state: "for" });
        },
        foreach: function () {
          _GobalModel.set({ state: "foreach" });
        },
        executefunction: function(){
          _GobalModel.set({ state: "executefunction" });
        },
        return: function(){
          _GobalModel.set({ state: "return" });
        },
        getfunctionparameter: function(){
          _GobalModel.set({ state: "getfunctionparameter" });
        },
        recaptchav3: function(){
          _GobalModel.set({ state: "recaptchav3" });
        },
        break: function(){
          _GobalModel.set({ state: "break" });
        },
        continue: function(){
          _GobalModel.set({ state: "continue" });
        },
        success: function(){
          _GobalModel.set({ state: "success" });
        },
        fail: function(){
          _GobalModel.set({ state: "fail" });
        },
        custom: function(){
          _GobalModel.set({ state: "custom" });
        },
        script: function(){
          _GobalModel.set({ state: "script" });
        },
        clickelement: function(){
          _GobalModel.set({ state: "clickelement" });
        },
        moveelement: function(){
          _GobalModel.set({ state: "moveelement" });
        },
        moveandclickelement: function(){
          _GobalModel.set({ state: "moveandclickelement" });
        },
        clear: function(){
          _GobalModel.set({ state: "clear" });
        },
        typeelement: function(){
          _GobalModel.set({ state: "typeelement" });
        },
        exist: function(){
          _GobalModel.set({ state: "exist" });
        },
        style: function(){
          _GobalModel.set({ state: "style" });
        },
        check: function(){
          _GobalModel.set({ state: "check" });
        },
        focus: function(){
          _GobalModel.set({ state: "focus" });
        },
        set: function(){
          _GobalModel.set({ state: "set" });
        },
        set_integer: function(){
          _GobalModel.set({ state: "set_integer" });
        },
        set_random: function(){
          _GobalModel.set({ state: "set_random" });
        },
        attr: function(){
          _GobalModel.set({ state: "attr" });
        },
        set_attr: function(){
          _GobalModel.set({ state: "set_attr" });
        },
        clickextensionbutton: function(){
          _GobalModel.set({ state: "clickextensionbutton" });
        },
        captcha: function(){
          _GobalModel.set({ state: "captcha" });
        },
        screenshot: function(){
          _GobalModel.set({ state: "screenshot" });
        },
        length: function(){
          _GobalModel.set({ state: "length" });
        },
        loopelement: function(){
          _GobalModel.set({ state: "loopelement" });
        },
        clickCaptchaBrowser: function () {
          _GobalModel.set({ state: "clickCaptchaBrowser" });
        },
        solvecaptcha: function(){
                  _GobalModel.set({ state: "solvecaptcha" });
                },
        javascript: function(){
                  _GobalModel.set({ state: "javascript" });
                },
        reset: function(){
                  _GobalModel.set({ state: "reset" });
                },
        openfile: function(){
                  _GobalModel.set({ state: "openfile" });
                },
        dragfile: function(){
                  _GobalModel.set({ state: "dragfile" });
                },
        /*getcookiesforurl: function(){
                  _GobalModel.set({ state: "getcookiesforurl" });
                },*/
        savecookies: function(){
                  _GobalModel.set({ state: "savecookies" });
                },
        restorecookies: function(){
                  _GobalModel.set({ state: "restorecookies" });
                },
        scroll: function(){
                  _GobalModel.set({ state: "scroll" });
                },
        html: function(){
                  _GobalModel.set({ state: "html" });
                },
        renderscreen: function(){
                  _GobalModel.set({ state: "renderscreen" });
                },
        cachemaskallow: function(){
                  _GobalModel.set({ state: "cachemaskallow" });
                },
        cachemaskdeny: function(){
                  _GobalModel.set({ state: "cachemaskdeny" });
                },
        cachemaskclear: function(){
                  _GobalModel.set({ state: "cachemaskclear" });
                },
        requestmaskallow: function(){
                  _GobalModel.set({ state: "requestmaskallow" });
                },
        requestmaskdeny: function(){
                  _GobalModel.set({ state: "requestmaskdeny" });
                },
        requestmaskclear: function(){
                  _GobalModel.set({ state: "requestmaskclear" });
                },
        cleardata: function(){
                  _GobalModel.set({ state: "cleardata" });
                },
        clearmasks: function(){
                  _GobalModel.set({ state: "clearmasks" });
                },
        getstatus: function(){
                  _GobalModel.set({ state: "getstatus" });
                },
        isloaded: function(){
                  _GobalModel.set({ state: "isloaded" });
                },
        getfromcache: function(){
                  _GobalModel.set({ state: "getfromcache" });
                },
        getallcache: function(){
                  _GobalModel.set({ state: "getallcache" });
                },
        redirectrequests: function(){
                  _GobalModel.set({ state: "redirectrequests" });
                },
        replacerequestcontent: function(){
                  _GobalModel.set({ state: "replacerequestcontent" });
                },
        replaceresponsecontent: function(){
                  _GobalModel.set({ state: "replaceresponsecontent" });
                },
        disablerules: function(){
                  _GobalModel.set({ state: "disablerules" });
                },
        getrulestats: function(){
                  _GobalModel.set({ state: "getrulestats" });
                },
        result: function(){
                  _GobalModel.set({ state: "result" });
                },
        globalset: function(){
                  _GobalModel.set({ state: "globalset" });
                },
        globalget: function(){
                  _GobalModel.set({ state: "globalget" });
                },
        httpclientproxy: function(){
                  _GobalModel.set({ state: "httpclientproxy" });
                },
        httpclientreset: function(){
                  _GobalModel.set({ state: "httpclientreset" });
                },
        httpclientdownload: function(){
                  _GobalModel.set({ state: "httpclientdownload" });
                },
        httpclientget: function(){
                  _GobalModel.set({ state: "httpclientget" });
                },
        httpclientpost: function(){
                  _GobalModel.set({ state: "httpclientpost" });
                },
        httpclienturl: function(){
                  _GobalModel.set({ state: "httpclienturl" });
                },
        httpclientcontent: function(){
                  _GobalModel.set({ state: "httpclientcontent" });
                },
        httpclientstatus: function(){
                  _GobalModel.set({ state: "httpclientstatus" });
                },
        httpclientgetheader: function(){
                  _GobalModel.set({ state: "httpclientgetheader" });
                },
        httpclientsetheader: function(){
                  _GobalModel.set({ state: "httpclientsetheader" });
                },
        httpclientclearheader: function(){
                  _GobalModel.set({ state: "httpclientclearheader" });
                },
        /*httpclientgetcookiesforurl: function(){
                  _GobalModel.set({ state: "httpclientgetcookiesforurl" });
                },*/
        httpclientsavecookies: function(){
                  _GobalModel.set({ state: "httpclientsavecookies" });
                },
        httpclientrestorecookies: function(){
                  _GobalModel.set({ state: "httpclientrestorecookies" });
                },
        httpclientfailonerror: function(){
                  _GobalModel.set({ state: "httpclientfailonerror" });
                },
        httpclientiserror: function(){
                  _GobalModel.set({ state: "httpclientiserror" });
                },
        httpclientgeterrorstring: function(){
                  _GobalModel.set({ state: "httpclientgeterrorstring" });
                },
        httpclientxpathxml: function(){
                  _GobalModel.set({ state: "httpclientxpathxml" });
                },
        httpclientxpathxmllist: function(){
                  _GobalModel.set({ state: "httpclientxpathxmllist" });
                },
        httpclientxpathtext: function(){
                  _GobalModel.set({ state: "httpclientxpathtext" });
                },
        httpclientxpathtextlist: function(){
                  _GobalModel.set({ state: "httpclientxpathtextlist" });
                },
        httpclientxpathcount: function(){
                  _GobalModel.set({ state: "httpclientxpathcount" });
                },
        httpclientxpathexists: function(){
                  _GobalModel.set({ state: "httpclientxpathexists" });
                },
        parseline: function(){
                  _GobalModel.set({ state: "parseline" });
                },
        waitelement: function(){
                  _GobalModel.set({ state: "waitelement" });
                },
        promptresult: function(){
                  _GobalModel.set({ state: "promptresult" });
                },
        httpauth: function(){
                  _GobalModel.set({ state: "httpauth" });
                },
        solverfailed: function(){
          _GobalModel.set({ state: "solverfailed" });
        },
        browserjavascript: function(){
          _GobalModel.set({ state: "browserjavascript" });
        },
        browserscript: function(){
          _GobalModel.set({ state: "browserscript" });
        },
        onloadjavascript: function(){
          _GobalModel.set({ state: "onloadjavascript" });
        },
        incvariable: function(){
          _GobalModel.set({ state: "incvariable" });
        },
        incglobalvariable: function(){
          _GobalModel.set({ state: "incglobalvariable" });
        },
        ignoreerrors: function(){
          _GobalModel.set({ state: "ignoreerrors" });
        },
        die: function(){
          _GobalModel.set({ state: "die" });
        },
        randomint: function(){
          _GobalModel.set({ state: "randomint" });
        }
        ,
        addtab: function(){
          _GobalModel.set({ state: "addtab" });
        }
        ,
        selecttab: function(){
          _GobalModel.set({ state: "selecttab" });
        },
        tabinfo: function(){
          _GobalModel.set({ state: "tabinfo" });
        }
        ,closetab: function(){
          _GobalModel.set({ state: "closetab" });
        }
        ,drag: function(){
          _GobalModel.set({ state: "drag" });
        }
        ,drop: function(){
          _GobalModel.set({ state: "drop" });
        }
        ,dragelement: function(){
          _GobalModel.set({ state: "dragelement" });
        }
        ,dropelement: function(){
          _GobalModel.set({ state: "dropelement" });
        },
        waitfiledownload: function(){
          _GobalModel.set({ state: "waitfiledownload" });
        },
        loadcookiesfrombrowser: function(){
          _GobalModel.set({ state: "loadcookiesfrombrowser" });
        },
        loadcookiesfromhttpclient: function(){
          _GobalModel.set({ state: "loadcookiesfromhttpclient" });
        },openbrowser: function(){
          _GobalModel.set({ state: "openbrowser" });
        }
        ,closebrowser: function(){
          _GobalModel.set({ state: "closebrowser" });
        }
        ,label: function(){
          _GobalModel.set({ state: "label" });
        }
        ,goto: function(){

          _GobalModel.set({ state: "goto" });
          BrowserAutomationStudio_FillGotoLabels()
            
        }
        ,restrictpopups: function(){
          _GobalModel.set({ state: "restrictpopups" });
        }
        ,allowpopups: function(){
          _GobalModel.set({ state: "allowpopups" });
        }
        ,restrictdownloads: function(){
          _GobalModel.set({ state: "restrictdownloads" });
        }
        ,allowdownloads: function(){
          _GobalModel.set({ state: "allowdownloads" });
        }
        ,setheader: function(){
          _GobalModel.set({ state: "setheader" });
        }
        ,mousesettings: function(){
          _GobalModel.set({ state: "mousesettings" });
        }
        ,notification: function(){
          _GobalModel.set({ state: "notification" });
        }
        ,browsersettings: function(){
          _GobalModel.set({ state: "browsersettings" });
        }
        ,getbrowserversionlist: function(){
          _GobalModel.set({ state: "getbrowserversionlist" });
        },
        getcurrentbrowserversion: function(){
          _GobalModel.set({ state: "getcurrentbrowserversion" });
        },
        executefunctioninseveralthreads: function(){
          _GobalModel.set({ state: "executefunctioninseveralthreads" });
        }
        _MACRO_INSERT_ROUTER_FUNC_
    });

    var _Router = new Router();



    var _TaskCollection = new TaskCollection([
                { description: tr("Generate code with AI"), type: "group", name: "ai", icon: _G["ai"]["icon"], info: tr(_G["ai"]["info"])},
                { description: tr("Browser"), type: "group", name: "browser", icon: _G["browser"]["icon"], info: tr(_G["browser"]["info"])},
                { name: tr(_A["load"]["name"]), description: tr(_A["load"]["description"]), ref: "load" },
                { name: tr(_A["url"]["name"]), description: tr(_A["url"]["description"]), ref: "url" },
                { name: tr(_A["navigateback"]["name"]), description: tr(_A["navigateback"]["description"]), ref: "navigateback" },
                { name: tr(_A["html"]["name"]), description: tr(_A["html"]["description"]), ref: "html" },
                { name: tr(_A["type"]["name"]), description: tr(_A["type"]["description"]), ref: "type" },
                { name: tr(_A["resize"]["name"]), description: tr(_A["resize"]["description"]), ref: "resize" },
                { name: tr(_A["screen"]["name"]), description: tr(_A["screen"]["description"]), ref: "screen" },
                { name: tr(_A["proxy"]["name"]), description: tr(_A["proxy"]["description"]), ref: "proxy" },
                { name: tr(_A["javascript"]["name"]), description: tr(_A["javascript"]["description"]), ref: "javascript" },
                { name: tr(_A["browserjavascript"]["name"]), description: tr(_A["browserjavascript"]["description"]), ref: "browserjavascript" },
                { name: tr(_A["onloadjavascript"]["name"]), description: tr(_A["onloadjavascript"]["description"]), ref: "onloadjavascript" },
                { name: tr(_A["reset"]["name"]), description: tr(_A["reset"]["description"]), ref: "reset" },
                { name: tr(_A["openfile"]["name"]), description: tr(_A["openfile"]["description"]), ref: "openfile" },
                { name: tr(_A["dragfile"]["name"]), description: tr(_A["dragfile"]["description"]), ref: "dragfile" },
                { name: tr(_A["promptresult"]["name"]), description: tr(_A["promptresult"]["description"]), ref: "promptresult" },
                { name: tr(_A["httpauth"]["name"]), description: tr(_A["httpauth"]["description"]), ref: "httpauth" },
                { name: tr(_A["scroll"]["name"]), description: tr(_A["scroll"]["description"]), ref: "scroll" },
                { name: tr(_A["renderscreen"]["name"]), description: tr(_A["renderscreen"]["description"]), ref: "renderscreen" },
                { name: tr(_A["solvecaptcha"]["name"]), description: tr(_A["solvecaptcha"]["description"]), ref: "solvecaptcha" },
                { name: tr(_A["recaptchav3"]["name"]), description: tr(_A["recaptchav3"]["description"]), ref: "recaptchav3" },
                { name: tr(_A["clickCaptchaBrowser"]["name"]), description: tr(_A["clickCaptchaBrowser"]["description"]), ref: "clickCaptchaBrowser" },
                { name: tr(_A["solverfailed"]["name"]), description: tr(_A["solverfailed"]["description"]), ref: "solverfailed" },
                { name: tr(_A["timeout"]["name"]), description: tr(_A["timeout"]["description"]), ref: "timeout" },
                { name: tr(_A["browsersettings"]["name"]), description: tr(_A["browsersettings"]["description"]), ref: "browsersettings" },
                { name: tr(_A["getcurrentbrowserversion"]["name"]), description: tr(_A["getcurrentbrowserversion"]["description"]), ref: "getcurrentbrowserversion" },
                { name: tr(_A["getbrowserversionlist"]["name"]), description: tr(_A["getbrowserversionlist"]["description"]), ref: "getbrowserversionlist" },
                { name: tr(_A["clickextensionbutton"]["name"]), description: tr(_A["clickextensionbutton"]["description"]), ref: "clickextensionbutton" },
                { name: tr(_A["touch"]["name"]), description: tr(_A["touch"]["description"]), ref: "touch" },
                { name: tr(_A["mousesettings"]["name"]), description: tr(_A["mousesettings"]["description"]), ref: "mousesettings" },
                { name: tr(_A["notification"]["name"]), description: tr(_A["notification"]["description"]), ref: "notification" },
                { description: tr("Script logic"), type: "group", name: "logic", icon: _G["logic"]["icon"], info: tr(_G["logic"]["info"]) },
                { name: tr(_A["if"]["name"]), description: tr(_A["if"]["description"]), ref: "if" },
                { name: tr(_A["while"]["name"]), description: tr(_A["while"]["description"]), ref: "while" },
                { name: tr(_A["for"]["name"]), description: tr(_A["for"]["description"]), ref: "for" },
                { name: tr(_A["foreach"]["name"]), description: tr(_A["foreach"]["description"]), ref: "foreach" },
                { name: tr(_A["break"]["name"]), description: tr(_A["break"]["description"]), ref: "break" },
                { name: tr(_A["continue"]["name"]), description: tr(_A["continue"]["description"]), ref: "continue" },
                { name: tr(_A["success"]["name"]), description: tr(_A["success"]["description"]), ref: "success" },
                { name: tr(_A["fail"]["name"]), description: tr(_A["fail"]["description"]), ref: "fail" },
                { name: tr(_A["die"]["name"]), description: tr(_A["die"]["description"]), ref: "die" },
                { name: tr(_A["label"]["name"]), description: tr(_A["label"]["description"]), ref: "label" },
                { name: tr(_A["goto"]["name"]), description: tr(_A["goto"]["description"]), ref: "goto" },
                { name: tr(_A["ignoreerrors"]["name"]), description: tr(_A["ignoreerrors"]["description"]), ref: "ignoreerrors" },
                { name: tr(_A["setvariable"]["name"]), description: tr(_A["setvariable"]["description"]), ref: "setvariable" },
                { name: tr(_A["incvariable"]["name"]), description: tr(_A["incvariable"]["description"]), ref: "incvariable" },
                { name: tr(_A["globalset"]["name"]), description: tr(_A["globalset"]["description"]), ref: "globalset" },
                { name: tr(_A["incglobalvariable"]["name"]), description: tr(_A["incglobalvariable"]["description"]), ref: "incglobalvariable" },
                { name: tr(_A["executefunction"]["name"]), description: tr(_A["executefunction"]["description"]), ref: "executefunction" },
                { name: tr(_A["getfunctionparameter"]["name"]), description: tr(_A["getfunctionparameter"]["description"]), ref: "getfunctionparameter" },
                { name: tr(_A["return"]["name"]), description: tr(_A["return"]["description"]), ref: "return" },
                { name: tr(_A["executefunctioninseveralthreads"]["name"]), description: tr(_A["executefunctioninseveralthreads"]["description"]), ref: "executefunctioninseveralthreads" },
                { description: tr("Tools"), type: "group", name: "tools", icon: _G["tools"]["icon"], info: tr(_G["tools"]["info"]) },
                { name: tr(_A["log"]["name"]), description: tr(_A["log"]["description"]), ref: "log" },
                { name: tr(_A["clearlog"]["name"]), description: tr(_A["clearlog"]["description"]), ref: "clearlog" },
                { name: tr(_A["result"]["name"]), description: tr(_A["result"]["description"]), ref: "result" },
                { name: tr(_A["custom"]["name"]), description: tr(_A["custom"]["description"]), ref: "custom" },
                /*{ name: tr(_A["globalget"]["name"]), description: tr(_A["globalget"]["description"]), ref: "globalget" },*/
                { name: tr(_A["parseline"]["name"]), description: tr(_A["parseline"]["description"]), ref: "parseline" },
                { name: tr(_A["randomint"]["name"]), description: tr(_A["randomint"]["description"]), ref: "randomint" },
                { description: tr("Network"), type: "group", name: "network", icon: _G["network"]["icon"], info: tr(_G["network"]["info"]) },
                //{ name: tr(_A["getcookiesforurl"]["name"]), description: tr(_A["getcookiesforurl"]["description"]), ref: "getcookiesforurl" },
                { name: tr(_A["savecookies"]["name"]), description: tr(_A["savecookies"]["description"]), ref: "savecookies" },
                { name: tr(_A["restorecookies"]["name"]), description: tr(_A["restorecookies"]["description"]), ref: "restorecookies" },
                { name: tr(_A["loadcookiesfromhttpclient"]["name"]), description: tr(_A["loadcookiesfromhttpclient"]["description"]), ref: "loadcookiesfromhttpclient" },
                { name: tr(_A["cachemaskallow"]["name"]), description: tr(_A["cachemaskallow"]["description"]), ref: "cachemaskallow" },
                { name: tr(_A["cachemaskdeny"]["name"]), description: tr(_A["cachemaskdeny"]["description"]), ref: "cachemaskdeny" },
                { name: tr(_A["requestmaskallow"]["name"]), description: tr(_A["requestmaskallow"]["description"]), ref: "requestmaskallow" },
                { name: tr(_A["requestmaskdeny"]["name"]), description: tr(_A["requestmaskdeny"]["description"]), ref: "requestmaskdeny" },
                { name: tr(_A["cleardata"]["name"]), description: tr(_A["cleardata"]["description"]), ref: "cleardata" },
                { name: tr(_A["clearmasks"]["name"]), description: tr(_A["clearmasks"]["description"]), ref: "clearmasks" },
                { name: tr(_A["getstatus"]["name"]), description: tr(_A["getstatus"]["description"]), ref: "getstatus" },
                { name: tr(_A["isloaded"]["name"]), description: tr(_A["isloaded"]["description"]), ref: "isloaded" },
                { name: tr(_A["getfromcache"]["name"]), description: tr(_A["getfromcache"]["description"]), ref: "getfromcache" },
                { name: tr(_A["getallcache"]["name"]), description: tr(_A["getallcache"]["description"]), ref: "getallcache" },
                { name: tr(_A["redirectrequests"]["name"]), description: tr(_A["redirectrequests"]["description"]), ref: "redirectrequests" },
                { name: tr(_A["replacerequestcontent"]["name"]), description: tr(_A["replacerequestcontent"]["description"]), ref: "replacerequestcontent" },
                { name: tr(_A["replaceresponsecontent"]["name"]), description: tr(_A["replaceresponsecontent"]["description"]), ref: "replaceresponsecontent" },
                { name: tr(_A["disablerules"]["name"]), description: tr(_A["disablerules"]["description"]), ref: "disablerules" },
                { name: tr(_A["getrulestats"]["name"]), description: tr(_A["getrulestats"]["description"]), ref: "getrulestats" },
                { name: tr(_A["restrictpopups"]["name"]), description: tr(_A["restrictpopups"]["description"]), ref: "restrictpopups" },
                { name: tr(_A["allowpopups"]["name"]), description: tr(_A["allowpopups"]["description"]), ref: "allowpopups" },
                { name: tr(_A["restrictdownloads"]["name"]), description: tr(_A["restrictdownloads"]["description"]), ref: "restrictdownloads" },
                { name: tr(_A["allowdownloads"]["name"]), description: tr(_A["allowdownloads"]["description"]), ref: "allowdownloads" },
                { name: tr(_A["setheader"]["name"]), description: tr(_A["setheader"]["description"]), ref: "setheader" },
                { description: tr("Waiters"), type: "group", name: "waiters", icon: _G["waiters"]["icon"], info: tr(_G["waiters"]["info"]) },
                { name: tr(_A["waitfullload"]["name"]), description: tr(_A["waitfullload"]["description"]), ref: "waitfullload" },
                { name: tr(_A["waitload"]["name"]), description: tr(_A["waitload"]["description"]), ref: "waitload" },
                { name: tr(_A["waiturl"]["name"]), description: tr(_A["waiturl"]["description"]), ref: "waiturl" },
                { name: tr(_A["waitcontent"]["name"]), description: tr(_A["waitcontent"]["description"]), ref: "waitcontent" },
                { name: tr(_A["waitcss"]["name"]), description: tr(_A["waitcss"]["description"]), ref: "waitcss" },
                { name: tr(_A["waitfiledownload"]["name"]), description: tr(_A["waitfiledownload"]["description"]), ref: "waitfiledownload" },
                { name: tr(_A["sleep"]["name"]), description: tr(_A["sleep"]["description"]), ref: "sleep" },
                /*{ description: tr("Email"), type: "group", name: "email", icon: _G["email"]["icon"], info: tr(_G["email"]["info"]) },
                { name: tr(_A["emailsettings"]["name"]), description: tr(_A["emailsettings"]["description"]), ref: "emailsettings" },
                { name: tr(_A["emailproxy"]["name"]), description: tr(_A["emailproxy"]["description"]), ref: "emailproxy" },
                { name: tr(_A["emaillength"]["name"]), description: tr(_A["emaillength"]["description"]), ref: "emaillength" },
                { name: tr(_A["emailsearchfirst"]["name"]), description: tr(_A["emailsearchfirst"]["description"]), ref: "emailsearchfirst" },
                { name: tr(_A["emailsearchall"]["name"]), description: tr(_A["emailsearchall"]["description"]), ref: "emailsearchall" },
                { name: tr(_A["emailpull"]["name"]), description: tr(_A["emailpull"]["description"]), ref: "emailpull" },
                { name: tr(_A["emailremove"]["name"]), description: tr(_A["emailremove"]["description"]), ref: "emailremove" },*/
                { description: tr("Http Client"), type: "group", name: "httpclient", icon: _G["httpclient"]["icon"], info: tr(_G["httpclient"]["info"]) },
                { name: tr(_A["httpclientproxy"]["name"]), description: tr(_A["httpclientproxy"]["description"]), ref: "httpclientproxy" },
                { name: tr(_A["httpclientreset"]["name"]), description: tr(_A["httpclientreset"]["description"]), ref: "httpclientreset" },
                { name: tr(_A["httpclientget"]["name"]), description: tr(_A["httpclientget"]["description"]), ref: "httpclientget" },
                { name: tr(_A["httpclientpost"]["name"]), description: tr(_A["httpclientpost"]["description"]), ref: "httpclientpost" },
                { name: tr(_A["httpclientdownload"]["name"]), description: tr(_A["httpclientdownload"]["description"]), ref: "httpclientdownload" },
                { name: tr(_A["httpclienturl"]["name"]), description: tr(_A["httpclienturl"]["description"]), ref: "httpclienturl" },
                { name: tr(_A["httpclientcontent"]["name"]), description: tr(_A["httpclientcontent"]["description"]), ref: "httpclientcontent" },
                { name: tr(_A["httpclientstatus"]["name"]), description: tr(_A["httpclientstatus"]["description"]), ref: "httpclientstatus" },
                { name: tr(_A["httpclientgetheader"]["name"]), description: tr(_A["httpclientgetheader"]["description"]), ref: "httpclientgetheader" },
                { name: tr(_A["httpclientsetheader"]["name"]), description: tr(_A["httpclientsetheader"]["description"]), ref: "httpclientsetheader" },
                { name: tr(_A["httpclientclearheader"]["name"]), description: tr(_A["httpclientclearheader"]["description"]), ref: "httpclientclearheader" },
                //{ name: tr(_A["httpclientgetcookiesforurl"]["name"]), description: tr(_A["httpclientgetcookiesforurl"]["description"]), ref: "httpclientgetcookiesforurl" },
                { name: tr(_A["httpclientsavecookies"]["name"]), description: tr(_A["httpclientsavecookies"]["description"]), ref: "httpclientsavecookies" },
                { name: tr(_A["httpclientrestorecookies"]["name"]), description: tr(_A["httpclientrestorecookies"]["description"]), ref: "httpclientrestorecookies" },
                { name: tr(_A["loadcookiesfrombrowser"]["name"]), description: tr(_A["loadcookiesfrombrowser"]["description"]), ref: "loadcookiesfrombrowser" },
                { name: tr(_A["httpclientfailonerror"]["name"]), description: tr(_A["httpclientfailonerror"]["description"]), ref: "httpclientfailonerror" },
                { name: tr(_A["httpclientiserror"]["name"]), description: tr(_A["httpclientiserror"]["description"]), ref: "httpclientiserror" },
                { name: tr(_A["httpclientgeterrorstring"]["name"]), description: tr(_A["httpclientgeterrorstring"]["description"]), ref: "httpclientgeterrorstring" },
                { name: tr(_A["httpclientxpathxml"]["name"]), description: tr(_A["httpclientxpathxml"]["description"]), ref: "httpclientxpathxml" },
                { name: tr(_A["httpclientxpathxmllist"]["name"]), description: tr(_A["httpclientxpathxmllist"]["description"]), ref: "httpclientxpathxmllist" },
                { name: tr(_A["httpclientxpathtext"]["name"]), description: tr(_A["httpclientxpathtext"]["description"]), ref: "httpclientxpathtext" },
                { name: tr(_A["httpclientxpathtextlist"]["name"]), description: tr(_A["httpclientxpathtextlist"]["description"]), ref: "httpclientxpathtextlist" },
                { name: tr(_A["httpclientxpathcount"]["name"]), description: tr(_A["httpclientxpathcount"]["description"]), ref: "httpclientxpathcount" },
                { name: tr(_A["httpclientxpathexists"]["name"]), description: tr(_A["httpclientxpathexists"]["description"]), ref: "httpclientxpathexists" },
                { description: tr("Open/close browser"), type: "group", name: "manual", icon: _G["manual"]["icon"], info: tr(_G["manual"]["info"]) },
                { name: tr(_A["openbrowser"]["name"]), description: tr(_A["openbrowser"]["description"]), ref: "openbrowser" },
                { name: tr(_A["closebrowser"]["name"]), description: tr(_A["closebrowser"]["description"]), ref: "closebrowser" }

                _MACRO_INSERT_ACTION_LIST_

            ]);

    var _A2G = {}

    var CurrentGroup = ""

    for(var i=0; i<_TaskCollection.length; i++)
    {
      var el = _TaskCollection.models[i]
      if(el.get("type") == "group")
      {
        CurrentGroup = el.get("name")
        _G[CurrentGroup]["name"] = el.get("description")
      }else
      {
        _A2G[el.get("ref")] = CurrentGroup
      }
    }

    var _PreserveMainPosition = new PreserveMainPosition();

    var _MultiSelectManager = new MultiSelectManager();

    var _SearchManager = new SearchManager();

    var _GobalModel = new GobalModel();

    var _SelectorModel = new SelectorModel();

    var _MainView = new MainView({collection: _TaskCollection, model: _GobalModel});

    var _ResourceCollection = new ResourceCollection();

    var _VariableCollection = new VariableCollection();

    var _GlobalVariableCollection = new GlobalVariableCollection();

    var _Schema = [];

    var _FunctionCollection = new FunctionCollection();

    var _EmbeddedModel = new EmbeddedModel();
 
    var _LabelCollection = new LabelCollection();

    var _ExpressionEditor = null;

    var ToolboxMaximizeCallback = null;

    var ActionHistory = []

    var BookmarkList = []

    var CurrentGroup = ""

    var CurrentTab = ""

    var BookmarkDrop = null;

    var RemoveBookmarkDrop = null;

    var BookmarkDrag = [];

    var OnHold = false;

    var CurrentDat = null;

    var CurrentParameters = null

    var RecaptchaV3ActionList = []

    /* Notifications */

    function BrowserAutomationStudio_Notify(subject, parameters)
    {
      if(subject == "download")
      {
        BrowserAutomationStudio_NotifyInternal(tr("File is downloading."), tr("BrowserAutomationStudio is downloading file. You can wait for it and obtain file name with \"Wait File Download\" action."), "#!/waitfiledownload")  
      }else if(subject == "upload")
      {
        BrowserAutomationStudio_NotifyInternal(tr("Open file dialog."), tr("BrowserAutomationStudio needs file input. Use \"Open File Result\" action to set upload file. This action must be used <strong>before</strong> dialog appear."), "#!/openfile")  
      }else if(subject == "prompt")
      {
        BrowserAutomationStudio_NotifyInternal(tr("Prompt dialog."), tr("Site has used prompt javascript function. Use \"Prompt Result\" in order to set result."), "#!/promptresult")  
      }else if(subject == "notification")
      {
        BrowserAutomationStudio_NotifyInternal(tr("Notifications."), tr("Site requests permission to show notifications. You can allow or deny it. This action must be used <strong>before</strong> notification is requested."), "#!/notification")  
      }else if(subject == "combobox")
      {
        if(typeof(window.WasComboboxNotification) == "undefined")
        {
          BrowserAutomationStudio_NotifyInternal(tr("Combobox."), tr("In order to automate combobox input you need to use keyboard - start typing option that you want to select and then hit ENTER." ), "")  
          window.WasComboboxNotification = true;
        }
      }else if(subject == "recaptchav3")
      {
        if(RecaptchaV3ActionList.indexOf(parameters) < 0)
        {
          RecaptchaV3ActionList.push(parameters)
          RecaptchaV3ActionList.sort()
        }
        $(".recaptcha-notify").remove()
        BrowserAutomationStudio_NotifyInternal(tr("Recaptcha V3."), tr("It seams that this site uses recaptcha v3(action: ") + "<strong>" + parameters + "</strong>" + tr("). You can resolve it with \"Recaptcha V3\" action."), "#!/recaptchav3", "recaptcha-notify")  
      }else if(subject == "search") 
      {
        BrowserAutomationStudio_NotifyInternal(tr(parameters), tr("Please select any element inside browser and click on the '") + tr(parameters) + tr("' action inside the menu that will appear."), "");
      }
    }
    
    function BrowserAutomationStudio_NotifyInternal(title, text, ref, addclass)
    {
      var finalclass = "toast-bottom-right"
      if(typeof(addclass) == "string")
      {
        finalclass += " " + addclass
      }
      toastr.info(text,title,
      {
        "positionClass": finalclass,
        timeOut: 60000,
        extendedTimeOut: 120000,
        closeButton: true,
        hideDuration: 1,
        onclick: function()
          {
            if(ref)
              _Router.navigate(ref, true);
          }
      })

    }

    function BrowserAutomationStudio_AskEnableModule(ModuleName, ModuleDescription)
    {
      bootbox.confirm(
      {
        title: tr("Enable module ") + ModuleDescription + "?",
        message: tr("In order to use this module, you need to enable it first. It will restart script.") + "<br><br><span style='color:gray;font-size:small'>" + tr("You can disable it later by using Menu -> Module manager.")  + "</span>",
        buttons:
        {
          confirm:
          {
            label: tr('Enable'),
            className: 'btn-success'
          },
          cancel:
          {
            label: tr('Cancel'),
            className: 'btn-primary'
          }
        },
        callback: function (result)
        {
          if(result == 1)
          {
            BrowserAutomationStudio_EnableModule(ModuleName)
          }
        }
      });
    }

    /* Preserve execute type */

    function BrowserAutomationStudio_MultiSelectReport(Report)
    {
      _MultiSelectManager.Report(Report)
    }

    var BrowserAutomationStudio_LastExecuteType = "executeandadd"

    function BrowserAutomationStudio_SetExecuteType()
    {
      if(typeof(BrowserAutomationStudio_LastExecuteType) == "undefined")
      {
        BrowserAutomationStudio_LastExecuteType = "executeandadd"
      }

      const $executeType = $('#executeType');
      $executeType.find(`[data-action="${BrowserAutomationStudio_LastExecuteType}"]`).trigger('click');
      $executeType.removeClass('open');
      $executeType.removeClass('show');
    }

    /* Test path */


    var BrowserAutomationStudio_TestPathLastPath = ""

    function BrowserAutomationStudio_TestPathInternal()
    {
      var clear_highlight = true;
      var path = "page().highlight('')!" + "\n" + "section_start(\"test\",-3)!"
      if($("#selector-input").length > 0 && $("#selector-input").val().length > 0)
      {

        var loader = new ResourceLoader();
        var p = GetPath(loader,true,true)
        path = p["path"] + ".highlight(_SELECTOR)!" + "\n" + "section_start(\"test\",-3)!"
        var selector = "";
        if(p["query"])
        {
          selector = ";_SELECTOR=" + p["query"] + ";"
        }
        path = loader.GetAdditionalData() + selector + path
        clear_highlight = false
      }
      
      if(typeof(BrowserAutomationStudio_TestPathLastPath) == "undefined")
        BrowserAutomationStudio_TestPathLastPath = ""


      if(BrowserAutomationStudio_TestPathLastPath != path)
      {
        BrowserAutomationStudio_TestPathFirstTry = false

        var prev = BrowserAutomationStudio_TestPathLastPath

        BrowserAutomationStudio_TestPathLastPath = path

        if(prev != "" && typeof(OnHold) == "boolean" && OnHold == false)
        {
          if(clear_highlight)
          {
            BrowserAutomationStudio_SetPathCount("0")
            BrowserAutomationStudio_ClearHighlight()  
          }else
          {
            BrowserAutomationStudio_SetPathCount("")
            BrowserAutomationStudio_Execute(path)
          }
        }
      }
    }

    function BrowserAutomationStudio_SetPathCount(count, path)
    {
      if(count.toString().length > 0)
      {
        $("#PathCount").css("visibility","visible")
        $("#PathCount").html(count)
        PreviewModel.deferUpdate(path);
      }else
      {
        $("#PathCount").css("visibility","hidden")
        PreviewModel.deleteImage();
      }
    }

    /* Bookmarks history */
    function BrowserAutomationStudio_DisableDragFunction(ev)
    {
        var img = document.createElement('img')
        img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
        ev.dataTransfer.setDragImage(img, 0, 0)
    }

    function BrowserAutomationStudio_SaveBookmarks()
    {
      if(CurrentTab == "bookmarks")
      {
        BookmarkList = []
        $(".leftactionpaneltitlebody a").toArray().forEach(function(el){
          var ref = $(el).attr("data-ref")
          BookmarkList.push(ref)
        })
        BrowserAutomationStudio_PreserveInterfaceState();
        
      }
      
    }

    function BrowserAutomationStudio_InstallBookmarks()
    {
      if(BookmarkDrag)
      {
        BookmarkDrag.forEach(function(el){
          el.destroy()
        })
      }
      BookmarkDrag = []
      $(".panel-group").toArray().forEach(function(el){
        el.ondragstart = BrowserAutomationStudio_DisableDragFunction
        BookmarkDrag.push(Sortable.create(el, {
          group: {
            name: 'input',
            pull: "clone",
            put: function(e){return false;}
          },
          draggable: ".toolbutton",
          onStart: function () {
            $(".tool").removeClass("toolhover")
          },

          onEnd: function () {
            $(".tool").removeClass("toolhover")
            BrowserAutomationStudio_SaveBookmarks();
          },
          ghostClass: 'ghost',

          sort: false,
          animation: 70
        }))
      })
    }


    function BrowserAutomationStudio_ShowHideHistory()
    {
      if(CurrentTab.length == 0)
      {
        BrowserAutomationStudio_RenderHistory();
        
        return;
      }

      if(CurrentTab == "bookmarks")
      {
        BrowserAutomationStudio_RenderHistory();
        return;
      }

      if(CurrentTab == "history")
      {
        BrowserAutomationStudio_HideHistoryBookmarks();
        return;
      }
      
    }

    function BrowserAutomationStudio_ShowHideBookmarks()
    {

      if(CurrentTab.length == 0)
      {
        BrowserAutomationStudio_RenderBookmarks();
        return;
      }

      if(CurrentTab == "history")
      {
        BrowserAutomationStudio_RenderBookmarks();
        return;
      }

      if(CurrentTab == "bookmarks")
      {
        BrowserAutomationStudio_HideHistoryBookmarks();
        return;
      }
    }

    function BrowserAutomationStudio_FillGotoLabels()
    {
      if(_LabelCollection.toJSON().length == 0)
        //$("#LabelList").html("<div style='margin-bottom:2px'>" + tr("No label found. Create one with 'Set label' action.") + "</div>")
        $("#LabelListInfo").html(_.template($('#info').html())({description: tr(`No label found. Create one with 'Set label' action.`), color: "gray"}))

      else
      {
        //$("#LabelList").html("<div style='margin-bottom:2px'>" + tr("Choose one of following labels") + ":</div>")
        $("#LabelListInfo").html(_.template($('#info').html())({description: tr(`Choose one of following labels`), color: "gray"}))
        _LabelCollection.toJSON().sort(function(a, b) {
          return a["name"].localeCompare(b["name"]);
        }).forEach(function(elem){
          var el = $('<button type="button" class="btn btn-default btn-sm"><i class="fa fa-tag"></i> <span class="text-label"></span></button>')
          if($("#LabelName").val() == elem["name"])
          {
            el.removeClass("btn-default").addClass("btn-primary")
          }
          el.find(".text-label").text(elem["name"])
          $(el).click(function(){
            $("#LabelName").val(elem["name"])
            $("#ok").click()
          })
          
          $("#LabelList").append(el)
        })
      }
    }

    function BrowserAutomationStudio_HideHistoryBookmarks()
    {
      $(".leftactionpaneltitledrop").hide()

      $(".leftactionpanel").hide()
      $(".mainscreen").css('margin-left','37px');
      CurrentTab = ""
      BrowserAutomationStudio_PreserveInterfaceState()
      $("#showhistory").removeClass("btn-primary").removeClass("btn-default").addClass("btn-default")
      $("#showbookmarks").removeClass("btn-primary").removeClass("btn-default").addClass("btn-default")

    }

    function BrowserAutomationStudio_RenderBookmarks()
    {
      $(".leftactionpaneltitledrop").hide()
      $(".leftactionpanel").show()
      $(".mainscreen").css('margin-left','259px');
        
      $(".leftactionpaneltitle").html('<div>' + tr('Bookmarks') + '</div><div style="color:gray">' + tr('Drag actions here') + '</div>')
      CurrentTab = "bookmarks"; 
      BrowserAutomationStudio_PreserveInterfaceState()
      

      $("#showhistory").removeClass("btn-primary").removeClass("btn-default").addClass("btn-default")
      $("#showbookmarks").removeClass("btn-primary").removeClass("btn-default").addClass("btn-primary")

      var render = ""
      BookmarkList.forEach(function(el){
        var name = ""
        if(_A[el])
        {
            name = tr(_A[el]["name"])
        }
        render += '<a class="toolbutton" href="#!/' + el + '" data-ref="' + el + '"><div class="tool"><span class="toolinner">' + name + '</span></div></a>'
      })


      $(".leftactionpaneltitlebody").html(render)

      if(BookmarkDrop)
        BookmarkDrop.destroy()

      BookmarkDrop = null

      if(RemoveBookmarkDrop)
        RemoveBookmarkDrop.destroy()

      RemoveBookmarkDrop = null

      var leftactionpaneltitledrop = $(".leftactionpaneltitledrop")
      if(leftactionpaneltitledrop.length > 0)
      {
        $(".leftactionpaneltitledrop")[0].ondragstart = BrowserAutomationStudio_DisableDragFunction

        RemoveBookmarkDrop = Sortable.create($(".leftactionpaneltitledrop")[0], {
          group: {
            name: 'output',
            put: function(e)
            {
              return true;
            }
          },
          onAdd: function (evt) {
            var el = evt.item;
            el.parentNode.removeChild(el);
          },
          onEnd: function () {
            $(".tool").removeClass("toolhover")
            BrowserAutomationStudio_SaveBookmarks();
          },
          animation: 70
        });
      }



      var leftactionpaneltitlebody = $(".leftactionpaneltitlebody")
      if(leftactionpaneltitlebody.length > 0)
      {
        $(".leftactionpaneltitlebody")[0].ondragstart = BrowserAutomationStudio_DisableDragFunction

        BookmarkDrop = Sortable.create($(".leftactionpaneltitlebody")[0], {
          group: {
            name: 'output',
            put: function(e){
              return true;
            }
          },

          onStart: function (e) {
            $(".leftactionpaneltitledrop").show()
          },

          onEnd: function (e) {
            $(".leftactionpaneltitledrop").hide()
            BrowserAutomationStudio_SaveBookmarks();

          },
          onAdd: function (e) {
            var item = e.item;
            if(BookmarkList.indexOf($(item).attr("data-ref")) >= 0)
              item.parentNode.removeChild(item);

          },

          ghostClass: 'ghost',
          animation: 70
        });
      }

    }

    function BrowserAutomationStudio_RenderHistory()
    {
      $(".leftactionpaneltitledrop").hide()
      $(".leftactionpanel").show()
      $(".mainscreen").css('margin-left','259px');
        
      $(".leftactionpaneltitle").html('<div>' + tr('History') + '</div><div style="color:gray">' + tr('Your recent actions') + '</div>')
      CurrentTab = "history";
      BrowserAutomationStudio_PreserveInterfaceState()
      $("#showhistory").removeClass("btn-primary").removeClass("btn-default").addClass("btn-primary")
      $("#showbookmarks").removeClass("btn-primary").removeClass("btn-default").addClass("btn-default")
      
      var data = "";

      _.each(ActionHistory, function(Action) {
        if(_A[Action])
        {
          data += '<a href="#!/' + Action + '"><div class="tool"><span class="toolinner">' + tr(_A[Action]["name"]) + '</span></div></a>'
        }
        
      })

      $(".leftactionpaneltitlebody").html(data)

      if(BookmarkDrop)
        BookmarkDrop.destroy()

      BookmarkDrop = null
      
    }




    function BrowserAutomationStudio_ReturnToMainFunction()
    {      
      $(".mainscreen *[data-group]").hide()
      $(".mainscreen *[data-group-all").show()
      $(".actions")[0].scrollTop = 0
      CurrentGroup = ""
    }

    function BrowserAutomationStudio_GotoGroup(group)
    {
        $(".mainscreen *[data-group]").hide()
        $(".mainscreen *[data-group=" + group + "]").show()
        $(".actions")[0].scrollTop = 0
        CurrentGroup = group
    }


    // Action history

    _Router.on("route", function(route, params) {
      if(route != "main" && _A[route] && _A[route]["class"] != "browser")
      {
        var index = ActionHistory.indexOf(route)
        if(index >= 0)
          ActionHistory.splice(index,1)

        ActionHistory.splice(0,0,route);
        ActionHistory = ActionHistory.slice(0,10);
        BrowserAutomationStudio_PreserveInterfaceState();
      }
    });

    function BrowserAutomationStudio_PreserveInterfaceState()
    {
      $(".toolbookmark").removeClass("toolbookmark")
      BookmarkList.forEach(function(name){
        var el = $(`.mainscreen [data-ref="${name}"]`)
        el.addClass("toolbookmark")          
      })
      BrowserAutomationStudio_SaveInterfaceState(JSON.stringify({
        recent: BasDialogsLib.store.save(), 
        bookmarks: BookmarkList,
        history: ActionHistory,
        tab: CurrentTab
      }));
    }

    function BrowserAutomationStudio_LoadInterfaceState(interface_json, scenario_json)
    {
      BrowserAutomationStudio_UpdatePreviewSettings(scenario_json);
      try
      {
        var interface_obj = JSON.parse(interface_json)
        BasDialogsLib.store.load(interface_obj["recent"])
        ActionHistory = interface_obj["history"]
        BookmarkList = interface_obj["bookmarks"]
        var tab = interface_obj["tab"] || ""
        if(tab == "history")
        {
          BrowserAutomationStudio_RenderHistory();
        }else if (tab == "bookmarks")
        {
          BrowserAutomationStudio_RenderBookmarks();
        }
        BookmarkList.forEach(function(name){
          var el = $(`.mainscreen [data-ref="${name}"]`)
          el.addClass("toolbookmark")          
        })
      }catch(e){}
    }


    function BrowserAutomationStudio_MaximizeCallback()
    {
      if(ToolboxMaximizeCallback)
      {
        ToolboxMaximizeCallback();
        ToolboxMaximizeCallback = null
      }
    }

    Backbone.history.start();

    $( document ).ready(function() {
        document.documentElement.style.zoom = _Z + '%';
        /*$( document.body ).click(function(){
          $("#searchinput").focus()  

        })*/

        /*$( document ).click(function(){
          $(".dropdown-menu-css-options").hide()
          $(".dropdown-menu-match-xpath-at-css-options").hide()
        })*/

        $(window).on('popstate', function(event) {
          $('.modal').modal('hide');
        });

        $( window ).resize(function() {
          $(".search").css("height", window.innerHeight * (100.0 / _Z) - 40 + "px");
          $(".actions").css("height", window.innerHeight * (100.0 / _Z) - 40 + "px");
          $(".leftactionpanel").css("height", window.innerHeight * (100.0 / _Z) - 45 + "px")
          $(".leftactionpaneltitlebody").css("min-height", window.innerHeight * (100.0 / _Z) - 95 + "px")

        });

        $(document).keyup(function(e) {
          if($("#NodeAll").length>0)
            return
          if (e.keyCode == 27)
          {
            if ($(".search").is(":visible"))
            {
              _SearchManager.hide();
            }
            /*if($('.modal.in').length > 0)
            {
              $('#' + $('.modal.in').attr("id")).modal('hide');
              return;
            }

            if($("#expressioneditor-container").is(":visible"))
            {
              $("#expressioneditor-cancel").click()
              return;
            }

            if($(".returntomain").is(":visible") && CurrentGroup != "")
            {
              BrowserAutomationStudio_ReturnToMainFunction();
              return;
            }
            
            var el = $("#backtomain")
            if(el.length > 0)
            {
              el[0].click()
            }*/
            
            }
          if (e.keyCode == 13)
          {
            if( e.target.nodeName == "TEXTAREA" ) return

            if($('.modal.in').length > 0)
            {
              return;
            }

            if($('#modalDialogContainer').length > 0) 
            {
              return;
            }

            if($("#expressioneditor-container").is(":visible"))
            {
              return;
            }

            if($(".returntomain").is(":visible") && CurrentGroup != "")
            {
              return;
            }
            
            var el = $("#ok")
            if(el.length > 0)
            {
              el[0].click()
            }

          }
        });
    });

    function Invalid(data)
    {
      bootbox.alert({title:tr("Unable to save action"), message:"<div class='text-danger'>" + data + "</div>"});
      BrowserAutomationStudio_TriggerEvent('toolbox.editFail', JSON.stringify(data));
    }

    function je(data)
    {
      return data
      .replace(new RegExp("\\\\","g"),"\\u005c")
      .replace(new RegExp("<","g"),"\\u003c")
      .replace(new RegExp(">","g"),"\\u003e")
      .replace(new RegExp("\"","g"),"\\u0022")
      .replace(new RegExp("'","g"),"\\u0027")
      .replace(new RegExp("&","g"),"\\u0026")
      .replace(new RegExp("{","g"),"\\u007b")
      .replace(new RegExp("}","g"),"\\u007d")
      .replace(new RegExp("\\n","g"),"\\n")
      .replace(new RegExp("\\r","g"),"\\r")
      .replace(new RegExp("\\)\\!","g"),"\\)\\!")
    }

    function jsort(json)
    {
      return json.sort(function (a, b) {
        if (a["name"].toLowerCase() > b["name"].toLowerCase()) {
          return 1;
        }
        if (a["name"].toLowerCase() < b["name"].toLowerCase()) {
          return -1;
        }
        return 0;
      })
    }

    function utf8_to_b64( str ) {
        return window.btoa(unescape(encodeURIComponent( str )));
    }

    function b64_to_utf8( str ) {
        return decodeURIComponent(escape(window.atob( str )));
    }

    function fromhex(hex,str)
    {
      var str = "";
      try
      {
        str = decodeURIComponent(hex.replace(/(..)/g,'%$1'))
      }
      catch(e)
      {
        str = hex
      }
      return str
    }


    function tohex(str,hex)
    {
      try
      {
        hex = unescape(encodeURIComponent(str)).split('').map(function(v){
          return v.charCodeAt(0).toString(16)
        }).join('')
      }
      catch(e){
        hex = str
      }
      return hex
    }


    function BrowserAutomationStudio_GetWaitCode()
    {
      var usewaiter = $("#use-waiter")

      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true")  
      {
        return "\n" + timeout_waiter() + "\nwait_async_load()!"
      }

      return "";
    }

    function BrowserAutomationStudio_MouseCustom(x,y)
    {

      if($("#Check2").is(':checked'))
      {
        return "_type(" + JSON.stringify("<CONTROL><MOUSELEFT>") + ",100)!";
      }

      var type = $("#Select").val();
      
      if(type == "left")
      {
        return "mouse(" + x + "," + y + ")!"
      }

      var text = ""

      /*if($("#MouseClickShift").is(':checked'))
      {
        text += "<SHIFT>"
      }

      if($("#MouseClickCtrl").is(':checked'))
      {
        text += "<CONTROL>"
      }*/

      

      if(type == "right")
      {
        text += "<MOUSERIGHT>" 
      }

      if(type == "double")
      {
        text += "<MOUSEDOUBLE>" 
      }


      return "_type(" + JSON.stringify(text) + ",100)!";


      //return "mouse_custom(" + x + "," + y + "," + JSON.stringify($("#Select").val()) + ", " + (($("#MouseClickShift").is(':checked')) ? "true" : "false") + ", " + (($("#MouseClickCtrl").is(':checked')) ? "true" : "false") + ")!";
    }

    function timeout_general()
    {
      var usewaiter = $("#use-timeout")
      if(usewaiter.length == 0)
        return ""
      var timeout_value = usewaiter.attr("data-value")
        if(timeout_value.length == 0)
          timeout_value = "0"

      timeout_value = parseInt(timeout_value) * 1000

      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true" && timeout_value != "0")  
      {
        return "general_timeout_next(" + timeout_value + ")"
      }

      return "" 
    }

    function timeout_solver()
    {
      var usewaiter = $("#use-timeout")
      if(usewaiter.length == 0)
        return ""
      var timeout_value = usewaiter.attr("data-value")
        if(timeout_value.length == 0)
          timeout_value = "0"

      timeout_value = parseInt(timeout_value) * 1000

      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true" && timeout_value != "0")  
      {
        return "solver_timeout_next(" + timeout_value + ")"
      }

      return "" 
    }

    function timeout_value()
    {
      var usewaiter = $("#use-timeout")
      if(usewaiter.length == 0)
        return 0
      var timeout_value = usewaiter.attr("data-value")
        if(timeout_value.length == 0)
          timeout_value = "0"

      timeout_value = parseInt(timeout_value) * 1000

      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true" && timeout_value != "0")  
      {
        return timeout_value
      }

      return 0 
    }

    function timeout_waiter()
    {
      var usewaiter = $("#use-timeout")
      if(usewaiter.length == 0)
        return ""
      var timeout_value = usewaiter.attr("data-value")
        if(timeout_value.length == 0)
          timeout_value = "0"

      timeout_value = parseInt(timeout_value) * 1000

      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true" && timeout_value != "0")  
      {
        return "waiter_timeout_next(" + timeout_value + ")"
      }

      return "" 
    }

    function BrowserAutomationStudio_GetTargetCode(loader)
    {
      var usetarget = $("#use-target")

      if(usetarget.length > 0 && usetarget.attr("data-enabled") == "true")  
      {
        var TargetUrl = GetInputConstructorValue("TargetUrl",loader);
        var TargetTabNumber = GetInputConstructorValue("TargetTabNumber",loader);
        return "\n_set_target({url:" + TargetUrl["updated"] + ",tab:" + TargetTabNumber["updated"] + "})\n"
      }

      return "";
    }

    function BrowserAutomationStudio_GetMoveJson(loader)
    {
      var usemove = $("#use-move")

      if(usemove.length > 0 && usemove.attr("data-enabled") == "true")  
      {
        var Speed = GetInputConstructorValue("Speed",loader);
        var Gravity = GetInputConstructorValue("Gravity",loader);
        var Deviation = GetInputConstructorValue("Deviation",loader);
        return ' {"speed": ' + Speed["updated"] + ',"gravity": ' +  Gravity["updated"] + ',"deviation": ' + Deviation["updated"] + '} '
      }

      return ' {} ';
    }

    function BrowserAutomationStudio_GetEmulationTarget(target, target2)
    {
      if(target && target2)
      {
        return `{x: (${target}), y: (${target2})}`;
      }else if(_SelectorModel.get("is_image"))
      {
        return '_image()';
      }else
      {
        return '_SELECTOR';
      }
    }

    function BrowserAutomationStudio_GetEmulationData(loader, target, target2)
    {
      var collectParams = function(names, arr = []){
        for(var name of names){
          var value = GetInputConstructorValue(name, loader)["updated"];
          if(value !== '""'){
            arr.push(`${name}: (${value})`);
          }
        }
        return arr;
      }

      var emulationSettings = collectParams(["time", "accuracy", "intensity"], ['useGeneral: true', `target: ${BrowserAutomationStudio_GetEmulationTarget(target, target2)}`]);

      var actions = collectParams(["sleep", "longElementMove", "shortElementMove", "scroll", "randomMove", "microMove", "goingBeyond", "moveAlongText"]);
      if(actions.length){
        emulationSettings.push(`useActions: {${actions.join(', ')}}`);
      }

      collectParams(["longMax", "shortMax", "miss", "delay", "targetScroll", "targetDelay", "filters", "hoverMode", "maxRepeatSkip", "overlapByPoints", "reverseScroll"], emulationSettings);

      return `{${emulationSettings.join(', ')}}`;
    }

    function BrowserAutomationStudio_GetScrollParams(loader)
    {
      var params = [];
      var usescrollparams = $("#use-scroll-params")

      if(usescrollparams.length > 0 && usescrollparams.attr("data-enabled") == "true")  
      {
        var scrollSpeed = GetInputConstructorValue("scrollSpeed", loader);
        params.push(`speed: (${scrollSpeed["updated"]})`);
        var minPause = GetInputConstructorValue("minPause", loader);
        var maxPause = GetInputConstructorValue("maxPause", loader);
        params.push(`pause: {min: (${minPause["updated"]}), max: (${maxPause["updated"]})}`);
        var moveChance = GetInputConstructorValue("moveChance", loader);
        var moveInScrollDirection = $("#moveInScrollDirection").is(':checked');
        var moveBeyond = GetInputConstructorValue("moveBeyond", loader);
        var moveMinDistance = GetInputConstructorValue("moveMinDistance", loader);
        var moveMaxDistance = GetInputConstructorValue("moveMaxDistance", loader);
        var moveSpeed = GetInputConstructorValue("moveSpeed", loader);
        var moveGravity = GetInputConstructorValue("moveGravity", loader);
        var moveDeviation = GetInputConstructorValue("moveDeviation", loader);
        params.push(`move: {chance: (${moveChance["updated"]}), in_scroll_direction: ${moveInScrollDirection}, beyond: (${moveBeyond["updated"]}), min_distance: (${moveMinDistance["updated"]}), max_distance: (${moveMaxDistance["updated"]}), speed: (${moveSpeed["updated"]}), gravity: (${moveGravity["updated"]}), deviation: (${moveDeviation["updated"]})}`);
      }

      return `{${params.join(', ')}}`;
    }

    function BrowserAutomationStudio_UsesWaitCode()
    {
      var usewaiter = $("#use-waiter")
      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true")  
        return true
      return false
    }

    function BrowserAutomationStudio_ThreadNumberEdit()
    {
        _Router.navigate("#!/threadnumber", true);
    }

    function BrowserAutomationStudio_RunFunction(FunctionName)
    {
        _Router.navigate("#!/executefunction", true);
        $("#FunctionName").val(FunctionName)
        _MainView.funcchange(FunctionName)
    }

    function BrowserAutomationStudio_OpenAction(Name)
    {
        if ($("#expressioneditor-container").is(":visible")) {
          $("#expressioneditor-cancel").click();
        }

        $('.modal').modal('hide');

        _Router.navigate("#!/" + Name, true);
    }
    
    function BrowserAutomationStudio_RunFunctionSeveralThreads(FunctionName)
    {
        _Router.navigate("#!/executefunctioninseveralthreads", true); 
        $("#FunctionName").val(FunctionName)
    }

    function BrowserAutomationStudio_RunFunctionAsync(FunctionName)
    {
        _Router.navigate("#!/asyncfunction_call", true); 
        $("#FunctionName").val(FunctionName)
        _MainView.funcchange(FunctionName)
    }

    function BrowserAutomationStudio_SuccessNumberEdit()
    {
        _Router.navigate("#!/successnumber", true);
    }

    function BrowserAutomationStudio_FailNumberEdit()
    {
        _Router.navigate("#!/failnumber", true);
    }

    function BrowserAutomationStudio_SaveControls(additional)
    {
      var loader = new ResourceLoader();
      var ControlsText = {s:_GobalModel.get("state"),v: 1}

      if(additional)
        ControlsText = Object.assign({},ControlsText, additional);

      ControlsText["f"] = _Filter.GetModels()
      
      var usewaiter = $("#use-waiter")
      if(usewaiter.length > 0 && usewaiter.attr("data-enabled") == "true")  
      {
        ControlsText["uw"] = "1"
      }else
      {
        ControlsText["uw"] = "0"
      }

      var usetarget = $("#use-target")
      if(usetarget.length > 0 && usetarget.attr("data-enabled") == "true")  
      {
        ControlsText["ut"] = "1"
      }else
      {
        ControlsText["ut"] = "0"
      }

      var usetimeout = $("#use-timeout")
      if(usetimeout.length > 0 && usetimeout.attr("data-enabled") == "true")  
      {
        ControlsText["uto"] = "1"
        ControlsText["uti"] = $("#timeout-val").html()
      }else
      {
        ControlsText["uto"] = "0"
      }

      var usemove = $("#use-move")
      if(usemove.length > 0 && usemove.attr("data-enabled") == "true")  
      {
        ControlsText["um"] = "1"
      }else
      {
        ControlsText["um"] = "0"
      }

      var useemulation = $("#use-emulation")
      if(useemulation.length > 0 && useemulation.attr("data-enabled") == "true")  
      {
        ControlsText["ue"] = "1"
      }else
      {
        ControlsText["ue"] = "0"
      }

      var usescrollparams = $("#use-scroll-params")
      if(usescrollparams.length > 0 && usescrollparams.attr("data-enabled") == "true")  
      {
        ControlsText["usp"] = "1"
      }else
      {
        ControlsText["usp"] = "0"
      }

      var ControlList = $("*[data-preserve=true]")
      var Elements = []

      for(var i = 0;i<ControlList.length;i++)
      {
        var el = $(ControlList[i])
        var NewElement = {}
        var id = el.attr("data-preserve-id")
        var type = el.attr("data-preserve-type")
        var json = el.attr("data-preserve-json")


        NewElement["id"] = id
        NewElement["type"] = type
        NewElement["json"] = json


        if(type == "constr")
        {
          if($("#" + id).attr("data-is-code-editor") == "true")
          {
            NewElement["data"] = window[id].Editor.getValue()
            NewElement["class"] = "expression"
          }
          else
          {
            NewElement["data"] = GetInputConstructorValue(id,loader)["original"]
            NewElement["class"] = $("*[data-selector-id=" + id + "]").html()
            NewElement["is_def"] = IsDefaultValueUsed(id)
          }
        }else if(type == "filter")
        {
          NewElement["data"] = _Filters.getFilters(id)
          NewElement["is_def"] = !NewElement["data"].length
        }else if(type == "var")
        {
          NewElement["data"] = $("#" + id).val()
          NewElement["is_def"] = IsDefaultVariableUsed(id)

        }else if(type == "select")
        {
          NewElement["data"] = $("#" + id).val()
          NewElement["is_def"] = IsDefaultSelectUsed(id)
        }else if(type == "check")
        {
          NewElement["data"] = $("#" + id).prop("checked")
          NewElement["is_def"] = IsDefaultCheckUsed(id)

        }else if(type == "text")
        {
          NewElement["data"] =  $("#" + id).val()
        }

        Elements.push(NewElement)
      }
      ControlsText["d"] = Elements
      if($(".path").length>0 || $(".path2").length>0)
      {
        var all = {}
        var json = _SelectorModel.toJSON()
        all["is_image"] = json["is_image"]
        if(json["is_image"])
        {
          //all["image_data"] = json["image_data"]
          /*all["scroll"] = json["scroll"]
          all["threshold"] = json["threshold"]*/
        }else
        {
          var pid = PreviewModel.sendPreview()
          var current = json["current"]
          if (pid) all["pid"] = pid

          if(json["is_ai_generated"] === true)
          {
            all["ig"] = true
            all["gd"] = json["ai_generated_name"]
          }
          
          all["css"] = json["css"]
          all["version"] = json["version"]
          all["css1"] = ("css1" in json) ? json["css1"] : ""
          all["css2"] = ("css2" in json) ? json["css2"] : ""
          all["css3"] = ("css3" in json) ? json["css3"] : ""
          all["current"] = current
          all["match"] = json["match"]
          all["xpath"] = json["xpath"]
          all["at"] = json["mousex"] + ", " + json["mousey"]

          if(current!="none")
            all[current] = $("#selector-input").val()

          
        }
        if($("#checkbox-wait-element").length > 0)
          all["we"] = $("#checkbox-wait-element").prop("checked")
        
        if($("#checkbox-fail-action").length > 0)
          all["fa"] = $("#checkbox-fail-action").prop("checked")

        ControlsText["p"] = all
      }
      // console.log(ControlsText);
      ControlsText = "/*Dat:" + utf8_to_b64(JSON.stringify(ControlsText)) +  "*/\n";
      BasDialogsLib.store.addElements(Elements);
      return ControlsText;
    }

    function BrowserAutomationStudio_EditStart(dataraw, metadata)
    {
      _SelectorModel.set("is_editing",true)
      var data = JSON.parse(b64_to_utf8(dataraw))
      CurrentDat = data

      _SelectorModel.set("is_ai_generated",false)
      _SelectorModel.set("ai_generated_name","")
      
      if("p" in data)
      {
        var selector = data["p"]
        _SelectorModel.set("is_image",selector["is_image"])

        if(selector["is_image"])
        {
          //console.log(data["d"])
          //_SelectorModel.set("image_data",data["d"]["ImageBase64"]["data"])
          /*_SelectorModel.set("threshold",selector["threshold"])
          _SelectorModel.set("scroll",selector["scroll"])*/
        }else
        {
          if(selector["ig"] === true)
          {
            _SelectorModel.set("is_ai_generated",true)
            _SelectorModel.set("ai_generated_name",selector["gd"])
          }

          _SelectorModel.set("css",selector["css"])

          if("css1" in selector)
            _SelectorModel.set("css1",selector["css1"])
          else
            _SelectorModel.set("css1","")
          
          if("css2" in selector)
            _SelectorModel.set("css2",selector["css2"])
          else
            _SelectorModel.set("css2","")
          
          if("css3" in selector)
            _SelectorModel.set("css3",selector["css3"])
          else
            _SelectorModel.set("css3","")

          _SelectorModel.set("match",selector["match"])
          _SelectorModel.set("xpath",selector["xpath"] || "")
          var split = selector["at"].split(",")
          _SelectorModel.set("mousex",split[0].replace(/\s/g, ''))
          _SelectorModel.set("mousey",split[split.length - 1].replace(/\s/g, ''))
          _SelectorModel.set("current",selector["current"])
          _SelectorModel.set("version",selector["version"])
        }

      }

      $('.modal').modal('hide');
      _GobalModel.attributes["isedit"] = true
      _GobalModel.set({ state: data["s"] });
      if (metadata && typeof metadata === "string") {
        try {
          const { preview } = JSON.parse(metadata);
          PreviewModel.edit(preview);
        } catch (e) {
          console.log('Error while parsing edit metadata:', e);
        }
      }

      try
      {
        for(var i = 0;i<data["d"].length;i++)
        {
          var el = data["d"][i]

          if(el.id == "FunctionName")
          {

            _MainView.funcchange(el.data)
            break;
          }
        }
      }catch(e)
      {

      }

      if(["cachemaskallow","cachemaskdeny","requestmaskdeny","requestmaskallow","getstatus","isloaded","getfromcache","getallcache","waitload"].includes(data["s"])) // Replacing masks with filters where needed
      {
        try
        {
          if(!data["d"].some((ell) => ell.id == 'urlFilters'))
          {
            let ell = data["d"].find((ell) => ell.id === (data["s"] === "waitload" ? 'Wait' : 'Value'))

            if(ell && ell.data !== "*")
            {
              _Filters.addFilter('urlFilters', {match: true, type: 'Mask', value: {
                data: ell.data,
                class: ell.class
              }})
            }
          }
        }catch(e)
        {

        }
      }

      $("#executeType").hide()

      if("p" in data)
      {
        if(typeof(selector["we"]) != "undefined")
        {
          $("#checkbox-wait-element").prop("checked", selector["we"]);
        }
        
        if(typeof(selector["fa"]) != "undefined")
        {
          $("#checkbox-fail-action").prop("checked", selector["fa"]);
        }

        if(selector["ig"] === true)
        {
          $("#selector-ai").show()
          $("#selector-ai-name").text(selector["gd"])
        }

      }

      if(data["uw"] == "1")
      {
        $("#use-waiter").attr("data-enabled","true")
        $("#use-waiter").removeClass().addClass("use-waiter-enabled")
      }else if(data["uw"] == "0")
      {
        $("#use-waiter").attr("data-enabled","false")
        $("#use-waiter").removeClass().addClass("use-waiter-disabled")
      }

      if(data["ut"]  == "1")
      {
        $("#use-target").attr("data-enabled","true")
        $("#use-target").removeClass().addClass("use-target-enabled")
        $("#target-data").show()
      }else if(data["ut"] == "0")
      {
        $("#use-target").attr("data-enabled","false")
        $("#use-target").removeClass().addClass("use-target-disabled")
        $("#target-data").hide()
      }

      if(data["um"]  == "1")
      {
        $("#use-move").attr("data-enabled","true")
        $("#use-move").removeClass().addClass("use-move-enabled")
        $("#move-data").show()
      }else if(data["um"] == "0")
      {
        $("#use-move").attr("data-enabled","false")
        $("#use-move").removeClass().addClass("use-move-disabled")
        $("#move-data").hide()
      }

      if(data["ue"]  == "1")
      {
        $("#use-emulation").attr("data-enabled","true")
        $("#use-emulation").removeClass().addClass("use-emulation-enabled")
        $("#emulation-data").show()
      }else if(data["ue"] == "0")
      {
        $("#use-emulation").attr("data-enabled","false")
        $("#use-emulation").removeClass().addClass("use-emulation-disabled")
        $("#emulation-data").hide()
      }

      if(data["usp"]  == "1")
      {
        $("#use-scroll-params").attr("data-enabled","true")
        $("#use-scroll-params").removeClass().addClass("use-scroll-params-enabled")
        $("#scroll-params-data").show()
      }else if(data["usp"] == "0")
      {
        $("#use-scroll-params").attr("data-enabled","false")
        $("#use-scroll-params").removeClass().addClass("use-scroll-params-disabled")
        $("#scroll-params-data").hide()
      }

      var timeout_value = 0
      if(data["uto"]  == "1")
        timeout_value = parseInt(data["uti"])
      

      $("#use-timeout").attr("data-value", (typeof(timeout_value) != "undefined" && timeout_value > 0) ? timeout_value : "0")
                        .attr("class", ((typeof(timeout_value) != "undefined" && timeout_value > 0) ? "" : "use-timeout-disabled") + " trtitle")
                        .attr("data-enabled", (typeof(timeout_value) != "undefined" && timeout_value > 0) ? "true" : "false")

      $("#timeout-val").html((typeof(timeout_value) != "undefined" && timeout_value > 0) ? ("" + timeout_value) : "")
      if(typeof(timeout_value) != "undefined" && timeout_value > 0)
      {
        $("#timeout-is-default").hide()
      }else
      {
        $("#timeout-is-default").show()
      }


      
      for(var i = 0;i<data["d"].length;i++)
      {
        var el = data["d"][i]
        
        var id = el["id"]
        var type = el["type"]
        var _data = el["data"]

        if(id == "ImageBase64")
        {
          _SelectorModel.set("image_data",_data)
          $("#ImageData").attr("src","data:image/png;base64," + _SelectorModel.get("image_data"))
        }

        if(type == "constr")
        {
          
          var _class = el["class"]
          $("*[data-preserve-id=" + id + "] a." + _class).click()
          $("*[data-preserve-id=" + id + "]").attr("data-preserve-json",el["json"])
          if(_class == "int")
          {
            $("#" + id + "_number").val(parseInt(_data))
          }else
          {
            if($("#" + id).attr("data-is-code-editor") == "true")
            {
              if(!window[id])
                window[id] = {Editor: null, InitialValue: ""}
              if(window[id].Editor)
                window[id].Editor.setValue(_data)
              window[id].InitialValue = _data

            }
            else
            {
              $("#" + id).val(_data)
              $("#" + id).trigger("change")
            }
          }

        }else if(type == "filter")
        {
          _Filters.restore(id, _data)
        }else if(type == "check")
        {
          var attr = $("#" + id).attr("onclick")
          if(typeof(attr) == "string" && attr.length > 0)
          {
            if($("#" + id).prop("checked") != _data)
              $("#" + id).trigger("click")
          }else
          {
            $("#" + id).prop("checked",_data);
            $("#" + id).trigger("change")
          }
        }else if(type == "select")
        {
          $("#" + id).val(_data);
          SelectChange(id, _data)
        }else
        {
          $("#" + id).val(_data);
          if(type === "var")
          {
            $("#" + id).trigger("input")
          }
        }

      }
      _MainView.tablechange();
      if(typeof(data["f"]) != "undefined" && data["f"])
        _Filter.RestoreModels(data["f"])

      if(_MainView.model.get("state") == "goto")
      {
        BrowserAutomationStudio_FillGotoLabels()
      }

      if (data['d'].some((el) => $(`#${el.id}`).data('is-code-editor') || el.id === 'NodeVersionList')) {
        if (!isEditorInstalled()) {
          _MainView.once('monacoEditorCreated', () => {
            BrowserAutomationStudio_TriggerEvent('toolbox.editStarted');
          });
        } else {
          BrowserAutomationStudio_TriggerEvent('toolbox.editStarted');
        }
      } else {
        BrowserAutomationStudio_TriggerEvent('toolbox.editStarted');
      }
    }

    function BrowserAutomationStudio_EditEnd()
    {
      PreviewModel.reset();
      _GobalModel.attributes["isedit"] = false
      bootbox.hideAll()
      $('.modal').modal('hide')
      if(typeof(BrowserAutomationStudio_IsUpdatingAllActions) == "boolean" && BrowserAutomationStudio_IsUpdatingAllActions)
      {
        //If updating project action, goto blank screen instead of main
        //This significantly increaces speed.
        //If same state will be left, may lead to prject corruption
        _GobalModel.set({ state: "___none" });
      }else
      {
        _GobalModel.set({ state: "main" });
      }
      BrowserAutomationStudio_TriggerEvent('toolbox.editEnd');
    }

    function BrowserAutomationStudio_EditSaveStart()
    {
      if($("#node-check").length == 1)
      {
        $("#node-check").click()
      }else
        _MainView.accept()
    }


    function BrowserAutomationStudio_SetResources(resources, additionalResources)
    {
      const additionalSource = JSON.parse(additionalResources);
      const source = JSON.parse(resources);
      _ResourceCollection.reset();

      for (let i = 0; i < source.length; i++) {
        _ResourceCollection.add({ name: source[i]["name"], description: source[i]["description"], type: source[i]["type"] });
      }

      for (let i = 0; i < additionalSource.length; i++) {
        _ResourceCollection.add({ name: additionalSource[i]["name"], description: additionalSource[i]["name"] });
      }

      BasDialogsLib.store.addResource([...additionalSource, ...source]);
    }

    function BrowserAutomationStudio_SetGlobalVariables(globalVariables)
    {
      const source = JSON.parse(globalVariables);
      _GlobalVariableCollection.reset();

      source.sort((a, b) => a["name"] >= b["name"]);
      for (let i = 0; i < source.length; i++) {
        _GlobalVariableCollection.add({ name: source[i]["name"], global: true });
      }

      BasDialogsLib.store.addVariable(source, true);
    }

    function BrowserAutomationStudio_SetVariables(variables)
    {
      const source = JSON.parse(variables);
      _VariableCollection.reset();

      let addedCycleIndex = false;

      for (let i = 0; i < source.length; i++) {
        if (source[i]["name"] === "CYCLE_INDEX") {
          addedCycleIndex = true;
        }
      }

      if (!addedCycleIndex) {
        source.push({ name: "CYCLE_INDEX" });
      }

      source.sort((a, b) => a["name"] >= b["name"]);
      for (let i = 0; i < source.length; i++) {
        _VariableCollection.add({ name: source[i]["name"], global: false });
      }

      BasDialogsLib.store.addVariable(source, false);
    }

    function BrowserAutomationStudio_SetFunctions(functions)
    {
      const source = JSON.parse(functions);
      _FunctionCollection.reset();

      for (let i = 0; i < source.length; i++) {
        try {
          const dat = JSON.parse(JSON.parse(source[i]["name"]));
          const prop = { name: dat["n"] };
          if (dat["fd"]) {
            prop["properties"] = JSON.parse(dat["fd"]);
          }
          _FunctionCollection.add(prop);
        } catch (e) { }
      }

      BasDialogsLib.store.addFunction(source);
    }

    function BrowserAutomationStudio_SetSchema(schema)
    {
      _Schema = JSON.parse(schema)
      _Filter.Install(_Schema)
      _MainView.render()
    }

    function BrowserAutomationStudio_SetEmbeddedData(data, languages)
    {
      _EmbeddedModel.ParseData(data, languages)
    }

    function BrowserAutomationStudio_SetCurrentFunction(FunctionData)
    {
      CurrentParameters = JSON.parse(FunctionData)["p"].map(function(el){return el["name"]})
      if(CurrentParameters.length == 0)
        CurrentParameters = null
    }

    function BrowserAutomationStudio_SetLabels(labels)
    {
      _LabelCollection.reset()
      var res = JSON.parse(labels)

      for(var i = 0;i < res.length;i+=1)
      {
        _LabelCollection.add({name:res[i]["name"]})
      }
    }

    function ParameterNotSpecified(name)
    {
      Invalid(tr("The parameter \"") + tr(name) + tr("\" is not specified"));
    }

    function GetInputConstructorValueFilename(id, loader)
    {

      try
      {
        var Value = $("#" + id).val()
        var Match = Value.match(/^{{([^}]+)}}$/)
        if(Match && typeof(_ResourceCollection.toJSON().find(function(el){return el["name"] == Match[1] && el["type"] == "LinesFromFile"})) != "undefined")
        {
          
          return {"original": Value, "updated": `RInfo("${Match[1]}","Location")`}
        }

      }catch(e)
      {
        return GetInputConstructorValue(id, loader)
      }
      return GetInputConstructorValue(id, loader)

    }

    function GetInputConstructorValueResourceGroup(id, loader)
    {

      try
      {
        var Value = $("#" + id).val()
        var Match = Value.match(/^{{([^}]+)}}$/)
        if(Match && _ResourceCollection.toJSON().some(function(el){return el["name"] == Match[1]}))
        {
          return {"original": Value, "updated": `_db_get_resource_group_id("${Match[1]}")`}
        }

      }catch(e)
      {
        return GetInputConstructorValue(id, loader)
      }
      return GetInputConstructorValue(id, loader)

    }

    function GetInputConstructorValue(id, loader)
    {
        
        var ResTextTypeIsString = $("*[data-selector-id=" + id + "]").html() == "string";
        var ResTextTypeIsInt = $("*[data-selector-id=" + id + "]").html() == "int";
        var ResTextTypeIsEditor = $("*[id=" + id + "][data-is-code-editor=true]").length == 1
        var ForceString = $("*[id=" + id + "][data-force-string=true]").length == 1


        var ResText;
        if(ResTextTypeIsEditor)
          ResText = window[id].Editor.getValue();
        else if(ResTextTypeIsString)
        {
          ResText = $("#" + id).val();
          if($("#" + id).attr("data-replace-linebreaks"))
          {
            ResText = ResText.replace(/\r?\n/g, "\r\n")
          }
        }
        else if(ResTextTypeIsInt)
          ResText = $("#" + id + "_number").val();
        else
          ResText = $("#" + id).val();

        // console.log(ResTextTypeIsEditor)

        loader.SetIsString((ResTextTypeIsString && !ResTextTypeIsEditor) || ForceString)
        var ResTextUpdated = loader.Resolve(ResText+"");
        if(ResTextUpdated.length == 0)
          ResTextUpdated = "\"\""
        return {"updated" : ResTextUpdated, "original" : ResText, "isString": ResTextTypeIsString};
    }

    function IsDefaultValueUsed(id)
    {
      const type = $(`*[data-selector-id=${id}]`).html();
      if(typeof type === 'string' && (type === "string" || type === "int" || type === "expression"))
      {
        const input = $(`#${id}${type === "int" ? "_number" : ""}`)[0];
        if(input == null)
          return false
        if(type === "int" && input.hasAttribute("data-no-default") && input.getAttribute("data-no-default") == "true")
        {
          return false
        }
        return input.value === input.defaultValue;
      }
      return false;
    }

    function IsDefaultCheckUsed(id)
    {
      const input = $(`#${id}`);
      let result = true
      try
      {
        result = input.attr("data-default") === input.prop("checked").toString();
      }catch(e)
      {

      }

      return result;
    }

    function IsDefaultSelectUsed(id)
    {
      const input = $(`#${id}`);
      let result = true
      try
      {
        result = input.find("option[data-default]").attr("value") === input.val();
      }catch(e)
      {

      }
      return result;
    }

    function IsDefaultVariableUsed(id)
    {
      const input = $(`#${id}`)[0];
      return input != null && input.value === input.defaultValue;
    }

    function GetPath(loader, need_all, need_visible, selector_index)
    {
      if(_SelectorModel.get("is_image"))
      {
        var waitelement = true
        var failaction = true
        if($("#checkbox-wait-element").length > 0)
        {
          waitelement = $("#checkbox-wait-element").prop("checked") 
        }

        if($("#checkbox-fail-action").length > 0)
        {
          failaction = $("#checkbox-fail-action").prop("checked") 
        }

        var scroll = 'data["scroll"] = ' + GetInputConstructorValue("Scroll",loader)["updated"] + ' == "scroll";'
        var threshold = 'data["threshold"] = parseInt(' + GetInputConstructorValue("Threshold",loader)["updated"] + ');'
        var timeout = timeout_value()
        if(timeout == 0)
          timeout = 60000
        timeout = 'data["timeout"] = ' + timeout + ';'

        var dataraw = GetInputConstructorValue("ImageBase64",loader)["updated"]
        
        var data = 'data["data"] = ' + dataraw + ';'

        var rawnodata = scroll + threshold + timeout
        var raw = rawnodata + data

        var resultwaiter = ""
        var resultpath = ""

        resultwaiter = "var data = {fail:" + failaction + ",wait:" + waitelement + "};" + raw + "_wait_image(data)!"
        resultpath = "_image()"

        return {path: resultpath,waiter: resultwaiter, imagesearch:true}

      }else if(_SelectorModel.get("version") == "1.0" || $("#selector-input").val().indexOf(">CSS>") >= 0 || $("#selector-input").val().indexOf(">MATCH>") >= 0|| $("#selector-input").val().indexOf(">FRAME>") >= 0|| $("#selector-input").val().indexOf(">XPATH>") >= 0 || $("#selector-input").val().indexOf(">AT>") >= 0 || _SelectorModel.get("current") == "xpath")
      {
        //New selectors
       
        var raw = $("#selector-input").val()

        if(typeof(selector_index) != "undefined")
        {
          raw += ">AT>" + selector_index
        }

        var current = _SelectorModel.get("current")
        if(current == "none")
          return {path:"page()",waiter:"",raw:"", querycss: je(_SelectorModel.get("css")), querycss2: je(_SelectorModel.get("css2")), querycss3: je(_SelectorModel.get("css3")), querymatch: je(_SelectorModel.get("match")), queryxpath: je(_SelectorModel.get("xpath"))}

        if(current == "at")
          return {path:"position(" + raw + ")",waiter:"", raw:"position " + raw, querycss: je(_SelectorModel.get("css")), querycss2: je(_SelectorModel.get("css2")), querycss3: je(_SelectorModel.get("css3")), querymatch: je(_SelectorModel.get("match")), queryxpath: je(_SelectorModel.get("xpath"))}

        loader.SetIsString(true)
        var raw_not_escaped = raw
        raw = loader.Resolve(raw+"")


        var waiter_func_name = "wait_element";
        if((typeof(need_visible) != "undefined" && need_visible))
        {
          waiter_func_name = "wait_element_visible"
        }

        var waitelement = true
        var failaction = true
        if($("#checkbox-wait-element").length > 0)
        {
          waitelement = $("#checkbox-wait-element").prop("checked") 
        }

        if($("#checkbox-fail-action").length > 0)
        {
          failaction = $("#checkbox-fail-action").prop("checked") 
        }
        

        var querycss = _SelectorModel.get("css")
        var querycss2 = _SelectorModel.get("css2")
        var querycss3 = _SelectorModel.get("css3")
        var querymatch = _SelectorModel.get("match")
        var queryxpath = _SelectorModel.get("xpath")

        if(current == "css")
        {
          querycss = raw
          querymatch = loader.Resolve(querymatch+"")
          queryxpath = loader.Resolve(queryxpath+"")
        }
        if(current == "match")
        {
          querymatch = raw
          querycss = loader.Resolve(querycss+"")
          queryxpath = loader.Resolve(queryxpath+"")
        }
        if(current == "xpath")
        {
          queryxpath = raw
          querycss = loader.Resolve(querycss+"")
          querymatch = loader.Resolve(querymatch+"")
        }

        var resultpath = "get_element_selector(_SELECTOR, " + (typeof(need_all) != "undefined" && need_all).toString() + ")"
        var resultwaiter = "_SELECTOR = " + raw + ";"

        if(waitelement == true && failaction == true)
        {
          resultwaiter += timeout_waiter() + "\n" + waiter_func_name + "(_SELECTOR)!"
        }else if(waitelement == false && failaction == true)
        {
          resultwaiter += "waiter_timeout_next(1000)\n" + waiter_func_name + "(_SELECTOR)!"
          resultpath += ".nowait()"
        }else if(waitelement == true && failaction == false)
        {
          resultwaiter += timeout_waiter() + "\nwaiter_nofail_next();\n" + waiter_func_name + "(_SELECTOR)!"
          resultpath += ".nowait()"
        }else if(waitelement == false && failaction == false)
        {
          resultwaiter += "waiter_timeout_next(1000)\nwaiter_nofail_next();\n" + waiter_func_name + "(_SELECTOR)!"
          resultpath += ".nowait()"
        }

        return {path: resultpath,waiter: resultwaiter,raw:"css " + raw_not_escaped, querycss: querycss, querycss2: querycss2, querycss3: querycss3, querymatch: querymatch, queryxpath: queryxpath, query: raw}
        
       
      }
      else
      {
        //Old selectors
        var current = _SelectorModel.get("current")
        if(current == "none")
          return {path:"page()",waiter:"",raw:"", querycss: '"' + je(_SelectorModel.get("css")) + '"', querycss2: '"' + je(_SelectorModel.get("css2")) + '"', querycss3: '"' + je(_SelectorModel.get("css3")) + '"', querymatch: '"' + je(_SelectorModel.get("match")) + '"'}

        var raw_not_escaped = $("#selector-input").val()
        var raw_original = $("#selector-input").val()
        var index = ""

        var index_match = raw_not_escaped.match(/\s*\<\s*([^\>\<]+)\s*\>\s*$/)
        if(index_match)
        {
          index = index_match[1]
          raw_not_escaped = raw_not_escaped.replace(/\<\s*([^\>\<]+)\s*\>\s*$/,"")
        }

        var raw = raw_not_escaped

        var frames_array = []
        var frames_path = ""
        while(true)
        {
          var indexcss = raw.indexOf(">css>")
          var indexmatch = raw.indexOf(">match>")

          if(indexcss < 0 && indexmatch < 0)
            break;

          if(indexcss >= 0 && (indexmatch < 0 || indexcss < indexmatch))
          {
            var frame_item = raw.substring(0,indexcss)
            

            loader.SetIsString(true)
            frame_item = loader.Resolve(frame_item+"")
            frames_array.push("{type: \"css\", data: " + frame_item + "}");
            
            frames_path += "frame_css(" + frame_item + ")."
            indexcss += ">css>".length
            raw = raw.substring(indexcss,raw.length)
            continue;
          }

          if(indexmatch >= 0 && (indexcss < 0 || indexmatch < indexcss))
          {
            var frame_item = raw.substring(0,indexmatch)

            loader.SetIsString(true)
            frame_item = loader.Resolve(frame_item+"")     
            frames_array.push("{type: \"match\", data: " + frame_item + "}");
            
            frames_path += "frame_match(" + frame_item + ")."
            indexmatch += ">match>".length
            raw = raw.substring(indexmatch,raw.length)
            continue;
          }

        }

        loader.SetIsString(true)
        raw = loader.Resolve(raw+"")

        if(index.length > 0)
        {
          loader.SetIsString(false)
          index = loader.Resolve(index+"")
        }
        

        if(current == "css")
        {
          var path = "css"

          if(index.length > 0 || (typeof(need_all) != "undefined" && need_all))
            path = "all"

          path += "(" + raw + ")"

          if(index.length > 0)
            path += ".at(" + index + ")"

          var waiter_func_name = "wait_css";
          if((typeof(need_visible) != "undefined" && need_visible))
          {
            waiter_func_name = "wait_css_visible"
          }

          var raw_object = ["raw:" + raw, "frames:" + "[" + frames_array.join(",") + "]"]
          
          if(index.length > 0)
            raw_object.push("index:" + index)

          raw = "{" + raw_object.join(",") + "}"

          return {path:frames_path + path,waiter: timeout_waiter() + "\n" + waiter_func_name + "(" + raw + ")!",raw:"css " + raw_not_escaped, querycss: '"' + je(raw_original) + '"', querycss2: '"' + je(_SelectorModel.get("css2")) + '"', querycss3: '"' + je(_SelectorModel.get("css3")) + '"', querymatch: '"' + je(_SelectorModel.get("match")) + '"'}
        }

        if(current == "match")
        {
          var path = "match"

          if(index.length > 0 || (typeof(need_all) != "undefined" && need_all))
            path = "match_all"

          path += "(" + raw + ")"

          if(index.length > 0)
            path += ".at(" + index + ")"

          var waiter_func_name = "wait_content";
          if((typeof(need_visible) != "undefined" && need_visible))
          {
            waiter_func_name = "wait_content_visible"
          }

          var raw_object = ["raw:" + raw, "frames:" + "[" + frames_array.join(",") + "]"]
          
          if(index.length > 0)
            raw_object.push("index:" + index)

          raw = "{" + raw_object.join(",") + "}"

          return {path:frames_path + path,waiter: timeout_waiter() + "\n" + waiter_func_name + "(" + raw + ")!", raw:"match " + raw_not_escaped, querycss: '"' + je(_SelectorModel.get("css")) + '"', querycss2: '"' + je(_SelectorModel.get("css2")) + '"', querycss3: '"' + je(_SelectorModel.get("css3")) + '"', querymatch: '"' + je(raw_original) + '"'}
        }

        if(current == "at")
          return {path:"position(" + raw + ")",waiter:"", raw:"position " + raw_not_escaped, querycss: '"' + je(_SelectorModel.get("css")) + '"', querycss2: '"' + je(_SelectorModel.get("css2")) + '"', querycss3: '"' + je(_SelectorModel.get("css3")) + '"', querymatch: '"' + je(_SelectorModel.get("match")) + '"'}

        return {path:"page()",waiter:"",raw:"", query: "", querycss: '"' + je(_SelectorModel.get("css")) + '"', querycss2: '"' + je(_SelectorModel.get("css2")) + '"', querycss3: '"' + je(_SelectorModel.get("css3")) + '"', querymatch: '"' + je(_SelectorModel.get("match")) + '"'}
      }
    }

    function InsertAtCaret(areaId,text)
    {
        var txtarea = document.getElementById(areaId);
        var scrollPos = txtarea.scrollTop;
        var strPos = 0;
        var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
            "ff" : (document.selection ? "ie" : false ) );
        if (br == "ie") {
            //txtarea.focus();
            var range = document.selection.createRange();
            range.moveStart ('character', -txtarea.value.length);
            strPos = range.text.length;
        }
        else if (br == "ff") strPos = txtarea.selectionStart;

        var front = (txtarea.value).substring(0,strPos);
        var back = (txtarea.value).substring(strPos,txtarea.value.length);
        txtarea.value=front+text+back;
        strPos = strPos + text.length;
        if (br == "ie") {
            //txtarea.focus();
            var range = document.selection.createRange();
            range.moveStart ('character', -txtarea.value.length);
            range.moveStart ('character', strPos);
            range.moveEnd ('character', 0);
            range.select();
        }
        else if (br == "ff") {
            txtarea.selectionStart = strPos;
            txtarea.selectionEnd = strPos;
            //txtarea.focus();
        }
        txtarea.scrollTop = scrollPos;
    }

    function ResourceLoader()
    {
      var AdditionalData = "";
      var IsString = true;
      var IsPrerender = false;
      var IsJsonStringify = false;

      this.Resolve = function(str)
      {
        var res = this.ResolveResources(str);
        //res = this.ResolveVariables(res);
        return res;
      }

      this.SetIsString = function(value)
      {
        IsString = value;
      }

      this.SetIsPrerender = function(value)
      {
        IsPrerender = value;
      }

      this.SetIsJsonStringify = function(value)
      {
        IsJsonStringify = value;
      }

      this.ResolveVariables = function(str)
      {
        var res = "";
        var reg = new RegExp("\\[\\[([^\\]]+)\\]\\]")
        var rest = str
        var all = ""
        while(true)
        {
          all = res
          if(res.length > 0 && rest.length > 0)
            all += ((IsString) ? " + " : "")

          if(rest.length > 0)
            all += ((IsString) ? "\"" : "") + ((IsString) ? je(rest) : rest) + ((IsString) ? "\"" : "")

          var match = reg.exec(rest)
          if(!match)
            break;

          var i = match.index
          var resnew = "";
          if(i>0)
          {
            resnew += (IsString) ? "\"" : ""
            resnew += (IsString) ? je(rest.substr(0,i)) : rest.substr(0,i)
            resnew += (IsString) ? "\" + " : ""
          }

          if(IsPrerender)
            resnew += match[0]
          else
          {
            var match_add = match[1]
            if(match_add.indexOf("GLOBAL:") >= 0)
            {
              match_add = "JSON.parse(P(\"basglobal\", " + JSON.stringify(match_add.substr(7)) + ") || '\"\"')";
            }else
            {
              match_add = "VAR_" + match_add
            }

            if(IsJsonStringify)
            {
              match_add = "JSON.stringify(" + match_add + ")"
            }
            resnew += match_add
            
          }


          i = match.index + match[0].length
          var j = rest.length - i
          if(j>0)
          {
            rest = rest.substr(i,j)
          }else
            rest = ""

          if(res.length == 0)
            res = resnew
          else
            res +=  ((IsString) ? " + " : "") + resnew


        }
        return all;
      }

      this.ResolveResources = function(str)
      {
        var res = "";
        var reg = new RegExp("\\{\\{([^\\}]+)\\}\\}")
        var rest = str
        var all = ""
        while(true)
        {
          all = res
          if(res.length > 0 && rest.length > 0)
            all += ((IsString) ? " + " : "")

          if(rest.length > 0)
            all += this.ResolveVariables(rest)

          var match = reg.exec(rest)
          if(!match)
            break;
          var Iteration = Math.floor(Math.random() * (999999 - 100000) + 100000)

          var v = "RESOURCE_" + Iteration;
          var m = match[1].split("|")[0]
          var notreuse = match[1].indexOf("|notreuse")>=0
          var onlyfail = match[1].indexOf("|onlyfail")>=0
          AdditionalData +=  _.template($('#resource_code').html())({resource:m,variable:v,notreuse:notreuse,onlyfail:onlyfail});

          var i = match.index
          var resnew = "";
          if(i>0)
          {
            resnew += this.ResolveVariables(rest.substr(0,i))
            resnew += ((IsString) ? " + " : "")
          }

          if(IsPrerender)
            resnew += match[0]
          else
            resnew += (IsJsonStringify) ? "JSON.stringify(" + v + ")" : v

          i = match.index + match[0].length
          var j = rest.length - i
          if(j>0)
          {
            rest = rest.substr(i,j)
          }else
            rest = ""

          if(res.length == 0)
            res = resnew
          else
            res +=  ((IsString) ? " + " : "") + resnew


        }
        return all;
      }

      this.GetAdditionalData = function()
      {
        return AdditionalData;
      }

    }

    function BrowserAutomationStudio_AddTab()
    {
      _Router.navigate("#!/addtab", true);
    }

    function BrowserAutomationStudio_SelectTab(i)
    {
      _Router.navigate("#!/selecttab", true);
      _GobalModel.set("index",i)
    }

    function BrowserAutomationStudio_TabInfo()
    {
      _Router.navigate("#!/tabinfo", true);
    }

    function BrowserAutomationStudio_CloseTab(i)
    {
      _Router.navigate("#!/closetab", true);
      _GobalModel.set("index",i)
    }


    function BrowserAutomationStudio_Click(x, y)
    {
      _Router.navigate("#!/click", true);
      _GobalModel.set("x",x.toString())
      _GobalModel.set("y",y.toString())
    }

    function BrowserAutomationStudio_Move(x, y)
    {
      _Router.navigate("#!/move", true);
      _GobalModel.set("x",x.toString())
      _GobalModel.set("y",y.toString())
      
    }

    function BrowserAutomationStudio_MoveAndClick(x, y)
    {
      _Router.navigate("#!/moveandclick", true);
      _GobalModel.set("x",x.toString())
      _GobalModel.set("y",y.toString())
      
    }

    function BrowserAutomationStudio_Drag(x, y)
    {
      _Router.navigate("#!/drag", true);
      _GobalModel.set("x",x.toString())
      _GobalModel.set("y",y.toString())
    }

    function BrowserAutomationStudio_Drop(x, y)
    {
      _Router.navigate("#!/drop", true);
      _GobalModel.set("x",x.toString())
      _GobalModel.set("y",y.toString())
    }

    
    //This function is called when selector has been updated
    function BrowserAutomationStudio_UpdateSelectorResult(selector)
    {
      if(typeof(selector) == "object")
      {
        //Disable info about ai generation
        _SelectorModel.set("is_ai_generated",false)
        _SelectorModel.set("ai_generated_name","")

        //Clear ui for ai generation
        $("#selector-ai").hide()

        //Set model data for selector
        _SelectorModel.set("is_image",false)
        _SelectorModel.set("css",selector["css"])
        _SelectorModel.set("css1",selector["css1"])
        if("css2" in selector)
          _SelectorModel.set("css2",selector["css2"])
        else
          _SelectorModel.set("css2","")

        if("css3" in selector)
          _SelectorModel.set("css3",selector["css3"])
        else
          _SelectorModel.set("css3","")

        _SelectorModel.set("match",selector["match"])
        _SelectorModel.set("xpath",selector["xpath"] || "")

        //Select css selector and update ui for selector
        $("#selector").html("css")
        $("#selector-input").removeAttr("disabled").val(_SelectorModel.get("css"))
        BrowserAutomationStudio_TestPathInternal();
        
        let CssHtml = `<li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item" data-selected="true">${selector["css1"]}</a></li>`
        if("css2" in selector)
        {
          CssHtml += `<li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item">${selector["css2"]}</a></li>`
        }
        if("css3" in selector)
        {
          CssHtml += `<li class="dropdown-border"><a tabindex="-1" href="#" class="dropdown-menu-css-item">${selector["css3"]}</a></li>`
        }


        $(".dropdown-menu-css-item").parent().replaceWith(CssHtml)

      }

    }
    
    function BrowserAutomationStudio_ElementFunction_Internal(selector, name, is_loop)
    {
      _SelectorModel.set("is_editing",false)
      _SelectorModel.set("version","1.0")
      _SelectorModel.set("is_ai_generated",false)
      _SelectorModel.set("ai_generated_name","")
      var need_to_set_image_data = false

      _Router.navigate("#", true);
      if(is_loop !== 1)
      {
        if(typeof(selector) == "string")
        {
          need_to_set_image_data = true
          _SelectorModel.set("is_image",true)
          _SelectorModel.set("image_data",selector)
        }else
        {
          _SelectorModel.set("is_image",false)
          _SelectorModel.set("css",selector["css"])
          _SelectorModel.set("css1",selector["css1"])
          if("css2" in selector)
            _SelectorModel.set("css2",selector["css2"])
          else
            _SelectorModel.set("css2","")

          if("css3" in selector)
            _SelectorModel.set("css3",selector["css3"])
          else
            _SelectorModel.set("css3","")

          _SelectorModel.set("match",selector["match"])
          _SelectorModel.set("xpath",selector["xpath"] || "")
        }

      }
      else
      {
        if(_.pluck(_VariableCollection.toJSON(), 'name').indexOf("FOR_EACH_CSS") < 0)
        {
          bootbox.alert(tr("Start Loop to use this function"))
          return
        }

        _SelectorModel.set("css","[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]")
        _SelectorModel.set("css1","[[FOR_EACH_CSS]]>AT>[[CYCLE_INDEX]]")
        _SelectorModel.set("css2","")
        _SelectorModel.set("css3","")
        _SelectorModel.set("match","[[FOR_EACH_MATCH]]>AT>[[CYCLE_INDEX]]")
        _SelectorModel.set("xpath","[[FOR_EACH_XPATH]]>AT>[[CYCLE_INDEX]]")

      }
      _SelectorModel.set("mousex",parseInt(selector["mousex"]))
      _SelectorModel.set("mousey",parseInt(selector["mousey"]))

      _Router.navigate("#!/" + name, true);
      if(need_to_set_image_data)
      {
        $("#ImageBase64").val(_SelectorModel.get("image_data"))
        $("#ImageData").attr("src","data:image/png;base64," + _SelectorModel.get("image_data"))

      }
    }

    function BrowserAutomationStudio_ElementFunction(selector, name, is_loop)
    {
      if(is_loop)
      {
        bootbox.confirm(
        {
          title: tr("Execution point is inside loop. Which element do you want to use?"),
          message: "<span style='width: 8px;height: 8px;margin-right: 8px;background-color: #337ab7;border-radius: 50%;display: inline-block;margin-bottom: 1px;'></span><span>" + tr("Element from the loop") + "</span> - <span style='color:gray;font-size:small'>" + tr("action will be performed for each element in a loop") + "</span>."+
          
          "<br /><span style='margin-top:7px;display:inline-block;'><span style='width: 8px;height: 8px;margin-right: 3px;background-color: #5cb85c;border-radius: 50%;display: inline-block;margin-bottom: 1px;'></span> " + tr("Element that you just selected") + "</span> - <span style='color:gray;font-size:small'>" + tr("default option. Action will be performed each time for same element (element that was just selected)") + ".</span>",
          buttons:
          {
            cancel:
            {
              label: tr('Element that you just selected'),
              className: 'btn-success bootbox-right'
            },
            confirm:
            {
              label: tr('Element from the loop'),
              className: 'btn-primary'
            }
          },
          callback: function (result)
          {
            is_loop = result ? 1 : 0;
            BrowserAutomationStudio_ElementFunction_Internal(selector, name, is_loop)
          }
        });
      }else
      {
        BrowserAutomationStudio_ElementFunction_Internal(selector, name, is_loop)
      }
    }

    function BrowserAutomationStudio_LoopElement(selector)
    {
      BrowserAutomationStudio_ElementFunction(selector, "loopelement", false)
    }

    _MACRO_INSERT_ELEMENT_FUNCTION_

    function BrowserAutomationStudio_Wait(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "waitelement", is_loop)
    }

    function BrowserAutomationStudio_GetXml(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "xml", is_loop)
    }

    function BrowserAutomationStudio_GetText(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "text", is_loop)
    }

    function BrowserAutomationStudio_ExecuteScript(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "browserscript", is_loop)
    }


    function BrowserAutomationStudio_ClickElement(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "clickelement", is_loop)
    }
    function BrowserAutomationStudio_MoveElement(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "moveelement", is_loop)
    }
    function BrowserAutomationStudio_DragElement(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "dragelement", is_loop)
    }
    function BrowserAutomationStudio_DropElement(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "dropelement", is_loop)
    }
    function BrowserAutomationStudio_MoveAndClickElement(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "moveandclickelement", is_loop)
    }
    function BrowserAutomationStudio_Clear(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "clear", is_loop)
    }
    function BrowserAutomationStudio_Type(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "typeelement", is_loop)
    }
    function BrowserAutomationStudio_Exists(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "exist", is_loop)
    }
    function BrowserAutomationStudio_Style(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "style", is_loop)
    }
    function BrowserAutomationStudio_Check(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "check", is_loop)
    }
    function BrowserAutomationStudio_Focus(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "focus", is_loop)
    }
    function BrowserAutomationStudio_Set(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "set", is_loop)
    }
    function BrowserAutomationStudio_SetInteger(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "set_integer", is_loop)
    }
    function BrowserAutomationStudio_SetRandom(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "set_random", is_loop)
    }
    function BrowserAutomationStudio_GetAttr(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "attr", is_loop)
    }
    function BrowserAutomationStudio_GetLinkURL(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "linkurl", is_loop)
    }
    function BrowserAutomationStudio_SetAttr(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "set_attr", is_loop)
    }
    function BrowserAutomationStudio_Captcha(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "captcha", is_loop)
    }
    function BrowserAutomationStudio_Length(selector)
    {
      BrowserAutomationStudio_ElementFunction(selector, "length", false)
    }
    function BrowserAutomationStudio_Screenshot(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "screenshot", is_loop)
    }
    function BrowserAutomationStudio_GetCoordinates(selector, is_loop)
    {
      BrowserAutomationStudio_ElementFunction(selector, "coordinates", is_loop)
    }

    function BrowserAutomationStudio_HandleEvent(name, data) {
      if (name === 'scenario.previewSettings') {
        BrowserAutomationStudio_UpdatePreviewSettings(data);
      }

      if (name === 'scenario.updateFinish') {
        window.BrowserAutomationStudio_IsUpdatingAllActions = false
        _GobalModel.set({ state: "main" });
        Toolbox.overlay.hide();
      }

      if (name === 'scenario.updateStart') {
        window.BrowserAutomationStudio_IsUpdatingAllActions = true
        Toolbox.overlay.show();
      }
    }

    function BrowserAutomationStudio_ClearWindowModalTimeout()
    {
      if(typeof(window.WindowModalTimeout) != "undefined")
      {
        clearTimeout(window.WindowModalTimeout);
        delete window.WindowModalTimeout
      }
    }


    function BrowserAutomationStudio_ShowWaiting(code)
    {
      OnHold = true
      $(".modal").modal('hide')
      var text = prepare_title_code(code,"")
      if(text.length > 0)
      {
        $("#WaitingActionName").html(text)
        $("#InterruptMessage").hide()
        $("#WaitingDisable").show()
        BrowserAutomationStudio_ClearWindowModalTimeout();
        $('#WaitingModal').modal({keyboard: false,backdrop: 'static'})
      }
          
    }
    function BrowserAutomationStudio_HideWaiting()
    {
      OnHold = false
      
      BrowserAutomationStudio_ClearWindowModalTimeout()

      window.WindowModalTimeout = setTimeout(function(){
        $('#WaitingModal').modal('hide')
        BrowserAutomationStudio_ClearWindowModalTimeout()
      }, 200)
    }

    function BrowserAutomationStudio_UpdatePreviewSettings(settings) {
      try {
        const state = JSON.parse(settings);
        if (state && state.selectorPreview) {
          PreviewModel.updateSettings(state.selectorPreview);
        }
      } catch (e) {
        console.log('Error while parsing preview settings:', e);
      }
    }

    function Normalize(code, tab)
    {
      var a = code.split("\n")
      var res = "";
      for(var i=0;i<a.length;i+=1)
      {
        var l = a[i].trim()
        if(l.length == 0)
          continue;

        if(res.length != 0)
        {
          res += "\n"
        }
        for(var j = 0;j<tab;j+=1)
          res += "   "
        res += l
      }
      return res
    }


  </script>

</body>
</html>