在Firefox中设置选择值

时间:2014-02-03 15:38:26

标签: javascript firefox prototypejs

我正在为遗留站点创建输入替换,这意味着我被困在使用prototype.js(1.7.1.0)

除了Firefox(26.0 OSX)

之外,我的选择输入可以正常运行

在FF中,选择选项正确设置了'selected'属性,但是尝试读取元素值或selectedIndex总是返回初始值,这是必不可少的,因为我无法控制某些第三方代码。 / p>

当我在测试原始输入的可见性是否相关时(事实并非如此),我发现可以让替换工作正常,但前提是您首先使用原始输入。此外,如果您先使用替换,原始输入将不起作用。

我在这里有一个测试用例: http://jsfiddle.net/DisasterMan/gUam3/4/

使用输入替换时,将读取值和索引,并且(应该)显示在下面。

我已经尝试拆分现有代码以查看它是如何完成的,但是没有找到可用的原型选择替换。我打算尝试挑选一个正在运行的jQuery版本,例如http://groenroos.github.io/minimalect/,看看我是否可以解决它是如何完成的,但是非常感谢任何帮助!

<!-- language: javascript -->
// To hell with IEh8! Not worth the time implementing the drop-down
if( ! $$( 'html' )[0].hasClassName( 'ltie9' ) )
{

    //Replace select inputs
    $$( 'select' ).each( function( select )
    {

                                                                    // All other checkboxs that share this name (i.e. this group)
        var allOptions                     = $$( 'select[name="' + select.name + '"] option' ),
                                                                    // id attribute of the input
                replacementId              = 'replace-' + select.name,
                                                                    // CSS styled select replacement
                replacement                = '<div id="' + replacementId + '" data-name="' + select.name + '" class="select-replacement"><span class="option-label"></span><span class="arrow"><span class="head"></span></span></div>',
                                                                    // Replacemet options container id
                replacementOptionsId       = replacementId + '-options',
                                                                    // Replacement options container
                replacementOptionsHtml     = '<div id="' + replacementOptionsId + '" class="select-replacement-options">',
                replacementOptionsElements,
                selectedLabel              = false;

        // Build replacement options elements
        allOptions.each( function ( option, index )
        {
            var selected = false,
                    label    = option.innerHTML;

            if( option.getAttribute( 'selected' ) !== null )
            {
                selected      = true;
                selectedLabel = label;
            }

            replacementOptionsHtml += '<span data-value="' + option.value + '" data-selected="' + selected + '" data-parent="' + replacementId + '" data-index="' + index + '">' + label + '</span>';
        } );

        replacementOptionsHtml += '</div>';


        // Insert replacement
        new Insertion.After( select, replacement );

        replacementElement       = $( replacementId );
        replacementSelectedLabel = replacementElement.down( '.option-label' );

        new Insertion.Bottom( replacementElement, replacementOptionsHtml );

        if( selectedLabel )
        {
            Element.update( replacementSelectedLabel, selectedLabel );
        }

        replacementOptions = $( replacementOptionsId );

        replacementOptionsElements = $$( '#' + replacementOptionsId + ' span' );

        // Hide input
        //select.hide( );
        replacementOptions.hide( );

        // Add click event listener to this select input
        replacementElement.observe( 'click', function ( event )
        {

            var eventSrc = getEventSrc( this, event );

            replacementOptions   = $( eventSrc.id + '-options' );
            replacementOptions.show( );

        } );

        // Options select handler
        replacementOptionsElements.each( function ( option ){

            option.observe( 'click', function ( event ){

                event.stopPropagation( );

                var option                       = getEventSrc( this, event ),
                        selectedValue            = option.getAttribute( 'data-value' ),
                        selectedIndex            = option.getAttribute( 'data-index' ),
                        replacementId            = option.getAttribute( 'data-parent' ),
                        replacementElement       = $( replacementId ),
                        replacementOptions       = $( replacementId + '-options' ),
                        previouslySelected       = replacementElement.down( '[data-selected="true"]' ),
                        replacementSelectedLabel = replacementElement.down( '.option-label' ),
                        selectName               = replacementElement.getAttribute( 'data-name' ),
                        select                   = $$( 'select[name="' + selectName + '"]' )[0],
                        selectedOption           = select.down( 'option[value="' + selectedValue + '"]' ),
                        currentSelectedOption    = select.down( 'option[selected]' );

                triggerEvent( select, 'click')
                // Hide replacement options
                replacementOptions.hide( );

                // Set visibly selected option on replacement select input
                Element.update( replacementSelectedLabel, option.innerHTML );

                // Unset previous selected option
                currentSelectedOption.removeAttribute( 'selected' );

                // Unset previous selected replacement option
                if( previouslySelected !== undefined )
                {
                    previouslySelected.removeAttribute( 'data-selected' );
                }

                // Set selected option
                selectedOption.setAttribute( 'selected', 'selected' );
                selectedOption.selected = true;

                // Set new selected replacement option attribute
                option.setAttribute( 'data-selected', 'true' );

                triggerEvent( select, 'change', function ( )
                {
                    triggerEvent( select, 'blur' );
                } );

                var dateSegment  = select.name.substring( select.name.indexOf( '_' ) + 1 ).toLowerCase(),
                    valDisplay   = $$( '.' + dateSegment + '-value' )[0],
                    indexDisplay = $$( '.' + dateSegment + '-index' )[0];
                valDisplay.update( select.value );
                indexDisplay.update( select.selectedIndex );
console.log(select.value);
console.log(select.selectedIndex);

            } );
        } );

    } );

}


