UNPKG

ionic

Version:

A tool for creating and developing Ionic Framework mobile apps.

244 lines (228 loc) • 8.84 kB
/* * * 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)) { throw new Error("cordova already defined"); } /*global symbolList*/ 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 = {}, 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; } var cordova = { platformVersion:PLATFORM_VERSION_BUILD_LABEL, version:PLATFORM_VERSION_BUILD_LABEL, require: require, platformId:platform.id, /** * 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;