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).
Related
I keep receiving the following error from the browser console when loading my script into my Magento store. All that it is listening for is an onclick event on a div yet I receive this error:
"Uncaught TypeError: Cannot read property 'click' of null."
The script works in JSfiddle so I'm really not quite sure why it isn't working. I've tried enclosing it within a $( document ).ready() as well but I receive the same error.
Code:
var step = 0;
var deviceType = "";
var modelType = "";
function showGen(){
$('.phoneTypes').css("display", "none");
if (deviceType == "Samsung"){
$('.sphoneGens').css("display", "block");
}
if (deviceType == "iPhone"){
$('.iphoneGens').css("display", "block");
}
if (deviceType == "iPad"){
$('.ipadGens').css("display", "block");
}
}
// Pick Device Type
$('.choicelabel').click(function(){
deviceType = $(this).children('input').val();
showGen();
});
//Pick Device Gen
$('.choiceType').click(function(){
modelType = $(this).children('input').val();
//$(".iphoneGens").css("display", "none");
console.log(deviceType);
console.log(modelType);
$(this).parents(".row").hide();
});
Any help debugging this issue will be greatly appreciated.
TL;DR:
jQuery( document ).ready(function( $ ) {
// Code using $ as usual goes here.
// And document is ready too
});
What's the issue?
Prototype.js was loaded after jQuery and was overwrite global $ symbol.
How can we deal with it?
You still have jQuery global to use. Just use it everywhere, where you want to use $.
// Pick Device Type
jQuery('.choicelabel').click(function(){
deviceType = jQuery(this).children('input').val();
showGen();
});
//Pick Device Gen
jQuery('.choiceType').click(function(){
modelType = jQuery(this).children('input').val();
//jQuery(".iphoneGens").css("display", "none");
console.log(deviceType);
console.log(modelType);
jQuery(this).parents(".row").hide();
});
You can also to define some shorthand for simplify it:
jQ = jQuery;
Common best practice for cases like this is to use IIFE wrap for your code:
;(function($){ // see note-1
// Use $ here! It's jQuery now
$(function(){
// be sure DOM was loaded before work with it(ex: binding events)
});
})(jQuery);
This adds nothing to global scope and achieves what we need.
You always can inject some other libraries(prototypejs?) with alias what you want to this IIFE.
note-1: Semicolon before IIFE protects javascript from previous expression with missed semicolon to be interpreted as function call.
jQuery itself provides shorthand for this case:
jQuery( document ).ready(function( $ ) {
// Code using $ as usual goes here.
// And document is ready too
});
That site isn't using jQuery, it's using prototypejs
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
Hello I have made a jQuery image map on codepen but when I transfer it to my clients WordPress install it no longer works?
The WordPress site is made with genesis and I thought that may be causing the problem... I also replaced $ with jQuery to stop conflict problems.
Pen: http://codepen.io/naniio/pen/QwVXWG
jQuery:
jQuery(document).ready(function($) {
jQuery(".clickable").click(function() {
var toHide = $(this).attr('data-hide');
jQuery(".map").toggle();
jQuery("#" + toHide).toggle();
});
jQuery(".hide").click(function() {
jQuery(".map").toggle();
jQuery(this).toggle();
});
});
Site www.shakesafe.co.nz
I added the code (HTML + JS) the home page with simple hooks and then added the CSS with a custom body tag for the home page in gensis samples stylesheet.. but the Jquery doesn't work? do you guys have any ideas as to why?
Thanks for your time and effort as always!
Always check your browser console for errors thrown. In this case, I see a Uncaught TypeError: undefined is not a function message. That error is found on line 112 on your page, and if you check it carefully, you are using the $ without assigning the jQuery object to it, hence causing an error:
jQuery(document).ready(function() {
jQuery(".clickable").click(function() {
var toHide = $(this).attr('data-hide'); // Line 112 where error is from
jQuery(".map").toggle();
jQuery("#"+toHide).toggle();
});
jQuery(".hide").click(function() {
jQuery(".map").toggle();
jQuery(this).toggle();
});
});
Replace the $ with jQuery, i.e. var toHide = jQuery(this).attr('data-hide');.
Alternatively, you can tell jQuery that you are using $ to stand in for the jQuery object, saving you 5 characters every single instance you call for it:
jQuery(document).ready(function($) {
$(".clickable").click(function() {
var toHide = $(this).attr('data-hide');
$(".map").toggle();
$("#"+toHide).toggle();
});
$(".hide").click(function() {
$(".map").toggle();
$(this).toggle();
});
});
May be it's because of $ on 3rd line:
var toHide = $(this).attr('data-hide');
Try changing it to jQuery. It may work.
Also your site had no $ on your code:
jQuery(document).ready(function() {
try putting $ between small braces after function
Don't ask me why, but a developer I commissioned used JQuery 1.4.4 to set up a couple functions on a page, and I am trying to update the JQuery version to 2.1.1. Doing this, I am getting a couple JS errors that are dealing with scrolling, namely:
$(document).ready(function(){
var scroll_pos = 0;
$(document).scroll(function() {
scroll_pos = $(this).scrollTop();
var hrt = $('.boxBg').offset().top-200;
if(scroll_pos > hrt) {
$('i.fa-heart').addClass('individual-heart-hover');
}
else{
$('i.fa-heart').removeClass('individual-heart-hover');
}
});
});
and
var _rys = jQuery.noConflict();
_rys("document").ready(function () {
_rys(window).scroll(function () {
if (_rys(this).scrollTop() >100) {
_rys('.navbar').addClass("f-nav");
_rys('.discoverSection').addClass("f-nav2");
$('.tabsection').css('display','block');
} else {
_rys('.navbar').removeClass("f-nav");
_rys('.discoverSection').removeClass("f-nav2");
$('.tabsection').css('display','none');
}
});
});
The lines that are receiving errors are:
$(document).ready(function(){
and
$('.tabsection').css('display','block');
both are receiving errors saying "Uncaught TypeError: undefined is not a function".
Strangely, these both work flawlessly with JQuery 1.4.4.
This line is suspicious:
var _rys = jQuery.noConflict();
That code removes the definition of $, so any subsequent code that uses $ will fail.
You should only use jQuery.noConflict() if you need to load two different versions of jQuery simultaneously, or if you are using another library that defines $ to mean something else. (.noConflict() actually restores any previous definition of $, but from the error you received it looks like there was no previous $.)
Assuming you are not dealing with one of those special situations, simply remove the noConflict line completely, and then change every instance of _rys to $.
Resolved:
Thank you all for your help. I'm not sure exactly what caused this, but I restarted Visual Studio and everything went back to normal. Not sure why, but it's been working ever since (yesterday).
I didn't have these problems last night (with the same code - unchanged):
I don't see what the issue is.
The error I am getting is:
JavaScript critical error at line 1, column 9 in [path/app.ts]
SCRIPT1004: Expected ';'.
What the deuce?!
Incase you can't see the image, the error is referring to this line:
declare var document;
Update
The javascript file which is a result of the TypeScript being compiled into JavaScript looks like this:
window.onload = function () {
start();
};
function sayHello(msg) {
return msg = "Hello, therel ol!";
}
function start() {
var element = document.getElementById("link");
element.addEventListener("click", function () {
var element = document.getElementById("response").innerText = sayHello("Hi");
}, false);
if(XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
And as you can see, everything looks fine. I don't get why it's throwing this error.
My guess is that you have referenced the app.ts file on your page by mistake, when you should have referenced the app.js file.
I'm assuming you get this error when running your application, not at design time.
i.e.
<script src="app.ts"></script>
Should be
<script src="app.js"></script>
You should not need to declare document - it should already be declared. It comes from the virtual lib.d.ts file which is referenced by default.
Try commenting out the declare line.