select attr from adjacent class with a specific name - html

my html is structured like so:
<div class='quiz-question'>
<div name='qc-1' class='btn quiz-choice ' >3</div>
<div name='qc-2' class='btn quiz-choice correct' >4</div>
<div name='qc-3' class='btn quiz-choice ' >5</div>
</div>
i want to use jquery to select the name attribute from the correct div when you click on ANY of the quiz-choice divs.
so no matter which one i click on i'd like to get the value of the name from whichever one has the correct class
i think it should be something like this but it keeps coming back as undefined.
jQuery('.quiz-choice').click(function(){
var correctChoice = $(this).parent('.quiz-question').children('.quiz-choice').hasClass('correct').attr('name');
});

Related

Why show hide option does not work using this query

Why show hide option does not work?
The idea is to be able to use class name with space like class="BXXX 01"
where XXX 01 is dynamic data
Here is not working jsfidle: https://jsfiddle.net/master1991/fq32Lhe9/36/
$(document).on('keyup', ".BenterInput", function() {
var item = $(this).attr('data-item');
var num = $(this).val();
if ($.isNumeric(num)) {
$("a[class='B" + item + "']").show();
} else {
$("a[class='B" + item + "']").hide();
}
console.log(item + ' ' + num);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="qInDocBXXX"></div>
<input type="text" name="valueToAdd" data-item="XXX" class="BenterInput">
<a class="btn btn-default btn-xs add_row BXXX" data-but="B" style="display: none;">XXX</a>
The idea is to be able to use class name with space like class="BXXX 01"
That's not a class name with a space in it; that's two classes.
Matching against the entire classNames list is fragile, because you're having to include a whole bunch of irrelevant classnames, and if any of them differ or are missing the match will fail. It will also break if the classnames are correct but happen to come in a different order:
div[class="a b c"] {
background-color: green
}
<div class="a b c">One</div>
<div class="b c a">two</div>
I would strongly recommend against that approach.
Instead you can just match the two specific classes you're interested in:
a.BXXX.AB {...}
...or in your case (assuming item contains the string "XXX AB")
$("a.B"+item.replace(/ /g,"."))
The reason your code does not work is that the actual className is btn btn-default btn-xs add_row BXXX AB so you cannot use
$("a[class='BXXX AB']")
to make your code work, you would have to do
$("a[class='btn btn-default btn-xs add_row B" + item + "']").show();
but that would assume the order of your classes stayed the same.
I suggest you instead toggle the element on and off using the isNumeric instead of show/hide
NOTE: If you have data-item="XXX.AB" then it works without the split
$(document).on('keyup', ".BenterInput", function() {
var item = $(this).attr('data-item');
var num = $(this).val();
$(`a.B${item.split(" ").join(".")}`).toggle($.isNumeric(num));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="qInDocBXXX"></div>
<input type="text" name="valueToAdd" data-item="XXX AB" class="BenterInput">
<a class="btn btn-default btn-xs add_row BXXX AB" data-but="B" hidden>XXX</a>

How to show/hide in Angular2

I have a component that show/hide element by clicking a button.
This is my html
<div *ngFor="let history of histories | sortdate: '-dateModified'">
<p><b>{{ history.remarks }}</b> - <i>{{history.dateModified | date:'short'}}</i></p>
<a href="google.com"
[class.datatable-icon-right]="history.$$expanded"
[class.datatable-icon-down]="!history.$$expanded"
title="Expand/Collapse Row"
(click)="toggleExpandRow(history)"></a>
<!-- hide/show this by clicking the button above.-->
<div *ngFor="let step of history.steps; let i = index">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
<hr />
</div>
and my .ts
toggleExpandRow(row) {
console.log('Toggled Expand Row!', row);
//row
return false;
}
trying to search but, can't find any same sample.
On jquery, I can do this, but on Angular2, I am having hard time to figure this.
There are two options:
1- You can use the hidden directive to show or hide any element
<div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
2- You can use the ngIf control directive to add or remove the element. This is different of the hidden directive because it does not show / hide the element, but it add / remove from the DOM. You can loose unsaved data of the element. It can be the better choice for an edit component that is cancelled.
<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
Use the ngIf in your repeated rows. Create a boolean property called showStep to indicate whether the row should be expanded or not.
<div *ngFor="let step of history.steps; let i = index" ngIf="history.showStep">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
Then, in your .ts file:
toggleExpandRow(history) {
history.showStep = !history.showStep
//note the same porperty of showStep that is used in your html
}
Extra:
In fact, to save a few lines of codes, you don't even need the toggleExpandRow function at all. You can do it inline in your html:
//other attributes omitted for brevity
<a (click)="history.showStep = !history.showStep">

Xpath find child on the parent only if another child is present

So I have a web page where I would like to find button SignUp only if button NameField is present in the div entire class.
<div class="entire class">
<div class = "upper class>
<button class="NameField"></button>
</div>
<div class="lower class">
<button class="SignUp"></button>
</div>
</div>
How would I achieve that? I have tried the following:
$x("//div[#class='entire class']//button[#class='NameField'] and not(descendant::button[#class='SignUp']")
$x("//*[#class='upper class'] | [#class='SignUp']")
$x("//*[#class='SignUp'] | //body)[last()]")
$x("//div[//button[#class='SignUp'] and [//button[#class='NameField']]")
None of them seems to be working.
Try below XPath:
//div[button[#class="NameField"]]/following-sibling::div/button[#class="SignUp"]
//div[#class="entire class" and div[button[#class="NameField"]]]/div/button[#class="SignUp"]
or simplified one:
//button[#class="NameField"]/following::button

I need CSS selector to select elements that contain a given text

Line:
<div class="btn btn-second-in-pair-not-desired btn-tall">Clear search</div>
<div class="btn btn-second-in-pair-not-desired btn-tall">Raw Search</div>
<div class="btn btn-second-in-pair-not-desired btn-tall">Basic Search</div>
<div class="btn btn-primary-stand-alone btn-tall search-btn">Search</div>
Here is what i have tried so far -
".btn:contains('Clear search')" but selenium is not able to catch it
CSS Selector doesn't support :contains() anymore. You have to use XPath "//div[text()='Clear search']".
I don't think css supports searching by content of the html element.
Why not try:
<div class="btn btn-second-in-pair-not-desired btn-tall clear">Clear search</div>
<div class="btn btn-second-in-pair-not-desired btn-tall raw">Raw Search</div>
<div class="btn btn-second-in-pair-not-desired btn-tall basic">Basic Search</div>
<div class="btn btn-primary-stand-alone btn-tall search-btn">Search</div>
And then selecting via:
.btn{
color:red;
}
.clear, .raw, .basic, .search-btn{
color:blue;
}
Or you could always try using ids
<div id="search">Search</div>
select:
#search{
...
}
If your using Selenium, it also accepts XPATH strings, which can sometimes be more flexible than CSS Selectors in some instances. Because I'm super lazy as well, I find it quite handy that you can right click a tag in the Elements view of DevTools and "Copy > Copy XPath"
webDriver.findElement(
By.xpath(
"//div[text()='Clear search']"
)
).click();
you cannot change the class depending on the content ?
<?php
$content = $your_content_from_database;
$arr_content = explode(" ", $content);
$first = $arr_content[0];
echo '<div class="btn btn-second-in-pair-not-desired btn-tall clear" data-content="'.$first.'">'. $content. '</div>' ; ?>
and the CSS
[data-content="Clear"]{
color:red;
}
Hi on the basis of the source provided by you in the question you can use css selector as below to identify the elements
// take everything inside the list for div with same class
List<WebElement> mycsselements = driver.findElements(By.cssSelector(".btn.btn-second-in-pair-not-desired.btn-tall"));
System.out.println("Size of the div elements with same class name : " + mycsselements.size());
// printing value one by one
System.out.println("First value is " + mycsselements.get(0).getText());
System.out.println("Second value is " + mycsselements.get(1).getText());
System.out.println("Third value is " + mycsselements.get(2).getText());
// and for the last one do it like below
System.out.println("Last value is " + driver.findElement(By.cssSelector(".btn.btn-primary-stand-alone.btn-tall.search-btn")).getText());
and the output is :
Size of the div elements with same class name : 3
First value is Clear search
Second value is Raw Search
Third value is Basic Search
Last value is Search
Hope this helps you
User below css code:
css=div:contains('Clear search')
More details click on link: SauceLab

Dojo StackController: how can I set a title for each button?

(using dojo 1.10.1)
I am working with dojo's dijit/layout/StackContainer and dijit/layout/StackController which are working fine, here is a simplified example. My problem is that I cant find a "clean" way to add mouseover titles to each controller button that the StackController creates?
html
<div>
<div data-dojo-type="dijit/layout/StackContainer"
data-dojo-props="id: 'contentStack'">
<div data-dojo-type="dijit/layout/ContentPane" title="one">
<h4>Group 1 Content</h4>
</div>
<div data-dojo-type="dijit/layout/ContentPane" title="two">
<h4>Group 2 Content</h4>
</div>
<div data-dojo-type="dijit/layout/ContentPane" title="three">
<h4>Group 3 Content</h4>
</div>
</div>
<div data-dojo-type="dijit/layout/StackController" data-dojo-props="containerId:'contentStack'"></div>
</div>
So for each title in each child contained within the StackContainer, a button is cerated by the StackController with the same label, but the button has no mouseover text, I need to add that as well.
I am not interested in any solution that involves me looping over the nodes and finding each button, its just not nice.
One of the best solutions would be to send properties, methods and events of buttons via corresponding ContentPanes. For example:
<div data-dojo-type="dijit/layout/ContentPane" title="one" data-dojo-props=
"controllerProps: {onMouseOver: function(){"doSomething"}}">
<h4>Group 1 Content</h4>
</div>
But as far as I understood this is not possible, because StackController passes to its buttons "title" and some other unimportant properties of ContentPane. So if you are really interested in above solutions you have to override the default behavior of StackController. Which is possible, but needs more time! :)
So I suggest you other solution which works and faster. You give to StackController-div an id:
<div id="myController" data-dojo-type="dijit/layout/StackController" data-dojo-
props="containerId:'contentStack'"></div>
You use "dijit/registry" to call that id:
var controllerWidget = registry.byId("myController");
You have now StackController widget. Call getChildren() method of it and you have an array of Button widgets. The rest I guess straightforward.
Here is the JSFiddle example.
Cheers!
Update:
Hey I have found another solution, which satisfies your requirements: "No button search"
These are the properties which StackController passes to buttonWidget:
var Cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget;
var button = new Cls({
id: this.id + "_" + page.id,
name: this.id + "_" + page.id, // note: must match id used in pane2button()
label: page.title,
disabled: page.disabled,
ownerDocument: this.ownerDocument,
dir: page.dir,
lang: page.lang,
textDir: page.textDir || this.textDir,
showLabel: page.showTitle,
iconClass: page.iconClass,
closeButton: page.closable,
title: page.tooltip,
page: page
});
So if you give a tag "tooltip" for your ContentPane, it will appear in buttonWidget as "title".
<div data-dojo-type="dijit/layout/ContentPane" title="one" tooltip="First Page">
Here is another JSFiddle example.