Register single click on list item child elements - javascript

I have the following HTML structure:
<li class="is_tab" id="geometry_tab">
<a data-toggle="collapse" href="#geometry_tab_collapse">
<i class="pe-7s-plugin"></i>
<p>Geometry
<b class="caret"></b>
</p>
</a>
<div class="collapse" id="geometry_tab_collapse">
<ul class="nav">
<li class="is_tab" id="pipe_geometry_tab">Pipe Geometry</li>
</ul>
</div>
</li>
Using jQuery, my objective is to retrieve the <li> id on click, irrespective of whether the user clicks li.is_tab, li.is_tab > a, li.is_tab > a > p, or li.is_tab > a > i. Moreover, I would like the same event handler to be capable of distinguishing between clicks on #pipe_geometry_tab and #geometry_tab, i.e., simply returning a single, correct id when one or the other is clicked.
My question is this:
Given the following snippet,
$(<selector>).on("click", function(){...})
is there a <selector> that will register a single click on li.is_tab regardless of whether it or its a, i, or p children is clicked?
If not, I would appreciate any recommendations on how to go about this.
PS I've tried quite a few things, but rather than bloat this post with them, I'm hoping someone more experienced feels this has an obvious solution.

$('li.is_tab').on("click", function(e){...});
^^ that should work fine and anything that is clicked on the li will be handled.
If you want the li that was clicked you can look at e.currentTarget if you want to see the actual element that was clicked you can use e.target
So if you want the id of the li that was clicked you can use e.currentTarget.id

Related

Binding button to element inside ng-repeat

I'm trying to bind a button inside ng-repeat to that unique element for the button within the same repeat, pretty hard to word for me so I'll give a code snippet.
<li ng-repeat="thing in listOfThings track by $index">
<div ng-model="text"> text < /div>
<button ng-click="highlightText()" />
</ li>
Although not exact, that's the idea. The problem is that when I click the button, it will highlight all the texts inside the listOfThings.
Note: assume that the text is given a ng-class that highlights when a boolean is true, and not highlighted when it's false, toggled by the button.
Any idea how to "bind" that button to only that one text so it doesn't highlight everything else?
I've tried to google for it, it might be a duplicate question but not sure how to search for something this specific so please link the answer if it's a duplicate.
If I understand your example correctly, your ng-class is going to apply the class to all items inside of your repeat based on the click event.
You need to track the button selection individually, by each element in the list. Something like:
HTML:
<li data-ng-repeat="thing in listOfThings track by $index">
<div data-ng-model="text" data-ng-class="{ 'highlighted': thing.Selected }"> < /div>
<button data-ng-click="highlightText(thing)" />
</li>
JS:
$scope.highlightText = function(thing){
thing.Selected = true;
}
CSS:
.highlighted{
background-color: yellow;
}
EDIT: Good suggestion made by skyboyer, this could be made cleaner by moving the highlighted function and not tracking the flag on the thing variable.
HTML:
<li data-ng-repeat="thing in listOfThings track by $index">
<div data-ng-model="text" data-ng-class="{ 'highlighted': selected }"> < /div>
<button data-ng-click="selected = true" />
</li>

Add a link to switch to the next tab

Pretty simple question please : How can I add a button at the bottom called "Next" to switch to the next tab without having to get to the top of the page and click on the next tab ?
In fact, I'm copying the tab's code existing in the top of my page but it's not working.
<a id="aba_2" href="#aba_2">Next</a>
This is the existing HTML code that you can also find here https://codepen.io/DiogoAlvaro/pen/wWzNEm :
<ul id="abas" class="teste">
<li class="selecionada"><a id="aba_1" href="#aba_1">Aba 1</a></li>
<li><a id="aba_2" href="#aba_2">Aba 2</a></li>
<li><a id="aba_3" href="#aba_3">Aba 3</a></li>
</ul>
<div id="conteudos">
<div id="conteudo_1" class="conteudo visivel">
<p>Conteúdo da Aba 1</p>
</div>
<div id="conteudo_2" class="conteudo">
<p>Conteúdo da Aba 2</p>
</div>
</div>
The javascript code is :
var abas = document.getElementById("abas");
var conteudos = document.getElementById("conteudos");
function limparSelecao(){
abas.getElementsByClassName("selecionada")[0].classList.remove("selecionada");
conteudos.getElementsByClassName("visivel")[0].classList.remove("visivel");
}
abas.addEventListener("click", function(event){
var abaClicada = event.target.id;
var itemSelecionado = abaClicada.substring(abaClicada.lastIndexOf("_"));
limparSelecao();
event.target.parentElement.classList.add("selecionada");
conteudos.querySelector("#conteudo"+ itemSelecionado).classList.add("visivel");
});
The problem I'm noticing is the switching functionality between tabs is working only one time. It means if I copy the same tabs' code another time it will not work.
Can you help me with this issue please ?
Thanks in advance.
As you can see in your javascript, when you click on a tab things will be done in the background in order to show you its content.
When a tab is clicked the class selectionada is added to your tab as well the class visivel is added to your content in order to show it.
So that sad if you want to use a button you will need then some additional javascript which has to add the class selectionada to the tab and the class visivel to the content you want to display.
Additionally the button has to know which the current open (selectionada) tab is in order to open the next one. Also if you use a Next button it seems to me logical that you will also need a Previous button.
I don't know your programming skills but this process involves some logic in order to be done.
If you are confident with javascript and jquery you can do this with some little effort.
Anyway you know now why just using a button as you ar doing, will not work.

Replace all childnodes that have classname attribute in java script

I am using Selenium Webdriver for my project. I have a webpage where there are multiple menu items which in turn has sub menu items. I want to replace the classname attribute for all child elements under the nav-left-main div tag with "" (space) so that all elements are visible in the main page to click (instead of navigating to each menu->sub menu)
Basically i want to find all elements with classname under id=main and replace them with ''. How do i do that with JavaScriptExecutor in selenium webdriver?
<div id="nav-left-main">
<div>
<a class="left-nav-icons icomoon-icon-users3 " title="Users" href="#Users-tab">
<div id="Users-sub" class="nav-left-subnav">
<div id="Users-tab" class="hidden-menu">
<ul class="level3menu">
<li>
<i class="cm-icon18 iconfont-arrow-sans-right" style="margin-top:-2px;margin-left:-17px;"></i>
<a>Users</a>
<ul class="second-level-hidden-menu" style="margin-left:5px;margin- top:10px;">
<ul class="second-level-hidden-menu" style="margin-left:5px;margin-top:10px;">
<ul class="second-level-hidden-menu" style="margin-left:5px;margin-top:10px;">
</li>
</ul>
<ul>
<li>
<a id="AdminGroups" class="$item.className" title="" href="cms?action=groupList&pageTitle=Groups">Groups</a>
</li>
</ul>
<ul>
</div>
</div>
</div>
This might work for you:
var main_div = document.getElementById("nav-left-main");
var all_childs = main_div.getElementsByTagName("*"); // get all child elements
for (var i=0; i<all_childs.length; i++)
{
if ( all_childs[i].hasAttribute("class") ) all_childs[i].className = ""; // or all_childs[i].removeAttribute("class")
}
I'm assuming you're trying to write some automated tests. Consider this: if you modify the UI content, you just might affect the behavior of something else on the page (e.g. some JS assuming those class-attribute values might stop functioning).
Alternatively, inject CSS (via STYLE or LINK) that changes the appearance and visibility of those elements (hint: !important). However, even this, theoretically, is not ideal solution, because like-JS (for example) might go bananas for the same reason.
I'm not experienced in testing webpages, but isn't the point of Selenium to automate behavior of a human user? In other words, maybe the best would be to write test-code to activate the menu the same way human-user would (mouseover, etc).

jQuery update li class attribute href after ajax call

