XETOWN

질문/답변

웹에 관련된 질문과 답변을 나눌 수 있습니다.
질문/답변
2016.09.29 10:08

js의 파이어폭스에서 이상동작

조회 수 57 댓글 8

회원검색을 하는 위젯이 있습니다. 검색어를 넣으면 매칭이 되는 회원을 자동으로 나열해 주는 위젯입니다. 회원의 닉네임을 찾거나 할때 편리합니다.

 

그런데 파이어폭스에서는 동작이 좀 상이해서 사용하기 어려운 점이 있어서요.

 

증상 : 검색어를 입력하고 스페이스로 한칸을 띄우고 다시 백스페이스로 공백을 줄여줘야 동작을 합니다.

 

다른 브라우저는 이증상이 없이 그냥 검색어 입력한 후 따로 스페이스로 한칸을 띄웠다가 다시 공백을 없애주는 동작없이 검색어 입력으로 매칭되는 회원이 출력됩니다.

 

js 내용입니다.

 

 

jQuery(function($) {
    /**
     * 필요 전역변수 선언
     */
    var search_target;
    var disp_info;
    var delay_time;
    var sort_order;
    var sort_list;
    var list_count;
    var page = 1;
    var t;
    var length = 0;
    var cur_select = -1;
    var dispMemberInfo = "";
    var width = 0;
    
    /**
     * 문서 로드시 실행되는 메소드들.
     */
    $(document).ready(function() {
        // 전역변수에 값 집어넣고 hidden input 제거
        search_target = $('.user_finder_box .search_target').val();
        disp_info = $('.user_finder_box .disp_info').val();
        delay_time = parseInt($('.user_finder_box .delay_time').val()) * 1000;
        sort_order = $('.user_finder_box .sort_order').val();
        sort_list = $('.user_finder_box .sort_list').val();
        list_count = parseInt($('.user_finder_box .list_count').val());
        page = 1;
        dispMemberInfo = $('.user_finder_box .dispMemberInfo').val();
        dispMemberInfo = dispMemberInfo.replace('z', '');
        width = parseInt($('.user_finder_box .width').val());
        $('.user_finder_box .search_target').remove();
        $('.user_finder_box .disp_info').remove();
        $('.user_finder_box .delay_time').remove();
        $('.user_finder_box .sort_order').remove();
        $('.user_finder_box .sort_list').remove();
        $('.user_finder_box .list_count').remove();
        $('.user_finder_box .dispMemberInfo').remove();
        $('.user_finder_box .width').remove();
        search_target = search_target.split(',');
        disp_info = disp_info.split(',');
        length = 0;
        cur_select = -1;
        $('.user_finder_box .inputbox').val($('.user_finder_box .inputbox').attr('default'));
        
        // 가로 길이 정리
        $('.user_finder_box').css('width', width + 'px');
        $('.user_finder_box .inputbox').css('width', width - 5 + 'px');
        $('.user_finder_box .btnClose').css('left', width - 22 + 'px');
    });
    
    $('.user_finder_box .inputbox').keyup(function(event) {
        page = 1;
        // 화살표 아래, 위 키가 눌러졌다면 선택해준다.
        // 아래 키
        if (event.keyCode == 40) {
            console.log('length = ' + length);
            console.log('cur_select = ' + cur_select);
            // 없을 때 무시, 마지막 항목이 이미 선택되었을 때 무시
            if (length < 1)
                return false;
            if (length == ++cur_select) {
                cur_select--;
                return false;
            }
            lighten_member_info($('.user_finder_box .user_info:eq(' + (cur_select - 1) + ')'));
            darken_member_info($('.user_finder_box .user_info:eq(' + cur_select + ')'));
            return false;
        }
        // 위 키
        else if (event.keyCode == 38) {
            // 하나짜리일 때 무시, 첫 번째 항목이 이미 선택되었을 때 무시
            if (length == 0)
                return false;
            if (cur_select == 0) {
                return false;
            }
            cur_select--;
            lighten_member_info($('.user_finder_box .user_info:eq(' + (cur_select + 1) + ')'));
            darken_member_info($('.user_finder_box .user_info:eq(' + cur_select + ')'));
            return false;
        }
        // 엔터키 눌렀을 때 사용자 정보 페이지로 넘어가기
        else if (event.keyCode == 13) {
            // 선택된게 없다면 취소
            if (cur_select < 0)
                return false;
            var member_srl = $('.user_finder_box .user_info:eq(' + cur_select + ')').attr('member_srl');
            location.href = dispMemberInfo + member_srl;
            return false;
        }
        //올바른 입력키가 입력되었는지 확인
        if (!isValidInputKey(event)) {
            return false;
        }
        // 키가 눌러진 후 몇 초간 간격 뒤에 찾기 알고리즘 실행
        var $that = $(this);
        clearTimeout(t);
        t = setTimeout(function() {
            var responses = ['member_list'];
            var params = {};
            params['search_keyword'] = $that.val();
            if ($that.val() == '') {
                $('.user_finder_box .user_info').remove();
                length = 0;
                cur_select = -1;
                return false;
            }
            for (var i in search_target) {
                params[search_target[i]] = $that.val();
            }
            params['sort_order'] = sort_order;
            params['sort_list'] = sort_list;
            params['list_count'] = parseInt(list_count) + 1;
            params['page'] = page;
            exec_xml('user_finder', 'getUser_finderMemberList', params, completeGetUserFinder, responses);
        }, delay_time);
    });
    
    function completeGetUserFinder(ret_obj) {
        // 만약에 기존에 사용자 정보를 담은 필다가 있다면 그 필드 모두 지우기
        if (page == 1)
            $('.user_finder_box .user_info').remove();
        length = 0;
        cur_select = -1;
        $('.user_finder_box .user_info').each(function() {
            lighten_member_info($(this));
        });
        
        // 요청 실패시 취소
        var message = ret_obj['message'];
        if (message != 'success') {
            $('.user_finder_box .inputbox').val($('.user_finder_box .inputbox').attr('default'));
            $('.user_finder_box .user_info').remove();
            length = 0;
            cur_select = -1;
            $('.user_finder_box .see_more').css('display', 'none');
            return false;
        }
        
        // 받은 사용자 정보를 넣는다.
        var member_list = ret_obj['member_list'];
        
        // 아무것도 받은 것이 없다면 취소
        if (member_list == null) {
            $('.user_finder_box .user_info').remove();
            length = 0;
            cur_select = -1;
            $('.user_finder_box .see_more').css('display', 'none');
            return false;
        }
        
        // member_list.item 이 array 형식이 아닐 경우 array로 변환
        if (!$.isArray(member_list.item)) {
            member_list.item = new Array(member_list.item);
        }
        // 받은 모든 아이템을 박스화로 만들어서 출력시켜준다.
        for (var i in member_list.item) {
            if (i >= list_count)
                break;
            
            var $user_info = $('.user_finder_box .user_info_original').clone();
            $user_info.removeClass('user_info_original');
            $user_info.addClass('user_info');
            $user_info.find('div').addClass('member_' + member_list.item[i]['member_srl']);
            $user_info.css('display', 'block');
            $user_info.attr('order', i);
            $user_info.attr('member_srl', member_list.item[i]['member_srl']);
            
            // 프로필 사진.
            if (member_list.item[i].profile_image != null) {
                $user_info.find('.profile').attr('src', member_list.item[i].profile_image['file']);
            } else {
                $user_info.find('.profile').attr('src', 'widgets/user_finder/skins/default/img/anonymous.jpg');
            }
            // disp_info 에 명시되어있는 3개의 아이템을 출력시켜준다.
            for (var j = 1; j <= 3; j++) {
                if (disp_info[j - 1] == null)
                    break;
                $user_info.find('.inbox_' + j).text(member_list.item[i][disp_info[j - 1]]);
                $user_info.find('.inbox_' + j).addClass(disp_info[j - 1]);
                $user_info.find('.inbox_' + j).removeClass('inbox_' + j);
            }
            // 마우스를 올렸을 때 진해지도록 이벤트 할당
            $user_info.bind('mouseenter', onMouseEnter);
            // 마우스를 내렸을 때 연해지도록 이벤트 할당
            $user_info.bind('mouseleave', onMouseLeave);
            // html element 삽입
            $('.user_finder_box .user_info_original').before($user_info);
        }
        // list_count보다 더 많다면 더보기 버튼 보이기
        if (i >= list_count) {
            $('.user_finder_box .see_more').css('display', 'block');
        } else {
            $('.user_finder_box .see_more').css('display', 'none');
        }
        length = $('.user_finder_box .user_info').length;
    }
    
    /**
     * 최초에 클릭하면 기존에 있던 '사용자를 찾아보세요...' 메시지 없앤다.
     */
    $('.user_finder_box .inputbox').click(function() {
        var theVal = $(this).val().toString();
        var theDef = $(this).attr('default').toString();
        if (theVal != theDef)
            return false;
        else
            $(this).val('');
    });
    
    /**
     * 닫기 버튼을 클릭하면 모든 검색 결과를 없애주고 택스트 박스 글자 원위치
     */
    $('.user_finder_box .btnClose').click(function() {
        $('.user_finder_box .user_info').remove();
        length = 0;
        cur_select = -1;
        $('.user_finder_box .inputbox').val($('.user_finder_box .inputbox').attr('default'));
        $('.user_finder_box .see_more').hide();
    });
    
    /**
     * 더 보기를 눌렀을 때 다음 페이지를 불러오기
     */
    $('.user_finder_box .see_more').click(function() {
        var responses = ['member_list'];
        var params = {};
        page++;
        params['search_keyword'] = $('.user_finder_box .inputbox').val();
        for (var i in search_target) {
            params[search_target[i]] = $('.user_finder_box .inputbox').val();
        }
        params['sort_order'] = sort_order;
        params['sort_list'] = sort_list;
        params['list_count'] = parseInt(list_count) + 1;
        params['page'] = page;
        console.log(params);
        
        exec_xml('user_finder', 'getUser_finderMemberList', params, completeGetUserFinder, responses);
    });
    
    /**
     * 마우스를 올렸을 때 진하게 만듬
     */
    function onMouseEnter(event) {
        // 일단 모든 엘리먼트들을 연하게 만듬.
        $('.user_finder_box .user_info').each(function() {
            lighten_member_info($(this));
        });
        // 마우스 올라간 녀석 진하게 만듬
        darken_member_info($(this));
        // 전역변수 정리하기
        cur_select = $(this).attr('order');
    }
    /**
     * 마우스를 내렸을 때 연하게 만듬
     */
    function onMouseLeave(event) {
        // 처리 안해도 되나???
    }
    
    /**
     * 진하게 만드는 함수
     */
    function lighten_member_info(obj) {
        obj.removeClass('darkened');
    }
    
    /**
     * 연하게 만드는 함수
     */
    function darken_member_info(obj) {
        obj.addClass('darkened');
    }
    
    /**
     * 입력된 키가 올바른 값인지 확인
     * 13(엔터)을 눌렀을 때 사용자 정보 페이지로 넘어가자.
     */
    function isValidInputKey(e) {
        //8(bs), 32(sp), 48 ~ 57(숫자), 65 ~ 90(알파벳), 96 ~ 109(키패드:모질라)
        var k = e.keyCode;
        if ((k == 8) || ((k >= 48)&&(k <= 57)) ||
                ((k >= 65)&&(k <= 90)) || ((k >= 96)&&(k <= 109))) {
            return true;
        }
        return false;
    }
});

