jQuery select dropdown value based on value of other dropdown - javascript

I'm trying to get my head around jQuery, but I have trouble figuring out plain arrays vs jQuery arrays, and DOM elements vs jQuery elements.
So here's an example I try to do. The example is simple really, but I need some hand-holding :-p so I'll be verbose in my requirements hoping that the answers will be, in turn, descriptive.
I have two <select> drop-downs, with IDs #version and #target.
When I click a button, I want to select in #target the option following with the same name as the last-but-one value in #version. (the item WILL exist)
Example: #version has options: a,b,c,x. #target has options a,b,c,d,h,m.
I click the button. What should happen is:
read the last-but-one option in #version: "c"
find the option with the same name in #target: the 3rd (i.e. index is 2)
set the selected value in #target to the one after "c", i.e. "d" (the 4th, index 3)
Here's a fiddle with the example.
For the 1st step, I think I figured it out:
var latestVersion = $("#version option").get(-2).text;
//side-note: why does .text work but not .val() ? oh, .get() returns a DOM element
// so How do I get back to a jQuery element?
// $($("#version option").get(-2)).val() works but looks ugly
For step 2, I tried this:
var target = $("#target option:contains(latestVersion)");
but it doesn't work. And there's GOT to be a better way than manually iterating all the values searching for the right one.
Step 3: ??.

Using 1st step as you figured try the following:
$('#button').click(function(){
var latestVersion = $("#version option").get(-2).text;
//index of LAST-BUT-ONE
var target=$("#target option[value="+latestVersion+"]").index();
//Setting next index value
$("#target").prop("selectedIndex",target + 1);
});
http://jsfiddle.net/GpBDY/16/

.val() does not work on an option element, but it does work on a select element:
var v = $( "#version" ).val();
gives you the element selected in the dropdown #version.
The following line will not do what you want:
var target = $("#target option:contains(latestVersion)");
That is because latestVersion is treated as the value "latestValue" and not as the name of a variable. To use the value of the variable latestValue, put latestValue outside the string like:
... contains(" + latestVersion + ")...
You might be interested in the jQuery method .next() in combination with your code in step 2 to get the value of the next option element. Be aware that if there is no next element, the value will be "undefined".

You can do this using nth-child to select value of version and using that set the value of target this way:
$('#button').click(function(){
var latestVersion = $("#version option:nth-child(3)").text();
$("#target").val($('#target option[value="'+latestVersion+'"]').next().text());
});
Demo Fiddle

i am not sure i understand you are looking for, but i think that you want something like this:
$('#button').click(function(){
var arrVersion = $("#version option");
var latestVersion = $(arrVersion[arrVersion.length - 2]).val();
$("#target").val(latestVersion);
var actualSelected = parseInt($("#target").prop("selectedIndex"));
$("#target").prop("selectedIndex", actualSelected + 1);
});
http://jsfiddle.net/GpBDY/9/

Related

jQuery .remove() Not Working After Valid Selection of Element