triggerEvent = function( element, eventName, callback )
{
    if (document.createEvent)
    {
        var evt = document.createEvent( 'HTMLEvents' );
        evt.initEvent( eventName, true, true );

        if( callback && typeof( callback ) === "function" )
        {
            callback();
        }
        return element.dispatchEvent( evt );
    }

    if ( element.fireEvent ){
        return element.fireEvent( 'on' + eventName );
    }
}


getEventSrc = function ( object, event )
{
    if ( object === window )
    {
        return event.srcElement;
    }
    else
    {
        return object;
    }
}

2 个答案:

答案 0 :(得分:0)

尝试使用setValue()方法。 http://api.prototypejs.org/dom/Form/Element/prototype/setValue/

在第90-92行的jsfiddle中添加此行

select.setValue(selectedValue);

我可以告诉select是您的下拉元素,而selectedValue是您要设置为下拉元素的新值。

使用setValue()清除所有浏览器中尝试设置下拉值的所有混乱。在JS的下方,我看到你试图设置属性 - 这应该处理它。

此外,如果你想要干净的下拉替换,我喜欢使用Chosen Drop Downs http://harvesthq.github.io/chosen/index.proto.html

答案 1 :(得分:0)

初始化选择替换时,将selectedIndex设置为-1'激活'元素,然后以编程方式选择它。

L.22

select['selectedIndex'] = -1;

我通过纯粹的反复试验找到了这个,所以我没有正确的解释,但我会试着简要解释一下我是如何做到的:

似乎如果将select设置为没有value属性的选项,Firefox会使用javascript设置该值。

从你点击选择输入时的行为,我有一种预感(显然是胡说八道!)Firefox不知何故想要激活该元素 - 如果我可以模仿该点击,并将其唤醒,事情会没事的,但我不知道怎么做。

我尝试了逆向工程jQuery插件,该插件实际上是为了查看是否有跨浏览器设置值的方式,但没有任何帮助。

在弄清楚值时,我注意到替换工作的关键似乎与select的CURRENT值有关。原始选择默认为没有值字符串的选项(输入由第三方生成 - 我甚至无法控制ID和类)一旦select有一个值,更改它与替换工作正常。

将索引设置为0不起作用,可能是因为第一个标记没有值。设置为&gt; 0工作,但默认情况下设置值是不可接受的,所以我认为我会给-1一个去,相当于取消选择所有值,并且...其余的是历史。虽然不是好的类型。只是在逆行代码的泥泞无人之地漫长的跋涉中获得了一个小小的胜利。老实说,如果你看到其中的一部分,你会为作者的母亲哭泣的泪水。

工作测试版:

http://jsfiddle.net/DisasterMan/gUam3/8/