Using Handsontable with RequireJS - requirejs

When shimming Handsontable with requirejs I keep getting the following error and stack trace
Uncaught TypeError: undefined is not a function VM18361 handsontable.full.js:20729
unformatNumeral VM18361 handsontable.full.js:21325
numeral.fn.Numeral.unformat VM18361 handsontable.full.js:21325
numeral VM18361 handsontable.full.js:21037
This happens even with the examples from http://handsontable.com/.
My requirejs config and the module using handsontable look like this
require.config({
paths: {
handsontable : '/js/dependencies/handsontable.full'
},
shim: {
'handsontable': {
deps: ['jquery'],
exports: 'Handsontable'
}
}
define(['handsontable'], function(Handsontable) {
var data = [
['', 'Maserati', 'Mazda', 'Mercedes', 'Mini', 'Mitsubishi'],
['2009', 0, 2941, 4303, 354, 5814],
['2010', 3, 2905, 2867, 412, 5284],
['2011', 4, 2517, 4822, 552, 6127],
['2012', 2, 2422, 5399, 776, 4151]
];
var container = document.getElementById('example');
var config = {
data: data,
minSpareRows: 1,
colHeaders: true,
contextMenu: true
};
var hot = new Handsontable(container, config);
});
Does anyone else experience this problem?
For now, the only solution I can see is including handsontable as a global object (circumventing the whole purpose of requirejs of managing dependencies).
I'd appreciate a better solution.
Thanks!

I believe the issue here is that you are using the full version of Handsontable, which includes dependencies, such as Numeral.js. Since some of the dependencies are AMD compliant, i.e. there is a call to define(), you end up with the reference to Numeral.js and not Handsontable.
To use it correctly, you'll need to use just bare distribution file, handsontable.js, and include all the dependencies required for that version of Handsontable. Something like this:
require.config({
paths: {
handsontable : '/js/dependencies/handsontable'
},
shim: {
'handsontable': {
deps: ['moment', 'pikaday', 'zeroclipboard'],
exports: 'Handsontable'
}
}
})
I'm not sure which version of Handsontable you are using, the current version, 0.20.3, depends on moment, pikaday, and zeroclipboard. See the dist/READEME.md for more information.

Related

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');

Automatically load postrequisite files

I'm looking to automatically load dependant files, similarly to how deps works however these files need to be loaded AFTER the initially requested.
For example:
require.config({
baseUrl: '/',
paths: {
jquery: '/assets/components/jquery/dist/jquery.min',
highcharts: '/assets/components/highcharts/highcharts.js',
'highcharts.more': '/assets/components/highcharts/highcharts-more.js'
},
shim: {
jquery: { exports: 'jQuery' },
highcharts: { deps: ['jquery'] },
'highcharts.more' : { deps: ['highcharts'] },
}
});
define(function (require) {
var app = require('assets/js/app');
app.start();
});
When requiring highcharts, jQuery will automatically be loaded as a dependant, however Highcharts requires that you load two files.
Does anyone know how I can load postrequisite files, i.e. after loading highcharts to automatically load highcharts.more.
I could simply set highcharts a dependency of highcharts-more and load highcharts-more however hoped there was a cleaner way?
Hope this makes sense?!
Thanks
Gav
Loading highcharts.more and making it a dependency of highcharts is the way to go. You can also hide highcharts.more from your modules by using a map configuration:
map: {
"*": {
highcharts: "highcharts.more"
},
"highcharts.more": {
highcharts: "highcharts"
}
}
The mapping above says "in all modules (*) when highcharts is requested, load highcharts.more instead, but in highcharts.more when highcharts is requested load highcharts".
With this, you can just list highcharts as a dependency in your actual modules.

Should requirejs be included in the main built file when using the requirejs bundles option

I'm running into an issue when using the require bundles option. If the main built file has requirejs inside of it everything works fine until I try to load a file from a different bundle. The bundled file is retrieved but then throws an "define is undefined" error. The only way I have been able to get the bundle to load is to make sure requirejs is not in the main-built file or the pm.js and then to load requirejs with a script tag and use the data-main attribute, but this doesn't seem right.
So something like this initially works when requirejs is included in main-built.js (site loads fine), but I get the "define is undefined" error when pm.js bundle loads
<script type="text/javascript" src="~/dist/main-built.js"></script>
requirejs.config({
bundles: {
'pm': ['pm/dashboard', 'text!pm/dashboard.html']
}
});
This is how I ended up getting it to work, but doesn't seem right.
<script type="text/javascript" src="~/scripts/require.js" data-main="dist/main-debug")"></script>
This durandal task creates the main-built file
durandal: {
main: {
src: ["app/**/*.*", "scripts/durandal/**/*.*", "!app/mockup/**/*.*", "!app/performancemanagement/**/*.*"],
options: {
//name: "scripts/require",
name: "",
baseUrl: requireConfig.baseUrl,
paths: mixIn({}, requireConfig.paths, { "require": "scripts/require.js" }),
exclude: ["jquery", "knockout", "toastr", "moment", "underscore", "amplify"],
optimize: "none",
out: "dist/main-debug.js"
}
},
},
This task builds the pm.js bundle
requirejs: {
compile: {
options: {
include: generateFileList("app/pm", "**/*.*", false, false),
//exclude: ["jquery", "knockout", "toastr", "moment", "underscore", "amplify", "preferenceconstants", "constants", "config", "utility/koutilities", "scripts/logger", "base/viewmodel"]
// .concat(generateFileList("scripts/durandal", "**/*.js", false))
// .concat(generateFileList("app/dataservice", "**/*.js", false))
// .concat(generateFileList("app/model", "**/*.js", false))
// .concat(generateFileList("app/reports", "**/*.js", false)),
baseUrl: "app/",
name: "",
paths: mixIn({}, requireConfig.paths, { "almond": "scripts/almond-custom.js" }),
optimize: 'none',
inlineText: true,
pragmas: {
build: true
},
stubModules: ['text'],
out: "dist/pm.js"
}
}
}
The pm.js bundle gets downloaded and executed when anything in main-built requires it, right now its being done by the router in Durandal, but I'm pretty sure Durandal has nothing to do with the issue.
This appears suspicious in your main file build:
paths: mixIn({}, requireConfig.paths, { "require": "scripts/require.js" }),
I'm not sure what the mixIn bit does as this is not stock RequireJS code, but you seem to want to include RequireJS in the build under the name require, which is definitely wrong. The documentation says:
If you want to include require.js with the main.js source, you can use this kind of command:
node ../../r.js -o baseUrl=. paths.requireLib=../../require name=main include=requireLib out=main-built.js
Since "require" is a reserved dependency name, you create a "requireLib" dependency and map it to the require.js file.

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'
}
});

