BEM. How to deal with label for/id? - input

As far as I know, BEM does not use elements id at all. But how to deal in this case with the label for/id combined with inputs? If I do not use id, people who're using screen readers will not get that this label is for that input. Am I right?

BEM suggests avoiding id for css selectors. It's perfectly valid to use id for A11y and usability.
<form class="form" method="post" action="">
<label for="email" class="form__label">Email</label>
<input type="email" id="email" class="form__control"/>
</form>
In the example above we are styling the input as an Element of the form block with the form__control class.
Also you can not use aria attributes without id for pointers to descriptive elements.
<div role="application" aria-labelledby="calendar" aria-describedby="info">
<h1 id="calendar">Calendar</h1>
<p id="info">
This calendar shows the game schedule for the Boston Red Sox.
</p>
<div role="grid">
...
</div>
</div>
Example taken from: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute

Related

Thymeleaf iteration with a specific integer, but not using an array size or index

Does anyone know if it's possible using thymeleaf templates to iterate with a specific numerical value that does not come from the index or the size of an array?
For example:
for(i=0;i<4;i++).
So something similar to a for loop and yes I have looked at the thymeleaf docs.
Thanks in advance!!
Hopefully this helps. The form below will be used to take in a chemical name along with a few other details which are the other fields. I would like to repeat the form fields a specific number of times which is determined by the user. So if the user is asked "how many chemicals would you like to add to your list?" and the answer is 3 I would like to have the form fields repeat 3 times.
<form method="post" th:object="${reagent}">
<div>
<label th:for="chemName">Compound/Reagent</label>
<input th:field="*{chemName}" />
<span th:errors="*{chemName}"></span>
</div>
<div>
<label th:for="mw">Molecular Weight(g/mol)</label>
<input th:field="*{mw}"/>
<span th:errors="*{mw}"></span>
</div>
<div>
<label th:for="density">Density(g/L)</label>
<input th:field="*{density}"/>
<span th:errors="*{density}"></span>
</div>
<div>
<label th:for="hazard">Hazards</label>
<textarea th:field="*{hazard}"></textarea><br/><br/>
<span th:errors="*{hazard}"></span>
</div>
<br/>
<input type="submit" value="Add Chemical"/>
</form>

capybara /cucumber can't find radio

