There is one requirement for my application to select multiple items from a listbox in microsoft edge browser
I am using watir webdriver to test my application
The DOM structure is as follows:
<div id="textSearch">
<div id="textSearch">
<select name="#Type" id="textType" onchange="unselectOptionZero('#Type');" size="7" multiple="" width="250">
<option value="*" selected="">- All -</option>
<option value="text1">text1</option>
<option value="text2">text2</option>
<option value="text3">text3</option>
<option value="text4">text4</option>
<option value="text5">text5</option>
</select>
</div>
</div>
I tried these following command to select multiple values
#browser.select_list(:id, "textType").option(:value => "text3").select
#browser.send_keys :control
#browser.select_list(:id, "textType").option(:value => "text4").select
which does not seem to working. I tried using iteration via .select but it does not seem to be working.
I also tried selenium support Selenium::WebDriver::Support::Select.new but it does not help. Is there any other way to select multiple options in microsoft edge browser using execute_script using javascript.
Watir's Select#select selects the options by calling the #click method. Unlike other drivers, Edge treats this like a regular click, which unselects the previous options. This is a known/expected behaviour by the Microsoft Edge Team.
Their suggestion is to use the Actions object to press and hold the control button. However, attempting to do this, ex by calling option.click(:control), will result in an unknown command exception. The Edge driver has not yet implemented the Actions command.
Until then, you will need to execute JavaScript to select the options.
If you are using Watir v6.8 or later, you can use the new #select! method to select the option via JavaScript instead of mouse clicks. This will retain the previously selected values.
s= #browser.select_list(:id, "textType")
s.select!("text3")
s.select!("text4")
Note that #select now supports looking for options by both text and value (as opposed to prior versions where it only checked text).
If you are using earlier versions of Watir, the same can be done using #execute_script:
s= #browser.select_list(:id, "textType")
select_script = 'arguments[0].selected=true;'
#browser.execute_script(select_script, s.option(:value => "text3"))
#browser.execute_script(select_script, s.option(:value => "text4"))
Related
I am a python selenium webdriver newbee.
I am stuck at a dropdown that has an "onchange" parameter in the html.
This is how the inspect window looks:
I am trying to first key in the date to the box called "Start"
Then move on to the dropdown for the "Schools" (School1, School2 etc).
Once I choose the school, the adjacent dropdown (School Levels) will refresh/update/populate with the school levels (middle, high, elem etc) for that school. There is an "onchange=" for this element.
Then move on to the School Levels dropdown to choose the level. There is an "onchange=" for this element, too
And then move on the the grade level dropdown.
I am stuck at the first dropdown.After I enter the start date, it does move on the dropdown and clicks on it and all three schools get visible but the driver does not select the school and does not move on to the adjacent school level dropdown.
As far as I understand from what I have found online, it most probably has to do with the onchange javascript event but couldn't figure out how to fire the event.
Please help.
Thank you in advance.
This is the html block for the start date box:
<div class="inline-block" ><input name="Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$DatePickerStartDate" type="text" size="9" id="Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_DatePickerStartDate" spellcheck="false" style="BACKGROUND:#ff9999;display:inline;" /><input type="image" name="Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$DatePickerStartDate_IB" id="Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_DatePickerStartDate_IB" src="Images/Mindex/WebControls/DatePicker/calendar.jpg" onclick="PopupCal('Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_DatePickerStartDate', 'Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_DatePickerStartDate',false,false); return false;" style="border-width:0px;display:inline;vertical-align:middle;" /></div></nobr>
And this is the html block for the two adjacent dropdowns:
<select name="Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingDropDown" onchange="javascript:setTimeout('__doPostBack(\'Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingDropDown\',\'\')', 0)" id="Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_BuildingDropDown">
<option selected="selected" value="3">School1</option>
<option value="4">School2</option>
<option value="5">School3</option>
</select>
<select name="Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingSchoolLevelDropDown" onchange="javascript:setTimeout('__doPostBack(\'Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingSchoolLevelDropDown\',\'\')', 0)" id="Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_BuildingSchoolLevelDropDown">
<option selected="selected" value="4">K-8</option>
<option value="5">High School</option>
<option value="6">Summer School</option>
<option value="7">Middle School</option>
<option value="8">Elementary</option>
</select></nobr>
And this is my code:
print("Clicking on student selector icon")
driver.find_element_by_xpath("/html/body/form/div[4]/div[1]/div/div[2]/div/table/tbody/tr/td/table[2]/tbody/tr["+str(r)+"]/td[1]/input").click()
time.sleep(2)
tab_student = driver.find_element_by_id("Template1_Control0_TabHeaderDetails_MenuTabs1_MenuTabStudent")#we can move this to the start of the script
tab_student.click()
time.sleep(3)
icon_add_enrollment = driver.find_element_by_id("Template1_Control0_BottomPanel_IconButtonAdd")#we can move this to the start of the script
icon_add_enrollment.click()
time.sleep(3)
input_startdate = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_DatePickerStartDate")
input_startdate.send_keys("4/21/2010")
time.sleep(2)
print("Start Date entered")
dropdown_school = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_BuildingDropDown")
dropdown_school.select_by_visible_text("School1")
time.sleep(5)
print("School picked")
time.sleep(6)
dropdown_level = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_BuildingSchoolLevelDropDown")
dropdown_level.select_by_visible_text("Elementary")
#or maybe I can use this? actions.move_to_element(dropdown_building).click().perform()
time.sleep(2)
print("Building picked")
time.sleep(6)
dropdown_grade = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_GradeDropDown")
actions.move_to_element(dropdown_grade).click().perform()
time.sleep(2)
dropdown_grade.select_by_visible_text("1").click()
print("Grade picked")
time.sleep(2)
dropdown_ethnicity = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_ddlEthnicity")
actions.move_to_element(dropdown_ethnicity).click().perform()
time.sleep(2)
dropdown_ethnicity.select_by_visible_text("White").click()
print("Ethnicity picked")
time.sleep(2)
icon_save_enrollment = driver.find_element_by_id("Template1_Control0_BottomPanel_StudentEditEnrollmentAdd_IconButtonAdd")#we can move this to the start of the script
icon_save_enrollment.click()
time.sleep(4)
print("Enrollment added.. Moving on to enrolling the next child")
I also tried move_to_element().click(perform() but still not working.
The onchange javascripts in the html is not showing correctly for some reason so I am attaching them below:
//for school dropdown:
javascript:setTimeout('__doPostBack(\'Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingDropDown\',\'\')', 0)
//for school levels dropdown:
javascript:setTimeout('__doPostBack(\'Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingSchoolLevelDropDown\',\'\')', 0)
Thank you again.
As far as I understand, this is your exact problem:
After I enter the start date, it does move on the dropdown and clicks on it and all three schools get visible but the driver does not select the school and does not move on to the adjacent school level dropdown.
Which means the error occurs when selecting the dropdowns or <select> inputs once the date is properly detected by the onchange.
Ive found this to work on similar cases:
schoolSelector = Select(driver.find_element_by_xpath('//select[#name="Template1$Control0$BottomPanel$StudentEditEnrollmentAdd$BuildingSchoolLevelDropDown"]'))
schoolOptions = schoolSelector.options
then if you want to iterate through each school you may use schoolOptions to get each one with:
for school in range(0,len(schoolOptions)):
schoolSelector.select_by_index(school)
Edit:
Had not noticed you posted all of your code, I think selecting by index and via XPATH is usually more precise. Give it a shot.
I have a Domain Class Project with a one-to-many property users :
static hasMany = [users: User]
In my scaffolding code the view is created with:
<div class="fieldcontain ${hasErrors(bean: projectInstance, field: 'users', 'error')} ">
<label for="users">
<g:message code="project.users.label" default="Users" />
</label>
<g:select name="users" from="${usermanagement.User.list()}" multiple="multiple" optionKey="id" size="5" value="${projectInstance?.users*.id}" class="many-to-many"/>
</div>
This results in a simple list where I can select multiple users. The user list is expected to be quite big so this selection isn't really viable. Is there a simple way in grails to do this a bit more comfortable? The best solution I can imagine would be a list with an autocomplete searchform and a second list where the selected entries are displayed.
I don't think that there is an easy way to do this and that I probably have to use javascript or jquery (autocomplete etc.)
Any help improving my current status (selection from huge list via ctrl + click)
would be very appreciated.
There is a jQuery plugin called Chosen that will do what you are wanting, it supports multiple selections. I have a use case much like yours in one of my apps and Chosen worked out great:
http://harvesthq.github.io/chosen/
A possible solution is using some javascript based stuff like boostrap select2 or Kendo UI Multiselect. They are based on a html select box that unobtrusively enhanced the selection model of a this html element. So there is no real javascript code to implement, since the selection model for the html form stays the same as with disabled javascript.
So i'm using angular and this is my select html:
<select id="date" ng-model="selectedDay" ng-change="setDate()" >
<option>another option</option>
<option>an option</option>
</select>
this is in my controller:
$scope.selectedDay;
document.getElementById("date").selectedIndex = "0";
The result: Three options: one blank (which is default selected) and then the two options I made in html
What the hell? why isn't the default when i open the view "another option"
Firstly, always check the official documentation. AngularJs is well documented.
Secondly, do not use document.getElementById ("date") selectedIndex = "0" - that's javascript. Avoid using pure Javascript when an Angular function is available.
Documentation:
https://docs.angularjs.org/api/ng/directive/select
https://docs.angularjs.org/api/ng/directive/ngSelected
Hi this JSFiddle works in Internet Explorer and Firefox but no other browxsers work. The idea of the code is a currency converter that is up to date using the Yahoo Currency API. It doesn't update the $scope on the other browsers the way it is supposed to on Chrome. http://jsfiddle.net/xHmLT/13/
choose a post ({{visible.post}} is visible)
<select>
<option ng-repeat="shot in shots" ng-click="visible.post = shot.Name" value="{{shot.Name}}">{{shot.Name}}</option>
</select>
<div ng-repeat="shot in shots" ng-if="visible.post == shot.Name">{{shot.Rate | currency:'':''}}
</div>
<div ng-repeat="shot in shots" ng-if="visible.post == shot.Name">{{shot.Rate *5 | currency:'':''}}
</div>
I updated your fiddle and is working as you'd intended...
Your select is now populated via ng-options and the model is visible.post (as an object). As a result anywhere showing visible.post, is now showing visible.post.Name (field on the object)
<select ng-options="s.Name for s in shots" ng-model="visible.post"></select>
The initialization of the selected value is done in the success promise handler:
$scope.visible.post = $scope.shots[0];
I'm using datatables, with their example i was able to build tables nicely. But the problem is i don't seem to understand how to move the "records per page" element, which is a "span6" class of bootstrap. i do get the point that it's actually javascript which is doing this, need some help on this. Here is the LINK for the example i'm using.
This is the div you are taking about in that page
<div class="span6">
<div id="example_length" class="dataTables_length">
<label>
<select size="1" name="example_length" aria-controls="example">
<option value="10" selected="selected">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>records per page</label>
</div>
</div>
Just copy this to other location and modify the css accordingly.
To modify the DOM using Javascript.
http://woork.blogspot.in/2007/10/how-to-change-text-using-javascript.html
Take a look at this page in their documentation... DataTables dynamic language. It doesn't give the best explanations of how to move things but it's a good place to start experimenting. I was able to hide or change the "records per page" text and I would image there is a way to move it as well.
The preamble on that page says "Changing the language information displayed by DataTables is as simple as passing in a language object to the dataTable constructor. The example above shows a different set of English language definitions to be used, rather than the defaults."
"oLanguage": {
"sLengthMenu": "Display _MENU_ records per page"
}
should give you a place to start.