External library variable not defined - javascript

I'm trying to include a javascript library (WaveSurfer) into my Angular app (Using Mean.io).
The problem is a warning appears into the console each time I run grunt :
In packages\tracks\public\services\tracks.js :
'WaveSurfer' is not defined.
Here is the code of my different files:
public/controllers/tracks.js
angular.module('mean').controller('PlayerController', ['$scope', 'Global', 'Tracks','myWaveSurfer',
function($scope, Global,Tracks, myWaveSurfer) {
$scope.global = Global;
//Player WaveSurfer
var wavesurfer = Object.create(myWaveSurfer);
wavesurfer.load('music.mp3');
public/services/tracks.js
angular.module('mean.tracks').factory('myWaveSurfer', function() {
return WaveSurfer; /*Warning here*/
});
The content of the wavesurfer.min.js looks like :
var WaveSurfer = {
defaultParams: {...}
init: function(params) {...}
...
}
I included correctly the library into config/assets.json so the library can be loaded.
I can see it on the Chrome console :
<script type="text/javascript" src="/bower_components/wavesurfer.js/build/wavesurfer.min.js"></script>
It only works with grunt --force but is there a solution to include properly this library without warning ?
Thanks in advance !

I assume you are inside the Node env.
Add this to your globals:
GLOBAL.WaveSurfer = {};
Or you could pull it in with require
GLOBAL.WaveSurfer = require('...');
If you require make sure the library module.exports the global object.

Related

Error while requiring external library with browserify (this = undefined)

I'm trying to require the library Chart.js with Browserify (tbh it's development environment with gulp, browserify and some other stuff that I barely know how it works togheter):
'use strict';
var angular = require('angular');
require('angular-ui-router');
require('./templates');
require('./controllers/_index');
require('./services/_index');
require('./directives/_index');
window.gauge = require('./vendors/gauge');
//this is what i'm trying to require
window.chartjs = require('./vendors/chart');
angular.element(document).ready(function() {
var requires = [
'ui.router',
'templates',
'app.controllers',
'app.services',
'app.directives'
];
window.app = angular.module('app', requires);
angular.module('app').constant('AppSettings', require('./constants'));
angular.module('app').config(require('./routes'));
angular.module('app').config(require('./PostFix'));
angular.module('app').run(require('./on_run'));
angular.bootstrap(document, ['app']);
});
Tbh it did work well with window.gauge = require('./vendors/gauge'); but when I require vendors/chart.js it throws this error:
undefined // chart.js:4
Uncaught TypeError: Cannot read property 'Chart' of undefined // chart.js:4
And here is those lines in the chart.js file:
(function(){
"use strict";
console.log(this); <------ outputs the "undefined"
var root = this,
previous = root.Chart; <----- fails, as "root" doesn't exist
It's weird, because when I add chart.js using <script></script> that console.log(this) outputs the window object/scope, but when executed from browserify, it's undefined, that's why the chart.js fails.
I'm a total newb with browserify/node/gulp, but I tried different stuff such as:
Browserify-shim -> same error
Requiring the script in different ways, like trying to require it inside an object { }, trying to do a var whatever = new require('./vendors/chart') but failed miserably like a beheaded chicken trying to go to the bathroom.
I'm guessing that somehow I have to attach that script to an object or something so this would not be undefined when executed, but I'm failing to find the way.
I already solved it. The problem was a browserify transform called Babelify. I still don't know why Babel was doing that, but I didn't need it anyway so I just disabled it and that was it. Just posting it here in case it happens to someone else.

Sharing global variables between javascript files loaded to Meteor

I have a javascript file that I place in the client/lib folder within my Meteor app. As the file grew bigger, I decided to split it into 3 files and define an object 'App' in the global namespace in order for the 3 files to share the data.
Each file starts with
var app = app || {};
(function () {
'use strict';
app.object1 = {
This way, file2 and file3 can still use app.object1, and so on.
The problem is when Meteor loads the files, it seems to automatically wraps it with function(){}, and this makes app.object1 not accessible from files loaded subsequently.
(function(){
var app = app || {};
(function () {
'use strict';
app.object1 = {
What is the best way to avoid this issue? Thanks.
EDIT: I referred to this posting [Link:][1]Global variables in Meteor which suggests defining the variable without "var". I replaced the code in file1 to app = {}, but my app is now crashing in file2 in the following line of code, with the message from the Meteor console pasted below.
app.ALL_LIST = 'all'
=> Your application is crashing. Waiting for file change.
ReferenceError: app is not defined
omit var in your variable declaration ;) then it will be scoped globally.

RequireJS plugin: load timeouts experienced when using plugin

Using RequireJS I'm building an app which make extensive use of widgets. For each widget I have at least 3 separate files:
request.js containing code for setting up request/response handlers to request a widget in another part of my application
controller.js containing handling between model and view
view.js containing handling between user and controller
Module definition in request.js:
define(['common/view/widget/entity/term/list/table/controller'],
function(WidgetController) { ... });
Module definition in controller.js:
define(['common/view/widget/entity/term/list/table/view'],
function(WidgetView) { ... });
Module definition of view.js is:
define(['module','require'],function(module,require) {
'use strict';
var WidgetView = <constructor definition>;
return WidgetView;
});
I have lots of these little situations as above in the case of widgets I have developed. What I dislike is using the full path every time when a module is requiring another module and both are located in the same folder. I'd like to simply specify as follows (assuming we have a RequireJS plugin which solves this for us):
define(['currentfolder!controller'],
function(WidgetController) { ... });
For this, I have written a small plugin, as I couldn't find it on the web:
define({
load: function (name, parentRequire, onload, config) {
var path = parentRequire.toUrl('.').substring(config.baseUrl.length) + '/' + name;
parentRequire([path], function (value) {
onload(value);
});
}
});
As you might notice, in its basic form it looks like the example of the RequireJS plugins documentation.
Now in some cases, the above works fine (e.g. from the request.js to the controller.js), but in other cases a load timeout occurs (from controller.js to view.js). When I look at the paths which are generated, all are proper RequireJS paths. Looking at the load timeouts, the following is logged:
Timestamp: 13-09-13 17:27:10
Error: Error: Load timeout for modules: currentfolder!view_unnormalized2,currentfolder!view
http://requirejs.org/docs/errors.html#timeout
Source File: http://localhost/app/vendor/requirejs/require.js?msv15z
Line: 159
The above log was from a test I did with only loading the view.js from controller.js using currentfolder!view in the list of modules in the define statement. Since I only requested currentfolder!view once, I'm confused as to why I both see currentfolder!view_unnormalized2 and currentfolder!view in the message.
Any idea as to why this might be happening?
My answer may not answer your primary questions, but it will help you achieve what you're trying to do with your plugin.
In fact, Require.js support relative paths for requiring modules when using CommonJS style. Like so:
define(function( require, exports, module ) {
var relativeModule = require("./subfolder/module");
module.exports = function() {
console.log( relativeModule );
};
});

Relative paths with RequireJS modules/packages

I'm fairly new to RequireJS and I've run into a bit of a problem. I've written a little framework built on Backbone using RequireJS and I want it to be re-usable in different projects. So, with some searching I learned that require allows packages. This seemed like what I was looking for. I have a main.js file to launch my app that essentially looks like this:
require.config({
packages: ['framework']
});
require(['framework'], function(framework) {
framework.createDash();
});
Then in the same directory as my main.js I have another directory called "framework" which contains another main.js which looks like this:
define(function(require, exports, module) {
exports.createDash = function(dash, element) {
require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) {
return new DashView({
model: new DashModel(dash),
el: element ? element : window
});
});
};
});
In searching I found this page which indicates that the 'require' argument should be scoped to the submodule. However, when I try to require things they are still relative to my original main.js. I've tried a number of things and searched for hours to no avail. Is there any way I can have my require/define calls within my package included relative to the main.js in it's root?
You need to define your submodule as package in the require configuration:
require.config({
packages: [
{ name: 'packagename',
location: 'path/to/your/package/root', // default 'packagename'
main: 'scriptfileToLoad' // default 'main'
}]
... some other stuff ...
});
To load your module you just need to use your 'packagename' at the requirements:
define(['jquery', 'packagename'], function($, MyPackage) {
MyPackage.useIt()
});
In your package you must use the ./ prefix to load your files relative to your submodule:
define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
LocalFile.finallyLoaded();
});
There is a useful shortcut: If your package name equals to your location and your main file is called 'main.js', then you can replace this
packages: [
{ name: 'packagename',
location: 'packagename',
main: 'main'
}]
to this:
packages: ['packagename']
As far as I can see, you already tried to define a package but did you also use the ./ prefix? Without this prefix require will try to find the files in it's global root-path. And without a package, ./ will be useless because the relative path is the same as the global root-path.
Cheers
I figured out the answer to my question, and the solution (they were not the same apparently). I guess I'll post it here in case it can help someone else in the future.
Essentially what I was wanting was to load my framework within its own context. I found the context option under the configuration section on require's website and an example of how to use it. Originally I tried this by doing something like:
var req = require.config({
baseUrl: 'framework',
context: 'framework',
paths: {
jQuery: 'lib/jquery/jquery-1.7.min.js',
Underscore: 'lib/underscore/underscore.min.js',
Backbone: 'lib/backbone/backbone.min.js',
etc...
}
});
req(['main'], function() {});
There were two problems with this. First, my 'req' variable was being defined outside of the framework, but I wanted the framework to define it's own paths. And second, whenever a file outside of the framework would require a file within the framework, which would in turn require 'jQuery', for example, then jQuery (or whatever else) wouldn't be required from within the context of the framework instance of require and so it couldn't find the file.
What I ended up doing was defining my framework's main.js to look something like this:
var paths = {
jQuery: 'lib/jquery/jquery-1.7.min.js',
Underscore: 'lib/underscore/underscore.min.js',
Backbone: 'lib/backbone/backbone.min.js',
etc...
};
define(function() {
var exports = {};
exports.initialize = function(baseUrl, overridePaths, callback) {
if(!overridePaths) {
overridePaths = {};
}
if(baseUrl && baseUrl[baseUrl.length - 1] != '/') {
baseUrl = baseUrl + '/';
}
var fullpaths = {};
for(var path in paths) {
// Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash
if(paths[path].match(/^(?:.*:\/\/|\/)/)) {
fullpaths[path] = paths[path];
}
else {
fullpaths[path] = baseUrl + paths[path];
}
}
var config = {paths: fullpaths};
for(var pathName in overridePaths) {
config.paths[pathName] = overridePaths[pathName];
}
require.config(config);
// Do anything else you need to do such as defining more functions for exports
if(callback) {
callback();
}
}
return exports;
});
And then in my project's main.js file I just do this:
require(['framework/main'], function(framework) {
// NOTE: This setTimeout() call is used because, for whatever reason, if you make
// a 'require' call in here or in the framework without it, it will just hang
// and never actually go fetch the files in the browser. There's probably a
// better way to handle this, but I don't know what it is.
setTimeout(function() {
framework.initialize('framework', null, function() {
// Do stuff here
}
}, 0);
});
This takes whatever is passed in to the framework's initialize() method for 'baseURL' and prepends that to any paths that the framework defines that do not start with a forward slash or 'anything://', unless they are override paths. This allows the package using the framework to override things like 'jQuery'.
This worked for me, adding a "./" prefix to the module names:
define(function (require, exports, module) {
exports.createDash = function (dash, element) {
require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) {
return new DashView({
model : new DashModel(dash),
el : element ? element : window
});
});
};
});
A process that worked well for me for allowing a package with submodules to be used directly from data-main or from an outside framework, assuming that a main.js (or other package main) is called by a particular name, was to use var baseUrl = require.toUrl('packageName') + '/../' as a prefix to a require.config({ paths: { ... } }) configuration file. For instance:
var music21Base = require.toUrl('music21') + '/../';
require.config({ paths: {
'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min';
'subModuleLoader': music21Base + 'src/subModuleLoader';
} });
The setting of context: "xxx" worked fine for calling normal modules with ./modName but did not work for the paths argument for me.

node-qunit doesn't include my source files in scope

I've installed node-qunit (stable) from npm, but can't seem to get any tests working. My source files don't seem to be included in scope.
./source/myscript.js:
var myObj = {
a : true
}
./test/tests.js:
test("that a is true", function () {
ok(myObj.a);
});
./test/runner.js:
var runner = require('qunit');
runner.run({
code : './source/myscript.js',
tests : './test/tests.js'
});
./Makefile:
test :
<tab>node ./test/testrunner.js
.PHONY: install test
If I run make test, I get a 'ReferenceError: myObj is not defined' error. The source file does run, because it can throw errors. It just doesn't seem to be included in the global scope as it should. It doesn't work if I do it from the command line, as per the instructions in the node-qunit readme. Anyone have any idea how to get this working?
You're not exporting anything. Behind the scenes, node-qunit is using require to load the specified modules. To expose variables when a module is required, you have to add them to the exports object (or assign your own object to the exports variable)
(There's also a syntax error - ; in the object literal)
This works for me:
./source/myscript.js:
exports.myObj = {
a: true
}
./test/tests.js:
QUnit.module('tests')
test("that a is true", function () {
ok(myObj.a)
})
./test/runner.js:
var runner = require('qunit')
runner.run({
code : './source/myscript.js'
, tests : './test/tests.js'
})

Categories