Loading hyperagent with require.js - requirejs

I've used bower to install hyperagent, and it pulled down some dependencies, I'm just not sure how to properly initialise it now.
As far as I call tell, it doesn't support AMD loading, so I'm trying to use a shim config. I've tried a few things, looking something like this:
<script src="{{ path('root') }}bower/requirejs/require.js"></script>
<script>
require.config({
"baseUrl": "{{ url('root') }}/bower/",
paths: {
"vue": 'vue/dist/vue.min',
"hyperagent": 'hyperagent/dist/hyperagent',
"jquery": "jquery/jquery.min",
"uri": "uri.js/src/URI.min"
},
shim: {
'hyperagent': {
'deps': ['jquery', 'uri'],
'exports': 'Hyperagent'
}
}
});
</script>
When I later do
require(['vue', 'hyperagent'], function(Vue, Hyperagent) { ... });
Hyperagent is undefined.
Am I way off the mark? (Oh, and the mustaches are twig, this is a Symfony project)

Thanks to Ben Weiner for this one. Taken from here.
I installed hyperagent and URIjs via bower and for now I'm just setting window.URI as a global before requiring hyperagent. Here's the relevant part of my require.js config:
require.config({
paths: {
'hyperagent': '../bower_components/hyperagent/dist/amd/hyperagent',
'URIjs': '../bower_components/uri.js/src',
}
});
To use it I just define an amd module that returns a configured hyperagent eg configured_hyperagent.js:
define(function(require) {
window.URI = require('URIjs/URI');
window.URITemplate = require('URIjs/URITemplate');
Hyperagent = require('hyperagent');
// Hyperagent.configure() etc..
return Hyperagent;
});

Related

Using bootbox in RequireJS app