/**
 * 학번을 받아서 뒷 자리 2자리를 *표로 가려준다.
 *
function maskStuid(stuid) {
    var t;
    t = stuid.substring(0, stuid.length - 2);
    t += "**";
    return t;
}
*/

  • profile
    기진곰 2016.09.29 11:46:20

    파이어폭스는 한글, 한자, 일본어 등 여러 키를 눌러야 하나의 문자가 완성되는 언어를 처리하는 방식이 좀 다릅니다. 이것 때문에 예전엔 에디터에서 자음과 모음이 분리되는 경우도 있었고요.

     

    모든 사용자에게 권해줄 수 있는 해결책은 아니지만, 혹시 about:config 화면에서 intl.tsf.enable 설정을 false로 변경한 후 파폭을 재시작해도 같은 현상인가요? (파폭 주소창에 about:config라고 입력하면 됩니다.)

  • profile
    웹지기 2016.09.29 11:47:42
    윽... 클라이언트에서 해결해야 할 문제라면 좀 어려운 문제군요. 일단 해보겠습니다.
  • profile
    웹지기 2016.09.29 11:54:28
    뭔가 바뀌긴 했는데 회원검색 위젯에서는 동일하네요. js에서 수정해서 될게 아니면 그냥 포기해야 할 것 같습니다. 클라이언트들을 다 제가 손봐줄 수 있는 상황이 아니니까요.

    증상이 정확이 어떤 증상이냐면요...
    다른 브라우저는 한글자를 완성하면 커서가 그 글자 앞에 깜빡입니다. 그러면서 해당글자와 매칭이 되는 것을 잘 출력을 해주구요.

    파이어폭스는 글자하나를 완성하면 커서가 아닌 해당글자를 음영 ? 과 같이 선택한 듯한 모습을 합니다. 그래서 그것을 스페이스로 한칸 이동한다음 다시 백스페이스로 해당문자와 커서를 붙여주면 이때 동작을 해요.

    지금 말씀해주신 설정으로 바꿨더니 문자완성후 커서가 생기지는 않고 글자 밑에 점선이 생기네요. 이전에는 글자에 블럭처럼 색칠? 같은거 였거든요.
  • profile
    기진곰 2016.09.29 12:01:23
    글자를 완성하는 방식만 바뀌고, 방금 입력한 문자는 아직 완성되지 않은 것으로 취급하는 문제는 마찬가지인 모양이네요. 하긴 "웹지기"라고 써놓으면 "웹지기"라고 다 쓴 건지, 아니면 "웹지김"이라고 아직 쓰는 중인지 구분하기가 곤란하잖아요. 확실하지 않으면 이벤트를 안 날리나 봅니다...

    그런데 스페이스를 누르면 입력이 끝난 것이 확실한데, 다시 백스페이스를 눌러서 커서를 붙여줘야 한다니 이상하네요. 혹시 입력값을 trim해 주지 않아서 스페이스까지 포함된 닉네임을 검색하려고 하는 게 아닐까요? 만약 이런 문제라면 js에서 수정할 수 있을 것 같습니다.
  • profile
    웹지기 2016.09.29 12:03:24
    일단 왜 그런지는 저는 알수 없지만 일정시간 후 동작하게 되는 것이 동작하려면 파이어폭스에서는 스페이스로 분리 한다음 다시 그 공백을 없애줘야 동작하는 것으로 보아 공백은 동작이 안되게 되어있는게 아닐까요... 닉네임에 공백은 안들어가니 제작자가 그렇게 처리를 했을라나요....
  • profile
    웹지기 2016.09.29 12:18:36

    테스트를 해보니 공백도 입력하고 있는 것으로 인식 합니다 ㅋ

    웹지_기 라고 검색을 하면 웹지기가 검색되어지네요.

    그러니까 검색하고 스페이스를 한칸 띄운 상태에서도 커서가 아닌 상황이라 동일하게 동작을 하고 있지 않네요. 스페이스 이후 공백을 백스페이스로 없애주면 커서로 되면서 동작을 하게 되는거네요.

     

    근데 스페이스로 공백상태에서는 모습은 커서 모습으로 하고 있긴 하네요.

  • profile
    기진곰 2016.09.29 13:14:01
    복잡하네요 ㅠ

    언제 기회가 있으면 모든 PC 및 모바일 브라우저에서 한글 입력을 처리하는 방식을 죄다 비교/분석해 봐야겠습니다. 예전에도 jQuery의 val()이 마지막으로 입력한 한글을 인식하지 못하는 문제를 본 적이 있는데, 그 때는 그냥 넘겼거든요...
  • profile
    웹지기 2016.09.29 13:19:24
    모바일은 이 서비스 저희도 제공하지 않아요 ㅋ 동작하지 않죠 ㅋ

