function RemoGeoLocation() { this._remoteSvrUrl = 'https://webapi.amap.com/html/geolocate.html'; this._callbackList = []; this._seqBase = 1; this._frameReady = 0; this._watchIdMap = {}; } RemoGeoLocation.prototype = { _getSeq: function() { return this._seqBase++; }, _onRrameReady: function(callback) { if (this._frameReady === 0) { if (!this._frameReadyList) { this._frameReadyList = []; } this._frameReadyList.push(callback); this._prepareIframe(); return; } callback.call(this); }, _prepareIframe: function() { if (this._iframeWin) { return; } var ifrm = document.createElement('iframe'); ifrm.src = this._remoteSvrUrl + (this._remoteSvrUrl.indexOf('?') > 0 ? '&' : '?'); ifrm.width = '0px'; ifrm.height = '0px'; ifrm.style.position = 'absolute'; ifrm.style.display = 'none'; var self = this; var timeoutId = setTimeout(function() { self._frameReady = false; self._callbackFrameReadyList(); }, 5000); ifrm.onload = function() { clearTimeout(timeoutId); self._frameReady = true; self._callbackFrameReadyList(); ifrm.onload = null; }; document.body.appendChild(ifrm); this._iframeWin = ifrm.contentWindow; window.addEventListener('message', function(e) { if (self._remoteSvrUrl.indexOf(e['origin']) !== 0) { return; } self._handleRemoteMsg(e['data']); }, false); }, _callbackFrameReadyList: function() { if (this._frameReadyList) { var list = this._frameReadyList; this._frameReadyList = null; for (var i = 0, len = list.length; i < len; i++) { list[i].call(this, this._frameReady); } } }, _pickCallback: function(seqNum, keepInList) { var callbackList = this._callbackList; for (var i = 0, len = callbackList.length; i < len; i++) { var cbkInfo = callbackList[i]; if (seqNum === cbkInfo.seq) { if (!keepInList) { callbackList.splice(i, 1); } return cbkInfo; } } }, _handleRemoteMsg: function(msg) { var seqNum = msg['seq']; var cbkInfo = this._pickCallback(seqNum, !!msg['notify']); if (cbkInfo) { cbkInfo.cbk.call(null, msg['error'], msg['result']); } else { console.warn('Receive remote msg: ', msg); } }, _postMessage: function(cmd, args, callback, seq) { this._prepareIframe(); var msg = { 'cmd': cmd, 'args': args, 'seq': seq || this._getSeq() }; this._callbackList.push({ cbk: callback, seq: msg['seq'] }); this._onRrameReady(function() { if (this._frameReady === true) { try { this._iframeWin.postMessage(msg, '*'); } catch (e) { this._pickCallback(msg['seq']); callback(e); } } else { this._pickCallback(msg['seq']); callback({ 'message': 'iFrame load failed!' }); } }); }, 'getCurrentPosition': function(succHandler, errHandler, options) { this._postMessage('getCurrentPosition', [options], function(err, result) { if (err) { if (errHandler) { errHandler(err); } return; } if (succHandler) { succHandler(result); } }); }, 'watchPosition': function(succHandler, errHandler, options) { var watchKey = 'wk' + this._getSeq(), cmdSeq = this._getSeq(); this._watchIdMap[watchKey] = { stat: 0, seq: cmdSeq }; var self = this; this._postMessage('watchPosition', [options], function(err, result) { var id = null; if (result) { id = result['id']; } var watchInfo = self._watchIdMap[watchKey]; watchInfo.id = id; watchInfo.stat = 1; if (watchInfo.callbackList) { var list = watchInfo.callbackList; watchInfo.callbackList = null; for (var i = 0, len = list.length; i < len; i++) { list[i].call(self, id); } } if (err) { if (errHandler) { errHandler(err); } return; } if (succHandler) { succHandler(result['pos']); } }, cmdSeq); return watchKey; }, 'clearWatch': function(watchKey, callback) { if (!this._watchIdMap[watchKey]) { callback('Id not exists: ' + watchKey); return; } var watchInfo = this._watchIdMap[watchKey]; var self = this; function clearId(id) { self._postMessage('clearWatch', [id], function(err, result) { if (!err) { self._pickCallback(watchInfo.seq); delete self._watchIdMap[watchKey]; } if (callback) { callback(err, result); } }); } if (watchInfo.stat < 1) { if (!watchInfo.callbackList) { watchInfo.callbackList = []; } watchInfo.callbackList.push(function(id) { clearId(id); }); } else { clearId(watchInfo.id); } } };