-
-
Save SMUsamaShah/dfcc6f709158b0adcc0a48c2d66fd353 to your computer and use it in GitHub Desktop.
| javascript:(function() { | |
| function sortEmailsBySender() { | |
| var emails = Array.from(document.querySelectorAll('.zA')); | |
| emails.sort(function(a, b) { | |
| var senderA = a.querySelector('.yW span').innerText.toLowerCase(); | |
| var senderB = b.querySelector('.yW span').innerText.toLowerCase(); | |
| return senderA.localeCompare(senderB); | |
| }); | |
| emails.forEach(function(email) { | |
| email.parentNode.appendChild(email); | |
| }); | |
| } | |
| sortEmailsBySender(); | |
| })(); |
It fixed that too
javascript:(function() {
function sortEmailsBySender() {
// Find the table containing emails
var emailTable = document.querySelector('table[role="grid"]');
if (!emailTable) {
console.log('Could not find email table');
return;
}
// Get the tbody or the table itself if no tbody
var tableBody = emailTable.querySelector('tbody') || emailTable;
// Get all row elements (emails)
var rows = Array.from(tableBody.querySelectorAll('tr[role="row"]'));
if (rows.length === 0) {
// Try alternate selector for newer Gmail versions
rows = Array.from(tableBody.querySelectorAll('tr.zA'));
}
if (rows.length === 0) {
alert('No email rows found to sort');
return;
}
// Store original positions to remember them later
rows.forEach(function(row, index) {
row.setAttribute('data-original-position', index);
});
// Create array of rows with sender info
var rowsWithSender = rows.map(function(row) {
// Different possible selectors for sender names
var sender = '';
var senderElement = row.querySelector('.yW span') ||
row.querySelector('[email]') ||
row.querySelector('[name]');
if (senderElement) {
sender = senderElement.innerText || senderElement.getAttribute('email') || senderElement.getAttribute('name') || '';
sender = sender.toLowerCase();
}
return {
row: row,
sender: sender,
originalPosition: parseInt(row.getAttribute('data-original-position'))
};
});
// Sort the rows by sender
rowsWithSender.sort(function(a, b) {
// First by sender name
var senderCompare = a.sender.localeCompare(b.sender);
if (senderCompare !== 0) return senderCompare;
// If sender names are the same, keep original order
return a.originalPosition - b.originalPosition;
});
// Store sorted order for each row
rowsWithSender.forEach(function(rowData, index) {
rowData.row.setAttribute('data-sorted-position', index);
rowData.row.style.order = index;
});
// Add flexbox display to container to make the order property work
tableBody.style.display = 'flex';
tableBody.style.flexDirection = 'column';
// Ensure rows take full width
rows.forEach(function(row) {
row.style.width = '100%';
});
// Track last clicked row for shift-select
var lastClickedRow = null;
// Add custom click handler for shift-select functionality
document.addEventListener('click', function(e) {
var row = e.target.closest('tr[role="row"]') || e.target.closest('tr.zA');
if (!row) return;
// Find the checkbox element
var checkbox = row.querySelector('input[type="checkbox"]') ||
row.querySelector('[role="checkbox"]');
// Handle shift-clicks for our custom select behavior
if (e.shiftKey && checkbox && lastClickedRow) {
e.preventDefault();
e.stopPropagation();
// Get sorted positions
var currentPos = parseInt(row.getAttribute('data-sorted-position'));
var lastPos = parseInt(lastClickedRow.getAttribute('data-sorted-position'));
// Determine range to select
var startPos = Math.min(currentPos, lastPos);
var endPos = Math.max(currentPos, lastPos);
// Select all rows in the range based on sorted order
rows.forEach(function(r) {
var sortedPos = parseInt(r.getAttribute('data-sorted-position'));
if (sortedPos >= startPos && sortedPos <= endPos) {
var cb = r.querySelector('input[type="checkbox"]') ||
r.querySelector('[role="checkbox"]');
if (cb) {
// Check if not already checked
if (cb.checked !== true && cb.getAttribute('aria-checked') !== 'true') {
cb.click(); // Simulate click to check
}
}
}
});
return;
}
// Update last clicked row if checkbox was clicked
if (e.target === checkbox || e.target.closest('[role="checkbox"]')) {
lastClickedRow = row;
return; // Let Gmail handle the single checkbox click
}
// Only handle clicks on the row itself, not on buttons or links
if (e.target.tagName === 'A' || e.target.tagName === 'BUTTON' ||
e.target.closest('a') || e.target.closest('button') ||
e.target.closest('[role="button"]') ||
e.target.closest('.T-I') || e.target.closest('.T-I-J-J5-Ji')) {
return; // Let Gmail handle these clicks
}
// Find the conversation link
var conversationLink = row.querySelector('a[href*="#inbox/"]') ||
row.querySelector('a[href*="mail/u/"]') ||
row.querySelector('a[href*="#search/"]');
if (conversationLink && conversationLink.href) {
window.location.href = conversationLink.href;
e.preventDefault();
e.stopPropagation();
}
}, true); // Use capture phase for early interception
console.log('Gmail emails sorted by sender with custom shift-select enabled');
}
sortEmailsBySender();
})();Hi SMUsamaShah,
I'm trying to run this but it doesn't seem to sort the emails. I tested the very first version and it does sort but when you open the email its the original message from that position.
So these newer versions are obviously better but don't seem to work for me. I checked the console messages and it does seem to be triggering but doesn't change the emails shown.
Any suggestions on what I might have missed?
Thanks
@shadsnz Did you remove all the comments when using it as bookmarklet?
Yes, I did. I'm using Chrome, have tested in both the Gmail Inbox, Sent and All Mail folders. I might try a different browser and another Gmail account to test.
Well, it seems to work sometimes now after refreshing browsers and increasing the number of messages per page. Thanks for posting the code.
Thanks to Claude. Following is working near perfectly
Shift + Select is not working correctly though