Fill the following form to generate a script submission file.
<style> #separator { width: 15%; } .cust-block { border: 1px solid #ccc; border-radius: 3px; padding: 20px; margin-top: 10px !important; } .tabs-pane.cust-block { margin-top: 0px !important; } #scriptText { border: none; resize: none; } #generateButton { margin-top: 10px; } </style> |
<div class="aui-group aui-group-split" style="padding: 0 5%;"> <div class="aui-item"> <form class="aui formulari"> <h2>Required information</h2> <div class="cust-block"> <!-- Program Selection --> <h3>Software information</h3> <div class="field-group"> <label class="inputTitle"> Select the program <span class="aui-icon icon-required">required</span> </label> <select class="select required" id="program" name="program" onchange="checkProgram()"> <option selected disabled>—</option> <!--<optgroup label="CONDA"> <option value="conda" data-version="3">Conda Python 3.7</option> </optgroup>--> <optgroup label="GAUSSIAN"> <option value="gaussian" data-version="g16b1">Gaussian 16 rev. B.01</option> <option value="gaussian" data-version="g09e1">Gaussian 09 rev. E.01</option> </optgroup> <optgroup label="GROMACS"> <option value="gromacs" data-version="2018.1">Gromacs 2018.1</option> <option value="gromacs" data-version="2019.1">Gromacs 2019.1</option> </optgroup> <optgroup label="VASP"> <option value="vasp" data-version="5.4.4">Vasp 5.4.4</option> </optgroup> <optgroup label="—————————"> <option value="other">—— Other software ——</option> </optgroup> </select> <div class="description"> A full list of the available software can be found <strong><a target="_blank" href="https://confluence.csuc.cat/display/HPCKB/Installed+software">here</a></strong>. </div> <div class="field-group"> </div> </div> <!-- Files and directories --> <div class="field-group"> <label for="jobName"> Job name <span class="aui-icon icon-required">required</span> </label> <input class="text required" type="text" id="jobName" title="Job name" data-aui-validation-field data-aui-validation-required="required"> <div class="description"> Specify a name for the job allocation. The specified name will appear along with the job id number when querying running jobs on the system with the <a href="https://confluence.csuc.cat/display/HPCKB/squeue" target="_blank"><strong><em>squeue</em></strong></a> command . </div> </div> <div class="field-group"> <label for="workDir"> Working directory </label> <input class="text" type="text" id="workDir" title="Working directory path"> <div class="description"> Absolute path. Output files will be copied there. </div> </div> <div id="softwareFiles"> </div> <div class="field-group"> <label for="calculTime"> Job's time limit <span class="aui-icon icon-required">required</span> </label> <input class="text short-field" min="0" value="00" type="number" id="calculTimeDays" title="Days" data-aui-validation-field>- <input class="text short-field" min="0" max="23" value="00" type="number" id="calculTimeHours" title="Hours" data-aui-validation-field>: <input class="text short-field" min="0" max="59" value="00" type="number" id="calculTimeMinutes" title="Minutes" data-aui-validation-field> <div class="description"> Set a run time limit (dd-hh:mm). </div> </div> </div> </form> <form class="aui formulari"> <h2>Extra information</h2> <div class="aui-tabs horizontal-tabs"> <ul class="tabs-menu"> <li class="menu-item active-tab"> <a href="#simple-configuration">Simple</a> </li> <li class="menu-item"> <a href="#advanced-configuration">Advanced</a> </li> </ul> <div class="tabs-pane active-pane cust-block" id="simple-configuration"> <!-- Mail preferences --> <div class="field-group"> <label for="userMail"> Email notifications </label> <input class="text" type="email" id="userMail" title="Mail addres" placeholder="Blank to avoid notifications"> <div class="aui-group"> <div class="checkbox aui-item"> <input class="checkbox" type="checkbox" name="mailEvent" id="mailEventBegin" value="BEGIN" checked> <label for="mailEventBegin">Begin</label> </div> <div class="checkbox aui-item"> <input class="checkbox" type="checkbox" name="mailEvent" id="mailEventEnd" value="END" checked> <label for="mailEventEnd">End</label> </div> <div class="checkbox aui-item"> <input class="checkbox" type="checkbox" name="mailEvent" id="mailEventFail" value="FAIL" checked> <label for="mailEventFail">Fail</label> </div> </div> <div class="description"> Email address where to receive notifications about changes on job's state. </div> </div> <!-- Where to submit the job --> <div class="field-group"> <label for="queue"> Partition (queue) </label> <select class="select" id='queue' name='queue' onchange="enableGpu()"> <option value="std" selected>Standard (std)</option> <option value="std-fat">Standard with Fat-Nodes (std-fat)</option> <option value="mem">Memory (mem)</option> <option value="gpu">GPGPU (gpu)</option> <option value="knl">Knights Landing (knl)</option> </select> <div class="description"> <strong>std: </strong>The default queue. Jobs requires less memory than 3900 MB/core</br> <strong>std-fat: </strong>Jobs requires between 3900 MB and 7900 MB of memory per core.</br> <strong>mem: </strong>Jobs requires between 7900 MB and 24180 MB of memory per core. <em>(Acces Restricted)</em>.</br> <strong>gpu: </strong>Job requires the use of P100 Nvidia GPGPU. <strong>(Acces Restricted)</strong>.</br> <strong>knl: </strong>Job requires the use the 2nd Generation Intel® Xeon Phi™ Processor (Knights Landing). <strong>(Acces Restricted)</strong>.</br> </div> </div> <!-- Job's requirements --> <fieldset class="group" id="gpuSpec"> </fieldset> <div id="numCoresField" class="field-group"> <label for="numCores"> <span>Number of cores</span> </label> <input class="text short-field" min="1" max="48" value="1" type="number" id="numCores" title="Number of cores"> <div class="description"> Number of cores needed for parallel jobs. </div> </div> </div> <div class="tabs-pane cust-block" id="advanced-configuration"> <div class="field-group"> <label for="numNodes"> <span>Number of nodes</span> </label> <input class="text short-field" min="0" max="49" value="0" type="number" id="numNodes" title="Number of nodes"> <div class="description"> Total number of requested nodes. Set a "0" value to let SLURM assign the minimum number of nodes (only in the generator). </div> </div> <div class="field-group"> <label for="numTasks"> <span>MPI processes</span> </label> <input class="text short-field" min="1" max="48" value="1" type="number" id="numTasks" title="Number of processes"> <div class="description"> Total number of MPI processes for parallel execution. </div> </div> <div class="field-group"> <label for="numThreads"> <span>Threads OMP</span> </label> <input class="text short-field" min="1" max="48" value="1" type="number" id="numThreads" title="Number of threads per task"> <div class="description"> Number of OMP threads per task for parallel execution. </div> </div> <!-- <fieldset class="group"> <legend> <span>Memory</span> </legend> <div class="radio"> <input class="radio" type="radio" checked="checked" name="memOptions" id="memStdThin" value="memStdThin"> <label for="memStdThin">< 4 GB</label> </div> <div class="radio"> <input class="radio" type="radio" name="memOptions" id="memStdFat" value="memStdFat"> <label for="memStdFat">≥ 4 GB and < 8 GB</label> </div> <div class="radio"> <input class="radio" type="radio" name="memOptions" id="memMem" value="memMem"> <label for="memMem">≥ 8 GB</label> </div> <div class="description"> Amount of memory that job needs. </div> </fieldset> --> </div> </div> <div id='generateButton' class='aui-button aui-button-primary'> <span class="aui-icon aui-icon-small aui-iconfont-code">Generate script</span> Generate </div> </form> </div> <div id="separator" class="aui-item"></div> <div class="aui-item"> <form class="aui top-label script"> <h2>Generated Script</h2> <div class="field-group cust-block"> <textarea id="scriptText" class="textarea full-width-field" rows="20" name="scriptText"></textarea> </div> <div class="aui-group aui-group-split"> <div class="aui-item aui-buttons"> <div id='downloadButton' class='aui-button aui-button-primary'> <span class="aui-icon aui-icon-small aui-iconfont-download">Download script</span> Download </div> <div id='copyButton' class='aui-button'> <span class="aui-icon aui-icon-small aui-iconfont-copy-clipboard">Copy</span> Copy </div> </div> <div class="aui-item"> <div id='resetButton' class='aui-button aui-button-subtle'> <span class="aui-icon aui-icon-small aui-iconfont-delete">Reset script</span> Reset </div> </div> </div> </form> </div> </div> |
<script> function enableGpu() { var queue = document.getElementById("queue").value; var gpuSpec = document.getElementById("gpuSpec"); if ( queue == "gpu" ) { gpuSpec.innerHTML = ` <legend> <span>GPGPU and cores</span> </legend> <div class="radio"> <input class="radio" type="radio" name="numGpu" id="gpu1" value="1" checked> <label for="gpu1">1 GPGPU + 24 cores per node</label> </div> <div class="radio"> <input class="radio" type="radio" name="numGpu" id="gpu2" value="2"> <label for="gpu2">2 GPGPU + 48 cores per node</label> </div> <div class="description"> Number of GPGPU needed. Each of them has 24 cores associated. </div>`; document.getElementById("numCoresField").hidden = true; } else { gpuSpec.innerHTML = ""; document.getElementById("numCoresField").hidden = false; } } function checkProgram() { var softwareFiles = document.getElementById("softwareFiles"); var programName = document.getElementById("program").value; softwareFiles.innerHTML = ""; switch (programName) { case 'amber': files=[{ class: "inputFile", title: "Input file (-i)", label: "Input file (-i)", default:"mdin", flag: "-i", info: "Contains control data for the min/md run." }, { class: "inputFile", title: "Input file (-p)", label: "Input file (-p)", default:"pmrtop", flag: "-p", info: "Contains molecular topology, force field, periodic box type, atom and residue names." }, { class: "inputFile", title: "Input file (-c)", label: "Input file (-c)", default:"inpcrd", flag: "-c", info: "Contains initial coordinates and (optionally) velocities and periodic box size." }, { class: "outputFile", title: "Output file (-r)", label: "Output file (-r)", default:"restrt", flag: "-r", info: "Contains final coordinates, velocity, and box dimensions for restarting run." }, { class: "outputFile", title: "Output file (-o)", label: "Output file (-o)", default:"mdout", flag: "-o", info: "Contains user readable state info and diagnostics." }, { class: "outputFile", title: "Output file (-x)", label: "Output file (-x)", default:"mdcrd", flag: "-x", info: "Contains coordinate sets saved over trajectory." }, { class: "outputFile", title: "Output file (-e)", label: "Output file (-e)", default:"mden", flag: "-e", info: "Contains extensive energy data over trajectory (not synchronized with mdcrd or mdvel)." }, { class: "outputFile", title: "Output file (-inf)", label: "Output file (-inf)", default:"mdinfo", flag: "-inf", info: "Contains Latest mdout-format energy info." }]; break; case 'gamess': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"gamess_input", flag: "", info: "Without extension." }]; break; case 'gaussian': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"in.com", flag: "", info: "Usually a <strong><em>.com<strong><em> file." }, { class: "outputFile", title: "Output file", label: "Output file", default:"out.log", flag: "", info: "Usually a <strong><em>.log<strong><em> file." }]; break; case 'gromacs': files=[{ class: "inputFile", title: "Input file (-s)", label: "Input file (-s)", default:"in.tpr", flag: "-s", info: "For <strong><em>mdrun</em></strong>, contains the topology of the system. Valid extensions: <strong><em>.tpr .tpb .tpa</strong></em>" }, { class: "outputFile", title: "Output file (-g)", label: "Output file (-g)", default:"out.log", flag: "-g", info: "For <strong><em>mdrun</em></strong>, valid extension: <strong><em>.log</strong></em>" }, { class: "outputFile", title: "Output file (-o)", label: "Output file (-o)", default:"out.trr", flag: "-o", info: "For <strong><em>mdrun</em></strong>, contains coordinates, velocities and optionally forces. Valid extensions: <strong><em>.trr .cpt .trj .tng</strong></em>" }, { class: "outputFile", title: "Output file (-c)", label: "Output file (-c)", default:"out.gro", flag: "-c", info: "For <strong><em>mdrun</em></strong>, contains the coordinates and velocities of last step. Valid extensions: <strong><em>.gro .g96 .pdb .brk .ent .esp</strong></em>" }, { class: "outputFile", title: "Output file (-e)", label: "Output file (-e)", default:"out.edr", flag: "-e", info: "For <strong><em>mdrun</em></strong>, contains energies, temperature, pressure, etc. Valid extension: <strong><em>.edr</strong></em>" }]; break; case 'lammps': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"input.in", flag: "", info: "" }]; break; case 'orca': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"example.inp", flag: "", info: "Usually a <strong><em>.inp<strong><em> file." }, { class: "outputFile", title: "Output file", label: "Output file", default:"example.out", flag: "", info: "Usually a <strong><em>.out<strong><em> file." }]; break; case 'siesta': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"in.com", flag: "", info: "Usually a <strong><em>.com<strong><em> file." }, { class: "outputFile", title: "Output file", label: "Output file", default:"out.log", flag: "", info: "Usually a <strong><em>.log<strong><em> file." }]; break; case 'vasp': files=[{ class: "inputFile", title: "Input file", label: "Input file", default:"INCAR", flag: "", info: "It holds the input parameters for the calculation.</em>" }, { class: "inputFile", title: "Input file", label: "Input file", default:"POSCAR", flag: "", info: "It contains the information on the structure." }, { class: "inputFile", title: "Input file", label: "Input file", default:"KPOINTS", flag: "", info: "It determines the sampling of the 1st Brillouin zone." }, { class: "inputFile", title: "Input file", label: "Input file", default:"POTCAR", flag: "", info: "It contains the relevant information concerning the pseudo potentials that are necessary to run the calculation." }, { class: "outputFile", title: "Output file", label: "Output file", default:"OUTCAR", flag: "", info: "It gives detailed output of a VASP run." }, { class: "outputFile", title: "Output file", label: "Output file", default:"OSZICAR", flag: "", info: "It gives a short summary of the results." }, { class: "outputFile", title: "Output file", label: "Output file", default:"CONTCAR", flag: "", info: "It gives the updated geometry at the end of the run." }, { class: "outputFile", title: "Output file", label: "Output file", default:"XDATCAR", flag: "", info: "It contains updated ionic positions of each ionic step." }, { class: "outputFile", title: "Output file", label: "Output file", default:"DOSCAR", flag: "", info: "It contains the total and integrated DOS and optionally the local partial DOS." }, { class: "outputFile", title: "Output file", label: "Output file", default:"CHGCAR", flag: "", info: "It contains the charges p*V." }, { class: "outputFile", title: "Output file", label: "Output file", default:"WAVECAR", flag: "", info: "It contains the wave function coefficients. It can be used to continue from a previous run." }]; break; default: return; break; }; for ( file of files ) { softwareFiles.innerHTML = softwareFiles.innerHTML + ` <div class="field-group"> <label> ${file.label} </label> <input class="text ${file.class}" type="text" value="${file.default}" title="${file.title}" data-flag="${file.flag}"> <div class="description">${file.info}</div> </div>`; } } function checkForm() { if ( program.value == "—" ) { var myFlag = AJS.flag({ close: 'auto', type: 'error', title: 'ERROR: FIELD REQUIRED', body: '<p>Please, select a program.</p>' }); program.focus(); return false; } if ( !jobName.value ) { var myFlag = AJS.flag({ close: 'auto', type: 'error', title: 'ERROR: FIELD REQUIRED', body: '<p>Please, type a job name.</p>' }); document.getElementById("jobName").focus(); return false; } if ( ( calculTimeDays.value + calculTimeHours.value + calculTimeMinutes.value ) == 0 ) { var myFlag = AJS.flag({ close: 'auto', type: 'error', title: 'ERROR: FIELD REQUIRED', body: '<p>Please, Specify a job\'s time limit.</p>' }); document.getElementById('calculTimeDays').focus(); return false; } return true; } function generateScript() { var jobName = document.getElementById("jobName").value; var program = document.getElementById("program"); var programName = program.value; var calculTimeDays = parseInt(0 + document.getElementById('calculTimeDays').value); var calculTimeHours = parseInt(0 + document.getElementById('calculTimeHours').value); var calculTimeMinutes = parseInt(0 + document.getElementById('calculTimeMinutes').value); if( !checkForm() ) return false; // Directories and files var directoriesText = ""; var workDir = document.getElementById("workDir").value || '${SLURM_SUBMIT_DIR}'; var inputFiles = []; var outputFiles = []; if ( document.getElementsByClassName("inputFile") ) { inputFiles = document.getElementsByClassName("inputFile"); var inputFilesNames = []; for ( var i = 0; i < inputFiles.length; i++ ) { inputFilesNames.push(inputFiles[i].value); } }; if ( document.getElementsByClassName("outputFile") ) { outputFiles = document.getElementsByClassName("outputFile"); var outputFilesNames = []; for ( var i = 0; i < outputFiles.length; i++ ) { outputFilesNames.push(outputFiles[i].value); } }; var userMail = document.getElementById("userMail").value; var mailText = ""; var queue = document.getElementById("queue").value; var numNodes = document.getElementById("numNodes").value; var numCores = document.getElementById("numCores").value; var numTasks = document.getElementById("numTasks").value; var numThreads = document.getElementById("numThreads").value; //var memory = document.querySelector("input[name='memOptions']:checked").value; var ompText = ""; var programVersion = program.options[program.selectedIndex].getAttribute('data-version'); if ( numTasks > 1 ) { numCores = numTasks; } // Job name jobNameText = '\n#SBATCH -J ' + jobName + '\n#SBATCH -e ' + jobName + '.%j.err' + '\n#SBATCH -o ' + jobName + '.%j.out'; // Mail preferences var mailEvents = document.querySelectorAll("input[name='mailEvent']:checked"); var mailType = ''; if (userMail) { if ( mailEvents.length == 0 ) { mailType = 'NONE '; } else { for (var i = 0; i < mailEvents.length; i++) { mailType += mailEvents[i].value + ','; } } mailType = mailType.slice(0,-1); mailText = "\n#SBATCH --mail-user=" + userMail + "\n#SBATCH --mail-type=" + mailType; } // Where to submit (partition) var whereText = '\n#SBATCH -p ' + queue; // Resources and specs var resourcesText = ''; if ( numNodes > 0 ) { resourcesText += '\n#SBATCH -N ' + numNodes; } if ( programName == "gaussian" ) { resourcesText += '\n#SBATCH -n 1' + '\n#SBATCH -c ' + numCores; } else if ( queue == "gpu" ) { var numGpu = document.querySelector("input[name='numGpu']:checked").value; resourcesText += '\n#SBATCH --gres=gpu:' + numGpu; resourcesText += '\n#SBATCH -N ' + Math.max(numNodes, 1); numCores = numGpu * 24; } else { resourcesText += '\n#SBATCH --ntasks=' + Math.max(numCores, 1); } if ( numThreads > 1 ) { resourcesText += '\n#SBATCH --cpus-per-task=' + numThreads; ompText = '\n\nexport OMP_NUM_THREADS=' + numThreads; } /* switch ( memory ) { case 'memStdFat': resourcesText += '\n#SBATCH --mem-per-core=7900' + '\n#SBATCH -C mem'; break; case 'memMem': resourcesText += '\n#SBATCH --mem-per-core=15000'; break; default: break; } */ resourcesText += '\n#SBATCH --time=' + calculTimeDays + '-' + calculTimeHours; + ':' + calculTimeMinutes; // Charge modules and run var modules = '\n\nmodule load apps/' + programName + '/' + programVersion + "\n"; var extraModulesText = ''; var runCommand = ''; directoriesText = '\n##\n# Modify the input and output files!'; switch (programName) { case 'amber': var executable = "pmemd"; directoriesText += '\nINPUT_FILES=$(ls ${SLURM_SUBMIT_DIR}/' + inputFilesNames[0] + ',' + inputFilesNames[1] + ',' + inputFilesNames[2] + ')'; if ( queue == "gpu" ) { executable += ".cuda"; } if ( numCores > 1 ) { executable = "mpirun -np " + numCores + " " + executable + ".MPI"; } runCommand = executable + ' -O' + ' -i ' + inputFilesNames[0] + ' -p ' + inputFilesNames[1] + ' -c ' + inputFilesNames[2] + ' -r ' + outputFilesNames[0] + ' -o ' + outputFilesNames[1] + ' -x ' + outputFilesNames[2] + ' -e ' + outputFilesNames[3] + ' -inf ' + outputFilesNames[4]; break; case 'conda': //directoriesText = ''; runCommand = '\n\n# Check the available conda environments with "conda env list".' + '\nconda activate <your_environment>'; break; case 'gaussian': directoriesText += '\nINPUT_FILES=' + workDir + '/' + inputFilesNames[0] + '\nOUTPUT_FILES=' + workDir + '/' + outputFilesNames[0]; runCommand = '\n\nsrun ' + programVersion.substr(0, 3) + ' < ' + inputFilesNames[0] + ' > ' + outputFilesNames[0]; break; case 'gromacs': directoriesText += '\nINPUT_FILES=' + workDir + '/' + inputFilesNames[0] + '\nOUTPUT_FILES=' + workDir + '/{' + outputFilesNames.join() + '}'; runCommand = '\n\n#Gromacs has multiple programs and options.\n#Go to the reference manual for more information.\n'; if ( numCores > 1 || numTasks > 1 ) { runCommand += 'mpirun -np ' + numCores + ' gmx_mpi mdrun'; } else { runCommand += 'gmx mdrun'; } runCommand += ' -s ' + inputFilesNames[0] + ' -g ' + inputFilesNames[1] + ' -o ' + inputFilesNames[2] + ' -c ' + inputFilesNames[3] + ' -e ' + inputFilesNames[4]; break; case 'lammps': runCommand = 'mpirun -np ' + numCores + ' lmp_mpi -in '+ inputFilesNames[0]; break; case 'namd': runCommand = 'namd2 +p4 ' + inputFile + '.namd > ' + inputFile + '.out'; break; case 'nwchem': runCommand = 'mpijob nwchem ' + inputFile + '.in > ' + inputFile + '.out'; break; case 'orca': runCommand = '`which orca` ' + inputFilesNames[0] + ' > ' + outputFilesNames[0]; directoriesText += '\nINPUT_FILES=$(ls ${SLURM_SUBMIT_DIR}/' + inputFilesNames[0] + ')'; break; case 'R': runCommand = 'Rscript ' + inputFile + '.R > ' + inputFile + '.out'; break; case 'siesta': directoriesText += '\nINPUT_FILES=$(ls ${SLURM_SUBMIT_DIR}/' + inputFilesNames[0] + ')'; runCommand = 'siesta < ' + inputFilesNames[0] + ' > ' + outputFilesNames[0]; break; case 'vasp': directoriesText += '\nINPUT_FILES=' + workDir + '/' + inputFilesNames.join() + '})' + '\nOUTPUT_FILES=' + workDir + '/{' + outputFilesNames.join() + '}'; runCommand = '\n\nsrun `which vasp_std`'; extraModulesText = '\nulimit -s unlimited'; break; default: modules = "\n\n# Load here the modules you require"; runCommand = "# Type here the execution command"; break; } var modulesText = modules + extraModulesText; var output = outputFilesNames.join(); if ( outputFilesNames.length > 1 ) { output = '{' + output + '}'; } var calculationText = directoriesText + '\n\n##' + '\n# You don\'t need to modify nothing more' + '\ncp -r ${INPUT_FILES} ${SCRATCH}' + '\ncd ${SCRATCH}' + runCommand + '\n\ncp ' + output + ' ' + workDir; /*if ( stayDirectories ) { calculationText = directoriesText + '\n##' + '\n# You don\'t need to modify nothing more\n' + runCommand; }*/ document.getElementById('scriptText').value = '#!/bin/bash' + jobNameText + mailText + whereText + resourcesText + modulesText + ompText + calculationText; var myFlag = AJS.flag({ close: 'auto', type: 'success', title: 'GENERATED', body: '<p>Script generated succesfully!</p>' }); } function copyScript() { var scriptText = document.getElementById('scriptText'); scriptText.select(); document.execCommand('copy'); var myFlag = AJS.flag({ close: 'auto', type: 'success', title: 'COPIED', body: '<p>Script copied succesfully!</p>' }); } function downloadScript() { var jobName = document.getElementById("jobName").value; if (!jobName) { jobName = "default"; } var text = document.getElementById('scriptText').value; var filename = jobName + ".slm"; var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function resetScript() { document.getElementById('scriptText').value = ""; } //AJS.$(document).on('click', '#generateButton', generateScript); document.getElementById('generateButton').addEventListener('click', generateScript); document.getElementById('downloadButton').addEventListener('click', downloadScript); document.getElementById('resetButton').addEventListener('click', resetScript); document.getElementById('copyButton').addEventListener('click', copyScript); </script> |