Phonegap index.js not entering $(function(){}) - javascript

This only happens on the device, not in the simulator. I can get as far as the 1st alert which leads me to believe it's not a html issue (very open to correction on this of course...). In the weinre debugger, I tried copying and pasting the $(document).on function but it said $(document) was null. This was working fine yesterday evening until i accidentally opened the file with libre office instead of notepad++. Notepad++ shows the line breaks as CR CF, could that have something to do with it?
Edit: I copied the contents of index.html to a notepad file and saved it as html in order to get rid of any hidden formatting. I've also added jQuery as the first script in index.html.
Finally, if I look at the elements in the weinre debugger, I can see index.html.
jQuery(document) gives me ReferenceError: jQuery is not defined so something seems to be wrong with jquery...
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="cordova.js"></script>
The paths are correct
Answer ahem... my bat script to package the contents of bin/debug/ only packed the files and not the folders, so no js folder went into the zip...
Thanks in advance for the help!
window.PhotoScan = window.PhotoScan || {};
alert("we can get this far");
$(function () {
alert("how do we not get to here???!!!!!");
$(document).on("deviceready", function () {
alert("index #5");
navigator.splashscreen.hide();
if(window.devextremeaddon) {
window.devextremeaddon.setup();
}
$(document).on("backbutton", function () {
DevExpress.processHardwareBackButton();
});
});
function onNavigatingBack(e) {
if (e.isHardwareButton && !PhotoScan.app.canBack()) {
e.cancel = true;
alert("index #6");
exitApp();
}
}
function exitApp() {
switch (DevExpress.devices.real().platform) {
case "android":
navigator.app.exitApp();
break;
case "win8":
window.external.Notify("DevExpress.ExitApp");
break;
}
}
alert("index #7");
PhotoScan.app = new DevExpress.framework.html.HtmlApplication({
namespace: PhotoScan,
layoutSet: DevExpress.framework.html.layoutSets[PhotoScan.config.layoutSet],
navigation: PhotoScan.config.navigation,
commandMapping: PhotoScan.config.commandMapping
});
alert("index #8");
PhotoScan.app.router.register(":view/:id", { view: "home", id: undefined });
PhotoScan.app.on("navigatingBack", onNavigatingBack);
PhotoScan.app.navigate();
});

Not sure where you have gone wrong, but typically i just wrap my bootstrap code inside the device ready. As i typically create a db schema first anyways.
document.addEventListener('deviceready', function () {
alert("index #5");
navigator.splashscreen.hide();
if(window.devextremeaddon) {
window.devextremeaddon.setup();
}
$(document).on("backbutton", function () {
DevExpress.processHardwareBackButton();
});
});
// ... your other functions here
If you want to keep them off global scope, can just wrap them in a self executing function:
(function() {
document.addEventListener('deviceready', function () {});
})();
I haven't used document ready in cordova apps, as i just have the js scripts load at the bottom. Then i load most content through handle bar templates and javascript.
Edit
As per the comments, you need to make sure that each time you add a new file or make a change to files in a cordova project, it must be rebuilt:
cordova run ios --device
cordova run android

#rory,
you wrote $(function(){})
This is NOT a good way to do things. If your function fails, for whatever reason, your program will NOT work.
Did you intend to do this?
Jesse

Related

How do I trigger the window load event in this Jest test?

