my code in JS is getting very large right now and so I wanted to outsource sections to other files, for clarity.
In my main file I use
jQuery(document).ready(function ($) {
$.getScript("/wp-content/plugins/file2.js",function(){
console.log("loaded 2");
});
$.getScript("/wp-content/plugins/file3.js",function(){
console.log("loaded 3");
});
This works.
In file 2 and 3 I use jQuery with functions like:
function getData(){
$.("#foo").on("click", function(){});
}
So I am getting the error
$ is undefined
because I do not declare $.
But if I wrap around the $.ready function I can't access the functions inside file 2 which are used by the other files.
How can I 'declare' the $ separately without loosing the global scope of the function. Or is there even a better way?
I only include in html:
<script src="/wp-content/plugins/file1.js" type="text/javascript"></script>
Thanks for helping!
A copy of jQuery is assigned to $ by default.
It will only be undefined if you:
Overwrite it
Mask it
Call $.noConflict()
… so don't do any of those.
Related
I have an HTML page with multiple attached js files that include functions that are used on that page.
For functions that are included on the base HTML page they are successfully re-assigned. FunctionA = FunctionB.
The problem comes when I try to reassign a function that is part of one of the attached js files. The normal reassignment doesn't work. Say FunctionC is on attached js file more functions.js .
I try FunctionC = FunctionD. FunctionC runs as it would normally - WITHOUT the reassignment to FunctionD. I know the reassignment to FunctionD 'should' occur before the FunctionC runs because it fires when I check with console.log.
Any ideas as to why this isn't working would be appreciated.
You have to make your reassignments after included file.
For example (Disclamer: don't do this in real projects - this is for demo purposes only) the code below includes jQuery library, but then overwrites jQuery function with a custom one:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
jQuery = function(s) {
alert(s);
}
</script>
<script>
jQuery('aaa');
</script>
when this runs it produces alert (demo), but if you reverse the order of first two script tags - original "attached" jQuery function will take over.
I'm bringing a template across from an old version of Joomla into Wordpress and got quite a few javascript files that I have to use with the main referring out to functions in the others. All of these files use jQuery left right and centre and given Wordpress uses noconflict by default I thought it would be straightforward to wrap each js file up like this:
(function($){
....my code...
})(jQuery);
The problem I get is with the scope of functions that are called across files, so for example:
File 1
(function($){
$(document).ready(function(){
mainmenu();
});
})(jQuery);
File 2
(function($){
function mainmenu(){
alert("hello");
}
})(jQuery);
Here is the problem I get the error "uncaught ReferenceError: mainmenu is not defined", I know it will be something simple to reference the function, but I can't see it, probably be a "Doh" moment.
Any help is most appreciated. Yes I know I could just find and replace the '$' with 'jQuery' but I just thought that there must be a way to do it?
it is because the mainmenu is a closure function within the anonymous function in the second file.. so it is not available in file1.
One possible solution is to make it a global function, so that it will be available in the global scope.
(function($){
window.mainmenu = function (){
alert("hello");
}
})(jQuery);
I downloaded the sample-project for the latest-release of RequireJS. Their documentation implies anything loaded is passed-into the parameter list of the associated function (in corresponding order).
So I decided to try it...but it doesn't seem to work!
Firebug (net tab) shows jQuery as being loaded: so RequireJS obvioulsy did that part successfully
Firebug (console tab) shows '$ is not a function'
My question is: Why isn't the alias getting populated?
MY CODE LOOKS LIKE:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/require.js" type="text/javascript"></script>
<script type="text/javascript">
require(["scripts/jQuery/Core/jquery-1.7.2.min"], function ($) {
// jQuery is not passed-into the function, so the alias fails!
$(function () {
var stop = "";
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
THIER SAMPLE LOOKS LIKE:
//Inside scripts/main.js
require(["some/module", "a.js", "b.js"], function(someModule) {
//...
});
jQuery should be loaded through the special name "jquery", otherwise it won't register itself (since jQuery uses a named define).
// create an alias that points to proper file
require.config({
paths : {
jquery : "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min"
}
});
// require jquery usign the path config
require(["jquery"], function ($) {
console.log($);
});
That is the main reasons why named define is considered an anti-pattern and should be used only when needed (when you have multiple modules inside same file).
Be sure to read the "README.md" for the RequireJS+jQuery sample project. There are many complications with using jQuery that you need to decide on how best to tackle it for your project during the initial setup. Once you've figured out what's best for you and implemented it, though, it shouldn't be a problem again.
Much of the complication also comes from the fact that jQuery isn't a true AMD module, they just have a hack in the codebase to do a define if it detects the define function is available. For example, this means the jQuery module name will always be "jquery" (note the lowercase 'q') unless you wrap it yourself, so if you define the path for it in your config you MUST have the key named "jquery" (again, with a lowercase 'q') or there will be a mismatch. That bit us when first setting up RequireJS on our project (we named the key "jQuery").
Is your scripts folder 'Scripts' or 'scripts'?
You're making a request for "Scripts/require.js" as well as for "scripts/jQuery/Core/jquery-1.7.2.min". Take a look at the Net tab of Firebug... I bet you're generating a 404 there.
I've got a file notifications.js containing one event bound to an element, and a function updateNotification(). This function uses jQuery to update certain elements on the page when a JSON object is passed as a parameter.
The problem:
I'm attempting to call this function within the page (via <script> tags), however rather than calling it, it breaks the page. I did some digging around within the Chrome Developer Console (not sure of the name), and an error is flagged:
/pleaseshare/views/install/:50 Uncaught ReferenceError:updateNotification is not defined
However, when I pan within the console, I can clearly see the file notifications.js listed under scripts, and the function is defined there. If I define the function within the current scope (e.g. the line above the call), it works fine.
What I've tried
The function contains some javascript that requires jQuery, so I've attempted both with and without encasing it in $(document).ready( function() {});, with neither seeming to have any affect.
I'm pretty stumped.
For good measure, here's a link to show the structure of my javascript and html: http://snippi.com/s/znk6xe9
Any help in figuring out why this is happening, or explanations of why javascript functions cannot be called cross-file (although I'd hope this isn't the case), would be greatly appreciated ;)!!
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You code looks like the structure should work, but is clearly a reduced test case that has been reduced to the point where it won't.
Got it working. The issue was definitely multi-faceted, but I figured it out.
First off the use of RequireJS had an impact on updateNotification(), in that it couldn't be called cross-file, and was therefore considered undefined. I assume this because of how RequireJS loads files, and I'll look into the documentation later (and post an edit if I find anything relevant).
Secondly, updateNotification() would again be considered undefined when encased within jQuery's DOM ready loader $(document).ready(function(){}). However updateNotification() contains executions which require jQuery, so I had to encase the contents of the function in $(document).ready(function(){}).
This is an issue very unique to RequireJS/jQuery, hence why in most use cases this wouldn't occur.
Side note: The tags are edited to reflect this.
you need to import your script into your page:
<script type="text/javascript" language="javascript" src="path/to/notifications.js"></script>
This needs to be added above the <script> tag that calls updateNotification()
Functions do not need to be declared in the same file. In fact, avoiding having every declaration dumped into the global namespace is usually a concern in JavaScript.
In the sample code in the link you provided, updateNotification is declared as a global, so there should not be a scoping problem.
However, in the same sample, you don't show notifications.js being included. You need to import it using a <script></script> element and that element must come before the script element that includes the call to updateNotification. You also must include jQuery before notifications.js, since it uses jQuery. So you need something like:
<body>
// One or two elements
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="notifications.js"></script>
<script type="text/javascript">
$(document).ready( function() {
var json = {status : 'ok', message: 'Hello'};
updateNotification(json);
});
</script>
// All other elements
</body>
Looking into RequireJS but unlike Head.JS which downloads in undetermined order but evaluates in a determine order, RequireJS seems different
Normally RequireJS loads and evaluates scripts in an undetermined order.
Then it shows how to prefix order! to the script names for explicit ordering etc..
Then in the examples:
require(["jquery", "jquery.alpha", "jquery.beta"], function($) {
//the jquery.alpha.js and jquery.beta.js plugins have been loaded.
$(function() {
$('body').alpha().beta();
});
});
So if jquery.alpha is downloaded and evaluated before jquery then surely this would cause a problem? Forgetting any client code usage such as function body above, if like most plugin they attach to jQuery.fn then at stage of evaluation then jQuery will undefined in this scenario.
What am I missing here?
RequireJS is not designed to load plain javascript, but to load defined modules. The module format looks something like:
define(['a', 'b'], function(a, b) {
return { zzz: 123 };
});
The important thing to note is that all of the module code is inside an anonymous function. So if the file is run in an arbitrary order, it doesn't matter, because all it does is register the module. The module code is then run in dependency order, with the return value becoming the module object, which is passed as a parameter to code that uses the module.
If you are trying to load plain files, this will not work correctly for you. There is the order plugin to force load order in that case.
It should be noted that that example uses the custom made version of "requirejs and jquery" packaged together, which I believe means that jquery will always be available first.
If you have problems, you can always wrap your plugins within a module definition and make sure they depend on jquery themselves, again ensuring the order is correct:
/* SPECIAL WRAPPING CODE START */
define(['jquery'], function(jQuery) {
// .... plugin code ....
/* SPECIAL WRAPPING CODE END */
});
You are correct, without something to aid in the order an exception will occur. The good news is RequireJS has an Order plug-in to help in this.
I'm currently evaluating RequireJS...
And Here Is An Example of One of My Files:
The 'order!' command will load files for you sequentially. You can (then) use the callback to load other (support) files.
<script src="Loaders/RequireJS/requireJS.js" type="text/javascript"></script>
<script src="Loaders/RequireJS/order.js" type="text/javascript"></script>
<script type="text/javascript">
require(["Loaders/RequireJS/order!././Includes/JavaScript/jQuery/Core/jquery-1.3.2.js",
"Loaders/RequireJS/order!././Includes/JavaScript/jQuery/Core/jquery.tools.min.js",
"Loaders/RequireJS/order!././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.tmpl.js"], function() {
require(["././Includes/JavaScript/jQuery/jGeneral.js",
"././Includes/JavaScript/jQuery/autocomplete.js",
"././Includes/JavaScript/jQuery/jquery.ErrorWindow.js",
"././Includes/JavaScript/jQuery/jquery.ValidationBubble.js",
"././Includes/JavaScript/jQuery/jquery.Tootltip.js",
"././Includes/JavaScript/jQuery/jquery.Extensions.js",
"././Includes/JavaScript/jQuery/jquery.Toaster.js"], null);
require(["././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.dimensions.js",
"././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jQuery.Color.Animations.js",
"././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.corners.min.js",
"././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.tipsy.js",
"././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.numberformatter-1.1.0.js",
"././Includes/JavaScript/jQuery/ThirdPartyPlugIns/jquery.tipsy.js"], null);
});
</script>
In All Honesty:
I'm looking at various asynchronous resource-loaders and I'm having a hard-time finding one that does everything I need. I'm also finding the documentation in each one lacking.