I'm using my Wordpress site and have a popup modal window that just presents some radio buttons (#input_1_1). When changing value of the radio button field an ajax call is run and performs a simple mySql table update. All goes well and I would like to perform a change of the text of the href I used to open the window in the first place.
Below is the javascript I got so far, but the second JQuery row from the bottom does not execute the change I want. Regardless of even just trying to change the simple target url.
jQuery(document).ready(function(){
jQuery("#input_1_1").change(function(){
jQuery("body").css("cursor", "wait");
var commitmentID = jQuery("#gform_1 input[type='radio']:checked").val();
jQuery('#popmake-710').popmake('close');
jQuery.ajax({
url:"<?php bloginfo( 'wpurl' ); ?>/wp-admin/admin-ajax.php",
type:'POST',
data:'action=gf_submit_1_1&commitmentID=' + commitmentID,
success:function(results)
{
//Here is the problem I've been working on for too many hours/days now
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563").attr('href',"http://www.TheSameUrlButILikeADifferentTextToIt.com");
//See line above
jQuery("body").css("cursor", "default");
}
});
});
});
This is how the HTML for that part of the page looks like
<div id="et-secondary-menu">
<ul id="et-secondary-nav" class="menu">
<li class="bp-menu bp-profile-nav menu-item menu-item-type-custom menu-item-object-custom menu-item-152"></li>
<li class="popmake-fast-select-commitment current_commitment_text menu-item menu-item-type-post_type menu-item-object-page menu-item-563" style="cursor: pointer;">
<a href="http://www.myoriginalurlisjustfine.com/">
<i class="wp-svg-heart heart"></i>
THIS IS THE TEXT THAT I WANT TO HAVE CHANGED BY THE JQUERY AND IS THE TEXT PRESENTED IN THE SECONDARY WORDPRESS MENU
</a>
</li>
while you use
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563")
and this will just select the li which not has a href attr so you need to use (> a)
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563 > a").attr('href',"http://www.TheSameUrlButILikeADifferentTextToIt.com");
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563").attr('href',"http://www.TheSameUrlButILikeADifferentTextToIt.com");
you are seleting the li here not a
change it to
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563 > a").attr('href',"http://www.TheSameUrlButILikeADifferentTextToIt.com");
Use
jQuery("#et-secondary-nav > li.popmake-fast-select-commitment.current_commitment_text.menu-item.menu-item-type-post_type.menu-item-object-page.menu-item-563 a").attr('href',"http://www.TheSameUrlButILikeADifferentTextToIt.com");
to change the href. As others pointed out, you weren't change the <a> but the <li>.
Check https://api.jquery.com/category/selectors/ for reference on jQuery selectors.

Using .click instead of onclick and getting a variable value

I have seen that the inline/html events like onclick, mouseover etc are being used less and less and it is advised to register events using Javascript.
I currently have some HTML like:
<ul id="supported-locations">
<li onclick="setLocationId(32);">Mexico</li>
<li onclick="setLocationId(35);">Mongolia</li>
</ul>
Which works fine but I want to now do this without the "onclick" in the HTML but still be able to retrieve the ID number.
The <li> elements are retrieved via AJAX while the user types into an input box it queries the database and retrieve the data without loading the page.
When the user clicks on one of the countries it will run the setLocationId function which just simply sets a hidden HTML form element with the ID of the selected country so I can use that once the form is submitted.
How do you register an event listener for these <li>'s when the countries and their ID's will always be different and changing depending on what the user types into the box?
Use a data attribute to hold the number. On the onclick event, read the attribute on the element that was clicked.
HTML:
<ul id="supported-locations">
<li data-code="32">Mexico</li>
<li data-code="35">Mongolia</li>
</ul>
JavaScript:
$("#supported-locations").on("click", "li", function() {
var li = $(this);
console.log(li.data("code"));
});
Example:
JSFiddle
<ul id="supported-locations">
<li data-id="32">Mexico</li>
<li data-id="35">Mongolia</li>
</ul>
in jQuery
$('#supported-locations').on('click','li',function(){
setLocationId($(this).data('id'));
})
<ul id="supported-locations">
<li data-id="32">Mexico</li>
<li data-id="35">Mongolia</li>
</ul>
jQuery(function(){
$('#supported-locations li').click(function(){
alert($(this).data('id'))
})
})
I recommend giving a class to the dynamically loaded elements, then use jquery .on(http://api.jquery.com/on/) method to register event listeneres to elements belonging to a class, even those that are dinamically loaded..
Then you could just read out the data stored in the element(in the form of data-something attributes).
<ul id="supported-locations>
<li id="32">Mexico</li>
<li id="35">Mongolia</li>
</ul>
//Jquery
$("#supported-locations > li").on('click',function(){
setLocationId($(this).attr('id'));
});
When you register your event, you still have the ability to use this, which is linked to the HTML element.
In other word, you still can do something like that
<li id="YOUR_ID">Mexico</li>
And get the id of the li tag
You can attach an event handler to the li:
<ul id="supported-locations">
<li id="location32">Mexico</li>
<li id="location35">Mongolia</li>
</ul>
$("#supported-locations li").click(function() {
alert($(this).attr("id"));
});
http://jsfiddle.net/puL95/
try this.
$("#supported-locations li").click(function() {
alert("me")
}

Categories

Resources