Using jquery .on when running a function - javascript

I have the following line of jquery which reacts to any key up event in any text input on a form. It then runs a function called processPrimarySearch:
$('#primarySearch input[type="text"]').on('keyup', this, processPrimarySearch);
This works, but I want to adapt it so keyup ignores a tab key press as described here: Keyup event behavior on tab
I can't work out how to re-write this as I don't understand how to pass this before calling processPrimarySearch. For example I have the following but it doesn't work and I don't understand what I'm supposed to write to make it work:
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
if (e.which != 9) {
// No reference to 'this'!
processPrimarySearch();
}
}
});
function processPrimarySearch() {
// ...
}

Your logic is almost correct, you just need to use call() to provide the context for the function. Try this:
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
if (e.which != 9) {
processPrimarySearch.call(this);
}
}
});
function processPrimarySearch() {
// ...
}

Related

How to reference all <input> and <textarea> and do an action if they have :focus?

I am trying to use plain Javascript to set up a function that fires when the S key is pressed AND the search overlay is not already open AND the S is not pressed when inside an <input> or <textarea>. The issue is in the third argument and I can't seem to figure it out.
Can you please tell me how to set up the third argument in the IF statement?
I have been trying to get an equivent of the JQuery is() function in regular JS. Since I don't know much about JS I am avoiding JQuery until I get the basics down. I have created a class for OOP, so the this. is referencing that.
My Javascript:
keyPressControl(event) {
if (event.keyCode == 83 && !this.isOverlayOpen && !document.querySelectorAll('input, textarea').hasFocus()) {
this.staffSearchOpen();
}
}
The this.staffSearchOpen(); should function when all three arguments noted above are true, but I can only get the first two to work properly.
The wording of the question is a little confusing but it looks like you're trying to exclude event that happen when an input field is in focus, not the other way around.
Instead of "hasFocus()" you could just build the rule into the selector itself as input:focus, textarea:focus:
document.addEventListener('keypress', function() {
if (document.querySelector('input:focus, textarea:focus')) {
console.log("keypress event was inside an input")
} else {
console.log("No input in focus");
}
})
<input>
<textarea></textarea>
...so your function could be:
keyPressControl(event) {
if (
event.keyCode == 83 &&
!this.isOverlayOpen &&
!document.querySelector('input:focus, textarea:focus')
) {
this.staffSearchOpen();
}
}
Do it the other way around:
var elems = document.querySelectorAll('input, textarea');
elems.foreach(function (elem) {
this.addEventListener("keydown",keyPressControl);
});
keyPressControl(event) {
//you won't get a key event here unless the element is the focus owner
if (event.keyCode == ...) {
this.staffSearchOpen();
}
}

Javascript - Add specific keypress event inside a loop

