how to integrate d3 with require.js - d3.js

I'm having problems trying to integrate d3 into a require/backbone application. My main.js contains something like:
require.config({
paths: {
d3: 'libs/d3/d3.v2.min'
backbone: ...
...
}
});
And my backbone view something like (in coffeescript)
define ['backbone','d3',...], (Backbone,d3,...) ->
MyView = Backbone.View.extend
initialize: () ->
d3.somefunction
Console log says d3 is null. Is there a simple way to integrate d3 into this type of application?

d3 does not call define() to declare a module, so the local d3 reference to the backbone view will not be what you want. Either use the global variable made by d3:
define(['backbone', 'd3'], function (backbone, ignore) {
//Use global d3
console.log(d3);
});
Or use the shim config to declare an exports value for d3:
requirejs.config({
shim: {
d3: {
exports: 'd3'
}
}
});
That will tell requirejs to use the global d3 as the module value for d3.

Since d3.v3 now registers itself as an AMD module if a compatible library is present, you'll need to use this workaround (from http://pastebin.com/d5ZDXzL2):
requirejs.config({
paths: {
d3: "scripts/d3.v3",
nvd3: "scripts/nv.d3"
},
shim: {
nvd3: {
exports: 'nv',
deps: ['d3.global']
}
}
});
// workaround for nvd3 using global d3
define("d3.global", ["d3"], function(_) {
d3 = _;
});
define('myModule', ['nvd3'], function(nc) { /* .... */ });

I am not sure why but this works. I am not sure if it is the proper way of loading a module.
require(['libs/jquery', 'libs/d3'], function($, ignore) {
d3 = require('libs/d3');
});

Related

Vuelidate, can I inherit a custom method via mixin?

Using Veulidate, using VueJS 2 on a project built using Vue CLI, I'm simply trying to using a custom method for the purpose of validating a phone number. The method is coming from a global mixin located in main.js.
main.js
Vue.mixin({
methods: {
vd_phone(val) {
var phonePattern = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/;
return phonePattern.test(val) ? true : false
}
});
form.vue
validations: {
phone: {
required,
phone: this.vd_phone
}
}
Seems simple enough, right? Over and over, I get Cannot read property of 'vd_phone' of undefined. Tried vd_phone, this.vd_phone, this.vd_phone(), etc..
Also tried putting the method into a global methods option (instead of a mixin) and trying to access it via $root like this:
main.js
var vm = new Vue({
router, el: '#app', store,
methods: {
vd_phone() {
var phonePattern = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/;
return phonePattern.test(val) ? true : false;
}
},
render: h => h(App)
});
Same problem! In my form.vue file I attempted accessing this method using this.$root.vd_phone, $root.vd_phone, etc.. no dice.
This is all I found on the topic: https://github.com/vuelidate/vuelidate/issues/308, but this seems to talk about inheriting entire validator properties - not just a method.
Any help is appreciated.
You're using a factory pattern to instantiate a function from it's source for use in other files. To do this you must export from the source file so other files can import it, like this:
main.js
export default {
vd_phone(val) {
var phonePattern = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/;
return phonePattern.test(val) ? true : false;
}
}
Then import the file where ever you need that function, and you will have access to it.

Ember js integrating with D3

I want to include a graphs which have 2-y axis with relevant 2 data sets in my ember project.
Since I am newbie to D3 js as well as ember js I do some googling and come up with npm packages for doing that like these ember-d3, ember-charts, ember-d3-helpers. etc..
But all of them seems to me there is a bit of learning curve.
My questions are, from using those kind of packages can I integrate and draw my graphs?
Or else can I use directly D3 without any npm plunging?
Are there any suitable way to integrate D3 in ember project?
The simplested solution I am currently using is to import your third part libraries using ember-cli-build.js (see code below)
/*jshint node:true*/
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
});
app.import('./bower_components/d3/d3.js');
app.import('./bower_components/c3-0.4.11/c3.js');
app.import('./bower_components/c3-0.4.11/c3.css');
return app.toTree();
};
The code above let you have global access to d3 and c3 (which means which lib can be direct accessed in your window object ).
C3 is a really simple and powerful reusable d3 chart library and I recommend to every new d3 users.
http://c3js.org/
After you have your libs ready, put your chart generate code inside the component's didInsertElement hook (below just a sample and you can make it better for sure)
didInsertElement() {
this._super(...arguments);
const chart = c3.generate({
data: {
columns: []
},
axis: {
x: {
type: 'category',
categories: [
]
}
},
zoom: {
enabled: true
},
legend: {
show: false
},
grid: {
y: {show: true}
}
});
this.set('globalChart.lineChart', chart);
},
You can read more about Ember dependencies management at,
https://guides.emberjs.com/v2.11.0/addons-and-dependencies/managing-dependencies/

