Change dropdown selected text without changing the option text - javascript

I have an indented dropdownlist, where I have some root options and their children, like below:
Food
Market
Restaurants
Grossery
Clothes
Home
TV
If I select Market, for example, the text in the dropdownlist still indented. Then I did a jQuery function to remove the spaces before the text. It looks like this:
$(function () {
$("select").change(function () {
var str = jQuery.trim($("select option:selected").text());
$("select option:selected").text(str);
})
});
It works. But, if I try to select other option after selected Market, for example, The list looks like this:
Food
Market
Restaurants
Grossery
Clothes
Home
TV
Market lost its indentation. I would like a way to remove the spaces but only in the selected text shown in the dropdown, but not in the option.
What should I do?

Bit late to the party here...
First of all I've amended your HTML to include a class on each option element to indicate the level to which it should be indented.
<select class="select">
<option value="1" class="level-0">Item 1</option>
<option value="2" class="level-1">Item 1.1</option>
<option value="3" class="level-2">Item 1.1.1</option>
<option value="4" class="level-1">Item 1.2</option>
</select>
I have also written the jQuery to add the required indentation on load, using a string of non-breaking spaces. While this is hardly an elegant solution, it's the only one that will work across all browsers - as you've obviously discovered, OPTION elements are a land CSS forgot. It also includes the logic for the change event to remove/add the padding to the selected items.
While it's not the prettiest code, and I'm sure there are a lot of performance improvements which could be made (hey, it's late here and this was a brain dump as I was intrigued by the question), it works.
var levelClassPrefix = "level-";
var indentationString = " ";
$(".select").each(function() {
padOptions(this);
});
function padOptions(elem) {
$("OPTION", elem).each(function() {
var level = $(this).attr("class").replace(levelClassPrefix, "");
var currentText = $(this).html();
var regex = new RegExp(indentationString , "g");
$(this).html(padText(currentText.replace(regex, ""), level))
});
}
function padText(value, level) {
var output = "";
for (var i = 1; i <= level; i++) {
output = output + indentationString;
}
return output + value;
}
$(".select").change(function() {
padOptions(this);
var selectedOption = $("option:selected", this);
var currentText = selectedOption .html();
var regex = new RegExp(indentationString , "g");
selectedOption.text(currentText.replace(regex, ""));
});
Here is a fiddle to prove the theory

Why not style the indivudual options instead?
Something along these lines:
HTML:
<select>
<option>Food</option>
<option class='sub'>Market</option>
<option class='sub'>Restaurants</option>
<option class='sub'>Grossery</option>
<option>Clothes</option>
<option>Home</option>
<option class='sub'>TV</option>
</select>
CSS:
option.sub { text-indent: 2em; }

Why trim the string? I would add a css class similar to this
select .level0 {}
select.level1 {
text-indent: -1.5em; /* you have to calculate your indentation value */
}
select.level2 {
text-indent: -3em; /* you have to calculate your indentation value */
}
Forge html accordingly
<select>
<option class='level0'>Food</option>
<option class='level1'>Market</option>
<option class='level1'>Restaurants</option>
<option class='level1'>Grossery</option>
<option class='level0'>Clothes</option>
<option class='level0'>Home</option>
<option class='level1'>TV</option>
</select>
and apply the class accordingly. Maybe, I don't know jquery, you have to
$(function () {
$("select").change(function () {
var theclass = $("select option:selected").class();
$("select option:selected").set(class, theClass); // <-- is this jquery??
})
});

Related

Javascript / JQuery - Sorting by Multiple Classes

having a bit of trouble here, any help would be greatly appreciated...
I am trying to hide and show a bunch of list items based on several classes assigned to them.
In my JS Fiddle Example I have several items with classes relating to their description.
I have managed to hide and show these, but complex selections are not possible...
example: If I wanted to only see fabrics that are "premium", "blue" and "linen".
Something like this (that works lol) is what I am after...
$('.sel_range').click(function() {
range = document.getElementById("range").value;
if ($('.fabric_option').hasClass(range)) {
$('.' + range).fadeIn('fast', function() {
!$('.fabric_option').hasClass(range).fadeOut("fast");
});
}
});
Something like this should work
var selects = $('#range, #fabric, #colour');
selects.on('change', function() {
var el = selects.map(function(i, item) {
return item.value.indexOf('all_') === 0 ? '' : '.' + item.value;
}).get().filter(function(x) {
return x.length;
}).join('');
$('#fabric_options li').show().not(s?s:'*').hide();
});
FIDDLE
It starts with showing all the list items, then joins the values together to create a clas selector, leaving out the class if all_something is selected etc. and then hides everything that doesn't match, and if nothing is selected excludes everything.
I think it can be solved like this:
var range, fabric, colour;
var updateShown = function() {
$('li').show()
if (range) {
$('li:not(.' + range + ')').hide();
}
if (fabric) {
$('li:not(.' + fabric + ')').hide();
}
if (colour) {
$('li:not(.' + colour + ')').hide();
}
}
// Range
$('#range').change(function() {
range = $(this).val();
updateShown();
});
// Fabric
$('#fabric').change(function() {
fabric = $(this).val();
updateShown();
});
// Colour
$('#colour').change(function() {
colour = $(this).val();
updateShown();
});
With value="" of each select first option
<select id="range">
<option class="sel_range" value="">All Ranges</option>
<option class="sel_range" value="luxury">Luxury</option>
<option class="sel_range" value="premium">Premium</option>
<option class="sel_range" value="base">Base</option>
</select>
<select id="fabric">
<option class="sel_fabric" value="">All Fabrics</option>
<option class="sel_fabric" value="leather">Leather</option>
<option class="sel_fabric" value="linen">Linen</option>
<option class="sel_fabric" value="cotton">Cotton</option>
</select>
<select id="colour">
<option class="sel_colour" value="">All Colours</option>
<option class="sel_colour" value="red">Red</option>
<option class="sel_colour" value="blue">Blue</option>
<option class="sel_colour" value="green">Green</option>
</select>
jsFiddle demo
what about this?
$('#range').on('change',function () {
range = $("#range").val();
$('li').each(function(){
if(!$(this).hasClass(range)){
$(this).hide();
}else{
$(this).show();
}
});
});
// just for range, rest in fiddle
http://jsfiddle.net/J3EZX/6/
If you're using jQuery, just string them together with a . and no space, e.g.:
$(".linen.red.base").text("Help! I'm being replaced!");

Need to use a Function on Multiple Div Box onClick

This is only for IE.
I have a function noted below it copies the content of the div when the div is clicked. It works fine. It used the getElementById.
I have 19 items I would like to use this for ... 'option1 - option19.
Instead of having to create 19 variables is there any other way of doing this...
I am totally a noob to this stuff....
function CopyToClip() {
var Cdiv = document.getElementById('option1');
Cdiv.contentEditable = 'true';
var controlRange;
if (document.body.createControlRange) {
controlRange = document.body.createControlRange();
controlRange.addElement(Cdiv);
controlRange.execCommand('Copy');
}
div.contentEditable = 'false';
}
I should mention that these id's are for Divs.
These divs are a show / hide based on a drop down selection.
The drop down has its on function to show the selected div.
The function is:
$(window).load(function () {
$(document).ready(function () {
$('.block').hide();
$('#option1').show();
$('#selectField').change(function () {
$('.block').hide();
$('#' + $(this).val()).fadeIn();
});
});
});
My HTML is:
<div class="col_1">
<h1>communication:</h1>
<div class="box">
<select id="selectField" style="padding-left: 20px;width:175px">
<option value="option1">Device Shipped to ASC</option>
<option value="option2">Device Received at ASC</option>
<option value="option3">ASC Shipped Device to Store</option>
<option value="option4">Device Pick-up Follow-up</option>
<option value="option5">Device Pick-up Final Reminder</option>
<option value="option6">Impress Phase Direct Feedback</option>
<option value="option7">Abandon Notice</option>
<option value="option8">Mailer Shipped to Client</option>
<option value="option9">Mailer Received by Client</option>
<option value="option10">Mailer Pick-up Notice</option>
<option value="option11">Mailer Final Pick-up Notice</option>
<option value="option12">Mailer Failed to Pick-up</option>
<option value="option13">Mailer Return Defective Device Notice</option>
<option value="option14">Mailer Final Return Defective Device Notice</option>
<option value="option15">Mailer Failed to Return Defective Device</option>
<option value="option16">Mailer Defective Device Received at ASC</option>
<option value="option17">Mailer Charges to Customer</option>
<option value="option18">Mailer Process Confirmation</option>
<option value="option19">Quote Un-replied</option>
</select>
<div id="option2" class="block" style="background-color:white" onClick="javascript:CopyToClip()"> blah </div>
Had I have 19 of this divs.
I don't know if this helps ... Sorry I am in way over my head on this one.
I had to hack things about a little, and your clipboard code will not work on all browsers:
JSFiddle: http://jsfiddle.net/THU5f/2/
function CopyToClip($div) {
var div = $div[0];
div.contentEditable = 'true';
var controlRange;
if (document.body.createControlRange) {
controlRange = document.body.createControlRange();
controlRange.addElement(div);
controlRange.execCommand('Copy');
alert("Copied: " + div.html());
}
div.contentEditable = 'false';
}
$(function () {
// Hide copy button
$('#copy').hide();
// Hide all content divs
$('.content').hide();
$('#selectField').change(function () {
// Show the copy button
$('#copy').show();
// Hide all content divs
$(".content").fadeOut();
// Show the select content div
$('#' + $(this).val()).fadeIn();
});
$('#copy').click(function(){
// Get the div the current selection points to
var $div = $('#' + $('#selectField').val());
// Copy the div to the clipboard
CopyToClip($div);
});
});
I added comments throughout. Hope this helps.
I've been working on similar thing lately. I was supposed to show/hide DIV depending on the selection. The HTML code is generated and there can be 1 to 8 selects generated, with each dependent div shown under the its select. I came up with this solution.
"Second half" of the code basically finds all select elements with given ID, loops trough them and depending on the selected value, shows or hides the div. I had to use this selectors: $('*[id*=delegate_form]') and $('*[id*=show_hidden_delegate'), because if I used $("#delegate_form") the code only affected the element with index 0. I have no idea why.
First half of the code handles the same situation on the read-only page.

Javascript/jQuery: ensuring unique option added to pulldown

I have an HTML pulldown menu along with a text element that allows users to add new options to the menu. I'd like to make sure that every option that is added is unique. The following two lines were the first option I thought of that worked (option value = innHTML for all of the options). I'm wondering if there's a more elegant solution to this -- the second line just seems clunky. It also doesn't handle spaces in the new_name string.
var new_name = document.getElementById("preset_name").value
var unique_name = $("option[value="+new_name+"]").length === 0 ? true : false
Do you need something like this?
HTML:
<select id="myselect">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<input id="newoption" type="text" />
<button id="check">Check</button>
jQuery:
$(document).ready(function() {
$("button#check").click(function() {
var newOpt = $("input#newoption").val();
$("#myselect option").each(function(){
var text = $(this).val();
if(newOpt.length>0 && text.indexOf(newOpt)!=-1){
console.log("already present!");
}
});
});
});
jsfiddle
Combining the two comments on the question, you could streamline down to 1 line:
var unique_name = $("option[value="+$("#preset_name").val()+"]").length === 0;
You don't need the ternary, as the === results in a true or false value. Unless you need the test value again, you don't even need to store it in a variable - you can just retrieve it with jQuery.

How to update html SELECT options with javascript or jquery, using values from other SELECT's (within eric hynds's multiselect widget)

