jQuery: Select all 'select' elements with certain val() - jquery-selectors

Does anyone know of an easy way, using jQuery, to select all <select> elements whose val() attribute yields a certain value?
I'm trying to do some validation logic and would like to just select all those elements with a single selector, then apply a warning class to each of their parents. This I know how to do once I select all the elements, but I didn't see a selector that handles this case.
Am I going to have to select all of the <select> elements into a selector, then iterate through them and check each of their values? I was hoping there would be a simpler way.
Thanks.

Why doesn't select[value=x] work? Well firstly because <select> doesn't actually have a value attribute. There is not a single value of a select box: there may be no selected options (there shouldn't normally be, but there can be in at least IE), and, in a <select multiple>, there can be any number of selected options.
Even input[value=x] doesn't work, even though <input> does have a value attribute. Well, it does work, it just doesn't do what you think. It fetches the value of the value="..." attribute in the HTML, not the current value you have entered into the form. The value="..." attribute actually corresponds to the defaultValue property and not value.
Similarly, option[value=x][selected] doesn't work because it is checking the <option selected> attribute from the HTML source (selected attribute -> defaultSelected property) and not the current selectedness of the option (selected property not attribute) - which might have changed since the page was loaded.
Except in IE, which gets the value, selected etc form attributes wrong.
Except (again): Tesserex's example may seem to work, and the reason for that is that that it's using a non-standard jQuery-specific selector, :has. This causes the native querySelectorAll methods of modern browsers to fail, and consequently jQuery falls back to its own (native JavaScript, slow) selector engine instead. This selector engine has a bug where it confuses properties for attributes, allowing [value=x] to do what you expected, and not fail like it should! (Update: this is probably no longer the case in newer jQuery versions.)
Summary: form field state checking and selectors don't mix. Apart from these issues, you also have to worry about escaping issues - for example, what if the value you want to test against contains quotes or square brackets?
So instead, yes, you should check it manually. For example using a filter:
$('select').filter(function() {
return $(this).val()==='the target value';
}).parent().addClass('warning');
(There is a value property in HTML5 and supported by modern browsers, that when you read it gives you the value of the first selected <option>. jQuery's val() is safe to use here because it provides the same method of getting the first selected option even on browsers that don't support this.)

The existing answers don't work on select tags, but I found something that does. Ask for a select that has a selected option.
$("select:has(option[value=blah]:selected)")

You can use :
$("select[value=X]");
where X is the value against which you want to check the select's value.

Attribute selectors Is what you're looking for I believe.
Something like $+('element[attribute="value"]')
See also:
*= anywhere
^= starts with
$= ends with
~= contains word
etc.

You can create a change event that puts the value in a custom attribute on the select element whenever the value changes. You can then use a simple selector to find all of the select elements that have that value. For example:
$("select").on("change", function (e) {
var $select = $(e.currentTarget);
$select.attr("select-value", $select.val());
});
And then you can do this:
var $matches = $("select[select-value='" + searchVal + "']");
$matches will have all of your matching selects.
This is a lot easier than having to iterate through elements. Remember to set select-value to the initial value when rendering the page so you don't need to trigger a change event for each select so the select-value is set.

Related

Pre-populating form fields with model data in Sightly/HTL

I've tried all the HTL context parameters (even 'unsafe'). When I inspect the input, I can see the value intact, but you can't see the value pre-populated in the field. I tried different types of values, different contexts, and different types of input fields. [AEM 6.2]
<input type="email" name="senderEmail" value="${userProfile.email # context='text'}"/>
If the value is rendered in page source and also visible in browser inspector, could it be that it's hidden by some weird CSS? Something like color:transparent
There are many possible causes. I'll pitch in one, to help get you thinking. Is userProfile available via the use api?
I've made this mistake before:
<div data-sly-use.bean="com.beans.Bean">
${bean.value}
</div>
// ... other code
${bean.value}
The "Bean" isn't available later, outside it's host element.
If I understand your question correctly this isn't actually about HTL, but rather about the HTML input element itself. You have an input element with a value attribute set, yet that value is not displaying in the box. If that's correct, then I'd recommend doing some investigation around HTML input value not displaying when set, rather than sightly context issues.
Some possible answer would include css styles hiding the input text or javascript clearing out the values after page load. There are certainly more potential causes, but we'd need to know more about your page to provide a better answer.
To do some of your investigation you can try loading a component with only that input in it and see if that works, that would eliminate any css or js executing elsewhere on the page.

Live search combo in Ext JS 4.2.2

I'm trying to implement a live search combo. It suppose to work like this:
When I enter a character into the combo field I read the current value and send it as a parameter to the store's url. In the backend the parameter is used to return any value from the database that contains it, so the store behind the combo gets filled only with those filtered values.
As I continue to enter characters into the combo, the parameter should be updated and sent again to the backend and so on, getting like this a smaller and smaller store.
I tryied to achieve this behaviour using the combo's event keypress, even keyup, but the problem is it's impossible for me to get access to the current value from the combo field.
For example, when I entered the "for" string into the combo, how can I obtain this value using the combo object? comboName.getValue() doesn't work, it returns nothing "".
I already saw the live combo example here: http://docs.sencha.com/extjs/4.2.2/#!/example/form/forum-search.html but doesnt help me at all.
So my big question is: how do i get the current value while still editing the combo's field?
Any help would be appreciated, thanks.
You should be able to use
comboName.getValue();
or
comboName.getRawValue();
Where comboName is your combo box. Are neither working- I note in your post you state getValues() which is an improper method. You may want to also check whether when you're referring to your combo box object, that the reference is actually correct. The first argument from the key events is actually the object itself, so you should be able to do, e.g.
listeners:{
keyup:function(comboBox){
var value = comboBox.getValue() || comboBox.getRawValue();
console.log(value);
}
}
Swapping you the value getting method as appropriate.
I found that the combo already has a quick search behaviour, I just have to set queryMode on 'remote' and some other small configurations. More details here:
Ext Js 4.2.2 combobox queryMode

Find CURRENTLY selected <option> with XPath

What's the correct XPath syntax to check if an option element is currently selected, or just to get the selected option element from a select element, on an open page with which the user, and JavaScript, may have interacted? Is this even possible with XPath, or does it lack the ability to look at DOM properties?
I can't find any documentation on this, and have (speculatively) tried:
//option[#selected=true]
//option[#selected="selected"]
//option[#selected]
but none of these work; they simply don't match any elements.
(In case it matters, I've tried this both using the $x function in the Chrome developer console, and using the find_elements_by_xpath method in Selenium for Python.)
Short answer: it's not possible.
Longer answer: XPath can look at HTML attributes, but it can't look at DOM properties. Selecting an <option> element in a <select> changes the selected property of the <option> to true, and also changes the value property of its parent <select> element, but it doesn't affect the attributes of either, so it is invisible to XPath.
To find <option> elements that have the selected attribute set, which is often how a page author might determine which option is initially selected, you can use //option[#selected]. But this does not find the currently selected <option>; changes that the user makes to the selection are invisible to XPath. There's no guarantee it will even find the initially selected option, since it's possible that the page author didn't put the selected attribute on any elements and either let the browser select the first option by default or had some JavaScript select the initial option via the selected property.
The multiple other answers here claiming that a selector like //option[#selected] can detect selection changes made by the user after the page loads are simply completely wrong.
Of course, if you're able to use CSS selectors instead of XPath selectors, then option:checked will do the job.
The problem could be the " (double quotes).
//select/option[#selected='selected'] - Will match the selected option, i am using this successfully.
//select/option[#selected='selected' and #value='specific value'] - Will only match the selected option if it has a 'specific value', i'm also using this.
If you are still having trouble, it could be an entirely different problem, perhaps there is no option node. I hope this helps.
I think we can use a knowledge from #Mark's answer and account that. Let's just find a node which HAS desired attribute:
tree.xpath('//select/option[#selected]/text()')[0].strip()
I tried "//option[#selected=''] and it has worked for me.
it is able to highlight the selected option within Page objects model.
I would try //option[#selected='true']
i.e. driver.findElements(By.xpath("//option[#selected='true']")).getText();

Is it allowed to use <label> tag without labeled control?

I need to show in a page a list of, let's say, person's properties that should be rendered more or less as follow:
name: Name
date: 1/1/2000
other: Other
Reading the doc they say:
The LABEL element may be used to attach information to controls.
So, is it the right tag to encompass the names of the properties like name, date...
even if there's not an <input> to associate with?
Nope, as per Quentin’s answer.
However, in HTML5, <dl> can be used for generic associations where <label> isn’t appropriate.
No.
It says that it can associate information with controls.
It does not say that it can associate information with anything else.
See also the newer (but draft) specification:
Some elements, not all of them form-associated, are categorized as
labelable elements. These are elements that can be associated with a
label element.
button input (if the type attribute is not in the hidden state) keygen
meter output progress select textarea
No, it is not correct to use the label element like that.
The important thing here is the meaning of may.
The LABEL element may be used to attach information to controls.
RFC 2119 (which the HTML4 spec follows) defines may:
May: This word, or the adjective "OPTIONAL", mean that an item is truly optional
So here, may does not mean the label element can be used for other purposes; it just means that it is not required to use a label element with controls.
As far as alternatives go, it depends what you want to achieve. If you are just trying to follow the spec closely, then I suggest using p and a strong element for each pair. If you want the data to be more meaningful to computers, you could consider using one of the Microformat specifications.
I partially agree with the answers so far but want to add that if you want to use labels for some reason, then I would display the property values in read-only controls, and then your labels will be valid.
I've done this using appropriate styling to differentiate the read-only controls from the functioning controls to avoid confusing your users. This was on a sequence of pages which built up the information gathered from the user in a wizard.
I have this link to W3C - the "Editor's Draft" as opposed to the link above which is the "Working Draft", which states that you can associate it with any element - as long as it's 'labelable' - even though this is a subsection of the Form section. It states earlier that a labelable element does not have to be within a form.
http://dev.w3.org/html5/spec/single-page.html#the-label-element

DOM - preferred way to access a select's value?

In several recent answers I see this code given as the way to retrieve the currently selected value of a <select> tag:
el.options[el.selectedIndex].value
Whereas the MDN documentation says that the .value property of an HTMLSelectElement is equivalent ("The value of this form control, that is, of the first selected option.")
el.value
Is there some reason (old broken browsers?) why the longer version seems to be preferred?
To my best knowledge, the .value way has always worked.
There is actually an extra problem with the first one - what happens when the user has not yet selected an option? Then the .selectedIndex is -1, which will make your script crash.
So go with el.value