b0y-101 Mini Shell


Current Path : E:/www/advanced-mba/ad_std/javascript/
File Upload :
Current File : E:/www/advanced-mba/ad_std/javascript/jquery.auto-province.js

/** jQuery AutoProvince Version 1.0
 */

var ESCAPE_KEY = 27;
var ENTER_KEY = 13;
var UP_KEY = 38;
var DOWN_KEY = 40;
var PAGEUP_KEY = 33;
var PAGEDOWN_KEY = 34;
var DELETE_KEY = 46;
var SHIFT_KEY = 16;
var CTRL_KEY = 17;
var ALT_KEY = 18;
var TAB_KEY = 9;
var LEFT_KEY = 37;
var RIGHT_KEY = 39;
var END_KEY = 35;
var HOME_KEY = 36;

if (typeof console == 'undefined'){
    var console = {
        log: function(){}
    }
}
var AJS = {
    update: function(l1, l2) {
        for(var i in l2)
            l1[i] = l2[i];
        return l1;
    }
}
AJS.Class = function(members) {
    var fn = function() {
        if(arguments[0] != 'no_init') {
            return this.init.apply(this, arguments);
        }
    }
    fn.prototype = members;
    AJS.update(fn, AJS.Class.prototype);
    return fn;
}
AJS.Class.prototype = {
    extend: function(members) {
        var parent = new this('no_init');
        for(k in members) {
            var prev = parent[k];
            var cur = members[k];
            if (prev && prev != cur && typeof cur == 'function') {
                cur = this._parentize(cur, prev);
            }
            parent[k] = cur;
        }
        return new AJS.Class(parent);
    },

    implement: function(members) {
        AJS.update(this.prototype, members);
    },

    _parentize: function(cur, prev) {
        return function(){
            this.parent = prev;
            return cur.apply(this, arguments);
        }
    }
}//end AJS.Class

