Hi I'm new to web development and I'm trying to play around with Cytoscape.js. I decided to use Node.js, Express, and Express-handlebars to run my webpage. I wanted to use Cytoscape.js to display a graph however I'm not sure how to use handlebars to get a reference to the container to initialize the cytoscape object.
Here's my main.handlebars file:
<!doctype html>
<html>
<head>
<title>Hello Cytoscape</title>
</head>
<body>
{{{body}}}
</body>
</html>
Here's my home.handlebars file:
<div id="cy"></div>
Here's my .js file:
/**
*
*/
'use strict';
var express = require('express');
var app = express();
var cytoscape = require('cytoscape');
//layout defaults to main, located in the views layout folder
var handlebars = require('express-handlebars').create({defaultLayout:'main'});
app.use(express.static('public'));
//sets the template engine to use for the express object
//a template engine will implement the view part of the app
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');
//initialize the cytoscape object
var cy = cytoscape({
//<----not sure how to do this----->
container: document.getElementById('cy'), // container to render in
elements: [ // list of graph elements to start with
{ // node a
data: { id: 'a' }
},
{ // node b
data: { id: 'b' }
},
{ // edge ab
data: { id: 'ab', source: 'a', target: 'b' }
}
],
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
rows: 1
},
// initial viewport state:
zoom: 1,
pan: { x: 0, y: 0 },
// interaction options:
minZoom: 1e-50,
maxZoom: 1e50,
zoomingEnabled: true,
userZoomingEnabled: true,
panningEnabled: true,
userPanningEnabled: true,
boxSelectionEnabled: false,
selectionType: 'single',
touchTapThreshold: 8,
desktopTapThreshold: 4,
autolock: false,
autoungrabify: false,
autounselectify: false,
// rendering options:
headless: false,
styleEnabled: true,
hideEdgesOnViewport: false,
hideLabelsOnViewport: false,
textureOnViewport: false,
motionBlur: false,
motionBlurOpacity: 0.2,
wheelSensitivity: 1,
pixelRatio: 'auto'
});
app.get('/', function (req, res) {
var context = {};
res.render('home', context);
});
//listener all for unrecognized urls
//return 404 not found response
app.use(function(req,res){
res.status(404);
res.render('404');
});
//listener for errors generate on server
//return 500 response
app.use(function(err, req, res, next){
console.error(err.stack);
res.type('plain/text');
res.status(500);
res.render('500');
});
if (module === require.main) {
// [START server]
// Start the server
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log('App listening on port %s', port);
});
// [END server]
}
module.exports = app;
So I guess my question is how do I get a reference to the div container id="cy" to initialize my Cytoscape.js graph using express-handlebars, thanks in advance for any help.
If you run Cytoscape on the serverside -- as you're doing in your example -- then it's not running and not shown on the clientside.
Unless you're doing serverside-only graph analysis, you should be using Cytoscape on the clientside. Your page (main.handlebars) is the driver of everything clientside, so put your Cytoscape code there. Or in the page, reference your Cytoscape code with a <script> tag.
Related
I am using ngx-quill editor as my rich text editor in my angular project. So that I can save HTML generated by it in DB and then render it on different browsers as innerHTML. As it is not using inline CSS and there is a class attribute to style the HTML which refers to the inbuilt classes of this editor. I want to render this HTML on the platform where these inbuilt-classes are not available.
How to render the HTML on the page where these inbuilt classes are not available?
OR
Is there any way to convert these classes into inline styles?
OR
and if any other options to render HTML saved by this editor with the styling applied to it?
Any help would be appreciated
It's definitely possible. I managed to do it, but not in an Angular way, so in the end I am only using quill and not ngx-quill. I've been trying to figure out how to adjust ngx-quill to reflect this but with no success yet.
Anyway if you want to know how I am currently doing it.
First I create the html element:
<div id="editor"></div>
Then I add this to the top of my component:
import Quill from 'quill'
var DirectionAttribute = Quill.import('attributors/attribute/direction');
Quill.register(DirectionAttribute, true);
var AlignClass = Quill.import('attributors/class/align');
Quill.register(AlignClass, true);
var BackgroundClass = Quill.import('attributors/class/background');
Quill.register(BackgroundClass, true);
var ColorClass = Quill.import('attributors/class/color');
Quill.register(ColorClass, true);
var DirectionClass = Quill.import('attributors/class/direction');
Quill.register(DirectionClass, true);
var FontClass = Quill.import('attributors/class/font');
Quill.register(FontClass, true);
var SizeClass = Quill.import('attributors/class/size');
Quill.register(SizeClass, true);
var AlignStyle = Quill.import('attributors/style/align');
Quill.register(AlignStyle, true);
var BackgroundStyle = Quill.import('attributors/style/background');
Quill.register(BackgroundStyle, true);
var ColorStyle = Quill.import('attributors/style/color');
Quill.register(ColorStyle, true);
var DirectionStyle = Quill.import('attributors/style/direction');
Quill.register(DirectionStyle, true);
var FontStyle = Quill.import('attributors/style/font');
Quill.register(FontStyle, true);
var SizeStyle = Quill.import('attributors/style/size');
Quill.register(SizeStyle, true);
And then in my init method I declare it:
ngOnInit() {
this.editor = new Quill('#editor', {
modules: {
'toolbar': [
[{ 'font': [] }, { 'size': [] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'script': 'super' }, { 'script': 'sub' }],
[{ 'header': '1' }, { 'header': '2' }, 'blockquote', 'code-block'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }],
['direction', { 'align': [] }],
['link', 'image', 'video']
]
},
theme: 'snow'
})
}
And then wherever I want to read the content:
this.email.message = this.editor.root.innerHTML
Of course this is not ideal at all, and it's a lot of code that I prefer to have inside a component. Maybe somebody else can help out squeezing this in a component
I was following the phaser 3.x tutorial to make a simple game. Phaser Tutorial I used meteor.js as a platform for that.
Everything worked just fine:
Template.App_home.helpers({
game: function() {
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
function preload ()
{
this.load.image('sky', './assets/sky.png');
this.load.image('ground', './assets/platform.png');
this.load.image('star', './assets/star.png');
this.load.image('bomb', './assets/diamond.png');
this.load.spritesheet('dude',
'./assets/dude.png',
{ frameWidth: 32, frameHeight: 48 }
);
}
var platforms;
function create ()
{
this.add.image(400, 300, 'sky');
platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground').setScale(2).refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.physics.add.collider(player, platforms);
cursors = this.input.keyboard.createCursorKeys();
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: [ { key: 'dude', frame: 4 } ],
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});
}
function update ()
{
if (cursors.left.isDown)
{
player.setVelocityX(-160);
player.anims.play('left', true);
}
else if (cursors.right.isDown)
{
player.setVelocityX(160);
player.anims.play('right', true);
}
else
{
player.setVelocityX(0);
player.anims.play('turn');
}
if (cursors.up.isDown && player.body.touching.down)
{
player.setVelocityY(-330);
}
}
}
});
I called the game function with {{game}} but I realized when I switched the route of my site the game was on every page. Is there some way to isolate the game on just one template/area? It even duplicated after I went back to the original page where I put the {{game}}.
Thanks for any help!
Instead of within the helper, try inside its own Template.onCreated, and using {{> game}} the template spacebars instead of the helper spacebars. This seems to work ok for me so far but I haven't tested much beyond this (if I remove the {{> game}}, then the game isn't instantiated so I assume this will work ok)... Im moving my game from a webpack build over into meteor so ill update if i run into any problems! Unfortunately a lot of the examples of this Ive seen are outdated packages or pseudo code so hopefully this is helpful...
dont forget to :
meteor npm install phaser
/client/main.html:
<head>
<title>example-meteor</title>
</head>
<body>
{{> game}}
</body>
<template name="game">
</template>
/client/main.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
// import logoImg from "./assets/logo.png";
import './main.html';
import Phaser from "phaser";
let config;
let game;
Template.game.onCreated( () => {
config = {
type: Phaser.AUTO,
parent: "phaser-example",
width: 900,
height: 900,
scene: {
preload: preload,
create: create
}
};
game = new Phaser.Game(config);
function preload() {
// this.load.image("logo", logoImg);
}
function create() {
console.log('game created')
}
});
Template.game.helpers({
});
Template.game.events({
});
I am trying to test my app and followed this link http://lathonez.github.io/2016/ionic-2-e2e-testing/ i merged my app with firebase. Everything worked good, but when i run npm run e2e browser opens and close immediately in my terminal pops an error.
I followed this link http://lathonez.github.io/2016/ionic-2-e2e-testing/
Actually my issue is that i could not able to see any action takes place in my e2e browser could some on help me
protractorconfig.js
exports.config = {
baseUrl: 'http://192.168.1.2:8100/',
specs: [
'../app/pages/home/home.e2e.ts',
'../app/pages/Admin/admin.e2e.ts',
//'../app/pages/Listing/lisitngPage.e2e.ts'
],
exclude: [],
framework: 'jasmine2',
allScriptsTimeout: 110000,
jasmineNodeOpts: {
showTiming: true,
showColors: true,
isVerbose: false,
includeStackTrace: false,
defaultTimeoutInterval: 400000
},
directConnect: true,
chromeOnly: true,
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
'args': ['--disable-web-security']
}
},
onPrepare: function() {
var SpecReporter = require('jasmine-spec-reporter');
jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: true}));
browser.ignoreSynchronization = false;
},
useAllAngular2AppRoots: true
};
gulpfile.ts
import { join } from 'path';
const config: any = {
gulp: require('gulp'),
appDir: 'app',
testDir: 'test',
testDest: 'www/build/test',
typingsDir: 'typings',
};
const imports: any = {
gulp: require('gulp'),
runSequence: require('run-sequence'),
ionicGulpfile: require(join(process.cwd(), 'gulpfile.js')),
};
const gulp: any = imports.gulp;
const runSequence: any = imports.runSequence;
// just a hook into ionic's build
gulp.task('build-app', (done: Function) => {
runSequence(
'build',
(<any>done)
);
});
// compile E2E typescript into individual files, project directoy structure is replicated under www/build/test
gulp.task('build-e2e', ['clean-test'], () => {
let typescript: any = require('gulp-typescript');
let tsProject: any = typescript.createProject('tsconfig.json');
let src: Array<any> = [
join(config.typingsDir, '/index.d.ts'),
join(config.appDir, '**/*e2e.ts'),
];
let result: any = gulp.src(src)
.pipe(typescript(tsProject));
return result.js
.pipe(gulp.dest(config.testDest));
});
// delete everything used in our test cycle here
gulp.task('clean-test', () => {
let del: any = require('del');
// You can use multiple globbing patterns as you would with `gulp.src`
return del([config.testDest]).then((paths: Array<any>) => {
console.log('Deleted', paths && paths.join(', ') || '-');
});
});
// run jasmine unit tests using karma with PhantomJS2 in single run mode
gulp.task('karma', (done: Function) => {
let karma: any = require('karma');
let karmaOpts: {} = {
configFile: join(process.cwd(), config.testDir, 'karma.config.js'),
singleRun: true,
};
new karma.Server(karmaOpts, done).start();
});
// run jasmine unit tests using karma with Chrome, Karma will be left open in Chrome for debug
gulp.task('karma-debug', (done: Function) => {
let karma: any = require('karma');
let karmaOpts: {} = {
configFile: join(process.cwd(), config.testDir, 'karma.config.js'),
singleRun: false,
browsers: ['Chrome'],
reporters: ['mocha'],
};
new karma.Server(karmaOpts, done).start();
});
// run tslint against all typescript
gulp.task('lint', () => {
let tslint: any = require('gulp-tslint');
return gulp.src(join(config.appDir, '**/*.ts'))
.pipe(tslint())
.pipe(tslint.report('verbose'));
});
// build unit tests, run unit tests, remap and report coverage
gulp.task('unit-test', (done: Function) => {
runSequence(
['lint', 'html'],
'karma',
(<any>done)
);
});
I keep seeing this error when executing the compiled file:
Uncaught Error: No json
Here's my current requirejs grunt task configuration:
requirejs: {
options: {
baseUrl: "build/repos/staging/dev",
mainConfigFile: "dev/main.js",
generateSourceMaps: false,
preserveLicenseComments: false,
name: "almond",
out: "./static/js/compiled.js",
//excludeShallow: ['vendor'],
findNestedDependencies: true,
removeCombined: true,
//wrap: true,
optimize: "uglify2",
uglify2: {
output: {
beautify: true,
},
lint: true,
mangle: false,
compress: false,
compress: {
sequences: false
}
}
}
}
And here's my dev/main.js file:
// This is the runtime configuration file.
// It also complements the Gruntfile.js by supplementing shared properties.require.config({
waitSeconds: 180,
urlArgs: 'bust=' + (new Date()).getTime(),
paths: {
"underscore": "../vendor/underscore/underscore",
"backbone": "../vendor/backbone/backbone",
"layoutmanager": "../vendor/layoutmanager/backbone.layoutmanager",
"lodash": "../vendor/lodash/lodash",
"ldsh": "../vendor/lodash-template-loader/loader",
"text": "../vendor/requirejs-plugins/lib/text",
"json": "../vendor/requirejs-plugins/json",
"almond": "../vendor/almond/almond",
// jquery
"jquery": "../vendor/jquery/jquery",
"jquery.transit": "../vendor/jquery.transit/jquery.transit",
"jquery.mousewheel": "../vendor/jquery.mousewheel/jquery.mousewheel",
"jquery.jscrollpane": "../vendor/jquery.jscrollpane/jquery.jscrollpane"
},
shim: {
'backbone': {
deps: ['underscore']
},
'layoutmanager': {
deps: ['backbone', 'lodash', 'ldsh']
},
'jquery.transit': {
deps: ['jquery']
},
'json': {
deps: ['text']
}
}});
// App initialization
require(["app"], function(instance) {
"use strict";
window.app = instance;
app.load();
});
And finally, my dev/app.js file:
define(function(require, exports, module) {
"use strict";
// External global dependencies.
var _ = require("underscore"),
$ = require("jquery"),
Transit = require('jquery.transit'),
Backbone = require("backbone"),
Layout = require("layoutmanager");
module.exports = {
'layout': null,
'load': function() {
var paths = [
// ***
// *** 1- define its path
// ***
'json!config/main.json',
'modules/nav',
'modules/store',
'modules/utils',
'modules/preloader',
'modules/popup',
'modules/login',
'modules/user',
'modules/footer',
];
try {
require(paths, function(
// ***
// *** 2- call it a name
// ***
Config,
Nav,
Store,
Utils,
Preloader,
Popup,
Login,
User,
Footer
) {
// ***
// *** 3- instance it in the app
// ***
app.Config = Config;
app.Nav = Nav;
app.Store = Store;
app.Utils = Utils;
app.Preloader = Preloader;
app.Popup = Popup;
app.Login = Login;
app.User = User;
app.Footer = Footer;
// require and instance the router
require(['router'], function(Router) {
// app configuration
app.configure();
// app initialization
app.Router = new Router();
});
});
} catch (e) {
console.error(e);
}
},
'configure': function() {
var that = this;
// set environment
this.Config.env = 'local';
// Ajax global settings
Backbone.$.ajaxSetup({
'url': that.Config.envs[that.Config.env].core,
'timeout': 90000,
'beforeSend': function() {
},
'complete': function(xhr, textstatus) {
}
});
// Template & layout
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
Layout.configure({
// Allow LayoutManager to augment Backbone.View.prototype.
manage: true,
// Indicate where templates are stored.
prefix: "app/templates/",
// This custom fetch method will load pre-compiled templates or fetch them
// remotely with AJAX.
fetch: function(path) {
// Concatenate the file extension.
path = path + ".html";
// If cached, use the compiled template.
if (window.JST && window.JST[path]) {
return window.JST[path];
}
// Put fetch into `async-mode`.
var done = this.async();
// Seek out the template asynchronously.
$.get('/' + path, function(contents) {
window.JST[path] = contents;
done(_.template(contents));
}, "text");
}
});
},
};
});
Any ideas why is that json module not "required" when executing grunt requirejs ?
Thanks in advance.
Not sure if this is still an issue, but from the requirejs optimizer docs (http://requirejs.org/docs/optimization.html):
The optimizer will only combine modules that are specified in arrays of string literals that are passed to top-level require and define calls, or the require('name') string literal calls in a simplified CommonJS wrapping. So, it will not find modules that are loaded via a variable name...
It sounds like the requirejs optimizer doesn't like the require calls being made with a variable that is an array of dependencies.
It also sounds like the requirejs optimizer doesn't like the syntax of require([dependency array], callback) being used within the actual file being optimized.
You may have to refactor your dependency declarations within dev/app.js to conform to this specification. For example, you might be able to use the following refactoring of steps 1 and 2:
var Config = require('json!config/main.json');
var Nav = require('modules/nav');
var Store = require('modules/store');
var Utils = require('modules/utils');
var Preloader = require('modules/preloader');
var Popup = require('modules/popup');
var Login = require('modules/login');
var User = require('modules/user');
var Footer = require('modules/footer');
If this does work, it looks like you'll also have to do something similar for the Router dependency declaration.
Also, a minor addition that you might want to include to your requirejs configuration once you get it running is:
stubModules : ['json']
Since the built file should have the JSON object within it, you won't even need the plugin within the built file! As such, you can reduce your file size by removing the json plugin from it.
I'm quite new to sencha touch. The goal is to create an app which has a TabPanel containing four Tabs, one of them should be a map (the others are a NestedList and two Panels working like a charm). I've tried to make the map card like
NPApp.views.Mapcard = Ext.extend(Ext.Map, { ...
where I ended up with getting really strange results like some views are overlapping and no map is shown.
The second try was to creating a Panel, embed it into the TabPanel and add a map to the panel, where I get this error:
Uncaught TypeError: Cannot read property 'ROADMAP' of undefined;
sencha-touch-debug.js:24840
I've already tried to change the mapType to google.map.MapTypeID like mentioned in the Google Map API V3, no success there.
I just can't get the hang on it, hope you can give me some hints!
The App:
NPApp = new Ext.Application({
name: "NPApp",
title: "NextPuff",
icon: 'images/icon.png',
tabletStartupScreen: 'images/index_default.jpg',
phoneStartupScreen: 'images/index_default.jpg',
launch: function() {
this.views.viewport = new this.views.Viewport();
this.views.homecard = this.views.viewport.getComponent('navi');
}
});
The Viewport:
NPApp.views.Viewport = Ext.extend(Ext.TabPanel, {
fullscreen: true,
store: NPApp.npstore,
initComponent: function() {
Ext.apply(this, {
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
{ xtype: 'homecard', stretch: true},
{ xtype: 'searchcard', id: 'navi' },
{ xtype: 'mapcard' },
{ xtype: 'morecard' }
]
});
NPApp.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});
The Mapcard:
NPApp.views.Mapcard = Ext.extend(Ext.Panel, {
title: "Map",
iconCls: "map",
initComponent: function() {
var npMap = new Ext.Map({
title: 'Map',
useCurrentLocation: true,
listeners: {
centerchange : function(comp, map){
// refreshMap(map);
}
},
mapOptions : {
mapTypeControl : false,
navigationControl : false,
streetViewControl : false,
backgroundColor: 'transparent',
disableDoubleClickZoom: true,
zoom: 17,
draggable: false,
keyboardShortcuts: false,
scrollwheel: false
}
});
Ext.apply(this, {
defaults: {
styleHtmlContent: true
},
items: [npMap]
});
NPApp.views.Homecard.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('mapcard', NPApp.views.Mapcard);
Sencha 1.1.0; Google JavaScript Maps API V3; Safari 5.1
I have a similar application running. Your tabpanel is perfect. All you need to alter is your map code.... Try this instead :
var map = new Ext.Map({
mapOptions : {
center : center,
zoom : 20,
mapTypeId : google.maps.MapTypeId.HYBRID,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
}
},
listeners : {
maprender : function(comp, map){
var marker = new google.maps.Marker({
position: center,
//title : 'Sencha HQ',
map: map
});
setTimeout( function(){map.panTo (center);} , 1000);
}
},
geo:new Ext.util.GeoLocation({
autoUpdate:true,
maximumAge: 0,
timeout:2000,
listeners:{
locationupdate: function(geo) {
center = new google.maps.LatLng(geo.latitude, geo.longitude);
if (map.rendered)
map.update(center)
else
map.on('activate', map.onUpdate, map, {single: true, data: center});
},
locationerror: function ( geo,
bTimeout,
bPermissionDenied,
bLocationUnavailable,
message) {
if(bLocationUnavailable){
alert('Your Current Location is Unavailable on this device');
}
else{
alert('Error occurred.');
}
}
}
})
});
This creates the map object and sets the center to ur current location. Now you need to dock this object inside an Ext.extend(Ext.Panel({}) object. Ive tried directly creating the map object but it needs a panel to display on.
So you're panel code should go something like so:
NPApp.views.Mapcard = new Ext.extend(Ext.Panel({
iconCls : 'map',
title : 'Map',
layout: 'card',
ui: 'light',
items: [map],
listeners:{
}
});
)
It took me ages of going thru a dozen or more examples to make the current location work. This is a combination of several codes and a bunch of stuff in the Google API.
Lemme know if you have any more questions about Google Maps or directions.
Cheers :)
Sasha