Home > Back-end >  Javascript - Sort columns in table by date while rows content changes
Javascript - Sort columns in table by date while rows content changes

Time:01-12

I have a table/div like the one below, and the data is generated dynamically in real time so the rows keep coming and changing.

The table is floating on my browser, I don't have control over the source website so I cannot use jQuery to modify the table. I can ONLY use JavaScript, (by using the browser extension) to alter the DOM.

<div >

<div >
  <div >
    <div >
      <div >MacKenzi</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>1:59:08 PM</span></div>
  </div>
  <div >
    <div >
      <div >Sophia</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>12:10:00 AM</span></div>
  </div>
  <div >
    <div >
      <div >Luc</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>12:40:02 AM</span></div>
  </div>

    <div >
    <div >
      <div >Daniel</div>
    </div>
    <div >status: unknown</div>
    <div ><span>1/11/2022</span><span>12:32:02 AM</span></div>
  </div>

    <div >
    <div >
      <div >Michael</div>
    </div>
    <div >is blocked</div>
    <div ><span>1/11/2022</span><span>12:49:02 AM</span></div>
  </div>

  <div >
    <div >
      <div >Vova</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>3:02:01 PM</span></div>
  </div>
</div>

</div>

I need the JavaScript code that can:

  • sort the table by the date and time - newest on top
  • highlight rows that have the word: "blocked"
  • hide rows that have the word: "unknown" (but make the rows appear when the content is changed to something else)
  • keep sorting when 'timeCell' or 'descriptionCell' is updated in any row (or maybe run the sorting every 30 seconds)

I am not familiar with the modern JS code but I think that the date time can be changed to Unix timestamp so it makes the sorting easier.

I tried to use Chrome browser extension called: Javascript Injector and some JavaScript code that uses const, i.e: const tabledoc = document;

But when I click the update button of the extension, it will show me some error that says "Uncaught SyntaxError: Identifier 'tabledoc' has already been declared".

Can you please help me?

CodePudding user response:

If you're purely modifying the DOM, especially querying plain text, then I recommend using xpath, which is used for xml/html document traversal (I think XPath 1.0 is supported in all browsers). There's a bit of a ramp up, but it's a really valuable tool similar to CSS selectors. This syntax sheet might help, it's fun to mess around with.

You can then use the DOM nodes for sorting purposes, probably parsing out the tag/attributes/properties you care about, eg HTMLElement.innerText that you can match with a regex eg

let someInfo = someNode.innerText.match(/(?<=startsWithThisText). ?(?=\n|$)/)[0];

In Chrome DevTools, you can use $x() to quickly attempt queries, but otherwise these might help you:

const blockedNodes = getLowestDomNodesByText('blocked');
blockedNodes.forEach(blockedNode => {
  console.log({ blockedNode });
  // you can traverse up with blockedNode.parentNode or whatever to check attributes or tag names
});


function x (expression) {
  const results = new XPathEvaluator().evaluate(expression, document);

  const nodes = [];
  let node = null;
  while (node = results.iterateNext()) {
    nodes.push(node);
  }

  return nodes;
};

function getLowestDomNodesByText (text) {
  return x(`//*[contains(normalize-space(.), '${text}')][not(.//*[contains(normalize-space(.), '${text}') ])]`);
};

CodePudding user response:

Ok this should get you started


const wrapper = document.querySelector('.wrapper-QqYJdG');
const bodyRows = wrapper.querySelectorAll('.bodyRow-3OfxA');

const sortedBodyRowsArray = Array.from(bodyRows).sort((bodyRowA, bodyRowB) => { 
  const timeCellA = bodyRowA.querySelector('.cell-3OfxA.timeCell-3OfxA');
    const dateA = timeCellA.firstChild.innerText;
    const timeA = timeCellA.lastChild.innerText;

  const timeCellB = bodyRowB.querySelector('.cell-3OfxA.timeCell-3OfxA');
    const dateB = timeCellB.firstChild.innerText;
    const timeB = timeCellB.lastChild.innerText;

  return new Date(dateA   ' '   timeA) - new Date(dateB   ' '   timeB);
});

wrapper.innerHTML = '';
sortedBodyRowsArray.forEach(bodyRow => {
  wrapper.appendChild(bodyRow);
});
<div >

<div >
  <div >
    <div >
      <div >MacKenzi</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>1:59:08 PM</span></div>
  </div>
  <div >
    <div >
      <div >Sophia</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>12:10:00 AM</span></div>
  </div>
  <div >
    <div >
      <div >Luc</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>12:40:02 AM</span></div>
  </div>

    <div >
    <div >
      <div >Daniel</div>
    </div>
    <div >status: unknown</div>
    <div ><span>1/11/2022</span><span>12:32:02 AM</span></div>
  </div>

    <div >
    <div >
      <div >Michael</div>
    </div>
    <div >is blocked</div>
    <div ><span>1/11/2022</span><span>12:49:02 AM</span></div>
  </div>

  <div >
    <div >
      <div >Vova</div>
    </div>
    <div >visited</div>
    <div ><span>1/11/2022</span><span>3:02:01 PM</span></div>
  </div>
</div>

</div>

  •  Tags:  
  • Related