Below is the HTML code for the element I want to click:
<select id = "per-page-xxxxxxxx" //xxxxxxx is a dynamic string
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
It is basically a dropdown list that allow you to choose how many items to be displayed on current page.
My code to click <option value="100">100</option> is:
var dropdownListXpath = "//select[starts-with(#id,'per-page-')]";
var PublicationPerPageOptionXpath = "//select[starts-with(#id,'per-page-')]/option[#value='100']";
var dropdownList;
var PublicationPerPageOption;
aqUtils.Delay(500);
try {
dropdownList = PageObj.EvaluateXpath(dropdownListXpath);
dropdownList[0].Click();
aqUtils.Delay(500);
PublicationPerPageOption = PageObj.EvaluateXpath(PublicationPerPageOptionXpath);
PublicationPerPageOption[0].Click();
}
catch(err) {
Log.Message("Can not find options to show 100 publications per page.");
}
The result:
Dropdown list is clicked and expanded, then nothing happens afterwards, e.g. option 100 is not clicked
Can anyone please provide any help?
Related
I've recently asked this question, it's working fine as I expected until I found out that when I submitted the form and there's an error with the inputs (I'm using Laravel) after the page reloads the Grade Levels options which should be disabled some option based on the value of the Level selection options are now all enabled.
The expected outcome is even if the page reloads (because of the error after the form has been submitted) the Grade Levels options are still disabled based on the value of Level.
The value of the Level select box is preserved and selected after the error occurred, also did a console.log and it's showing the preserved value.
My approach is to have a DOMContentLoaded and place the JavaScript code there to handle the disabling of options based on the selected value in Level select option but I didn't make it work.
Code I'm trying to
document.addEventListener('DOMContentLoaded', (event) => {
let level = document.getElementById('level')
let grade_level = document.getElementById('grade_level')
let gradeSelect = document.querySelector('.grade_level')
let currentLevel = level.value;
console.log(currentLevel) // this shows the current value of level select option
grade_level.disabled = true
if (level.value == 'Senior') {
grade_level.removeAttribute('disabled')
} else if (level.value == 'Junior') {
grade_level.removeAttribute('disabled')
}
gradeSelect.querySelectorAll('option[value]').forEach(function(option) {
let match = currentLevel === option.dataset.level
option.disabled = !match
if(! match){
option.closest("select").append(option)
}
});
});
Code which is working fine with all inputs in the form is valid (no errors and not being redirected back to the page):
let gradeSelect = document.querySelector('.grade_level')
document.getElementById('level').onchange = function() {
let level = this.value;
gradeSelect.querySelectorAll('option[value]').forEach(function(option) {
let match = level === option.dataset.level
option.disabled = !match
if(!match){
option.closest("select").append(option)
}
});
// Sets the first one (Choose Grade Level) selected
gradeSelect.querySelector('option').selected = true
};
<select name="level" id="level" autofocus>
<option selected disabled>Choose</option>
<option value="Junior">Junior</option>
<option value="Senior">Senior</option>
</select>
<select name="grade_level" class="grade_level">
<option selected disabled>Choose Grade Level</option>
<option value="Grade 7" data-level="Junior">Grade 7</option>
<option value="Grade 8" data-level="Junior">Grade 8</option>
<option value="Grade 9" data-level="Junior">Grade 9</option>
<option value="Grade 10" data-level="Junior">Grade 10</option>
<option value="Grade 11" data-level="Senior">Grade 11</option>
<option value="Grade 12" data-level="Senior">Grade 12</option>
</select>
EDIT
I've implemented Stephen and Louys's answer but none of them works in disabling the Grade Levels select options based on the preserved value of the Level select option after page reloads.
To explain what I mean in page reloads I have a form (post method) that is submitted and by using PHP Laravel as the backend I validate the inputs if there's an error with the inputs the page then reloads and I'm showing the error and also I'm able to get the previously selected value of the Level select box.
I have the previous value of the Level select box (it is already selected) and by that value I want to also preserve the current state of Grade Levels options - only enable what is connected to the current value of Level select and disable the remaining options.
Question:
Why do you need to show all the Grade Levels options again instead of also preserving the previously selected value?
A:
I want to do that but I can't because I'm also populating the Grade Levels options using javascript inside $function()
$(function() {
// init the grade level options
$('#grade_level').site_data('fetch_list')
});
My current code
function updateSelect() {
const level = levelSelect.value;
// Ensure everything is enabled when no level selected (on first page load)
if (level === 'Choose') {
gradeSelect.querySelectorAll('option[value]')
.forEach(o => o.disabled = false);
}
gradeSelect.querySelectorAll('option[value]')
.forEach(function(option) {
option.disabled = !(level === option.dataset.level)
});
// Sets the first one (Choose Grade Level) selected
gradeSelect.querySelector('option').selected = true;
}
let levelSelect = document.getElementById('level');
let gradeSelect = document.querySelector('.grade_level');
// Update the selection when the page loads, so if 'level' already has
// a value the grade_levels will be enabled/disabled appropriately.
document.addEventListener('DOMContentLoaded', updateSelect);
levelSelect.onchange = updateSelect;
let test = document.querySelector("#level")
test.addEventListener("change", function(){
updateSelect()
})
let customEvent = document.createEvent("event");
customEvent.initEvent('change', true, true);
test.dispatchEvent(customEvent);
<select name="level" id="level" autofocus>
<option selected disabled>Choose</option>
<option value="Junior">Junior</option>
<option value="Senior">Senior</option>
</select>
<select name="grade_level" class="grade_level">
<option selected disabled>Choose Grade Level</option>
<option value="Grade 7" data-level="Junior">Grade 7</option>
<option value="Grade 8" data-level="Junior">Grade 8</option>
<option value="Grade 9" data-level="Junior">Grade 9</option>
<option value="Grade 10" data-level="Junior">Grade 10</option>
<option value="Grade 11" data-level="Senior">Grade 11</option>
<option value="Grade 12" data-level="Senior">Grade 12</option>
</select>
EDIT #2
Here, I will make Senior as default and we will try to see if the Grade Levels options will disable Grade 7-10.
function updateSelect() {
const level = levelSelect.value;
// Ensure everything is enabled when no level selected (on first page load)
if (level === 'Choose') {
gradeSelect.querySelectorAll('option[value]')
.forEach(o => o.disabled = false);
}
gradeSelect.querySelectorAll('option[value]')
.forEach(function(option) {
option.disabled = !(level === option.dataset.level)
});
// Sets the first one (Choose Grade Level) selected
gradeSelect.querySelector('option').selected = true;
}
let levelSelect = document.getElementById('level');
let gradeSelect = document.querySelector('.grade_level');
// Update the selection when the page loads, so if 'level' already has
// a value the grade_levels will be enabled/disabled appropriately.
document.addEventListener('DOMContentLoaded', updateSelect);
levelSelect.onchange = updateSelect;
let test = document.querySelector("#level")
test.addEventListener("change", function(){
updateSelect()
})
let customEvent = document.createEvent("event");
customEvent.initEvent('change', true, true);
test.dispatchEvent(customEvent);
<select name="level" id="level" autofocus>
<option disabled>Choose</option>
<option value="Junior" selected >Junior</option>
<option value="Senior">Senior</option>
</select>
<select name="grade_level" class="grade_level">
<option selected disabled>Choose Grade Level</option>
<option value="Grade 7" data-level="Junior">Grade 7</option>
<option value="Grade 8" data-level="Junior">Grade 8</option>
<option value="Grade 9" data-level="Junior">Grade 9</option>
<option value="Grade 10" data-level="Junior">Grade 10</option>
<option value="Grade 11" data-level="Senior">Grade 11</option>
<option value="Grade 12" data-level="Senior">Grade 12</option>
</select>
In your other question, where it uses an anonymous function .onchange = function() — you will want to take that and make it a named function so it becomes (for example if you called that function "updateSelect") .onchange = updateSelect
Then you will want to run that function when the page loads, not just onchange, with something like document.addEventListener('DOMContentLoaded', updateSelect);
This assumes that, as you say, when the page reloads after your submit the value of the level select box is preserved and selected.
Adapting Louys Patrice Bessette's answer, I've pulled the function out to the top, set it up to be called when the page (DOM) is ready, and set it to be called onchange of the Level selection.
function updateSelect() {
const level = levelSelect.value;
// Ensure everything is enabled when no level selected (on first page load)
if (level === 'Select') {
gradeSelect.querySelectorAll('option[value]')
.forEach(o => o.disabled = false);
}
gradeSelect.querySelectorAll('option[value]')
.forEach(function(option) {
option.disabled = !(level === option.dataset.level)
});
// Sets the first one (Choose Grade Level) selected
gradeSelect.querySelector('option').selected = true;
}
let levelSelect = document.getElementById('level');
let gradeSelect = document.querySelector('.grade_level');
// Update the selection when the page loads, so if 'level' already has
// a value the grade_levels will be enabled/disabled appropriately.
document.addEventListener('DOMContentLoaded', updateSelect);
levelSelect.onchange = updateSelect;
<select name="level" id="level" autofocus>
<option selected disabled>Choose</option>
<option value="Junior">Junior</option>
<option value="Senior">Senior</option>
</select>
<select name="grade_level" class="grade_level">
<option selected disabled>Choose Grade Level</option>
<option value="Grade 7" data-level="Junior">Grade 7</option>
<option value="Grade 8" data-level="Junior">Grade 8</option>
<option value="Grade 9" data-level="Junior">Grade 9</option>
<option value="Grade 10" data-level="Junior">Grade 10</option>
<option value="Grade 11" data-level="Senior">Grade 11</option>
<option value="Grade 12" data-level="Senior">Grade 12</option>
</select>
EDIT
When you are populating the grade_level as you show in the update to your question:
$(function() {
// init the grade level options
$('#grade_level').site_data('fetch_list')
});
This is likely happening after the DOMContentLoaded event fires and updateSelect is run, therefore there are no <option> elements in grade_level yet for updateSelect to act upon.
You should be able to solve this by doing all of your initialization in one place, either moving the call to updateSelect into that function instead of using the DOMContentLoaded handler:
$(function() {
// init the grade level options
$('#grade_level').site_data('fetch_list');
updateSelect();
});
-or- eliminate that function and move populating the list into the DOMContentLoaded handler:
document.addEventListener('DOMContentLoaded', function() {
$('#grade_level').site_data('fetch_list');
updateSelect();
});
(note I have not tested these updated code fragments)
As in my title mentioned I would like to have a select field where I can click on a option Item and then it shows me the suboptions. I only found solutions where you divide it in optgroups but then all the options are visible or I found something which is formatted.
My idea to solve this was the following:
Html
<select data-role="select" data-filter="false" v-on:change="boolValueChanger(testSelector)">
<option value="testSelector">vegetable</option>
<optgroup v-if="testSelector" label="vegetable">
<option value="123123">pepper</option>
<option value="4565">spinach</option>
<option value="64734">broccoli</option>
</optgroup>
<optgroup label="fruits">
<option value="43534">banana</option>
<option value="3345">apple</option>
<option value="45645">orange</option>
</optgroup>
</select>
JS
setup(props) {
return {testSelector: ref(false) };
},
methods: {
boolValueChanger: function (x) {
if (x === true) this.testSelector = false;
else this.testSelector = true;
}
}
My idea was to make a "main menu" where I can select my optgroup (in my example that would be vegetable). If I select that the testSelector would be changed and the optgroups would display but unfortunately that didn't work. My example would be look ok but if I have like 200 options this would be look not so good anymore and a user would have to scroll a lot(I could use a search filter but if the options are unknown to the user this is also not nice).
Does anyone have an idea how I could realize something like that?
So I am making two dropdowns. One is dependent on the other one, as in when you choose an option in the first dropdown, the values in the other should change. I am rendering my form with Symfony3.4, so I do not have much control over it. (I do not think I can add dynamic class names/value names to it). If it is relevant, I am using Bulma css framework.
Here is what my selectboxes look like:
states:
<select name="state" id="stateSelect">
<option value="1">Lagos</option>
<option value="2">Abuja</option>
<option value="3">Rivers</option>
<option value="4">Ogun</option>
<option value="5">Oyo</option>
<option value="6">Anambra</option>
<option value="7">Enugu</option>
<option value="8">Akwa Ibom</option>
<option value="9">Adamawa</option>
...
<option value="37">Zamfara</option>
</select>
LGA (local government areas):
<select id="lgaSelect" name="areas_registration[lga]">
<optgroup label="Lagos">
<option value="1">Abule Egba</option>
<option value="2">Agege</option>
<option value="3">Ajah</option>
<option value="4">Alimosho</option>
<option value="5">Amuwo Odofin</option>
...
</optgroup>
<optgroup label="Abuja">
<option value="38">Apo</option>
<option value="39">Asokoro</option>
<option value="40">Central Area</option>
<option value="41">Chika</option>
<option value="42">Dakibiyu</option>
...
</optgroup>
....35 more optgroups
</select>
My goal is when a user chooses an option from States dropdown, the LGA dropdown should only have options relevant to the selected state. I am using optgroup label for this. What I tried in my javascript is that when the page loads, I clone the LGA dropdown, hide it, call it lgaSelectSeed and use it for seeding the original LGA dropdown: (#hiddenLgas is just an empty div)
$(function () {
var stateSelect = $("#stateSelect") || null;
var lgaSelect = $("#lgaSelect") || null;
var hiddenLga = $("#hiddenLgas") || null;
$(hiddenLga).html(lgaSelect.clone().prop('id', 'lgaSelectSeed'));
stateSelect.change(function () {
var select_class = $(this).find('option:selected').text();
var options = $(lgaSelectSeed).find('optgroup[label="' + select_class + '"]');
$(lgaSelect).html(options.children());
}
This works but there is a bug in it. If you select random options in the state dropdown, and then go up and select Lagos or Abuja, the LGA dropdown becomes blank. I have been trying to figure out for a few days why this is happening, but still cant. Is there any jquery plugin to handle this instead?
DEMO: https://jsfiddle.net/gafyvbL9/
How to replicate the bug: In the states dropdown (left), choose Lagos. Then choose Anambra. Then choose Lagos again, then choose Anambra. You can see that the LGA dropdown (right) becomes empty. Why is this happening? Thanks in advance
Make a clone of the stored options so you don't remove the originals from $(hiddenLga)
Change:
$(lgaSelect).html(options.children());
To
$(lgaSelect).html(options.children().clone());
Playing with your fiddle, I think the issue is when you perform $(lgaSelect).html(), you're deleting all of the information stored there. Try storing that outside of your handler.
let $options = $('#lgaSelect').clone();
$("#stateSelect").on('change',function() {
let state = $(this).find('option:selected').text();
$("#lgaSelect").html($options.find(`optgroup[label="${state}"]`).html());
});
EDIT:
Notice the double quote in optgroup[label="${state}"]. This prevents issue with states that contain a space, like Akwa Ibom.
I want to achieve:
If I select "16" in first select box and bigger value in second, for example "17", then in second select automatically changing to "16".
Just if value in first select box is lower than second, always change to same values, for example 16 to 16, 18 to 18.
<select id="from_age_js" name="from_age" class="select-advertise-style">
<option value="f13">13</option>
<option value="f14">14</option>
<option value="f15">15</option>
<option value="f16">16</option>
<option value="f17">17</option>
<option value="f18" selected>18</option>
<option value="f19">19</option>
<option value="f20">20</option>
</select>
—
<select id="to_age_js" name="to_age" class="select-advertise-style">
<option value="t13">13</option>
<option value="t14">14</option>
<option value="t15">15</option>
<option value="t16">16</option>
<option value="t17">17</option>
<option value="t18">18</option>
<option value="t20" selected>20+</option>
</select>
That's an easy one, in your case, with pure javascript, I would do something like this:
function checkit()
{
//Store the two dropdowns for easy reference
var fromAge = document.getElementById('from_age_js');
var toAge = document.getElementById('to_age_js');
//Verify if the toAge value is minor, to see if the conditional code will be executed
if( fromAge.options[fromAge.selectedIndex].value >
toAge.options[toAge.selectedIndex].value)
{
//In that case, match the values to be the same...
document.getElementById('to_age_js').value =
fromAge.options[fromAge.selectedIndex].value;
}
}
And you just have to add that function to where you want it to be called. I would choose to add the onchange event from Javascript within the select dropdowns. Like this:
<select id="from_age_js" name="from_age" class="select-advertise-style" onchange="checkit();">
You can see a working example here:
https://jsfiddle.net/8cmad3tz/19/
<select id="country_name" onchange="changeCounty();">
<option value="IND"> IND</option>
<option value="US">US</option>
<option value="JP">JP</option>
<option value="UK">UK</option>
</select>
i have the above code.
when i select one option it will do some changes to the page.but when i open the page in new tab of browser the already selected option reset. and default selected option set.How do i cop with this?
You need something to pass the value from one page to another, as tabs are by default totally separate pages.
One workaround could be something like this (using LocalStorage) :
// Save value when it is changed by user
function changeCounty(){
if(window.localStorage){
var inputValue = document.getElementById('country_name').value
window.localStorage.set('mySavedValueName',inputValue )
}
//..your original code
}
// Load value if it exists
window.addEventListener('load', function getContryFromLS(){
if(window.localStorage){
var lsvalue = window.localStorage.get('mySavedValueName')
if(lsvalue)
document.getElementById('country_name').value=lsvalue
}
}
Your Html code
<select id="country_name" onchange="changeCounty(this);">
<option value="IND"> IND</option>
<option value="US">US</option>
<option value="JP">JP</option>
<option value="UK">UK</option>
</select>
JQuery Code
$(function(){
var d=localStorage.getItem("selectval");
if(d!=null){
console.log(d);
$("#country_name").val(d);
}
$("#country_name").change(function(){
localStorage.setItem("selectval",$(this).val());
});
});
Demo Here