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.
Related
Is it possible to have 2 different inputs controlling a Foundation range slider? I need to add a field to set specific fractions (like so): https://codepen.io/jinch/pen/OaKpZX?editors=1000
<div class="row">
<div class="small-2 columns">Width:</div>
<div class="small-5 columns">
<div class="slider" data-slider data-initial-start="20" data-options="precision:3; decimal:3; start:8; end:36;" style="margin-top: 12px;">
<span class="slider-handle slideWidth" data-slider-handle role="slider" tabindex="1" aria-controls="customPort-2-width"></span>
<span class="slider-fill" data-slider-fill></span>
</div>
</div>
<div class="small-5 columns">
<input type="number" step="1" id="customPort-2-width" style="border: 1px solid #999999; display:inline-block; width:39%;">
<select class="fractions fractionWidth" name="WidthFraction" style="border: 1px solid #999999; display:inline-block; width:39%;">
<option value="0" selected="">0</option>
<option value="1/8">1/8</option>
<option value="1/4">1/4</option>
<option value="3/8">3/8</option>
<option value="1/2">1/2</option>
<option value="5/8">5/8</option>
<option value="3/4">3/4</option>
<option value="7/8">7/8</option>
</select>
<span class="small">in.</span>
</div>
TL;DR The good news is this can be done! The bad news is that you'll need to adjust your code a bit. I'm typing this out at ten minutes past midnight so you will more than likely need to refactor this 😂but I hope it's a starting point.
I'll go into the reasons for the implementation, but if you want to just get into it, I've created a Codepen https://codepen.io/jamie-endeavour/pen/zyxPaY?editors=1010
A Bit of Background
When I first found this question I looked at the Slider documentation and noticed a section about 'Reflow' - https://foundation.zurb.com/sites/docs/slider.html#reflow - after reading about this method I decided to look in the Foundation source code:
_reflow() {
this.setHandles();
}
Then, I looked into setHandles()...
setHandles() {
if(this.handles[1]) {
this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true, () => {
this._setHandlePos(this.$handle2, this.inputs.eq(1).val(), true);
});
} else {
this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true);
}
}
Notice here that _setHandlePos() makes a reference to a value from a property called inputs.
When the Slider class is initialized the following are set:
this.inputs = this.$element.find('input');
this.$input = this.inputs.length ? this.inputs.eq(0) : $(`#${this.$handle.attr('aria-controls')}`);
In your example, you weren't supplying an input element. So as you can see the code is using the value of aria-controls to build up the selector of the 'input'. This is where your restriction lies as you won't be able to associate two input fields with the Slider this way.
The Solution
So, remember the ternary that was used in this.$input? If we add an <input> within your .slider element, then we can use this as a reference point for the Slider.
<div class="slider" data-slider data-initial-start="20" data-options="precision:3; decimal:3; start:8; end:36;" style="margin-top: 12px;">
<input type="hidden" id="slider-reference" value="8" />
...
Now that you have a reference that can be used between the two input fields. You can then update this reference field's value on the back of a change callback against each element, then Slider will read this and update accordingly.
The JS required for the number input is fairly straightforward as we are supplying the absolute number that Slider needs to calculate the width position.
The fraction input gets a bit funky because you need to return a fraction of the difference between your min and max value (28) rather than a fraction of your max value (36 in this case). This is why I've included additional calculations to ensure you get the correct position against the Slider element. This is also the part that I feel can be refactored with a fresh set of eyes 😬
Finally, once you have acquired the new values in each change handler you simply call the _reflow method and this will update the Slider plugin accordingly without you having to re-initialize the plugin or anything nasty like that!
Is it possible that the user could select from the utility dropdown (see picture below) a search option which will effect the search text field?
Or is it possible merge the dropdown and search text field together?
I think you will be able to do this leveraging input-groups. But the docs also mention:
Avoid using elements here as they cannot be fully styled in
WebKit browsers.
HTML to integrate a <select> in the navbar:
<form class="navbar-form navbar-left select-search" role="search">
<div class="input-group">
<span class="input-group-addon">
<select class="form-control">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</span>
<input type="text" class="form-control">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
Then apply the following CSS:
.select-search .input-group-addon {
padding: 0;
border: 0;
}
.select-search .input-group .input-group-addon > select.form-control {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
Demo: http://www.bootply.com/8zPGZ9ySOl
I found this works well in chrome, but in firefox the select arrow got some button like styling:
I'm not sure how to fix the style of the select arrow here. Style the select with -moz-appearance:none or -moz-appearance:menulist won't help. Possible related to: Clearing the background of a <select> element's pulldown button with CSS
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.
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.
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>.