How to trigger a function from click on document - javascript

Here's my situation: I've got a field that once the user double click, it'll edit the field. That's fine and working. I've got two functions: ok and cancel. Cancel disables the editing mode. ATM, the user has to click cancel to disable the editing mode. What I'd like to is to allow the editing mode to be disabled when the user clicks anywhere else on the page. How can I accomplish this with Angular?
EDIT: I'm adding my markup (Note: this is Jade):
tr(ng-repeat="user in users | filter:searchText"s)
td(ng-dblclick="editItem(user)", hm-double-tap="editItem(user)", ng-blur="cancelEditing()")
span(ng-hide="user.editing") {{user.name}}
form(ng-submit="doneEditing(user)", ng-show="user.editing", class="inline-editing-2", ng-blur="cancelEditing()")
input(type="text", class="form-control", ng-model="user.name")
button(class="btn btn-success mr-1", ng-show="user.editing", ng-click="doneEditing(user)")
span(ng-click="doneEditing(user)").fa.fa-check-circle
button(class="btn btn-warning mr-1", ng-show="user.editing", ng-click="cancelEditing(user)")
span(ng-click="cancelEditing(user)").fa.fa-times-circle
As you can see, I've got a hg-repeat on user. When double click on the td element it makes user.editing true so the form shows up. the cancelEditing(user) makes the variable false and only the field is displayed.
I've added ng-blur="cancelEditing()" on thetr,td,spanandform` and none of it worked.
Any ideas what am I missing?

Use ng-blur to bind your cancel event to the element. It will fire when the element loses focus.
IE: <input ng-blur="cancel()" />
Note: The cancel function must be within scope.
Angular ngBlur Docs
Update from comments:
Give the input element focus when your double tab event fires making the field editable. Your blur event is likely not firing because the input element never had focus.
You could do this from inside your editItem function or from inside the directive.
As an example:
yourApp.directive('hmDoubleTap', function(){
return function(scope, element, attr){
if(doubleTap) {
// Fire editItem(user)
// You could add your .focus() inside editItem().
// Or focus the first input element at the end of the directive.
element.find("input")[0].focus();
}
};
});

b1j's answer would work only if the element gains focus. Does hm-double-tap directive focuses the element after double click? If not you will have to trigger focus in editItem function.

Another approach would be to handle the click event on any other element like this:
$('#field-no-edit').click(function() {
$(this).hide();
$('#field-edit').show().focus();
});
$('body').on('click', function(e){
console.log($(e.target).attr('id'));
if ($(e.target).attr('id') != 'field-no-edit') {
console.log('not');
$('#field-no-edit').text($('#field-edit').val());
$('#field-edit').hide();
$('#field-no-edit').show();
}
});
JSFiddle

Related

.on('change' ...) doesn't trigger for data changed by JS

I am trying to trigger an event when an input textbox changed:
$('.packeta-selector-branch-id').on('change', function () { alert('helo'); })
This works only If I manually type something in the textbox, but in my case where an external javascript is setting the textbox value, not working.
I created a little jsfiddle to show this:
https://jsfiddle.net/6vnuqxa0/
To try out:
Click on Choose pickup point
Select something from list and click on "Choose this pick up point".
Any ideas how to resolve this issue?
The selected answer to jQuery watch for domElement changes? suggests binding to the DOMSubtreeModified event. I have tried iin your fiddle and it works! The answer does mention that this event may be deprecated, but it is worth looking into.
In your case, add an id to your div so that you have:
<div id="packeta-selector-branch-id" class="packeta-selector-branch-id"></div>
Then the following code will trigger the alert when the contents of that div change.
$('#packeta-selector-branch-id').bind('DOMSubtreeModified', function(e) {
if (e.target.innerHTML.length > 0) {
alert('helo');
}
});
Otherwise, I would look at the widget itself and try and determine if it fires any events on select. If so, you could attach some behaviour to that event.
trigger('change') when click button. but a ID or name on your input would be better
$(document).off('click', '.button select-branch').on('click', '.button select-branch', function(){
$('.packeta-selector-branch-id').trigger('change');
})

Override parrents onClick event with checkbox onClick?

