I have the following javascript function that prevents form submission if all required fields are not complete and is part of a form I am creating using Google Apps Scripts. Note that the #submitbutton is actually a regular button and Google Apps Scripts forces strict javascript. The script works fine on chrome, but when I test it on Safari or Firefox, it doesn't appear to be running. Am I using a method that only works on Chrome? Am I missing something here?
I get the following errors in Safari:
Uncaught TypeError: undefined is not a function (evaluating '(1, $)('#submitbutton')') and Uncaught Strict mode does not allow function declarations in a lexically nested statement.
Firefox gives a similar issue: Uncaught in strict mode code, functions may be declared only at top level or immediately within another function 2699307207-maestro_htmlapp_bin_maestro_htmlapp.js:84:360 and Uncaught TypeError: $ is not a function
<script type="text/javascript">
$('#submitbutton').on('click', function() {
$(this).val("Submitting...");
//check for required fields
var emptyFields = $('[required]').filter(function() {
$(this).removeClass("warning");
if ($(this).val().length === 0){
$(this).addClass("warning")
return true
} else {
return false
}
});
if (emptyFields.length === 0) {
$(this).prop('disabled', true);
document.getElementById('incompleteWarning').style.display = 'none';
document.getElementById('bePatient').style.display = 'inline';
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(this.parentNode);
} else{
$(this).val("Submit Application")
document.getElementById('incompleteWarning').style.display = 'inline';
document.getElementById('incompleteWarning').style.color = 'red';
}
});
</script>
jsfiddle here: https://jsfiddle.net/hofresre/
Note that the jsfiddle doesn't use the google.script, but replaces it with this.parentNode.submit()
Any help is greatly appreciated.
Per comments:
Line 84 of maestro_htmlapp_bin_maestro_htmlapp.js:84:360:
function ys(a){for(var b=[],c=0;c<a.length;++c){var d=a[c];b[c]=Mn(d)?(new String(d)).toString():d}return b}var As=[vh,"[object Object]"];var Bs=["alert",ts(function(a){return alert(a)},16,[4]),"confirm",ts(function(a){return confirm(a)},16,[4]),"prompt",ts(function(a,b){return prompt(a,b)},16,[4,4])];var Cs=window.console&&window.console.error?function(a){window.console.error(a)}:void 0,Ds=window.console&&window.console.info?function(a){window.console.info(a)}:void 0,Es=window.console&&window.console.log?function(a){window.console.log(a)}:void 0,Fs=window.console&&window.console.warn?function(a){window.console.warn(a)}:void 0,Gs=["console.debug",ts(window.console&&window.console.debug?function(a){window.console.debug(a)}:void 0,16,[4]),"console.error",ts(Cs,16,[4]),"console.info",ts(Ds,16,[4]),
I guess you know that browser don't support web functionalities the same way. We know that google always focalize their web library and their support firstly for chrome browser.
When you just have this error:
functions can only be declared at top level or immediately within another function
You must not put a function declaration inside any other block, like an if-statement or for-loop; cause any block scope that use curly braces: try-catch-finally, if-else if-else, for, switch, and ES6 also define new feature that utilize block scope such as class.
you can't: "use strict" { Function bar(){/****/} }
Therefore, independents solutions that i can provide are:
Find if there is a version of script (here google script or JQuery) (which is recent) where this problem have been solved.
You can also comment "use strict" in the corresponding script (for example in google script).
Make show that you first include google script and JQuery before the other js scripts.
Try to use non minified script library because something (an example which append with JQuery 1.11) it's the cause of the problem.
Before trying previous solutions, maybe this modified code can work:
<script type="text/javascript">
var trySubmission = function() {
$(this).val("Submitting...");
//check for required fields
var emptyFields = $('[required]').filter(function() {
$(this).removeClass("warning");
if ($(this).val().length === 0){
$(this).addClass("warning")
return true
} else {
return false
}
});
if (emptyFields.length === 0) {
$(this).prop('disabled', true);
document.getElementById('incompleteWarning').style.display = 'none';
document.getElementById('bePatient').style.display = 'inline';
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(this.parentNode);
} else{
$(this).val("Submit Application")
document.getElementById('incompleteWarning').style.display = 'inline';
document.getElementById('incompleteWarning').style.color = 'red';
} ;
}
$('#submitbutton').on('click', trySubmission ) ;
</script>
What mode are you loading the HTML as from the GS file?
When in SandboxMode.NATIVE the error occurs in SandboxMode.IFRAME things seem to work
Here is some test code for a GS file
function doGet(e) {
var html= HtmlService.createTemplateFromFile("test.html");
return html.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
...and the HTML as test.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
function myFunction() {
if (jQuery) {
// jQuery is loaded
console.log( "Loaded" );
} else {
// jQuery is not loaded
console.log( "Not Loaded" );
}
$("#message").html("Something happened.");
}
$(document).ready(myFunction);
</script>
<p id="message">Nothing happened. </p>
Related
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).
The following JavaScript works correctly in all browsers except IE 7 and 8:
if (typeof django != 'undefined') {
console.log('Django admin loaded');
var jQuery = django.jQuery;
}
This code is on top of a JavaScript file that is loaded both inside Django's admin interface and on our public pages. Django's admin loads its own jQuery, so we use that one preferably ...
However, IE 7 and 8 executes the variable assignment inside this if statement even if the condition (typeof django != 'undefined') is false. At the same time, the console.log() is not executed :-/ Removing the var keyword, the same code works perfectly also in IE 7 and 8:
if (typeof django != 'undefined') {
console.log('Django admin loaded');
jQuery = django.jQuery;
}
But why? That doesn't make any sense, does it?
ALL browsers will do this. It's called hoisting.
function test() {
if( false) {
var abc;
}
alert(abc); // expect ReferenceError, get undefined
}
Since you're defining jQuery, you probably want that as a global variable, so window.jQuery = django.jQuery should do just fine.
There is no such thing as block scope within javascript (please see here for more details of JS scoping: What is the scope of variables in JavaScript?).
Your initial code doesn't make much sense anyway - if you are trying to set the global jQuery variable, then your code should be:
if (typeof django != 'undefined') {
console.log('Django admin loaded');
jQuery = django.jQuery;
}
What you are seeing is probably a difference with how IE7 and 8 handle their JS scopes.
If you define the var keyword then you need to do like this:
if (typeof django != 'undefined') {
console.log('Django admin loaded');
var jQuery = django;
django.jQuery; // or django = django.jQuery
}
How can I use a javascript function globally in Drupal 7.
I have my javascript file set up like this and add it using drupal_add_js():
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
});
In my block WYSIWIG I added the following code (The reason I add it in the WYSIWIG is because I want it to update before the page is fully rendered):
<script type="text/javascript">
add_if_country_is_not_usa();
</script>
But I get the following error:
Uncaught ReferenceError: add_if_country_is_not_usa is not defined
(anonymous function)
I read about adding functions to Drupal behaviors but that happens on document ready. I want to run the function as soon as the block is shown.
Any ideas?
Either define in the global scope, or do like below:
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
// set as a property of the global object `window`
window.add_if_country_is_not_usa = add_if_country_is_not_usa;
});
Not sure if this is the best way but I ended up being able to get it work using a namespaces. I call myGlobalObject.add_if_country_is_not_usa() from my block and it works now.
var myGlobalObject = mySingleGlobalObject || { 'country': {} };
(function ($) {
myGlobalObject.country = '';
myGlobalObject.add_if_country_is_not_usa = function() {
// Check what country it is
// myGlobalObject.country = 'US';
}
})(jQuery);
I found the following definition
$.fn.flex = function ( options ) {
var p = this.data("flex"),
opts = options || {};
if (p) return p;
this.each(function () {
p = new Flex( this, opts );
$(this).data("flex", p);
});
return opts.api ? p : this;
};
which defines function flex() in original code.
Unfortunately, it stops defining this function in my environment, i.e. function call causes an error that flex is not a function.
What is critical here for flex being a function?
UPDATE
Sorry, actually I didn't modify anything. I just put this javascript https://github.com/jasonenglish/jquery-flex/ into my environment (Liferay) and the code to run script
<script type="text/javascript">
$(function() {
$(".flex").flex();
});
</script>
caused an error. So I replaced $ to jQuery everywhere as I did before and it is still not working.
UPDATE 2
Hmmm. Error occurs in widget.js from Twitter. Says
TypeError: jQuery(...).flex is not a function
If I rename flex to flex1 everywhere, it says "flex1" is not a function.
Sorry, actually I didn't modify anything. I just put this javascript ... into my environment (Liferay) and the code to run script
Because that's a jQuery plug-in, you need to make sure you include that script after jQuery on the page. So
<script src="/path/to/jquery.js"></script>
<script src="/path/to/the-plugin.js"></script>
If you put them in the other order, the first script will fail because it will try to take the value of the jQuery symbol, which doesn't exist yet, throwing a ReferenceError (in both loose and strict mode).
First of all in $.fn.flex $ and fn are jQuery variables. they are not native to JavaScript. $.fn provided by jQuery to attach method/property to jquery object
For some reason my javascript code is messed up. When run through firebug, I get the error proceedToSecond not defined, but it is defined!
JavaScript:
<script type = "text/javascript">
function proceedToSecond () {
document.getElementById("div1").style.visibility="hidden";
document.getElementById("div2").style.visibility="visible";
}
function reset_Form() {
document.personalInfo.reset();
}
function showList() {
alert("hey");
if (document.getElementsById("favSports").style.visibility=="hidden") {
document.getElementsById("favSports").style.visibility="visible");
}
}
//function showList2() {
//}
</script>
HTML:
<body>
<!--various code -->
<input type="button" onClick="proceedToSecond()" value="Proceed to second form"/>
</body>
The actual problem is with your
showList function.
There is an extra ')' after 'visible'.
Remove that and it will work fine.
function showList()
{
if (document.getElementById("favSports").style.visibility == "hidden")
{
// document.getElementById("favSports").style.visibility = "visible");
// your code
document.getElementById("favSports").style.visibility = "visible";
// corrected code
}
}
There are a couple of things to check:
In FireBug, see if there are any loading errors that would indicate that your script is badly formatted and the functions do not get registered.
You can also try typing "proceedToSecond" into the FireBug console to see if the function gets defined
One thing you may try is removing the space around the #type attribute to the script tag: it should be <script type="text/javascript"> instead of <script type = "text/javascript">
I just went through the same problem. And found out once you have a syntax or any type of error in you javascript, the whole file don't get loaded so you cannot use any of the other functions at all.
important: in this kind of error you should look for simple mistakes in most cases
besides syntax error, I should say once I had same problem and it was because of bad name I have chosen for function. I have never searched for the reason but I remember that I copied another function and change it to use. I add "1" after the name to changed the function name and I got this error.