JSFiddle: https://jsfiddle.net/coh1xr77/5/
I need to delete an <LI> DOM Element correctly selected with a Selector based on its exact content. My list contains a set of Time LI's and my choice is to delete the first one in the list, 12:15am, based on the exact text match, when I click the button.
I can see that my selection is correct because I'm getting an [Object] reference in the alert box, rather than "Undefined".
However, the subsequent remove() on this element does nothing: the element remains.
var myselection = '12:15am';
$('#remove').click(function() {
var current = $('.ui-timepicker-list li').filter(function() {
return $(this).text() === myselection;
});
alert('current = ' + current); // This works, element found
$(current).remove(); // This does nothing (or doesn't remove properly)
});
You need to change the condition to check if the li's innerText starts with the selected time string. Like: $(this).text().indexOf(myselection) == 0
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/11/
Update
Considering that all time values have the bracketed relative time strings at the end, you could try splitting based on that bracket (, and compare with the first part of that string. Like: $(this).text().split('(')[0].trim() == myselection
Here's the fiddle with that: https://jsfiddle.net/coh1xr77/12/
Update 2
If you are absolutely certain that the structure of li elements will not change, you could access the text using the childNodes. Like: $(this)[0].childNodes[0].textContent == myselection;
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/14/

how to get second last element using java script

I have a drop down of 7 options. I need to get the value of second last option using java script. I wrote something but it is not working .
$('.checkbox4').on('click', function(e) {
var last_chekbox4 = $('.checkbox4:last.prev()');
if (last_chekbox4.is(':checked')) {
$('.checkbox4').prop('checked', false);
$(this).prop('checked', true);
}
});
Use prev() method
$('.checkbox4:last').prev()
If there is some other element in between then use
$('.checkbox4:last').prevAll('.checkbox4').first()
FYI : Above methods don't work if elements are not siblings.
UPDATE :
Or get the last within the collection which excluded the last one using :not() and jQuery :last.
$('.checkbox4:not(:last):last')
Or by the index using eq() method.
var $col = $('.checkbox4');
// get element by index, where index starts from 0
var $ele = $col.eq($col.length - 2);
You have 7 elements. Use nth-of-type selector
$(".checkbox4:nth-of-type(6)");
To select the second last option

This jQuery toggleClass behaviour seems strange, am I doing this correctly?

I have a CSS rule for hiding elements with a class="hidden" and I'm using jQuery to toggle this class on and off on whatever ID i click on so I can make elements disappear.
Why does this not work?
$(this).attr('id').toggleClass("hidden");
but this does?
var x = "#" + $(this).attr('id');
$(x).toggleClass("hidden");
I know that the id is being taken correctly on the first example, but it seems that to toggle the class I have to add a "#". I haven't seen any examples of others having to resort to this so I'm wondering what madness I have here.
Many thanks
$(this).attr('id').toggleClass("hidden");
You are chaining events here. $(this).attr('id') already returns you a string. So you are technically doing "someid".toggleClass("hidden") which doesn't makes sense.
In your second example, you are actually selecting the same element again via id and firing your method, which is right
.attr('id') returns a string, not an element.
Let's pretend your element has an ID of myThing. Here's what your code translates to:
// 1
"myThing".toggleClass("hidden");
// 2
var x = "#myThing";
$("#myThing").toggleClass('hidden');
But really, if you're getting the ID from this, there's no reason to extract the ID in the first place. Just use this directly.
$(this).toggleClass('hidden');
You can simply use:
$(this).toggleClass("hidden");
$(this) is the actual element you're working with, so you can use this to directly toggle classes with.
In your examples, $(this).attr('id') is a string, and not an element.
This code works, because you're taking the ID (As a string), and selecting the ID on the webpage.:
//Store the id into a string
var x = "#" + $(this).attr('id');
//Pass the ID back into jQuery, and find the element
$(x).toggleClass("hidden");

JQuery find element that has specific value without loop

I am trying to figure out if there is a way (without using any loops like each etc..) to look up element that has specific value, something like
var myElment = $('.container');
var child = $('.container-child');
myElement.find(child /* That has value of test */);
value is related to .val() of child element, so text inside it.
By the Attribute Equals Selector which is [attr=value].
So, to do that, just use
$(".container .container-child[value='test']")

jquery find() method

Please consider the following code :
<!DOCTYPE html>
<html>
<style>
p{ width:200px; }
</style>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<p><span>Hello</span>, how are you?</p>
<p>Me? I'm <span>good</span>.</p>
<script>
$(document).ready(function(){$("p").find($("*")).andSelf().css("background- color","blue"); });
</script>
</body>
</html>
The output is the whole document turning into blue color while I only wanted the paragraph and span inside it to turn blue.
If I use $("p").find(" * ") instead of $("p").find($(" * ")) then everything shows according to my need. Can anyone work out the difference between the two approach?Thanks!
Note: Please everyone note that I know there are easier methods to do this stuff,but I just want to know why this didn't work..
Disclaimer: The other answers already suggest better selectors to
achieve your goal, but I understand you want to know why andSelf()
ends up matching all the elements in the document, so I'll try to
explain that.
First, as you know, andSelf() adds the previous set of elements on the stack to the current set. So, in your case, it seems it should add the <p> elements to the set containing their descendants:
$("p") // match the paragraphs
.find($("*")) // match all the elements that descend from a paragraph
.andSelf() // add the paragraphs to the elements above
However, the above assumes that find($("*")) is the previous set of elements, and that's simply not the case here. The first hint about this comes from the documentation for find():
As of jQuery 1.6, we can also filter the selection with a given jQuery
collection or element. With the same nested list as above, if we start
with:
var $allListElements = $('li');
And then pass this jQuery object to find:
$('li.item-ii').find( $allListElements );
This will return a jQuery collection which contains only the list
elements that are descendants of item II.
The last sentence is particularly interesting: it seems to imply that the jQuery object passed to find() is filtered in order to match the descendants of the elements in the original set. If that's indeed the case, the logic would be inverted, and the previous element set would end up being $allListElements instead of the set returned by find().
A look at the jQuery source code shows that's exactly what happens:
find: function(selector) {
var self = this, i, l;
if (typeof selector !== "string") {
return jQuery(selector).filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if (jQuery.contains(self[i], this)) {
return true;
}
}
});
}
// [...]
}
So, when you write:
var elements = $("p").find($("*")).andSelf();
You're actually writing the equivalent of:
var self = $("p"), i, l;
var elements = $("*").filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if ($.contains(self[i], this)) {
return true;
}
}
}).andSelf();
As you can see, the previous element set is actually $("*") instead of the set returned by find($("*")) because of the logic inversion. Therefore, all the elements in the document end up being legitimately added to the current set by andSelf().
You just need
$("p").css("background-color","blue");
To change the color or all the p tags in the document. Is there some specific reason for the way you have done it?
The $("*") has no context, so it selects every element in the document. You want to find all elements within the currently selected element, so you need to just pass the string to find.
However, it's completely unnecessary and you could just apply the style to the p (as the span is a child you don't to apply it to that too):
$("p").css("background-color","blue");
Note that in that line above I've used background-color with no spaces, unlike in your question. I'm guessing it was just a typo when you wrote the question, but it won't work if you put spaces in the property name.
You don't have to do any of that. Just do this.
$(function() { $("p").css('background-color', 'blue'); });
Note: $(function() {}); is the same as $(document).ready(function(){});
Edit: Since you have two, you may have to do this:
$(function() { $("p").each(item, function() { item.css('backround-color', 'blue'); })});
Edit2: Based on your comments, you want this:
$(function() { $("p").find('span').andSelf().css('background-color', 'blue'); });
The difference between $("p").find(" * ") and $("p").find($(" * ")) is that in the second one you're passing find() a jquery object instead of a regular selector string.
EDIT: I just tried it out. Looks like adding the andSelf() makes it select the entire document somehow. The logical process would be select p > find all elems inside that match everything in the document > select self(p) > color, but it seems to be going wrong at the select self bit.
I think it(the andSelf()) just selects the object passed to find(), which is $('*'), and so selects everything.
If you want to select all P's simply use
$(document).ready(function(){
$("p").css("background-color","blue");
});
No reason to complicate stuff
If you want to select the spans inside you can do something like
$(document).ready(function(){
$("p > span").css("background-color","blue");
});
** Update **
Your selector attribute in your find query is bad, you shouldn't have it like $("*") but only "*". However the $("p").find("*")... will only select any elements inside the <p> tag so trailing the find method with an andSelf will make the selection ambiguous.

Categories

Resources