Event on one element to trigger event on another - javascript

I'll use a specific example but this could apply to any event on one element triggering any event on another. Suppose that we want to focus an <input> when we click a <span>. We can do this using a directive like:
<div ng-controller="Ctrl">
<span ng-focus-other>focus</span><input>
<div>
app.directive("ngFocusOther", function () {
return function (scope, element) {
element.bind("click", function () {
this.nextSibling.focus();
});
};
});
However this does not seem very Angular. This would also not work were there any changes to the DOM (e.g. if <input> were moved before <span>). It would also be nice if the same code could work on multiple groups of <span>-<input> combinations perhaps each with a different DOM layout.
What is the Angular way of using one event to trigger another event on another element?

Why not simply have clicking the span set a boolean called "inputFocused" to true and then let the input pay attention to that scope variable. I.e.
<span ng-click="inputFocused = true">FOCUS</span>
<input ng-focus="inputFocused" value="GIVE ME FOCUS">

Related

Vue3: How to receive #click event on parent DOM?

I have following structure in Vue3 template:
template:
/*html*/
`<div class='element1' #click='onClick'>
<img :src='image_url' />
<p>{{desc_text}}</p>
</div>`,
data() {
return {
image_url: "path/to/image",
desc_text: "Some text goes here"
}
},
methods: {
onClick(e) {
console.log(e);
}
}
Depending on where I click, console outputs e.target to be either <img>, <p> or <div class='element1'>, and it will have e.path set to array of elements, from the element that was topmost under the pointer to the bottom-most, while currentTarget is set to null.
I am looking for a solution where event handler would be called with e.target that points to the element that has #click listener added, in this case, <div class='element1'>. Not to point to any of it's children.
I've been looking at Vue3 documentation on the event bubbles, but so far no modifiers fit my need.
For example #click.self will only fire if e.target is the element that has the event listener, however, if pointer was above any of it's children, it will not fire.
Right now, I use pointer-events: none; styling on all children elements I don't want to have their own pointer event handling, which appears to have sufficient coverage. However, I'm surprised if Vue does not have any option on it's own to handle this case, maybe I am missing it?
I've read through Vue3 Event Modifiers document, but no option listed there does this.
In some cases, I have dozen of sub-elements in an element (eg. a card showing image, title, paragraph etc.), and I'd like entire element to be one big button to click on, with just one #click event handler set.
You can achieve same result (maybe better) without using event target but by passing arguments to the onClick handler.
What I usually do when rendering clickable list is that I pass the entire item
<div v-for="element in elements" :key="'element' + item.id" class="'element' + element.id" #click="onClick(element)">
<img :src='element.image_url' />
<p>{{element.desc_text}}</p>
</div>
It then become easy to handle the onclick as you already have the element you want at your disposal
onClick(element) {
console.log(element);
}

Get data of specific node element on click

I'm trying to get specific data depending on which node element the user is clicking. I have 4 elements that I have targeted using the querySelectorAll code. What I want to accomplish is that if I click the first element I will console.log that specific data, and if I select the third element I will get that data logged. I've tried a couple of things, but haven't got it to work yet.
function selectedSplit() {
var macroSplits = document.querySelectorAll(".card");
console.log(macroSplits[0].childNodes[3].childNodes[1].innerHTML);
}
It's unclear where you are using selectedSplit - Wether or not it is being used as the event listener return function. But using an onClick event listener, you're return function will be passed the information you need.
If you want to accomplish this in the markup, you could do -
<div class='card' onClick="selectedSplit"></div>
Then you can simply access it via event.target
function selectedSplit(event) {
var thisCard=event.target;
console.log(thisCard.innerHTML);
}
event.target has the clicked element:
d.onclick = e => console.log(e.target)
<div id=d>
<button><b>b</b></button>
<button><i>i</i></button>
<button><u>u</u></button>
<button><s>s</s></button>
</div>

What is the angular way of hiding all specific divs with the same class

