how to sort element id by knowing their position in DOM
I have one array of element IDs on the page but this array is not sorted by their position in DOM/page. I want to sort them by their position on the page.
Array:
[{ id:'first', type:'TEXT'},{id:'third',type:'DROPDOWN'},{id:'second',type:'TEXT'}]
output:
[{id:'first', type:'TEXT'},{id:'second',type:'TEXT'},{id:'third',type:'DROPDOWN'}]
A generic approach which works across any DOM structure follows this steps ...
id based lookup-table / map / index for any reference which is listed within the unordered array of reference-items. Use reduce for achieving this task.getElementsByTagName('*').filter the element-array by existing reference-ids while using the reference-lookup as the filter-function's this context.map the filtered element array of step 3 back to an array of reference-items by each element's id while using again the reference-lookup as the map-function's this context; thus preserving the order of the former through mapping this order to the final result.... and might look similar to the next provided example code ...
const unorderedReferenceList = [
{ id: 'bar', type: 'TEXT' },
{ id: 'baz', type: 'DROPDOWN' },
{ id: 'foo', type: 'TEXT' },
];
console.log({ unorderedReferenceList });
const referenceIndex = unorderedReferenceList
.reduce((index, reference) => {
index[reference.id] = reference;
return index;
}, {});
console.log({ referenceIndex });
const elementList = Array.from(
document.body.getElementsByTagName('div')
);
console.log({ elementList });
const filteredElementList = elementList
.filter(function (elm) {
return (elm.id in this);
}, referenceIndex);
console.log({ filteredElementList });
const orderedReferenceList = filteredElementList
.map(function (elm) {
return this[elm.id];
}, referenceIndex);
console.log({ orderedReferenceList });
.as-console-wrapper { min-height: 100%!important; top: 0; }
<div>
<div>
<div>
<div>
<div></div>
<div id="foo">foo</div>
</div>
<div id="bar">bar</div>
</div>
</div>
<div>
<div>
<div id="baz">baz</div>
<div></div>
</div>
</div>
</div>