How to expand the length of an input text/number based on it's `value` attribute?

Issue

I have a form that I’m using to modify a SQL tables values. I can easily get everything to populate using PHP; however, I’m having issues getting the input fields to size properly. I’m hoping there’s an easier way than brute forcing the CSS to work the way I want…

PHP/HTML

echo "<table class='modify woSub'>";
echo "<tr><th>KeyID</th><th>Rx Number</th><th>Name</th><th>Alt Name</th><th>Patient</th><th>Prescriber</th><th>Dose/Pill</th>
<th>Dose Metric</th><th colspan='2'>Quantity / Frequency</th><th class='box'>AM</th><th class='box'>Noon</th><th class='box'>PM</th>
<th class='box'>Bed</th><th class='box'>PRN</th><th>Last Fill</th><th>Pills Filled</th></tr>";
echo "<form class='modifyForm' action='modify.php' method='post'>";
$sql = "SELECT * FROM prescriptions WHERE patient = '$patient' ORDER BY rxPrimeName";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo "<tr>";
        echo "<td><input type='text' inputmode='numeric'  value='" . $row['keyID'] . "' name='keyID' disabled/></td>";
        echo "<td><input type='text' inputmode='numeric'  value='" . $row['rxID'] . "' name='rxID'/></td>";
        echo "<td><input type='text' value='" . $row['rxPrimeName'] . "' name='rxPrimeName'/></td>";
        echo "<td><input type='text' value='" . $row['rxAltName'] . "' name='rxAltName'/></td>";
        echo "<td><input type='text' value='" . $patient . "' name='patient' disabled/></td>";
        echo "<td><input type='text' value='" . $row['prescriber'] . "' name='prescriber'/></td>";
        echo "<td><input type='text' inputmode='numeric' value='" . $row['dpp'] . "' name='dpp'/></td>";
        echo "<td><input type='text' value='" . $row['dppMetric'] . "' name='dppMetric'/></td>";
        echo "<td><input class='split' type='text' inputmode='numeric'  value='" . $row['frequency'] . "' name='frequency' style='border-right: none !important'/></td>";
        echo "<td><input class='split' type='text' value='" . $row['freqMetric'] . "' name='freqMetric' style='border-left: none !important'/></td>";
        echo "<td><input type='checkbox' name='am' value='am' /></td>";
        echo "<td><input type='checkbox' name='pm' value='noon' /></td>";
        echo "<td><input type='checkbox' name='pm' value='pm' /></td>";
        echo "<td><input type='checkbox' name='bed' value='bed' /></td>";
        echo "<td><input type='checkbox' name='prn' value='prn' /></td>";
        echo "<td><input type='date' value='" . $row['lastFill'] . "' name='lastFill'/></td>";
        echo "<td><input type='text' inputmode='numeric' value='" . $row['pills'] . "' name='pills'/></td>";
        echo "</tr>";
    }
}
echo "</form>";
echo "</table>";

CSS

table {
    border-collapse: collapse;
    width: 1400px;
}

th,
td {
    border: 1px solid white;
    border-collapse: collapse;
    overflow: hidden;
    text-align: center;
    vertical-align: middle;
}
th {
    padding: 5px 10px;
}
td>input {
    width: 85%;
    margin: 5px;
}
.box {
    width: 10px;
}
.split {
    width: 30px;
    text-align: center;
}

This is the PHP>Table>Form I’m using. No, I haven’t put in a submit portion yet, and I’m not too worried about that. I’m just working on aesthetics right now.

Here is a snippet of what it’s showing exactly as-is:

IMGUR Image

If you look at the first 4 columns, this is the area I’m trying to get to fit. I would like this all to fit the size of the largest value with a tiny bit of padding (like 2-5px).

Everything I’ve found online is for how to have the input auto-expand when typing, but I’m trying to do it based on the php value that is being pushed into the value attribute.

Solution

Here is a bit complicated javascript method. The idea is to create an element with exact same style as input field. Then load into it string from each input field sorted by column and find the longest one. Then set input width per column.

const setWidth = (() =>
{
  //clone style from <input> into our hidden div
  const div = document.createElement("div"),
        selector = '.modify input[type="text"]'; //input fields

  div.className = "hiddenBox";
  for(let i = 0, style = getComputedStyle(document.querySelector(selector)); i < style.length; i++)
    div.style[style[i]] = style[style[i]]; //copy all styles into hidden div

  document.body.appendChild(div);

  return () =>
  {
    let max = [];
    for(let i = 0, input = document.querySelectorAll(selector); i < input.length; i++)
    {
      div.textContent = input[i].value; //load text into hidden div
      if (div.clientWidth > ~~max[input[i].parentNode.cellIndex])
        max[input[i].parentNode.cellIndex] = div.clientWidth; //record widest size
    }
    for(let i = 0, box = document.querySelector(".modify"); i < max.length; i++)
      max[i] && box.style.setProperty("--width"+(i+1), max[i] + "px"); //set CSS variable for input width for each column
  }
})();

setWidth(); //set <input> width



//ignore everything below

generateRows(10) //add 10 rows
function generateRows(num)
{
  // generate additional rows
  for(let i = 1, tr = document.querySelector(".modify tr:not(:first-child)"); i < num; i++)
    tr.parentNode.appendChild(tr.cloneNode(true));

  randText(); //generate text
}

function randText()
{
  for(let i = 0, input = document.querySelectorAll('.modify input[type="text"]'); i < input.length; i++)
  {
    input[i].value = "";
    let len = ~~(Math.random() * 20 + 1);
    while(input[i].value.length < len)
    {
      input[i].value += String.fromCharCode((~~(Math.random() * 2) ? 97 : 65) + ~~(Math.random() * 26));
      if (!~~(Math.random() * 10))
        input[i].value += " ";
    }
  }
  setWidth();
};
.modify td:nth-child(1) input {width: var(--width1);}
.modify td:nth-child(2) input {width: var(--width2);}
.modify td:nth-child(3) input {width: var(--width3);}
.modify td:nth-child(4) input {width: var(--width4);}
.modify td:nth-child(5) input {width: var(--width5);}
.modify td:nth-child(6) input {width: var(--width6);}
.modify td:nth-child(7) input {width: var(--width7);}
.modify td:nth-child(8) input {width: var(--width8);}
.modify td:nth-child(9) input {width: var(--width9);}
.modify td:nth-child(10) input {width: var(--width10);}
.modify td:nth-child(17) input {width: var(--width17);}

.hiddenBox
{
  position: absolute !important;
  top: -200000vh !important;
  width: unset !important;
  white-space: pre !important;
  padding: initial !important; /* delete this if some text doesn't fit */
  border: 0 !important; /* delete this if some text doesn't fit */
}
<button onclick="randText()">Generate again</button>

<table class='modify woSub'>
<tr><th>KeyID</th><th>Rx Number</th><th>Name</th><th>Alt Name</th><th>Patient</th><th>Prescriber</th><th>Dose/Pill</th>
<th>Dose Metric</th><th colspan='2'>Quantity / Frequency</th><th class='box'>AM</th><th class='box'>Noon</th><th class='box'>PM</th>
<th class='box'>Bed</th><th class='box'>PRN</th><th>Last Fill</th><th>Pills Filled</th></tr>
<form class='modifyForm' action='modify.php' method='post'>
  <tr>
    <td><input type='text' inputmode='numeric' value='' name='keyID' disabled/></td>
      <td><input type='text' inputmode='numeric'  value='' name='rxID'/></td>
      <td><input type='text' value='' name='rxPrimeName'/></td>
      <td><input type='text' value='' name='rxAltName'/></td>
      <td><input type='text' value='' name='patient' disabled/></td>
      <td><input type='text' value='' name='prescriber'/></td>
      <td><input type='text' inputmode='numeric' value='' name='dpp'/></td>
      <td><input type='text' value='' name='dppMetric'/></td>
      <td><input class='split' type='text' inputmode='numeric'  value='' name='frequency' style='border-right: none !important'/></td>
      <td><input class='split' type='text' value='' name='freqMetric' style='border-left: none !important'/></td>
      <td><input type='checkbox' name='am' value='am' /></td>
      <td><input type='checkbox' name='pm' value='noon' /></td>
      <td><input type='checkbox' name='pm' value='pm' /></td>
      <td><input type='checkbox' name='bed' value='bed' /></td>
      <td><input type='checkbox' name='prn' value='prn' /></td>
      <td><input type='date' value='' name='lastFill'/></td>
      <td><input type='text' inputmode='numeric' value='' name='pills'/></td>
      </tr>
</form>
</table>

Answered By – vanowm

Answer Checked By – David Goodson (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.