I have a multiple select listbox. This listbox contains the names of many entities. Around 1000+. So as you can see it would be very annoying to scroll through. What I want to do is to display A-Z on the side vertically. When the user clicks a letter, javascript is fired to set the scroll position (NOT select the item) of the first occurring character selected. This is a control that is being created in c# and javascript being rendered using the client script manager. Basically what I have done so far is to add a new htmlanchor from a char array A-Z. This lists the alphabet vertically. This would be very similar to an iTouch/iPhone music library, touch/click the letter and the scroll is set to the first occurrence. I know how to loop through the list. So far I have an onclick function that acts as such:
private HtmlGenericControl alphaSortContainer;
this.alphaSortContainer = new HtmlGenericControl("div");
char[] alphabet = { 'Z'.......'A' };
for (int i = 0; i < 26; i++)
{
var letter = new HtmlAnchor();
link.InnerText = alphabet[i].ToString();
link.Attributes.Add("onclick", "javascript:jumpToIndex('" + link.InnerText + "');");
alphaSortContainer.Controls.Add(letter);
}
The above code adds (or should) letters stacked on top of each other. Their onclick will fire the javascript function and send in the letter.
My javascript so far:
function jumpToIndex(var index) {
var list = document.getElementByID('" + this.list.ClientID + "');
for(var i=0; i < list.length; i++) {
if(list.options[i].value.charAt(0) == index) {
HOW TO SET THE SCROLL POSITION TO MAKE THAT OBJECT THE TOP OF THE LIST BOX
break; //pretty sure this is how i would break out of both loops.
}
}
}
I just need to scroll to the item that matches the if statement. Also, i am pretty sure that would be how I break out of both loops. Please help!
The only way to do this is to select one of the options in the select list, which you can do the following way:
<select id="myselect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected="selected">3</option>
<option value="4">4</option>
</select>
Of course, if you don't want to make this choice serverside when you build the list or if you build the list clientside, you can always do it using javascript like this:
document.getElementById('myselect').options[<insert number>].selected = true;
and remember that <insert number> is zerobased
Now before you say i don't want to select it, just scroll to it, remember that if you see an option in a listbox, it is already selected by default.
Unless you are working with a multi-select selectbox in which case this is a whole different ballgame, and you are shit out of luck ;)
Have you considered not displaying the whole list but having javascript arrays for each letter. When a letter is selected the list is populated with just that letter's items?
var alphalist=new Array();
alphalist['a']=new Array('aardvark','acorns','apples');
alphalist['b']=new Array('baby','barley');
//etc
function fill_list{selectedLetter){
listItems=alphalist[selectedLetter];
mylist=document.getElementById('mylist');
mylist.length=0;.length=0;
for(var i=0;i<listItems.length;i++){
optionName = new Option(listItems[i],listItems[i])
var length = mylist.length;
mylist.options[length] = optionName;
}
}
Related
I am populating my dropdown menu dynamically and I sometimes end up with having a single element in the dropdown. For multiple elements, there is no problem, the onChange() of my select tag works perfect. However, when there is only 1 element, the onChange() does not invoke. How can I solve this problem? Thank you!
getOptions(){
var dynamicOptions = this.props.something
const returnedOptions = []
for(int i=0; i< dynamicOptions.length;i++){
returnedOptions.push(<option value = {dynamicOptions[i]}>something</option>
}
return dynamicOptions;
}
return(
<select onChange=this.onchangemethod, value = {something}>
{this.getOptions()}
</select>
)
You would be having the same problem if the user would like to select the first option of many, since it would be the already selected one and the user would not need to re-select it.
One workaround is to always specify an "empty" option with a placeholder text
<select onChange={this.onchangemethod}>
<option value="">Please choose an option</option>
{this.getOptions()}
</select>
This way, you will always have at least two options, and the user will have to open and select one.
An alternative is to pre-select the first option so that, again, in case of user inaction, there is one option selected.
for(int i=0; i < dynamicOptions.length; i++) {
const optionProperties = {value: dynamicOptions[i]};
if (i === 0) { optionProperties.selected: true };
returnedOptions.push(<option {...optionProperties}>something</option>);
}
I have a chrome extension that when I click it, it will click all the same element buttons on a page and then after the function is done, I want it to select all the 'P's on the drop down. I have multiple 'pf' classes on the page and will need to set all of the to P. The first function is working, when it gets to the second function, there is an error showing the option.length is undefined. My question is how do it get all the option counts inside a class?
function clickUpdate(_callback) {
var updateArray = document.getElementsByClassName("updateButton");
[].slice.call(updateArray).forEach(function(item) {
item.click();
});
console.log("this is the array legnth: " + updateArray.length);
_callback();
}
//Get select object
var objSelect = document.getElementsByClassName("pf");
//Set selected
setSelectedValue(objSelect, "P");
function setSelectedValue(selectObj, valueToSet) {
clickUpdate(function(){
console.log("I am done with the first function");
});
for (var i = 0; i < selectObj.options.length; i++) {
if (selectObj.options[i].text == valueToSet) {
selectObj.options[i].selected = true;
return;
}
}
}
<select class="pf">
<option selected="selected" value="">Not Run</option>
<option value="P">Pass</option>
<option value="F">Fail</option>
<option value="N">N/A</option></select>
Here's your problem:
//Get select object
var objSelect = document.getElementsByClassName("pf");
This doesn't just return the select dropdown - it returns an HTMLCollection (ie, a group of elements) with any elements matching that class name. Even if there's only one present, it'll come back as a collection. But your setSelectedValue function isn't expecting a collection, just a single element - that's why you get the undefined error.
There are a few ways you can handle this, depending on what you're doing elsewhere on the page:
You can use document.querySelector('.pf') to return the first element with that class - do this if you're only going to have one .pf on the page, or only want to manage one of them.
Alternately, you can use document.getElementsByClassName('pf')[0] to achieve the same thing.
Or you can give the select an id and use document.querySelector('#pf') or document.getElementById('pf')
If, on the other hand, you plan to have multiple .pf elements that all work this way...you'll have to do some refactoring first. But that's a whole other discussion.
I started studying javascripting and was wondering if anyone know how to hide values in dropdown list for html?
For example: a dropdwon list with values
Select One
Item1
Item2
Item3
Item4
Item5
I wanna hide the Item 4 and 5, like this and show it when "Show... " is clicked.
Select One
Item1
Item2
Item3
Show 2 more items (Item 4 and 5 hidden)
Is that possible? Below is a piece of code i already started.
var css = select;
var markers = cluster.getMarkers();
var markersLength = markers.length;
var nextOption = new Option("Select One");
css.add(nextOption, 0);
for(var i = 0; i < markersLength; i++) {
nextOption = new Option(markers[i].title);
try {
css.add(nextOption, -1);
} catch (e) {
css.add(nextOption, null);
}
}
You want a generic solution, so tag the more option and the hidden items with classes.
It turns out you cannot consistently style-out options in a select across browsers, so you need to dynamically alter the list options: Refer to this question: How to hide a <option> in a <select> menu with CSS?
Final solution (append elements from another hidden select):
JSFiddle: http://jsfiddle.net/TrueBlueAussie/93D3h/12/
HTML:
Select One
<select class="hidden">
<option>Item4</option>
<option>Item5</option>
<option>Item6</option>
<option>Item7</option>
<select>
<select>
<option>Item1</option>
<option>Item2</option>
<option>Item3</option>
<option class="more">More</option>
</select>
jQuery:
$('select').change(function(){
var $select = $(this);
if ($select.val() == "More"){
$('.more').remove();
$select.append($('.hidden').children());
}
});
Previous info:
Then on then select change event you hide the more option and show the hidden elements:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/93D3h/2/
$('select').change(function(){
var $select = $(this);
if ($select.val() == "More"){
$('.more').hide().prevAll('.hidden').show();
}
});
There appears to be a weird bug in selects as the last item is always visible (even when styled out!). I added a blank entry to fix this for now. This is also why I did not place the hidden items after the more as the last one always shows (what a strange bug - have asked that as a new question: Why is last select option always shown, even when styled out).
You will also want to clear the selected value of "More" as that will no longer exist.
e.g. http://jsfiddle.net/TrueBlueAussie/93D3h/3/
$('select').change(function () {
var $select = $(this);
if ($select.val() == "More") {
$('.more').hide().prevAll('.hidden').show();
$select.val('');
}
});
Followup:
Based on my related question, I was pointed to this one: How to hide a <option> in a <select> menu with CSS? Apparently you cannot style out select options consistently, so adding the items to the list dynamically would be the ideal solution.
Here's my solution:
Html
<select id="test">
<option value="1">Select One</option>
<option value="2">Item 1</option>
<option value="3">Item 2</option>
<option value="4">Item 3</option>
<option value="5">Select Two</option>
<option value="6">Item 4</option>
<option value="7">Item 5</option>
</select>
Script
var array1 = ["1","6","7"];
var array2 = ["1","2","3","4"];
var arrayAll = ["1","2","3","4","5","6","7"];
function hideOptions(array) {
for (var i = 0; i < array.length; i++) {
$('#test option[value="' + array[i] + '"]').hide();
}
}
function showOptions(array) {
for (var i = 0; i < array.length; i++) {
$('#test option[value="' + array[i] + '"]').show();
}
}
$("#test").change(function(){
if($("#test").val()=="5"){
hideOptions(array2);
showOptions(array1);
}
if($("#test").val()=="1"){
hideOptions(array1);
showOptions(array2);
}
});
hideOptions(array1);
here's the fiddle
What about something like:
<head>
<script type="text/javascript">
function makeDynamicOption(target, threshold, messageMore, messageLess) {
var allOptions = collectOptions();
target.addEventListener("change", updateOptions, false); // Use your own event manager
showOptions(threshold);
addMessage(messageMore);
// ---
function collectOptions() {
var options = [];
for(var ii=0; ii<target.options.length; ii++) {
options.push(target.options[ii]);
}
return options;
}
function updateOptions() {
var selectedText = this.options[this.selectedIndex].text;
if (selectedText == messageMore) {
showOptions(allOptions.length);
addMessage(messageLess);
} else if (selectedText == messageLess) {
showOptions(threshold);
addMessage(messageMore);
}
}
function showOptions(upToIndex) {
removeOptions();
for (var ii=0; ii<upToIndex; ii++) {
target.options[ii] = allOptions[ii];
}
}
function removeOptions() {
while(target.options.length > 0) {
target.removeChild(target.options[0]);
}
}
function addMessage(message) {
target.options[target.options.length] = new Option(message, "");
}
}
</script>
</head>
<body>
<select id="foo">
<option value="value1">item1</option>
<option value="value2">item2</option>
<option value="value3">item3</option>
<option value="value4">item4</option>
<option value="value5">item5</option>
</select>
<script type="text/javascript">
makeDynamicOption(
document.getElementById("foo"),
3,
"More...",
"Less..."
);
</script>
</body>
This design separates the lib part (to be linked in the HEAD as an external script) from the activation part. It also lets you inject localized text while generating the view, and preserve existing options in case you have other scripts interacting with them. Note that you should still use your own event manager, and not addEventListener directly as shown in the script, for better cross-browser support.
EDIT: here's how the scripts works:
You call the makeDynamicOptions() function on the select object you want to augment, passing the number of options you want to display, as well as messages to expand/collapse other options. The messages can be written by the view manager, i.e. it could be easily localized if needed.
The first initialization step sees that all original options be collected, so that they can be added back when the user wants to expand the select. Note that we collect the objects themselves, and not only their value/text property values, as other scripts could reference these objects.
The second initialization step registers a change handler on the select, so as to trigger the update on the options list. The script uses addEventListener, but one should substitute one's own event management mechanism, for better cross-browser support.
The last initialization step collapses the select in the intended start position.
The rest is pretty straightforward. Once the user selects an option, the script decides whether the list of options should be repopulated, by analyzing the text of the selected option, and comparing it to the provided expand/collapse labels. If options are to be redrawn, then the script removes all options, adds the expected ones, then adds the new expand/collapse message.
HTH.
I have a form UI whereby several sections require duplicate HTML select list to be updated dynamically from a single, dynamically-updatable select list.
The dynamically-updatable list works just fine, in that new options can be added and removed on-the-fly. I can then get this update to propagate through each of the duplicate lists using JQuery .find(). I have even added a bit of logic to maintain the currently selected index of the original select list.
What I'm not able to do is maintain the selected state of each of the duplicate select lists as new options are added and removed from the original select list. As each update to the original select list iterates through each duplicate select list, they lose their currently selected option index.
Here is an example of my conundrum--*EDIT--I would encourage you to try and execute the code I've provided below and apply your theories before suggesting a solution, as none of the suggestions so far have worked. I believe you will find this problem a good deal trickier than you might assume at first:
<form>
<div id="duplicates">
<!--// I need for each of these duplicates to maintain their currently selected option index as the original updates dynamically //-->
<select>
</select>
<select>
</select>
<select>
</select>
</div>
<div>
<input type="button" value="add/copy" onclick="var original_select = document.getElementById('original'); var new_option = document.createElement('option'); new_option.text = 'Option #' + original_select.length; new_option.value = new_option.text; document.getElementById('original').add(new_option); original_select.options[original_select.options.length-1].selected = 'selected'; updateDuplicates();" />
<input type="button" value="remove" onclick="var original_select = document.getElementById('original'); var current_selected = original_select.selectedIndex; original_select.remove(original_select[current_selected]); if(original_select.options.length){original_select.options[current_selected < original_select.options.length?current_selected:current_selected - 1].selected = 'selected';} updateDuplicates();" />
<select id="original">
</select>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
function updateDuplicates(){
$("#duplicates").find("select").html($("#original").html());
}
</script>
</form>
It is important to note that the duplicate HTML select lists should remain somewhat arbitrary, if at all possible (i.e.; no ID's) as this method needs to apply generically to other dynamically-created select lists throughout the document.
Thanks in advance!
Still not 100% sure what you're asking but it seems like this should do what you're looking for and is a few less lines of code.
(function () {
function updateDuplicates() {
$("#duplicates").find("select").html($("#original").html());
$('#duplicates select').each(function () {
var lastSelectedValue = $(this).data('lastSelectedValue');
$(this).val(lastSelectedValue || $(this).val());
});
}
$(document).ready(function () {
$('button:contains(remove)').bind('click', function (e) {
e.preventDefault();
var original_select = document.getElementById('original'),
current_selected = original_select.selectedIndex;
original_select.remove(original_select[current_selected]);
if (original_select.options.length) {
original_select.options[current_selected < original_select.options.length ? current_selected : current_selected - 1].selected = 'selected';
}
updateDuplicates();
});
$('button:contains(add/copy)').bind('click', function (e) {
e.preventDefault();
var original_select = document.getElementById('original'),
new_option = document.createElement('option');
new_option.text = 'Option #' + original_select.length;
new_option.value = new_option.text;
document.getElementById('original').add(new_option);
original_select.options[original_select.options.length - 1].selected = 'selected';
updateDuplicates();
});
$('#duplicates select').bind('change', function () {
$(this).data('lastSelectedValue', $(this).val());
});
} ());
} ());
EDIT: I changed your markup to be
<button>add/copy</button>
<button>remove</button>
just set the currently selected item/value of select to some variable, then do your operation,
finally reselect the value to the select.
Okay, I think I have a workable approach to a solution, if not a clumsy one. The tricky part isn't adding a value to the original list, because the added option is always at the end of the list. The problem comes in removing a select option because doing so changes the index of the currently selectedIndex. I've tested using Google Chrome on a Mac with no errors. I have commented the code to demonstrate how I approached my solution:
<form>
<div id="duplicates">
<!--// Each of these select lists should maintain their currently selected index //-->
<select>
</select>
<select>
</select>
<select>
</select>
</div>
<div>
<!--// Using a generic function to capture each event //-->
<input type="button" value="add/copy" onClick="updateDuplicates('add');" />
<input type="button" value="remove" onClick="updateDuplicates('remove');" />
<select id="original">
</select>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
function updateDuplicates(editMode){
///* Capture the selectedIndex of each select list and store that value in an Array *///
var original_select = document.getElementById('original');
var current_selected = new Array();
$("#duplicates").find("select").each(function(index, element) {
current_selected[index] = element.selectedIndex;
});
switch(editMode){
case "add":
var new_option = document.createElement('option');
new_option.text = 'Option #' + original_select.length;
new_option.value = new_option.text;
original_select.add(new_option);
original_select.options[original_select.options.length-1].selected = 'selected';
///* Traverse each select element and copy the original into it, then set the defaultSelected attribute for each *///
$("#duplicates").find("select").each(function(index, element){
$(element).html($("#original").html());
///* Retrieve the currently selected state stored in the array from before, making sure it is a non -1 value, then set the defaultSelected attribute of the currently indexed element... *///
if(current_selected[index] > -1){
element.options[current_selected[index]].defaultSelected = true;
}
});
break;
case "remove":
var current_index = original_select.selectedIndex;
original_select.remove(original_select[current_index]);
///* Thou shalt not remove from thine empty list *///
if(original_select.options.length){
original_select.options[current_index > 0?current_index - 1:0].selected = 'selected';
}
///* Traverse each select element and copy the original into it... *///
$("#duplicates").find("select").each(function(index, element){
$(element).html($("#original").html());
///* Avoid operating on empty lists... *///
if(original_select.options.length){
///* Retrieve the currently selected state stored in the array from before, making sure it is a non -1 value... *///
if(current_selected[index] > -1){
///* If the stored index state is less or equal to the currently selected index of the original... *///
if(current_selected[index] <= current_index){
element.options[current_selected[index]].defaultSelected = true;
///* ...otherwise, the stored index state must be greater than the currently selected index of the original, and therefore we want to select the index after the stored state *///
}else{
element.options[current_selected[index] - 1].defaultSelected = true;
}
}
}
});
}
}
</script>
</form>
There is plenty of room to modify my code so that options can be inserted after the currently selectedIndex rather than appended to the end of the original select list. Theoretically, a multi-select list/menu should work as well. Have at thee.
I'm sure one of the geniuses here will be able to do this same thing with cleaner, prettier code than mine. Thanks to everyone who reviewed and commented on my original question! Cheers.
If you can reset a little, I think that the problem is you are setting your select list's HTML to another list's HTML. The browser probably doesn't try to preserve the currently selected item if all the of underlying html is being changed.
So, I think what you might try doing is explicitly adding the option elements to the target lists.
Try this jsfiddle. If you select an item other than the default first item and click "add", notice that the selected item is maintained. So you need to be a little more surgical in your managing of the target list items.
Maybe that'll help or maybe I missed the point.
There seems to be a problem with the JS Code for Opera browsers, as it only removes the last option tag that is selected within a multiple select tag, can someone please help me.
Here is the HTML for this:
<select id="actions_list" name="layouts" multiple style="height: 128px; width: 300px;">
<option value="forum">forum</option>
<option value="collapse">collapse</option>
<option value="[topic]">[topic]</option>
<option value="[board]">[board]</option>
</select>
Of course it's within a form tag, but there's a ton more code involved with this form, but here is the relevant info for this.
Here is the JS that should handle this, but only removes the last selected option in Opera, not sure about other browsers, but it really needs to remove all selected options, not just the last selected option...
var action_list = document.getElementById("actions_list");
var i = action_list.options.length;
while(i--)
{
if (action_list.options[i].selected)
{
action_list.remove(i);
}
}
What is wrong with this? I can't figure it out one bit.
It's easiest to do this with jQuery but it you want to do this using plain Javascript you can.
The problem you are experiencing is that when you remove an item from the options list in Opera it deselects all the selected items, so only the first is removed. A workaround is to first remember which items were selected before removing any.
var action_list = document.getElementById("actions_list");
// Remember selected items.
var is_selected = [];
for (var i = 0; i < action_list.options.length; ++i)
{
is_selected[i] = action_list.options[i].selected;
}
// Remove selected items.
i = action_list.options.length;
while (i--)
{
if (is_selected[i])
{
action_list.remove(i);
}
}
You can do it much easier using jQuery:
$('#actions_list option:selected').remove()
$.each($('[name="alltags"] option:selected'), function( index, value ) {
$(this).remove();
});
try this instead to remove multiple selection
Removing multiple options from select based on condition:
while(SelectBox.length > 1){
if(SelectBox[SelectBox.length -1].text != "YourCondition"){
SelectBox.remove(SelectBox.length -1);
}
}