I'm using Eric Hynds's jQuery multiselect widget to display a list of employees in several different sections on the same screen. I have several different multiselects on the same page, some of which have the same employees.
If a user selects (or unselects) an employee in one multiselect, I need to update the others to reflect the same choices. I have 2 'optgroups' to consider as well, if possible, but those can be ignored for this purpose, unless it's relatively easy to handle.
The options could be refreshed with javascript or jquery, independent of the multiselect widget, and then the .refresh method could be called to update the widget. So, the solution to this may or may not use code from the widget to do the updating of the options.
Here are examples of two SELECTs and their options. Brian Jones appears in both. If Brian Jones is selected in the first example, how can I dynamically select him in the second example (and if possible, move him to the 'Assigned Employees' group)? Same goes for if he is un-selected.
<select id="empSelection_01" name="employee_01" multiple="multiple">
<optgroup label="Unassigned Employees">
<option value="42954">Smith, Joe</option>
<option value="30357">Jones, Brian</option>
</optgroup>
<optgroup label="Assigned Employees">
<option value="42900">Brown, Laura</option>
<option value="30399">Evans, Jessica</option>
</optgroup>
</select>
<select id="empSelection_02" name="employee_02" multiple="multiple">
<optgroup label="Unassigned Employees">
<option value="42954">Doe, Jane</option>
<option value="30357">Jones, Brian</option>
</optgroup>
<optgroup label="Assigned Employees">
<option value="42900">Hix, Carolyn</option>
<option value="30399">Evans, Jessica</option>
</optgroup>
</select>
Try like this fiddle
$('#empSelection_01').multiselect({click:function(e){
var isChecked = $(e.currentTarget).attr("checked")=="checked";
var labelFrom = isChecked ? 'Unassigned Employees' : 'Assigned Employees';
var labelTo = !isChecked ? 'Unassigned Employees' : 'Assigned Employees';
var el = $('#empSelection_02').children('[label="' + labelFrom + '"]').children('[value="' + e.currentTarget.value + '"]');
el.remove();
$('#empSelection_02').children('[label="' + labelTo + '"]').append(el);
if (isChecked) {
el.attr('selected', 'selected');
} else {
el.removeAttr('selected');
}
$('#empSelection_02').multiselect('refresh');
}});
It's example how you can manipulate with this plugin, but it's not enough to solve you problem. You neeed some logic, to take options into consideration, and indicate in which group options must be located, especially if many-to-many connections is possible.
I ended up using this JavaScript, which receives the ID of the SELECT that was just changed, and then uses values within that SELECT to process all other SELECT's on the screen:
function refreshEmps(currID){
var sel = document.getElementById(currID);
var opt = sel.options;
var checkedVals = new Array();
// save checked values ***************************
for (i=0; i<opt.length; i++){
if (opt[i].selected==true) {
checkedVals[checkedVals.length]=opt[i].value;
}
}
//update remaining SELECT's ***************************
var ddCounter = 0; //
while(document.getElementById("employeeDD_" + ddCounter)!=null) {
var sel2 = document.getElementById("employeeDD_" + ddCounter);
if (currID!=sel2.id) {
var opt2 = sel2.options;
for (i=0; i<opt2.length; i++){
for (j=0; j<checkedVals.length; j++) {
if(opt2[i].value==checkedVals[j]) {
opt2[i].disabled=true;
opt2[i].style.color = 'red';
}
}//end for
}
}//end if
ddCounter++;
}//end WHILE
$("select").multiselect('refresh');
}

