I am trying to simulate the click on the refresh button above the inbox.
This is my current (not working) script:
var $elem = $('div.T-I.J-J5-Ji.nu.T-I-ax7.L3'); //getting the "refresh" button
if ($elem.length > 0) {
var event = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
$elem[0].dispatchEvent(event);
}
I also tried to use trigger('click') and click() on the query object.
I had the same problem some time ago. For some reason, it requires the button to be focused and the event ocurrs ONLY after a keydown|mousedow AND then keyup|mouseup is executed. Saddly, using click() or any other JQuery event trigger doesn't work.
My solution using pure JS:
function refreshDomNow() {
var refreshButtons = $( 'div.T-I.J-J5-Ji.nu.T-I-ax7.L3' ),
buttonsFounds = refreshButtons.length,
visibleButton = 0,
refreshed = false;
if ( buttonsFounds > 0 ) { // There should be at least one of these buttons
for ( var i = 0; i < buttonsFounds; i++ ) {
var currentButton = $(refreshButtons[i]);
if ( currentButton.is(':visible') ) {
var rButton = $(rButtonClass)[i];
visibleButton++;
//Trigger mouse down event
var mouseDown = document.createEvent('MouseEvents');
mouseDown.initEvent( 'mousedown', true, false );
rButton.dispatchEvent(mouseDown);
//Trigger mouse up event
var mouseUp = document.createEvent('MouseEvents');
mouseUp.initEvent( 'mouseup', true, false );
rButton.dispatchEvent(mouseUp); // This opens the composer
refreshed = true;
} // End of IF currentButton.is(':visible')
} // End of FOR loop
} // End of IF buttonsFounds > 0
return refreshed;
} // End of refreshDomNow();
And even though this works, I'm not happy with it. Mainly because the refresh button is not visible when you are reading a mail thread. I'm looking for one step ahead: I want to know HOW to trigger the function that is attached to the refresh button (and yes, trigger() does not work) without the need of clicking it.
Any ideas? thoughts?
Related
I have a SELECT element that I am replacing with a dropdown. I have successfully created the dropdown from the SELECT and child OPTION elements, but I need to add a click event.
This click event would be as such:
If LI is clicked, also click corresponding OPTION.
This is because Woocommerce must have some JS or PHP working where depending on the option, it shows stock status and variable amount. As such, I assume that the click event will also bind the OPTION value to the form for adding to cart.
I have this JS code:
window.onload = main;
function main(){
var select = document.querySelector('.turnintodropdown');
var selsOpts = document.querySelector('.turnintodropdown option');
var selsLi = document.querySelector('.selectOption');
var trigger = document.createElement('a');
var openDropdown = 'dropdownVisible';
var closeDropdown = 'dropdownHidden';
(function addDropdown() {
if(select) {
var selsCon = document.createElement('div');
var selsOuter = document.createElement('ul');
selsCon.classList.add('selectContainer');
selsOuter.classList.add('selectOuter');
select.parentNode.insertBefore(selsCon, select);
selsCon.appendChild(selsOuter);
for(var i=0; i<select.length; i++) {
if(select.childNodes[i].classList.contains('enabled') || select.childNodes[i].innerHTML == '- -'){ // Select First Child and <option> Tags with Enabled Class
// Create New Elements
var optsNew = document.createElement('li');
optsNew.innerHTML = select.childNodes[i].text;
optsNew.classList.add('selectOption');
// Set Attributes to New Elements
if(optsNew.innerHTML !== '- -') {
optsNew.setAttribute('value', select.childNodes[i].text);
}
else {
void(0);
}
optsNew.click(clickFunc);
// Add New LI <option> to UL <container>
selsOuter.appendChild(optsNew);
// Click Events
console.log(select.firstChild);
}
}
var clickFunc = function() {
select.click();
};
select.style.display = 'none';
}
})();
}
Any help would be greatly appreciated.
Regards
Michael
I was a bit long to answer, sorry.
the function was originally taken from this webpage and not modified, it is supposed to work with most old browsers. I actually tested on last versions of Firefox / Chrome / Opera / Edge with success.
The version which handles all types of events is more complicated because you have to make cases for standard events to process them by type (not all are MouseEvents).
It also supports the inline functions, with onclick= in the html tag, and works also for events set with jQuery.
Note that if you want the same support for old broswers, you'll have to differentiate cases for the setting of events too, the modern addEventListener being not supported by all.
function fireClick(node){
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
used like this for example:
fireClick(document.getElementById("myId"));
Vanilla JS (without jQuery)
/**
* Simulate a click event.
* #public
* #param {Element} elem the element to simulate a click on
*/
var simulateClick = function (elem) {
// Create our event (with options)
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
// If cancelled, don't dispatch our event
var canceled = !elem.dispatchEvent(evt);
};
To use it, call the function, passing in the element you want to simulate the click on.
var someLink = document.querySelector('a');
simulateClick(someLink);
src / full article: https://gomakethings.com/how-to-simulate-a-click-event-with-javascript/
I am going to use a button I found online:
http://codepen.io/ibrahimjabbari/pen/ulbek
After clicking it, it doesn't reset to the original state, how would I do this?
<nav class="ij-effect-2">
When you click elsewhere on the page it causes it to reset to original state but I want this done automaticly after being clicked
Well I might have a solution:
function fireClick(node){
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
Using this you can fire a click by calling click on body. With fireClick(document.body). Source: http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
This is my first post so ill try to explain it clear:
Im working on a web application, but the main point is, that i want let my users feel like its a native app. In a native app you cant scroll like in iOS safari so i tried to disable scrolling with event.preventDefault. This works great except that form elements and links arent tapable anymore. My solution to that was this little script, but if you start a touch on one of the escaped elements, it scrolls anyway. Not a big deal but its driving me insane...
notes to script:
isTouch returns true/false if its a touchable device
the .contains method returns true/false if an array contains a string
if (isTouch) {
window.addEventListener("touchstart", function (evt) {
var target = evt.touches[0].target;
var tags = 'a input textarea button'.split(' ');
if ( tags.contains(target.tagName) === false ) {
evt.preventDefault();
}
}, false);
}
EDIT
My main question is, is there a solution to fire the tap event without a touchmove event to allow scrolling
EDIT 2
I solved the problem. My solution is, to emulate the events on interactive elements:
var eventFire = function (el, etype) {
if (el.fireEvent) {
(el.fireEvent('on' + etype));
}
else {
var evObj = document.createEvent('Events');
evObj.initEvent(etype, true, false);
el.dispatchEvent(evObj);
}
}
if (isTouch) {
window.addEventListener("touchstart", function (evt) {
var target = evt.touches[0].target;
var foc = 'input textarea'.split(' ');
var clck = 'a button'.split(' ');
if ( foc.contains(target.tagName) ) {
target.focus();
eventFire(target,'click');
evt.preventDefault();
}
else {
evt.preventDefault();
}
}, false);
}
I have a form, with a button called add rows. I would like to disable this button after user clicks on it thrice.
You could set a click counter on the button, but seeing as it is called "add rows", I suppose you might be able to just count the number of rows, and determine if it should be disabled that way.
bool disabled = true;
$('#add-rows').prop('disabled', disabled);
Replace true with your favourite means of calculating the number of rows.
From the top answer in google Triple Click Event:
$.event.special.tripleclick = {
setup: function(data, namespaces) {
var elem = this, $elem = jQuery(elem);
$elem.bind('click', jQuery.event.special.tripleclick.handler);
},
teardown: function(namespaces) {
var elem = this, $elem = jQuery(elem);
$elem.unbind('click', jQuery.event.special.tripleclick.handler)
},
handler: function(event) {
var elem = this, $elem = jQuery(elem), clicks = $elem.data('clicks') || 0;
clicks += 1;
if ( clicks === 3 ) {
clicks = 0;
// set event type to "tripleclick"
event.type = "tripleclick";
// let jQuery handle the triggering of "tripleclick" event handlers
jQuery.event.handle.apply(this, arguments)
}
$elem.data('clicks', clicks);
}
};
Used like so:
$("#mybutton").bind("tripleclick", function() {
$(this).attr("disabled", "disabled");
}
Note that you'll probably want to use on instead of bind, see What's the difference between `on` and `live` or `bind`?
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.
There's a script here that looks it does what you're trying to do. Is that the whole script you needed to create or was that just part of the functionality?
According to the discussions, they did create it for Firefox which it works in, some people have commented it doesn't work in Chrome, so you might be looking at a solution that needs to target different browsers (your question doesn't specify if it must work in Chrome, just that you were using it).
This is what they are using to select the unread messages, it looks like they are simulating the mousedown and mouseup events on each item:
var handler = function(type,e) {
e.preventDefault();
e.stopPropagation();
var e2 = document.createEvent('MouseEvents');
e2.initEvent('mousedown',true,false);
var el = anchor.wrappedJSObject;
el.dispatchEvent(e2);
setTimeout(function() {
var el = document.querySelectorAll('div[selector='+type+'] > div')[0].wrappedJSObject;
var e2 = document.createEvent('MouseEvents');
e2.initEvent('mouseup',true,false);
el.dispatchEvent(e2);
},100);
}
They are calling this by setting up a click event further down which calls handler('unread',e);
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);