I'm trying to display a D3 geo projection in a React component.
When viewing any page, this error happens inside the D3 Geo projection module:
Object doesn't support property or method 'readFileSync'
It is thrown at this line in the module's index.js:
module.exports = new Function("d3",
fs.readFileSync(path.join(__dirname, "d3.geo.projection.js"), "utf-8"));
Here are the modules added to the package.json as dependencies:
"d3": "^3.5.16",
"d3-geo-projection": "^0.2.16",
"topojson": "^1.6.25"
The following is the code for my GeoMap React component using D3 geo projection plugin:
var React = require('react');
var ReactDOM = require('react-dom');
var d3 = require("d3");
require("d3-geo-projection")(d3);
var d3GeoMap = {};
d3GeoMap.create = function(el, props, state) {
var svg = d3.select(el).append("svg")
.attr("class", "geoChart")
.attr("width", props.width)
.attr("height", props.height);
this.update(el, state);
};
d3GeoMap.update = function(el, state) {
d3.select(el).select("svg").append("rect")
.data(state.data)
.enter()
.attr("class", "map")
.attr("d", d3.geo.path().projection(d3.geo.mercator()));
};
var GeoMap = React.createClass({
propTypes: {
data: React.PropTypes.object
},
componentDidMount: function() {
var el = this.refs.geoRoot;
d3GeoMap.create(el,
{
width: 900,
height: 900
},
{
data: this.props.data
});
},
render: function() {
return (<div ref="geoRoot"></div>);
}
});
module.exports = GeoMap;
NOTE: This error happens when hitting any page, even ones that do not use my GeoMap component.
Does anyone have insight on why the D3 Geo Projection plugin cannot find the 'fs' module?
require("d3-geo-projection") when bundled assumes that fs.readFileSync is replaced with the actual code which for example in browserify is done with the brfs transform
However the index.js file is just doing the following
module.exports = function (d3) {
// all the code of ./d3.geo.projection.js is included here
}
Therefore if you're not using a bundler with this transform use this instead
var d3 = require("d3");
// assumes that d3 is already defined here
require("d3-geo-projection/d3.geo.projection")
Related
I have created gulp tasks scheduler for JavaScript minification and image resizing. All things work nicely when I executes command manually.
Command:
gulp
But when I include gulp-livereload module to perform operation automatically, Command line watch continuously when I upload images, it does not resize.
Just cursor is blinking. When uploads an image, no activities display in command watch list.
gulpfile.js
// include gulp
var gulp = require('gulp');
// include plug-ins
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var stripDebug = require('gulp-strip-debug');
var uglify = require('gulp-uglify');
var watch = require('gulp-watch');
var imageresize = require('gulp-image-resize');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var liveReload = require("gulp-livereload");
// JS hint task
gulp.task('jshint', function () {
gulp.src([
'./app/client/app.js',
'./app/client/app.routes.js',
'./app/client/modules/**/controllers/*.js',
'./app/client/modules/**/directives/*.js',
'./app/client/modules/**/services/*.js',
'./app/client/services/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(liveReload());
});
gulp.task('jsminification', function () {
gulp.src([
'./app/client/app.js',
'./app/client/app.routes.js',
'./app/client/modules/**/controllers/*.js',
'./app/client/modules/**/directives/*.js',
'./app/client/modules/**/services/*.js',
'./app/client/modules/**/filter/*.js',
'./app/client/services/*.js'])
.pipe(concat('script.js'))
.pipe(stripDebug())
.pipe(uglify())
.pipe(gulp.dest('./app/build/scripts/'))
.pipe(liveReload());
});
gulp.task('resize', function () {
// set the folder name and the relative paths
// in the example the images are in ./assets/images
// and the public directory is ../public
var paths = {
folder: 'media/',
src: './app/client/',
dest: './app/client/resize/'
};
// create an array of image groups (see comments above)
// specifying the folder name, the ouput dimensions and
// whether or not to crop the images
var images = [
// {folder: 'bg', width: 1200, crop: false},
{folder: 'photo', width: 120, height: 120, crop: true},
//{folder: 'projects', width: 800, height: 500, crop: true}
];
console.log("resize called");
// loop through image groups
images.forEach(function (type) {
console.log(type);
var source_ = paths.src + paths.folder + type.folder + '/*';
var scale_ = type.width + "x" + type.height + "/";
//var destination_ = paths.dest + paths.folder + scale_ + type.folder;
var destination_ = paths.dest + scale_ + type.folder;
console.log(">source:" + source_);
console.log(">scale:" + scale_);
console.log(">destination:" + destination_);
// build the resize object
var resize_settings = {
width: type.width,
crop: type.crop,
// never increase image dimensions
upscale: false
}
// only specify the height if it exists
if (type.hasOwnProperty("height")) {
resize_settings.height = type.height;
}
gulp
// grab all images from the folder
.src(source_)
// resize them according to the width/height settings
.pipe(imageresize(resize_settings))
// output each image to the dest path
// maintaining the folder structure
.pipe(gulp.dest(destination_))
.pipe(liveReload());
});
});
gulp.task('watch', function () {
liveReload.listen({host: process.env['HOST'], port: process.env['PORT']});
gulp.watch('./app/client/media/photo/*.{png,jpg,jpeg}', ['resize']);
});
gulp.task('default', ['jshint', 'jsminification', 'resize', 'watch']);
I want to resize image automatically as new image uploads in photo folder.
After some R&D I have found following solution using "gulp-watch" module and it works fine.
// include gulp
var gulp = require('gulp');
// include plug-ins
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var stripDebug = require('gulp-strip-debug');
var uglify = require('gulp-uglify');
var imageresize = require('gulp-image-resize');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var watch = require("gulp-watch");
var newer = require("gulp-newer");
var paths = {
folder: 'media/',
src: './app/client/',
dest: './app/client/resize/'
}
var images = [
{folder: 'photo', width: 120, height: 120, crop: true},
];
// JS hint task
gulp.task('jshint', function () {
gulp.src([
'./app/client/app.js',
'./app/client/app.routes.js',
'./app/client/modules/**/controllers/*.js',
'./app/client/modules/**/directives/*.js',
'./app/client/modules/**/services/*.js',
'./app/client/services/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
// JS minification task
gulp.task('jsminification', function () {
gulp.src([
'./app/client/app.js',
'./app/client/app.routes.js',
'./app/client/modules/**/controllers/*.js',
'./app/client/modules/**/directives/*.js',
'./app/client/modules/**/services/*.js',
'./app/client/modules/**/filter/*.js',
'./app/client/services/*.js'])
.pipe(concat('script.js'))
.pipe(stripDebug())
.pipe(uglify())
.pipe(gulp.dest('./app/build/scripts/'));
});
// image resize
gulp.task('resize', function () {
// loop through image groups
images.forEach(function (type) {
var source_ = paths.src + paths.folder + type.folder + '/*';
var scale_ = type.width + "x" + type.height + "/";
//var destination_ = paths.dest + paths.folder + scale_ + type.folder;
var destination_ = paths.dest + scale_ + type.folder;
// build the resize object
var resize_settings = {
width: type.width,
crop: type.crop,
// never increase image dimensions
upscale: false
}
// only specify the height if it exists
if (type.hasOwnProperty("height")) {
resize_settings.height = type.height;
}
gulp
// grab all images from the folder
.src(source_)
.pipe(newer(destination_))
// resize them according to the width/height settings
.pipe(imageresize(resize_settings))
// optimize the images
.pipe(imagemin({
progressive: true,
// set this if you are using svg images
svgoPlugins: [{removeViewBox: false}],
use: [pngquant()]
}))
// output each image to the dest path
// maintaining the folder structure
.pipe(gulp.dest(destination_));
});
});
// Gulp default task
gulp.task('default', ['jshint', 'jsminification', 'resize'], function () {});
// Gulp watch for new image resizing
watch('./app/client/media/photo/*.+(png|jpg|jpeg|gif)', function () {
gulp.run('resize');
});
when i run the server..this component is loaded ...no errors found on server side...but browser console gives back a following error :
Uncaught TypeError: (intermediate value)[chartType] is not a function
my code is as follows :
var React = require('react');
var ReactDOM = require('react-dom');
var chart = require('chart.js');
var DoughnutChart = require("react-chartjs").Doughnut;
var Tempvshum = React.createClass({
render() {
var chartOptions = {
segmentShowStroke : true
};
var chartData = [{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
}];
return(<DoughnutChart data={chartData} options={chartOptions} />);
}
});
module.exports = Tempvshum;
I think the issue is related to chart.js.
https://www.npmjs.com/package/chart.js says that the package has been uploaded 2 days ago and it is now in version 2.0.0-beta2. I modified my package.json to use the older version 1.1.1 and everything works.
I don't have experience at all with nodejs and I am learning. I have a code, which I am testing and giving me the following errors, and I don't understand why:
1) Part 3 Assessment Tests "before all" hook:
ReferenceError: wagner is not defined
at Object. (fx.js:2:31)
at Object. (dependencies.js:3:10)
at Context. (test.js:29:20)
2) Part 3 Assessment Tests "after all" hook:
TypeError: Cannot read property 'close' of undefined
at Context. (test.js:65:11)
These are the programs involved in the issue:
test.js --------------
var assert = require('assert');
var express = require('express');
var fs = require('fs');
var status = require('http-status');
var superagent = require('superagent');
var wagner = require('wagner-core');
var URL_ROOT = 'http://localhost:3000';
var PRODUCT_ID = '000000000000000000000001';
describe('Part 3 Assessment Tests', function() {
var server;
var app;
var succeeded = 0;
var finalCharge;
var Category;
var Config;
var fx;
var Product;
var Stripe;
var User;
before(function() {
app = express();
// Bootstrap server
models = require('./models')(wagner);
dependencies = require('./dependencies')(wagner);
// Make models available in tests
var deps = wagner.invoke(function(Category, fx, Product, Stripe, User, Config) {
return {
Category: Category,
fx: fx,
Product: Product,
Stripe: Stripe,
User: User,
Config: Config
};
});
...
dependencies.js -------------
var wagner = require('wagner-core');
var fs = require('fs');
var fx = require('./fx')(wagner);
var Stripe = require('stripe');
module.exports = function(wagner) {
var stripe =
// TODO: Make Stripe depend on the Config service and use its `stripeKey`
// property to get the Stripe API key.
wagner.factory('Stripe', function() {
return Stripe(Config.stripeKey);
});
wagner.factory('fx', fx);
wagner.factory('Config', function() {
return JSON.parse(fs.readFileSync('./config.json').toString());
});
var Config = wagner.invoke(function(Config) {
return Config;
});
};
fx.js --------------------------
var superagent = require('superagent');
var _ = require('underscore')(wagner);
module.exports = function(Config) {
...
};
I think I shouldn't have any problem because wagner is defined on test.js and passed as parameter to dependencies.js, and it is passing it on to fx.js.
1- Could you tell me what is wrong in the code ?
2- The second error, I have not cue why is it happening.
Please, help
In your dependencies.js, in the fx definition, you dont need to pass wagner as parameter, because that variable doesnt exist there:
var fx = require('./fx');
As i see, you already defined the Config factory, and you dont need to assign it to a variable for use it, because wagner will autoinject your "Config" factory, allowing you access to it:
wagner.factory('Stripe', function(Config) {
return Stripe(Config.stripeKey);
});
...
wagner.factory('Config', function() {
return JSON.parse(fs.readFileSync('./config.json').toString());
});
Then in your fx.js, when you wanna use the Config parameter you just pass it:
module.exports = function(Config) {
var url = 'http://openexchangerates.org/api/latest.json?app_id=' +
Config.openExchangeRatesKey;
...
}
Exactly the same you should do if you wanna use the "Config" factory in any other file:
[auth.js]
function setupAuth(User, Config, app) {
...
}
You're trying to use wagner in fx.js before you execute the exported function and outside of the scope that wagner is passed to. Also, Config seems a bit misleading if you're passing wagner to that function instead.
If you can defer loading underscore, you could do something like:
var superagent = require('superagent');
var _;
module.exports = function(Config) {
if (!_)
_ = require('underscore')(Config);
// ...
};
I'm using the d3 library. Its pretty big, so I only want to download the chunk on demand. I can create the split point with require.ensure, but I'm lost as to how you actually get the library into the scope of the module. This is as close as I can get, the chunk is downloaded, but d3 is always undefined. Any help would be greatly appreciated.
var React = require('react');
var d3;
require.ensure([], function(require){
d3 = require('d3');
});
var Chart = React.createClass({
render: function() {
var props = this.props;
var width = props.width;
//d3 is undefined here
var xScale = d3.scale.linear().domain([
0, 111
]).range([
0, width
]);
return (
<g>
</g>
);
}
});
module.exports = Chart;
From my understanding the mechanism goes like this:
require.ensure(["<file-path or module name>"], function(moduleExportsValue) {
var myModule = require("<file-path or module name>");
});
for your specific example:
require.ensure(["d3"], function() {
var d3 = require("d3");
// do something with d3
});
Edit: It's very helpful for stuff that is not immediately visible in the app. Such as dialogs, modals, overlays.
onButtonClick: function(event) {
this.showLoader();
var self = this;
require.ensure("path/to/dialog", function() {
self.hideLoader();
var dialog = require("path/to/dialog");
dialog.open();
});
},
I am serializing a canvas on the client, and post it to a node.js server (ubuntu 14.10, with node.js version v0.10.34 and fabric 1.4.13).
On the client canvas, objects are in a group.
The problem is, the objects are moved when de-serialized on the server.
Client code:
$(function(){
fc= new fabric.Canvas('myCanvas');
fc.setBackgroundColor('white');
group = new fabric.Group([], { hasControls:false, hasBorders:true, top:-fc.getHeight(), left:-fc.getWidth(), width:2*fc.getWidth(), height:2*fc.getHeight(), hoverCursor:'default' });
fc.add(group);
// create a rectangle object
var rect = new fabric.Rect({
left: 150,
top: 100,
fill: 'red',
width: 20,
height: 20
});
// "add" rectangle onto canvas
group.add(rect);
var rect2 = new fabric.Rect({
left: 100,
top: 150,
fill: 'blue',
width: 20,
height: 20
});
group.add(rect2);
fc.renderAll();
$.post( window.location.origin+':8124/', {
width: group.getWidth(),
height: group.getHeight(),
data: encodeURI(JSON.stringify(fc.toDatalessJSON()))
}, function( data ) {}
);
});
Server code:
var fabric = require('fabric').fabric;
var express = require('express');
var app = express();
var fs = require('fs');
var PORT = 8124;
var bodyParser = require('body-parser')
app.use(bodyParser.json({ limit: '50mb'}) ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true,
limit: '50mb'
}));
app.post('/', function(req, res){
console.log('Post received');
if (req.body) {
res.writeHead(200, { 'Content-Type': 'image/png' });
var w=parseInt(req.body.width);
var h=parseInt(req.body.height);
var canvas = fabric.createCanvasForNode(w, h);
console.log(req.body.data);
out = fs.createWriteStream(__dirname + '/mindmap.png');
canvas.loadFromDatalessJSON(decodeURI(req.body.data), function() {
canvas.renderAll();
console.log(JSON.stringify(canvas.toDatalessJSON()));
var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
out.write(chunk);
console.log('writing chunk');
});
stream.on('end', function() {
out.end();
});
});
}
});
app.listen(PORT);
The console.log statement shows that the two rects are created (left:15, top-35) and (left:-35, top:15) respectively.
On the client, top/left object properties are relative to center of the group.
This is why I create the group with -fc.getWidth and-fc.getHeight left and top respectively. This works fine on the client.
Maybe this is not the case on the server?
EDIT: this seems to be an issue with loadFromDatalessJSON, at least on node.
Running the following code on the node server shows that top/left properties of the rectangles are wrong after serializing the first canvas and deserializing into the second one:
var fabric = require('fabric').fabric;
var fs = require('fs');
var canvas = fabric.createCanvasForNode(200, 200);
canvas.setBackgroundColor('white');
var out = fs.createWriteStream(__dirname + '/mindmap.png');
var group = new fabric.Group([], { top:-200, left:-200, width:400, height:400});
canvas.add(group);
var rect = new fabric.Rect({
left:150,
top:100,
fill:'red',
width:20,
height:20
});
group.add(rect);
var rect2 = new fabric.Rect({
left:100,
top:150,
fill:'blue',
width:20,
height:20
});
group.add(rect2);
canvas.renderAll();
console.log(JSON.stringify(canvas.toDatalessJSON()));
var canvas2 = fabric.createCanvasForNode(200, 200);
canvas2.loadFromDatalessJSON(canvas.toDatalessJSON());
canvas2.renderAll();
var stream = canvas2.createPNGStream();
stream.on('data', function(chunk) {
out.write(chunk);
console.log('writing chunk');
});
stream.on('end', function() {
out.end();
console.log('png image generated');
});
console.log(JSON.stringify(canvas2.toDatalessJSON()));
Next step is to run similar code on the client and see if the problem exists as well.
EDIT2: the same problem occurs on the client, and with toJSON as well instead of toDatalessJSON. Can someone help? Is this a known issue with groups serialization/deserialization? Is there a workaround?
Thanks
After searching for similar issues, it looks like this is very similar to [#1159] [https://github.com/kangax/fabric.js/issues/1159]
But this issue is supposed to be fixed, and I don't have any transform on my canvas ...
I had this problem and fixed it by installing the latest version from the github releases section: https://github.com/kangax/fabric.js/releases