QRTEngine - Simulating keypress with click event - javascript

there's not a lot of documentation for this but I'm hoping someone can help me.
I'm using the QRTEngine provided by the folks over at http://qrtengine.com/ for Qualtrics (http://www.qualtrics.com/) - a survey tool.
I have managed to set up a 'agree/disagree' survey quite easily (user presses the key 'z' for disagree and 'm' for agree)
The problem is that I need this to work on mobile too. Now I've tried the following:
var j = jQuery.noConflict();
(function( j ) {
j(function() {
// More code using $ as alias to jQuery
var e = j.Event("keyup");
e.which = 77; // # Some key code value
j( ".agree" ).bind( "click", function( event ) {
j(this).trigger(e);
alert(e.which);
});
});
})(j);
Which executes the alert but doesn't seem to simulate the keypress. I don't think there's anything wrong with my code, but I'm wondering if I'm missing something in regard to the QRTEngine I'm using.
Any help (ANY) would be appreciated.
Thanks

$ is the alias for the Prototype framework in Qualtrics. If you want use an alias for jQuery you need to make it something else like $j:
var $j = jQuery.noConflict();
EDIT: Maybe this is your problem...from http://bililite.com/blog/2015/01/14/rethinking-fn-sendkeys/ :
"Modern browsers won't let synthetic events (triggered with dispatchEvent) execute their default actions (meaning the action that would occur if the event was triggered by a user action). The Event object has a read-only field called isTrusted that is false for anything but unmodified user-initiated events. These are called "trusted events", and I understand the justification, but they go too far. It makes it impossible to implement a virtual keyboard, since triggering keydown or keypress events aren't trusted and won't insert the character (the default action)."
Check out the link referenced above for a potential solution.

Related

Remove window event handler after triggered one time

I am dealing with an odd problem where I need an event handler to bind upon instantiation of a module, but when the module is terminated via a click or a keypress, I no longer want this global event bound. I've gotten the click event to register termination of the module handled elsewhere in code and that works, but the problem is the escape press that I want to globally terminate the module regardless of where my user currently is in the app.
My problem is that the .off() doesn't appear to work given the circumstances.
let tools = {};
//how can i eliminate this next line of code after escape has been triggered?
$(window).on('keydown', (e)=>escape(e, tools));
function escape(e, tools){
if (e.which==27){
//do some stuff with tools, etc
$(window).off('keydown', $(window), escape); //this line doesn't seem to work
alert('alert triggered, but next time escape is pressed it wont.');
}
}
Am I going about this approach wrong? I tried binding it to the div element itself, but this has a whole lot more baggage associated with focussing the div to recieve the keypresses, and if the user navigates to another module, the escape will no longer be triggered because this module will no longer have focus, and well, etc etc etc.
Thank you!
Here is fiddle:
https://jsfiddle.net/rbfebL5y/1/
Use only handler function as argument according to documentation:
let tools = {};
//how can i eliminate this next line of code after escape has been triggered?
$(window).on('keydown', escape);
function escape(e){
if (e.which==27){
//do some stuff with tools, etc
$(window).off('keydown', escape);
alert('alert triggered, but next time escape is pressed it wont.');
}
}
You could use localStorage:
// check key pressed and whether we've done this before
if (e.which==27 && !localStorage.getItem('hasLoggedEscape')){
// set the local storage value saying we've done this before
localStorage.setItem('hasLoggedEscape', 1);
//do some stuff with tools, etc
}
later if you want to reset this, do
localStorage.removeItem('hasLoggedEscape');

Storing arbitrary data in an $.event

Here is my code:
var e = jQuery.Event( "keydown", { keyCode: 64 } );
There is data being attached to the event in the second parameter. Now I have seem that kind of syntax in a lot of plugins and was wondering, what's the use of attaching arbitrary data to a $.event/custom event?
I have seen the jQuery docs event object and also trigger.
I am wondering, if the only usage of attaching data to a event is as follows:
var e = jQuery.Event( "keydown", { keyCode: 64 } );
// above is the line I am having difficulty understanding
// the usage of arbitrary data with the $.event is quite
// elusive to a novice developer like me
$(window).on('keydown' , function(e){
console.log('key 64 pressed');
});
press = function(){
$(window).trigger(e);
}
setTimeout(function(){
press();
}, 2000);
JS Fiddle here
I.e. triggering an event on a specific key or a specific element, I mean is this the only use of attaching arbitrary data to an $.event?
Sometimes you are using your code that behaves in some way depending on the interaction.
In your example, you are "manually" triggering the keydown event on that input in order to "trigger" the event-listeners listening to this event.
Probably on this example you have a idle logout system going on and you activated something to keep the session alive on your UI as long as needed.
The other day I had to use something similar in order to keep a dropdown open in a third party plugin that was closing a drop down on selection after a search.

Javascript How to tell if event.preventDefault has occurred on a listener

