I'm using the following in some selenium code:
WaitForElement(By.CssSelector("#document-count:contains(<number greater than 0>)"));
Specifying the number greater than 0 is where I'm stuck. Is there any way to use only css to check and see if an element's innertext has something other than 0?
:contains was deprecated in CSS3. Since WebDriver ties directly into the browser, it's unable to use that pseudo-class.
Is there any way to use only css to check and see if an element's innertext has something other than 0?
Unfortunately not. CSS really screwed Selenium users over with their deprecation of both :contains and :nth
As Arran said, you can use xpath, or - if you are willing to experiment with C# and CSS together (not just css as you state) then you can come up with something to loop x amount of times checking the text.
Per Chris Coyier at CSS Tricks:
Deprecated
:contains() - As far as I know, this is gone. The current
CSS3 spec has removed it. I don't know the story, let me know if you
do. At a glance, it looks ridiculously useful (being able to select
objects based on the textual content they contain). It may be because
of problems, or having content in selectors being undesirable. My
preference would be to have it select by elements rather than text,
like p:contains(img), but alas, no such luck.
That said, if you were to set the value properties, you may be able to use :not([value="0"]):
See jsFiddle demo
HTML
<div id="doc">
<input type="text" value="0" />
<br />
<input type="text" value="1" />
<br />
<input type="text" value="2" />
</div>
CSS
#doc input[value="0"]
{
background: red;
}
#doc input:not([value="0"])
{
background: green;
}
Result
Related
I have found many examples explaining how to use multiple :not selectors on an individual element. However, so far I have been unable to find any examples that use :not selectors on different levels within a single selection path in CSS / JS querySelector.
For example, given a HTML structure of:
<div class="anything_except_ignore">
<input type="text" id="a" />
<input type="hidden" id="b" />
</div>
<div class="ignore">
<input type="text" id="c" />
</div>
I wish to select JUST input#a.
I have tried the following in JS and it does not seem to work:
var elems = document.querySelectorAll("div:not(.ignore) input:not([type='hidden'])");
In this case it appears the first :not selector is ignored (so in the above example both input#a AND input#c are selected.
Have I made a mistake in the syntax or is this approach not possible to use :not selectors in this way to select just input#a?
I can work around this by looking a parent class in JS once the elements are selected, but I'd rather do it properly at the selector stage.
---UPDATE--- as suggested in one of the answers, my mistake was in not understanding that other DIVs further up the DOM can fulfil the :not(.ignore) criteria and so the input under the div.ignore element IS selected. If I remove other DIVs then the requested logic does seem to work as proved by this test:
var res="",elems = document.querySelectorAll("div:not(.ignore) input:not([type='hidden'])");
for(var i=0;i<elems.length;i++){
res = res + elems[i].id + "\n";
}
alert(res);
<div class="anything_except_ignore">
<div>
<input type="text" id="aa" value="a"/>
<input type="hidden" id="bb" value="b"/>
</div>
</div>
<div class="anything_except_ignore2">
<span>
<input type="text" id="dd" value="d"/>
<input type="hidden" id="ee" value="e"/>
</span>
</div>
<div class="ignore">
<input type="text" id="cc" value="c"/>
</div>
Sorry for any confusion, but at least this helps clarify how it should work as I could find no other examples of this in my searching.
---CONCLUSION---
As far as I can tell I have to either:
make sure that my inputs are always immediate children of the div I want to check and use the ">" syntax
after selection of all non-hidden inputs, use JS to check up the DOM tree of each, to check the class name of all DIVs up the tree.
If there is a better querySelector way to solve this particular issue then I'd love to hear it.
This is a common misunderstanding of how :not works in combination with other selectors.
Let me guess, there are actually more div elements than you have shown us, around these elements …?
div:not(.ignore) is not “ignored”, but the condition is just fulfilled by a different element than you thought - by some div element further up the tree. The space in between the two partial selectors is the descendant selector, so every input:not([type='hidden']) element that has a div ancestor that doesn’t have the class ignore anywhere above it in the DOM tree, matches the full selector.
If you change your selector to div:not(.ignore) > input:not([type='hidden']), this would only select such input fields if their immediate parent is a div without that class.
I want to do a portion of a form look like a spreadsheet.
There are several forms and <table> is thus not viable (though I'm not against it when you do are printing semantically tabular data, as it is the case).
So I tried to simply use a CSS2.1 layout directly with the form input elements, eg.
<div class="table">
<form class="tbody">
<div class="tr">
<label class="td">Label</label>
<input class="td" name />
<input class="td" name />
</div>
</form>
</div>
Full example in the fiddle.
But it looks like display:table-cell does not work on <input> elements!
If you check in Chrome "Computed Style" the display will be "inline-element".
But I did not find anywhere why it shouldn't:
Mozilla Dev Network CSS:display
W3C CSS 2.1 Recommendation Visual Formatting Model
W3C Tables Recommendation
Any idea?
It sounded so much better than having some <div class="cell"> around the <input> and then having to play with box-model to get it look nice...
From W3.org:
"CSS 2.1 does not define which properties apply to form controls and frames, or how CSS can be used to style them. User agents may apply CSS properties to these elements. Authors are recommended to treat such support as experimental. A future level of CSS may specify this further."
Sorry, but display: table-cell on input elements is treated experimental. Try to avoid it, use wrapper-elements for the positioning for example.
I've made an example with div elements. You can now have multiple forms within a table, however it only works when the form element spans full rows. Otherwise your nesting will be broken.
EDIT:
Updated the fiddle with a version where border-collapse is added to avoid double borders.
JSFiddle example
I have a simple form in a ASPX page that have a lot of <label> and <asp:TextBox> pairing that construct the outlay of the form.
I have a requirement to add a string behind the textbox to indicate that the field is compulsory. I'd tried adding either a <span>, a <em> or a <div> after the field but it will still display the message at the bottom of the textbox.
Any way for me to achieve this?
EDIT:
I mean right hand side of the textbox, not behind as in watermark. My Bad.
EDIT for sample code:
I'd tried all the suggestion but it is still not working, thinking whether it's my code issue or not. Below are my codes:
<label>Telephone No.</label>
<asp:TextBox ID="txtTelNo" runat="server"></asp:TextBox>
<span class="afterInput">test</span>
any pointers? Thanks.
EDIT for Answer
As it turns out the problem lies in the css property. The template that i used has all the input assigned with the display: block property, which makes anything after the <input> element to be pushed down.
After creating a custom css class with display: inline-block and assign to them appropriately, i manage to get the result that i wanted.
Many thanks for the answer provided, especially the :after attributes and the watermark attributes.
See http://jsfiddle.net/ekWG9/
.required:after{
content: "*";
color: red;
}
<label>A box</label><input type="text" value="Hello" /><span class="required"></span>
<!-- alternative HTML -->
<span class="required"><label>A box</label><input type="text" value="Hello" /></span>
Using the :after pseudo element selector allows you to take the literal content out of the markup (e.g. you don't have to repeat "*" over and over).
You can also use relative or absolute positioning to tweak the location of the content of the :after pseudo element. Example: http://jsfiddle.net/ekWG9/1/
By behind the textbox, seems you are talking of watermark text.
You could use the TextBoxWatermark from ajaxcontrol toolkit.
There are also several jQuery alternatives to implement it.
html5 also has browser support for watermarks:
<input name="q" placeholder="Go to a Website">
You could add an attribute to your control to that effect.
Use css for this purpose:
span.clsRequired {
float:left;
margin:2px 0 0 3px;
color:red;
}
And your span before text box looks like:
<span class="clsRequired ">*</span>
you should try something like this
<body>
<form id="form1">
<asp:TextBox ID="TextBox1" runat="server"/> <span>Required field</span>
</form>
</body>
Above is a Form. There are different methods to get the following form above, with the input and text seperated on different lines.
One is to use < br / > and another use fieldset, p-tag, etc.
But I am wondering what the proper way is to seperate the form different things in different lines?
The easiest way is simply:
label, input {
display: block;
}
Edited to add the content of a comment made below, from myself to the OP, since it seems pertinent to the answer:
The 'best' is a very subjective measure. The 'best' is simply the easiest way to achieve your end-result, ideally without mangling the semantics of the HTML. Using div elements in forms gives no meaning to the contained elements, or their relationship to each other.
Using a fieldset gives some idea of the relationship, but typically (possibly should, but I'm unsure) is used to group elements together, rather than simply style them. I'd argue my method is 'best' simply because it relies on no additional (meaningful or meaningless) HTML elements being added to the page.
There are no fast rules. HTML5 seems to favor using the p element, see its example on it. By old HTML specifications, p means a paragraph, but HTML5 defines a paragrapg as virtually any block of inline content.
In practice, it is best to select the markup according to the desired default rendering. If you prefer no vertical spacing, use br or div (in the latter, you would wrap each line in a div element, making it easier to style it if desired). If you prefer spacing (empty lines), use p. Using a table is one possibility but unnecessarily complicated in a simple case like this.
Using <br/> tags to control layout is not recommended. This tag should only use to break a line in a paragraph. Using it for layout purposes is lazy and bad practice.
The best way to create forms in general like the above is to use a <ul> list.
<form>
<ul>
<li>
<label for="firstname">Name</label>
<input name="firstname" type="text" />
</li>
<li>
<label for="surname">Surname</label>
<input name="surname" type="text" />
</li>
</ul>
</form>
This is considered by many the "proper" way of doing it.
Then you can style your list in whichever way you like, so depending on the css the label can be above or next to the input field (this is where the <br/> tag would spoil that).
The basic style you need to apply is:
form ul {
list-style-type:none;
}
This gets rid of the bullet points in the list. Then you can e.g. set the elements inside to block or make them float.
I would use <div> tags and position them manually with CSS. You can also use the clear:both within CSS. I have used <br /> before as well. You do not want to be using <p> tags though because it will confuse the Google Bot which crawls your website to place you on Google Search, from a SEO point of view <p> is bad unless you actually have content within the tags.
Tables may also look a good option but here is a good article on why you should not use tables for layout http://phrogz.net/css/WhyTablesAreBadForLayout.html
Ain't nothing wrong with using br's, though the cleanest way is to just make those items display:block.
http://jsfiddle.net/chad/MdbKE/
Quite semantic way to markup label/field pairs is to use DL list (for example, this is used by default in Zend_Form). For submit button, DIV can be used:
<dl>
<dt><label for="frm-login-username">Username</label></dt>
<dd><input type="text" name="username" id="frm-login-username" /></dd>
<dt><label for="frm-login-password">Username</label></dt>
<dd><input type="password" name="password" id="frm-login-password" /></dd>
</dl>
<div><input type="submit" value="Login" /></div>
Is there any difference in:
#example .test{margin-top:10px}
And
#example span.test{margin-top:10px}
.test is totally unique, no any class with that name exists. I have been trying to use like
<div id="example">
<label for="name">Name</label>
<input name="name" type="text" />
<span class="test">asdfghjkl</span>
</div>
The first css won't work, while the second works fine. Just wondering why first wont work?
Thanks
Edit:
I found out that in the input field (in above example), i had put float:left;, which was causing the problem. If anyone is interested, here you can see example. If you remove float:left;, it will work fine.
http://jsfiddle.net/CmXrX/1/
Yes, there is a difference. That difference is in specificity. If you have conflicting CSS rules -- two rules point to the same element but certain properties conflict -- the conflict will be sorted out by the rules about specificity.
Each type of selector has a certain number of "specificity points" For instance:
Selector type Points
-----------------------------
HTML selector 1
class selector 10
id selector 100
So if you had these two rules:
#example .test{margin-top:10px}
#example span.test{margin-top:20px}
the top margin would be 20px, because the second rule has a specificity of 111 (100 + 10 + 1) whereas the first has 110 (100 + 10).
My guess, therefore, is that you have a conflicting style somewhere that has 111 specificity.
There are two differences:
The latter will only apply, if the class test is applied to a span and no other element.
(and most likly more relevant in your case) the latter has a higher specificity than the former.
You probably have an other rule with a higher specificity then the first selector but lower than the second. That means this other rule will override the first rule, but not the second.
I found out that in the input field (in above example), i had put float:left;, which was causing the problem. If anyone is interested, here you can see example. If you remove float:left;, it will work fine. http://jsfiddle.net/CmXrX/1/
yes there is a difference :
<div id="example">
<label for="name">Name</label>
<input name="name" type="text" />
<span><div class="test">asdfghjkl</div></span>
</div>