Cancelling propagation of the onchange event of a select control - javascript

I have a select control nested inside a table cell. The Table row that contains the table cell has an onclick event. When I click on the select control to change the value the onclick event of the row is fired.
I've tried using the stoppropagation method on the onchange event but it doesn't seem to work.
Below is my code
xxxxxxx.Helper.DDGoto = function (o, e) {
e.stopPropagation();
var path = $(o).val();
if (path != null) {
this.Goto(path);
}
}
<tr onclick="somemethod()">
<td>some text</td>
<td>
<select onchange="xxxxxxx.Helper.DDGoto(this, event)">some options</select>
</td>
</tr>

The event triggered with the onchange event on your select is not firing the onclick event on your tr, they are not of the same type. They are two different events. That's also why stopping propagation of the onchange event does not stop the onclick event to be triggered.
You should instead in your onclick handler check if the select element was clicked or not:
somemethod = function (event) {
if (event.target.nodeName === 'SELECT') {
// The select was clicked, stopping...
return;
}
// The select was not clicked, go ahead...
}
To get the event in your handler, you need to change your declaration to:
<tr onclick="somemethod(event)">
I used the nodeName property for the example, but you could also use the type property of the target or any other method to detect if the select was clicked or not.
You can check this fiddle for an example.

When you click on select tag, both onChange and onClick event is fired!
I solved this by creating a onClick handler along side onChange handle and then calling e.stopPropogation() function.
Worked for me!
<select (click)="StopPropogation($event)" (change)="textureChanged($event,i)" class="form-control" id="sel1">
<option selected="isTextureSolid(nodule.texture)">solid</option>
<option selected="isTexturePartSolid(nodule.texture)">part-solid</option>
<option selected="isTextureNonSolid(nodule.texture)">non-solid</option>
</select>
Javascript code:
StopPropogation(e: Event) {
e.stopPropagation();
console.log('Click event stopped from propogating');
}
textureChanged(e: Event, i: number) {
e.stopPropagation();
console.log('textTure Changed');
let btnId = 'save' + i.toString();
document.getElementById(btnId).style.display = 'block';
document.getElementById(btnId).style.visibility = 'visible';
}

Related

how to make a javascript event occur only if another event to the same element is first triggered?

I have attached a mouseleave event to the select tag. But I want this event should only occur if a user first clicks the select tag and then removes the mouse from.
function loseFocus() {
var dateSelect=document.querySelector('[name="dayCount"]');
dateSelect.blur();
console.log('mouse leave event triggered')
}
<select name="dayCount" onmouseleave="loseFocus()">
<option >op1</option>
<option >op2</option>
<option>op3</option>
</select>
You can define a variable as false and run a click event on your drop down, then in your call back for the click event set that variable to true. Then in your blur event call back a conditional to check if the variable is true.
You may want to do a mouseout event if you don't want to have to click off the drop down menu after a selection has been made.
let dateSelect = document.querySelector('[name="dayCount"]');
let clicked = false;
function changeClick(){
clicked = true;
}
function checkFocus(){
clicked === true ? console.log('BLUR FIRED -> select has lost focus') : null;
}
function mouseOut(){
clicked === true ? console.log('MOUSEOUT FIRED -> Your mouse is not over the select element') : null;
}
dateSelect.addEventListener('click', changeClick);
dateSelect.addEventListener('blur', checkFocus);
dateSelect.addEventListener('mouseout', mouseOut);
<select name="dayCount">
<option >op1</option>
<option >op2</option>
<option>op3</option>
</select>

How to keep track of focused elements in a form

I'm new to vuejs and I'm wondering what would be the best way to keep track of the latest focused input/textarea in a form in order to programatically modify their values from the parent component.
Example
Form
Input1
Input2 -> focused
Textarea
Button (onclick -> appends "hello" to the focused input)
Answer:
You can create a data property that tracks the currently focused/last focused input element. In the below example this is called current_focus.
To do this you could use the focus event - but because focus doesn't bubble you would have to apply it to each individual input element manually.
It is easier to provide a focusin event handler to the parent. This event, unlike focus, bubbles up the DOM from any child to its parent. This allows you to utilize an event delegation pattern.
Event Delegation means that you apply one handler to a parent for an event, then do something depending on the source of the event. This means when we receive a focusin event, we can simply check if the focused element is an input element, then update our data property ( current_focus )
Code Sandbox Example:
https://codesandbox.io/s/focus-handler-vzip0
Code Example:
FocusDemo.js
<template>
<div v-on:focusin="updateFocus">
<input name="one">
<br>
<input name="two">
<br>
<input name="three">
<br>
<button #click="handleClick">Add Text To Focused</button>
</div>
</template>
<script>
export default {
name: "FocusDemo",
data: function() {
return {
current_focus: undefined
};
},
methods: {
updateFocus: function(e) {
let element = e.target;
if (element.matches("input")) {
this.current_focus = element;
}
},
handleClick: function(e) {
if (this.current_focus) {
this.current_focus.value = "Button was clicked!";
}
}
}
};
</script>

click event on HTML select element

