<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Excel2Graph</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://bootswatch.com/5/morph/bootstrap.min.css" type="text/css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/mdbassit/Coloris@latest/dist/coloris.min.css"/> <script src="https://cdn.jsdelivr.net/gh/mdbassit/Coloris@latest/dist/coloris.min.js"></script> </head> <body> <div class="container"> <h1>Excel2Graph</h1> <p>Instructions:</p> <ol> <li>Paste Excel data into the text area below</li> <li>Select the correct columns</li> <li>Click "Load Data from Columns"</li> <li>Fill in the rest of the form</li> <li>Click "Generate Plot"</li> </ol> <form action="/process_data" method="post" onsubmit="prepareSubmission"> <textarea id="excelData" placeholder="Paste Excel data here" class="form-control mb-3" name="excelData"></textarea> <button type="button" onclick="processData()" class="btn btn-outline-primary mb-3">Process Excel Data</button> <div name="dataSeriesDiv" id="data-series-div"> <div class="row mt-3 mb-3"> <div class="col-md-2"> <label for="xColumn-1" class="form-label">X Data Column</label> <select id="xColumn-1" class="form-control table-data" name="xColumn-1"></select> </div> <div class="col-md-2"> <label for="yColumn-1" class="form-label">Y Data Column</label> <select id="yColumn-1" class="form-control table-data" name="yColumn-1"></select> </div> <div class="col-md-2"> <label for="stdDevColumn-1" class="form-label" >Error Bars</label> <select id="stdDevColumn-1" class="form-control table-data" name="stdDevColumn-1"> <option value="">None</option> </select> </div> <div class="col-md-2"> <label for="dataSeries-1" class="form-label">Data Series Name</label> <input type="text" name="dataSeries-1" id="dataSeries-1" class="form-control" placeholder="Data"> </div> <div class="col-md-2"> <label for="colorPicker-1" class="form-label">Datapoint Color</label> <input name="colorPicker-1" class="form-control" id="colorPicker-1" name="colorPicker-1" value="#000000" data-coloris> </div> </div> </div> <button class="btn btn-outline-primary mb-4" type="button" onclick="addDataSeries()">Add Data Series</button> <script type="text/javascript"> function addDataSeries() { let dataSeriesCount = document.getElementById('data-series-div').childElementCount; let dataSeriesDiv = document.getElementById('data-series-div'); let row = document.createElement('div'); row.classList.add('row'); row.classList.add('mb-3'); row.id = `dataSeriesRow-${dataSeriesCount + 1}`; let col1 = document.createElement('div'); col1.classList.add('col-md-2'); let col2 = document.createElement('div'); col2.classList.add('col-md-2'); let col3 = document.createElement('div'); col3.classList.add('col-md-2'); let col4 = document.createElement('div'); col4.classList.add('col-md-2'); let col5 = document.createElement('div'); col5.classList.add('col-md-2'); let col6 = document.createElement('div'); col6.classList.add('col-md-2'); let xColumn = document.createElement('select'); xColumn.classList.add('form-control'); xColumn.classList.add('table-data'); xColumn.id = `xColumn-${dataSeriesCount + 1}`; xColumn.name = `xColumn-${dataSeriesCount + 1}`; let yColumn = document.createElement('select'); yColumn.classList.add('form-control'); yColumn.classList.add('table-data'); yColumn.id = `yColumn-${dataSeriesCount + 1}`; yColumn.name = `yColumn-${dataSeriesCount + 1}`; let stdDevColumn = document.createElement('select'); stdDevColumn.classList.add('form-control'); stdDevColumn.classList.add('table-data'); stdDevColumn.id = `stdDevColumn-${dataSeriesCount + 1}`; stdDevColumn.name = `stdDevColumn-${dataSeriesCount + 1}`; // Default to None let stdDevOption = document.createElement('option'); stdDevOption.value = ''; stdDevOption.innerHTML = 'None'; stdDevColumn.appendChild(stdDevOption); let dataSeries = document.createElement('input'); dataSeries.classList.add('form-control'); dataSeries.id = `dataSeries-${dataSeriesCount + 1}`; dataSeries.name = `dataSeries-${dataSeriesCount + 1}`; dataSeries.placeholder = 'Data'; let colorPicker = document.createElement('input'); colorPicker.classList.add('form-control'); colorPicker.id = `colorPicker-${dataSeriesCount + 1}`; colorPicker.name = `colorPicker-${dataSeriesCount + 1}`; colorPicker.value = '#000000'; colorPicker.setAttribute('data-coloris', ''); let removeButton = document.createElement('button'); removeButton.classList.add('btn'); removeButton.classList.add('btn-outline-danger'); removeButton.classList.add('mb-3'); removeButton.type = 'button'; removeButton.innerHTML = 'Remove Data Series'; removeButton.onclick = function() { let row = document.getElementById(`dataSeriesRow-${dataSeriesCount + 1}`); row.remove(); } // If excel data is present, populate the column selectors let headersDiv = document.getElementById('headersDiv'); if (headersDiv) { let headers = JSON.parse(headersDiv.innerHTML); headers.forEach((header, index) => { let option = new Option(header, index); xColumn.add(option.cloneNode(true)); yColumn.add(option.cloneNode(true)); stdDevColumn.add(option.cloneNode(true)); }); } col1.appendChild(xColumn); col2.appendChild(yColumn); col3.appendChild(stdDevColumn); col4.appendChild(dataSeries); col5.appendChild(colorPicker); col6.appendChild(removeButton); row.appendChild(col1); row.appendChild(col2); row.appendChild(col3); row.appendChild(col4); row.appendChild(col5); row.appendChild(col6); dataSeriesDiv.appendChild(row); } </script> <input type="hidden" name="xData" id="xData"> <input type="hidden" name="yData" id="yData"> <input type="hidden" name="stdDevData" id="stdDevData"> <br><br> <div> <button type="button" onclick="prepareSubmission()" class="btn btn-outline-primary">Load Data from Columns</button> <button type="button" class="btn btn-outline-warning">Reset Data Load</button> </div> <div class="row mb-3 mt-3"> <label for="xTitle" class="form-label">X-Axis Title</label> <input type="text" name="xTitle" id="xTitle" class="form-control" placeholder="X-Axis"> </div> <div class="row mb-3"> <label for="yTitle" class="form-label">Y-Axis Title</label> <input type="text" name="yTitle" id="yTitle" class="form-control" placeholder="Y-Axis"> </div> <div class="row mb-3"> <label for="plotTitle">Plot Title</label> <input type="text" name="plotTitle" id="plotTitle" class="form-control"> </div> <div id="constantLinesContainer"> </div> <button type="button" class="btn btn-outline-primary mb-3" onclick="addConstantLine()">Add Constant Line</button> <div class="row mb-3"> <div class="col-md-4"> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="calcTrendline" name="calcTrendline" checked=""> <label class="form-check-label" for="calcTrendline">Calculate Trendline</label> </div> </div> </div> <div class="row mb-3"> <div class="col-md-4"> <label for="colorPickerPlotBackground" class="form-label">Plot Background Color</label> <input name="colorPickerPlotBackground" class="form-control" id="colorPickerPlotBackground" value="#ffffff" data-coloris> </div> <div class="col-md-4"> <label for="colorPickerTrendline" class="form-label">Trendline Color</label> <input name="colorPickerTrendline" class="form-control" id="colorPickerTrendline" value="#000000" data-coloris> </div> </div> <div class="row mb-3"> <div class="col-md-4"> <label for="xAxisScale" class="form-label">X-Axis Scale</label> <select name="xAxisScale" id="xAxisScale" class="form-control"> <option value="linear" default>Linear</option> <option value="log">Logarithmic</option> <option value="symlog">Symmetrical Logarithmic</option> <option value="logit">Logit</option> </select> </div> <div class="col-md-4"> <label for="yAxisScale" class="form-label">Y-Axis Scale</label> <select name="yAxisScale" id="yAxisScale" class="form-control"> <option value="linear" default>Linear</option> <option value="log">Logarithmic</option> <option value="symlog">Symmetrical Logarithmic</option> <option value="logit">Logit</option> </select> </div> </div> <input type="submit" value="Generate Plot"> </form> <div id="tableContainer"></div> <script type="text/javascript"> // add change handler for textarea and execute processData function //document.getElementById('excelData').addEventListener('change', processData); function prepareSubmission() { const data = document.getElementById('excelData').value; const rows = data.split('\n').map(row => row.split('\t')); // Assuming first row contains headers const headers = rows.shift(); populateColumnSelectors(headers); // Prepare data for submission const xIndex = document.getElementById('xColumn').value; const yIndex = document.getElementById('yColumn').value; const stdDevIndex = document.getElementById('stdDevColumn').value; const xData = rows.map(row => row[xIndex]); const yData = rows.map(row => row[yIndex]); const stdDevData = stdDevIndex ? rows.map(row => row[stdDevIndex]) : []; document.getElementById('xData').value = JSON.stringify(xData); document.getElementById('yData').value = JSON.stringify(yData); document.getElementById('stdDevData').value = JSON.stringify(stdDevData); // Optionally, create and display table for review before submission createTable(rows, headers); } function processData() { const data = document.getElementById('excelData').value; const rows = data.split('\n').map(row => row.split('\t')); // Assuming first row contains headers const headers = rows.shift(); populateColumnSelectors(headers); // Create and display table createTable(rows, headers); // Create hidden div with headers data const headersDiv = document.createElement('div'); headersDiv.id = 'headersDiv'; headersDiv.classList.add('d-none'); headersDiv.innerHTML = JSON.stringify(headers); document.body.appendChild(headersDiv); } function populateColumnSelectors(headers) { const xColumnSelect = document.getElementById('xColumn'); const yColumnSelect = document.getElementById('yColumn'); const stdDevSelect = document.getElementById('stdDevColumn'); /* headers.forEach((header, index) => { let option = new Option(header, index); xColumnSelect.add(option.cloneNode(true)); yColumnSelect.add(option.cloneNode(true)); stdDevSelect.add(option.cloneNode(true)); }); */ // Fill all data series var allSelect = document.getElementsByClassName('table-data'); console.log(allSelect) for (var i = 0; i < allSelect.length; i++) { for (var j = 0; j < headers.length; j++) { let option = new Option(headers[j], j); allSelect[i].add(option.cloneNode(true)); } } } function createTable(data, headers) { let table = '<table contenteditable="true" class="table">'; table += '<tr>' + headers.map(header => `<th scope="col">${header}</th>`).join('') + '</tr>'; data.forEach(row => { table += '<tr>' + row.map(cell => `<td>${cell}</td>`).join('') + '</tr>'; }); table += '</table>'; document.getElementById('tableContainer').innerHTML = table; } let constantLineCount = 0; function addConstantLine() { const container = document.getElementById('constantLinesContainer'); const line = document.createElement('div'); line.innerHTML = ` <div class="row mb-3"> <div class="col-md-4"> <label for="constantLine${constantLineCount}">Constant Line (y=)</label> <input type="text" name="constantLine${constantLineCount}" id="constantLine${constantLineCount}" class="form-control"> </div> <div class="col-md-4"> <label for="constantLineLabel${constantLineCount}">Line Title</label> <input type="text" name="constantLineLabel${constantLineCount}" id="constantLineLabel${constantLineCount}" class="form-control"> </div> <div class="col-md-4"> <button type="button" class="btn btn-outline-danger mb-3 mt-4" onclick="this.parentElement.parentElement.remove()">Remove Constant Line</button> </div> </div> `; container.appendChild(line); constantLineCount++; } // You should add more JavaScript for handling editing and validation </script> <style type="text/css"> textarea { width: 100%; height: 150px; } select { margin: 5px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid black; padding: 5px; text-align: left; } </style> </div> </body> </html>