I have a chrome extension that when I click it, it will click all the same element buttons on a page and then after the function is done, I want it to select all the 'P's on the drop down. I have multiple 'pf' classes on the page and will need to set all of the to P. The first function is working, when it gets to the second function, there is an error showing the option.length is undefined. My question is how do it get all the option counts inside a class?
function clickUpdate(_callback) {
var updateArray = document.getElementsByClassName("updateButton");
[].slice.call(updateArray).forEach(function(item) {
item.click();
});
console.log("this is the array legnth: " + updateArray.length);
_callback();
}
//Get select object
var objSelect = document.getElementsByClassName("pf");
//Set selected
setSelectedValue(objSelect, "P");
function setSelectedValue(selectObj, valueToSet) {
clickUpdate(function(){
console.log("I am done with the first function");
});
for (var i = 0; i < selectObj.options.length; i++) {
if (selectObj.options[i].text == valueToSet) {
selectObj.options[i].selected = true;
return;
}
}
}
<select class="pf">
<option selected="selected" value="">Not Run</option>
<option value="P">Pass</option>
<option value="F">Fail</option>
<option value="N">N/A</option></select>
Here's your problem:
//Get select object
var objSelect = document.getElementsByClassName("pf");
This doesn't just return the select dropdown - it returns an HTMLCollection (ie, a group of elements) with any elements matching that class name. Even if there's only one present, it'll come back as a collection. But your setSelectedValue function isn't expecting a collection, just a single element - that's why you get the undefined error.
There are a few ways you can handle this, depending on what you're doing elsewhere on the page:
You can use document.querySelector('.pf') to return the first element with that class - do this if you're only going to have one .pf on the page, or only want to manage one of them.
Alternately, you can use document.getElementsByClassName('pf')[0] to achieve the same thing.
Or you can give the select an id and use document.querySelector('#pf') or document.getElementById('pf')
If, on the other hand, you plan to have multiple .pf elements that all work this way...you'll have to do some refactoring first. But that's a whole other discussion.
Related
I have this code:
var elementSelector = 'select.myClass';
$(elementSelector).each(function(i){
/*
* if (several conditions return true) {
*/
doSomeDOMChanges(); //Change the DOM and add several more <select class="myClass">
/*
* }
*/
});
Problem is, within that loop, $(elementSelector) is not reevaluated, and its' size remains the same throughout the entire loop. $(elementSelector).length for example would stay 18, even though it actually increased to 20 within the 4th iteration.
My question is, how to force JQuery to re-select $(elementSelector) on the next iteration (without "resetting" the loop / repeating previous iterations, of course).
Thank you.
mark used classes with an attribute or some class, and select which are not used
var elementSelector = $('select.myClass:not[data-used=1]');
$(elementSelector).each(function(i){
$(this).data('used', 1)
if (several condition return true) {
doSomeDOMChanges(); //Change the DOM and add several more <select class="myClass">
}
});
If it is guaranteed that the modified DOM content occurs further in the document than the element that you are currently visiting in the loop, then you could rely on DOM methods that return a live NodeList, such as:
getElementsByTagName
getElementsByClassName
getElementsByName
children
Here is a demo where the DOM is extended with one more select element, when the value of the current select element has less than 5 characters. The newly inserted select element will have options which have values that are 1 character longer.
function doSomeDOMChanges(select) {
$(select).after($("<select>").addClass("myClass").append(
$("<option>").text($(select).val() + "0"),
$("<option>").text($(select).val() + "1"),
$("<option>").text($(select).val() + "2")
));
}
for (var select of document.getElementsByTagName("select")) {
if ($(select).is(".myClass")) {
if ($(select).val().length < 5) {
doSomeDOMChanges(select);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="myClass">
<option>2
<option selected>3
<option>5
</select>
The downsides:
You cannot get such a live collection from a call to $(), using the power of a CSS selector
It only works when the DOM changes are further in the document. If changes are made in content that is already "behind" the currently iterated element, the loop will not work as expected, as the new DOM element is inserted in the live collection before the currently iterated element, meaning it will not be visited, and maybe even worse: the current element will move to a higher index in that collection and be visited again by the loop.
If one of these points is a problem, you could just make the jQuery selection again, and keep a Set of the elements you had already visited. The next demo makes DOM changes before the currently visited element:
function doSomeDOMChanges(select) {
$(select).before($("<select>").addClass("myClass").append(
$("<option>").text($(select).val() + "0"),
$("<option>").text($(select).val() + "1"),
$("<option>").text($(select).val() + "2")
));
}
let visited = new WeakSet;
let selector = "select.myClass";
for (let more = true; more; null) {
more = false;
$(selector).each(function() {
if (visited.has(this)) return;
visited.add(this);
if ($(this).val().length < 5) {
doSomeDOMChanges(this);
more = true;
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="myClass">
<option>2
<option selected>3
<option>5
</select>
I'm running into a little trouble trying to determine the value of an HTML select object.
I've got 2 items, which I'm putting down as Value 1 or Value 2, however any method I try just returns "Undefined" when printed to console
var catId = document.getElementById('catid');
var catCheck = catId.options[catId.selectedIndex].value;
console.log(catId);
console.log(catCheck);
<select name="catid" id="catid">
<option value="1">Category</option>
<option value="2">Product</option>
</select>
However when I console.log(catId.Value) or console.log(catCheck.value) (I'm obviously not trying both at the same time) I just returned an "Undefined" value.
I want to run an IF ELSE statement based on this variable, so ideally I'd like it to be able to pick up at least one of the two values!
Likelihood is I've made a dumb mistake and just can't see the wood for the trees but any help would be appreciated
You could also get the selected <select> <option> like this:
var catCheck = document.getElementById("catid").selectedIndex;
console.log(catCheck);
Your first option would return 0, your second 1 and so on.
You wouldnt have to use value this way.
You can listen for the select element to change by adding an event listener for the change event. This will trigger the performDropdownAction function anytime you select a new value within the dropdown list. You can then use this.value to get the value of the current drop-down item you're on.
Also, I've added a window.onload event, which will fire when your webpage has loaded, meaning it will perform the performnDropdownAction when the page loads and when a new item is selected.
See working example below :
const performDropdownAction = function() {
let current = this.value || document.getElementById('catid').value;
if (current == 1) {
console.log("One is selected");
} else if (current == 2) {
console.log("Two is selected");
}
}
window.onload = performDropdownAction;
document.getElementById('catid').addEventListener('change', performDropdownAction);
<select name="catid" id="catid">
<option value="1">Category</option>
<option value="2">Product</option>
</select>
I am new into javascript, and I've been working on this "project", but I need some help because I'm stuck. I might've not expressed my self correctly in the title so here it is:
I would like to get the ID of an option element (<select> <option id="#"> </select>) by using the "change" event listener on the <select>. So when I choose for example "Action" from the select dropdown, I'd like that change to trigger a function that will get that element's ID and use it in a function down below. Here's the code that I have so far, which basically does the following:
1.) Gets the genre list;
2.) Then for every item in the response.data.genres, sets a number which corresponds to the length of the array (total 19 items).
3.) If the selected "option" element matches the name of the genre in the array, then it defines the genre ID(the integer) and makes another request to the API in order to list the movies matching that genres ID. Thanks in advance.
//Genres
function genres(){
//API request.
axios.get("https://api.themoviedb.org/3/genre/movie/list?api_key=<API_KEY>&language=en-US")
.then((response)=>{
//console.log(response);
let genres = response.data.genres;
genres.length;
console.log(genres)
for(var i = 0; i < genres.length; i++){
var genresId = response.data.genres[i];
var tag = document.getElementById("Thriller");
console.log(genresId);
if(tag.id === genresId.name){
let genre = genresId.id;
axios.get("https://api.themoviedb.org/3/discover/movie?api_key=<API_KEY>&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres="+genre)
.then((response)=>{
console.log(response);
})
}
}
})
}
So there are two steps if I understand correctly.
1. get the list of genres and fill a selectbox with it.
2. get a list of movies if an option in the selectbox is selected.
The first step, you can do with an innerHTML method. For every genre that is returned, you build a string like <option value='genre'>genre</option>. With innerHTML you add these options to the select box. The value property is what you use to see which option is selected.
Next we add an eventlistener to the dropbox so our script will react to the changes the user makes. The event we're listening for is 'change' and it will trigger the function 'getMovies'. See Mozilla docs for more info. event.target.value will give you the value of the selected option, which you can use as genre id.
Inside this function you will do your second api call to get your movie list.
A simple example without the api calls is this:
let genreDropdown = document.getElementById('genre');
genreDropdown.innerHTML = getGenres();
genreDropdown.addEventListener("change", getMovies);
function getGenres(){
let genres = ['action', 'romcom', 'thriller']; //this would be replaced with the api call to get the genres
let innerHtml = '';
for(var i = 0; i < genres.length; i++){
var option = '<option value='+genres[i]+'>'+genres[i]+'</option>';
innerHtml += option;
}
return innerHtml;
}
function getMovies(event) {
let genre = event.target.value;
alert(genre) //you can replace this with the api call to get the movies.
}
<select id='genre'>
<option>loading...</option>
</select>
The following Code will look for a <select> (its id to be exact) Element and on change it will output the ID of the Direct Child (<option> in this case).
$(document).ready(function(){
$("#myDropdown").on("change", function(){
the_id = $(this).children(":selected").attr("id")
$("#output").html(the_id);
});
});
I have made an Example for you > JS Fiddle
Hope you can use the jQuery Code.
let's say I have a form that contains several "select" element that the User can choose.
when ready to submit, I need to find all the "select" that have changed.
how can I do it?
for example:
<form>
<input type="text" name="a"/>
<select name="b">...</select>
<select name="c">...</select>
<select name="d">...</select>
</form>
Using jQuery, something like this should work:
$('select').change(function() {
$(this).addClass('changed');
});
$('form').submit(function() {
var changed_selects = $('select.changed');
// do what you want with the changed selects
});
I would take advantage of the defaultSelected property on HTMLOptionElement instead of trying to keep track of selects that have changed:
form.onsubmit = function() {
var selects = form.getElementsByTagName("select")
, i
, changedSelects = []
, selected
, select;
/* Iterate over all selects in the form: */
for (i = 0; i < selects.length; i++) {
select = selects[i];
/* Get the currently selected <option> element: */
selected = select[select.selectedIndex];
/* Determine if the currently selected option is the one selected by default: */
if (!selected.defaultSelected) {
changedSelects.push(select);
}
}
alert(changedSelects.length);
}
You can iterate over all of the select elements on your form, determine if the selected option is the one that was selected by default, and push each one whose selected option wasn't the default into an array.
Example: http://jsfiddle.net/andrewwhitaker/abFr3/
You could register an event listener (using onchange, etc.) to determine if any changes were made.
Alternatively, you could keep a private copy of all of the previous values, then run a comparison before submit to check for changes.
Do something like:
var selectedVal = $("select[name='a'] option:selected").val();
//check this with your default selected val
You can attach the onchange event listener to each <select> element. When the event is triggered, you can store the actual elements in an a temporary array and reference it later when you are ready to submit. Note that the array can hold the actual DOM elements.
You need to clarify what you mean by "the select have changed".
If you mean have changed from their default value, then you should have one option on each select (usually the first) set as the default selected option. Then you can iterate over the selects and see if the option with the selected attribute (or where the defaultSelected property is true) is the selected option, e.g.
<script>
function anyChanged(){
var select, selects = document.getElementsByTagName('select');
for (var i=0, iLen=selects.length; i<iLen; i++) {
select = selects[i];
if (!select.options[select.selectedIndex].defaultSelected) {
// the selected option isn't the default
alert('select ' + (select.id || select.name) + ' changed');
}
}
}
</script>
<select name="one">
<option selected>one
<option>two
<option>three
</select>
<button onclick="anyChanged()">Check</button>
However, if you want to see if the user has changed the selected option based on some other logic, you need to say what it is.
I have a multiple select listbox. This listbox contains the names of many entities. Around 1000+. So as you can see it would be very annoying to scroll through. What I want to do is to display A-Z on the side vertically. When the user clicks a letter, javascript is fired to set the scroll position (NOT select the item) of the first occurring character selected. This is a control that is being created in c# and javascript being rendered using the client script manager. Basically what I have done so far is to add a new htmlanchor from a char array A-Z. This lists the alphabet vertically. This would be very similar to an iTouch/iPhone music library, touch/click the letter and the scroll is set to the first occurrence. I know how to loop through the list. So far I have an onclick function that acts as such:
private HtmlGenericControl alphaSortContainer;
this.alphaSortContainer = new HtmlGenericControl("div");
char[] alphabet = { 'Z'.......'A' };
for (int i = 0; i < 26; i++)
{
var letter = new HtmlAnchor();
link.InnerText = alphabet[i].ToString();
link.Attributes.Add("onclick", "javascript:jumpToIndex('" + link.InnerText + "');");
alphaSortContainer.Controls.Add(letter);
}
The above code adds (or should) letters stacked on top of each other. Their onclick will fire the javascript function and send in the letter.
My javascript so far:
function jumpToIndex(var index) {
var list = document.getElementByID('" + this.list.ClientID + "');
for(var i=0; i < list.length; i++) {
if(list.options[i].value.charAt(0) == index) {
HOW TO SET THE SCROLL POSITION TO MAKE THAT OBJECT THE TOP OF THE LIST BOX
break; //pretty sure this is how i would break out of both loops.
}
}
}
I just need to scroll to the item that matches the if statement. Also, i am pretty sure that would be how I break out of both loops. Please help!
The only way to do this is to select one of the options in the select list, which you can do the following way:
<select id="myselect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected="selected">3</option>
<option value="4">4</option>
</select>
Of course, if you don't want to make this choice serverside when you build the list or if you build the list clientside, you can always do it using javascript like this:
document.getElementById('myselect').options[<insert number>].selected = true;
and remember that <insert number> is zerobased
Now before you say i don't want to select it, just scroll to it, remember that if you see an option in a listbox, it is already selected by default.
Unless you are working with a multi-select selectbox in which case this is a whole different ballgame, and you are shit out of luck ;)
Have you considered not displaying the whole list but having javascript arrays for each letter. When a letter is selected the list is populated with just that letter's items?
var alphalist=new Array();
alphalist['a']=new Array('aardvark','acorns','apples');
alphalist['b']=new Array('baby','barley');
//etc
function fill_list{selectedLetter){
listItems=alphalist[selectedLetter];
mylist=document.getElementById('mylist');
mylist.length=0;.length=0;
for(var i=0;i<listItems.length;i++){
optionName = new Option(listItems[i],listItems[i])
var length = mylist.length;
mylist.options[length] = optionName;
}
}