Error with requirejs domReady - javascript

I am using the requirejs domReady plugin within my code like this:
1.Config for module:
requirejs.config({
baseUrl:'scripts',
paths:{
async:'lib/plugins/async',
domReady:'lib/plugins/domReady'
}
});
2.Actual module
require(['domReady!','./gmaps','./gmaps_controls'],function(gmaps,controls){
//get mapdiv here by id
//create controls from controls module here...
});
I get the error:
GET http://localhost:8180/lib/plugins/domReady.js 404 (Not Found) require.js:34
Uncaught Error: Script error for: domReady
http://requirejs.org/docs/errors.html#scripterror require.js:8
This is my file strcuture within the scripts folder:
./lib:
plugins require.js
./lib/plugins:
async.js domReady.js
UPDATE2:
I load requirejs like this:
<script type="text/javascript" data-main="scripts/gmaps_displayScenario" src="scripts/lib/require.js"></script>
This is working for me:
requirejs.config({
baseUrl:'scripts',
paths:{
async:'lib/plugins/async',
domReady:'lib/plugins/domReady'
}
});
require(['domReady!','./gmaps','./gmaps_geoJSON'],function(domReady,gmaps,geoJSON){
//code goes on
I did this because I use jQuery only for the $(document).ready() function and for making ajaxcalls...I did not want to load the whole library for this. However this is not working as specified here.

Related

requirejs config gives ReferenceError: can't find variable $

Maybe I have fundamentally misunderstood how requirejs config works but I thought my configuration below made some libraries global so I could just use them in other files while only having to require and define files that I needed to use within the individual script. However I cannot reference $ (jQuery) in my application code without getting a reference error indicating it is not globally accessible. I've isolated the problem to the simple example below.
My file set up is as follows:
test
|
|-index.html
|-TestApp.js
|-MainApp.js
|-lib
| |-require.js
| |-jquery.js
| |-loadash.js
| |-backbone.js
|-css
|-test.css
The library file versions are RequireJS 2.1.22, jQuery 2.0.3, Loadash 3.10.1 and Backbone 1.2.1. I'm just trying to set up my environment and the approach I am taking is to pass my TestApp.js file to require.js to load the required files and bootstrap the application code in MainApp.js. The script in index.html is as follows:
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' type='text/css' href='css/test.css'/>
</head>
<body>
<div></div>
<script src="./lib/require.js" type="text/javascript" data-main="./TestApp.js"></script>
</body>
</html>
The referenced css script file simply ensured the div is visible as an orange square. See below:
div {
height: 100px;
width: 100px;
background-color: #FA6900;
border-radius: 5px;
}
It's the script line in index.html that then kicks off the application code by passing my configuration file to requirejs. This is the TestApp.js passed across as data-main. The TestApp.js is here:
require.config({
paths: {
'jquery': 'lib/jquery',
'lodash': 'lib/lodash',
'backbone': 'lib/backbone'
},
map: {
'*': {
// Backbone requires underscore. This forces requireJS to load lodash instead:
'underscore': 'lodash'
}
},
shim: {
jquery: {exports: '$'},
underscore: {
deps: ['jquery'],
exports: '_'
},
backbone: {
deps: ['underscore'],
exports: 'Backbone'
},
TestApp: {
deps: ['backbone'],
exports: 'TestApp'
}
}
});
require(['MainApp'], function(MainApp) {
MainApp.run();
});
The file above references the paths to the library files I want to use, I then remap loadash to be loaded when underscore is required (I need some of the extra loadash capability), I then use the shim to ensure the dependancies are correct as the files are loaded. Passing this config file to require.js in the index.html seems to be working as all of the files are showing as loaded in my browser. However the problem seems to be they do not appear to be globally accessible as I thought they would be.
Following the config section the last require call loads the MainApp.js file and calls the exposed run function. The MainApp.js looks like this:
define(function(require) {
var run = function() {
$(document).ready(function() {
$('div').click(function() {
$('div').fadeOut('slow');
});
});
};
return {
run: run
};
});
As far as I understood I should not need to require the files I already mentioned in the require config, I thought they should be loaded and available to this code. This is where I have misunderstood what is going on or have missed a step out. The exposed run function is being called but the first line that calls $ throws the error:
ReferenceError: Can't find variable: $
So my questions are:
What have I got wrong in my thinking?
(or) What am I doing incorrectly?
What should I be doing in order to preload and make available
frequently referenced libraries so that I do not need to require and
define them in every file I have?
As far as I understood I should not need to require the files I already mentioned in the require config, I thought they should be loaded and available to this code.
You misunderstood how RequireJS works. You should read the documentation from start to finish. For now, here are things you should change.
You should require jquery in your MainApp module:
define(function(require) {
var $ = require("jquery");
You should remove your shims that you have for jquery, underscore and backbone as they all call define and shim is only for code that does not call define. I don't know what TestApp is but if it is your own code, you really should make it into a proper AMD module and remove the shim.
#Louis has made me realise the error in what I was doing above. Changing the shim in TestApp.js so that is reads:
MainApp: {
deps: ['backbone'],
exports: 'MainApp'
}
Corrected the problem, now Backbone, $ and _ are all available to the rest of my application code without cluttering up each files require. i.e. I do not need to begin every file with:
define (['lib/jquery', 'lib/loadash', 'lib/backbone'], function($, _ , Backbone) {
Given in my actual app the list of common deps is quite large this means I only need to define locally used resources and can control the paths from a single location.

Calling require(['app']) Only Once

How can I call requireJS require(['app'], function() {}); only once at the beginning for the whole application so that any subsequent require(["..."], function(...){}); don't need to be wrapped within require(['app']?
This is my set up:
1) Load require.js
<script data-main="js/app.js" src="requirejs/require.min.js"></script>
2) Have app.js shims and basUrl configured properly.
requirejs.config({
baseUrl: "scripts/js",
paths: {
"jquery": "../bower_components/jquery/dist/jquery.min",
"modernizr": "../bower_components/modernizr/modernizr",
.
.
.
},
shim: {
"jquery.migrate": ['jquery'],
.
.
.
}
});
3) Dynamically load JS on different pages:
// Home Page
require(['app'], function() {
require(["jquery", "foundation", "foundation.reveal"], function ($, foundation, reveal){
$(document).foundation();
});
});
// Catalog Page
require(['app'], function() {
require(["jquery", "lnav/LeftNavCtrl","controllers/ProductCtrl", "controllers/TabsCtrl"], function ($, NavCtrl, ProductCtrl, TabsCtrl){
$(function() {
NavCtrl.initLeftNav();
});
});
});
Unless I wrap with require(['app'], function()) each time I call require("...") to load external JS or AMD modules, the app is not initialized and I get JavaScript errors. The above code works but it's not very efficient.
Is there a way to start my requireJS app before I try loading scripts?
I tried calling at the very beginning right after I load require.min.js:
require(["app"], function (app) {
app.run();
});
but it didn't work.
There are no provisions in RequireJS to ensure that a specific module is always loaded before any other module is loaded, other than having your first module load the rest. What you are trying to do is share your first module among multiple pages so it cannot perform the work of loading what is specific to each page.
One way you can work around this is simply to load app.js with a regular script element:
<script src="requirejs/require.min.js"></script>
<script src="js/app.js"></script>
Then the next script element can start your application without requiring app.js:
<script>
require(["jquery", "foundation", "foundation.reveal"], function ($, foundation, reveal){
$(document).foundation();
});
</script>
This is actually how I've decided to launch my modules in the applications I'm working on right now. True, it is not as optimized as it could be because of the extra network round-trip, but in the case of the applications I'm working on, they are still in very heavy development, and I prefer to leave this optimization for later.
Note that generally you don't want to use script to load RequireJS modules but your app.js is not a real module as it does not call define, so this is okay.
Another option would be to use a building tool like Grunt, Gulp, Make or something else and create one app.js per page and have each page load its own app.js file. This file would contain the configuration and the first require call to load the modules specific to your page.

Why is requirejs respecting the data-main entry point for some modules, but not others?

My program starts through this entry point in a twig template:
<script data-main="{{ asset('bundles/wwwcms/js/app') }}" src="{{ asset('bundles/wwwcms/js/require.js') }}"></script>
This outputs:
<script data-main="static.correct_require_url.net/js/app" src="static.correct_require_url/require.js"></script>
That all works fine, so require executes my app.js (config):
requirejs.config({
'baseUrl': 'js/lib',
'paths': {
'app': '../app',
'jquery': '//code.jquery.com/jquery-1.10.2.min',
'bootstrap': '//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min'
},
'shim': {
'bootstrap': {
deps: ['jquery']
}
}
});
// always require jquery and bootstrap onload
requirejs(['bootstrap']);
Which also works.
The directory structure is as follows:
app.js
require.js
/lib
- test.js
/app
- dirty.js
- import.js
Okay so here is where the error comes
For a page, let's say I want to load dirty.js and import.js. dirty.js depends on jquery, and import.js depends on "test.js" (something I just made up for demonstration purposes).
So I load the dependencies on the page this way:
<script type="text/javascript">
require(['app/dirty', 'app/import']);
</script>
When the page loads, dirty.js and import.js are loaded in just fine, from the correct url relative to "app". However, the dependency for import.js (test.js) does not get loaded correctly.
This is how import.js starts:
require(['jquery', 'test'], function($, test) {
...
});
As you can see, it's asking for lib/test.js. It pulls jQuery from a CDN, so that's taken care of. But for test.js, it uses the wrong path.
import.js (and all other modules loaded first) are pulled in using the correct static url path, but dependencies for modules are loaded using the wrong path- they are loaded using the url of that page!
So when I look at the network tab in the debugger console, import.js comes from:
static.blahblah.com/js/app/import.js.
but test.js comes from:
blahblah.com/route/to/current/page/js/app/test.js
(which obviously 404s every time)
What are possible reasons for this occurring? Am I doing something wrong? Any help would be greatly appreciated.
This is how the script tags look before require runs:
<script data-main="//static.bananajams.cloud.net/bundles/wwwcms/js/app" src="//static.bananajams.cloud.net/bundles/wwwcms/js/require.js"></script>
<script type="text/javascript">
require(['app/dirty', 'app/preview', 'app/import']);
</script>
Basically data-main is only a good idea if it's the single entry point for your code. It's loaded asynchronously, so there is no guarantees it runs before the other code in your app. See
RequireJS does not run data-main script before loading required modules
for more info on this.

Using jQuery plugins with RequireJS

I'm using the latest version of RequireJS and trying to get it to work with jQuery and jQuery plugins.
I can get it to load jQuery fine, but I can't get it to work with jQuery plugins. This is my code:
var dependencies = ["order!jquery"];
dependencies = dependencies.concat([
"order!plugins/underscore-1.3.1",
"order!plugins/backbone-0.9.1",
"order!plugins/jquery.typewatch"]);
require.config({
waitSeconds: 30,
paths: {
"jquery": 'http://code.jquery.com/jquery-1.9.1'
}
});
require(dependencies, function($) {
...
jQuery is loading OK, but I then get
Uncaught ReferenceError: jQuery is not defined jquery.typewatch.js:92
Uncaught TypeError: undefined is not a function backbone-0.9.1.js:1064
The first error is complaining about jQuery not being defined, and the second about $ not being defined.
Why isn't this working? Everything seems to be loading in the right order, the order plugin works OK for underscore and backbone, and I can use $ in the code for normal jQuery functions.

Inlcuding AMD javascript as non-AMD results in library is undefined in all sorts of DOM waiting mechanisms

Trying to create an AMD Javascript library to be included in non-AMD projects. Here's my setup:
app.coffee
define ->
class App
constructor: -> console.log 'instantiating App'
init: -> console.log 'Init called'
index.html
<body>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="dev-latest.js"></script>
<script type="text/javascript">
$(document).ready(function(){
console.log('doc', window.app);
});
$(function(){
console.log('func', window.app);
});
window.onload = function()
{
console.log('onload', window.app);
}
</script></body>
main.js
require(['cs!app'], function(app){
return window.app = new app;
});
I am building this project with r.js optimizer to get dev-latest.js as the output. Here's my build file (PS: Build is successful):
({
baseUrl: './vendor',
paths: {
app: '../app',
'require-lib': 'require'
},
name: '../main',
out: 'dev-latest.js',
include: 'require-lib',
preserveLicenseComments: false
})
When running the code in the browser here's the output:
doc undefined
func undefined
onload undefined
instantiating App dev-latest.js:1
app.init(); // running this manually in the browser console
Init called
How should I go about this and get app to load before being used ?
Using AMD you cant rely on a module being created outside of a module. The only reliable way is to load the result of a module into another module. So in your case need to create a new module which then can lsiten to $.read:
define( [App], (App)->
$(document).ready(function(){
console.log('doc', App);
});
)
Solved it by using browserify (just found about it) which uses the CommonJS form of dependency loading and saves all that clutter. Also a great template for starting projects is amitayd's grunt-browserify-jasmine setup

Categories