| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| // Workaround for Windows 10 in hosted environment case |
| // http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object |
| if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef |
| throw new Error('cordova already defined'); |
| } |
| |
| var channel = require('cordova/channel'); |
| var platform = require('cordova/platform'); |
| |
| /** |
| * Intercept calls to addEventListener + removeEventListener and handle deviceready, |
| * resume, and pause events. |
| */ |
| var m_document_addEventListener = document.addEventListener; |
| var m_document_removeEventListener = document.removeEventListener; |
| var m_window_addEventListener = window.addEventListener; |
| var m_window_removeEventListener = window.removeEventListener; |
| |
| /** |
| * Houses custom event handlers to intercept on document + window event listeners. |
| */ |
| var documentEventHandlers = {}; |
| var windowEventHandlers = {}; |
| |
| document.addEventListener = function (evt, handler, capture) { |
| var e = evt.toLowerCase(); |
| if (typeof documentEventHandlers[e] !== 'undefined') { |
| documentEventHandlers[e].subscribe(handler); |
| } else { |
| m_document_addEventListener.call(document, evt, handler, capture); |
| } |
| }; |
| |
| window.addEventListener = function (evt, handler, capture) { |
| var e = evt.toLowerCase(); |
| if (typeof windowEventHandlers[e] !== 'undefined') { |
| windowEventHandlers[e].subscribe(handler); |
| } else { |
| m_window_addEventListener.call(window, evt, handler, capture); |
| } |
| }; |
| |
| document.removeEventListener = function (evt, handler, capture) { |
| var e = evt.toLowerCase(); |
| // If unsubscribing from an event that is handled by a plugin |
| if (typeof documentEventHandlers[e] !== 'undefined') { |
| documentEventHandlers[e].unsubscribe(handler); |
| } else { |
| m_document_removeEventListener.call(document, evt, handler, capture); |
| } |
| }; |
| |
| window.removeEventListener = function (evt, handler, capture) { |
| var e = evt.toLowerCase(); |
| // If unsubscribing from an event that is handled by a plugin |
| if (typeof windowEventHandlers[e] !== 'undefined') { |
| windowEventHandlers[e].unsubscribe(handler); |
| } else { |
| m_window_removeEventListener.call(window, evt, handler, capture); |
| } |
| }; |
| |
| function createEvent (type, data) { |
| var event = document.createEvent('Events'); |
| event.initEvent(type, false, false); |
| if (data) { |
| for (var i in data) { |
| if (data.hasOwnProperty(i)) { |
| event[i] = data[i]; |
| } |
| } |
| } |
| return event; |
| } |
| |
| /* eslint-disable no-undef */ |
| var cordova = { |
| platformVersion: PLATFORM_VERSION_BUILD_LABEL, |
| version: PLATFORM_VERSION_BUILD_LABEL, |
| require: require, |
| platformId: platform.id, |
| |
| /* eslint-enable no-undef */ |
| |
| /** |
| * Methods to add/remove your own addEventListener hijacking on document + window. |
| */ |
| addWindowEventHandler: function (event) { |
| return (windowEventHandlers[event] = channel.create(event)); |
| }, |
| addStickyDocumentEventHandler: function (event) { |
| return (documentEventHandlers[event] = channel.createSticky(event)); |
| }, |
| addDocumentEventHandler: function (event) { |
| return (documentEventHandlers[event] = channel.create(event)); |
| }, |
| removeWindowEventHandler: function (event) { |
| delete windowEventHandlers[event]; |
| }, |
| removeDocumentEventHandler: function (event) { |
| delete documentEventHandlers[event]; |
| }, |
| /** |
| * Retrieve original event handlers that were replaced by Cordova |
| * |
| * @return object |
| */ |
| getOriginalHandlers: function () { |
| return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener}, |
| 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}}; |
| }, |
| /** |
| * Method to fire event from native code |
| * bNoDetach is required for events which cause an exception which needs to be caught in native code |
| */ |
| fireDocumentEvent: function (type, data, bNoDetach) { |
| var evt = createEvent(type, data); |
| if (typeof documentEventHandlers[type] !== 'undefined') { |
| if (bNoDetach) { |
| documentEventHandlers[type].fire(evt); |
| } else { |
| setTimeout(function () { |
| // Fire deviceready on listeners that were registered before cordova.js was loaded. |
| if (type === 'deviceready') { |
| document.dispatchEvent(evt); |
| } |
| documentEventHandlers[type].fire(evt); |
| }, 0); |
| } |
| } else { |
| document.dispatchEvent(evt); |
| } |
| }, |
| fireWindowEvent: function (type, data) { |
| var evt = createEvent(type, data); |
| if (typeof windowEventHandlers[type] !== 'undefined') { |
| setTimeout(function () { |
| windowEventHandlers[type].fire(evt); |
| }, 0); |
| } else { |
| window.dispatchEvent(evt); |
| } |
| }, |
| |
| /** |
| * Plugin callback mechanism. |
| */ |
| // Randomize the starting callbackId to avoid collisions after refreshing or navigating. |
| // This way, it's very unlikely that any new callback would get the same callbackId as an old callback. |
| callbackId: Math.floor(Math.random() * 2000000000), |
| callbacks: {}, |
| callbackStatus: { |
| NO_RESULT: 0, |
| OK: 1, |
| CLASS_NOT_FOUND_EXCEPTION: 2, |
| ILLEGAL_ACCESS_EXCEPTION: 3, |
| INSTANTIATION_EXCEPTION: 4, |
| MALFORMED_URL_EXCEPTION: 5, |
| IO_EXCEPTION: 6, |
| INVALID_ACTION: 7, |
| JSON_EXCEPTION: 8, |
| ERROR: 9 |
| }, |
| /** |
| * Called by native code when returning successful result from an action. |
| */ |
| callbackSuccess: function (callbackId, args) { |
| this.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback); |
| }, |
| /** |
| * Called by native code when returning error result from an action. |
| */ |
| callbackError: function (callbackId, args) { |
| // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative. |
| // Derive success from status. |
| this.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback); |
| }, |
| /** |
| * Called by native code when returning the result from an action. |
| */ |
| callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) { |
| try { |
| var callback = cordova.callbacks[callbackId]; |
| if (callback) { |
| if (isSuccess && status === cordova.callbackStatus.OK) { |
| callback.success && callback.success.apply(null, args); |
| } else if (!isSuccess) { |
| callback.fail && callback.fail.apply(null, args); |
| } |
| /* |
| else |
| Note, this case is intentionally not caught. |
| this can happen if isSuccess is true, but callbackStatus is NO_RESULT |
| which is used to remove a callback from the list without calling the callbacks |
| typically keepCallback is false in this case |
| */ |
| |
| // Clear callback if not expecting any more results |
| if (!keepCallback) { |
| delete cordova.callbacks[callbackId]; |
| } |
| } |
| } catch (err) { |
| var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err; |
| console && console.log && console.log(msg); |
| this.fireWindowEvent('cordovacallbackerror', { 'message': msg }); |
| throw err; |
| } |
| }, |
| addConstructor: function (func) { |
| channel.onCordovaReady.subscribe(function () { |
| try { |
| func(); |
| } catch (e) { |
| console.log('Failed to run constructor: ' + e); |
| } |
| }); |
| } |
| }; |
| |
| window.cordova = module.exports = cordova; |