diff --git a/spec/coffee/providers/google-map-api-provider.spec.coffee b/spec/coffee/providers/google-map-api-provider.spec.coffee index 08b93d959..bdd6b356d 100644 --- a/spec/coffee/providers/google-map-api-provider.spec.coffee +++ b/spec/coffee/providers/google-map-api-provider.spec.coffee @@ -20,32 +20,60 @@ describe 'uiGmapGoogleMapApiProvider', -> it 'uses maps.google.cn when in china', -> options = { china: true, v: '3.17', libraries: '', language: 'en', sensor: 'false' } mapScriptLoader.load(options) + + loadEvent = document.createEvent 'CustomEvent' + loadEvent.initCustomEvent 'load', false, false, null + document.dispatchEvent loadEvent + lastScriptIndex = document.getElementsByTagName('script').length - 1 expect(document.getElementsByTagName('script')[lastScriptIndex].src).toContain('http://maps.google.cn/maps/api/js') describe 'on Cordova devices', -> beforeAll -> + window.cordova = {} window.navigator.connection = {} window.Connection = WIFI: 'wifi' NONE: 'none' - afterAll -> delete window.navigator.connection + afterAll -> + delete window.navigator.connection + delete window.cordova - it 'should include the script when the device is online', -> + it 'should wait for the deviceready event to include the script when the device is online', -> window.navigator.connection.type = window.Connection.WIFI options = { v: '3.17', libraries: '', language: 'en', sensor: 'false', device: 'online' } mapScriptLoader.load(options) + loadEvent = document.createEvent 'CustomEvent' + loadEvent.initCustomEvent 'load', false, false, null + document.dispatchEvent loadEvent + + lastScriptIndex = document.getElementsByTagName('script').length - 1 + expect(document.getElementsByTagName('script')[lastScriptIndex].src).not.toContain('device=online') + + readyEvent = document.createEvent 'CustomEvent' + readyEvent.initCustomEvent 'deviceready', false, false, null + document.dispatchEvent readyEvent + lastScriptIndex = document.getElementsByTagName('script').length - 1 expect(document.getElementsByTagName('script')[lastScriptIndex].src).toContain('device=online') - it 'should wait for the online event to include the script when the device is offline', -> + it 'should wait for the deviceready and online event to include the script when the device is offline', -> window.navigator.connection.type = window.Connection.NONE options = { v: '3.17', libraries: '', language: 'en', sensor: 'false', device: 'offline' } mapScriptLoader.load(options) + + loadEvent = document.createEvent 'CustomEvent' + loadEvent.initCustomEvent 'load', false, false, null + document.dispatchEvent loadEvent + + readyEvent = document.createEvent 'CustomEvent' + readyEvent.initCustomEvent 'deviceready', false, false, null + document.dispatchEvent readyEvent + lastScriptIndex = document.getElementsByTagName('script').length - 1 expect(document.getElementsByTagName('script')[lastScriptIndex].src).not.toContain('device=offline') diff --git a/src/coffee/providers/map-loader.coffee b/src/coffee/providers/map-loader.coffee index f0db7e376..6708cbb93 100644 --- a/src/coffee/providers/map-loader.coffee +++ b/src/coffee/providers/map-loader.coffee @@ -2,6 +2,7 @@ angular.module('uiGmapgoogle-maps.providers') .factory('uiGmapMapScriptLoader', ['$q', 'uiGmapuuid', ($q, uuid) -> scriptId = undefined + lastNetworkStatus = undefined getScriptUrl = (options)-> #china doesn't allow https and has a special url @@ -23,7 +24,10 @@ angular.module('uiGmapgoogle-maps.providers') query = _.map _.omit(options, omitOptions), (v, k) -> k + '=' + v - document.getElementById(scriptId).remove() if scriptId + if scriptId + scriptElem = document.getElementById(scriptId) + scriptElem.parentNode.removeChild(scriptElem) + query = query.join '&' script = document.createElement 'script' script.id = scriptId = "ui_gmap_map_load_#{uuid.generate()}" @@ -31,9 +35,33 @@ angular.module('uiGmapgoogle-maps.providers') script.src = getScriptUrl(options) + query document.body.appendChild script + isGoogleMapsLoaded = -> angular.isDefined(window.google) and angular.isDefined(window.google.maps) + isWebView = (obj = window) -> + !(!obj.cordova && !obj.PhoneGap && !obj.phonegap && !obj.forge) + + onWindowLoad = (options)-> + if isWebView() + document.addEventListener 'deviceready', -> + if window.navigator.connection.type == window.Connection.NONE + document.addEventListener 'online', -> + # Workaround for issue where in Android, network events are fired multiple times in a row + # https://issues.apache.org/jira/browse/CB-7787 + if !lastNetworkStatus || lastNetworkStatus != 'online' + lastNetworkStatus = 'online' + includeScript options if !isGoogleMapsLoaded() + + document.addEventListener 'offline', -> + lastNetworkStatus = 'offline' + + else + includeScript options + + else + includeScript options + load: (options)-> deferred = $q.defer() @@ -48,12 +76,12 @@ angular.module('uiGmapgoogle-maps.providers') deferred.resolve window.google.maps return - # Cordova specific https://github.com/apache/cordova-plugin-network-information/ - if window.navigator.connection && window.Connection && window.navigator.connection.type == window.Connection.NONE - document.addEventListener 'online', -> - includeScript options if !isGoogleMapsLoaded() + if document.readyState == 'complete' + onWindowLoad(options) else - includeScript options + window.addEventListener 'load', -> + window.removeEventListener 'load', onWindowLoad, false + onWindowLoad(options) # Return the promise deferred.promise