Page specific scripts are not loading with jquery mobile - jquery-mobile

I'm using jquery mobile and phonegap to create an android application. I followed the short guide "20 Recipes for Programming Phonegap" which recommends using a callback from a custom script loaded on index.html to a function named onPageLoad() where Page is the name of the destination page's html file.
I'm stuck however, because the javascript, which I included inside the data-role="page" div with a script tag, is not loading.
https://stackoverflow.com/a/8838639/153382 points to the jQuery mobile guide that says this should work. I've read the guide, it's not working. Now what?
Has something changed with jquery mobile that makes this no longer work?
Update
Some testing shows that inline scripts run, but the script src attribute is not being evaluated for the script I am trying to load from a file.
also tried <script type="text/javascript">$.getScript("js/lookup.js");</script>. It did not work either.
code
common.js included on index.html after <div data-role="page">...</div>:
<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery.mobile-1.1.0.min.js"></script>
<script type="text/javascript" charset="utf-8" src="js/common.js"></script>
relevant contents of common.js:
function executeCallback() {
if (isPhoneGapReady) {
// get name of current html page
var pages = currentUrl.split("/");
var currentPage = pages[pages.length - 1].
slice(0, pages[pages.length - 1].indexOf(".html"));
// captalize the first letter and execute the function
currentPage = currentPage.charAt(0).toUpperCase() +
currentPage.slice(1);
if (typeof window['on' + currentPage + 'Load'] ==
typeof(Function)) {
window['on' + currentPage + 'Load']();
}
alert('on' + currentPage + 'Load: ' + typeof window['on' + currentPage + 'Load']);
// says onLookupLoad: undefined
}
}
$(document).bind("pageload", function(event, data) {
init(data.url);
});
window.onload = init;
init(url) calls onDeviceReady() which calls executeCallback()
lookup.html includes the following line inside <div data-role="page">:
<script type="text/javascript" charset="utf-8" src="js/lookup.js"></script>

Seems as if the issue was that Eclipse was not generating a new apk. I guess this is because the assets directory changed, but the src directory had not. If I delete the apk in the bin folder and run the emulator my code works as designed.

Related

How to use html templates in electron framework?

I need to build a cross platform app with multiple windows. So I would like to know how to use html templates in electron.
Based on a similar question and what I've seen, there's no built in html template language in Electron, which is actually great because it allows you to use any other template language.
I'm currently playing with ejs in Electron.
Below is my index.ejs template file:
<html lang="en">
<head>
<title>The Index Page</title>
</head>
<body>
<h1>Welcome, this is the Index page.</h1>
<% if (user) { %>
<h3>Hello there <%= user.name %></h3>
<% } %>
</body>
</html>
And below is a section of my main.js file where the above template is rendered and loaded onto the BrowserWindow. Note that I've left out most of the boilerplate code:
const ejs = require('ejs');
//... Other code
let win = new BrowserWindow({width: 800, height: 600});
//... Other code
// send the data and options to the ejs template
let data = {user: {name: "Jeff"}};
let options = {root: __dirname};
ejs.renderFile('index.ejs', data, options, function (err, str) {
if (err) {
console.log(err);
}
// Load the rendered HTML to the BrowserWindow.
win.loadURL('data:text/html;charset=utf-8,' + encodeURI(str));
});
I'll give some credit to this gist for helping me find the data:text/html;charset=utf-8 part of the url that can be used to load dynamic content.
UPDATE
I'm actually not using this anymore. It's faster to just load the default html and use the native DOM methods. The Electron Quickstart program shows how to do this nicely.
Another option is to do the templating during your build. Here is a simple example using gulp to add nonces to the CSP meta tag and the inline script.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-<%= scriptNonce %>';">
<title>Basic Electron App</title>
</head>
<body>
<div id="app"></div>
<script type="application/javascript" nonce=<%= scriptNonce %>>
require('./index.js');
</script>
</body>
</html>
and in gulfile.js add the following to what you already have and make sure this task is included in your pipeline. You can also just update your current html task with the code below.
const template = require('gulp-template');
const uuidv4 = require('uuid/v4');
gulp.task('copy-html', () => {
// Create nonces during the build and pass them to the template for use with inline scripts and styles
const nonceData = {
scriptNonce: new Buffer(uuidv4()).toString('base64'),
styleNonce: new Buffer(uuidv4()).toString('base64')
};
return gulp.src('src/*.html')
.pipe(template(nonceData))
.pipe(gulp.dest('dist/'));
});
This is a very stripped down example. I have a more complete example at https://github.com/NFabrizio/data-entry-electron-app if anyone is interested, though there is still one warning when running the application because one of the packages I am using pulls in react-beautiful-dnd, which adds inline styles but does not currently accept nonces.