I would like to listen a click event in the event. The change event is only fired when I select other items, but I need an event to be triggered even I click the selected one.
For example, when I select Apple, change event triggered. Then I select Apple again, I need an event to be triggered as well.
$("#fruit").on('click', function() {
console.log("click event");
});
$("#fruit").on('change', function() {
console.log("change event");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="fruit">
<option>Apple</option>
<option>Pear</option>
</select>
I solve that problem wrapping the select element with a div element and using the onclick over the div, after that the function javascript call the select element using the id, like this:
HTML:
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<div onclick="ReadSelected()">
<select id="fruit">
<option value="Apple">Apple</option>
<option value="Pear">Pear</option>
</select>
</div>
Javascript:
function ReadSelected(){
var selectedValues = $("#fruit").val();
console.log(selectedValues); //if you select apple will be ['Apple']
}
According to the jQuery docs:
The change event is sent to an element when its value changes. This event is limited to elements, boxes and elements. For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.
As there is no change when you click on 'Apple' when 'Apple' is already selected, it looks like the 'click' event is your best option. Why exactly do you need the change event to fire when you click the same option? Maybe there is a better solution than firing the change event in this case?
You may check condition on click like below to achieve what you want .
var flag = false;
$('#fruit').on('click', function() {
if (flag) {
console.log($(this).val());
flag = false;
} else {
flag = true;
}
}).on('blur', function() {
flag = false;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="fruit">
<option>Apple</option>
<option>Pear</option>
</select>

Prevent function execution twice within two triggered events

I have the following code:
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
The problem with the above is when I click myButton both events are triggered and triggerProcess() is fired twice which is not desired.
I only need triggerProcess() to fire once. How can I do that?
Small demo
You can have a static flag that disables any more triggers once the first trigger has occurred. Might look something like this:
var hasTriggered = false;
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
function triggerProcess () {
// If this process has already been triggered,
// don't execute the function
if (hasTriggered) return;
// Set the flag to signal that we've already triggered
hasTriggered = true;
// ...
}
For resetting the hasTriggered flag, that's entirely up to you and how this program works. Maybe after a certain event occurring in the program you'd want to reenable the ability to trigger this event again — all you'd need to do it set the hasTriggered flag back to true.
You can use the mousedown event, which will fire before the input is blurred, and then check if the input has focus by checking if it's the activeElement, and if it does have focus, don't fire the mousedown event, as the change event will fire instead.
Additionally, if you want a mousedown event to occur when the value hasn't changed, and the change event doesn't fire, you'll need a check for that as well
var myInput = $('#test1'),
myButton = $('#test2'),
i = 0;
myInput.change(function(e) { // this triggers first
$(this).data('prev', this.value);
triggerProcess();
});
myButton.mousedown(function(e) { // this triggers second
var inp = myInput.get(0);
if (document.activeElement !== inp || inp.value === myInput.data('prev'))
triggerProcess();
});
function triggerProcess() {
console.log('triggered : ' + (++i))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="test1">
<br />
<br />
<button id="test2">
Click
</button>
In a fairly typical scenario where you have an input with a button next to ie, eg quick search.
You want to fire when the input changes (ie onblur) but also if the user clicks the button.
In the case where the user changes the input then clicks the button without changing input focus (ie no blur), the change event fires because the text has changed and the click event fires because the button has been clicked.
One option is to debounce the desired event handler.
You can use a plugin or a simple setTimeout/clearTimeout, eg:
$('#inp').change(debounceProcess)
$('#btn').click(debounceProcess);
function debounceProcess() {
if (debounceProcess.timeout != null)
clearTimeout(debounceProcess.timeout);
debounceProcess.timeout = setTimeout(triggerProcess, 100)
}
function triggerProcess() {
console.log('process')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="inp">
<button id="btn">Click</button>
Use a real <button>BUTTON</button>. If you click on input text, alert is triggered, then once you leave the input text to click anywhere else, that unfocuses the input text which triggers the change event, so now 2 events have been triggered from the text input.
This is an assumption since the code provided is far from sufficient to give a complete and accurate answer. The HTML is needed as well as more jQuery/JavaScript. What is myInput and myButton actually referring to, etc.?
So I bet if you change...
var myButton = $('{whatever this is}'); and <input type='button'>
...TO:
var myButton = $("button"); and <button></button>
...you should no longer have an event trigger twice for an element.
This is assuming that triggerProcess() is a function that does something that doesn't manipulate the event chain or anything else involving events. This is an entirely different ballgame if instead of click() and change() methods you are using .trigger() or triggerHandler(), but it isn't. I'm not certain why such complex answers are derived from a question with very little info...?
BTW, if myInput is a search box and myButton is the button for myInput, as freedomn-m has mentioned, simply remove:
myButton.click(...
Leave myButton as a dummy. The change event is sufficient in that circumstance.
SNIPPET
var xInput = $('input');
var xButton = $('button'); //«———Add
xInput.on('change', alarm);
xInput.on('click', alarm);
xButton.on('click', alarm);
function alarm() {
return alert('Activated')
}
/* For demo it's not required */
[type='text'] {
width: 5ex;
}
b {
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='f1' name='f1'>
<input type='text'>
<input type='button' value='BUTTON TYPE'>
<label><b>⇦</b>Remove this button</label>
<button>BUTTON TAG</button>
<label><b>⇦</b>Replace it with this button</label>
</form>

how to prevent onclick event to trigger in select option

I have a select that triggers an event when it is clicked. But I want to prevent it to trigger again when I click in the respective option.
Is there a way to do that?
How about you try using onchange. So if there is not change in what is selected. Nothing is triggered.
Just use onchange event. Here is an example: https://jsfiddle.net/rafb0vyw/2/
$('#sel').on('change', function() {
alert('change');
})
You could check the event.target property, which will have a different value. Like this:
var select = document.querySelector('select');
var span = document.querySelector('span');
select.onclick = function(e) {
// show e.target in snippet (you would remove this line in your code):
span.textContent = 'You clicked on ' + e.target.tagName + '.' +
' Current selected value is ' + select.value;
if(e.target.tagName !== 'SELECT') return; // ignore
// The rest of your event handling comes here...
// This will only be executed when you click the SELECT and not the OPTION.
};
<select>
<option value = 'A'>Option A</option>
<option value = 'B'>Option B</option>
</select>
<span></span>
Make sure to have the event parameter (named e in the above example) defined in your event handler function.

Categories