I want to do a simple thing:
I have an app, which has certain divs that in need to show (Only the specific one) and hide if clicked somewhere outside of it (All with the specific class for example).
This is easy using jquery:
$('some-class').style('display','none') //psuedo code here
How should i do the same with angular js?
A specific reason to do so:
I want to build a simple select drop-down (I don't want to use one that exist, i want to understand this...), when i click one, it suppose to open a div right beneath the button, when i click outside of it, it suppose to close not only this one, but some other elements like it in the app.
one point worth mentioning: Not all my select boxes are pre-rendered, some are dynamically added (inside directive), so not all of the are in the $scope, but inside them directives which has isolated scope.
Its better to make directives for these kind of things:
Make a directive for toggleDisplay as following
app.directive('toggleDisplay', function() {
return function(scope, element) {
element.bind('click', function() {
element.toggleClass('unneeded-class'); // or something else
});
};
});
and then you can apply this directive to any element in the html:
<div toggle-display></div>
You can make a drop down logic or kindof accordion etc following this pattern
How do i listen to a click anywhere in the app, that when i click it
and "that" element is not the select box, close all the select boxes?
let suppose you have that opend/dispalyed div that you want to hide when you click outside of it . give it a class "divvy" and attach the following directive to its wrapping container:
app.directive('toggleFocus', function() {
return function(scope, element) {
element.bind('click', function() {
if(!element.hasClass('divvy'))
angular.element(document.querySelector('.divvy')).css({display:'none'})
});
};
});
html:
<div toggle-focus>
<div class="divvy"></div>
</div>
It's in the angular documentation: https://docs.angularjs.org/api/ng/directive/ngShow
<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="myValue"></div>
<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="myValue" class="ng-hide"></div>
just attach ng-show="whateverValue" to each div you want to hide/show based on whether "whateverValue" is true/false

When a Div class is clicked, alert it's inner content's Div Class

How do i even put these, let me try. In the following sets of codes, i want to click 'parentclass' and have an alert value of 'child1' and when i click the class below it which is 'Parent 2' have an alert fire with a value of 'child2'
So this must alert the content of that class only and not the entire class.
Here's some Javascript in Jquery.
var childclass = $('.childclass').html();
$('.parentclass').click(function(e) {
alert (childclass)
});
$('.childclass').click(function(e) {
e.stopPropagation()
e.preventDefault()
});
And HTML
<a href="" onClick="return false">
<div class='parentclass'>
Parent 1
<div style="display:none" class="childclass">child1</div>
</div>
</a>
<a href="" onClick="return false">
<div class='parentclass'>
Parent 2
<div style="display:none" class="childclass">child2</div>
</div>
</a>
This line var childclass = $('.childclass').html(); doesnt make sense as it doesn't know which element in particular you mean. The result of that will just be child1child2 which is just a concatenation of the .html() of all the elements with class childclass. This is obviously not what you want.
Therefore you should dynamically find the child with a class of childclass upon receiving the click event.
$('.parentclass').click(function(e) {
alert($(this).find('.childclass').html())
});
Also, you should know that your child class event handler is useless as we don't care if the event gets propogated downwards. If you DID care, then your e.stopPropagation() and e.preventDefault() should be in the event handler of the parent class.
You need to fetch the html of the clicked parent element within the click handler
$('.parentclass').click(function (e) {
alert($(this).find('.childclass').html())
});
$('.childclass').click(function (e) {
e.stopPropagation()
e.preventDefault()
});
Demo: Fiddle
Several ways you can go about this.
First, if your HTML will not be dynamic (elements already exist when page loads), then you can select elements by the parent class name and assign click event as so:
$('.parentclass').click(function(e) {
// the first variable here is selecting the inner elements having class 'childclass'
// keep in mind, if more than one child having that class is present within this parent, it will select all of them
var child = $(this).find('.childclass');
// here we alert the text of the inner child found
// if it is more than one, you will have undesired results. you may want to specify `.first()`
alert(child.text())
})
For newer jQuery you can also use $('.parentclass').on('click', function(e) {.
If you expect any pieces of parentclass to be dynamic, then you'll want to delegate the event based on either a static parent to the parents or document. This can be like so:
$(document).on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Or, if you have a static (already there when page loads) wrapping element, give it an ID like `parentClassWrapper' and assign the click event dynamically as:
$('#parentClassWrapper').on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Some helpful links:
jQuery API
jQuery Selectors
.click()
.on()
Some info on Event Delegation
jquery on vs click methods
jQuery .on('click') vs. .click() and .delegate('click')
jquery .live('click') vs .click()
I made several adjustments to your html that are worth noting. There's no need for the <a> tag. Don't use inline js - onlick in your html. Note that I wrapped the text inside of the div in the <a> tag instead. This markup is more semantic. Also, move your styles to css rather than in the html.
<div class="parent">
<a>Parent 1</a>
<a class="child">child of parent 1 contents</a>
</div>
<div class="parent">
<a>Parent 2</a>
<a class="child">child of parent 2 contents</a>
</div>
css:
.parent > .child { /* good practice: only select an immediate child of the parent */
display: none;
}
The other answers here are using find() to select the child, but I recommend children() instead. For example, if you had additional nested .childs, find() will select them all, but children() will only select direct .childs of the parent, so it is better in this case. I also recommend using the console for debugging rather than alert.
Live demo here (click).
$('.parent').click(function() {
var $child = $(this).children('.child');
var cls = $child.attr('class');
console.log(cls);
$child.show(); //added so that you can click the child
});
$('.child').click(function() {
var html = $(this).html();
console.log(html);
//if you just want the text, use this instead:
var text = $(this).text();
console.log(text);
});

How to select element relative to 'this' in javascript

I have the following:
<div class="tab-pane" id="message">
<textarea rows="4" cols="50" id="send_message" placeholder="Enter text ..."> </textarea>
OK
Cancel
I want to bind the click method to the 'div' element , and when one of the child 'a' elements is clicked do separate things. I am trying to distinguish between them using the button text, but the following is not working:
$(function(){
$('#message').click(function(){
if($(this + ">a").is(":contains(OK)")) {
console.log("OK!!");
How can I fix this?
Okay there are two ways of doing this:
.find(selector)
if(this).find("a").is(":contains(OK)")) {
console.log("OK!!");
OR
$(selector,context)
if("a",this).is(":contains(OK)")) {
console.log("OK!!");
In javascript, this is essentially the context of the current function. In jQuery event callbacks, this is set to be the source element of the event - not the selector string, which is what you are treating it as.
Instead, you want to do a test like: if($("a", this).is(":contains(OK)")) {
This works because the second parameter to the jQuery selector is the context to search in, so you are only searching for the a tags under the source element of the click.
Binding the click element to the Div, then checking the text string of the A tags will make both events happen on every click. You want to bind 2 separate click events on each A tag. Add an ID to each A tag, then try this code
$('#okLinkID').click(function(){
console.log("OK!!");
});
$('#cancelLinkID').click(function(){
console.log("Cancel!!");
});
//Attaches only one listener to the #message div and listens for any 'a' element within it to be clicked.
$('a','#message').on('click',function(){
var $this = $(this),
btnText = $this.text();
console.log(btnText);
});
http://jsfiddle.net/YA7Ds/

Categories