/*jslint browser:true, devel:true */
/*global window, $, jQuery*/
/**
* jquery.jpostal.js ver2.7
*
* Copyright 2014, Aoki Makoto, Ninton G.K. http://www.ninton.co.jp
*
* Released under the MIT license - http://en.wikipedia.org/wiki/MIT_License
*
* Requirements
* jquery.js
*/
var Jpostal = {};
Jpostal.Database = function () {
"use strict";
this.address = []; // database cache
this.map = {};
this.url = {
'http' : '//jpostal-1006.appspot.com/json/',
'https' : '//jpostal-1006.appspot.com/json/'
};
};
Jpostal.Database.prototype.find = function (i_postcode) {
"use strict";
var address = [];
this.address.forEach(function (eachAddress) {
if (eachAddress[0] === '_' + i_postcode) {
address = eachAddress;
}
});
return address;
};
Jpostal.Database.prototype.get = function (i_postcode) {
"use strict";
// --------------------------------------------------
// i_postcode find() find() result
// 1234567 123
// --------------------------------------------------
// 1 - - defaults
// 12 - - defaults
// 123 - Y find( '123' )
// 123 - N defaults
// 1234 - Y find( '123' )
// 1234 - N defaults
// 1234567 Y - find( '1234567' )
// 1234567 N Y find( '123' )
// 1234567 N N defaults
// --------------------------------------------------
var defaults = ['', '', '', '', '', '', '', '', ''],
address,
head3;
switch (i_postcode.length) {
case 3:
case 4:
case 5:
case 6:
head3 = i_postcode.substr(0, 3);
address = this.find(head3);
address = $.extend(defaults, address);
break;
case 7:
address = this.find(i_postcode);
if (address.length === 0) {
head3 = i_postcode.substr(0, 3);
address = this.find(head3);
}
address = $.extend(defaults, address);
break;
default:
address = defaults;
break;
}
return address;
};
Jpostal.Database.prototype.getUrl = function (i_head3) {
"use strict";
var url = '';
switch (this.getProtocol()) {
case 'http:':
url = this.url.http;
break;
case 'https:':
url = this.url.https;
break;
}
url = url + i_head3 + '.json';
return url;
};
Jpostal.Database.prototype.request = function (i_postcode, i_callback) {
"use strict";
var head3,
url,
options;
head3 = i_postcode.substr(0, 3);
if (i_postcode.length <= 2 || this.getStatus(head3) !== 'none' || head3.match(/\D/)) {
return false;
}
this.setStatus(head3, 'waiting');
url = this.getUrl(head3);
options = {
async : false,
dataType : 'jsonp',
jsonpCallback : 'jQuery_jpostal_callback',
type : 'GET',
url : url,
success : function () { // function(i_data, i_dataType
i_callback();
},
timeout : 5000 // msec
};
this.ajax(options);
return true;
};
Jpostal.Database.prototype.ajax = function (options) {
"use strict";
$.ajax(options);
};
Jpostal.Database.prototype.save = function (i_data) {
"use strict";
var that = this;
i_data.forEach(function (rcd) {
var postcode = rcd[0];
if (that.map[postcode] === undefined) {
that.address.push(rcd);
that.map[postcode] = {state : 'complete', time : 0};
} else if (that.map[postcode].state === 'waiting') {
that.address.push(rcd);
that.map[postcode].state = 'complete';
}
});
};
Jpostal.Database.prototype.getStatus = function (i_postcode) {
"use strict";
// --------------------------------------------------
// # ['_001'] ..state .time result
// --------------------------------------------------
// 1 =undefined - - none
// 2 !=undefined 'complete' - complete
// 3 !=undefined 'waiting' <5sec waiting
// 4 !=undefined 'waiting' >=5sec none
// --------------------------------------------------
var st = '',
postcode = '_' + i_postcode,
t_ms;
if (this.map[postcode] === undefined) {
// # 1
st = 'none';
} else if ('complete' === this.map[postcode].state) {
// # 2
st = 'complete';
} else {
t_ms = this.getTime() - this.map[postcode].time;
if (t_ms < 5000) {
// # 3
st = 'waiting';
} else {
// # 4
st = 'none';
}
}
return st;
};
Jpostal.Database.prototype.setStatus = function (i_postcode) {
"use strict";
var postcode = '_' + i_postcode;
if (this.map[postcode] === undefined) {
this.map[postcode] = {
state : 'waiting',
time : 0
};
}
this.map[postcode].time = this.getTime();
};
Jpostal.Database.prototype.getProtocol = function () {
"use strict";
return window.location.protocol;
};
Jpostal.Database.prototype.getTime = function () {
"use strict";
return (new Date()).getTime();
};
(function () {
"use strict";
var instance;
Jpostal.Database.getInstance = function () {
if (instance === undefined) {
instance = new Jpostal.Database();
}
return instance;
};
}());
Jpostal.Jpostal = function (i_JposDb) {
"use strict";
this.address = '';
this.jposDb = i_JposDb;
this.options = {};
this.postcode = '';
this.minLen = 3;
};
Jpostal.Jpostal.prototype.displayAddress = function () {
"use strict";
var that = this;
if (this.postcode === '000info') {
this.address[2] += ' ' + this.getScriptSrc();
}
Object.keys(this.options.address).forEach(function (key) {
var format = that.options.address[key],
value = that.formatAddress(format, that.address);
if (that.isSelectTagForPrefecture(key, format)) {
that.setSelectTagForPrefecture(key, value);
} else {
$(key).val(value);
}
});
};
Jpostal.Jpostal.prototype.isSelectTagForPrefecture = function (i_key, i_fmt) {
"use strict";
// 都道府県のSELECTタグか?
var f;
switch (i_fmt) {
case '%3':
case '%p':
case '%prefecture':
if ($(i_key).get(0).tagName.toUpperCase() === 'SELECT') {
f = true;
} else {
f = false;
}
break;
default:
f = false;
break;
}
return f;
};
Jpostal.Jpostal.prototype.setSelectTagForPrefecture = function (i_key, i_value) {
"use strict";
var value,
el;
// 都道府県のSELECTタグ
// ケース1:
$(i_key).val(i_value);
if ($(i_key).val() === i_value) {
return;
}
// ケース2: valueが数値(自治体コードの場合が多い)
// テキストが「北海道」を含むかどうかで判断する
//
//
value = '';
el = $(i_key)[0];
Object.keys(el.options).forEach(function (i) {
var p = String(el.options[i].text).indexOf(i_value);
if (0 <= p) {
value = el.options[i].value;
}
});
if (value !== '') {
$(i_key).val(value);
}
};
Jpostal.Jpostal.prototype.formatAddress = function (i_fmt, i_address) {
"use strict";
var s = i_fmt;
s = s.replace(/%3|%p|%prefecture/, i_address[1]);
s = s.replace(/%4|%c|%city/, i_address[2]);
s = s.replace(/%5|%t|%town/, i_address[3]);
s = s.replace(/%6|%a|%address/, i_address[4]);
s = s.replace(/%7|%n|%name/, i_address[5]);
s = s.replace(/%8/, i_address[6]);
s = s.replace(/%9/, i_address[7]);
s = s.replace(/%10/, i_address[8]);
return s;
};
Jpostal.Jpostal.prototype.getScriptSrc = function () {
"use strict";
var src = '',
el_arr,
i,
n,
el_src;
el_arr = document.getElementsByTagName('script');
n = el_arr.length;
for (i = 0; i < n; i += 1) {
el_src = el_arr[i].src;
if (0 <= el_src.indexOf("jquery.jpostal.js")) {
src = el_src;
break;
}
}
return src;
};
Jpostal.Jpostal.prototype.init = function (i_options) {
"use strict";
if (i_options.postcode === undefined) {
throw new Error('postcode undefined');
}
if (i_options.address === undefined) {
throw new Error('address undefined');
}
this.options.postcode = [];
if (typeof i_options.postcode === 'string') {
this.options.postcode.push(i_options.postcode);
} else {
this.options.postcode = i_options.postcode;
}
this.options.address = i_options.address;
if (i_options.url !== undefined) {
this.jposDb.url = i_options.url;
}
};
Jpostal.Jpostal.prototype.main = function () {
"use strict";
var that,
f;
this.scanPostcode();
if (this.postcode.length < this.minLen) {
// git hub issue #4: 郵便番号欄が0~2文字のとき、住所欄を空欄にせず、入力内容を維持してほしい
return;
}
that = this;
f = this.jposDb.request(this.postcode, function () {
that.callback();
});
if (!f) {
this.callback();
}
};
Jpostal.Jpostal.prototype.callback = function () {
"use strict";
this.address = this.jposDb.get(this.postcode);
this.displayAddress();
};
Jpostal.Jpostal.prototype.scanPostcode = function () {
"use strict";
var s = '',
s3,
s4;
switch (this.options.postcode.length) {
case 0:
break;
case 1:
// github issue #8: 1つ目を空欄、2つ目を「001」としても、「001」として北海道札幌市を表示してしまう
// ----------------------------------------
// case postcode result
// ----------------------------------------
// 1 '' ''
// 1 12 ''
// 2 123 123
// 2 123- 123
// 2 123-4 123
// 3 123-4567 1234567
// 2 1234 123
// 4 1234567 1234567
// ----------------------------------------
s = String($(this.options.postcode[0]).val());
if (0 <= s.search(/^([0-9]{3})([0-9A-Za-z]{4})/)) {
// case 4
s = s.substr(0, 7);
} else if (0 <= s.search(/^([0-9]{3})-([0-9A-Za-z]{4})/)) {
// case 3
s = s.substr(0, 3) + s.substr(4, 4);
} else if (0 <= s.search(/^([0-9]{3})/)) {
// case 2
s = s.substr(0, 3);
} else {
// case 1
s = '';
}
break;
case 2:
// github issue #8: 1つ目を空欄、2つ目を「001」としても、「001」として北海道札幌市を表示してしまう
// ----------------------------------------
// case post1 post2 result
// ----------------------------------------
// 1 '' --- ''
// 1 12 --- ''
// 2 123 '' 123
// 2 123 4 123
// 3 123 4567 1234567
// ----------------------------------------
s3 = String($(this.options.postcode[0]).val());
s4 = String($(this.options.postcode[1]).val());
if (0 <= s3.search(/^[0-9]{3}$/)) {
if (0 <= s4.search(/^[0-9A-Za-z]{4}$/)) {
// case 3
s = s3 + s4;
} else {
// case 2
s = s3;
}
} else {
// case 1
s = '';
}
break;
}
this.postcode = s;
};
// MEMO: For the following reason, JposDb was put on the global scope, not local scope.
// ---------------------------------------------------------------------
// data file callback JposDb scope
// ---------------------------------------------------------------------
// 001.js JposDb.save global scope
// 001.js.php $_GET['callback'] local scopde for function($){}
// ---------------------------------------------------------------------
var jQuery_jpostal_callback = function (i_data) {
"use strict";
Jpostal.Database.getInstance().save(i_data);
};
(function ($) {
"use strict";
$.fn.jpostal = function (i_options) {
var Jpos,
selector;
Jpos = new Jpostal.Jpostal(Jpostal.Database.getInstance());
Jpos.init(i_options);
if (typeof i_options.click === 'string' && i_options.click !== '') {
$(i_options.click).bind('click', function () {
Jpos.main();
});
} else {
selector = Jpos.options.postcode[0];
$(selector).bind('keyup change', function () {
Jpos.main();
});
if (1 <= Jpos.options.postcode.length) {
selector = Jpos.options.postcode[1];
$(selector).bind('keyup change', function () {
Jpos.main();
});
}
}
};
}(jQuery));