How to access cordova functions from an IFrame in phonegap IOS

IN my Phonegap ios project i have an i frame and src of Iframe is a local html page within the same www folder . inside the html (IFrame source) one button and onlick listener. i need to open one website while clicking that button in InAppBrowser or in safari (new window). i cannot able to access phonegap methods from the html file (IFrame source), i includeed cordova on both html files, my source html page given bellow, this page is shown in an Iframe.
<html>
<head>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script src="js/libs/jquery.js"></script>
<script src="adv.js"></script>
<script>
$(document).ready(function () {
$('#advArea').find('button').on('click', function (e) {
e.preventDefault();
var path = "http://www.google.com");
console.log(path);
//window.open(path,'__system');
//need to acces inApp Browser from here
})
});
</script>
</head>
<body>
<div id="advArea">
<button></button>
</div>
</body>
</html>
In your "parent" page where your iFrame is, create the below function
function popnew(path) {
navigator.app.loadUrl(link, { 'openExternal' : true });
}
then you call the above function for any button/link in the iFrame
<button onclick="javascript:parent.popnew('http://www.stackoverflow.com')"></button>

phonegap + jquery mobile, good practices

until now I was not using this index.js that Phonegap recommends :
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 explicity 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);
}
};
Where should I put my own js functions and events (all my js file), into this, out of this, in another file ?
Where should I call those js files and where should I call the app.initialize, in relation to the position of the calls to the js files ?
Here's my html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="height=device-height,width=device-width,initial-scale=1.0,maximum-scale=1.0">
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/style.css" type="text/css" media="all" />
<script src="js/jquery-1.9.1.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
<script src="js/jquery.mobile.config.js"></script>
<script src="js/jquery.mobile-1.3.2.js"></script>
<script src="js/jquery-geturlvar.js"></script>
<script src="js/boardDims.js"></script>
<script src="js/functions.js"></script>
<!-- <script src="cordova.js"></script>-->
</head>
<body>
For now I am compiling using the remote service : $ phonegap remote run android
It would be really useful to have a default template of an app using Phonegap + JQM, for beginners like me ;-)
That index.js is included as an example, you don't really need to use it. It is basically showing you how to work with ondeviceready. You need to use ondeviceready when you work with plugins, since most of their calls will only be available after ondeviceready has been fired. So you hook up your calls to plugins on a listener to ondeviceready. I am doing it like this for instance:
<script type="text/javascript">
function onLoad() {
document.addEventListener("deviceready", MYAPP.events.onDeviceReady, false);
}
</script>
</head>
<body onload="onLoad();">
And inside MYAPP.events.onDeviceReady I do the calls to geolocation, camera, or whatever plugin I'm working with.
BTW, two important things to notice in you example: You need to include cordova.js before you can access ondeviceready or work with any plugin, plus you are including index.js twice. Perhaps you duplicated the <script src="js/index.js"></script> to edit it and include js/cordova.js and forgot to change the name/path?
Apart from that, what I do is separating the app's JS and the external libs in two separate directories for better organisation, like "lib" and "js", so you would include "js/functions.js" and "lib/jquery.js".
I include both the libs and custom JS files at the bottom of the body tag for a slight better performance: Where should I put <script> tags in HTML markup?
And I name the files under "js" (custom JS files for the app) according to their purpose/content, like: events.js, models.js, settings.js, util.js, ... You can see in the snippet above that I have "namespaced" my custom JS objects under the capitalised name of the app, so everything in util.js will be called like: MYAPP.util.formatDate().

Gmaps4Rails with OpenLayers gives JS error when marker clicked: this.serviceObject is undefined

