Jquery keypress event does not add character to textbox - angularjs

Through code, I would like to manually enter some characters to a input using JQuery.
I am using this:
var e = jQuery.Event("keypress");
e.which = 97;
$("input").trigger(e);
I also have a eventhandler attached to the input that is logging the triggered event correctly along with the keyCode etc.
In other words the event does seem to be fired through code and get handled too. However, the value on the input is still empty. The character is not added there. Not sure what is going on.
EDIT: I am creating automated tests that is supposed to trigger a keypress on my autocomplete compoment. the App is written using AngularJS. It is not possible to put all the code and html on JSFiddle etc. I have isolated this to be a Jquery problem as stated above.
I know I can use val() directly but that will not trigger the keypress events necessary for the plugin to work

Did you tried:
$("input").keypress(function(){
$(this).prop('value', 'your value')
});

Related

How do I return focus to an element when the entire page changes?

I have a complicated setup. My application is driven by a set of "rules" which dictate what the user interface is. The UI is rendered by looping through the rules and creating the individual dropdowns. Initially, everything renders properly. However, once a user makes a change to the UI, other rules may be affected. In my application, an api call is made, which then returns a modified set of rules. In the attached plunker, I've simplified things such that only the new set of rules is applied, which causes the page to re-render. The problem is that my users would like to be able to tab between all of the entries on the page and make changes. However, once the page is re-rendered, the currently selected page element is now gone nothing has the focus. I've tried to put the focus back on the proper element by tracking a common Id, but to no avail.
Using either of these doesn't seem to work.
var el = document.getElementById(focusId);
el.focus();
angular.element(el).focus();
I've also tried using the autofocus attribute on the dropdown that I want to have focus, but that didn't work either. I'm using angularjs 1.2. Any ideas are appreciated.
http://plnkr.co/edit/ND9PKqULIOlixWR4XChN?p=preview
If you want to assign auto focus dynamically to a element on the DOM from angular you can use this:
var myEl = angular.element(document.querySelector('select'));
myEl.attr('autofocus',"attr val");
You can also pass in an id like: angular.element(document.querySelector('#focusId'));
You can look here for a prior answer which may be of some more help!
-Cheers!
Problem here is, you are trying to focus the element before the blur event completes. So you need to execute the focus code after blur event. Async execution of your focus code would solve the problem. You can use either setTimeout or $timeout.
setTimeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
or
$timeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
dont forgot to inject $timeout to your controller if you are using second code. Hope this helps :)

TinyMCE + AngularJS - Keyup event triggered before update of ng-model

I am fairly new to AngularJS and the TinyMCE editor. I was fiddling around with the keyup event available in TinyMCE when I came across this issue. In the keyup handler, I am accessing one of the controller's ng-model. Here's where things start to get odd. I printed out the ng-model value and the editor's content for comparison purposes and it would seem that the ng-model is lagging by 1 key/character behind i.e. the editor's content is the most up to date. I have a hunch that the model is updated only after the keyup event is finished. That would explain why I am seeing two values here. Perhaps I am going about this the wrong way? Speaking of which, what would be the best/correct way to access the editor's contents? Through angular or TinyMCE?
If it helps, the code looks something like this (They are placed under a single controller):-
...
this.text = "";
var viewModel = this;
this.tinymceOptions = {
setup: function (editor) {
editor.on('keyup', function (e) {
console.log(editor.getContent());
console.log(viewModel.text);
});
},
...
};
Has anyone encountered this problem before?
Thanks for the help in advance!

Why is my event handler always one keystroke behind, and how does $timeout fix this?

I'm totally confused as to why my keypress event handler is always one keystroke behind. http://plnkr.co/edit/w3FAXGd5zjrktO6DgOpD?p=preview
<body ng-controller="myController">
<form>
<input ng-keypress="handleKeypress($event)" />
</form>
</body>
Controller:
myapp.controller('myController', function($scope, $timeout){
$scope.handleKeypress = function(ev){
console.log(ev.target.value); //always one keystroke behind
//$timeout(function(){console.log(ev.target.value);}); //works!
};
});
Why is $timeout necessary and why/how does it work? (A newbie-friendly answer is preferable)
I understand that with the keypress event the character hasn't yet been inserted into the DOM, but I'm confused because the Hello World example at angularjs.org responds before a key is released. Their example doesn't use a custom event handler, but clearly Angular is updating the model before the keyup event, so I'd like understand more about doing this in a custom event handler.
idursun's answer points out that event.which is available on keypress, and I thought Angular might be using String.fromCharCode(), but I don't see anything in the Angular source to this effect.
You should use ng-keyup. Keypress might not always work as expected.
From the jQuery documentation:
Note: as the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms.
Because event target in your example is an input element and keystroke has not been processed by the element yet so value of that element is always one keystroke lagging. This gives a chance to the event handler to reject key press.
You can check pressed key value by looking at which field of the event object.
tl:dr - event.target.value + event.key will give you the latest value.
The reason why it is one step behind is that it allows for you to reject the keypress by triggering the event prior to it is registered. This is not a bug, but a feature.
But if you want to get the most updated value, here's a workaround:-
html:-
<input type="text" (keypress)="myFunction($event)">
JS:-
myFunction(event) {
event.preventDefault()
console.log('latest input field value => ', event.target.value + event.key)
}
Update:-
Add event.preventDefault() to avoid double characters.
Update 2:-
The events are called in this order:-
Keydown
Keypress
updateview
Keypress
updateview
keyup
So if you can change this event to keyup then you will get the latest value and wouldn't have to do additional changes in the method.