RequireJS + Optimizer Include modules defined on the main file

I'm using Optimizer for the first time and I am running in some issues or questions.
I'm trying to optimize a main file and it puts, like I've expected, the jQuery, Backbone and Require modules ( and uses then across the whole navigation). But let's say I have a jQuery Plugin that I use on several views. I've tried to add it in the main file using the "include" option on the build.js file. It adds it ( e.g jQuery Slides ) but as I have a view with define("jquery-slides") ( again, an example ) the browser loads the file of the plugin again. Even if it is on the main built file.
Is this suppose to happen? Can I fix this?
Thanks.
Here is some code. Hope it helps =)
build.js
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
name: "main-site",
include: ['libs/requirejs/require', jquery-slides'],
insertRequire: ['main-site'],
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
}
}
main-site.js
require.config({
baseUrl: "/javascripts/",
paths: {
'jquery': 'libs/jquery/jquery',
'underscore': 'libs/underscore/underscore',
'bootstrap': 'libs/bootstrap/bootstrap.min',
'datepicker': 'libs/bootstrap/plugins/bootstrap-datepicker',
'backbone': 'libs/backbone/backbone.max',
'backbone-paginator': 'libs/backbone/plugins/backbone.paginator',
'backbone-validation': 'libs/backbone/plugins/backbone.validation',
'text': 'libs/requirejs/text',
'templates': '/templates/site',
'views': 'views/site',
'jquery-cookie': 'libs/jquery/plugins/jquery.cookie',
'jquery-raty': 'libs/jquery/plugins/jquery.raty.min',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
shim: {
'backbone-paginator': ['backbone'],
'bootstrap': ['jquery'],
'datepicker': ['bootstrap'],
'jquery-cookies': ['jquery'],
'jquery-raty': ['jquery'],
'jquery-slides': ['jquery'],
'backbone-validation': ['backbone']
}
});
require([
'app-site'
], function(App) {
$(function(){
App.initialize();
});
});
Instead of using include I recommend you to declare the modules you want to build. In this way requirejs will package the module and all its dependencies in the optimized bundle.
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
modules : [
{
name : 'main-site',
}
]
}
Further considerations:
If you have jquery-slides included as a dependency in any of your modules define(['jquery-slides'], function() {... } you don't need to use the include directive since all the dependencies of that module will be included in the optimized file
See the documentation of the modules property in this link
https://github.com/jrburke/r.js/blob/master/build/example.build.js#L330
Use the property mainConfigFile to avoid duplications https://github.com/jrburke/r.js/blob/master/build/example.build.js#L35
Good luck and I hope this helps you

Resources