I am having trouble with using OpenLayers in Gmaps4Rails (Gem version 1.5.2.) When I click on a marker I would like to show the typical callout (Infobox). Unfortunately I get the following JavaScript error:
this.serviceObject is undefined
Firebug calls the line 195 of the file "gmaps4rails.openlayers.js" responsable:
return this.serviceObject.addPopup(popup);
If I use Google Maps as API provider instead, everything works fine. Showing and hiding the infobox works nicely. This is why I assume that the error must be somewhere in "gmaps4rails.openlayers.js"
I tried on the latest FF and Chrome on Mac.
For reproducing the error in a reduced example, I created a simple HTML page in the public folder of my Rails 3.2 app and directly linked the needed JS and CSS files. To create the HTML page I copied the HTML code of my broken Rails app and reduced it.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href="/assets/gmaps4rails.css" media="screen" rel="stylesheet" type="text/css" />
<script src="/assets/gmaps4rails/gmaps4rails.base.js" type="text/javascript"></script>
<script src="/assets/gmaps4rails/gmaps4rails.openlayers.js" type="text/javascript"></script>
</head>
<body>
<div class="map_container">
<div id="map" class="gmaps4rails_map"></div>
</div>
<script src="http://www.openlayers.org/api/OpenLayers.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
Gmaps.map = new Gmaps4RailsOpenlayers();
Gmaps.load_map = function() {
Gmaps.map.map_options.provider = "openlayers";
Gmaps.map.initialize();
Gmaps.map.markers = [
{"description":"<p>This shall be in in the popup</p>",
"id":117979030,
"lat":39.5715,
"lng":2.64694}
];
Gmaps.map.create_markers();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
Gmaps.oldOnload = window.onload;
window.onload = function() {
Gmaps.triggerOldOnload();
Gmaps.loadMaps();
};
</script>
</body>
</html>
Unfortunately I could not find a working example of a successful Gmap4Rails–Openlayers integration on the web. Am I missing a mandatory parameter?
Thanks in advance.
It's a bug.
Replace:
return this.serviceObject.addPopup(popup);
with:
return this.map.addPopup(popup);
I'll push a fix soon, thanks and +1

jQuery Mobile causes Access Denied in jQuery

I'm following this tutorial on adding mobile features to an ASP.Net MVC 4 application.
When I launch the application (causing the Login page to be loaded), I get Access denied at the following point in jQuery 1.7.2 (also reproduced with 1.7.1)
if ( elem.parentNode ) { // Access denied here, Line 6081
elem.parentNode.removeChild( elem );
}
Walking down the call stack, I see the following in jquery.mobile-1.1.0.js (there are a few other methods on the call stack as well)
// Called from .initializePage:
if ( !$pages.length ) {
$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 ); // Called from here, Line 7475
}
// First method in jquery.mobile:
if( $.mobile.autoInitializePage ){
$.mobile.initializePage(); // Called from here, Line 7541
}
If I comment out jquery.mobile from my application, it works as it did previously:
// _Layout.cshtml:
<script src="#Url.Content("~/Scripts/jquery-1.7.2.js")" type="text/javascript"></script>
#*<script src="#Url.Content("~/Scripts/jquery.mobile-1.1.0.js")" type="text/javascript"></script>*#
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.19.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
All JavaScript files are being served via the built-in VS2010 web server from the main project's domain.
UPDATE
Upon further inspection, I realize this is what jQuery Mobile is doing when the error happens:
// find and enhance the pages in the dom and transition to the first page.
// if no pages are found, create one with body's inner html
$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
What's happening to cause jquery.mobile to fail?
It turns out that there was a reference to a third party script on the page (Comodo SSL validation) that certainly did not need to be on a mobile version of the page. jQuery Mobile tried to manipulate the related DOM, causing the error.
Thank you for pointing me in the right direction. I've been searching for days why the popup method (JQuery Mobile) didn't work on an .aspx page. Visual Studio automatically initializes the page with a scriptmanager.
The solution was to comment out the following line in the Asp:Scriptmanager tag, since it is conflicting with the JQuery reference in the head of the page:
<asp:ScriptReference Name="jquery" />

Resources