adding json data using taffydb in durandal - javascript

I'm trying to use taffydb with durandal. I'm able to add simple json-data to a ko.observableArray() (a colleague showed me how :-) ).
Now I want to save it using taffydb.
main.js:
requirejs.config({
paths: {
'taffy': '../lib/db-master/taffy'
...
}
});
participant.js:
define(['durandal/app', 'knockout', 'models/user', 'taffy'], function (app, ko, user, taffy) {
...
}
Whenever I add this:
var db = taffy;
db.insert({record:1, data:"test"});
I get this error:
Uncaught TypeError: Cannot call method 'insert' of undefined
Leaving it out will add test-data as expected. Am I 'holding' durandal the wrong way?
regards
Claus

If this code is the one you are loading, then you need a shim in the configuration you pass to RequireJS because taffy is not AMD-aware. I believe this should work:
shim: {
taffy: {
exports: "TAFFY"
}
}
I've never used taffy so I'm not aware what its dependencies might be. You might need to add a deps: [...] field to the shim so that the dependencies are loaded ahead.

Related

Angular-formly trying to get api-check from a non-existing source

I'm trying to add angular-formly to my AngularJs application using RequireJS. I've added
'apiCheck': '../vendor/api-check/dist/api-check',
'formly': '../vendor/angular-formly/dist/formly',
and added shim;
'formly': {
exports: 'formly',
deps: ['angular', 'apiCheck']
},
But, when I look at the network, it gets both of the libraries by making correct calls. However, it creates another request (probably formly doing this) to get apiCheck from http://localhost:9000/assets/javascripts/api-check.js addess.
So far, I have tried to add apiCheck in shim and removing it from the formly dependencies etc.
How can I avoid this? It does not allow my application to run. Thanks...
I've solved my problem. It turns out that formly looks for api-check and I've defined dependency as apiCheck. Changing main.js like this worked;
'api-check': '../vendor/api-check/dist/api-check',
'formly': {
exports: 'formly',
deps: ['angular', 'api-check']
},

How to inject a dependency on an external script

I'm using a cloud service called Parse in a JavaScript closure injected with require.js:
define([/*some dependencies*/],
function(/*some dependencies*/) {
...
// using Parse. For example:
var TestObject = Parse.Object.extend("TestObject");
...
}
The tutorial for using Parse in Javascript instructs to include their script in the HTML header:
<script src="//www.parsecdn.com/js/parse-1.4.2.min.js"></script>
I don't want the HTML page to depend on Parse and I don't want to clutter the HTML with external scripts. Instead, I would like to require parse-1.4.2.min.js directly from the script. What's the proper way of doing so? How do I define this dependency and make it work?
Similar to jQuery, Parse adds itself to the global scope on load. If no other scripts depend on it, it can simply be included as a dependency in a module or require call.
require([
'https://www.parsecdn.com/js/parse-1.4.2.min.js',
], function () {
console.log(Parse);
}
If you are using any other non-AMD scripts that depend on Parse (or any other library) you will need to use a config/shim. It tells requireJS what order it should load the scripts, based on their dependencies.
E.g. when using a jQuery plugin, you wouldn't want it to load and execute before jQuery itself.
A config/paths setup also helps organise your project by allowing script locations to be defined in a single location and then included by reference.
See the requireJS docs for more info.
The following config/require successfully loads Parse and a fictional plugin:
require.config({
// define paths to be loaded, allows locations to be maintained in one place
paths: {
parse: 'https://www.parsecdn.com/js/parse-1.4.2.min',
plugin: 'example-non-amd-parse-plugin.js'
},
// define any non-amd libraries and their dependancies
shim: {
parse: {
exports: 'Parse'
},
plugin: {
exports: 'plugin',
deps: ['parse']
}
}
});
require(['parse'], function(Parse){
console.log(Parse);
});
// note Parse is not required
require(['plugin'], function(plugin){
// Parse is available as it is depended on by plugin and on the global scope
console.log(Parse, plugin);
});
So after all I just wrote this and it seems to work. Don't know what the problem was in the first place...
define(["https://www.parsecdn.com/js/parse-1.4.2.min.js"],
function () {

How to use require.js with complicated source tree, or import something else from CommonJS'es main.js?

My JS code is Backbone.js based, so I think it is a good idea to separate "classes" with this logic as shown on picture (though I'm not sure where to place templates - in this packages or in global templates folder, and do not mind main.js - it is not related to CommonJS packages) :
Now since there is fairly lot of them - I've decided to use require.js to deal with this bunch of <script src=... tags but got stuck with app.js config file (which is the only one that I include like this -
<script data-main="/static/js/app.js" src="/static/js/libmin/require.js"></script>
What do I mean with stuck - of course I can iterate all this js files in require statement using names like PlayerApp/PlayerAppController.js, or using paths directive (not sure if it will make the code look not that ugly), but it would be cool if I can use something like python's from package import *, and of course there is no such thing in require.js.
The most similar thing is packages directive, but seems like it allows you to import only main.js from each package, so then the question is - what is the most correct way to load other files of concrete package from CommonJS's main.js? I have even found a way to determine current .js file's name and path - like this, and given that I can make up other files names in current package(if I will keep naming them with the same pattern), but still do not know how to import them from main.js
Edit:
There might be an opinion that it is not very clear what exactly am I asking, so let me get this straight: how on Earth do I import a huge amount of javascript files with that project structure in the most nice way?
You are mis-understanding the purpose of a module loader. require.js is not there to make it easy for you to import all of your packages into the current namespace (i. e. the browser). It is there to make it easy to import everything you need to run app.js (based on your data-main attribute). Don't try to import * - instead, just import thingYouNeed.
Configuration
What you will want to do is set up your require.config() call with all the necessary paths for libraries like Backbone that don't support AMD and then update your code to explicitly declare its dependencies:
require.config({
// Not *needed* - will be derived from data-main otherwise
baseUrl: '/static/js/app',
paths: {
// A map of module names to paths (without the .js)
backbone: '../libmin/backbone',
underscore: '../libmin/underscore',
jquery: '../libmin/jquery.min',
jqueryui.core: '../libmin/jquery.ui.core'
// etc.
}
shim: {
// A map of module names to configs
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
jquery: {
exports: 'jQuery'
},
// Since jQuery UI does not export
// its own name we can just provide
// a deps array without the object
'jqueryui.core': ['jquery']
}
});
Dependencies
You will want to update your code to actually use modules and declare your dependencies:
// PlayerAppModel.js
define(['backbone'], function(Backbone) {
return Backbone.Model.extend({modelStuff: 'here'});
});
// PlayerAppView.js
define(['backbone'], function(Backbone) {
return Backbone.View.extend({viewStuff: 'here'});
});
// PlayerAppController.js
define(['./PlayerAppModel', './PlayerAppView'],
function(Model, View) {
// Do things with model and view here
// return a Controller function of some kind
return function Controller() {
// Handle some route or other
};
});
Now, when you require(['PlayerApp/PlayerAppController'], function(Controller) {}) requirejs will automatically load jQuery, underscore, and Backbone for you. If you never actually use mustache.js then it will never be loaded (and when you optimize your code using the r.js compiler, the extra code will be ignored there as well).

Using OpenLayers with RequireJS and AngularJS

I'm trying to get an app running that uses both AngularJS and RequireJS. I'm having problems getting my OpenLayers lib to work in this setup.
I set the main AMD-modules in the main.js:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
openLayers: 'vendor/openlayers-debug',
other modules.....
},
shim: {
angular: {
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
other modules....
}
}
);
require(['openLayers',
'angular',
'app',
'controllers/olMapController',
'directives/olMap',
other modules...
], function(OpenLayers) {
return OpenLayers;
}
);
Then in the angular controller I use for the initialisation of OpenLayers, I try to indicate that openlayers-debug.js is a dependency:
define(['openLayers'],
function(OpenLayers) {
controllers.controller('olMapController', ['$scope', function(scope) {
console.log('Loaded olMapController. OpenLayers version: ' + OpenLayers.VERSION_NUMBER);
}]);
}
);
Well, this doesn't work. SOMETIMES the olMapController function is executed, but mostly not. The console then just displays an error stating:
Error: [ng:areq] Argument 'olMapController' is not a function, got undefined
So, I think OpenLayers hasn't finished loading yet, but somehow require thinks it has and continues loading code that depends on OpenLayers, in this case the olMapController. It then can't find its dependency, whereupon Angular returns this error message. Or something like that...? Sometimes something happens that makes OpenLayers load fast enought for it to be present when it is loaded as a dependency. What that is, I can't tell.
I left out other libraries and modules require and define to keep the code readable. I hope the example is still understandable.
Any ideas on what I could do to get openlayers to load well? The error message disappears when I leave the ['openLayers'] dependency out of olMapController.
Thanks in advance for any help.
Best regards,
Martijn Senden
Well, just for reference my final solution. The comment by angabriel set me off in the right direction.
Like i said, I'm using the domReady module provided by RequireJS to bootstrap Angular. This is still being called to early, because OpenLayers isn't loaded yet when angular starts. RequireJS also provides a callback property in require.config. This is a function that is triggered when all the dependencies are loaded. So I used that function to require the angular bootstrap module. My config now looks like this:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
domReady: 'vendor/domReady',
openLayers: 'vendor/openlayers-debug',
etcetera....
},
shim: {
angular: {
deps: ['jquery'],
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
},
deps: ['angular',
'openLayers',
'app',
'domReady',
'controllers/rootController',
'controllers/olMapController',
'directives/olMap'
],
callback: function() {
require(['bootstrap']);
}
}
);
And the bootstrap module looks like this:
define(['angular', 'domReady', 'app'], function(angular, domReady) {
domReady(function() {
angular.bootstrap(document, ['GRVP']);
});
});
Thanks for the help. #angabriel: I upvoted your comment. It's not possible to accept a comment as an answer, is it? Your initial answer wasn't really the answer to my question, but the comment helped a lot...
Regards, Martijn
Sorry this answer will only contain text as your code is too big for a small example.
I would suggest to write a directive that utilizes head.js to load libraries you need at a specific context. One could also think of a directive that initializes openLayers this way.
I guess your error is a timing problem, because the require.js and angular.js module loading gets out of sync - more precisely there seems to be no sync at all between them.
update
To repeat my comment which lastly helped to lead the OP in the right direction:
You have to decide which framework gives the tone. If you go with requireJS, then require everything and bootstrap angular manually. (Remove ng-app="" from index.html) and do `angular.bootstrap()ยด when requirejs has completed. So the problem most likely is, that angular starts too early.

Loading Highcharts via shim using RequireJS and maintaining jQuery dependency

I'm attempting to load the Highcharts library using a shim in RequireJS. However, when Highcharts loads, it throws an exception because it can't access the jQuery methods it depends on.
The require config looks like so:
require.config({
baseUrl: "js",
shim: {
'libs/highcharts/highcharts.src.js': {
deps: ['jquery'],
exports: function(jQuery)
{
this.HighchartsAdapter = jQuery;
return this.Highcharts;
}
}
}
});
The exception that is thrown is:
Uncaught TypeError: undefined is not a function
and is in regards to this line:
dataLabels: merge(defaultLabelOptions, {
The issue is the merge call, which eventually maps itself back to jQuery (or some other adapter that Highcharts supports; but I'm just using jQuery).
I'm not sure exactly how to make sure Highcharts gets access to jQuery using RequireJS and shim.
Has anyone used RequireJS and Highcharts together before? I guess the issue isn't specific to highcharts, but any library that has other sorts of dependencies.
Thanks in advance for any advice or points to the correct direction!
To add further context, in hopes that someone who is familiar with require.js or shims will be able to help without having to be too intimately familiar with highcharts, here's some source that sets up this merge method in Highcharts
var globalAdapter = win.HighchartsAdapter,
adapter = globalAdapter || {},
// Utility functions. If the HighchartsAdapter is not defined,
// adapter is an empty object
// and all the utility functions will be null. In that case they are
// populated by the
// default adapters below.
// {snipped code}
merge = adapter.merge
// {snipped code}
if (!globalAdapter && win.jQuery) {
var jQ = win.jQuery;
// {snipped code}
merge = function () {
var args = arguments;
return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
};
// {snipped code}
}
The win object is a reference set up to window at the beginning of the script. So, I thought adding window.jQuery = jQuery; to the export method on the shim would result in highcharts picking up the jQuery reference; but it didn't.
Again, any insight, info, advice, or heckles would be appreciated at this point - I'm at a complete loss, and starting to question whether trying to implement and AMD package system in browser javascript is even worth it.
After accepting the answer from pabera below I thought it appropriate to update my question to reflect how his answer helped my solution (though, it's basically his answer).
RequireJS uses "paths" to find libs that aren't "AMD" supported and loads them on your page. the "shim" object allows you to define dependencies for the libraries defined in paths. The dependencies must be loaded before requirejs will try to load the dependent script.
The exports property provides a mechanism to tell requirejs how to determine if the library is loaded. For core libs like jquery, backbone, socketio, etc they all export some window level variable (Backbone, io, jQuery and $, etc). You simply provide that variable name as the exports property, and requirejs will be able to determine when the lib is loaded.
Once your definitions are done, you can use requirejs' define function as expected.
Here's my example require.config object:
require.config({
baseUrl: "/js/",
paths: {
jquery: 'jquery',
socketio: 'http://localhost:8000/socket.io/socket.io', //for loading the socket.io client library
highcharts: 'libs/highcharts/highcharts.src',
underscore: 'libs/underscore',
backbone: 'libs/backbone'
},
shim: {
jquery: {
exports: 'jQuery'
},
socketio: {
exports: 'io'
},
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
highcharts: {
deps: ['jquery'],
exports: 'Highcharts'
}
}
});
As pabera mentioned before, this is for Require.JS version 2.0.1.
I hope someone gets some use out of this; I know it road blocked me for a little while; so hopefully we kept you from banging your head into the same spot in the wall that we did, by posting this.
I had the exact same problem and I was struggling around many hours until I saw your entry here. Then I started over from scratch and now it works for me at least.
requirejs.config({
baseUrl:'/js/',
paths:{
jquery:'vendor/jquery',
handlebars: 'vendor/handlebars',
text: 'vendor/require-text',
chaplin:'vendor/chaplin',
underscore:'vendor/underscore',
backbone:'vendor/backbone',
highcharts: 'vendor/highcharts'
},
shim: {
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
highcharts: {
exports: 'Highcharts'
}
},
});
Since I use Chaplin on top of Backbone, I am including some more files in my paths attribute. Highcharts has a similar structure to Backbone so I thought I could load it the same way. It works for me now. As you can see, I am introducing highcharts in the paths attribute already to export it as a shim afterwords.
Maybe this helps, otherwise let's try to contribute on it even more to solve your problem.
Although jQuery can be used as an AMD module it will still export itself to the window anyway so any scripts depending on the global jQuery or $ will still work as long as jQuery has loaded first.
Have you tried setting a path? jQuery is an interesting one because although you're encoruaged not to name your modules by the RequireJS documentation, jQuery actually does.
From the jQuery source
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
define( "jquery", [], function () { return jQuery; } );
}
What that means is you will need to tell RequireJS where to find 'jquery'. So:
require.config({
paths: {
'jquery': 'path/to/jquery'
}
});
If you're interested in why jQuery registers itself this way then there is a pretty large comment in the source which goes into more detail

Categories

Resources