What is the Twitter Bootstrap convention for adding a new style to form labels? - twitter-bootstrap-3

I want to create a new style for forms in my Twitter Bootstrap site and I want to keep with the SMACKS / OOCSS conventions.
This is the default form:
<form role="form">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<!-- More coontent in form here -->
If I want to override the input style it would seem to me to keep with conventions to add a class of form-control-newstyle:
<form role="form">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<!-- More coontent in form here -->
However I also want to style the label. Should I add a new style to the label or to the div.form-group?

.form-group wraps around form groups label and an input, it acts like a .row in a .form-horizontal and otherwise, when the form stacks on smaller viewports there's some vertical space so it all doesn't squish together.
The default label style that goes on all labels is:
label {
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
font-weight: bold;
}
To do
.form-group label {}
Would affect all labels if you've properly formatted your forms.
If you just want to isolate it to a specific label you can make a class for that label and assign a class to just that label. If you want to affect all labels you can just modify the label element.
You can also make a new parent class for anything wrapping around that form and address the label styling like that.

Related

How to line break the selected option text in a MaterializeCSS select

I have a MaterializeCSS form with selects which have more text than the default width can show.
Currently, the text is a single line that is simply cut off at the widget edge.
The expanded dropdown of options line breaks the text correctly, but the collapsed dropdown does not.
I want to resize the collapsed select dropdown so that all text is shown.
My form is generated by django-material in a Django app, but I believe my fundamental problem is with MaterializeCSS's select widget.
An example element looks like this:
<div class="select-field col s12 required" id="id_formset-organisation_answers-1-question_container">
<label for="id_formset-organisation_answers-1-question">Question</label>
<div class="select-wrapper">
<input class="select-dropdown dropdown-trigger" type="text" readonly="true"
data-target="select-options-f739ead4-0165-a758-650e-74ba61fac041">
<ul id="select-options-f739ead4-0165-a758-650e-74ba61fac041"
class="dropdown-content select-dropdown"
tabindex="0">
<li id="select-options-f739ead4-0165-a758-650e-74ba61fac0410" tabindex="0">
<span>---------</span>
</li>
<li id="select-options-f739ead4-0165-a758-650e-74ba61fac0411" tabindex="0">
<span>VERY LONG TEXT 1</span>
</li>
<li id="select-options-f739ead4-0165-a758-650e-74ba61fac0412" tabindex="0"
class="selected">
<span>VERY LONG TEXT 2</span>
</li>
<li id="select-options-f739ead4-0165-a758-650e-74ba61fac0413" tabindex="0">
<span>VERY LONG TEXT 3</span>
</li>
</ul>
<svg class="caret" height="24" viewBox="0 0 24 24" width="24"
xmlns="http://www.w3.org/2000/svg">
<path d="M7 10l5 5 5-5z"></path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
<select id="id_formset-organisation_answers-1-question"
name="formset-organisation_answers-1-question" tabindex="-1">
<option value="">---------</option>
<option value="1">VERY LONG TEXT 1</option>
<option value="2" selected="selected">VERY LONG TEXT 2</option>
<option value="3">VERY LONG TEXT 3</option>
</select>
</div>
<div class="help-block">The question.</div>
</div>
The element <input class="select-dropdown dropdown-trigger" type="text" readonly="true" data-target="..."> does not contain any inner HTML, but by some JS magig shows the selected option. That option, a very long text, is shown as a single line. That line is what I want to line break.
I have searched the MaterializeCSS docs, SO, and the web to figure out a way to force the text to linebreak. The obvious answer seems to be to apply CSS styles for display, overflow and the like.
Style via CSS
I can access the selected text from CSS:
input.select-dropdown {
/* This works: */
color:green;
min-height: 20rem;
/* This does not do anything: */
display: inline-block;
min-height: -moz-fit-content;
min-height: fit-content;
overflow-wrap: break-word;
z-index:10;
}
The above CSS makes the text in each select green and increases the box height, but still comes as a single line with invisible overflow.
I have experimented with different CSS selectors to make sure that we're targeting the correct element here.
No permutation of any CSS class here could get that line to wrap.
Style via JS
MaterializeCSS initialises the widgets through a lot of JS events on page load.
I can also override the styles using JS after page load by inserting:
/**
* Resize select dropdowns to fit text
* #see https://materializecss.com/select.html
*/
window.addEventListener('load', function() {
document.querySelectorAll('select').forEach((el) => {
console.log("Styling element " + el.id);
el.M_FormSelect.input.style.cssText="color:red;";
console.log(el.M_FormSelect.input.style);
});
So I can now take the text that was green as per my CSS and make it red. Again, no style related to text flow (overflow, display, etc) is able to break the text here either.

BEM. How to deal with label for/id?

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

What is the data-dojo-props used to specify text alignment = right?

I have been trying the documentation of dijit textbox, but there seem to be no proper documentation on how to do text-align: right css style settings.
<input type="text" name="firstname" value="testing testing"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="trim:true, propercase:true" id="firstname" />
If I add the "align: right" the parse fails. I also tried via CSS but the text-align seem to not be reflected.
<input type="text" name="firstname" value="testing testing"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="trim:true, propercase:true, align: right" id="firstname" />
I also tried text align via css style but it does not parse well.
<input type="text" name="firstname" value="testing testing"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="style: { width: '150px'; text-align: right}" id="firstname" />
I don't know if it is possible to set text alignments using data-dojo-props attribute. However you can solve your problem using CSS selectors:
HTML:
<input type="text" name="firstname" value="testing testing"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="trim:true, propercase:true, align: right" id="firstname" />
CSS (examples):
input[name="firstname"] {
text-align: right;
}
or
#firstname {
text-align: right;
}
another elegant approach would be, to create an attribute selector querying the align: right value of your data-dojo-props attribute. With this selector you can reach all of your input items once.
input[data-dojo-props*="align: right"] {
text-align: right;
}
Here you can find an jsfiddle example.
UPDATE:
I have done some further investigations and I came to the conclusion that it is a syntax problem why the dojo parsing fails.
The following piece of code works without parsing errors:
<input type="text" name="firstname" value="testing testing"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="trim:true, propercase:true, style:'text-align: right'" id="firstname" />
but the result is not as expected:
<div class="dijit dijitReset dijitInline dijitLeft dijitTextBox"
id="widget_firstname" role="presentation" widgetid="firstname" style="text-
align: right;"><div class="dijitReset dijitInputField dijitInputContainer">
<input class="dijitReset dijitInputInner" data-dojo-attach-
point="textbox,focusNode" autocomplete="off" name="firstname" type="text"
tabindex="0" id="firstname" value="Testing Testing"></div></div>
because the styling will applied to the wrapper div.
I my opinion the best way to handle your requirements is to work only with CSS stylings without using the data-dojo-props attribute.
Dojo supports right aligned text inputs natively through bi-directional text support https://dojotoolkit.org/reference-guide/1.10/quickstart/internationalization/bi-directional-text.html
This is intended to reverse the text direction of a portion or the entire page (including inputs) by setting the dir tag on an element:
<body dir="rtl">
<!-- Widgets Here -->
</body>
However, that probably isn't what you want. Try this CSS:
.dijitInputContainer .dijitInputInner {
text-align: right;
}

How to change autocompleter widget size

I tried the code from the project to change the size of the select box:
<strong>Result Div :</strong>
<div id="formResult" class="result ui-widget-content ui-corner-all">Submit form bellow.</div>
<strong>Topics Div :</strong>
<div id="topics" class="result ui-widget-content ui-corner-all"></div>
<s:form id="form" action="echo" theme="simple" cssClass="yform">
<fieldset>
<legend>Select Box as Autocompleter</legend>
<div class="type-select">
<label for="echo">Echo: </label>
<sj:autocompleter
id="customers"
name="echo"
list="%{customers}"
listValue="name"
listKey="id"
selectBox="true"
selectBoxIcon="true"
onChangeTopics="autocompleteChange"
onFocusTopics="autocompleteFocus"
onSelectTopics="autocompleteSelect"
cssStyle="width:100%;"
/>
</div>
<div>
<sj:submit
targets="formResult"
value="AJAX Submit"
indicator="indicator"
button="true"
/>
<img id="indicator" src="images/indicator.gif" alt="Loading..." style="display:none"/>
</div>
</fieldset>
</s:form>
<br/>
but it doesn't work. I don't know what is the problem with this code.
Looking at generated HTML neither cssStyle nor cssClass of <sj:autocompleter> tag is set to actual input field. But you can use plain CSS to style this input field. Put your <sj:autocompleter> inside of some element to change only specific input then you can use something like that:
.type-select .s2j-combobox-input {
width: 100%;
}
Where type-select is class of wrapper element and s2j-combobox-input is the class of generated input field for the <sj:autocompleter>.

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