I have a Node application where I want to use socket.io to communicate data to a client where it is displayed by smoothie. I have both packages installed (via NPM) on two different node environments and in both cases in the node_modules sub-directory of my project. One of the environments is the BeagleBone Black and the other is the Cloud9 IDE environment. In both cases the socket.io module resolves and works fine but no combination of path names gets the smoothie module to resolve (which I can get to work if I just pull it from GitHub directly).
Here are the relevant bits of the server side code for the Cloud9 IDE:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(process.env.PORT, process.env.IP);
function handler (req, res) {
fs.readFile(__dirname + '/NotWorking.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
.
.
.
Here are the relevant bits from the client side:
<!DOCTYPE html>
<html>
<head>
<script src="smoothie/smoothie.js"></script>
<script src="socket.io/socket.io.js"></script>
<script>
var line1 = new TimeSeries();
var line2 = new TimeSeries();
var socket = io.connect('http://demo-project.wisar.c9.io/');
socket.on('news', function (data) {
for (var property in data) {
dataPoint = data[property];
}
line1.append(new Date().getTime(), dataPoint);
line2.append(new Date().getTime(), 40);
socket.emit('my other event', { my: dataPoint });
});
</script>
.
.
.
As I said, both modules are located in the node_modules sub directory of the project directory where the above scripts live. The node documentation describes how includes are supposed to be resolved (http://nodejs.org/api/modules.html#modules_all_together) and I think that I can follow the path to how it resolves the link to socket.io by way of the index.js route...but it also works when I put a "/" in front which I can not find a path for. No permutation or combination of paths makes the smoothie module resolve. smoothie, btw, is a small charting application that can be found in npm under that name.
Any help would be appreciated.
If your current file is in the same directory as node_modules, then to load smoothie try this path in src of script tag:
./node_modules/smoothie/smoothie.js
The path smoothie/smoothie.js is not giving the location of smoothie.js, which lies in node_modules/smoothie/smoothie.js. This worked for me, I hope this works for you.
Related
I made a npm module, it works perfectly in node, but I laso want to make it avaible in browser as Socket.io is. In node I use it that way : var AIM = require('aimjs')(server)
server param is optional and is from http.Server (Node.js doc) if specified it serve a client version of the module as Socket.io do :
if (this.server != null) {
var listeners = this.server.listeners('request').slice()
this.server.removeAllListeners('request')
this.server.on('request', function (req, res) {
if (url.parse(req.url).pathname === '/AIM.js') {
res.setHeader('Content-Type', 'application/javascript')
res.writeHead(200)
res.end(fs.readFileSync(__dirname + '/AIM.client.js'))
} else {
for (var i = 0; i < listeners.length; i++) {
listeners[i].call(self.srv, req, res)
}
}
})
}
This file (AIM.client.js) is a browserified version of my main, but the module is not avaible outside. How can I make it global ? I want that users just have to install module, include <script type='text/javascript' src='/AIM.js'></script> and can use it both client side and server side.
When you browserify your file, use the --standalone (-s) option.
Example:
browserify index.js -s aimjs
This will make your file a UMD bundle.
If it is used in a CommonJS environment, it will behave as a CommonJS module.
If it is used in an AMD environment, it will behave as an AMD module.
If it is simply included via a script tag, it will attach itself to window.aimjs.
I am not able to access variable 'dps' declare in index.js within index.html , using npm start(for starting electron app)
I am able to access my sql and get data in index.js and i want to show that on index.html (used nodeJs and Electron)
'dps' refers to js object which has mysql data
//My index.js file has
var app = require('app');
var dps = [{x:1,y:2}];
// Module to create native browser window.
var BrowserWindow = require('browser-window');
var mainWindow = null;
var dps = [{x:1,y:2}];
var mysql = require('mysql');
// Quit when all windows are closed.
app.on('window-all-closed', function () {
if (process.platform != 'darwin') {
app.quit();
}
});
app.on('ready', function () {
// Create the browser window.
mainWindow = new BrowserWindow({ width: 800, height: 600 });
mainWindow.loadUrl('file://' + __dirname + '/index.html');
// Open the devtools.
// mainWindow.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
});
//My html file
<html>
<head>
<!--<script type="text/javascript" src = "index.js"/>-->
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript">
alert(dps); --- not getting dps value here(/anywhere in html)
</head>
</html>
Your code in index.html runs in a different process (usually called the Renderer process) than your in index.js (which runs in the Main process). Furthermore, your index.js file is a module, therefore, even if the two were run by the same process, you'd have to export your dps variable or make it a global variable like global.dps (however, that's a bad practice!).
There are a number of ways to share date between the Main and the Renderer process; Electron provides the ipcMain, ipcRenderer and remote modules for that purpose; you can also pass data from Main to the Renderer using URL encoded parameters (but this doesn't help you if the data changes); finally, you can use any other form of IPC (e.g., send messages over a socket, use shared memory or shared files, etc.) -- but it's a good idea to start with Electron's ipc or remote modules.
Having said that, in your case, the consensus seems to be not to use the Main process for DB access only to then pass the information on to the Renderer, but rather access the DB directly from the Renderer; that way you won't have to worry about IPC at all (at least in this case).
Need help.
I use gulp-conect and it livereload method. But if I build a few template in time, get a lot of page refresh. Is any solution, I want to build few templates with single page refresh?
So, I reproduce the problem you have and came accross this working solution.
First, lets check gulp plugins you need:
gulp-jade
gulp-livereload
optional: gulp-load-plugins
In case you need some of them go to:
http://gulpjs.com/plugins/
Search for them and install them.
Strategy: I created a gulp task called live that will check your *.jade files, and as you are working on a certain file & saving it, gulp will compile it into html and refresh the browser.
In order to accomplish that, we define a function called compileAndRefresh that will take the file returned by the watcher. It will compile that file into html and the refesh the browser (test with livereload plugin for chrome).
Notes:
I always use gulp-load-plugin to load plugins, so thats whay I use plugins.jad and plugins.livereload.
This will only compile files that are saved and while you have the task live exucting on the command line. Will not compile other files that are not in use. In order to accomplish that, you need to define a task that compiles all files, not only the ones that have been changed.
Assume .jade files in /jade and html output to /html
So, here is the gulpfile.js:
var gulp = require('gulp'),
gulpLoadPlugins = require('gulp-load-plugins'),
plugins = gulpLoadPlugins();
gulp.task('webserver', function() {
gulp.src('./html')
.pipe(plugins.webserver({
livereload: true
}));
gulp.watch('./jade/*.jade', function(event) {
compileAndRefresh(event.path);
});
});
function compileAndRefresh(file) {
gulp.src(file)
.pipe(plugins.jade({
}))
.pipe(gulp.dest('./html'))
}
Post edit notes:
Removed liveReload call from compileAndRefresh (webserver will do that).
Use gulp-server plugin insted of gulp-connect, as they suggest on their repository: "New plugin based on connect 3 using the gulp.src() API. Written in plain javascript. https://github.com/schickling/gulp-webserver"
Something you can do is to watch only files that changes, and then apply a function only to those files that have been changed, something like this:
gulp.task('live', function() {
gulp.watch('templates/folder', function(event) {
refresh_templates(event.path);
});
});
function refresh_templates(file) {
return
gulp.src(file)
.pipe(plugins.embedlr())
.pipe(plugins.livereload());
}
PS: this is not a working example, and I dont know if you are using embedlr, but the point, is that you can watch, and use a callback to call another function with the files that are changing, and the manipulate only those files. Also, I supposed that your goal is to refresh the templates for your browser, but you manipulate as you like, save them on dest or do whatever you want.
Key point here is to show how to manipulate file that changes: callback of watch + custom function.
var jadeTask = function(path) {
path = path || loc.jade + '/*.jade';
if (/source/.test(path)) {
path = loc.jade + '/**/*.jade';
}
return gulp.src(path)
.pipe(changed(loc.markup, {extension: '.html'}))
.pipe(jade({
locals : json_array,
pretty : true
}))
.pipe(gulp.dest(loc.markup))
.pipe(connect.reload());
}
First install required plugins
gulp
express
gulp-jade
connect-livereload
tiny-lr
connect
then write the code
var gulp = require('gulp');
var express = require('express');
var path = require('path');
var connect = require("connect");
var jade = require('gulp-jade');
var app = express();
gulp.task('express', function() {
app.use(require('connect-livereload')({port: 8002}));
app.use(express.static(path.join(__dirname, '/dist')));
app.listen(8000);
});
var tinylr;
gulp.task('livereload', function() {
tinylr = require('tiny-lr')();
tinylr.listen(8002);
});
function notifyLiveReload(event) {
var fileName = require('path').relative(__dirname, event.path);
tinylr.changed({
body: {
files: [fileName]
}
});
}
gulp.task('jade', function(){
gulp.src('src/*.jade')
.pipe(jade())
.pipe(gulp.dest('dist'))
});
gulp.task('watch', function() {
gulp.watch('dist/*.html', notifyLiveReload);
gulp.watch('src/*.jade', ['jade']);
});
gulp.task('default', ['livereload', 'express', 'watch', 'jade'], function() {
});
find the example here at GitHub
When setting up an E2E test with my existing angular app, I am having trouble getting starting since I am using socket.io in my application. Protractor can't find the socket.io files that are typically served by the node module since it's not part of my personal code.
I am getting the error:
UnknownError: Error Message => 'Can't find variable: io'
On the angular side:
angular.module('socket.io', []).factory(function($rootScope) {
var socket = io.connect(); // I believe the error is being thrown from here
return {
on: function (eventName, callback) {
socket.on(eventName, function () {...});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {...});
}
};
});
I believe that is because it's typically served by the node module:
<script type="text/javascript" src='/socket.io/socket.io.js'></script>
vs my socket.io factory shown above
<script type="text/javascript" src='js/services/socket-service.js'></script>
Is there a way to solve this without having the copy the socket.io.js file in to the client codebase?
Make sure that the file socket.io.js is being included before socket-service.js. You can either do thus manually or use a module loader such as requirejs (http://www.requirejs.org)
codes in file main.js is like this:
phantom.injectJs("libs/require-1.0.7.js");
require.config(
{
baseUrl: ""
}
);
require([], function(){});
when i run "phantomjs main.js" in the commandline, requirejs doesn't work well in the main.js. I know how to use requirejs in the page running in the browser(including phantomjs' way: page.open(url, callback)), but not like above. I tries using requirejs like the main.js, it is a popular problem, i think. Thank you!
I just struggled for some time. My solution is not clean, but it works, and I'm happy with that due to the unfinished api documentation from phantomjs.
Wordy explanation
You need three files. One is your amd phantomjs test file which I'll call "amd.js". The second is your html page to load which I'll name "amd.html". Finally the browser test which I called "amdTestModule.js".
In amd.html, declare your script tag per normal:
<script data-main="amdTestModule.js" src="require.js"></script>
In your phantomjs test file, this is where it gets hacky. Create your page, and load in the 'fs' module. This allows you to open a relative file path.
var page = require('webpage').create();
var fs = require('fs');
page.open('file://' + fs.absolute('tests/amd.html'));
Now since requirejs loads files asynchronously, we can't just pass in a callback into page.open and expect things to go smoothly. We need some way to either
1) Test our module in the browser and communicate the result back to our phantomjs context. Or
2) Tell our phantomjs context that upon loading all the resources, to run a test.
#1 was simpler for my case. I accomplished this via:
page.onConsoleMessage = function(msg) {
msg = msg.split('=');
if (msg[1] === 'success') {
console.log('amd test successful');
} else {
console.log('amd test failed');
}
phantom.exit();
};
**See full code below for my console.log message.
Now phantomjs apparently has an event api built in but it is undocumented. I was also successfully able to get request/response messages from their page.onResourceReceived and page.onResourceRequested - meaning you can debug when all your required modules are loaded. To communicate my test result however, I just used console.log.
Now what happens if the console.log message is never ran? The only way I could think of resolving this was to use setTimeout
setTimeout(function() {
console.log('amd test failed - timeout');
phantom.exit();
}, 500);
That should do it!
Full Code
directory structure
/projectRoot
/tests
- amd.js
- amdTestModule.js
- amd.html
- require.js (which I symlinked)
- <dependencies> (also symlinked)
amd.js
'use strict';
var page = require('webpage').create();
var fs = require('fs');
/*
page.onResourceRequested = function(req) {
console.log('\n');
console.log('REQUEST');
console.log(JSON.stringify(req, null, 4));
console.log('\n');
};
page.onResourceReceived = function(response) {
console.log('\n');
console.log('RESPONSE');
console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response, null, 4));
console.log('\n');
};
*/
page.onConsoleMessage = function(msg) {
msg = msg.split('=');
if (msg[1] === 'success') {
console.log('amd test successful');
} else {
console.log('amd test failed');
}
phantom.exit();
};
page.open('file://' + fs.absolute('tests/amd.html'));
setTimeout(function() {
console.log('amd test failed - timeout');
phantom.exit();
}, 500);
amd.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script data-main='amdTestModule.js' src='require.js'></script>
</body>
</html>
amdTestModule.js
require([<dependencies>], function(<dependencies>) {
...
console.log(
(<test>) ? "test=success" : "test=failed"
);
});
console
$ phantomjs tests/amd.js
amd test successful
you are misunderstanding webpage.injectJs()
it's for injecting scripts into the page you are loading, not into the phantomjs runtime environment.
So using .injectJs() is making requirejs load up into your page, not into phantomjs.exe.
That said, phantomjs's runtime environment has an aproximation of commonjs. RequireJs will not run on there by default. If you felt especially (VERY) motivated, you could attempt porting the require-shim made for nodejs, but it doesn't work out of the box, and would require an incredibly deep understanding of the runtimes. for more details: http://requirejs.org/docs/node.html
a better idea:
probably you should make sure you have commonjs versions of your javascript you wish to run. i personally write my code in typescript so i can build for either commonjs or amd. i use commonjs for phantomjs code, and amd for nodejs and browser.