/** 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);