This repository has been archived by the owner. It is now read-only.

Cannot read property 'hideKeyboardAccessoryBar' of undefined in Ripple Emulator #18

Closed
andycaramba opened this Issue May 29, 2014 · 11 comments

Comments

Projects
None yet
6 participants
@andycaramba

andycaramba commented May 29, 2014

Hi. I get the following error when trying to run the ionic app with this plugin in the Ripple emulator. Other plugins do not cause such error.

missing exec:Keyboard.hideKeyboardAccessoryBar ripple.js:34331
Array[1]
 ripple.js:34332
TypeError
message: "Cannot read property 'hideKeyboardAccessoryBar' of undefined"
stack: (...)
get stack: function () { [native code] }
set stack: function () { [native code] }
__proto__: Error
 ripple.js:34333
TypeError: Cannot read property 'hideKeyboardAccessoryBar' of undefined
    at module.exports.exec (http://localhost:4400/ripple/assets/ripple.js:34328:30)
    at Function.Keyboard.hideKeyboardAccessoryBar (http://localhost:4400/plugins/com.ionic.keyboard/www/keyboard.js:10:5)
    at http://localhost:4400/js/app.js:14:42
    at Array.<anonymous> (http://localhost:4400/vendor/ionic/js/ionic.bundle.js:36865:19)
    at onPlatformReady (http://localhost:4400/vendor/ionic/js/ionic.bundle.js:2329:24)
    at Channel.fire (http://localhost:4400/cordova.js:760:23)
    at http://localhost:4400/cordova.js:223:49 ripple.js:34334
Keyboard ripple.js:50497
hideKeyboardAccessoryBar ripple.js:50498

I use autogenerated code on app run

.run(function ($ionicPlatform) {
        $ionicPlatform.ready(function () {
            // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
            // for form inputs)
            if (window.cordova && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
            }
            if (window.StatusBar) {
                // org.apache.cordova.statusbar required
                StatusBar.styleDefault();
            }
        });
    })
@tlancina

This comment has been minimized.

Show comment
Hide comment
@tlancina

tlancina May 29, 2014

Member

It looks like Ripple has some plugins predefined and emulates their functionality (device, camera, file, etc.), but doesn't support custom plugins since it's not a real device. This error is a little scary because it's so verbose, but all it is saying is that the keyboard plugin is not on the list of plugins bundled in with Ripple, which is fine since it is running in a browser so there is no keyboard anyway.

It does allow you to manually fake a callback by entering in json data into the textarea that pops up, but in this case that's not necessary because there is no callback for any of the keyboard plugin functions :)

Member

tlancina commented May 29, 2014

It looks like Ripple has some plugins predefined and emulates their functionality (device, camera, file, etc.), but doesn't support custom plugins since it's not a real device. This error is a little scary because it's so verbose, but all it is saying is that the keyboard plugin is not on the list of plugins bundled in with Ripple, which is fine since it is running in a browser so there is no keyboard anyway.

It does allow you to manually fake a callback by entering in json data into the textarea that pops up, but in this case that's not necessary because there is no callback for any of the keyboard plugin functions :)

@tlancina tlancina closed this May 29, 2014

@andycaramba

This comment has been minimized.

Show comment
Hide comment
@andycaramba

andycaramba May 29, 2014

Thanks for the explanation. It's really annoying popup and I had to comment out a block with the plugin on development.

andycaramba commented May 29, 2014

Thanks for the explanation. It's really annoying popup and I had to comment out a block with the plugin on development.

@tlancina

This comment has been minimized.

Show comment
Hide comment
@tlancina

tlancina May 29, 2014

Member

Yeah it's pretty annoying, if you're switching between ripple and devices you could add something like

var annoyingDialog = parent.document.getElementById('exec-dialog');
if ( annoyingDialog ) annoyingDialog.outerHTML = "";

so you don't have to comment out custom plugin code every time you switch environments.

Member

tlancina commented May 29, 2014

Yeah it's pretty annoying, if you're switching between ripple and devices you could add something like

var annoyingDialog = parent.document.getElementById('exec-dialog');
if ( annoyingDialog ) annoyingDialog.outerHTML = "";

so you don't have to comment out custom plugin code every time you switch environments.

@andycaramba

This comment has been minimized.

Show comment
Hide comment
@andycaramba

andycaramba May 29, 2014

Your solution is pretty clever and more helpful. It allows to get rid of other annoying Ripple dialogs. Thanks for sharing.

andycaramba commented May 29, 2014

Your solution is pretty clever and more helpful. It allows to get rid of other annoying Ripple dialogs. Thanks for sharing.

@wocar

This comment has been minimized.

Show comment
Hide comment
@wocar

wocar May 20, 2015

@tlancina Thank you so much,

wocar commented May 20, 2015

@tlancina Thank you so much,

@rodrigobotti

This comment has been minimized.

Show comment
Hide comment
@rodrigobotti

rodrigobotti Sep 23, 2015

I know it's an old post but here's my solution to hide ripple's popup entirely:

var dialogBody = parent.document.getElementById("exec-dialog");
var overlay = parent.document.querySelector(".ui-widget-overlay");
var ngDialog = angular.element(dialogBody.parentElement);
var ngOverlay = angular.element(overlay);
var hideRules = { "height": "0px", "width": "0px", "display": "none" };
ngDialog.css(hideRules); // hide annoying popup
ngOverlay.css(hideRules); // hide annoying popup's backdrop

PS: I ommited the if checks for the sake of demostration.

rodrigobotti commented Sep 23, 2015

I know it's an old post but here's my solution to hide ripple's popup entirely:

var dialogBody = parent.document.getElementById("exec-dialog");
var overlay = parent.document.querySelector(".ui-widget-overlay");
var ngDialog = angular.element(dialogBody.parentElement);
var ngOverlay = angular.element(overlay);
var hideRules = { "height": "0px", "width": "0px", "display": "none" };
ngDialog.css(hideRules); // hide annoying popup
ngOverlay.css(hideRules); // hide annoying popup's backdrop

PS: I ommited the if checks for the sake of demostration.

@nsw2206

This comment has been minimized.

Show comment
Hide comment
@nsw2206

nsw2206 Oct 5, 2015

Hi,
where exactly does this code go? I've tried the start of
$ionicPlatform.ready(function() {
in app.js but still the popup.. :(
and where were the if checks omitted?
thanks in advance

nsw2206 commented Oct 5, 2015

Hi,
where exactly does this code go? I've tried the start of
$ionicPlatform.ready(function() {
in app.js but still the popup.. :(
and where were the if checks omitted?
thanks in advance

@rodrigobotti

This comment has been minimized.

Show comment
Hide comment
@rodrigobotti

rodrigobotti Oct 5, 2015

Hi @nsw2206.To address you questions:

  • where were the if checks ommited ?
    • after getting the reference to ripple's dialog's DOM nodes I didn't check to see if they were actually not undefined (and they will be undefined in a real device or device emulator) such as adding if (!dialogBody) return; to the code above.
    • what I actualy end up using is a function to check if the code is running in a ripple simulated environment so I don't actually have to manually check if each dialog node I'm referencing actually exists
  • where exactly does this code go?
    • I put it in the callback of $ionicPlatform.ready just like yourself. I did one thing different though: executed the code inside a $timeout with 0ms of interval ('trick' to schedule the function's execution in the event bus)
  • In the end I have something like this:
// I define this as a global function since I use it in other places
function isRunningInRipple(){
   // in an actual device(or emulator) all url's in the webview are 'file:// ... ' (since I don't load any external urls)
   return document.URL.indexOf('http://') >= 0 || document.URL.indexOf('https://') >= 0;
}

var app =  angular.module('myApp', [ ' ...dependencies...' ]);
app.run(['$ionicPlatform', '$timeout', '...other services...', function($ionicPlatform, $timeout, ...other services...){

  function disableRipplePopup() {
    var dialogBody = parent.document.getElementById("exec-dialog");
    var overlay = parent.document.querySelector(".ui-widget-overlay");
    var ngDialog = angular.element(dialogBody.parentElement);
    var ngOverlay = angular.element(overlay);
    var hideRules = { "height": "0px", "width": "0px", "display": "none" };
    ngDialog.css(hideRules); // hide annoying popup
    ngOverlay.css(hideRules); // hide annoying popup's backdrop
  }

  $ionicPlatform.ready(function(){
    // ... some app bootstrap code    

    if(isRunningInRipple()) $timeout(disableRipplePopup);

   // ...  more app bootstrap code
  });

}]);

EDIT: adressed @nsw2206 comments:

  • changed isRippleEmulator to isRunningInRipple
  • added $timeout service dependency in app.run

rodrigobotti commented Oct 5, 2015

Hi @nsw2206.To address you questions:

  • where were the if checks ommited ?
    • after getting the reference to ripple's dialog's DOM nodes I didn't check to see if they were actually not undefined (and they will be undefined in a real device or device emulator) such as adding if (!dialogBody) return; to the code above.
    • what I actualy end up using is a function to check if the code is running in a ripple simulated environment so I don't actually have to manually check if each dialog node I'm referencing actually exists
  • where exactly does this code go?
    • I put it in the callback of $ionicPlatform.ready just like yourself. I did one thing different though: executed the code inside a $timeout with 0ms of interval ('trick' to schedule the function's execution in the event bus)
  • In the end I have something like this:
// I define this as a global function since I use it in other places
function isRunningInRipple(){
   // in an actual device(or emulator) all url's in the webview are 'file:// ... ' (since I don't load any external urls)
   return document.URL.indexOf('http://') >= 0 || document.URL.indexOf('https://') >= 0;
}

var app =  angular.module('myApp', [ ' ...dependencies...' ]);
app.run(['$ionicPlatform', '$timeout', '...other services...', function($ionicPlatform, $timeout, ...other services...){

  function disableRipplePopup() {
    var dialogBody = parent.document.getElementById("exec-dialog");
    var overlay = parent.document.querySelector(".ui-widget-overlay");
    var ngDialog = angular.element(dialogBody.parentElement);
    var ngOverlay = angular.element(overlay);
    var hideRules = { "height": "0px", "width": "0px", "display": "none" };
    ngDialog.css(hideRules); // hide annoying popup
    ngOverlay.css(hideRules); // hide annoying popup's backdrop
  }

  $ionicPlatform.ready(function(){
    // ... some app bootstrap code    

    if(isRunningInRipple()) $timeout(disableRipplePopup);

   // ...  more app bootstrap code
  });

}]);

EDIT: adressed @nsw2206 comments:

  • changed isRippleEmulator to isRunningInRipple
  • added $timeout service dependency in app.run
@nsw2206

This comment has been minimized.

Show comment
Hide comment
@nsw2206

nsw2206 Oct 6, 2015

thanks rodrigo. a thousand noobs will appreciate this :)
I know I do... 👍

nsw2206 commented Oct 6, 2015

thanks rodrigo. a thousand noobs will appreciate this :)
I know I do... 👍

@nsw2206

This comment has been minimized.

Show comment
Hide comment
@nsw2206

nsw2206 Oct 6, 2015

two changes - add $timeout to the app.run line to avoid $timeout undefined and isRunningInRipple, not isRippleEmulator

app.run(function($ionicPlatform,$timeout) {
and
if(isRunningInRipple()) $timeout(disableRipplePopup);

nsw2206 commented Oct 6, 2015

two changes - add $timeout to the app.run line to avoid $timeout undefined and isRunningInRipple, not isRippleEmulator

app.run(function($ionicPlatform,$timeout) {
and
if(isRunningInRipple()) $timeout(disableRipplePopup);

@amilino

This comment has been minimized.

Show comment
Hide comment
@amilino

amilino Jun 3, 2016

I would remove display attribute, because it affects on your browser. Side effect is that you cannot for instance refresh page by pressing F5 in your browser or Ctrl+F5...

Before
var hideRules = { "height": "0px", "width": "0px", "display": "none" };

New
var hideRules = { "height": "0px", "width": "0px" };

amilino commented Jun 3, 2016

I would remove display attribute, because it affects on your browser. Side effect is that you cannot for instance refresh page by pressing F5 in your browser or Ctrl+F5...

Before
var hideRules = { "height": "0px", "width": "0px", "display": "none" };

New
var hideRules = { "height": "0px", "width": "0px" };

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.