First, sorry for my bad English.
I'm making a Coupons site and have trouble with selecting and deselecting the coupons. Each coupon is in a DIV 'box' in which there is a checkbox.
I made a onClick function on the DIV box (so the user can select the coupon by clicking on anything inside the DIV box. What I need now is, when the user want to deselect the coupon (by clicking on the checkbox inside the DIV box), I need to 'override' the DIV's onClick function (execute the checkbox onClick event, not the DIV's onClick event).
I know that everyone prefers some code as an example, but the question/problem is simple and I don't think you need all of my un'useless code inside the events/functions :)
Thanks :)
It seems like you want stopPropagation if the checkbox is being unchecked: http://jsfiddle.net/8Dcq8/.
$("div").click(function() {
alert("add"); // clicking anywhere in div to add coupon
});
$(":checkbox").click(function(e) {
if(!this.checked) { // if unchecking, remove coupon
alert("remove");
e.stopPropagation(); // don't run parent onclick
}
});
If the <div> click handler looks something like this:
var $boxes = $('div.box');
$boxes.on('click', function ()
{
// do whatever to select the coupon
});
Then the checkbox handler should look something like this:
$boxes.find('input[type="checkbox"]').on('click', function (event)
{
event.stopPropagation();
// do whatever to deselect the coupon
});
See event.stopPropagation().
You have to cancel bubbling. See here for an explanation.
You can use the jQuery Alternative, or create sub-elements with onClicks that don't target your checkbox. you might be able to use something like this also.
document.getElementById('element').checked.onreadystatechange=function(){
//code
}
good luck

Event Listener valid for HTML5 forms

New on HTML5 there's an "invalid" event, to which you can add a listener:
document.addEventListener('invalid', function(e){
var element = $(e.target);
element.addClass("invalid");
element.parent().addClass("invalid");
}, true);
Please note, this event just works when submitting the form... If I style the input input:invalid { background: red }, the style is applied when the user starts typing and his input is not valid. Is that event only fired on submit? I tried adding the listener to the inputs themselves instead of the document and it didn't work.
I add a listener in order to apply a style to the input's parent... Now, when the user corrects it, it's valid again... I know there's not a "valid" event, so, how can I accomplish it?
Ok, so here's a fiddle --> http://jsfiddle.net/Osoascam/ceArQ/7/
The invalid listener seems to be only fired on submit... I just wanted to know whether there's a way to add a handler just like there is for focus. See that if you type a
Thanks in advance,
Óscar
You should use the :invalid pseudo selector and the input or the change event, to solve your problem.
$(document).bind('change', function(e){
if( $(e.target).is(':invalid') ){
$(e.target).parent().addClass('invalid');
} else {
$(e.target).parent().removeClass('invalid');
}
});
Here is a simple fiddle http://jsfiddle.net/trixta/YndYx/.
If you want to remove the error class as soon as possible you should add the error class on change and remove it on the input event (Note: input event is much better than here suggested keyup, simply because it also is triggered on paste etc., but it only works with input elements, not textarea.)
And here is a fiddle using a mixture of input and change event:
http://jsfiddle.net/trixta/jkQEX/
And if you want to have this cross browser you can simply use webshims lib to polyfill. Here is a x-browser example:
http://jsfiddle.net/trixta/RN8PA/
Since these classes are always added when a form is submit, remove the class prior validating:
$('#myForm').submit(function(){
$('.invalid', this).removeClass('invalid'); // Remove all invalid classes
$(this).removeClass('invalid'); // If the parent = form.
// Normal validation procedure.
});
Expected result:
User initiates submit
onsubmit is triggered > All invalid class names within the form are removed.
The invalid events are triggered, and the invalid classes are added when necessary
Update
Added an extra block to your fiddle, see updated fiddle: http://jsfiddle.net/ceArQ/10/. I have implemented the checkValidity() method and the validity.valid property. Now, the classes are automatically added when the input is invalid.
document.addEventListener('keyup', function(e){
var input = e.target;
if (!$.nodeName(input, 'input')) return;
input.checkValidity();
var element = $(input).parent();
if(input.validity.valid) {
element.removeClass('invalid');
element.parent().removeClass('invalid');
} else { //Remove the lines below if you don't want to automatically add
// classes when they're invalid.
element.addClass('invalid');
element.parent().removeClass('invalid');
}
});
On key-up, the validity of an input element is checked. If it's valid, the invalid class is removed from its parent.
You could bind your validation logic to the focus and blur events, or to be even more responsive, to the keyup event.
$('input').keyup(function() {
if(isValid(this)) {
$(this).removeClass('invalid').parent().removeClass('invalid');
$(this).addClass('valid').parent().addClass('invalid');
}
else {
$(this).removeClass('valid').parent().removeClass('valid');
$(this).addClass('invalid').parent().addClass('invalid');
}
});
Have you tried using :valid to give an indicator as to whether a field is valid. and having forms that are invalid just keep their default styling.
Then calling form.checkValidity() in the submit handler? (The browser should then tell the end-user which form element is not valid).

Jquery : how to trigger an event when the user clear a textbox