Kendo-UI components when using Durandaljs

I'm spent days trying to work out how to use the kendo-ui component with Durandal but to no avail.
I've managed to add a kendo-ui component declaratively on the page i.e. . This has no problems.
However, I would like to do some animations based on page events. Coding directly in the javascript viewmodel makes it easier to manipulate afterwards.
I've added my code below (which doesn't work), and I'm not sure that I'm taking the right approach. Actually, I'm sure I'm not. Anyone who can point me in the right direction I would appreciate it.
Any help or suggestions are welcome
Main.js
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins': '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'jquery': '../lib/jquery/jquery-1.9.1',
'kendo': '../lib/kendo/kendo.ui.core.min',
'knockout': '../lib/knockout/knockout-3.1.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'toastr': '../lib/toastr/toastr',
'lib': '../lib'
},
shim: {
'kendo': { deps: ['jquery'], exports: 'kendo' },
'bootstrap': {deps: ['jquery'],exports: 'jQuery'}
}
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'durandal/binder', 'kendo'], function (system, app, viewLocator, binder, kendo) {
app.title = 'My Jumpstart';
//specify which plugins to install and their configuration
app.configurePlugins({
router:true,
dialog: true,
widget: {
kinds: ['expander']
}
});
kendo.ns = "kendo-";
binder.binding = function (obj, view) {
kendo.bind(view, obj.viewModel || obj);
};
app.start().then(function () {
viewLocator.useConvention();
app.setRoot('shell');
});
});
index.js
define(['durandal/app', 'durandal/system', 'knockout', 'toastr', 'kendo'],
function (app, system, ko, toastr, kendo) {
var myButton = function () {
var kbutton = $("#myButton").kendoButton();
};
var vm = {
myButton: myButton
};
return vm;
});
index.html
<section>
<div id="myButton">My Kendo Button</div>
</section>
Instead of shimming, add the Kendo libraries via the <script> tag on your index.html page. Be sure to add it after jQuery.
Also, are you using the knockout-kendo library from Ryan Niemeyer? That would affect my answer.

Durandal Weyland/Requirejs optimizer with kendo ui dataviz

I'm building an app with Durandal to bundle with PhoneGap. When I'm trying to run the weyland optimizer I'm running into some issues.
The build and optimization runs fine without any errors (I'm using requirejs as optimizer), but when I run the application my kendo ui chart throws an error saying "Uncaught TypeError: Object [object Object] has no method 'kendoChart'".
If I pause in debug mode in chrome where the kendoChart binding is taking place and type "kendo" in the console I get the kendoobject and can view its properties and so on, so it's definitely in the DOM.
Iv'e google around quite a bit and found some threads here on SO but none of them seem to sort my issue out. For instance this thread or this one.
I have a custom knockout binding for the chart, which is provided below.
My weyland.config looks like this:
exports.config = function (weyland) {
weyland.build('main')
.task.jshint({
include: 'App/**/*.js'
})
.task.uglifyjs({
// not uglyfying anything now...
//include: ['App/**/*.js', 'Scripts/durandal/**/*.js', 'Scripts/custom/**/*.js']
})
.task.rjs({
include: ['App/**/*.{js,html}', 'Scripts/custom/**/*.js', 'Scripts/jquery/*.js', 'Scripts/durandal/**/*.js'],
exclude: ['Scripts/jquery/jquery-2.0.3.intellisense.js', 'App/main.js'],
loaderPluginExtensionMaps: {
'.html': 'text'
},
rjs: {
name: 'main',
baseUrl: 'App',
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'knockout': '../Scripts/knockout/knockout-2.3.0',
'kendo': 'empty:', <-- tried refering kendo.all.min, or dataviz.chart or the path
'jquery': '../Scripts/jquery/jquery-2.0.3.min',
'Helpers': '../Scripts/custom/helpers',
........ other scripts ......
},
deps: ['knockout', 'ko_mapping', 'command'],
callback: function (ko, mapping, command) {
ko.mapping = mapping;
}
//findNestedDependencies: true, **<-- tried both true and false here**
inlineText: true,
optimize: 'none',
pragmas: {
build: true
},
stubModules: ['text'],
keepBuildDir: false,
out: 'App/main-built.js'
}
});
};
// The custom binding for the kendo chart
define([
'knockout',
'jquery',
'Helpers',
'kendo/kendo.dataviz.chart.min'
], function (
ko,
$,
helpers,
kendoui
) {
function drawChart(element, values, options) {
$(element).kendoChart({ **<-- this is where I get an error**
... options for chart ...
});
}
// kendoUi data viz chart
ko.bindingHandlers.moodChart = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
//set the default rendering mode to svg
kendo.dataviz.ui.Chart.fn.options.renderAs = "svg"; **<-- this renders no errors**
// if this is a mobile device
if (kendo.support.mobileOS) {
// canvas for chart for you!
kendo.dataviz.ui.Chart.fn.options.renderAs = "canvas";
}
var values = ko.unwrap(valueAccessor());
setTimeout(function () {
drawChart(element, values);
}, 125);
}
};
});
I might add that everything works fine running the not optimized code in a web browser (or a phone for that matter).
I've also tried to shim the kendo path in the config file and add a dependency to jquery, which doesn't really seem to do any difference.
Any help would be appreciated!
For large frameworks like kendo that have their own set of dependencies e.g. jquery version, I tend not to bundle them with my own AMD modules. Personal preference, I know.
Take a look at how you could load jquery , knockout and kendo via normal script tags in the .NET example
<body>
<div id="applicationHost"></div>
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.js"></script>
<script type="text/javascript" src="~/Scripts/whateverKendoVersionGoesHere.js"></script>
<script type="text/javascript" src="~/Scripts/knockout-2.3.0.js"></script>
<script type="text/javascript" src="~/Scripts/bootstrap.js"></script>
<script type="text/javascript" src="~/Scripts/require.js" data-main="/App/main"></script>
</body>
That way jquery and knockout will be loaded as globals. In main.js you'd have to define jquery and knockout in order to make them available to Durandal (see main.js) as Durandal internally is still using them as AMD modules.
requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions'
}
});
define('jquery', function () { return jQuery; });
define('knockout', ko);
define(['durandal/system', 'durandal/app', 'durandal/viewLocator'], function (system, app, viewLocator) {
...
});

Loading "knockout.mapping" plugin using require.js

I am creating an MVC3 application, with requireJS. In my views I need to convert the Model object into a knockout viewmodel object. So I need to use knockout and knockout.mapping libraries.
My application is designed in the following way,
1). All the script files are categorized into folders
Scripts/app/home/ - contains the scripts for the views in Home controller.
Scripts/lib/ - contains the scripts like jQuery, knockout,knockout.mapping, requirejs etc
2). In the "_Layout.cshtml" I am referencing "require.js" like this.
<script src="#Url.Content("~/Scripts/lib/require.js")" type="text/javascript"></script>
3). To configure the require.js settings I am using a different script file called "common.js" (Scripts/lib/common.js)
require.config(
{
baseUrl: "/Scripts/",
paths:{
jquery: "lib/jquery-2.0.3",
ko: "lib/knockout-2.3.0",
komapping: "lib/knockout.mapping"
}
});
4). This is my index.js file which is in 'Scripts/app/home/"
define(['ko', 'komapping'], function (ko, komapping) {
var person = function () {
var self = this;
self.getPersonViewModel = function (data) {
return ko.mapping.fromJS(data); ;
};
};
return { Person: person };
});
5). This is my "Index" action method in the "Home" controller
public ActionResult Index()
{
var person = new Person
{
Id = 1,
Name = "John",
Addresses = new List<Address>(new[]{new Address{Country = "Country 1", City = "City 1"}})
};
return View(person);
}
6). Finally this is my "Index" view
#model MMS.Web.Models.Person
<script type="text/javascript">
require(["/Scripts/common/common.js"], function () {
require(["app/home/index"], function (indexJS) {
var person = new indexJS.Person();
var vm = person.getPersonViewModel(#Html.Raw(Json.Encode(Model)));
});
});
</script>
The problem which I am facing is when loading the index.js file, I get a script error that the knockout.js cannot be loaded.
Failed to load resource: the server responded with a status of 404 (Not Found) - http:///Scripts/knockout.js
But if I remove the dependency of "komapping" inside the "index.js" file it loads correctly, but then I cannot use the mapping functionality.
I had a look inside these links, but couldn't find a solution,
Knockout.js mapping plugin with require.js and
https://github.com/SteveSanderson/knockout.mapping/issues/57
Your help, suggestions are much appreciated. Thanks!
I had the same issue. The problem is that the knockout.mapping defines a knockout dependency, so you need to satisfy this one when you load the script.
Here is how you should load your mapping stuff
require.config(
{
baseUrl: "/Scripts/",
paths:{
jquery: "lib/jquery-2.0.3",
knockout: "lib/knockout-2.3.0",
komapping: "lib/knockout.mapping"
},
shim: {
komapping: {
deps: ['knockout'],
exports: 'komapping'
}
}
});
Then in my case, I use an index.js file with a requirejs call like the following
requirejs(['jquery', 'knockout', 'komapping'], function($, ko, komapping){
ko.mapping = komapping;
//Do other stuff here
});

Resources