2011-08-03 74 views
7

我有一个残疾Option至极一个Select是选择一个默认的:HTML选择与禁用选项返回错误的selectedIndex在FireFox

<select name="select" size="1"> 
    <option>0</option> 
    <option selected disabled>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
</select> 

如果我能选择的,则返回1。一切还好。

但是,如果我打开弹出式窗口,用光标移到另一个Option悬停(例如,“4”)
,并通过ESC或通过点击其他地方取消它。

Select输入显示旧值1但返回时得到所选4

Example with jsfiddle

它不适用于Chrome只发生在火狐(4/5)

+2

这是什么意图?对我来说,至少禁用和选择声音,因为它们应该是相互排斥的,虽然我无法在规范中找到明确说明这一点的任何地方,但我不确定为什么选择和禁用某些内容是有道理的。你想用这个做什么? – Chris

+0

用户从框中选择一些东西。管理员可以启用或取消箱子中的物品。当用户选择并保存了一些值后,管理员禁用此项目,则用户应该将其设置看作禁用的选定项目。用户打开盒子,但没有找到他喜欢的任何其他选项,因此按下了ESC。但下一次保存会改变选定的值。 – oliholz

+3

啊。我明白你来自哪里。对我而言,感觉就像解决方案不让用户继续拥有一个已被管理员明确禁用的值,并给他们一个“不适用”的选择或者强制他们选择一个新的。尽管我已经有了一些戏,并没有比亚历山大更进一步。当你失去焦点时,Firefox会明确地启动它的更改事件,这意味着浏览器认为它已被更改。也许如果保留这个选项实际上是有效的,那么如果它也被“选择”,你不想“禁用”。这似乎可以解决你的问题 – Chris

回答

1

看来,当你离开你选择这种方式然而Firefox是寻找一个不同的显示器不改变selectedValue,因为它发现当前选中的选项被禁用,这在firefox眼中应该是不可能的。

onChange事件直到onBlur事件(即selectedValue被更改,但这不是显示更改为)时才被触发。如果我们要在onChange事件中重置我们的值,则可能会再次调用此事件。因此,通过利用onblur事件,我们可以提供以下解决方法:

onBlur="javascript:document.getElementsByName('select')[0].selectedIndex = document.getElementsByName('select')[0].selectedIndex;"

http://jsfiddle.net/aRMpt/22/

我希望我做的意义在这里。

+0

感谢您的建议,但我希望原始禁用的选项获得selectedItem,因为我用'ESC'取消了选择。 – oliholz

1

检测的esc键和复位,这里是使用jQuery的例子(和你的代码的破折号)

$('select').keyup(function(e) { 
    if (e.keyCode == 27) { 
    document.getElementsByName('select')[0].selectedIndex = 1; 
    } 
}); 

UPDATE没有jQuery的解决方案

更新2抽象出来发现事件和键码用于重新使用。

DEMO:http://wecodesign.com/demos/stackoverflow-6923135.htm

<script type="text/javascript"> 
function getEvent(event) { 
    if (window.event) return window.event; 
    return event; 
} 
function getKeycode (event) { 
    if (event.which) return event.which; 
    else return event.keyCode; 
} 
changeToDefaultListener = function(event) { 
    theEvent = getEvent(event); 
    theKeyCode = getKeycode(theEvent); 
    if(theKeyCode == 27) { 
     document.getElementsByName('select')[0].selectedIndex = 1; 
    } 
}; 
</script> 
<select name="select" size="1"> 
    <option>0</option> 
    <option selected disabled>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
</select> 

<a href="javaScript:alert(document.getElementsByName('select')[0].selectedIndex);">getSelected</a> 

<script type="text/javascript"> 
document.getElementsByName('select')[0].onkeyup=changeToDefaultListener; 
</script> 
+0

因为他没有使用jQuery尝试给出一个不在jQuery中的例子... – Bot

+0

@jostster我已经用非jQuery解决方案更新了我的示例。 –

+0

这不幸是不够的,因为错误不仅发生在单击Escape之后,而且还会发生,例如,如果你点击文档的其他部分,如果你关注另一个窗口等等。 – duri

1

下面的代码是丑陋,但它正是你想要的(我认为)。基本上,我拦截所有onChange事件,并且只有在对应的onClick事件导致更改的值时才处理它们。还注意到更改事件在点击事件之前处理。编辑:只是介绍了这不适用于铬,所以我添加了一些浏览器检测代码,以便它只在Firefox执行。

注意:如果用户已将选项框标签并使用错误键进行了更改,则当前代码将不起作用,但下面的方法也可轻松适用于处理该情况。您只需按照向上箭头或向下箭头或TAB或ENTER键的方式处理关键事件,方法与下面的处理点击方式相同,但仅在选择框具有焦点时进行。

注2:玩这个更多,这种行为是非常奇怪的。如果您退出选择,onChange事件不会被触发,但会被保存起来。如果在以后任何时候点击屏幕上的onChange事件将被触发,以查找您在转义时悬停的值,即使该值在您转义后实际上已更改。所以这变得棘手。我想你可能需要分开处理这两个案件。一个处理点击的案例,一个处理逃跑出局(帕特里克回答)。

它变得毛茸茸的,我看不到优雅的方式来编码。如何在文本框旁边的用户提示“您当前选择的选项1不再可用”。然后你可以有一个只有可用选项的选择框。

<select name="select" size="1" onChange="handleChange()" onClick="handleClick()" > 
    <option>0</option> 
    <option selected disabled>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
</select> 
<br /> 


<script> 
var initialValue = document.getElementsByName('select')[0].selectedIndex; 
var potentialChange; 
var processClick; 

function handleClick() { 

    //ignore this code if not firefox 
    if (navigator.userAgent.indexOf("Firefox") === -1) 
     return; 

    var curVal = document.getElementsByName('select')[0].selectedIndex; 
    if (!processClick) 
     return; 
    // a value change click occured, now we actually process it. 
    document.getElementsByName('select')[0].value = potentialChange; 
} 
function handleChange() { 
    // save the potential change, which will be used if a real click was detected 
    potentialChange = document.getElementsByName('select')[0].selectedIndex; 
    processClick = (potentialChange !== initialValue); 
    // undo the attempted change, in case of an escape or page click 
    // but only on firefox 
    if (navigator.userAgent.indexOf("Firefox")!=-1) 
     document.getElementsByName('select')[0].value = initialValue; 

    document.getElementsByName('select')[0].value = initialValue; 
} 
</script> 

<a href="javaScript:alert(document.getElementsByName('select')[0].selectedIndex);">getSelected</a> 
0

我必须使用的解决方法是将事件侦听器置于未选定选项的单击事件下拉列表中。在事件监听器的函数中,我设置了一个全局布尔值。

var selectChanged = false; 
$('#select option:not(:selected)').click(function() { 
    selectChanged = true; 
}); 

然后在我需要下降的设定值的向下码的区域,我查布尔:

如果布尔是真的,我就可以使用它的新价值

如果布尔值为假,我可以从Html属性(包含下拉的初始值)获取值。

var selectValue = selectChanged ? $('#select').val() : $($('#select').outerHtml()).find('option:selected').val() 

这是丑陋的我知道,但这是我能找到的唯一工作。