List of Articles
번호 분류 제목 최종 글
공지 질문/답변 답변을 확실히 받기위한 질문자 지침서 20  
» 질문/답변 js의 파이어폭스에서 이상동작 8 2016.09.29 수정 웹지기
2910 질문/답변 스케치북 파이어폭스에서 동작하지 않는 클릭 동작 수정을 어떻게 해야 할까요? 3 2016.09.29 수정 웹지기
2909 질문/답변 예전에 신청서.. 2016.09.29 작성 가이더
2908 질문/답변 회원 기간제 모듈이나 에드온 없나요? 2 2016.09.29 수정 BlackTeddyBear
2907 질문/답변 이미지 관련 질문합니다 2 2016.09.29 수정 기진곰
2906 질문/답변 국내 IP를 구분하는 방법이 있을까요? 2 2016.09.29 수정 하늘희
2905 질문/답변 제목에 나오는 " 요거 없에는 방법 있을가요...? 11 2016.09.29 수정 웹지기
2904 질문/답변 도메인에 대해서 갑자기 궁금합니다 5 2016.09.28 수정 낙타
2903 질문/답변 comment 모듈의 발행대기/발행완료 기능? 9 2016.09.28 수정 웹지기
2902 질문/답변 관리자페이지에서 SSL 선택사용 그거 선택하는거요! 5 2016.09.28 수정 다이오니
2901 질문/답변 제이쿼리에 관하여 문의드립니다. 어떻게 해도 않되네요 ㅜ.ㅠ; 6 file 2016.09.28 수정 윤삼
2900 질문/답변 모바일 회원정보 문의 3 file 2016.09.28 수정 웹지기
2899 질문/답변 여기서 속도가 어떤건가요? 3 file 2016.09.28 수정 낙타
2898 질문/답변 여러 파일이 있는 폴더에서 특정 키워드 찾는 프로그램이 있을까요? 7 2016.09.28 수정 엘비스
2897 질문/답변 폰트질문드립니다. 2 2016.09.29 수정 가이더
2896 질문/답변 혹시 회원가입을 해야 특정 게시글 부분이 보인다는거 있나요? 3 2016.09.28 수정 라그릿
2895 질문/답변 VPS 추천 부탁드립니다~ 10 2016.09.27 수정 고라자
2894 질문/답변 슈퍼캐시 질문 좀 드려요 ~ 12 2016.09.27 수정 나만의너
2893 질문/답변 mod_pagespeed ( dns 질문 ) 9 2016.09.27 수정 웹지기
2892 질문/답변 메일 발송시 받는 사람 이름 표기 부분이 궁금합니다. 2 file 2016.09.28 수정 엘비스
Board Pagination Prev 1 ... 22 23 24 25 26 27 28 29 30 31 ... 172 Next
/ 172
위로
서버에 요청 중입니다. 잠시만 기다려 주십시오...