I have a sample app.js file with:
requirejs.config({
"baseUrl": "js/lib",
"paths": {
"jquery": "jquery",
"app": "../app",
"bootstrap": "bootstrap/js/bootstrap.bundle",
"bootbox": "bootbox.min"
},
"shim": {
"bootstrap": {
"deps": ["jquery"],
"exports": 'bootbox'
},
"main": { "deps": ["jquery","bootstrap"] },
"bootbox": {
"deps": ["jquery","bootstrap"],
"exports": 'bootbox'
},
}
});
require(['jquery','bootstrap','bootbox'], function($){
$(function(jquery) {
bootbox.alert("bla")
});
});
When I run my page, I can see the correct JS files being grabbed:
...yet my code fails:
bootbox.alert("bla")
Gives:
ReferenceError: bootbox is not defined
I must be missing something simple (again, apologies if this is a newbie error - I'm still trying to get my head around this library)
Don't use shim with Bootbox. If you look at the source code of Bootbox, you'll see it calls define, which registers it as a proper AMD module. The shim option is only for code which is not a proper AMD module.
Now, the define in Bootbox does this:
define(["jquery"], factory);
It sets a dependency on jQuery, but that is wrong, because in fact Bootbox also depends on Bootstrap being present. So we need to fix this. The following shows how you can fix it. You can use a map configuration option so that when Bootbox requires jQuery, it gets Bootstrap. And you set a shim for Bootstrap so that, in addition to having a dependency on jQuery, its module value is the same as jQuery ($).
Without the map setup, there's no guarantee that Bootstrap will load before Bootbox and you'll be facing a race condition: sometimes it'll work, sometimes not.
requirejs.config({
baseUrl: ".",
paths: {
jquery: "//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min",
bootstrap: "//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min",
bootbox: "//github.com/makeusabrew/bootbox/releases/download/v4.4.0/bootbox.min"
},
shim: {
"bootstrap": {
"deps": ["jquery"],
// We set bootstrap up so that when we require it, the value with get is just $.
// This enables the map below.
"exports": "$"
},
},
map: {
// When bootbox requires jquery, give it bootstrap instead. This makes it so that
// bootstrap is **necessarily** loaded before bootbox.
bootbox: {
jquery: "bootstrap",
},
}
});
require(["jquery", "bootbox"], function($, bootbox) {
$(function(jquery) {
bootbox.alert("bla");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

How to add AMD/legacy dependency (leaflet) with sub dependencies in requirejs

I installed a AMD module called leaflet and successfully using it as "L".
Next I need a plugin called leaflet.draw but I get confused about the dependencies. Consider the following code:
requirejs.config({
baseUrl: 'bower_components',
paths: {
leaflet: 'leaflet/dist/leaflet-src',
leafletdraw: 'leaflet-draw/dist/leaflet.draw-src'
...
requirejs(["leaflet", "leafletdraw"], function(L, leafletdraw) {
var map = new L.Map('map');
...
This gives a referenceError: L is not defined at Leaflet.draw.js:4. So I guess it needs the leaflet (L) as a dependency, right? I then tried to add it in the shim config:
shim: {
leafletdraw: {
deps: 'leaflet'
}
}
This results in a "Invalid require call". So my question is: How do I properly require a plugin with subdependencies?
The modules are installed with "bower install leaflet" and "bower
install leaflet-draw" respectivily. But im not sure if leaflet-draw
is AMD enabled. Why isnt that stated in repos docs? Can I assume it
is enabled by default?
This is what I try to achive:
http://codepen.io/osmbuildings/pen/LVJzWw, but with requirejs.
Solution: shim leaflet itself, and let it export 'L'. Then putting the deps in plugins will work. My full config:
requirejs.config({
baseUrl: 'bower_components',
paths: {
jquery: 'jquery/dist/jquery.min',
leaflet: 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet',
'leaflet-draw': 'http://cdn.osmbuildings.org/Leaflet.draw/0.2.0/leaflet.draw',
OSMBuildings: ['http://cdn.osmbuildings.org/OSMBuildings-Leaflet']
},
shim: {
leaflet: {
exports: 'L'
},
'leaflet-draw': {
deps: ['leaflet']
},
OSMBuildings: {
deps: ['leaflet'],
exports: 'OSMBuildings'
}
}
});
requirejs(["jquery", "leaflet", "leaflet-draw", "OSMBuildings"], function($, L, dummy, OSMBuildings) {
var map = new L.Map('map');

require js beginner - dependency injection

I'm a beginner with require js and I have a doubt here.
My files are structured like below:
root
|____assets
|____bootstrap-3.0.1
|________dist
|____________js
|____________bootstrap.min.js
|________js
|________angulajs.min.js
|________app.js
|________jquery.min.js
|________underscorejs-min.js
|____________app
|________________main.js
My app.js file is like below:
requirejs.config({
"baseUrl": "assets/js",
"paths": {
": "app",
"jquery": "jquery.min",
"jquery-migrate": "jquery-migrate.min",
"twitter-bootstrap": "../bootstrap-3.1.0/dist/js/bootstrap.min",
"underscore": "underscore-min"
},
"shim": {
"twitter-bootstrap": {
deps: [ "jquery" ]
}
}
});
requirejs(["app/main"]);
My main.js is like below:
define([ "jquery", "twitter-bootstrap" ], function($) {
$(function() {
$("#teste").tooltip();
});
});
My question is about the main file and the dependency jquery in the case of bootstrap. If I had declare that the Bootstrap depends on jQuery I still have to include "jquery" in define function?
I tried to remove "jquery" declaration but the dependency was not injected and I received a undefined error.
Thanks for any help!
Doing it like this is really the way to go:
define([ "jquery", "twitter-bootstrap" ], function($) {
$(function() {
$("#teste").tooltip();
});
});
In the code above, it is clear that $ should be bound to the jquery module. If you do this:
define(["twitter-bootstrap" ], function($) {
$(function() {
$("#teste").tooltip();
});
});
You are binding $ to the twitter-bootstrap module. This won't work without further configuration because twitter-bootstrap exports nothing. (It installs itself as a jQuery plugin.) You could work around it by setting your shim like this:
"shim": {
"twitter-bootstrap": {
deps: [ "jquery" ],
exports: '$.fn.tooltip',
init: function ($) { return $; }
}
}
However, I don't recommend this since someone who comes across the code without knowing the context (that is, not knowing the relationship between the jquery and twitter-bootstrap modules) won't readily know what is going on.
In the shim above the exports field is not absolutely necessary but it help RequireJS know when Bootstrap has been loaded. It should be a symbol that does not exist prior to Bootstrap being loaded but exists after it is loaded.

whats the correct way to define custom builds of vendor libraries in bower_components?

I am using the yeoman webapp generator with requirejs and I have installed canjs using bower.
canjs has a dir structure like the following
app/bower_components/canjs/amd/can.js
app/bower_components/canjs/amd/can/control.js
app/bower_components/canjs/amd/can/control/route.js
etc..
Inside the can.js file is the following.
define(["can/util/library", "can/control/route", "can/model", "can/view/ejs", "can/route"], function(can) {
return can;
});
All of the dependancy files (control.js, route.js) have their dependancies listed inside define() functions.
What I want to do is customise the canjs build and replace "can/view/ejs" with "can/view/mustache". I can get it to work by changing the reference to ejs within the can.js file but that means I'm editing a vendor file inside of bower_components dir.
I have tried to create a mycan.js build within my scripts dir which looks the same as the can.js file (except for the mustache dependency change) in bower_components and then I change the config to look like this.
require.config({
paths: {
jquery: '../bower_components/jquery/jquery',
can: '../bower_components/canjs/amd/can',
etc..
Then I require the mycan module in any of my files that need it.
This will work properly if I comment out the code inside bower_components/canjs/amd/can.js but if I don't comment the file out, it will require both builds (including the can/view/ejs file I didn't want).
In the require docs http://requirejs.org/docs/api.html under usage 1.1, it has an example of
• www/
• index.html
• js/
• app/
• sub.js
• lib/
• jquery.js
• canvas.js
• app.js
and in app.js:
requirejs.config({
//By default load any module IDs from js/lib
baseUrl: 'js/lib',
//except, if the module ID starts with "app",
//load it from the js/app directory. paths
//config is relative to the baseUrl, and
//never includes a ".js" extension since
//the paths config could be for a directory.
paths: {
app: '../app'
}
});
// Start the main app logic.
requirejs(['jquery', 'canvas', 'app/sub'],
function ($, canvas, sub) {
//jQuery, canvas and the app/sub module are all
//loaded and can be used here now.
});
Here they are using a path which is a directory, not a file. The sub module is getting found because it matches app/sub with the app in the paths config.
If I define my own version of can within the main.js file which contains the require.config then it seems to work but then when I go to build the app, it says
tim#machine:~/server/javascript/yoman:ruby-1.9.3: (master)$ grunt
Running "jshint:all" (jshint) task
Linting app/scripts/main.js ...ERROR
[L54:C1] W117: 'define' is not defined.
define('can', [
Warning: Task "jshint:all" failed. Use --force to continue.
Aborted due to warnings.
Elapsed time
default 567ms
jshint:all 124ms
Total 691ms
Whats the correct way for me to make a custom build of vendor libraries within bower_components?
Here is my main.js. This version works but fails when linting.
require.config({
paths: {
jquery: '../bower_components/jquery/jquery',
bootstrapAffix: '../bower_components/sass-bootstrap/js/affix',
bootstrapAlert: '../bower_components/sass-bootstrap/js/alert',
bootstrapButton: '../bower_components/sass-bootstrap/js/button',
bootstrapCarousel: '../bower_components/sass-bootstrap/js/carousel',
bootstrapCollapse: '../bower_components/sass-bootstrap/js/collapse',
bootstrapDropdown: '../bower_components/sass-bootstrap/js/dropdown',
bootstrapPopover: '../bower_components/sass-bootstrap/js/popover',
bootstrapScrollspy: '../bower_components/sass-bootstrap/js/scrollspy',
bootstrapTab: '../bower_components/sass-bootstrap/js/tab',
bootstrapTooltip: '../bower_components/sass-bootstrap/js/tooltip',
bootstrapTransition: '../bower_components/sass-bootstrap/js/transition',
can: '../bower_components/canjs/amd/can'
},
shim: {
bootstrapAffix: {
deps: ['jquery']
},
bootstrapAlert: {
deps: ['jquery']
},
bootstrapButton: {
deps: ['jquery']
},
bootstrapCarousel: {
deps: ['jquery']
},
bootstrapCollapse: {
deps: ['jquery']
},
bootstrapDropdown: {
deps: ['jquery']
},
bootstrapPopover: {
deps: ['jquery']
},
bootstrapScrollspy: {
deps: ['jquery']
},
bootstrapTab: {
deps: ['jquery']
},
bootstrapTooltip: {
deps: ['jquery']
},
bootstrapTransition: {
deps: ['jquery']
}
}
});
define('can', [
'can/util/library',
'can/control/route',
'can/construct/proxy',
'can/model',
'can/view/mustache',
'can/route'
], function(can) {
'use strict';
return can;
});
require(['app', 'jquery'], function (app, $) {
'use strict';
// use app here
console.log(app);
console.log('Running jQuery %s', $().jquery);
});
JSHint is complaining because require is in an external file. All require's functions are defined before your script loads, but because they're not inside the script JSHint thinks they're custom code which you forgot to define. This is an easy fix; add a predef config so that define, require are already passed to JSHint before it starts linting your files.
jshint: {
options: {
// all of your other options...
predef: ['define', 'require']
},
files : ['app/scripts/main.js']
},

Configure grunt watch to run Jasmine tests against an app using requirejs

In an attempt to level up my general coding skills... and to learn something new.
I've started attempting to wire up a front end only solution consisting of
Durandal
Jasmine - [added via npm]
Grunt Watch to monitor & run my tests as my code files change - [added via npm]
Feel free to correct me, as this is all based on my experimentation in the last 2 days. Most of this is new to me. My goal is to have something similar as to what angular has with karma.
Now I am aware that that the Durandal project (comes with a custom spec runner, as found in the github solution)
My setup:
gruntfile.js
module.exports = function(grunt) {
var appPath = 'App/viewmodels/*.js';
var testPath = 'Tests/**/*.js';
grunt.initConfig({
jasmine: {
pivotal: {
src: appPath,
options: {
specs: testPath,
template: require('grunt-template-jasmine-requirejs'),
templateOptions: {
requireConfigFile: 'SpecRunner.js'
}
}
}
},
jshint: {
all: [testPath, appPath],
options: {
curly: true
}
},
watch: {
files: [testPath, appPath],
tasks: ['jshint','jasmine']
}
});
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint','jasmine']);
};
SpecRunner.js
require.config({
paths: {
jquery: 'Scripts/jquery-1.9.1',
knockout: 'Scripts/knockout-2.3.0'
},
shim: {
knockout: {
exports: "ko"
}
}
});
When I run grunt, I get a Illegal path or script error: ['plugins/http']
(I've sorted out the ko issue in the screenshot)
Question:
How would i go about setting up my gruntfile to require any dependencies. I'm quite new to require, and I'm not sure how to configure it to make my tests aware of where to find things like 3rd party libraries and other custom js files for that matter
SpecRunner require.config is missing Durandal specific path information. If you set the baseUrl to 'App' then the paths below matches the HTML samples or StarterKit layout. If your layout is different you'd have to adjust this accordingly.
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-2.3.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1'
}
});

Resources