In Gmail, clicking on the checkbox shown below selects all messages and I'm making a userscript (for personal use and I need it to work in Chrome) that'll select the unread messages only (only the first 2 messages in the screenie below are unread) instead of the default behavior of that checkbox.
My first idea is to simulate click events and although I could access the "unread" menuitem fine using the code...
var unread_menuitem = document.getElementById('canvas_frame').contentWindow.document.getElementById(':s2');
$(unread_menuitem).css({'border':'thin red solid'});
and dispatch the click event to it using the code...
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent( 'click', true, true );
unread_menuitem.dispatchEvent(clickEvent); // Chrome's console returned 'true'
the unread messages don't get selected.
My second idea was to brute force the selection by checking the checkbox $('#canvas_frame').contents().find('tr.zE input').prop('checked', true)
and apply the css styles that Gmail applies on a manual click event, but while I was able to match the manual click event both visually as well as DOM-wise (afaik)...
Gmail says "No conversations selected" while performing some action, in this case I did a "Mark as Read". I also want to note that manually clicking on the checkboxes that were put in this state using my brute force method did not "uncheck" them as you'd expect. They needed one additional manual click to get unchecked.
Both my ideas have bombed and I want to know if there are others ways to tackle this, or if there are ways to improve upon my ideas above that can solve the problem.
Solved it, easy as pie and now that I think about it, it's the solution listed in user PirateKitten's answer - instead of "checking off" the checkboxes besides the unread messages like my second idea, simulate clicks on those checkboxes instead. Works like a charm and here's the code, which you can run in Chrome's console while using Gmail (doesn't need jQuery btw):
var unreadMessages = document.getElementById('canvas_frame').contentWindow.document.querySelectorAll('tr.zE input');
var numMessages = unreadMessages.length;
while ( numMessages-- ) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent( 'click', true, true );
unreadMessages[numMessages].dispatchEvent(clickEvent);
}
Here's my full script that you can run inside your Chrome console (or turn it into an extension/userscript) to change the default behavior of the checkbox from selecting ALL messages to just the unread messages only:
var hasUILoaded = setInterval( function() {
if( document.getElementById('canvas_frame').contentDocument.getElementsByClassName('J-Zh-I J-J5-Ji J-Pm-I L3') ) {
clearInterval( hasUILoaded );
setTimeout( function() {
var content_frame = document.getElementById('canvas_frame').contentDocument;
var chkbox = content_frame.getElementsByClassName( 'J-Zh-I J-J5-Ji J-Pm-I L3' );
var chkbox = chkbox[0].childNodes[0];
var unreadMessages = content_frame.getElementsByClassName('zE'); // DOM structure: <tr class=zE> <td> <img><input> </td> </tr> so we add ".childNodes[0].childNodes[1]" whenever we want to access the check boxes of each message.
var allMessages = content_frame.getElementsByClassName('zA');
chkbox.onclick = function() {
if( chkbox.checked ) {
var numUnread = unreadMessages.length;;
var numAll = allMessages.length;
setTimeout(function () {
if( allMessages[0].childNodes[0].childNodes[1].checked ) {
while ( numAll-- ) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent( 'click', true, true );
allMessages[numAll].childNodes[0].childNodes[1].dispatchEvent(clickEvent);
}
}
}, 10);
setTimeout(function (){
if(!unreadMessages[0].childNodes[0].childNodes[1].checked) {
while ( numUnread-- ) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent( 'click', true, true );
unreadMessages[numUnread].childNodes[0].childNodes[1].dispatchEvent(clickEvent);
}
}
}, 30);
}
}
}, 100);
}
}, 300);