I am attempting to assign a keypress event to an element within a for loop. I know that there are issues with assigning events while in a for loop dynamically, and I have solved that for the "click" event however I am at a loss for how it should work for the keypress. (probably because I don't really understand how the "click" one works to begin with... closure avoidance is not something I fully get)
The basic setup is that there is a for loop that will print out a number of different textareas and a div underneath them. Pressing the div will send the text in the text area to the right person. What I would like to have happen is that the same message should be sent if the enter button is pressed within the text area.
for( var i in people){
var message = $('<textarea></textarea>').appendTo(container);
message.on( "keypress", function(e) {
if(e.keyCode==13){
// code does make it in here ...
sendMessage(people[i].name); // but this never gets run
}
});
var messageButton= $('<div>Send</div>').appendTo(container);
messageButton.on( "click", sendMessage(people[i].name) );
}
var sendMessage = function(to) {
return function(){
/* do the sending of the message to the right person */
}
}
Can anyone help me understand the following?
Why does the click function work in the first place? I am not understanding why we have to put return around the function block.
Why doesn't the keypress function work similarly?
On a more general level, how does keypress work to begin with. The function(e) should not work because 'e' isn't anything, where does that even get set?
The problem with keypress in the code is that it will always send the message to latest person in people as at the moment when it is executed, i will have the latest value in it.
I probably would use forEach instead:
people.forEach(function (person) {
var message = $('<textarea></textarea>').appendTo(container);
// you can use keypress - http://api.jquery.com/keypress/#keypress-eventData-handler
// see the examples in the reference
message.keypress(function (e) {
if (e.which === 13) {
// here you should invoke the function returned by the sendMessage
sendMessage(person.name)();
}
});
var messageButton= $('<div>Send</div>').appendTo(container);
messageButton.click(sendMessage(person.name));
});
with this approach you do not need to wrap the function in the sendMessage and can just call the original function in the corresponding event handler.
Clean example using jQuery. You should read more about jQuery and closures for iterations so you can easily understand what is going on.
$.each(people, function (person) {
var $message = $('<textarea></textarea>').appendTo(container);
var $button = $('<div>Send</div>').appendTo(container);
var send = sendMessage(person.name);
// Keypress handler
$message.keypress(function (e) {
if (e.which === 13) { // on enter do the following
send();
}
});
$button.click(send);
});
Here's another solution using a handwritten closure:
http://jsfiddle.net/M5NsS/1/
var people = {
'p1': {
name: 'john'
},
'p2': {
name: 'bob'
},
'p3': {
name: 'jim'
}
};
var container = $('#container');
for (var i in people) {
(function (name) {
var message = $('<textarea></textarea>').appendTo(container);
message.keypress(function (e) {
if (e.keyCode == 13) {
sendMessage(name);
}
});
var messageButton = $('<div>Send</div>').appendTo(container);
messageButton.click(function () {
sendMessage(name)
});
})(people[i].name);
}
function sendMessage(to) {
console.log(to);
}
As others have stated, the issue is that the event is bound with the last reference to 'i' in the loop. Using a closure solves this issue while still allowing you to use your for..in loop.
Another thing to note is that if you are not dynamically appending these elements to the DOM after binding, there is no reason to use jquery's .on(). You can directly bind .keypress() and .click() handlers to the elements, as seen in my fiddle and on #AlexAtNet's answer.
But it's clunky, and I would just use jquerys $.each as others have already suggested.

Javascript Function being triggered by onClick check

I was wondering if there is a way for a function to check if it was triggered by the onClick method?
function check(id) {
if(onClick()) {
alert('thanks for clicking!');
}
}
I've tried to find this but I can't seem to come across anything.
Thanks!
Try this, this will give the type of event occured. Then you can match whether it was click or mousemove or mousedown or anything
<body onclick="eventType(event)">
function eventType(event)
{
alert(event.type); // if you want to check for click then use if(event.type=='click')
}
If your function is used a callback for an event somewhere, it will get the event object as an argument. So you simple check if event.type is "click".
function check(e) {
if (e.type == "click") {
alert("Thanks for clicking me!");
}
}
var button = document.getElementById("a_button");
button.onclick = check;

How to combine keypress & on click function in JavaScript?

I have the following two functions:
$("input").keypress(function(event) {
if (event.which == 13) {
//code
}
});
$('#login_submit').click(function () {
//code
});
The code which is being used in the functions are EXACTLY the same code, basically code dublication. So i was wondering if there is a way to combine these functions with an OR statement??
Create your own callback and pass that to the event handlers.
var callback = function() {...};
$("input").keypress(function() {
if (event.which == 13) callback();
});
$('#login_submit').click(callback);
Add a class to your HTML
<input class="myClass">
<div id="login_submit" class="myClass" ></div>
Now you can write:
$(".myClass").bind("keypress click", function(){});
Or do this:
$("input").add("#login_submit").bind("keypress click", function(){});
Be aware that clicking on the input will also trigger this.
Why don't you do it like this?
$("input").keypress(function(event) {
if (event.which == 13) {
foospace.yourfunction();
}
});
$('#login_submit').click(function () {
foospace.yourfunction();
});
var foospace={};
foospace.yourfunction=function() {
alert("your code goes here!");
}
Edit:
The callback solution by #David is slightly more elegant.
I would chain the events like:
var watchCurrentCursorPosition = function (){
console.log("foo");
}
$("input").keypress(
watchCurrentCursorPosition
).click(
watchCurrentCursorPosition
);
For those who still are looking for an answer to the #Sino's question.
The code which is being used in the functions are EXACTLY the same code, basically code dublication. So i was wondering if there is a way to combine these functions with an OR statement??
JQuery .on() method is the way to go.
Description: Attach an event handler function for one or more events to the selected elements.
So your code could go like this:
$("input").on("click keypress", function(event) {
if (event.which === 13) {
event.preventDefault();
//code
}
});

jQuery event binding with accessibility in mind - click and keypress

Just a quick question, I seem to do this a lot:
$saveBtn.bind("click keypress", function(e)
{
if (e.type != "keypress" || e.keyCode == 13)
{
// Do something...
return false;
}
});
Is there a quicker way to bind an 'action' listener to a button? I want to always ensure my buttons with event listeners fire on both clicks and the enter key...this seems like it'd be a fairly common thing to want to do but found nothing on google. Any thoughts?
Thanks.
The click event doesn't actually handle the keypress in every case, it's the button that is making the click event work. When you use a div with a tabindex attribute to make it keyboard accessible, the click handler will not trigger when you press enter.
HTML
<div id="click-only" tabindex="0">Submit click only</div>
<div id="click-and-press" tabindex="0">Submit click and press</div>​
jQuery
$("#click-only").click(function (e) {
addToBody(); // Only works on click
});
$("#click-and-press").bind("click keypress", handleClickAndPress(function (e) {
addToBody(); // Works on click and keypress
}));
function addToBody() {
$("body").append($("<p/>").text("Submitted"));
}
function handleClickAndPress(myfunc) {
return function (e) {
if (e.type != "keypress" || e.keyCode == 13) {
myfunc(e);
}
};
}
So to answer the question, I don't think there is a better way (that works in every case) other than yoda2k's solution.
By binding it with click will do the job, no need for keep press. Example
You could create a second function which handles the additional logic and pass your function as a parameter:
function handleClickAndPress(myfunc)
{
return function (e) {
if (e.type != "keypress" || e.keyCode == 13) {
myfunc(e);
}
};
}
$saveBtn.bind("click keypress", handleClickAndPress(function (e) {
// do your stuff here
}));
If it's part of a form you could just listen for the "submit" event?

Categories

Resources