How to get the value of a multiple option dropdown?

Say I have this dropdown:
<select name="color" multiple="multiple">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
So basically more than 1 color can be selected. What I'd like is that if a user selects red, and then clicks green, i'd like a function to be called each time which pops up a message box saying the color which was most recently clicked.
I've tried this:
<option value="red" onclick="alert('red');">Red</option>
<option value="green" onclick="alert('green');">Green</option>
<option value="blue" onclick="alert('blue');">Blue</option>
This works in firefox and chrome, but not in IE.
Any ideas?
$("select[name='color']").change(function() {
// multipleValues will be an array
var multipleValues = $(this).val() || [];
// Alert the list of values
alert(multipleValues[multipleValues.length - 1]);
});
Here's another examples: http://api.jquery.com/val/
The following code should do what I think you're after. Each time an item is selected, it compares the current list of selections against the previous list, and works out which items have changed:
<html>
<head>
<script type="text/javascript">
function getselected(selectobject) {
var results = {};
for (var i=0; i<selectobject.options.length; i++) {
var option = selectobject.options[i];
var value = option.value;
results[value] = option.selected;
}
return results;
}
var currentselect = {};
function change () {
var selectobject = document.getElementById("colorchooser");
var newselect = getselected(selectobject);
for (var k in newselect) {
if (currentselect[k] != newselect[k]) {
if (newselect[k]) {
alert("Option " + k + " selected");
} else {
alert("Option " + k + " deselected");
}
}
}
currentselect = newselect;
}
</script>
</head>
<body>
<select id="colorchooser"
name="color"
multiple="multiple"
onchange='javascript:change();'
>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
</body>
</html>
It should work just as well in Internet Explorer as Firefox et al.
Since you using jQuery,I suggest you to take a look at this superb plugins. This plugins will transform a multiple select dropdown into a checkbox list, so user can select multiple values with easy.
To get the values, I suggest you use fieldValue methods from jQuery form plugins. It's a robust way to get value from any type of form element. Beside, you can use this plugins to submit your form via AJAX easily.
This will alert only the last (most recent) selected value. Calling $(this).val() using the select's change handler will return an array of all your selected values:
$(document).ready(function() {
$("select[name=color] option").click(function() {
alert($(this).val());
});
});
I am not sure what you exactly want. This will always alert the last selected color:
$(function(){
var selected = Array();
$('select[name=color] option').click(function() {
if($(this).is(':selected')) {
selected.push($(this).val());
}
else {
for(var i = 0; i < selected.length;i++) {
if(selected[i] == $(this).val()) {
selected = selected.splice(i,1);
}
}
}
alert(selected[selected.length -1])
});
});
The array is used to maintain the history of selected colors.
For the last clicked color, it is simpler:
$(function(){
$('select[name=color] option').click(function() {
alert($(this).val());
});
});
This is so complicated to accomplish that I used a simpler option of listing the items with a checkbox next to them and a select/unselect all button. That works much better and is also supported by IE. Thanks to everyone for their answers.

Categories