I am trying to a select option from extjs combo box.
Here in the below code listElements is giving only the visible options(which are shown in the screen) and not all the options.
Here am restricted to select one of the options which are available in the screen.
I want to select the value which are in the bottom of the list.
I don't find any option to drag down the list to select the desired option.
List<WebElement> listElements = TestUtil.getWebDriver().findElements((By.className("x-boundlist-item")));
for(WebElement ele : listElements){
if(ele.getText().equals(TestUtil.getValue(DateTimeConstants.TIMEZONE_INPUT_VALUE))){
ele.click();
break;
}
}
Please find the html :
This is the combo box html:
<input id="currentTimezone-inputEl" class="x-form-field x-form-text x-form-focus x-field-form-focus x-field-default-form-focus" type="text" style="width: 100%; -moz-user-select: text;" name="dateTimeData.selectedTimezone" value="-- Please Select --" autocomplete="off" aria-invalid="false" data-errorqtip="">
Options are available below like this:
<div id="ext-gen1024" class="x-reset">
<div id="ext-gen1074" class="x-reset">
<div id="ext-gen1076" class="x-css-shadow" role="presentation" style="z-index: 19000; left: -9999px; top: -9995px; width: 355px; height: 296px; box-shadow: 0px 0px 4px rgb(136, 136, 136); display: none;"></div>
<div id="ext-gen1079" class="x-css-shadow" role="presentation" style="z-index: 19000; left: 20px; top: 321px; width: 355px; height: 296px; box-shadow: 0px 0px 4px rgb(136, 136, 136); display: none;"></div>
<div id="boundlist-1022" class="x-boundlist x-boundlist-floating x-layer x-boundlist-default" tabindex="-1" style="left: 20px; top: 317px; width: 355px; z-index: 19001; height: 300px; display: none;">
<div id="boundlist-1022-listEl" class="x-boundlist-list-ct" style="overflow: auto; height: 299px;">
<ul>
<li class="x-boundlist-item" role="option">Africa/Abidjan</li>
<li class="x-boundlist-item" role="option">Africa/Accra</li>
<li class="x-boundlist-item" role="option">Africa/Addis_Ababa</li>
<li class="x-boundlist-item" role="option">Africa/Algiers</li>
<li class="x-boundlist-item" role="option">Africa/Asmara</li>
<li class="x-boundlist-item x-boundlist-selected" role="option">America/St_Lucia</li>
</div>
</div>
</div>
Yes, I can reproduce this issue. The reason is that Selenium won't click on invisible elements, each of the invisible element's text will also be empty.
Here most of the combo list elements are invisible, so ele.getText() won't get you anything for them. As a result, you won't be able to compare the text with the one you want.
However, the workaround is, without using ele.getText() to get the text, you can try use textContent attribute of an element to get the text. Also, Selenium won't click on invisible element, so you need to use Actions click() rather than normal click(). Below is how you can do it.
List<WebElement> listElements = TestUtil.getWebDriver().findElements((By.cssSelector(".x-boundlist:not([style*='display: none'])")));
for(WebElement ele : listElements){
if(ele.getAttribute("textContent").equals(TestUtil.getValue(DateTimeConstants.TIMEZONE_INPUT_VALUE))) {
// print out ele.getAttribute("textContent") if you want
// ele.click(); ElementNotVisible exception may be thrown
new Actions(TestUtil.getWebDriver()).click(ele).perform();
break;
}
}
}
To solve this we can use xpath in the following manner. The reason why a country is not selected is it is not visible and for invisible elements selenium cannot perform the action.
We have to first make the countries list visible by clicking on the input box. Once the list is visible we can select any of the country in the list.
// Code to make the country list visible
WebElement element = driver.findElement(By.xpath("//div[contains(#id, 'boundlist')]"));
element.click();
//To click on some country in the drop down
driver.findElement(By.xpath("//div[contains(#id, 'boundlist')]//ul//li[text() = 'Africa/Abidjan']")).click();
//To make a reusable method
public void selectCountry(String countryName)
{
driver.findElement(By.xpath("//div[contains(#id, 'boundlist')]//ul//li[text() = '" +countryName +"']"));
}
Related
I created a dropdown menu that opens when you click on a text box, and then when you chose a string for that dropdown list, it puts it in the text box.
I would like to make that when you hover your mouse on the strings in the dropdown, they get slightly highlighted! how can I achieve this?
<div class="row">
<div class="col-xs-12 max300" uib-dropdown is-open="vm.descriptionDropdownOpen">
<textarea name="remarks" class="form-control" ng-model="vm.presence.description" ng-click="vm.toggleDescriptionDropdown()" autofocus></textarea>
<ul id="descriptionDropdown" uib-dropdown-menu>
<li ng-repeat="descr in vm.loadedDescriptions" ng-click="vm.presence.description = descr.text; vm.descriptionDropdownOpen = false;">
{{descr.text}}
</li>
</ul>
and the css to keep the dropdown aligned with the textbox:
#descriptionDropdown {
width: 100%;
line-height: 150%;
padding-left: 8px;
position: relative;
}
thank you very much
you can do something like this
#descriptionDropdown li:hover{
background-color:#eaeaea;
}
Change the color code to your desired color code.
And remove the padding from ul to avoid space around background when you hover. Instead, use padding on li
#descriptionDropdown li{
padding-left:8px;
}
You could add this css :
li:hover {
background-color: blue;
}
I have a simple ng-repeat <li>. Each <li> consumes 33.33% of the width so 3 items per row.
However, for some reason the items in the second row do not line up. After a big of digging, if i apply a min-width of say, 400px, then it works. But, i can not do this as the description text length is dynamic.
HTML:
<ul class="grid-wrap">
<li class="grid-col one-third" ng-repeat="job in Jobs" ng-init="descriptionLimit = 20">
<div>{{ job.JobTitle }}</div>
<div>{{ job.Location }}</div>
<div>{{ job.JobDescription | limitTo:descriptionLimit }}
<span ng-click="descriptionLimit = job.JobDescription.length"> >> </span></div>
</li>
</ul>
CSS:
ul, ol {
list-style: none;
padding: 0;
margin: 0;
}
.grid-wrap {
margin-left: -3em; /* the same as your gutter */
overflow: hidden;
clear: both;
}
.grid-col {
float: left;
padding-left: 3em; /* this is your gutter between columns */
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.one-third {
width: 33.33%;
}
plunker: http://plnkr.co/edit/oWXrqoJpaYPDbe4TwT3c?p=preview
If you click on the >> the description will expand and you can see each <li> does not line up:
Might something like this be what you are looking for?
.one-third:nth-of-type(3n+1) {
clear: both;
}
I.e. if you want to have exactly a maximum of 3 lis per row, and you want to always align your rows vertically, you'll need to explicitly do so.
Edit: And of course you could do this also with Angular, for example like this, first define a clearing class:
.clear-li {
clear:both
}
and then apply it with ng-class:
<li class="grid-col one-third" ng-repeat="job in Jobs" ng-init="descriptionLimit = 20" ng-class="{'clear-li': ($index % 3 === 0)}">
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am a HTML / CSS newbie.
I need to do something like this:
My web page is receiving sequences of events dynamically and I would like to visualize them on in the page.
I would like one sequence of events to be in a box, with lots of slots, and each slot has the event id.
So if I have several sequences, then I will have several such boxes.
However, the length of a sequence is dynamic. And the web page's window might be adjusted by the users, so even for a sequence, if it is too long or the window is too narrow, I have to break the box into several lines.
the above is my drawing of the design.
The A, B, etc, are the sequence title, then the numbers are the ids.
ideally, the space of all events / sequences should be as compact as possible.
And if a box has to change line, then it should be half-borded to indicate the continuous.
How can I do that? using CSS 3?
And also the framework I am using is AngularJS to control the data / UI binding, even if I manage to handle this case, how to dynamically bind the data to adjust this requirement?
Thanks
Doing this in CSS is tricky, because you want a border between elements only if those elements are on the same line. CSS doesn't know anything about wrapping.
I've solved the problem by:
Adding a left border on all boxes
Adding a right border on the last box only.
Adding a -1px left margin on all boxes except the first.
Placing the boxes in a container with overflow: hidden.
Having the right border on the last box only solves the right-hand issue.
The -1px left margin solves the left-hand issue.
Snippet:
.sequences {
overflow: hidden;
}
.sequence > div {
border: 1px solid black;
border-right: none;
height: 50px;
float: left;
margin-bottom: 10px;
}
.sequence > div:last-of-type {
border-right: 1px solid black;
margin-right: 20px;
}
.sequence > div:not(:first-of-type) {
margin-left: -1px;
}
.yellow div {background: yellow; width: 100px;}
.green div {background: lightgreen; width: 80px;}
.blue div {background: lightblue; width: 120px;}
<div class="sequences">
<div class="sequence yellow">
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sequence green">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sequence blue">
<div></div><div></div><div></div>
<div></div><div></div><div></div>
</div>
</div>
You can solve this using CSS by doing something like this.
I've given each sequence element a top, left and bottom border. T
This will give the illusion of a right border when the elements are floated next to eachother but when they're the last on that line it will brake of as per your request.
I also added a right border to the last div element and the last div in each section.
Fiddle
div{
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
float:left;
background: #eee;
border: 1px solid #000;
border-width: 1px 0 1px 1px;
margin-bottom: 10px;
}
div.last{margin-right: 5px;}
div.last,
div:last-child{border-right-width: 1px;}
<div class="seq-1">1</div>
<div class="seq-1">2</div>
<div class="seq-1">3</div>
<div class="seq-1">4</div>
<div class="seq-1 last">5</div>
<div class="seq-2">1</div>
<div class="seq-2">2</div>
<div class="seq-2 last">3</div>
Edit:
I just noticed you wan't the border to be 0px/blank on the last element and the first element each row. Now that is a bit trickier.
I'm not positive there's a good solution to solving that using css since your sequences seem to be dynamic.
Please correct me if I'm wrong, but I think you need to use javascript to manage this.
Edit 2: CSS and JQuery solution
I made a quick jquery solution that utilies my previously provided CSS code.
The jQuery script removes the left border if the elements left offset(within it's parent) is 0 and if the element is not the first element in each sequenc(first class added).
Fiddle
var containerOffset = $('.container').offset().left;
setBorderWidth();
$(window).resize(function(){
setBorderWidth();
});
function setBorderWidth(){
$('.block').each(function() {
var childOffset = $(this).offset().left;
if(childOffset - containerOffset == 0 && !$(this).hasClass('first'))
$(this).css("border-left-width", "0px");
else
$(this).css("border-left-width", "1px");
});
}
.container{width: 100%;}
.block{
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
float:left;
background: #eee;
border: 1px solid #000;
border-width: 1px 0 1px 1px;
margin-bottom: 10px;
}
.block.last{margin-right: 5px;}
.block.last,
.block:last-child{border-right-width: 1px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div class="container">
<div class="seq-1 block first">1</div>
<div class="seq-1 block">2</div>
<div class="seq-1 block">3</div>
<div class="seq-1 block">4</div>
<div class="seq-1 block last">5</div>
<div class="seq-2 block first">1</div>
<div class="seq-2 block">2</div>
<div class="seq-2 block last">3</div>
</div>
What I would recommend is to have 3 CSS classes
1) beginning of sequence
2) middle of sequence
3) end of sequence
then display different borders using:
.beginning-of-seq {
border-top-style: solid;
border-right-style: none;
border-bottom-style: solid;
border-left-style: solid;
}
for instance.
about the angular part just use ng-repeat="seq in sequences" for instance and then render the sequence with the classes you created so it will look good (of course you need the scope to have the sequences)
<span ng-repeat="seq in sequences">
<span class="beginning-of-seq"> {{seq.title}} </span>
<span class="middle-of-seq ng-repeat="elem in seq.otherElements">{{elem}}</span>
<span class="end-of-seq"> {{seq.lastElem}} </span>
</span>
</span>
this is a bit crude and i don't know how you implemented it but it should give you an idea where to start
This HTML/CSS should do the trick. As you mentioned about the user having different resolutions, I've used percentages for the widths (depending on your scenario, media queries may be needed).
.container {
width: 30%; /*Change this to fit your design*/
}
.seq {
display: inline;
border: 0.1em solid #000;
margin-right: 1em;
}
.seq .item {
display: inline-block;
width: 5%; /*Change this to fit your design*/
margin-bottom: 1em;
}
.seq .item:not(:last-child) {
border-right: 0.1em solid #000;
}
<div class="container">
<div class="seq">
<div class="item item-title">A</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<div class="seq">
<div class="item item-title">B</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<div class="seq">
<div class="item item-title">C</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<div class="seq">
<div class="item item-title">D</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
</div>
About the AngularJS binding:
In your controller define your array of sequences and some functions to manipulate the sequences:
$scope.sequences = [];
$scope.addSequence = function(sequenceName){
var newSequence = { name : sequenceName, events: [] };
$scope.sequences.push(newSequence);
};
$scope.addEventToSequence = function(sequenceName, event){
var sequence = getSequence(sequenceName); // write this function to get the right sequence from the array
sequence.events.push(event);
}
Now in your html loop over the sequences and events using ng-repeat
<ul>
<li ng-repeat="sequence in sequences">
<ul>
<li>{{sequence.name}}</li>
<li ng-repeat="event in sequence.event">{{event.name}}</li>
</ul>
</li>
</ul>
I'm trying to find list of element in ExtJS drop-down. I found a good solution on stackoverflow, though it doesn't work for me.
Solution in C#:
public void ClickComboItem(IWebElement input, string target)
{
input.Click();
IList<IWebElement> comboItems = _driver.FindElements(By.XPath("//*[contains(#class, 'x-combo-list') and contains(#style, 'visibility: hidden;')]//*[contains(#class, 'x-combo-list-item')]"));
comboItems.First(item => item.Text.Trim() == target).Click();
}
From here.
Part which I need to automate look like this:
<div class="x-ie-shadow" id="ext-gen546" style="z-index: 12004; filter: progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=4); WIDTH: 351px; display: none; height: 301px; top: 186px; left: 1187px;"/>
<div class="x-layer x-combo-list " id="ext-gen544" style="z-index: 12005; position: absolute; width: 350px; height: 302px; visibility: hidden; font-size: 12px; top: -10000px; left: 0px;">
<div class="x-combo-list-inner" id="ext-gen545" style="width: 348px; height: 300px; overflow: auto;">
<div class="x-combo-list-item" _nodup="30813" viewIndex="0">
<div class="x-combo-list-item" _nodup="30813" viewIndex="1">
Actual click on the pointer is executed and I can see see drop-down list on the page, though comboItem returns '0' results. I assume I should adjust xPath correctly for my case, though it seems for me that it should work, as soon as structure is very similar with an example from the post I mentioned above.
It seems that the xPath is not correct.
You gave "visibility: hidden;"
Try with ""visibility: visible;"
public void ClickComboItem(IWebElement input, string target)
{
input.Click();
IList<IWebElement> comboItems = _driver.FindElements(By.XPath("//*[contains(#class, 'x-combo-list') and contains(#style, 'visibility: visible;')]//*[contains(#class, 'x-combo-list-item')]"));
comboItems.First(item => item.Text.Trim() == target).Click();
}
You can take a different way without using Xpath
IWebElement dvInner = driver.FindElement(By.Id("ext-gen545"));
IList<IWebElement> comboItems = dvInner.FindElements(By.ClassName("x-combo-list-item"));
Try to implement using stable id of any of the parent nodes.Basically using the xpath-axis concept.
I am pretty new to Selenium Webdriver, so pardon me for all d 'noob' terminology used.
I have a dynamic table on the page, with 4 columns in the table. Out of this, only the first column name can be edited. The table looks like this :
Now using Webdriver, I need to locate 'group102' and verify the Level and the number of Cards (basically the text of the rest of the two columns) corresponding to 'group102'. The key point to note here is that this group is dynamic in nature. Right now, its sitting in row 3 but tomorrow, it may be on row 1 or row 10.
I am using Visual Studio (C#) and Selenium webdriver.
Please let me know how can I progress
EDIT :
HTML CODE:
<div id="formbland-1013" class="x-panel x-panel-default x-form-bland x-form-base" style="height: 9588px;">
<div id="formbland-1013-body" class="x-panel-body x-panel-body-default x-panel-body-default" style="left: 0px; top: 0px; width: 680px; height: 9588px;">
<span id="formbland-1013-outerCt" style="display: table; width: 100%; table-layout: fixed;">
<div id="formbland-1013-innerCt" style="display:table-cell;height:100%;vertical-align:top;">
<div id="ext-comp-1026" class="x-panel x-panel-default x-form-bland x-form-base" style="width: 680px; height: 47px;">
<div id="ext-comp-1036" class="x-panel x-panel-default x-form-bland x-form-base" style="width: 680px; height: 9541px;">
<div id="ext-comp-1036-body" class="x-panel-body x-panel-body-default x-panel-body-default" style="left: 0px; top: 0px; width: 680px; height: 9541px;">
<span id="ext-comp-1036-outerCt" style="display: table; width: 100%; table-layout: fixed;">
<div id="ext-comp-1036-innerCt" style="display:table-cell;height:100%;vertical-align:top;">
CODE WHICH I AM TRYING :
ReadOnlyCollection<IWebElement> select = WebDriver.FindElements(By.XPath("//td[contains(text(),'group102')]"));
if ("group102e".Equals(select.ToString()))
{
throw new SystemException("Group matches according to the Access");
}
else
{
throw new SystemException("Group does not matches according to the Access");
}
I can't provide exact code as I don't know the HTML for the table. But here are the code in theory.
You get the IWebElement input first by text first, then go to ancestor td's siblings (i.e. the next two column cells in this row), then get the element's text.
IWebElement inputGroup = WebDriver.FindElement(By.CssSelector("tbody input[value='group101']"));
IWebElement level = inputGroup.FindElement(By.XPath("(.//ancestor::td/following-sibling::td)[1]"));
string levelA = level.Text;
My questions about your code:
"group102e".Equals(select.ToString()) doesn't make sense, since your select is ReadOnlyCollection<IWebElement>, which is a list of IWebElements, ToString won't get you anything useful?
var location = WebDriver.FindElement(By.CssSelector("tbody input[value='Practice Wide Group 2']")).Location.ToString();, what do you want here? The location of the element (which is in the type of System.Drawing.Point)?