Reputation: 2748
I want the user to be able to select an option, and to be able to rename this when clicking a "rename" button.
I'm attempting this by nesting an input type = "text"
inside the selected option
. However, the onblur
event in the input
is not working...
It seems that select
does not allow nesting HTML elements inside option
, but it's functionality is ideal... With what structure might I implement something like this, an unordered-list?
<select id = "asdf" size = "2">
<option>asdf</option>
<option>qwerty</option>
</select>
<input type = "button" value = "rename" onclick = "rename();" />
...and here is the javascript/jQuery:
function rename() {
if ($("#asdf").length > 0) {
var selectedText = $("#asdf").find(":selected").text();
var selectedIndex = $("#asdf").find(":selected").index();
var options = document.getElementById("asdf").options;
options[selectedIndex].innerHTML =
"<input type = 'text' id = 'field' onblur = 'setField(this.value);'" +
"value = '" + selectedText + "' />";
function setField(newName) {
options[selectedIndex].innerHTML = newName;
}
}
}
Upvotes: 3
Views: 2601
Reputation: 402
I want the user to be able to select an option, and to be able to rename this when clicking a "rename" button.
Unable to find a suitable solution, I wrote the following, which I think works well, and does exactly as mentioned above. It seems a bit lengthy compared to the previous answers, but it uses no libraries.
It uses an <input type=text>
for editing the text of a given <option>
. The <input>
is sized and positioned on top of the select, and hidden when not actually in "edit" mode (when the input does not have focus).
//Javascript
var D = document;
function E(id) { return D.getElementById(id); }
var WIDGET_NAMES = [0,'Orange','Loud','Steel','Sky','Wheat','','Almond','Oak','Water','Vague'];
var $select_widget = E('ESL_select_widget');
var $widget_name = E('ESL_widget_name');
var $rename_widget = E('ESL_rename_widget');
var $delete_widget = E('ESL_delete_widget');
function Pad10(number) {
if ((number * 1) < 10) { var pad = " "; } else { var pad = ""; }
return pad + number;
}//end Pad10()
$select_widget.addEventListener("change", function() {
$widget_name.value = WIDGET_NAMES[$select_widget.value];
});
$select_widget.addEventListener("keypress", function(event) {
//Yes, both blur() & focus() are needed...
if(event.keyCode == 13) {
D.activeElement.blur();
$widget_name.style['visibility'] = "visible";
$widget_name.focus();
}
});
$widget_name.addEventListener("keypress", function(event) {
//Yes, both blur() & focus() are needed...
if(event.keyCode == 13) {
D.activeElement.blur();
$select_widget.focus();
}
});
$widget_name.addEventListener("blur", function(event) {
$widget_name.style['visibility'] = "hidden";
});
$widget_name.addEventListener("change", function() {
this.value = this.value.trim();
var current_widget = $select_widget.value;
//options count from 0, people count from 1.
var option = $select_widget.options[current_widget-1];
option.innerHTML = Pad10(current_widget) + ":: " + $widget_name.value;
WIDGET_NAMES[current_widget] = $widget_name.value;
});
$rename_widget.addEventListener("click", function() {
$widget_name.style['visibility'] = 'visible';
$widget_name.focus();
});
$delete_widget.addEventListener("click", function() {
var current_widget = $select_widget.value;
$select_widget.options[current_widget-1].innerHTML = Pad10(current_widget);
WIDGET_NAMES[current_widget] = '';
$widget_name.value = '';
});
for (var x = 1; x <= 10; x++) {
$select_widget.options[x-1].value = x;
if (WIDGET_NAMES[x] == '') { var mark = ''; } else { var mark = ":: "; }
$select_widget.options[x-1].innerHTML = Pad10(x) + mark + WIDGET_NAMES[x];
}
$widget_name.value = WIDGET_NAMES[$select_widget.value]
$select_widget.focus();
/* CSS */
* { margin: 0; padding: 0; box-sizing: border-box; }
input.ESL:focus, select.ESL:focus, button.ESL:focus { box-shadow: 0 0 3pt 1pt #006060 }
select.ESL:-moz-focusring { color: transparent; text-shadow: 0 0 0 #000; }
#ESL_container {
display: inline-block;
padding: .5rem;
border : solid 1px black;
}
#ESL_rename_container {
position: relative;
display: inline-block;
padding: 0;
margin: 0;
border: 0;
}
#ESL_select_widget {
width : 12rem;
margin : 0 0 .5rem 0;
padding: 0;
font-size : 1rem;
font-family: arial;
}
#ESL_select_widget option { text-align: left; padding-left: .2rem;}
#ESL_widget_name {
position: absolute;
top : 1px;
left : 2.1rem;
margin : 0;
padding : 1px 0 0 0;
width : 9.9rem;
height : 1.3rem;
border : solid 1px transparent;
text-align : left;
font-size : 1rem;
font-family: arial; /** set to same as select_widget. **/
visibility : hidden; /** visible during rename only **/
}
<!-- HTML -->
<div id=ESL_container>
<div id=ESL_rename_container>
<select id=ESL_select_widget class=ESL>
<option value=1 ></option>
<option value=2 ></option>
<option value=3 ></option>
<option value=4 ></option>
<option value=5 ></option>
<option value=6 ></option>
<option value=7 ></option>
<option value=8 ></option>
<option value=9 ></option>
<option value=10></option>
</select><br>
<input id=ESL_widget_name type=text class=ESL value="" tabindex=-1>
</div><br>
<button type=button id=ESL_rename_widget class=ESL>Rename Widget</button>
<button type=button id=ESL_delete_widget class=ESL>Delete Widget</button>
</div>
Upvotes: 0
Reputation: 1461
You can loop over the options:
for(var i = 0, l = select.options.length; i < l; i++)
{
var option = select.options[i];
var obj = {};
if(option.value == "...")
{
option.innerHTML = "...";
obj[option.value] = option.innerHTML;
}
}
return obj;
I would put that in a function and pass a value you search and the replacement, or a map. Something like:
setOptionText(select, 'value', 'text');
// or
setOptionText(select, {'value': 'text', 'value': 'text', ...});
Reference: HTMLSelectElement
Upvotes: 1
Reputation: 2748
Ok, I got it --
It turns out I was able to implement this with a ul
structure, and some rather nasty jQuery.
#list {
list-style-type: none;
}
.highlighted {
background-color: #FFFF00;
}
HTML:
<ul id = "list">
<li>asdf</li>
<li>qwerty</li>
<ul>
<input type = "button" value = "rename item" onclick = "renameSearch();" />
jQuery/javascript:
$("#list").on("click focus", "li", function() {
$(this)
.addClass("highlighted")
.siblings().removeClass("highlighted");
});
function renameSearch() {
$("#list li").each(function(index) {
if ($(this).hasClass("highlighted")) {
//alert(index + ": " + $(this).text());
$(this).html("<input type = 'text' id = 'renameField' value = '" + $(this).text() + "' />");
$("#renameField").focus();
$("#renameField").select();
$("#list li").on("focusout", "#renameField", function() {
//alert($(this).val());
$(this).parent().text($(this).val());
});
}
});
} // end of function
jsFiddle -- http://jsfiddle.net/icampbell2/59YDF/
Upvotes: 0