Simulating Enter Key Press on Input in Karma/Jasmine Tests - javascript

I am trying to test user search functionality inside an angular custom component. The input (and only input) in the directive template that I am trying add text to and trigger the search is:
<input type="text" ng-model="searchInput" class="form-control search"/>
I would like to add a text value of "User" into that input above. Test to make sure it has that value, and then simulate an enter key press to then select the first matching node.
Get the input element
Add text to the input
Test to make sure the input value is correct
Press enter on the input
Text to make sure the first matching item in the search is correct
Have tried:
it ("should search for the specified node", function () {
var value = "User is not registered"
var input = diagramDirective.find("input");
$(input).val(value).trigger("input");
scope.$apply();
//why can't I trigger a click event here by doing something like
var e = jQuery.Event("keypress");
e.keyCode = 13;
$(input).trigger(e);
}
Thanks

You need to match your JQuery.Event to whatever is triggering the final search in your controller, so if your controller is listening for a keypress, then you need to make sure your jQuery.Event is a "keypress" event, but if your controller is listening for a "keyup" you need to set your jQuery event to "keyup". You also need to look for the matching item in the callback of the actual event
it("should search for the specified nodes", function () {
var value = "User is not registered";
var e = jQuery.Event("keypress");
e.keyCode = 13;
// find the input
var directiveElementInput = diagramDirective.find("input");
// Set some text!
$(directiveElementInput).val(value).trigger("input");
// make sure the input has the value
expect(directiveElementInput).toHaveValue(value);
// execute the event on the input and check for the selected item
$(directiveElementInput).keypress(function () {
// do your check here for the matching item here
}).trigger(e);
});

I would recommend taking a look at the event listeners on the input box, because an input box isn't necessarily always triggered by the "enter" keypress. Some other possible events that it may be listening to are, "blur", "keyup", "change". Depending on if its an event listener or an on-whatever event, you'll have to trigger it accordingly.
Sorry this is kind of vague, but it's hard to say without knowing the event listeners attached to the input box.
Hope this helped!

Related

Trigger function on input event if selected text is within input

I've built a page where you can filter results by typing into an input box.
Basic mechanics are:
Start typing, input event is fired, elements without matching text begin hiding
If input becomes empty (or if you click a reset button), all elements are shown again
I have noticed a problem, though, when highlighting text. Say I type "apple" into the input. Then I highlight it, and type "orange."
If an element exists on the page containing "orange," but it was already hidden because I filtered for "apple," it does not show up. I have gathered this is because the input never truly empties; rather, I simply replace "apple" with the "o" from orange before continuing with "r-a-n-g-e." This means I get a subset of "apple" results that contain "orange," as if I had typed "apple orange."
What I really want to do is clear my input on the keypress for the "o" in "orange" before hiding nonmatching elements, so I'm effectively searching the whole page for "orange."
What I've tried so far
1: Set input value to '' on select event:
$('.myinput').on('select', function(){
$(this).val('');
});
This doesn't work because it just deletes my highlighted text, which is unexpected. I only want to reset the input on the keypress following the highlight.
2: Include an if statement in my input event that checks if there is a selection within the input:
$('.myinput').on('input', function(){
var highlightedText = window.getSelection();
if($(highlightedText).parent('.myinput')) {
//reset my input
}
});
This doesn't work because it seems to fire on every keypress, regardless of if there is any actual selection. (Are user inputs always treated as selected?)
3: Add a select event listener to the input element, and set a variable to true if there's a selection. Then, in my input event, check if the variable is true on keypress.
$(function(){
var highlightedText = false;
$('.myinput').on('input', function(){
if(highlightedText = true) {
//reset my input
}
//do stuff
highlightedText = false;
});
$('.myinput').on('select', function(){
highlightedText = true;
});
});
I really thought this one would work because a basic console log in the select function only fires when I want it to – when text in the input is highlighted, but not when other text is highlighted and not when text is entered into the input. But alas, when I change that to a variable toggle, it seems to fire on every keypress again.
So the question is: How can I fire a function on input only if text in my input is highlighted?
I have found this question that suggests binding to the mouseup event, but it seems like overkill to check every single click when I'm only worried about a pretty particular situation. Also, that solution relies on window.getSelection(), which so far isn't working for me.
I've also found another question that suggests to use window.selectionEnd instead of window.getSelection() since I'm working with a text input. I tried incorporating that into option 2 above, but it also seems to fire on every keypress, rather than on highlight.
This answer is not about text selection at all.
But still solve your problem to refilter text when highlighted text is being replaced with new input.
var input = document.getElementById('ok');
var character = document.getElementById('char');
var previousCount = 0;
var currentCount = 0;
input.addEventListener('input', function(){
currentCount = this.value.length;
if (currentCount <= previousCount){
/*
This will detect if you replace the highlighted text into new text.
You can redo the filter here.
*/
console.log('Highlighted text replaced with: ' + this.value);
}
previousCount = currentCount;
char.innerHTML = this.value;
});
<input type="text" id="ok">
<div id="char"></div>
I'll agree with others that you will save yourself some trouble if you change your filtering strategy - I'd say you should filter all content from scratch at each keypress, as opposed to filtering successively the content that remains.
Anyway, to solve your immediate problem, I think you can just get the selection and see if it is empty. You can modify your second attempt:
$('.myinput').on('input', function(){
// get the string representation of the selection
var highlightedText = window.getSelection().toString();
if(highlightedText.length) {
//reset my input
}
});
EDIT
As this solution seems to have various problems, I can suggest another, along the lines of the comment from #Bee157. You can save the old search string and check if the new one has the old as a substring (and if not, reset the display).
var oldSearch = '';
$('.myinput').on('input', function(){
var newSearch = $('.myinput').val();
if (newSearch.indexOf(oldSearch) == -1) {
// reset the display
console.log('RESET');
}
oldSearch = newSearch;
// filter the results...
});
This approach has the added benefit that old results will reappear when you backspace. I tried it in your codepen, and I was able to log 'RESET' at all the appropriate moments.

How to detect if user has left the input field?

Suppose I have an input field,
<input id="city" placeholder="city">
and I want to detect whenever user leaves this field. How can I do so?
Normal javascript
var element = document.getElementById("ELEMENT_ID");
element.addEventListener("blur", function() { ... your code here ...});
jQuery
$("#ELEMENT_ID").on("blur", function() { ... your code here ...});
If, by any chance, you're implementing those self-emptying fields with predefined text, use placeholder attribute. If you're changing style based on focus, use :focus CSS selector. Also, change event is emitted if user leaves the field and changed it's contents.
When an element loses focus, the onblur event is fired.
var elem = document.getElementById('city');
elem.addEventListener("blur", function( event ) {
console.log('Elvis has left the city (input)!');
}, true);
https://developer.mozilla.org/en-US/docs/Web/Events/blur

Check if input field has a value to toggle some classes

I got an input field in my meteor-app and I want to check if there is some content, because the position of the input field depends on wether there is an input value or not. If the user begins typing (min. one character), the input field moves to the top of the page.
In my current solution I'm looking for a keyup event to check if there is a value. If there is a value, a class will be added and another one is removed.
If the input field is empty, it is just the other way round.
Template.search.events({
'keyup input': function(event, template) {
if (event.target.value.length) {
$('#wrapper').addClass('top');
$('#result').removeClass('hide');
}
else {
$('#wrapper').removeClass('top');
$('#result').addClass('hide');
}
}
});
My problems
1) I think that the keyup event not the best way as the user could paste some content or cut it.
2) If the user types 'anything', classes will be changed 8 times - although you don't see that, but it is quite bad coding, isn't it?
3) If I could avoid that multiple looping, I could use a toggleClass...
PS: Maybe it is useful to save some informations in a session var? (I'm just brainstorming)
To handle cut and paste operations in your field without requiring the field to lose focus, use the input event. You can also use jQuery's toggleClass to simplify your code:
Template.search.events({
'input input': function(event, template) { // first input is the event, second is the object
var hasContent = event.target.value.length > 0;
$('#wrapper').toggleClass('top',hasContent);
$('#result').toggleClass('hide',!hasContent);
}
});

html catch event when user is typing into a text input

Im just wondering how I go about catching the event when the user is typing into a text input field on my web application.
Scenario is, I have a contacts listing grid. At the top of the form the user can type the name of the contact they are trying to find. Once there is more than 1 character in the text input I want to start searching for contacts in the system which contain those characters entered by the user. As they keep typing the data changes.
All it is really is a simple type ahead type functionality (or autocomplete) but I want to fire off data in a different control.
I can get the text out of the input once the input has lost focus fine, but this doesnt fit the situation.
Any ideas?
Thanks
Use the keyup event to capture the value as the user types, and do whatever it is you do to search for that value :
$('input').on('keyup', function() {
if (this.value.length > 1) {
// do search for this.value here
}
});
Another option would be the input event, that catches any input, from keys, pasting etc.
Why not use the HTML oninput event?
<input type="text" oninput="searchContacts()">
I would use the 'input' and 'propertychange' events. They fire on cut and paste via the mouse as well.
Also, consider debouncing your event handler so that fast typists are not penalized by many DOM refreshes.
see my try:
you should put .combo after every .input classes.
.input is a textbox and .combo is a div
$(".input").keyup(function(){
var val = this.value;
if (val.length > 1) {
//you search method...
}
if (data) $(this).next(".combo").html(data).fadeIn(); else $(this).next(".combo").hide().html("");
});
$(".input").blur(function(){
$(this).next(".combo").hide();
});

How do I use jQuery to disable a form's submit button until every required field has been filled?

I have a form with multiple inputs, select boxes, and a textarea. I would like to have the submit button be disabled until all of the fields that I designate as required are filled with a value. And after they are all filled, should a field that WAS field get erased by the user, I would like the submit button to turn back to disabled again.
How can I accomplish this with jQuery?
Guess my first instinct would be to run a function whenever the user starts modifying any of the inputs. Something like this:
$('#submitBtn').prop('disabled', true);
$('.requiredInput').change(function() {
inspectAllInputFields();
});
We then would have a function that checks every input and if they're validated then enable the submit button...
function inspectAllInputFields(){
var count = 0;
$('.requiredInput').each(function(i){
if( $(this).val() === '') {
//show a warning?
count++;
}
if(count == 0){
$('#submitBtn').prop('disabled', false);
}else {
$('#submitBtn').prop('disabled', true);
}
});
}
You may also want to add a call to the inspect function on page-load that way if the input values are stored or your other code is populating the data it will still work correctly.
inspectAllInputFields();
Hope this helps,
~Matt
Here's something comprehensive, just because:
$(document).ready(function() {
$form = $('#formid'); // cache
$form.find(':input[type="submit"]').prop('disabled', true); // disable submit btn
$form.find(':input').change(function() { // monitor all inputs for changes
var disable = false;
$form.find(':input').not('[type="submit"]').each(function(i, el) { // test all inputs for values
if ($.trim(el.value) === '') {
disable = true; // disable submit if any of them are still blank
}
});
$form.find(':input[type="submit"]').prop('disabled', disable);
});
});
http://jsfiddle.net/mblase75/xtPhk/1/
Set the disabled attribute on the submit button. Like:
$('input:submit').attr('disabled', 'disabled');
And use the .change() event on your form fields.
Start with the button disabled (obviously). Bind an onkeyup event to each required text input, and an onchange or onclick to the select boxes (and any radio buttons/checkboxes), and when it fires, check whether all required inputs are filled. If so, enable the button. If not, disable it.
There is one loophole here, though. Users can delete the value of a text field without triggering the onkeyup event by using the mouse to "cut" the text out, or by holding down the delete/backspace key once they have deleted it all, and clicking the button before deleting it.
You can get around the second by either
disabling the button with onkeydown and checking if it is ok on onkeyup
checking for validity when the button is clicked
An idea from me:
Define a variable -with global scope- and add the value true- Write a submit function within your check the value above varibale. Evalue the the submit event only, if the value is true.
Write a function which ckecks all value from input fields and select fields. Checking the length of value to zero. if the value length of one field zero then change the value of the global variable to false.
After that, add to all input fields the event 'onKeydown' or 'onKeyUp' and to all select boxes the event 'onChange'.
I recommend taking a slightly different approach and using jquery's validation http://docs.jquery.com/Plugins/validation. The tactic you are suggesting is prone to security holes. The user could easily using firebug enable that button and then submit the form.
Using jquery validation is clean and it allows you to show error messages under the required fields if so desired on submit.

Categories