I'm having an issue finding a radio button. Here is a snippet of the html:
<form action="/" id="frm-info" method="post"><input id="ClickedButton" name="ClickedButton" type="hidden" value="" /><input name="__RequestVerificationToken" type="hidden" value="KTQF3bkKPP0OirvtL1EYsW-Q77zq-8H9YAPqeoBB9ewpNSYoc0dOEout26qrtMmX6xBx0_roxqWRwCXAlwZRTyW9ZBTBjwNgifWqws6hyOFIRmc6O-7P6jZXbZNYJ5Pazt9Hmg2" /> <div class="row borGreyPad mlmrcolor bb0">
<div class="col-sm-12 coverImage">
<div class="col-md-7 col-lg-6 fr xs-fl">
<div class="frm-content axaborderBlue mt10">
<div class="pl25 pt15 pr15 pb10">
<p class="large-heading">Enter some basic information to get started</p>
<div class="row ">
<div class="row pl15">
<div class="col-sm-4 r xs-l mb5 f14">Application Taken: *</div>
<div class="col-sm-8 mb5">
<div class="groupBox">
<span class="dib f14 ">
<input id="ApplicationTaken" name="ApplicationTaken" tabindex="1" type="radio" value="ApplicationInPerson" /><span class="dib mr10 ">In Person</span>
</span>
<span class="dib f14 ">
<input id="ApplicationTaken" name="ApplicationTaken" tabindex="2" type="radio" value="ApplicationByPhone" /><span class="dib mr10 ">By Phone</span>
</span>
</div>
I want to select the radio button with name "ApplicationTaken" and value "ApplicationInPerson"
I've tried several different ways including:
When I click on the radio with name
"([^"]*)" and value "([^"]*)"$/ do |myName, myValue|
choose("#{myName}", :option => "#{myValue}")
end
and
When I click on the radio with name
"([^"]*)" and value "([^"]*)"$/ do |myName, myValue|
find(:xpath, "//input[#value='#{ myValue }']", match: :first).set(true)
end
I keep seeing the following error:
"Unable to find radio button "ApplicationTaken" with value "ApplicationInPerson".
I've also tried by ID, no luck. I CAN select a button on this page and fill in text fields, I just can't select radio buttons or drop downs. Thanks
Since you're using capybara try:
choose('Visible Text')
See:
https://gist.github.com/zhengjia/428105
For starters, you have two radio buttons with the same id. This is bad - you should not have duplicate ids on a page. Attempting to find an element by ID when there are duplicates is very unpredictable.
What's most likely happening is that it's finding the first element with a matching ID, and then checking the value attribute. When that doesnt match, it says the element could not be found, because it does not continue onto the next matching ID (because of the way id selectors work internally)
I see you're also using xpath to find the element. You generally should be using CSS instead of xpath for finding your elements.
So leaving the ID out, and using CSS instead, find('input[name=ApplicationTaken][value= ApplicationInPerson]') should get you the element you're looking for.

Can't get Cucumber/Capybara to find radio buttons

I'm having trouble getting Cucumber to "choose" a radio button and hoping someone can give me a sanity check. Without quoting a huge mass of HTML junk, here's the relevant portion (which I collected from print.html). It's within a modal div that is activated by a button. I can "click" that button and see the modal window appear (I'm running it as a #javascript scenario in Selenium).
<div class="modal-body pagination-centered">
<img src="/assets/payment.png" alt="Payment" />
<form novalidate="novalidate" method="post" id="edit_cart_1" class="simple_form edit_cart" action="/carts/complete" accept-charset="UTF-8">
<div style="margin:0;padding:0;display:inline">
<input type="hidden" value="✓" name="utf8" />
<input type="hidden" value="put" name="_method" />
</div>
<div class="control-group hidden cart_property_id">
<div class="controls">
<input type="hidden" name="cart[property_id]" id="cart_property_id" class="hidden" />
</div>
</div>
<div id="payment_fat_buttons" class="fat-buttons">
<div class="vertical-button-wrapper">
<input type="radio" value="cash" name="cart[payment_type]" id="cart_payment_type_cash_pay" data-property-id="1" />
<label for="cart_payment_type_cash_pay">Cash</label>
</div>
<div class="vertical-button-wrapper">
<input type="radio" value="credit" name="cart[payment_type]" id="cart_payment_type_credit_pay" data-property-id="1" />
<label for="cart_payment_type_credit_pay">Credit</label>
</div>
</div>
<div style="display: none;" id="cart_room_number_area_pay">
<div class="control-group string optional cart_room_number">
<label for="cart_room_number_pay" class="string optional control-label">Room number</label>
<div class="controls">
<input type="text" value="" size="50" name="cart[room_number]" id="cart_room_number_pay" class="string optional" />
</div>
</div>
</div>
<input type="checkbox" value="1" style="display: none;" name="receipt" id="receipt" />
<div class="sell-modal-footer">
<input type="submit" value="Complete With Receipt" name="commit" id="cart_complete_with_receipt" data_disable_with="Processing..." class="btn btn-danger" />
<input type="submit" value="Complete Sale" name="commit" data_disable_with="Processing..." class="btn btn-danger" />
</div>
</form>
</div>
I've tried as many different equivalent ways of getting at it that I can think of. Most obviously just by the label, or the ID, like:
choose 'cart_payment_type_cash_pay'
choose 'Cash'
which just gives me the error:
Unable to find radio button "cart_payment_type_cash_pay" (Capybara::ElementNotFound)
I thought it might have something to do with the modal dialog, visibility, etc. but I introduced the ID #payment_fat_buttons just for testing, and when I look for it like this:
find('#payment_fat_buttons').choose('Cash')
it finds that DIV OK, but still not the radio button. I also tried getting at it with :xpath on the whole page, and within a scope like:
within(:xpath, "//div[#id='payment_methods']") do
find(:xpath, ".//input[#id='cart_payment_type_cash_pay']").choose
end
which acts like it can also find the outer DIV, but not the radio button - I get the error:
Unable to find xpath ".//input[#id='cart_payment_type_cash_pay']" (Capybara::ElementNotFound)
Generally, it seems like I can find any arbitrary element around the radio buttons with :xpath or CSS expressions, just not the radio buttons. I can also push the submit buttons on the form without any problem. I tried dropping the data attributes as a test - no difference. Any help would be greatly appreciated. This is driving me nuts because it seems so simple, and yet I'm getting nowhere. I need to choose that for a big segment of Scenarios, so if I can't figure it out, I'll have to resort to something hokey and horrible. Many thanks in advance...
Relevant versions from Gemfile.lock:
rails (3.2.13)
cucumber (1.3.8)
gherkin (2.12.2)
cucumber-rails (1.4.0)
capybara (2.1.0)
selenium-webdriver (2.35.1)
I finally figured this one out. Capybara wasn't finding the radio button because buried deep in my styles was some CSS that hid it in order to change the appearance. Once I realized that, I figured out that I could side-step the whole issue of finding the radio button by just doing a click on the label instead:
find(:xpath, "//label[#for='the_radio_button_id']").click
I didn't realize it was possible to get at radio buttons that way - but in any case, it solves the issue of how to click a radio button that Capybara won't find due to styling or other issues. Hope that helps someone else.

Twitter Bootstrap 3 form-inline text input width depends on label width

I've noticed strange behavior of the Twitter Bootstrap 3: size of the input box depends on the size of its label when they are grouped with form-group:
<form class="form-inline">
<div class="form-group">
<label>A</label>
<input type="text" class="form-control" placeholder="First Name">
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" placeholder="Last Name">
</div>
</form>
Here is demo: http://jsfiddle.net/a3vAP/4/
Is this feature or bug? What would be the fix? I need input boxes of the same size.
The longer label is causing the input to be longer since they're both contained in the same form-group which uses display:inline-block so it's automatically sizing to the width of the label.
According the Bootstrap docs..
"Inputs, selects, and textareas are 100% wide by default in Bootstrap.
To use the inline form, you'll have to set a width on the form
controls used within."
So, you'd need to add some simple CSS to control the width..
.form-inline .form-group input {
width:140px;
}
Demo: http://bootply.com/87747

What is the Best Practice for placing validation messages using Twitter Bootstrap 3

I'm using MVC4 but I imagine this is an issue for anyone using the new Bootstrap 3 version. Since form-control is now width:100% by default, what is the best practice for placing validation messages?
In version 2.x, placing the validation messages in the help-inline span just after the input control worked best to ensure that the message was placed to the right of the control.
But in version 3, they always get pushed to the bottom making all the controls shift down because the validation messages are forced under the control.
<div class="form-group has-error">
<label for="Label" class="col-lg-2 control-label">Label</label>
<div class="col-lg-5">
<input class="form-control input-validation-error" data-val="true" data-val-required="Required" id="Label" name="Label" type="text" value="">
<span class="help-inline"><span class="field-validation-error" data-valmsg-for="Label" data-valmsg-replace="true"><span for="Label" generated="true" class="">Required</span></span></span>
</div>
</div>
I've considered manually setting them on a new column like this (below) but wondering if there was a more acceptable way or a less manual way of dealing with this.
<div class="form-group has-error">
<label for="Label" class="col-lg-2 control-label">Label</label>
<div class="col-lg-5">
<input class="form-control input-validation-error" data-val="true" data-val-required="Required" id="Label" name="Label" type="text" value="">
</div>
<div class="col-lg-5">
<p class="form-control-static"><span class="field-validation-error" data-valmsg-for="Label" data-valmsg-replace="true"><span for="Label" generated="true" class="">Required</span></span></p>
</div>
</div>
I wouldn't say there are "best practices" for presenting form validation errors. It's more of a personal design choice.
Depending on how much JS you want to write, you could get a little slick and insert an input group addon which holds an error message in a tooltip icon, like so...
<div class="input-group">
<input type="text" class="form-control">
<span class="input-group-addon">
<i data-toggle="tooltip" title="Error msg here" data-container="body" class="glyphicon glyphicon-question-sign"></i>
</span>
</div>
Honestly though, I think messages appearing below input fields are fine, as long as they don't disturb page layout and push content down when they appear. (Which is just a matter of having a container that displays block and has a a hard-coded height.)