I'm trying to set up my first DOM-manipulation/JQuery Jest test in my Rails project. In its essential form at the moment, I'm just trying to clear a basic hurdle of 'imported Javascript functions do anything at all'.
To that end, I have the following code in PledgeFormUpdates.js.test:
'use strict';
import pledge_form_updates from '../../app/javascript/components/PledgeFormUpdates.js';
test('Displays GDPR checkbox on EU country selection', () => {
// Set up our document body
document.body.innerHTML =
'<select id="pledge_pledgor_home_country" class="country-select"></select>'// +
pledge_form_updates();
const $ = require('jquery');
$(window).trigger('load');
$("#pledge_pledgor_home_country").trigger('change');
});
And in PledgeFormUpdates.js I have the following:
export default function() {
console.log('hello world');
window.addEventListener("load", function() {
console.log('mellow curled');
$("#pledge_pledgor_home_country").change(function() {
console.log('yellow twirled')
});
});
};
So when I run the test, I'm expecting to see printout including 'hello world', 'mellow curled' and 'yellow twirled'. But in practice it's stopping after the first output, and so presumably the window load event isn't actually getting triggered (which I confirmed by commenting out the window.addEventListener... line, then seeing all three printouts).
What am I doing wrong here - or rather, how should I trigger the load event? (I also tried $(window).load();, but that just raises a TypeError)
I found a workaround for this, though it seems quite hacky. In the tested file, if I substitute the line
window.addEventListener("load", function() {,
with
$(window).on("load", function() {
then running the test (including the $(window).trigger('load'); statement) prints all of the log lines.
I must be missing something, because I can't believe that Jest would require JQuery to trigger a page load event, but for now at least this works.

JavaScript: $ is not a function (but it seems like it is)

I have a weird JavaScript problem that I just cannot understand.
My custom JavaScript file "header.js" uses jQuery. It throws the infamous "$ is not a function" error message but I don't understand why. The weird thing is I'm including jQuery.js and the code in question seems to have no problem to bind to jQuery events. So not having included jQuery is not the problem.
header.js
$(document).ready(function () {
if ($(document).width() >= 768) {
var header = false;
var scrollHandler = function () {
var scrollTop = $(window).scrollTop(); // line 5 that throws the error
// more code
};
//register function which is called on scroll
$(window).scroll(scrollHandler);
}
});
My HTML (with some debug output)
<script src="~/js/vendor/jquery.js"></script>
<script>
function printTest(str) {
console.log("test (" + str + "): " + $(".test").length);
}
</script>
<script>
printTest("2.1 before header");
</script>
<script src="~/js/header.js"></script>
<script>
printTest("2.2 after header");
</script>
Output when I load the page
test (2.1 before header): 1
test (2.2 after header): 1
But once I scroll my console error output shows:
TypeError: $ is not a function (line 5 in header.js)
Does anyone have an idea why that is? I've analyzed it for hours and I don't understand the reason. Any help/idea/suggestion would be highly appreciated. Thank you.
I possibly have a workaround. Its not the exact answer you seek. But can you check if putting the scroll handler's definition outside the document ready works for you ?
Please try as follows:
var scrollHandler = function() {
var scrollTop = $(window).scrollTop(); // line 5 that throws the error
// more code
};
$(document).ready(function() {
if ($(document).width() >= 768) {
var header = false;
//register function which is called on scroll
$(window).scroll(scrollHandler);
}
});
If this does not work too then there is something overriding your $ definition. Can you tell us if this works in your code ?
Ok, so if you have the same problem here is how I solved it.
The problem was a conflict with require.js. Require.js comes automatically with a module in Sitecore. At first I was not aware that require.js was causing this conflict because when I checked the JavaScript file I was looking for some override of $. What I didn't know at this point was that require.js also has a configuration file that includes its own version of jQuery.
I solved it by removing require.js (and adding the dependencies that it brought manually to my page).

JavaScript global callback functions are not called?

I'm building a small web app with a few other people. I want to allow the other developers to define a couple of functions that are always called when the document is ready.
Our app inserts the following script into the HTML body of every page:
<script type="text/javascript">
(function(){
window.Utils = {
funcs: {}
};
$(document).ready(function(){
alert('Calling funcs...');
var startFunc = Utils.funcs['start'];
if (startFunc != undefined){
startFunc();
}
var finishFunc = Utils.funcs['finish'];
if (finishFunc != undefined){
finishFunc();
}
});
})();
</script>
Then, in a separate .js file, a developer should be able to do the following:
Utils.funcs['start'] = function(){
alert('Starting...');
};
Utils.funcs['finish'] = function(){
alert('Finishing...');
};
But this doesn't work. The functions are never called?
jsFiddle link: http://jsfiddle.net/XvQtF/
jsFiddle's (very surprising) default is to put your code in a window load handler. (You can see this on the left at the top, the second drop-down box says "onload".) That happens very late in the loading process, long after ready has fired. So the functions aren't added until after you've tried to run them.
If the other developers put their functions in Utils.funcs in script elements after your element defining Utils but without waiting for a load event, it's fine: Updated Fiddle
For what it's worth, though, I would lean toward using a pub/sub solution rather than a single function. If you want to have more than one start function, for instance, your current structure doesn't allow it.
jQuery has Deferred and Promise now, which can be used for this. Here's a simple example of that: Live Copy | Live Source
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<meta charset=utf-8 />
<title>Pub/Sub with Deferred and Promise</title>
</head>
<body>
<script>
(function($) {
// Deferred objects for our app states
var start = new $.Deferred(),
finish = new $.Deferred();
window.Utils = {
start: start.promise(), // Only expose the Promise of each
finish: finish.promise() // " " " " " "
};
$(function() {
alert("Calling funcs...");
// Start the app
start.resolve();
// Finish the app (or whatever)
finish.resolve();
});
})(jQuery);
</script>
<script>
// Module 1
Utils.start.then(function() {
alert("Module 1 Started!");
});
Utils.finish.then(function() {
alert("Module 1 Finished!");
});
</script>
<script>
// Module 2
Utils.start.then(function() {
alert("Module 2 Started!");
});
Utils.finish.then(function() {
alert("Module 2 Finished!");
});
</script>
</body>
</html>
Set up Utils in a separate script to be loaded as the very first one. Also, do this unconditionally (not in any callback etc):
/* load as first script, sets up a global container-object for later use */
var Utils = {
funcs: {}
}
Note that it is ok to define a global variable in the global scope.
/* other script */
(function(){
function myFunc() { /*...*/ };
// now store a reference in Utils
Utils.funcs.start = myFunc;
})();
As mentioned in an other answer: Be aware of the loading and calling order of your various scripts / code:
$(document).ready is essentially the "DOMContentLoaded"-event with most browsers (but earlier versions of IE). "DOMContentLoaded" fires, when all inline-resources originally found in the head-section have been loaded and the DOM-structure of the body is present.
Since this does not include any injected content, it is probably granted, that the event is fired before any modular library (which are loading modules by injecting script tags) is fully loaded and present. (Given that these scripts are loading concurrently with images and other inline-stuff using just a handful of network-slots/sockets provided by the browser, they are probably one of the last things to be ready in your whole loading-process.)
Instead of just using
startFunc() and
finishFunc()
try using this
startFunc.apply(this, null) and
finishFunc.apply(this, null)
this will invoke the functions.
also make sure that
Utils.funcs['start']
Utils.funcs['finish']
is getting initialized before they are called.

Why do I recieve both "$jQval is undefined" and "$.validator.unobtrusive is undefined" when using RequireJS?

This has had me puzzled for a few hours now. When the script is in a non-requirejs javascript file it works fine. When I use it with RequireJS it fails to work and gives me the error messages in the question title (though the firebug console).
I was just trying to get it to "work" with RequireJS before attempting to refactor into a module.
The Html is rendering correctly. The scripts are loading correctly. Also, I'm using the require-jquery.js bundle download, which is referenced in the layout template across all pages.
main.js:
require.config({
paths: {
"maximum-filesize": "modules/validation/maximum-filesize"
}
});
require(["maximum-filesize", "domReady!"], function (maxFileSize) {
});
maximum-filesize.js
require.config({
paths: {
"jquery-validate": "libs/jquery/jquery.validate",
"jquery-validate-unobtrusive": "libs/jquery/jquery.validate.unobtrusive"
}
});
define(["jquery", "jquery-validate", "jquery-validate-unobtrusive", "domReady!"], function ($) {
$.validator.unobtrusive.adapters.add(
'filesize', ['maxsize'], function(options) {
options.rules['filesize'] = options.params;
if (options.messages) {
options.messages['filesize'] = options.message;
}
});
$.validator.addMethod('filesize', function (value, element, params) {
if (element.files.length < 1) {
// No files selected
return true;
}
if (!element.files || !element.files[0].size) {
// This browser doesn't support the HTML5 API
return true;
}
return element.files[0].size < params.maxsize;
}, '');
});
Edit 1
I just tried commenting out all of the above code, and replaced it with a simple:
$('#Name').val("Hello");
This rendered "Hello" correctly in the #Name textbox, so JQuery is working.
You should use requires shim option to tell requires to load jquery before jquery validate. Otherwise load order is undefined.
Another possible problem is calling requirejs.config 2 times. Requirejs has problems with merging configs

What should I do to obtain javascript intellisense for my own js library in Visual Studio

I have multiple javascript files and they have their own functions. If I make reference one of them to inside any of them, it doesnt see its functions if the function is not prototype. What is logic inside the Intellisense ?
I want to use Splash function with Intellisense feature below, how can I do that ?
//My.js
/// <reference path="Test.js" />
.
//Test.js
NameSpace.prototype.UI = new function () {
this.Splash = function (value) {
try {
if (value == 1) {
$('#splash').css('height', $(document).height());
$('#splashContent').css('top', $(window).height() / 2);
$('#splash').fadeIn();
$('#splashContent').fadeIn();
setTimeout("SF.UI.Splash(0)", 3000);
}
else if (value == 0) {
$('#splash').fadeOut(1000);
$('#splashContent').fadeOut(1000);
}
else if (value == 3) {
$('#splash').css('height', $(document).height());
$('#splashContent').css('top', $(window).height() / 2);
$('#splash').fadeIn();
$('#splashContent').fadeIn();
}
} catch (e) {
Splash(0);
}
}
}
JS Intellisense is flaky at best. Despite all those articles, in my experience, it doesn't work as advertised. I would suggest:
Make sure all your JS files are in the same project (making ti work across projects is even trickier).
Make sure /// <reference path="Test.js" /> is the very first line in JS.
Make sure there are no errors in the Test.js file (run JSLint on it to be sure) or use the vsdoc approach.
Look at the Output tool window to see if it contains any errors related to updating intellisense. This will help you troubleshoot and remove errors in your referenced JS file.
Alternative to create a Test-vsdoc.js file (this way, even if your main JS file has errors, it would not cause intellisense to fail) :
//Test-vsdoc.js
NameSpace.prototype.UI = new function () {
this.Splash = function (value) {
/// <summary>This is my function summary</summary>
}
}
VS would automatically include it next time you restart the IDE (or try a force update Ctrl+Shift+J)
Assuming that is the actual contents of your js file, including the //My.js comment, then that is your problem right there.
/// <reference comments must be at the very top of the file, before any other content, otherwise they will not work.
Side note, did you know there is a code snippet for that reference? its ref, then tab tab. Also you can drag / drop a file and get the comment.
Once you have your references done, you can force VS2010 to refresh your js comments by pressing Ctrl+Shift+J while editing the .js file

Categories