i have a function that currently working on .keypress event when the user right something in the textbox it do some code, but i want the same event to be triggered also when the user clear the textbox .change doesn't help since it fires after the user change the focus to something else
Thanks
The keyup event will detect if the user has cleared the box as well (i.e. backspace raises the event but backspace does not raise the keypress event in IE)
$("#inputname").keyup(function() {
if (!this.value) {
alert('The box is empty');
}
});
jsFiddle
As Josh says, this gets fired for every character code that is pressed in the input. This is mostly just showing that you need to use the keyup event to trigger backspace, rather than the keypress event you are currently using.
The solution by Jonathon Bolster does not cover all cases. I adapted it to also cover modifications by cutting and pasting:
$("#inputname").on('change keyup copy paste cut', function() {
//!this.value ...
});
see http://jsfiddle.net/gonfidentschal/XxLq2/
Unfortunately it's not possible to catch the cases where the field's value is set using javascript. If you set the value yourself it's not an issue because you know when you do it... but when you're using a library such as AngularJS that updates the view when the state changes then it can be a bit more work. Or you have to use a timer to check the value.
Also see the answer for Detecting input change in jQuery? which suggests the 'input' event understood by modern browsers. So just:
$("#inputname").on('input', function() {
//!this.value ...
});
Another way that does this in a concise manner is listening for "input" event on textarea/input-type:text fields
/**
* Listens on textarea input.
* Considers: undo, cut, paste, backspc, keyboard input, etc
*/
$("#myContainer").on("input", "textarea", function() {
if (!this.value) {
}
});
You can check the value of the input field inside the on input' function() and combine it with an if/else statement and it will work very well as in the code below :
$( "#myinputid" ).on('input', function() {
if($(this).val() != "") {
//Do action here like in this example am hiding the previous table row
$(this).closest("tr").prev("tr").hide(); //hides previous row
}else{
$(this).closest("tr").prev("tr").show(); //shows previous row
}
});
Inside your .keypress or .keyup function, check to see if the value of the input is empty. For example:
$("#some-input").keyup(function(){
if($(this).val() == "") {
// input is cleared
}
});
<input type="text" id="some-input" />

How do a get buttons not to take the focus?

I want my (ExtJS) toolbar buttons not to grab the focus on the web page when they are clicked, but to do their "thing" while leaving the focus unchanged by the click. How do I do that?
Cancelling the default behavior of onmousedown prevents an element from getting the focus:
// Prevent capturing focus by the button.
$('button').on('mousedown',
/** #param {!jQuery.Event} event */
function(event) {
event.preventDefault();
}
);
document.activeElement stores the currently focussed element.
So on your toolbar, you can add a "mousedown" handler to this function :
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
Try this example :
<html>
<head>
<script>
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
</script>
</head>
<body>
<input type="text"/>
<input type="button" onmousedown="preventFocus()" onclick="alert('clicked')" value="Toolbar" />
</body>
</html>
This usually does the trick for me:
<button
tabindex="-1"
onclick="javascript:console.log('do your thing')"
>My Button</button>
From https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex:
A negative value (usually tabindex="-1") means that the element should be focusable, but should not be reachable via sequential keyboard navigation. It's mostly useful to create accessible widgets with JavaScript.
I don't think there's an easy way to do what you want to do because it's the browser's default behaviour.
You could of course blur() the button as soon as it is clicked, but that would simply unselect everything. To have the previously active object regain focus, you'd have to create a "memory" of sorts by adding a blur handler for every element to keep track of which element had/lost focus last (store the id of the element in a global and update it when an element loses focus).
The top-voted answer is technically correct, but depends on jQuery...
Here's a simpler example:
<span onclick="document.execCommand('bold', false);" onmousedown="event.preventDefault();"></span>
My solution is to replace <button /> with <div /> and style it as a button.
Looks like Div doesn't take a focus on it when you click it.
Because the toolbar buttons are just styled ordinary HTML button elements then this is an actual browser behavior, and you should think twice before changing it. But nevertheless...
You should be able to prevent the botton from receiving focus by just returning false from its onclick handler.
Maybe you should try to use stateful and state change properties for form fields or whatever to get focus back?
I would attach one blur event listener to all fields. This listener should save the field, that lost the focus, in a global variable.
Then all the toolbar button should get one focus event listener. This listener should focus the field, that was saved as described above.
This code should work, although it didn't test it
<script>
function focusor(){
document.getElementById('focus').focus;
}
document.onkeydown = focusor;
document.onclick = focusor;
</script>
<div style="width: 0px; height: 0px; overflow: hiddden;">
<button id="focus"></button>
</div>
What I have found, is you will have to make a dummy element, I found buttons to work best in this situation. put the button in a div and make the div 0px.
[do not make the div display none, some browsers will just ignore it]
Basically any click or button presses, it will focus on this dummy button.
I had a project very similar and whenever they pressed the down key it selected the first button on the page, this just focuses on the button over and over again.
Sort of jacked up, but it works.
All these answers are wack. Here's a very excellent trick that only uses CSS
<button type="submit" disabled>
<span>Submit</span> <!-- the <span> is the secret -->
</button>
Now in your css:
button[disabled] > * {
pointer-events: none;
}
The trick is the inner span has to be used, otherwise the button will still steal focus away from inputs.

Categories

Resources