;(function($){

AutoProvince = AJS.Class({
    init: function(opt){

    var d1 = '<div class="ap-tumbol-window"><div class="ap-title-bar"><div class="ap-ajaxloader"></div><div class="ap-button">รายชื่อตำบล<a href=".">[x]</a></div><br clear="both" /></div><div class="ap-list"></div></div>';
    var d2 = '<div class="ap-postcode-window"><div class="ap-title-bar"><div class="ap-button">รายชื่อรหัสไปรษณีย์<a href=".">[x]</a></div></div><div class="ap-list"></div></div>';
    var d3 = '<iframe width="0" scrolling="no" height="0" frameborder="0" class="ap-iframetop"></iframe>';
    var d4 = '<div class="ap-new-postcode-window"><div class="ap-button">เพิ่มรหัสไปรษณีย์<a href=".">[x]</a></div><form name="postcode-form" action=""><input type="hidden" size="10" class="ap-ref-amphur-id" value="" /><input type="text" size="10" class="ap-new-postcode" value="" /><input type="submit" value="เพิ่ม" class="ap-new-postcode-button" /></form></div>';

    var mp = this;
    var mpNumber = 'ap-'+($.fn.AutoProvince.number++);
    $.fn.AutoProvince.obj[mpNumber] = this;

    mp.tumbolWnd = $(d1).appendTo('body');
    mp.tumbolList = mp.tumbolWnd.find('.ap-list');
    mp.postcodeWnd = $(d2).appendTo('body');
    mp.postcodeList = mp.postcodeWnd.find('.ap-list');
    mp.iframeTop = $(d3).appendTo('body');
    mp.newPostcodeWnd = $(d4).appendTo('body');

    mp._tumbol = $(opt.tumbol);
    mp._amphur = $(opt.amphur);
    mp._province = $(opt.province);
    mp._postcode = $(opt.postcode);

    mp.tumbolBackup = mp._tumbol.val();
    mp.amphurBackup = mp._amphur.val();
    mp.provinceBackup = mp._province.val();
    mp.postcodeBackup = mp._postcode.val();
    
    mp.opt = opt;

    //mp.tumbolXhr;
    //mp.tumbolData;
    //mp.tumbolIndex;
    var divAjaxLoader = mp.tumbolWnd.find('.ap-ajaxloader');
    mp.tumbolLoader = $('<img />').appendTo(divAjaxLoader);
    mp.tumbolLoader.attr('src',opt.ajaxLoader);


    function hideWnd(obj){
        mp.iframeTop.hide();
        obj.hide();
    }
    function addHl(obj){
        obj.addClass('ap-highlight');
    }
    function removeHl(obj){
        obj.removeClass('ap-highlight');
    }
    function iframeAt(div){
        if ($.support.opacity){
           return;
        }
        mp.iframeTop.css({
           position:'absolute',
           width:div.width(),
           height:div.height(),
           left:div.offset().left,
           top:div.offset().top,
           display:'block',
           'z-index':mp.iframeTop.css('z-index')+1
        });
    }
    function hideAjaxLoader(loader){
        setTimeout(function(){
            loader.hide();
        },500);
    }
    function indexOfArray(value,a){
        var ret = -1;
        for(var i=0;i<a.length;i++){
            if (typeof a[i] != 'undefined'){
                if (a[i] == value){
                    ret = i;
                }
            }
        }
        return ret;
    }
    function showWnd(textbox,wnd){
        wnd.css({
            left: textbox.offset().left,
            top: textbox.offset().top+textbox.height()+10
        }).show();
    }


/**
 * ถูกเรียกเมื่อ keyup ที่ tumbol input
 */
function loadTumbolList(){
        if (mp._tumbol.val().length > 1 || mp._tumbol.val() == '-'){
            $.ajax({
                url: '../com_form/g_action.php?tumbol',
                type: 'get',
                dataType: 'json',
                data:{tumbol: mp._tumbol.val()},
                beforeSend: function(xhr){
                    //abort ajax thread
                    mp.tumbolList.hide();
                    mp.tumbolLoader.show();
                    showWnd(mp._tumbol,mp.tumbolWnd);
                    if (mp.tumbolXhr){
                        mp.tumbolXhr.abort();
                    }
                    mp.tumbolXhr = xhr;                    
                },
                success: function(d){
                    hideAjaxLoader(mp.tumbolLoader);
                    //บันทึกค่ารายชื่อ
                    mp.tumbolData = d;
                    if (setTumbolList()){
                        showTumbolList();
                        mp.tumbolList.show();
                    }else{                        
                        hideWnd(mp.tumbolWnd);
                        mp.tumbolList.show();
                    }
                },
                error: function(XMLHttpRequest, textStatus, errorThrown){
                    alert(textStatus);
                    hideAjaxLoader(mp.tumbolLoader);
                }
            });
        }else{
            hideWnd(mp.tumbolWnd);
        }
    }
/*
 * แสดงรายชื่อหน้างต่างรายชื่อตำบล
 * จะทำงานได้ถูกต้องก็ต่อเมื่อถูกเรียกหลังจากคำสั่ง setTumbolList
 */
function showTumbolList(){
        var xy = mp._tumbol.offset();
        var h = mp._tumbol.height();
        mp.tumbolBackup = mp._tumbol.val();
        mp.amphurBackup = mp._amphur.val();
        mp.provinceBackup = mp._province.val();
        mp.postcodeBackup = mp._postcode.val();
        //mp.tumbolList.show();
        showWnd(mp._tumbol, mp.tumbolWnd);
        iframeAt(mp.tumbolWnd);
        mp.tumbolList.attr('scrollTop',0);
        mp.tumbolList.find('a:first-child').trigger('mouseover');
    }

/**
 * แทรกรายชื่อตำบลลงใน tumbol list
 * ถูกเรียกเมื่อ ต้องการกำหนดรายการที่ได้จาก ajax หรือจาก cache (mp.tumbolData)
 */
function setTumbolList(){
        var p;
        var hasData = false;
        var d = mp.tumbolData;
        //clear รายการใน tumbol list
        mp.tumbolList.html('');
        //เพิ่มข้อมูลลิงค์เข้าไปทีละอัน
        for(var i in d.dname){
            d.postcode[i].sort();
            for(var j in d.postcode[i]){
                //if (d.postcode[i][j]){
                    p = $('<a />').appendTo(mp.tumbolList);
                    p.attr('index',i);
                    p.attr('href','#');
                    p.text(d.dname[i]+' - '+d.aname[i]+' - '+d.pname[i] + ' - ' + d.postcode[i][j]);
                //}
            }
            p = $('<a />').appendTo(mp.tumbolList);
            p.attr('index',i);
            p.attr('href','#');
            p.text(d.dname[i]+' - '+d.aname[i]+' - '+d.pname[i]);
            hasData = true;
            //break if too many data ***
            if (i>200){
                break;
            }
        }
        //onclick tumbol link
        $(document).ready(function(){
            tumbolLinkEvent();
        });
        return hasData;
    }
function tumbolLinkEvent(){
        mp.tumbolList.find('a').click(function(e){e.preventDefault();
            var idx = mp.tumbolIndex = $(this).attr('index');
            //ใส่ข้อมูลลงใน inputs
            mp._tumbol.val(mp.tumbolData.dname[idx]);
            mp._amphur.val(mp.tumbolData.aname[idx]);
            mp._province.val(mp.tumbolData.pname[idx]);
            //ล่างค่า postcode input เดิมออกก่อน
            setPostcodeList(mp.tumbolData.postcode[idx]);
            mp._postcode.val('');
            hideWnd(mp.tumbolWnd);
            if ( !$(this).text().match(/\d\d\d\d\d/)){
                //เปิดหน้าต่างเพิ่ม postcode
                mp.newPostcodeWnd.find('.ap-ref-amphur-id').val(mp.tumbolData.aid[idx]);                
                mp.newPostcodeWnd.css({
                    left: mp._tumbol.offset().left,
                    top: mp._tumbol.offset().top-50
                }).show();
                mp.newPostcodeWnd.find('.ap-new-postcode')
                .val('').focus();
            } else {
                //ใส่ข้อมูล postcode ใน postcode input
                mp._postcode.val($(this).text().replace(/^.*(\d\d\d\d\d).*$/, "$1"));
                mp._postcode.focus();
            }
        });
        mp.tumbolList.find('a').hover(function(){
            removeHl(mp.tumbolList.find('a'));
            addHl($(this));
            mp._tumbol.focus();
        },function(){
        });
    }
//==========================================================//

/**
 * ถูกเรียกเมื่อ keyup ที่ postcode input
 */
function loadPostcodeList(){
        if ((mp._tumbol.val().length > 1 || mp._tumbol.val() == '-')
            && mp._amphur.val().length > 1
            && mp._province.val().length > 1)
        {
            $.ajax({
                url: '../com_form/g_action.php?postcode',
                type: 'get',
                dataType: 'json',
                data:{
                    tumbol: mp._tumbol.val(),
                    amphur: mp._amphur.val(),
                    province: mp._province.val()
                },
                success: function(d){
                    showPostcodeList();
                }
            });
        }
    }
/*
 * แสดงรายชื่อหน้างต่างรายชื่อ postcode
 */
function showPostcodeList(){
        var xy = mp._postcode.offset();
        var h = mp._postcode.height();
        mp.postcodeBackup = mp._postcode.val();
        if (typeof mp.tumbolIndex != 'undefined'){
            setPostcodeList(mp.tumbolData.postcode[mp.tumbolIndex]);
            iframeAt(mp.postcodeWnd);
            mp.postcodeWnd.css({
                left: xy.left,
                top: xy.top+h+10
            }).show();
            mp.postcodeList.find('a:first-child').trigger('mouseover');
        }
    }
/**
 * แทรกรายชื่อตำบลลงใน postcode list
 * ถูกเรียกเมื่อ ต้องการกำหนดรายการที่ได้จาก ajax หรือจาก cache (mp.tumbolData)
 */
function setPostcodeList(postcodes){
        var p;
        var d = mp.tumbolData;
        mp.postcodeList.html('');
        postcodes.sort();
        for(var i in postcodes){
            p = $('<a />').appendTo(mp.postcodeList);
            p.attr('href','.');
            p.text(postcodes[i]);
        }
        $(document).ready(function(){
          postcodeLinkEvent();
        });
    }
function postcodeLinkEvent(){
        mp.postcodeList.find('a').click(function(e){e.preventDefault();
            mp._postcode.val($(this).text());
            hideWnd(mp.postcodeWnd);
        });
        mp.postcodeList.find('a').hover(function(){
            removeHl(mp.postcodeList.find('a'));
            addHl($(this));
            mp._postcode.focus();
        },function(){
        });        
    }


//==========================================================//
function onkeydownTextbox(op){
        //wnd,lst,button
        var opt = $.extend({
            wnd: mp.tumbolWnd,
            lst: mp.tumbolList,
            showWnd: function(){},
            down: function(){},
            up: function(){},
            enter: function(){},
            escape: function(){},
            e: null,
            scrollSize: 5
        }, op);
        if (opt.wnd.filter(':hidden').size() > 0){
            if (opt.e.keyCode == DOWN_KEY){
                opt.showWnd();
            }
            if (opt.e.keyCode == ESCAPE_KEY){
                opt.e.preventDefault();
            }
            return;
        }
        var hlink = opt.lst.find('.ap-highlight');
        var st = 0;
        var size = 0;
        switch (opt.e.keyCode) {
            case UP_KEY:
                if (hlink.prev().size() > 0){
                    removeHl(hlink);
                    addHl(hlink.prev());
                    st = opt.lst.attr('scrollTop')-hlink.height();
                    opt.lst.attr('scrollTop',st);
                } else {
                    if (opt.wnd==mp.postcodeWnd){
                        hideWnd(opt.wnd);
                    }
                }
                opt.up();
                break;
            case DOWN_KEY:
                if (hlink.next().size() > 0){
                    removeHl(hlink);
                    addHl(hlink.next());
                    if (hlink.offset().top+(hlink.height()*2)-opt.lst.offset().top > opt.lst.attr('clientHeight')){
                        st = opt.lst.attr('scrollTop')+hlink.height();
                        opt.lst.attr('scrollTop',st);
                    }
                }
                opt.down();
                break;
            case PAGEUP_KEY:
                var pv = hlink.prev();
                size = opt.scrollSize-1;
                while(pv.size() > 0 && size > 0){
                    size--;
                    pv = pv.prev();
                }
                if (pv.size() > 0){
                    removeHl(hlink);
                    addHl(pv);
                    st = opt.lst.attr('scrollTop')-hlink.height()*(opt.scrollSize-size);
                }else{
                    removeHl(hlink);
                    addHl(opt.lst.find('a:first-child'));
                    st = 0;                    
                }
                opt.lst.attr('scrollTop',st);
                break;
            case PAGEDOWN_KEY:
                var next = hlink.next();
                size = opt.scrollSize-1;
                while(next.size() > 0 && size > 0){
                    size--;
                    next = next.next();
                }
                if (next.size() > 0){
                    removeHl(hlink);
                    addHl(next);
                    if (hlink.offset().top+hlink.height()*2-opt.lst.offset().top > opt.lst.attr('clientHeight')){
                        st = opt.lst.attr('scrollTop')+hlink.height()*(opt.scrollSize-size);
                    } else {
                        st = hlink.offset().top-opt.lst.offset().top;
                    }
                }else{
                    removeHl(hlink);
                    addHl(opt.lst.find('a:last-child'));
                    st = opt.lst.attr('scrollHeight');
                }
                opt.lst.attr('scrollTop',st);
                /*console.log(
                    '  clientHeight='+opt.lst.attr('clientHeight')+
                    '  scrollTop='+opt.lst.attr('scrollTop')+
                    '  scrollHeight='+opt.lst.attr('scrollHeight')+
                    '  hlink='+hlink.offset().top+
                    '  current='+next.offset().top
                );*/
                break;
            case ENTER_KEY:
                hlink.trigger('click');
                opt.e.preventDefault();
                opt.enter();
                break;
            case ESCAPE_KEY:
                hideWnd(opt.wnd);
                opt.escape();
                break;
            default:
                break;
        }
    }


    //DEFINE EVENT HANLDER
    mp.tumbolWnd.find('.ap-button a').click(function(e){e.preventDefault();
        hideWnd(mp.tumbolWnd);
    });
    mp.postcodeWnd.find('.ap-button a').click(function(e){e.preventDefault();
        hideWnd(mp.postcodeWnd);
    });
    mp.newPostcodeWnd.find('.ap-button a').click(function(e){e.preventDefault();
        hideWnd(mp.newPostcodeWnd);
    });
    mp.newPostcodeWnd.find('form').submit(function(e){e.preventDefault();
        var newpostcode = mp.newPostcodeWnd.find('.ap-new-postcode').val();
        var amphur_id = mp.newPostcodeWnd.find('.ap-ref-amphur-id').val();
        $.ajax({
            url:'../com_form/g_action.php?add-postcode',
            type:'post',
            dataType:'json',
            data:{
                postcode: newpostcode,
                amphur_id: amphur_id
            },
            success:function(d){
                if (!d.error){
                    var idx = indexOfArray(amphur_id, mp.tumbolData.aid);
                    mp.tumbolData.postcode[idx].push(newpostcode);
                    mp._postcode.val(newpostcode);
                    mp.newPostcodeWnd.hide();
                    mp._postcode.focus();
                } else {
                    alert(d.message);
                    mp.newPostcodeWnd.find('.ap-new-postcode').focus();
                }
            }
        });
    });
    mp._tumbol.keyup(function(e){
        if (e.keyCode == DELETE_KEY && e.ctrlKey){
            e.preventDefault();
            return true;
        }
        var CONTROL_KEYS  = [
            TAB_KEY,ENTER_KEY,ESCAPE_KEY,SHIFT_KEY,CTRL_KEY,
            LEFT_KEY,UP_KEY,RIGHT_KEY,DOWN_KEY,
            PAGEUP_KEY,PAGEDOWN_KEY,END_KEY,HOME_KEY
        ];
        if (indexOfArray(e.keyCode, CONTROL_KEYS) != -1){
            e.preventDefault();
            return true;
        }
        loadTumbolList();
    });
    mp._tumbol.blur(function(e){
        //การปิดหน้าต่างด้วย onblur มีผลให้ onclick ทำงานไม่ทัน จึงแก้ไขด้วยการชลอการปิด
        setTimeout(function(){
            hideWnd(mp.postcodeWnd);
            hideWnd(mp.tumbolWnd);
        },200);
    });
    mp._postcode.blur(function(e){
        setTimeout(function(){
            hideWnd(mp.postcodeWnd);
            hideWnd(mp.tumbolWnd);
        },200);
    });
    mp._tumbol.keydown(function(e){
        if (e.ctrlKey && e.keyCode == DELETE_KEY){
            if (mp.tumbolWnd.filter(':visible').size() > 0){
                var hlink = mp.tumbolList.find('.ap-highlight');
                var idx = hlink.attr('index');
                var deleted = hlink.text().replace(/^.*(\d\d\d\d\d).*$/, "$1");
                if (hlink.text().match(/\d\d\d\d\d/) && confirm('ลบ '+hlink.text()+' ?')){
                    $.ajax({
                        url: 'auto-province/g_action.php?delete-postcode',
                        type: 'post',
                        dataType: 'json',
                        data:{
                            postcode: deleted,
                            amphur_id: mp.tumbolData.aid[idx]
                        },
                        success: function(d){
                            if (!d.error){
                                var removeIndex = indexOfArray(deleted, mp.tumbolData.postcode[idx]);
                                if (removeIndex != -1){
                                    mp.tumbolData.postcode[idx].splice(removeIndex,1);
                                }
                                hideWnd(mp.tumbolWnd);
                            } else {
                                alert(d.message);
                            }
                            mp._tumbol.focus();
                        }
                    });
                }
            }
            return true;
        }
        onkeydownTextbox({
            e: e,
            wnd: mp.tumbolWnd,
            lst: mp.tumbolList,
            showWnd: function(){
                if (!mp.tumbolData){
                    loadTumbolList();
                } else {
                    if (setTumbolList()){
                        showTumbolList();
                    }
                }
            },
            down: function(){},
            up: function(){},
            enter: function(){},
            escape: function(){
                setTimeout(function(){
                    mp._tumbol.val(mp.tumbolBackup);
                    mp._amphur.val(mp.amphurBackup);
                    mp._province.val(mp.provinceBackup);
                    mp._postcode.val(mp.postcodeBackup);
                },1000);
            },
            scrollSize: mp.opt.tumbolScrollSize
        });
    }).keypress(function(e){
        if (e.keyCode == ENTER_KEY){
            e.preventDefault();
        }
    });
    mp._postcode.keydown(function(e){
        onkeydownTextbox({
            e: e,
            wnd: mp.postcodeWnd,
            lst: mp.postcodeList,
            showWnd: function(){
                if (mp.tumbolData){
                    showPostcodeList();
                } else {
                    loadPostcodeList();
                }
            },
            down: function(){},
            up: function(){},
            enter: function(){},
            escape: function(){
                setTimeout(function(){
                    mp._postcode.val(mp.postcodeBackup);
                },1000);
            },
            scrollSize: mp.opt.postcodeScrollSize
        });
    });

    }//end init()
});

/************ PLUGIN CONSTRUCTOR *************/
$.fn.AutoProvince = function(option) {
    if (typeof option == 'string'){

    } else {        
        var opt = $.extend({}, $.fn.AutoProvince.defaults, option);
        return this.each(function(){
            opt.tumbol = '#'+$(this).attr('id');
            new AutoProvince(opt);
        });//end return each
    }
};
$.fn.AutoProvince.defaults = {
    tumbol:'#ap-tumbol',
    amphur:'#ap-amphur',
    province:'#ap-province',
    postcode:'#ap-postcode',
    ajaxLoader:'com_form/ajax-loader.gif',
    tumbolScrollSize:7,
    postcodeScrollSize:4
};
$.fn.AutoProvince.number = 0;
$.fn.AutoProvince.obj = {};

})(jQuery);

Copyright © 2019 by b0y-101