This should be an easy one :)
I want to add a click event listener only in case it hasn't been added earlier already, and prevent it from running twice. I thought of accomplishing this like so:
HTML
Google is your friend
Bing's alright as well
JS
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++)
{
if (*Default has been prevented for links[i]*){ //how do I implement this check?
return; //do nothing, we're all done.
} else {
links[i].addEventListener("click",function(event){
event.preventDefault();
alert("Showing you this instead of opening this link!");
});
}
}
In my real world case the added event listener is preventing the default behavior. So how can I check if it has been prevented before? I want to make sure the listener won't be added twice. How can I implement this check?
Many thanks for any ideas.
You can achive your goal using object identity. Quote from MDN:
Multiple identical event listeners
If multiple identical EventListeners are registered on the same
EventTarget with the same parameters, the duplicate instances are
discarded. They do not cause the EventListener to be called twice, and
since the duplicates are discarded, they do not need to be removed
manually with the removeEventListener method.
Example:
// the "one" handler function instance
var theEventPreventDefaultHandler = function (event) {
event.preventDefault();
};
var links = document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", theEventPreventDefaultHandler);
}
Watch the Fiddle.
I didn't check that out, but it could be possible the addEventListener function returns false to catch the case, when it didn't add a "duplicate". It doesn't, returns only undefined.
To "check if an event has a handler" is not supported natively. It is possible in jQuery, because this manages the handlers in a .data("events") array, also to support IE's old quirks behaviors in this and window.event. That said, it would be a pain in the ass to reimplement what ejohn did. There about are a bunch of questions on stackoverflow:
test if event handler is bound to an element in jQuery
Answer on "How to check if click event is already bound - JQuery"
... google "jquery check bound event"

pass an event AND a variable to an anon function in firefox

I come again with my inabilities to comprehend javascript.
I have a draggable library and it has a command that is called like so (the _ag is just namespacing stuff):
_ag.drag(event,targetDiv);
// targetDiv can be a string, btw - converted to an element in the function
so I've got code that looks like so (passing some data with a closure - a new trick to me):
header.onmousedown=function(targetDiv){
return function(){
_ag.drag(event,targetDiv)
}
}(aTargetDiv)
works great! just great! in...IE! SF! Chrome! NOT IN FIREFOX!
No, firefox cannot find the event. Now normally this is easy enough with something like this (formed slightly differently - hope it's still valid):
header.onmousedown=function(event){
alert(event.screenX)
}
However if I decide to pass some parameters in, it blows away event, which I guess is some sort of invisible parameter in FF?
//broken thing 1:
header.onmousedown=function(event){
alert(event.screenX) // somethingToPass in covers event in FF
}(somethingToPassIn)
// broken thing 2:
header.onmousedown=function(event){
alert(event.screenX)
}(event,somethingToPassIn) // event is undefined
SO FIREFOX: How do I send you events? Here's hoping this is a very stupid question, and that hoards of SO folks have the answers! Thanks in advance, I'll be right here banging my head against the wall.
Firefox probably doesn't have support for event, but instead passes it into your function when the event fires. So,
header.onmousedown=function(targetDiv){
return function(e){
e = e || event; //This will give support for global event and passing the event into the function
_ag.drag(e, targetDiv);
}
}(aTargetDiv)
You don't need the closure unless the aTargetDiv variable changes sometime later in the code. Instead, you could do:
header.onmousedown=function(e){
e = e || event;
_ag.drag(e, aTargetDiv);
};

A better way to search for events?

I recently found myself in the situation that I needed to remove a function bound to the resize event of the window by WordPress' media manager (media-upload.js), because it was interfering with the proper use of Thickbox. The event is attached like this:
a(window).resize(function(){tb_position()})
It took me a while, but I finally found out I could do it in this way:
jQuery.each( jQuery(window).data('events')['resize'], function(i, event) {
var thisEvent = event.toString().replace(/\n/g, '').replace(/\t/g, '').split(' ').join('');
var expectedEvent = 'function(){tb_position()}';
if (thisEvent == expectedEvent)
delete jQuery(window).data(‘events’)[‘resize’][i];
})
Here I cycle through the events, removing spaces, tabs and new lines from them and compare them to what I'm looking for, and when I find it I throw it out of the goddamn airlock. It happens in this case that the attached function perhaps doesn't have spaces, tabs or new lines, but this way also works with more complicated functions as far as I can tell.
Is there an easier and/or more elegant way of doing this? Is this a recipe for disaster down the road?
When you register a handler for an event, you can use a qualifier:
$('#something').bind('click.removeMeSomeday', function() { ... });
Then when you need to remove it you can do so without bothering other handlers for "click".
Now, it occurs to me that you may not be able to affect the way that Wordpress binds its event handler.
Another way around might be to use WordPress' system for queueing/unqueueing or registering/deregistering scripts. Unregister media-upload.js, and then queue your own version of it.
http://codex.wordpress.org/Function_Reference/wp_enqueue_script
http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-includes/functions.wp-scripts.php.source.html#l74
http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-includes/functions.wp-scripts.php.source.html#l37
Prem

Categories

Resources