3

I've got a form that uses jqTransform to replace the standard select boxes and radio buttons. It all works fine and dandy, except one thing that annoys me:

Since it replaces the select box with a list of links, when you type a letter to scroll it doesn't do anything. For instance, you click to open up the select, then type an S. It should scroll to the first S in the list, but nothing happens. Is there a way to re-instate this functionality? Below is the jqTransform code for the select box. I don't see a handler for this type of thing:

/***************************
  Select 
 ***************************/   
$.fn.jqTransSelect = function(){
    return this.each(function(index){
        var $select = $(this);

        if($select.hasClass('jqTransformHidden')) {return;}
        if($select.attr('multiple')) {return;}

        var oLabel  =  jqTransformGetLabel($select);
        /* First thing we do is Wrap it */
        var $wrapper = $select
            .addClass('jqTransformHidden')
            .wrap('<div class="jqTransformSelectWrapper"></div>')
            .parent()
            .css({zIndex: 10-index})
        ;

        /* Now add the html for the select */
        $wrapper.prepend('<div><span></span><a href="#" class="jqTransformSelectOpen"></a></div><ul></ul>');
        var $ul = $('ul', $wrapper).css('width',$select.width()).hide();
        /* Now we add the options */
        $('option', this).each(function(i){
            var oLi = $('<li><a href="#" index="'+ i +'">'+ $(this).html() +'</a></li>');
            $ul.append(oLi);
        });

        /* Add click handler to the a */
        $ul.find('a').click(function(){
                $('a.selected', $wrapper).removeClass('selected');
                $(this).addClass('selected');   
                /* Fire the onchange event */
                if ($select[0].selectedIndex != $(this).attr('index') && $select[0].onchange) { $select[0].selectedIndex = $(this).attr('index'); $select[0].onchange(); }
                $select[0].selectedIndex = $(this).attr('index');
                $('span:eq(0)', $wrapper).html($(this).html());
                $ul.hide();
                return false;
        });
        /* Set the default */
        $('a:eq('+ this.selectedIndex +')', $ul).click();
        $('span:first', $wrapper).click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
        oLabel && oLabel.click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
        this.oLabel = oLabel;

        /* Apply the click handler to the Open */
        var oLinkOpen = $('a.jqTransformSelectOpen', $wrapper)
            .click(function(){
                //Check if box is already open to still allow toggle, but close all other selects
                if( $ul.css('display') == 'none' ) {jqTransformHideSelect();} 
                if($select.attr('disabled')){return false;}

                $ul.slideToggle('fast', function(){                 
                    var offSet = ($('a.selected', $ul).offset().top - $ul.offset().top);
                    $ul.animate({scrollTop: offSet});
                });
                return false;
            })
        ;

        // Set the new width
        var iSelectWidth = $select.outerWidth();
        var oSpan = $('span:first',$wrapper);
        var newWidth = (iSelectWidth > oSpan.innerWidth())?iSelectWidth+oLinkOpen.outerWidth():$wrapper.width();
        $wrapper.css('width',newWidth);
        $ul.css('width',newWidth-2);
        oSpan.css({width:iSelectWidth});

                     $ul.css({height:'420px','overflow':'hidden'});

        // Calculate the height if necessary, less elements that the default height
        //show the ul to calculate the block, if ul is not displayed li height value is 0
        $ul.css({display:'block',visibility:'hidden'});
        var iSelectHeight = ($('li',$ul).length)*($('li:first',$ul).height());//+1 else bug ff
        (iSelectHeight < $ul.height()) && $ul.css({height:iSelectHeight,'overflow':'hidden'});//hidden else bug with ff
        $ul.css({display:'none',visibility:'visible'});

    });
};

Here is what we tried to do to implement this:

var oLinkOpen = $('a.jqTransformSelectOpen', $wrapper)
   .keypress(function (e) {
       $.each(myArray, function (i, l) {
           var sc = l.substr(0, 1).toLowerCase();
           var kc = String.fromCharCode(e.which);
           if (sc == kc) {
               $select[0].selectedIndex = i;
               $('span:eq(0)', $wrapper).html(l);
               $ul.hide();
               return false;
            }
});
});
  • The jqTransform initialization along with a sample of the HTML would be handy. At a guess, I would say your event handler is being lost; in this case, delegating an ancestor element as a listener will resolve this. But without a sample or looking at jqTransform, I don't know if that's something that's down to your own code or functionality within jqTransform. – Greg Pettit Dec 14 '11 at 17:11
  • I added the jqTransform code for the select box to the original question. My HTML is as simple as it gets, standard – user1098316 Dec 14 '11 at 17:19
  • I'm guessing I just need to add a keypress event to the select that will search the list and change the index, but I'm an absolute novice in jQuery and have no idea how to do it :) – user1098316 Dec 14 '11 at 17:31

3 Answers3

0

Add the following code at the end of return this.each(function(index){ ... }); that is inside of $.fn.jqTransSelect function.

Also you have to install the scrollTo jquery plugin.

CODE:

var newChar;
$(document).bind("keydown", function (e) {
    var char = String.fromCharCode(e.which);
    var code = e.keyCode || e.which;
    var charFound;

if( $ul.css('display') != 'none' ){
    if (newChar != char){
        newChar = char;

            $ul.find('a').each(function(){
                // Find first occurence of li that starts with letter typed
                if ($(this).text().substr(0,1).toUpperCase() == char && $(this).text() != "Choose"){
                    charFound = true;

                    $('a.selected', $wrapper).removeClass('selected');
                    $(this).addClass('selected');
                    $select[0].selectedIndex = $(this).attr('index');
                    $($select[0]).trigger('change');
                    $that = $(this);

                    return false;
                }
            });

            if (charFound == true){
                // Scroll to selected value
                $ul.scrollTo($('a.selected', $ul), 400);
            }
        }

        //If Enter has been pressed, select the value
        if(code == 13) { 
            $('span:eq(0)', $wrapper).html($that.html());
            $ul.hide();
            return false;
        }
    }
});
Georgia
  • 1
  • 1
0

Oh dang. I was missing the big picture without the code. Now I see what's going on... yeah, there's no "reinstating" the functionality since the new list of links is not actually a select box anymore. If jqTransform doesn't include a scrollable option by default I think you'll have to implement one.

If you look at their demo page, their "plain" select box works as expected (although it's hard to notice since all options start with "O", it WILL jump to the first "Option") and their styled select box does not.

Without looking deeper at the code, I suspect that means that a keypress capture is not implemented in the plug-in itself.

I'm afraid this isn't the "answer" you were probably hoping for. With any luck someone who has done this sort of thing before will hear your plea. ;-)

Greg Pettit
  • 10,749
  • 5
  • 53
  • 72
  • Aye. I should be asking "How to implement this in jqtransform?" It seems strange that there's not much on this online that I can find, considering jqtransform seems pretty popular. My friend tried to fix, I added the code above. – user1098316 Dec 14 '11 at 22:08
0

solution for jqTransform select keypress work link visit http://www.techapparatus.com/jqtransform-select-problem-with-keyboard-type-solution