After toggleClass tap fails in Cordova app

Marco Gasi
Marco Gasi used Ask the Experts™
on
Hi all.
Iìm learning about Cordova apps. I'm trying to use a very basic example of a page using jquery and Bootstrap 3. The pge has a left sidebar and a button which makes the sidebar slideLeft and slideRight alternatively using toggleClass.
Once build the Cordova app, it works fine in my smartphone running Android 4.4.4, but in my tablet with Android 4.1.2, after the first tap, which works, the secons takes no effect.
The problem is present only if I try to toggle classes: with a simple alert, the app works. I also changed the code in order to change the body background color at each tapping and this also worked fine.
Have you any idea?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Web Developer/Designer
Commented:
Different versions of Android will have different versions of webview. My guess is that the older OS version doesn't support something that you're trying to do ( but without seeing everything I'm not sure what exactly ).

You may want to try using Genymotion to emultate different Android devices and different OS versions in order to figure out what the trouble could be.

This link appears to be a good resource for help with remote debugging of Cordova apps.
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Hi Brandon, thnk you for your response. I'll try Genymotion tomorrow. For the moment, if you want to take a look to the whole code, I post it here. It is really basic, just to implement the sidebar:

index.html
<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Simple Sidebar - Start Bootstrap Template</title>

    <!-- Bootstrap Core CSS -->
    <link href="css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom CSS -->
    <link href="css/simple-sidebar.css" rel="stylesheet">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

  </head>

  <body>

    <div id="wrapper">

      <!-- Sidebar -->
      <div id="sidebar-wrapper">
        <ul class="sidebar-nav">
          <li class="sidebar-brand">
            <a href="#">
              Start Bootstrap
            </a>
          </li>
          <li>
            <a href="#">Dashboard</a>
          </li>
          <li>
            <a href="#">Shortcuts</a>
          </li>
          <li>
            <a href="#">Overview</a>
          </li>
          <li>
            <a href="#">Events</a>
          </li>
          <li>
            <a href="#">About</a>
          </li>
          <li>
            <a href="#">Services</a>
          </li>
          <li>
            <a href="#">Contact</a>
          </li>
        </ul>
      </div>
      <!-- /#sidebar-wrapper -->

      <!-- Page Content -->
      <div id="page-content-wrapper" style="background-color:white;">
        <div class="container-fluid">
          <div class="row">
            <!--<div class="col-lg-12">-->
              <h1>Simple Sidebar</h1>
              <p>This template has a responsive menu toggling system. The menu will appear collapsed on smaller screens, and will appear non-collapsed on larger screens. When toggled using the button below, the menu will appear/disappear. On small screens, the page content will be pushed off canvas.</p>
              <p>Make sure to keep all page content within the <code>#page-content-wrapper</code>.</p>
              <a href="#" class="btn btn-default" id="menu-toggle">Toggle Menu</a>
          </div>
        </div>
      </div>
      <!-- /#page-content-wrapper -->

    </div>
    <!-- /#wrapper -->

    <!-- jQuery -->
    <script src="js/jquery.js"></script>

    <!-- Bootstrap Core JavaScript -->
    <script src="js/bootstrap.min.js"></script>
    <script src="js/index.js"></script>

    <!-- Menu Toggle Script -->
    <script>
      $(document).ready(function () {
        jQuery(document).on('click', "#menu-toggle", function (e) {
          e.preventDefault();
          jQuery("#wrapper").toggleClass("toggled");
        });
      });
    </script>

  </body>

</html>

Open in new window


simple-sidebar.css
/*!
 * Start Bootstrap - Simple Sidebar HTML Template (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

/* Toggle Styles */
#page-content-wrapper{
	background-color: white;
}
#wrapper {
    padding-left: 0;
    -webkit-transition: all 0.5s ease;
    -moz-transition: all 0.5s ease;
    -o-transition: all 0.5s ease;
    transition: all 0.5s ease;
}

#wrapper.toggled {
    padding-left: 250px;
}

#sidebar-wrapper {
    z-index: 1000;
    position: fixed;
    left: 250px;
    width: 0;
    height: 100%;
    margin-left: -250px;
    overflow-y: auto;
    background: #000;
    -webkit-transition: all 0.5s ease;
    -moz-transition: all 0.5s ease;
    -o-transition: all 0.5s ease;
    transition: all 0.5s ease;
}

#wrapper.toggled #sidebar-wrapper {
    width: 250px;
}

#page-content-wrapper {
    width: 100%;
    position: absolute;
    padding: 15px;
}

#wrapper.toggled #page-content-wrapper {
    position: absolute;
    margin-right: -250px;
}

/* Sidebar Styles */

