I have the following HTML structure for a form (simplified):
<form class="form">
<div class="formRow">
<div class="formCol" data-id="First">First</div>
<div class="formCol" data-id="Last">Last</div>
<div class="formCol" data-id="Whatever">Whatever</div>
<div class="clear"></div>
</div>
<div class="formRow">
<div class="formCol" data-id="City">City</div>
<div class="clear"></div>
</div>
<div class="formRow">
<div class="formCol" data-id="Country">Country</div>
<div class="formCol" data-id="Phone">Phone</div>
<div class="clear"></div>
</div>
</form>
As I don't have any control over the output, I need to reorder the columns by using JavaScript:
const form = (() => {
const colClassName = 'formCol';
const rowClassName = 'formRow';
const clearClassName = 'clear';
function createRow(elForm) {
const elRow = document.createElement('div');
const elClear = document.createElement('div');
elRow.className = rowClassName;
elClear.className = clearClassName;
elRow.appendChild(elClear);
elForm.insertAdjacentElement('beforeEnd', elRow);
return elRow;
}
function moveColumn(elForm, elRow, colName) {
const elCol = elForm.querySelector(`.${colClassName}[data-id='${colName}']`);
elRow.insertAdjacentElement('afterbegin', elCol);
}
function removeEl(el) {
el.parentNode.removeChild(el);
}
function reorder(elForm, order) {
const elRows = elForm.querySelectorAll(`.${rowClassName}`);
const maxRows = Math.max(elRows.length, order.length);
let elCol;
for (var i = 0; i < maxRows; i++) {
if (order[i]) {
if (!elRows[i]) {
elRows[i] = createRow(elForm);
}
if (!Array.isArray(order[i])) {
moveColumn(elForm, elRows[i], order[i]);
} else {
for (j = order[i].length - 1; j >= 0; j--) {
moveColumn(elForm, elRows[i], order[i][j]);
};
}
} else {
elCol = elRows[i].querySelector(`.${colClassName}`);
if (!elCol) {
removeEl(elRows[i]);
}
}
}
}
return {
reorder,
// other functions for form
};
})();
form.reorder(document.querySelector('.form'), [
['Last', 'City'],
'First',
'Country',
'Phone',
]);
It does the following:
- Reorders the elements as specified in the array (multiple columns).
- Does not delete columns if they are not in the array (see column "Whatever").
- Creates new rows if necessary and deletes empty rows
While that works as is (see https://jsfiddle.net/6cy4mjvd/), I don't know if there are ways to improve readability / code in general, e.g. it feels wrong how I currently create new rows and modify elRows and also that I pass elForm to all helper functions... and probably a few other spots.
Btw. I plan on adding other functions other than reorder to modify the form. That's why I return an object (line // other functions for form) in the function.
displaytoflexand column'sorderto a value derived from the element's index in the array. \$\endgroup\$display: flexon the form would allow me to reorder the rows, but I also (sometimes) want to move the columns to a completely different row. That's why I only useddisplay: flexon the rows (see jsfiddle). Using JavaScript is also sightly easier to use (IMO) than having to hard code the order in CSS, e.g. I can display the form in 3 columns withreorder(el, ['Phone', 'Country', 'City'], ['First', 'Last', 'Whatever']). \$\endgroup\$Phonein the fourth row. In the fiddle, it is left in the third row. Am I misunderstanding something or is this a bug? \$\endgroup\$