Skip to content

Instantly share code, notes, and snippets.

@user20161119
Created July 1, 2014 10:05
Show Gist options
  • Save user20161119/049c4e685930e61a1552 to your computer and use it in GitHub Desktop.
Save user20161119/049c4e685930e61a1552 to your computer and use it in GitHub Desktop.
(function($) {
$.Address = {
Share: {
initialRegion: function () {
_initialRegion();
},
callback:function(){},
geoGPSInfo: {},
geoIPInfo: {}
},
defaults: {
debug: false,
maxHeight: 0,
maxItem: 0,
platform: 'web',
isfilter:true,
limit:Number.MAX_VALUE,
autocompleteOption: {
minLength: 5,
},
mapOption: { sensor: false, language: 'en', },
callback: function () { },
},
onPhone:{
remote: ''
},
online: {
searchArea: true,
isExtend: true,
zeroCallback: function () { }
}
};
//get geoip
//private fields
var googleGeocodeApiUrl = 'http://maps.googleapis.com/maps/api/geocode/json';
var googleDistancematrixApiUrl = 'http://maps.googleapis.com/maps/api/distancematrix/json';
//private method
var _geoCode = function (mapOption, getGeoCallback) {
if (!(mapOption && (mapOption.address || mapOption.latlng))) {
$.error('address or latlng is required.');
}
$.getJSON(googleGeocodeApiUrl, mapOption, function (data) {
if (getGeoCallback != null){
getGeoCallback(data.results, data.status);
}
});
};
var _getRegionByGPS = function () {
var timeout= 5000,isTimeout=false;
useIpGeo();
if (window.navigator.geolocation){
if ($.Address.Share.geoGPSInfo.region) {
$.Address.Share.callback.call(null, 'GPS', $.Address.Share.geoGPSInfo.latitude, $.Address.Share.geoGPSInfo.longitude);//call geolocation again
}
else {
setTimeout(function(){
error_callback();
},timeout);
navigator.geolocation.getCurrentPosition(success_callback, error_callback);
}
}
function useIpGeo(){
var geoIPInfoInterval = window.setInterval(function () {
if (!$.Address.Share.geoIPInfo.region) {
if (window.geoip_region_name) {
$.Address.Share.geoIPInfo = {
region: geoip_region_name(),
latitude: geoip_latitude(),
longitude: geoip_longitude()
};
}
}
else {
window.clearInterval(geoIPInfoInterval);
$.Address.Share.callback.call(null, 'IP',geoip_latitude(), geoip_longitude());
}
}, 100);
};
function success_callback(position) {
var tmpMapOption = {};
$.extend(tmpMapOption, $.Address.defaults.mapOption, { latlng: position.coords.latitude + ',' + position.coords.longitude });
$.Address.Share.callback.call(null, 'GPS',position.coords.latitude, position.coords.longitude);
_geoCode(tmpMapOption, function (results, status) {
if (status === 'OK') {
var addr, types, addrIndex, addrType,
levels, lvlIndex, lvladdr, lvlTypes, lvltype;
for (addrIndex in results) {
addr = results[addrIndex],
types = addr.types;
for (addrType in types) {
if (types[addrType] === 'locality') {
levels = addr.address_components;
for (lvlIndex in levels) {
lvladdr = levels[lvlIndex];
lvlTypes = lvladdr.types;
for (lvltype in lvlTypes) {
if (lvlTypes[lvltype] === 'locality') {
$.Address.Share.geoGPSInfo = {
region: lvladdr.short_name
};
$.extend($.Address.Share.geoGPSInfo, position.coords);
return;
}
}
}
}
}
}
}
});
};
function error_callback(position) {
if(!isTimeout){
isTimeout=true;
if (typeof geoip_city !== 'function') {
$.getScript("http://j.maxmind.com/app/geoip.js");
}
}
};
};
var _initialRegion = function () {
_getRegionByGPS();
};
var _iniAutoComplate = function ($e, Option) {
var autoCompleteWrapper, autoComplete, uuid,
tmpOption = Option;
$e.autocomplete(tmpOption.autocompleteOption);
uuid = $('.ui-autocomplete:not(.auto-used)').attr('id');
if (tmpOption.platform.toUpperCase() === 'MOBILE') {
if (iScroll) {
var maxheight = (+tmpOption.maxHeight) ? 'max-height:' + tmpOption.maxHeight + 'px' : '';
$('.ui-autocomplete:not(.auto-used)')
.css('position', 'static')
.addClass('auto-used')
.wrap('<div id="wrapper-' + uuid + '" class="addresses-Wrapper" style="text-align: left;position:absolute;' + maxheight + '"/>')
.wrap('<div id="scroll-' + uuid + '"/>');
autoComplete = $('#wrapper-' + uuid);
autoCompleteWrapper = new iScroll('wrapper-' + uuid, {
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
}
else {
$.error('iScroll plugin is required.');
}
}
else {
if (+tmpOption.maxHeight) {
autoComplete = $('.ui-autocomplete:not(.auto-used)').css({
'overflow-y': 'auto',
'text-align': 'left',
'max-height': +tmpOption.maxHeight + 'px'
});
}
}
$($e).trigger('initialized', [autoComplete]);
return {
autoCompleteWrapper: autoCompleteWrapper
, autoComplete: autoComplete
};
};
//get Region
_initialRegion();
// Constructor
var Address = function ($e, options) {
var _namespaces = 'jaddress',
_data = $e.data('jaddress'),
_userOptions = (typeof options === 'function') ? { callback: options } : options,
_addressOption = {
address: ''
, suite: ''
, street: ''
, city: ''
, state: ''
, country: ''
, zip: ''
, lat: NaN
, lng: NaN
},
_$autoCompleteMenu,
_options = $.extend({}, $.Address.defaults,$.Address.online, _userOptions, _data || {}, { address: _addressOption },_iniMethod()),
_$element = $e;
$e.data('jaddress', $.extend({}, _data, { initialized: true, waiting: false }, _options));
_load();
function _load() {
_$autoCompleteMenu=_iniAutoComplate(_$element, _Data({ autocompleteOption: _getAutoComplateOption() }));
_$element.bind('keyup', function (e) {
if (_$element.val() !== _$element.data('jaddress').address.address) {
_iniAddress();
}
});
};
function _Data(data) {
var tmpOption = _$element.data(_namespaces);
if (data) {
tmpOption = $.extend(true,tmpOption, data);
_$element.data(_namespaces, tmpOption);
}
return tmpOption;
};
function _iniAddress() {
var tmpOption = _$element.data('jaddress');
tmpOption.address = {
address: ''
, suite: ''
, street: ''
, city: ''
, state: ''
, country: ''
, zip: ''
, lat: NaN
, lng: NaN
};
_$element
.data('jaddress', tmpOption)
.trigger('iniAddressed',[]);
return;
}
/*function _combinAddress(results, status) {
if (status === "OK") {
addressList = [];
for (var i in results) {
var address;
address = _analyzeAddress(results[i]);
if (!$.isEmptyObject(address)) {
addressList.push({ value: address.address,data:address});
}
}
return addressList;
}
else {//if (data.status === 'ZERO_RESULTS') {
//zeroCallback();
}
}*/
// Private methods
function _combinAddress(mapOption, callback) {
callback = callback || function () { };
_geoCode(mapOption, function (results,status) {
if (status === "OK") {
addressList = [];
for (var i in results) {
var address;
if(_Data().isfilter){
address= _analyzeAddress(results[i]);
}
else{
address= _directAddress(results[i]);
}
if (!$.isEmptyObject(address)&&addressList.length<=_Data().limit) {
addressList.push(address);
}
}
callback(addressList);
}
else {//if (data.status === 'ZERO_RESULTS') {
//zeroCallback();
}
});
};
function _directAddress(googleAddress){
return _formatAddress(googleAddress);
};
function _formatAddress(googleAddress){
var _address={};
if (googleAddress.address_components != null && googleAddress.address_components.length > 0) {
for (var index in googleAddress.address_components) {
var val = googleAddress.address_components[index];
if (val.types[0] == "street_number") {
//_address.suite = val.long_name;
_address.suite = val.short_name;
} else if (val.types[0] == "route") {
_address.street = val.long_name;
//_address.street = val.short_name;
} else if (val.types[0] == "neighborhood") {
//_address.street = val.long_name;
} else if (val.types[0] == "locality") {
_address.city = val.long_name;
//_address.city = val.short_name;
} else if (val.types[0] == "sublocality") {
_address.street = (_address.street&&(_address.street + ', ')||'') + val.long_name;
//_address.city = val.short_name;
} else if (val.types[0] == "administrative_area_level_1") {
//_address.state = val.long_name;
_address.state = val.short_name;
} else if (val.types[0] == "administrative_area_level_2") {
//_address.street = val.long_name;
} else if (val.types[0] == "administrative_area_level_3") {
//_address.street = val.long_name;
} else if (val.types[0] == "country") {
//_address.country = val.long_name;
_address.country = val.short_name;
} else if (val.types[0] == "postal_code") {
_address.zip = val.long_name;
}
}
_address.lat = googleAddress.geometry.location.lat;
_address.lng = googleAddress.geometry.location.lng;
_address.address = googleAddress.formatted_address;// _address.suite + ' ' + _address.street + ' ' + _address.city + ', ' + _address.state + ' ' + _address.zip;
}
return _address;
};
function _analyzeAddress(googleAddress) {
var _address = {};
var _analyzeAccurate = function (googleAddress) {
_address=_formatAddress(googleAddress);
};
var _analyzeApproximate = function (googleAddress) {
if (googleAddress.types != null && googleAddress.types.length > 0) {
var isMatch = false;
for (index in googleAddress.types) {
if (googleAddress.types[index] == "subpremise" ||
googleAddress.types[index] == "premise" ||
googleAddress.types[index] == "street_address" ||
googleAddress.types[index] == "route") {
isMatch = true;
}
}
if (isMatch) {
_address=_formatAddress(googleAddress);
}
}
};
if (googleAddress) {
switch (googleAddress.geometry.location_type) {
case "ROOFTOP":
case "RANGE_INTERPOLATED":
case "GEOMETRIC_CENTER":
_analyzeAccurate(googleAddress);
break;
case "APPROXIMATE":
_analyzeApproximate(googleAddress);
break;
}
}
return _address;
};
function _iniMethod(){
return {
isValid: function () {
var _option = _$element.data('jaddress'),
tmpaddress = _option.address;
if (+tmpaddress.lat && +tmpaddress.lng && _$element.val() === tmpaddress.address) {
return true;
}
return false;
}
};
}
function _refreshWrapper() {
_$autoCompleteMenu.autoCompleteWrapper && _$autoCompleteMenu.autoCompleteWrapper.refresh();
};
function _getAutoComplateOption() {
return {
source: function (request, response) {
var tmpOption = _$element.data('jaddress'),
tmpMapOption = {},
addsearch = '';
if (tmpOption.searchArea) {
addsearch = $.Address.Share.geoIPInfo.region || $.Address.Share.geoGPSInfo.region || '';
}
$.extend(tmpMapOption, tmpOption.mapOption, { address: request.term + ' ' + addsearch });
_combinAddress(tmpMapOption, function (data) {
var _renderAddress = function (data) {
if (+tmpOption.maxItem) {
data = data.slice(0, +tmpOption.maxItem);
}
response($.map(data, function (item) {
return {
label: item.address,
value: item.address,
address: item
};
}));
_refreshWrapper();
};
if (data.length === 0 && addsearch && tmpOption.isExtend && tmpOption.searchArea) {
var tmpMapOption = {};
$.extend(tmpMapOption, tmpOption.mapOption, { address: request.term });
_combinAddress(tmpMapOption, function (data) {
_renderAddress(data);
});
} else {
_renderAddress(data);
}
});
},
select: function (event, ui) {
var _option = _$element.data('jaddress');
$.extend(_option.address, ui.item.address);
_$element.data('jaddress', _option);
_$element.val(ui.item.address.address);
if (_option.callback) {
_option.callback.call(_$element[0], ui.item.address);
}
},
open: function () {
_iniAddress();
//$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
}
};
};
// Remove the jaddress behavior and data from an element
function _destroy() {
return _$element.removeData('jaddress');
}
// Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript
function _debug(m) {
if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) {
if (typeof m === 'object') {
var args = [];
for (var sMethod in m) {
if (typeof console[sMethod] === 'function') {
args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]];
console[sMethod].apply(console, args);
} else {
console.log.apply(console, args);
}
}
} else {
console[m].apply(console, Array.prototype.slice.call(arguments, 1));
}
}
}
// Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method()
$.extend($e.jscroll, {
destroy: _destroy
});
return $e;
};
var Contact = function ($e, options) {
var _namespaces = 'jcontact',
_data = $e.data(_namespaces),
_userOptions = (typeof options === 'function') ? { callback: options } : options,
_contactOption = {
address: ''
, suite: ''
, street: ''
, city: ''
, state: ''
, country: ''
, zip: ''
, lat: NaN
, lng: NaN
, contact_name: ''
, contact_phone:''
},
_$autoCompleteMenu,
_options = $.extend({}, $.Address.defaults,$.Address.onPhone, _userOptions, _data || {}, { contact: _contactOption }, _iniMethod()),
_$contact = $e;
$e.data(_namespaces, $.extend({}, _data, { initialized: true, waiting: false }, _options));
_load();
function _iniMethod() { };
function _iniContact() {
_contactOption = {
address: ''
, suite: ''
, street: ''
, city: ''
, state: ''
, country: ''
, zip: ''
, lat: NaN
, lng: NaN
, contact_name: ''
, contact_phone: ''
},
_Data({ contact: _contactOption });
_$contact.trigger('iniContacted', []);
return;
};
function _load() {
_$autoCompleteMenu = _iniAutoComplate(_$contact, _Data({ autocompleteOption: _getAutoComplateOption() }));
_$contact.bind('keyup', function (e) {
if ($(this).val() !== _Data().contact.contact_phone) {
_iniContact();
}
});
};
//@FIXME quick search address book janwen
function _getAutoComplateOption() {
return {
source: function (request, response) {
$.get(_Data().remote, { params: JSON.stringify({ phoneOrNameOrAddress: request.term }) }, function (data) {
if (data.status === 'SUCCESS') {
response($.map(data.data, function (item) {
return {
label: item.foramt_address,
value: item.foramt_address,
contact: item
};
}));
_refreshWrapper();
}
});
},
select: function (event, ui) {
var tmpOption=_Data({ contact: ui.item.contact });
if (tmpOption.callback) {
tmpOption.callback.call(_$contact[0], ui.item.contact);
}
},
open: function () {
_iniContact();
//$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
//var phone=_Data().contact.contact_phone;
//if(phone){
// _$contact.val(phone);
//}
}
}
};
function _Data(data) {
var tmpOption = _$contact.data(_namespaces);
if (data) {
tmpOption = $.extend(true, tmpOption, data);
_$contact.data(_namespaces, tmpOption);
}
return tmpOption;
};
function _refreshWrapper() {
_$autoCompleteMenu.autoCompleteWrapper && _$autoCompleteMenu.autoCompleteWrapper.refresh();
};
};
$.fn.address = function (option, m, params) {
if (typeof option === 'string') {
var $this = $(this),
data = $this && $this.data('jaddress');
if (!data) {
$.error('address is not initialized.');
}
result = data[option];
if (m !== undefined) {//set
if ($.isPlainObject(result)) {
$.extend(result, m);
if (option === 'address') {
$this.val(result.address);//no check
}
}
else {
data[option] = m;
}
$this.data('jaddress', data);
}
else {//get
if(typeof result ==='function'){
return result.call(this, params);
}
else{
return result;
}
}
}
else {
m = option;
}
return this.each(function() {
var $this = $(this),
data = $this.data('jaddress');
// Instantiate jScroll on this element if it hasn't been already
if (data && data.initialized) return;
var address = new Address($this, m);
});
};
$.fn.contact = function (option, m, params) {
if (typeof option === 'string') {
var $this = $(this),
data = $this && $this.data('jcontact');
if (!data) {
$.error('contact is not initialized.');
}
result = data[option];
if (m !== undefined) {//set
if ($.isPlainObject(result)) {
$.extend(result, m);
}
else {
data[option] = m;
}
$this.data('jcontact', data);
}
else {//get
if (typeof result === 'function') {
return result.call(this, params);
}
else {
return result;
}
}
}
else {
m = option;
}
return this.each(function () {
var $this = $(this),
data = $this.data('jcontact');
// Instantiate jScroll on this element if it hasn't been already
if (data && data.initialized) return;
var contact = new Contact($this, m);
});
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment