Jquery - find closest text by class - javascript

Here is my HTML and script. I simply want to find the text of what is clicked, and include the text of it's previous element with a certain class, in the alert. Elements are not necessarily children/parents here.
So, if Prince5 is clicked, the alert should read King1: Queen3: Prince5
I'm close, but it's currently always giving the text as Queen1, since it's the first text in that column.
Any ideas?
<li class="king"><a href="#" >King1</a>
<span class="column1">
<li>Queen1</li>
<li> Prince1</li>
<li> Prince2</li>
<br>
<li>Queen2</li>
<li> Prince3</li>
<li> Prince4</li>
<br>
<li>Queen3</li>
<li> Prince5</li>
<li> Prince6</li>
</span>
<script type="text/javascript">
$("li a").click(function() {
var three= $(this).text(),
one = $(this).closest('.king').find('a:first').text();
two = $(this).closest(".column1").find("a.queen:first").text();
alert(one + ":" + two + ":" + three);
});
</script>

There are a number of problems with the HTML shown. A span is not a valid parent for the LI elements so I added a UL.
Basically you can go back up the ancestors of the clicked link, then sideways through previous siblings (that match .queen), then down again to the link on the first match:
$("li a").click(function () {
var three = $(this).text(),
one = $(this).closest('.king').find('a:first').text();
two = $(this).closest("li").prevAll("li:has(a.queen)").first().find('a').text();
alert(one + ":" + two + ":" + three);
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/7q3e9p7g/1/

Related

Unable to detect what div is clicked

I want every li tag to show the a's clicked href content below that li tag in a div. For example, I have a structure like this:
<ul id="ids">
<li class="res"><a class="item">item1</a></li>
<li class="res"><a class="item">item2</a></li>
<li class="res"><a class="item">item3</a></li>
</ul>
Dynamically if a's href is clicked, accordingly a function that shows the div <div class="testing"><h3>showing item1 here</h3></div> outside the <a> tag needs to be shown. That function could take time so until then Loading... needs to be shown. But I am unable to detect where the user has clicked as class names are the same. Once loading is done, loading should be hidden.
So far I have this:
$(document).on('click', '.item', function(e) {
e.preventDefault();
$(this).append('Loading');
//function code here
$(this).append('<div class="testing"><h3>showing item1 here</h3></div>');
});
Also, the function appends 1 div tag with class 'mydiv', that needs to be hidden. But again, since class names that get appended to every <li> is the same, I don't know where the click has taken place to detect it.
to summarise:
show a list of elements which has anchor tag
click on every element should show the content of the click in a div under that anchor tag
content of anchor tag can take 2 seconds so until then user should see "loading". Once it loads, loading should be hidden
You are looking for $.after() or $.insertAfter():
$(document).on('click', '.item', function(e) {
e.preventDefault();
var aTag = $(this);
if (aTag.siblings('.testing, .loader').length === 0) { //it's not loaded or loading
var loader = $('<div class="loader">Loading</div>');
loader.insertAfter(aTag);
//function code here
loader.remove();
aTag.after('<div class="testing"><h3>showing ' + aTag.html() + ' here</h3></div>');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="ids">
<li class="res"><a class="item">item1</a>
</li>
<li class="res"><a class="item">item2</a>
</li>
<li class="res"><a class="item">item3</a>
</li>
</ul>
If you want to avoid multiple loadings check if it exists before:
if(aTag.siblings('.testing, .loader').length === 0){ //it's not loaded or loading
}
You can get the href attribute using `$(this). This should work.
$(document).on('click', '.item', function(e) {
e.preventDefault();
var href = $(this).attr("href");
$(this).append('Loading');
$(this).append('<div class="testing"><h3>showing ' + href + ' here</h3></div>');
});
Also, the code above will append the div inside the a tag. You probably want to put it somewhere else using something like
$("#messageDiv").html('<div class="testing"><h3>showing ' + href + ' here</h3></div>');
To hide the loading message, you can wrap that in a span
$(this).append('<span class="loadingspan">Loading</span>');
Then in the code that runs when the load is complete, you can use
$('.loadingspan').hide();

Find closest element by attribute

I have this vote snippet, and I'd like to add a disabled class to the other button than what the user press. For example if user vote + on id 1 post then the - button would get a disabled class, but not the id 2 ones.
<span class="pull-right">
+
<span id="votes-1">0</span>
-
</span>
<span class="pull-right">
+
<span id="votes-2">0</span>
-
</span>
I already tried several things like .closest().find() but i couldnt make it work.
Traverse up to the parent of the clicked .vote element.
Use .not() and this to exclude the clicked .vote element.
$('.vote').click(function() {
var parent = $(this).parent();
$(this).removeClass('disabled');
parent.find('.vote').not(this).addClass('disabled');
});
.disabled {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<span class="pull-right">
+
<span id="votes-1">0</span>
-
</span>
<span class="pull-right">
+
<span id="votes-2">0</span>
-
</span>
$('.vote').click(function() {
var parent = $(this).parent();
$(this).removeClass('disabled');
parent.find('.vote').not(this).addClass('disabled');
});
You can use several approaches.
The following jQuery code is the shortest one. It takes all siblings and filters them with selector. The only item in array will be another button:
$(".vote").click(function()
{
$(this).siblings(".vote").addClass("disabled");
});
You can also do it this way. It is searching globally through the attribute value. It is good if you will need to disable something else in a document by attribute id.
$(".vote").click(function() {
var id = $(this).data('id');
$(".vote[data-id='" + id + "']").not(this).addClass("disabled");
});
Another option is traversing up to a parent, taking elements by selector and exlucing current one. Internally, it is almost the same as the first one.
$(".vote").click(function() {
$(this).parent().find(".vote").not(this).addClass("disabled");
});
Choose one which is the most preferrable.

How to extract the "href" attribute value from within the closest list item

My site has a column of checkboxes with IDs in sequential order like "keepbox1", "keepbox2", etc. Each checkbox resides within a list item, along with a href attribute like this:
<li>
Title
<br>
<input id="keepbox1" type="checkbox" class="kboxes" name="keepbox1" />
<label for="keepbox1">Keep</label>
<div class="tinybox" alt="tinypic1" id="tinypic1" style="display:none;">
Content Here
</div>
</a>
</li>
There is also an element on the page that I use as button
<a><label class="getFiles" for="lightbox-two">Submit</label></a>
When a user clicks this button, I have a script that loops through each variation of keepbox to see if a user checked it. If a particular keepbox is checked, I'd like to extract the href attribute's value in that particular li.
So if a user had checked keepbox1 from the demo code above, I'd like it to alert back "http://iNeedThisUrl.com".
I'm using the following script which successfully identifies a checked keepbox, but it's returning "undefined" in the alert box. I'm guessing I'm not grabbing the attribute properly. Any ideas? Thank you!
<script type="text/javascript">
$(document).ready(function() {
$('.getFiles').click(function() {
for (i = 1; i <= 100; i++)
{
if ($("#keepbox" + i).prop('checked'))
{
var addressValue = $("#tinypic" + i).closest("li").attr("href");
alert(addressValue);
}
}
});
});
</script>
Two issues:
1) you have closing anchor tag </a> without opening anchor tag as next sibling of div in li. you need to remove it.
2) div elements #tinypic+n are siblings of anchor element. You need to use:
$("#tinypic" + i).siblings("a").attr("href");
or
$("#tinypic" + i).prevAll("a").attr("href");
or
$("#tinypic" + i).closest("li").find("a").attr("href");
$(".kboxes").each(function(){
if ($(this).prop('checked')) {
var addressValue = $(this).closest("a").attr("href");
alert(addressValue);
return false;
}
});

Append sub-elements to its parent element only

I am trying to convert a bunch of menu dropdowns into multiple elements. I have been able to do this when theres only one dropdown on the page but once I add the others, my script seems to run through each menu multiple times. I am new to Javascript/Jquery but I was wondering if there was a way to make it only input to its parent element?
Here is my current script that works for a single dropdown:
$('.mylinks li').each(function() {
var inputClass = $('.mylinks .link').html().toLowerCase();
$('body').prepend('<select class="'+inputClass+'" onchange="window.location.href=this.options[this.selectedIndex].value"></select>');
$('a').each(function() {
var linkName = $(this).html();
var linkVal = $(this).attr('href');
$('select').append('<option value="'+linkVal+'">'+linkName+'</option>');
});
});
HTML
<div class="mylinks">
<ul>
<li>
Drop 1
Link 1
Link 2
Link 3
</li>
<li>
Drop 2
Link 1
Link 2
Link 3
</li>
</ul>
</div>
I have an example of this error here as well: http://jsfiddle.net/UdTcF/
You can try this code:
$(document).ready(function () {
$('.mylinks li').each(function () {
var inputClass = $('.mylinks a').html().toLowerCase();
var select = $('<select class="' + inputClass + '" onchange="window.location.href=this.options[this.selectedIndex].value"></select>');
$('body').prepend(select);
$(this).find('a').each(function () {
var linkName = $(this).html();
var linkVal = $(this).attr('href');
select.append('<option value="' + linkVal + '">' + linkName + '</option>');
});
});
});
Use a variable select to save the <select> you want to add, and late can add <option> to this variable using select.append().
And use $(this).find('a') instead of $('a') to find <a> in certain <li> but not all <a>.
Here is jsfiddle.
Here:
$('a').each,
you're selecting all a elements. I think that you want to select just only those in the current li. SO, just replace add:
$('a',this).each,
it will select only a elements which are children of this, eg the li element.

JQuery :has(), I need to select only children

I have some hierarchical data I am manipulating with JQuery, and I am trying to add some type of visual indication about which elements in my tree are selected. Here is a sample of the html I am generating (which we are manipulating):
<li>
<input class="selectedcheck" checked disabled type="checkbox" name="ign-130">
<input class="millermultiselect" type="checkbox" name="chk-130">
Egypt
<ul>
<li>
<input class="selectedcheck" checked disabled type="checkbox" name="ign-131">
<input class="millermultiselect" type="checkbox" name="chk-131">
Cairo
</li>
</ul>
</li>
All of this resides within a div#miller. The first check box (.selectedcheck), is used only to show that a region is selected (it starts out hidden, and is shown when the parent region is selected, so if you clicked the .millermultiselect in Egypt, the .selectedcheck in Cairo would become visible replacing Cairo's .millermultiselect). What I would like to do is also add a class to any li which contains (as a direct child) a checked check box. I am attempting to accomplish this with the following JQuery code:
$("#miller li:has(input:checkbox:checked:visible)").addClass('chosen');
The problem that I am having is that since all of the regions are composed of nested ul's, checking a check box in any region also adds .chosen to any li higher in the tree... so clicking the check box for Cairo adds the .chosen class to Egypt and Africa.
Anyone have an idea how I would go about only capturing li's that have a visible, checked check box as a direct child?
Here is my whole js file just in case it provides insight:
$(document).ready(function() {
$(".selectedcheck").hide();
showSelected = function(){
$("#miller li").removeClass("chosen");
$("#miller li:has(input:checkbox:checked:visible)").addClass('chosen');
};
$("#miller a").click(function(event) {
event.preventDefault();
$("#miller li").removeClass("selected");
$(this).parent().addClass("selected");
data = $(this).data();
$("#addChild").attr("href", "addChild.php?parentid=" + data.self).html("Add item under " + data.nodename);
$("#addSibling").attr("href", "addChild.php?parentid=" + data.parent).html("Add item next to " + data.nodename);
$("#editRegion").attr("href", "editRegion.php?id=" + data.self).html("Edit " + data.nodename);
$("#deleteRegion").attr("href", "deleteRegion.php?id=" + data.self).html("Delete " + data.nodename);
$("#addResort").attr("href", "addResort.php?regionid=" + data.self).html("Add resort to " + data.nodename);
$("#miller ul ul").hide();
$(this).parents("#miller ul").show();
$(this).siblings("#miller ul").show();
showSelected();
});
$("#miller .millermultiselect").click(function(event) {
$("#miller li").removeClass("selected");
$(this).parent().addClass("selected");
$("#miller ul ul").hide();
$(this).parents("#miller ul").show();
if($(this).is(':checked')) {
$(this).parent().find(".millermultiselect").not(this).hide();
$(this).parent().find(".millermultiselect").not(this).removeAttr("checked");
$(this).parent().find(".selectedcheck").show();
} else {
$(this).parent().find(".millermultiselect").not(this).show();
$(this).parent().find(".selectedcheck").hide();
}
$(this).siblings(".selectedcheck").hide();
$(this).siblings("#miller ul").show();
showSelected();
});
});
You can use the direct descendant selector and then get it's parent:
$("#miller li > input:checkbox:checked:visible").parent().addClass("chosen");
how I would go about only capturing li's that have a visible, checked check box as a direct child?
How about reversing the problem?
$('input:checkbox').is(':visible').is(':checked').parent('li')

Categories