.sidebar-nav {
    position: absolute;
    top: 0;
    width: 250px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.sidebar-nav li {
    text-indent: 20px;
    line-height: 40px;
}

.sidebar-nav li a {
    display: block;
    text-decoration: none;
    color: #999999;
}

.sidebar-nav li a:hover {
    text-decoration: none;
    color: #fff;
    background: rgba(255,255,255,0.2);
}

.sidebar-nav li a:active,
.sidebar-nav li a:focus {
    text-decoration: none;
}

.sidebar-nav > .sidebar-brand {
    height: 65px;
    font-size: 18px;
    line-height: 60px;
}

.sidebar-nav > .sidebar-brand a {
    color: #999999;
}

.sidebar-nav > .sidebar-brand a:hover {
    color: #fff;
    background: none;
}

@media(min-width:768px) {
    #wrapper {
        padding-left: 250px;
    }

    #wrapper.toggled {
        padding-left: 0;
    }

    #sidebar-wrapper {
        width: 250px;
    }

    #wrapper.toggled #sidebar-wrapper {
        width: 0;
    }

    #page-content-wrapper {
        padding: 20px;
        position: relative;
    }

    #wrapper.toggled #page-content-wrapper {
        position: relative;
        margin-right: 0;
    }
}

Open in new window


index.js
/*
 * 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.
 */
var app = {
	// Application Constructor
	initialize: function () {
		this.bindEvents();
	},
	// Bind Event Listeners
	//
	// Bind any events that are required on startup. Common events are:
	// 'load', 'deviceready', 'offline', and 'online'.
	bindEvents: function () {
		document.addEventListener('deviceready', this.onDeviceReady, false);
	},
	// deviceready Event Handler
	//
	// The scope of 'this' is the event. In order to call the 'receivedEvent'
	// function, we must explicitly call 'app.receivedEvent(...);'
	onDeviceReady: function () {
		app.receivedEvent('deviceready');
	},
	// Update DOM on a Received Event
	receivedEvent: function (id) {
		var parentElement = document.getElementById(id);
		var listeningElement = parentElement.querySelector('.listening');
		var receivedElement = parentElement.querySelector('.received');

		listeningElement.setAttribute('style', 'display:none;');
		receivedElement.setAttribute('style', 'display:block;');

		console.log('Received Event: ' + id);
	}
};

app.initialize();

		$(document).ready(function () {
			$(document).on('click', ' #menu-toggle', function (e) {
        e.preventDefault();
				if($('#wrapper').hasClass('toggled'))
				{
					alert('remove');
					$('#wrapper').removeClass('toggled');
				}
				else
				{
					alert('add');
				$('#wrapper').addClass('toggled');
				}
				if ($('#page-content-wrapper').css('background-color') == 'rgb(255, 255, 255)')
				{
					$('#page-content-wrapper').css('background-color', 'rgb(255, 0, 0)');
				}
				else if ($('#page-content-wrapper').css('background-color') == 'rgb(255, 0, 0)')
				{
					$('#page-content-wrapper').css('background-color', 'rgb(255, 255, 0)');
				}
				else if ($('#page-content-wrapper').css('background-color') == 'rgb(255, 255, 0)')
				{
					$('#page-content-wrapper').css('background-color', 'rgb(0, 255, 0)');
				}
				else if ($('#page-content-wrapper').css('background-color') == 'rgb(0, 255, 0)')
				{
					$('#page-content-wrapper').css('background-color', 'rgb(255, 255, 255)');
				}
				else 
				{
					alert('non funzia 2');
				}
			});
		});

Open in new window

Thank you again.
Brandon LyonWeb Developer/Designer

Commented:
The reason I suspected it's related to the older OS is because it works fine on the newer device.

There isn't anything in the CSS or HTML which jumps out at me as being incompatible with older devices.

Looking at the javascript, I do notice an extra space that shouldn't be there inside the index.js file. It's right before the #menu-toggle. I don't know if that matters or not. Syntax might parse correctly inside of a good browser and break inside of a bad one.

$(document).on('click', ' #menu-toggle', function (e) {...}

Open in new window


Other than that...

document.ready might not be triggering correctly
the click event might not be triggering correctly
e might not be passed or prevented correctly

I'm not super familiar with Cordova so I'm curious why a similar script functionality seems to exist twice, both in the index.js and the index.html. One of the on-click events might be overriding the other?
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
I'm not super familiar with Cordova so I'm curious why a similar script functionality seems to exist twice
That's a my mistake. In the original script it was in index.html: i has commented it out and added to index.js.Then posting here the code I forgot to comment or drop one of the two piexes of code :-)
Even the space in the selector is just a typo: the issue remains...
I thought it was due to oldier OS versions me too, but I hoped I can find a "cross-versions" workaround.
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Thank you Brandon.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial