I have an issue with the HTML select where I want to display longer options as ellipsis. I ma able to achieve this via javascript onChange where I check the length of the selected option text and if its greater than lets say N, it changes it to an ellipsis'd text. The problem here is that once the option is selected and ellipsis'd, and I click on the select box again , the original text now appears as ellipsis'd one. I need to always display the original list of options and perform the ellipsis only when an option is selected.
My onChange code looks like
if(option[selectedIndex].text.length > N){
var val = option[selectedIndex].text;
option[selectedIndex].text = option[selectedIndex].text.substr(0,N) + "...";
}
One of the way i thought to accomplish this was to refresh the original list whenever the select is clicked. Unfortunately my browser doesn't support 'click' event on HTML select. Evenif I use
event.preventDefault();
the DOM recognizes click event but is fired only after the list is displayed thereby defying the purpose. something like what i am doing here jsFiddle
Also a big limitation that I CANNOT use jQuery in this case!
Please advise!
To accomplish what you want, you have to first create a 'dummy' option element nested in the select element and hide it with CSS. When the user changes the value, you will overwrite the dummy display value with the value of the option selected by the user.
Afterwards, when the user goes to select a new option, the 'dummy' value will be hidden, but it will still be populated in the main select box. Here is some rough code based on your previous jsfiddle.
Caveat: I am not sure of the compatibility of this solution.
HTML:
<select id="select-el">
<option id="display-el" value="-1">Can't see me</option>
<option id="id1" value="1">Option 1</option>
<option id="id2" value="2">Option 2</option>
<option id="id3" value="3">Option 3</option>
<option id="id4" value="4">Option 4</option>
<option id="id5" value="5">Option Longer</option>
</select>
CSS:
#display-el {
display:none;
visibility: hidden;
}
JavaScript:
var N = 8;
var selectEl = document.getElementById('select-el');
var displayEl = document.getElementById('display-el');
selectEl.onchange= function(e) {
var index = selectEl.selectedIndex;
var option = selectEl[index];
selectEl.selectedIndex = 0;
if(option.text.length > N){
displayEl.text = option.text.substr(0, N) + "...";
} else {
displayEl.text = option.text
}
displayEl.value = option.value;
console.log(displayEl.value);
}
I've forked your jsFiddle here: http://jsfiddle.net/3v8yt/ so you can check it out.
I can think of two options.
Option 1:
have hidden elements with the "real text", let's say:
<input type="option1" value="Real text1" />
<input type="option2" value="Real text2" />
Then, when onchange is detected, repopulate select list (similar as you have, but instead for one element, apply the real text for all), then apply your code for selected (the '...').
Option 2:
before change the text to '...', save the state, I guess you only would need two javascript variables, let's say:
var actualOption = 0;
var realText = '';
Before apply the '...', set the actual state to those variables when onchange detected, something like:
1 - before change, set realText on actualOption (the option that is actually with '...')
2 - save realText plus actualOption with the new option (that is going to be changed)
3 - apply the '...'
When new onchange detected, it should restore the text of the option previously selected, and set the new one.
Hope you understand...
EDIT:
Long time that I don't work purely JS, but I'll try.
At some point on your code, declare 2 global vars:
var actualOption = 0;
var realText = '';
On your onchange function apply something like:
(...)
if (actualOption!=0) option[actualOption].text = realText;
(...)
On your if(option[selectedIndex....., apply something like:
var val = option[selectedIndex].text;
realText = val;
actualOption = selectedIndex;
option[selectedIndex].text = option[selectedIndex].text.substr(0,N) + "...";
In Resume:
Save the state of your selected option before change.
When new onchange detected, restore previous selected option, and save the new selected option state.
I think it should work.
You can actually achieve what you are wanting with just css, no need to replace option text using Javascript at all. You can even use the same css for both the select and the option.
CSS:
select, select option {
overflow: hidden;
text-overflow: ellipsis;
}
If you then have a width (or max-width) value set for the select and/or the option you should see the text includes ellipsis at the end, just before it is cut off.
Check out this jsfiddle example to see how easily this can be implemented.
Related
Okay so please read on before marking it as duplicate:
First Part: I have a select list. I need to set dynamically whenever I select that particular option.
Second Part: Once this is done, whenever I select another option from the same select list, I want the previous option's selected attribute to be removed and set to the current one.
Note: I dont care about getting the value. I just want to set "selected" attribute since I will be using that for another purpose.
Eg. Currently I selected option- Jquery
<select>
<option selected="selected">Jquery</option>
<option>Java</option>
<option>JS</option>
</select>
So the next time I select- Java, the following should occur:
<select>
<option>Jquery</option>
<option>Java</option>
<option selected="selected">JS</option>
</select>
So I have tried the following which doesn't seem to work:
//First remove the previous set attribute
$('select').click(function() {
$(this).find('option:selected').removeAttr('selected');
});
//Set the newly selected option's attribute to selected
$('select').on('change', function() {
$("option:selected").attr('selected','selected');
});
How can I make this happen? Javascript/Jquery solution that can be used for any similar select and not specific to this one.
Use an attribute selector to remove the attribute
The :selected selector works based on selected property, not the attribute
$('select').change(function(e){
$(this).find('[selected]').removeAttr('selected')
$(this).find(':selected').attr('selected','selected')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option selected="selected">Jquery</option>
<option>Java</option>
<option>JS</option>
</select>
Wrong Assumption
Attribute/Properties as Defaults
At first I thought this question was trivial because I naturally assumed that any attribute/property bestowed on a tag would show up easily since its just something that confirms a "state" to which an element is obviously in (ex. a checkbox is checked by a user, so there's no need to use .setAttribute() on it so it has the checked attribute because it should already have it by default.)
My assumption was wrong, attributes like checked, selected, disabled, etc are on a tag to set an initial "state" by default. So these attributes/properties do not magically manifest when a user checks a checkbox or selects on <option> from a <select> element. The two most effective ways to handle these attribute/properties is to:
Plain JavaScript
Use set/get/remove/hasAttribute() method family.
jQuery
Use .prop()/.removeProp() method, do not use .attr()
Solution
The following section discusses important parts of the Demo that follows:
var s = sel.options[sel.selectedIndex];
There's two parts to this assignment:
This s a HTMLOptionsCollection which is similar to a NodeList of an array-like Object.
.options
The second half is a property that is unique to <select> and <option> tags:
.selectedIndex
On its own it returns an index number of the first selected <option> of a given <select>, but in combination with the formerly mentioned .options Object, we have a very formidable tool to access a <select>, locate the selected <option>, and retrieve it as a useful DOM Object instead of an index number.
The rest of the demo uses a for() loop, Array.prototype.push(), .setAttribute(), .removeAttribute(). Almost forgot that the jQuery function listened for a "change" event occuring on the <select>:
$('select').on('change', function(e) {...
Demo
Details are commented in the demo on every line
// Listen for change events on a <select>
var s = $('select').on('change', function(sel) {
// Empty array
var sArr = [];
// Dereferenced jQuery Object
var sel = $('select')[0];
// options HTMLCollection with a selectedIndex property
var s = sel.options[sel.selectedIndex];
// Total number of loops
var sL = sel.length;
// for() loop
for (let S = 0; S < sL; S++) {
// On each loop a selected attr is removed from each option
sel[S].removeAttribute('selected');
// The empty array is loaded with only the first 3 loops
if (S < 3) {
sArr.push(sel[S]);
}
}
// One option from the 3 in the short array gets a selected attr
s.setAttribute('selected', 'selected');
// Clear console
console.clear();
// Display selected option
console.log(s);
// Display all 3 options from the short array
console.log(sArr);
});
.as-console-row-code {
color: gold;
background: #000;
font-size: 21px;
}
.as-console-row {
color: gold;
background: #000;
max-width: 15px;
}
<select>
<option> jQuery </option>
<option> JavaScript </option>
<option> CSS </option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
//initial code
var selectInputs = document.querySelectorAll('option:checked');
var selectArray=[];
for(var i=0;i<selectInputs.length;i++)
{
selectArray[i]=selectInputs[i].value;//am doing this since I found out (from stackoverflow) that selectInputs contains a NodeList and in order to use it, it must be converted or saved as an array
}
//later stage manipulation code
var input_select= document.querySelectorAll('option:checked');
for(var i=0;i<input_select.length;i++)
{
input_select[i].value=selectArray[i];//I am trying to change the value of the <select> option
}
PURPOSE: User selects option in a form and data is saved in local storage.
I want to reflect the same when the form reloads. I am not working for a specific form so using Jquery seems futile(as it works with class or id and I don't know the id or class of any tag of the generic form)
PROBLEM:
The problem is that I wanna select the entire options set of tag and not just the ones that have been checked/selected.The code above sets the value of the default selected option to the one stored in local storage but doesn't reflect the change in the form. It always displays the default value though giving
alert(input_select[i].value);
reflects the internal change perfectly!
Guess I gotta answer my own question :-D
If you could see, there's just one silly change in the
//later stage manipulation code
ABOVE.
ANSWER:
var input_select= document.querySelectorAll('select');
for(var i=0;i<input_select.length;i++)
{
input_select[i].value=selectArray[i];//I am trying to change the value of the <select> option
}
Instead of
var input_select= document.querySelectorAll('option:checked');
It must be
var input_select= document.querySelectorAll('select');
REASON: I have been trying to assign the stored value into the option itself (the option tag) rather than the select tag as a whole.
WARNING: In the code
input_select[i].value=selectArray[i];
It could also be
input_select[i].value="Friday";
provided that you already have an option like that, else it would show a blank.
<select name="days" id=days">
<option value="0"> Friday </option>
<option value="1"> Monday </option>
</select>
works
<select name="days" id=days">
<option value="0"> Saturday </option>
<option value="1"> Monday </option>
</select>
doesn't work. Shows a blank.
How do I display the selected option name in the div above it? If user has blue selected I want blue to show above.
<div id='text"> selection goes here</div>
<select id="dropdownselect">
<option> Red </option>
<option> White </option>
<option> Blue </option>
</select>
Use the following to get the text of the selected option:
var select = document.getElementById("dropdownselect");
var selectedText = select.options[select.selectedIndex].text;
Then, to add the value to the div with id text, use:
document.getElementById("text").innerHTML = selectedText;
If you want to reflect the selected value every time the option has changed, you need to attach the onchange event to the select, which, combined with the above code results in the following:
var select = document.getElementById("dropdownselect");
select.onchange = function () {
var selectedText = this.options[this.selectedIndex].text;
document.getElementById("text").innerHTML = selectedText;
};
Here's a working DEMO.
Just add onchange javascript event:
<div id="text"> selection goes here</div>
<select id="dropdownselect" onchange="document.getElementById('text').innerHTML = this.options[this.selectedIndex].text;">
<option> Red </option>
<option> White </option>
<option> Blue </option>
</select>
You should use a javascript framework to make it much easier. I personally use jQuery, in which case the javascript to get the value is:
$("#dropdownselect").val()
And you can change it automatically with:
<select id="dropdownselect" onChange="$('#text').text($(this).val());">
Similar functions are available with MooTools, or other frameworks I haven't used before.
jQuery can be made available with:
<script src="jquery.js"><!-- assuming you have a jquery file at this location -->
var selectBox = document.getElementById("dropdownselect"),
textDiv = document.getElementById("text");
textDiv.innerText = selectBox.options[selectBox.selectedIndex].text;
But i'd recommend using jQuery too.
I have a group list as select like that:
<select id="groups">
<option value="g1">G1</option>
<option value="g2">G2</option>
<option value="g3">G3</option>
</select>
I have a contact list which basically contains:
Name = group
============
Casper G1-G2-G3
Andy G1-G2
Mark G2-G3
When the user check the checkbox for Casperand click Edit button so G1-G2 and G3 should be highlighted (Selected) in the group list. When I get the value of the group field in the contact list, all of the three groups come with comma "G1-G2-G3".
Your help is highly appreciated.
Thanks,
Some tips, I believe it's good for you to solve this problem yourself ;)
Seems that Casper belongs to multiple groups, so you should set multiple="true" to your select
When you check Casper, retrieve the group data associated with him, say ["g1", "g2", "g3"]. Loop over this list, and set each option with the value to selected.
If you want to support IE6, you need also add a class, say selected to the selected option.
The CSS rule { option.selected: background: yellow} will do the trick.
If you only target on modern browser, option[selected]{ xxx } works well.
You could make the edit button assign the selected attribute to the options then use css to style it.
option[selected] { background: #f00; }
OK, so I guess there is a checkbox for Casper that when clicked calls the following function:
function(groupstring) {
// groupstring is something like "G1-G2"
var groups = groupstring.split("-");
var options = document.getElementById("groups").options;
for (var i=0; i<options.length; i++) {
var opt = options[i];
opt.defaultSelected = groups.indexOf(opt.value) > -1;
}
}
I'm not sure whether you want to use the selected or the defaultSelected property. Note that your select should have multiple set to true (<select id="groups" multiple>).
I have multiple select field each with multiple options.
So, by using jquery to get the respective selected options content, I would be able to get the selected option content. However, this work for the first select field. But, does not work for others. Others keep referencing the first select field selected options content, instead of it owns. Please guide me! Thanks!
My Select fields
<select id="resource_dd" name="resource_dd">
<option selected="selected" value="nil1">No resources.</option>
<option value="1">Week1</option>
<option value="2">Resource1</option>
</select>
<select id="module_dd" name="module_dd">
<option selected="selected" value="nil2">No restriction.</option>
<option value="1">IT1234</option>
<option value="2">IT2345</option>
</select>
Jquery to retrieve the selected content.
$("#module_dd").change(function ( event ) {
var option = $("this").children();
var module_id = $(option+":selected").val(); //module_id get 'nil1' as content instead of nil2
});
Just try this, it will give you the selected value.
$("#module_dd").change(function ( event ) {
var module_id = $(this).val();
});
First of all, you should be saying $(this) instead of $("this").
Second, $(event.target) is probably more appropriate here.
Third, using .children as in $(event.target).children(":selected") will get you what you want.
This is happening because you are referencing $("#module_dd").
You need to add another function and change that to $("#resource_dd") to get the other select field.
Problem code
var option = $("this").children();
var module_id = $(option+":selected").val();
You can't concat a selector string to a jQ collection object. You need to filter the option collection for those which are selected either by:
var option = $( this ).children(":selected");
Or
var option = $( this ).children();
var module_id = option.filter(":selected").val();
Please see Eli Courtwright's answer, but in addition to that, you should do something like $("select") or $("#module_dd, #resource_dd") to target both select fields.