Webshims - Show invalid form fields on initial load

(Follow on questions from Placeholder Hidden)
I'd like my form to validate existing data when it is loaded. I can't seem to get that to happen
I jQuery.each of my controls and call focus() and blur(), is there a better way than this? I tried to call ctrl.checkValidity(), but it wasn't always defined yet. When it was, it still didn't mark the controls.
I seem to have a timing issue too, while the focus and blur() fire, the UI does not update. It's as if the Webshims are not fully loaded yet, even though this fires in the $.webshims.ready event.
I also tried to call $('#form').submit(), but this doesn't fire the events as I expected. The only way I could make that happen was to include an input type='submit'. How can I pragmatically case a form validation like clicking a submit button would?
Here's a jsFiddle that demonstrates the problem. When the form loads, I want the invalid email to be marked as such. If you click the add button it will be marked then, but not when initially loaded. Why?
Focus and blur in the control will cause it to be marked.
BUT, clicking ADD will too (which runs the same method that ran when it was loaded). Why does it work the 2nd time, but not when initially loaded?
updateValidation : function () {
this.$el.find('[placeholder]').each(function (index, ctrl) {
var $ctrl = $(ctrl);
if( $ctrl.val() !== "" && (ctrl.checkValidity && !ctrl.checkValidity()) ) {
// alert('Do validity check!');
$ctrl.focus();
$ctrl.blur();
}
});
}
I see this in FF 17.0.5. The problem is worse in IE9, sometimes taking 2 or 3 clicks of ADD before the fields show in error. However, I get errors on some of the js files I've liked 'due to mime type mismatch'.
This has to do with the fact, that you are trying to reuse the .user-error class, which is a "shim" for the CSS4 :user-error and shouldn't be triggered from script. The user-error scripts are loaded after onload or as soon as a user seems to interact with an invalid from.
From my point of view, you shouldn't use user-error and instead create your own class. You can simply check for validity using the ':invalid' selector:
$(this)[ $(this).is(':invalid') ? 'addClass' : 'removeClass']('invalid-value');
Simply write a function with similar code and bind them to events like change, input and so on and call it on start.
In case you still want to use user-error, you could do the following, but I would not recommend:
$.webshims.polyfill('forms');
//force webshims to load form-validation module as soon as possible
$.webshims.loader.loadList(['form-validation']);
//wait until form-validation is loaded
$.webshims.ready('DOM form-validation', function(){
$('input:invalid')
.filter(function(){
return !!$(this).val();
})
.trigger('refreshvalidityui')
;
});

Display n time ago on various items using jquery, [issue with new elements generated after the loading the DOM]

I am using Jquery plugin http://timeago.yarp.com/ for showing time.
Issue is timeago will not take effect for dynamically generated items.
$(document).ready(function() {
$(".timeago").timeago(); // works perfectly fine for the items which are loaded on page load
//$(".timeago").live(timeago()); // gives me an error ie timeago is not defined
//$(".timeago").live($(".timeago").timeago()); // gives me an error too much recursion.
jQuery.timeago.settings.allowFuture = true;
});
From some google search I got to know something ie:
Using live is the same as using bind, except that it is limited only to the events click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup.
Now how can do it cause I dont have any click event? How can I bind this?
.live() and .bind() assign callbacks to event. In your case, you don't have an event to assign the function to and so it fails.
You can, in theory, assign your callback to a custom event. You will however have to manually trigger the event (using .trigger()) whenever your item is generated. For example:
$("abbr.timeago").live("timeago", function() {
$(this).timeago();
});
// ... and in the bit that generates your item
$new_item.trigger("timeago")
Demo: http://jsfiddle.net/ZjuW4/9
Of course, using .live() in this situation is purely academic and does not really serve a good purpose.
If you do have access to the code that's generating the items, you can simply chain in the call to .timeago() as the items are generated, i.e. http://jsfiddle.net/ZjuW4/3/
take a look in this topic
here was discussed how to put timeago on dynamically loaded items
for example the results of an ajax request.
Activate timeago on newly added elements only
PS: allowFuture does not have anything to do with putting timeago on newly created items on your page. it just allows dates in the future (f.e. "in 3 days", "next week")

Resources