dagre-d3 svg labels not rendering in Meteor - meteor

I'm somehow unable to apply the SVG label example here: http://cpettitt.github.io/project/dagre-d3/latest/demo/svg-labels.html into Meteor.
The svg_edge_label gets created, but somehow won't appear on the edge! Any idea what's unique about Meteor that doesn't allow this to render? (My Meteor app is using the perak:dagre-d3 package)
main.html:
<head></head>
<body></body>
main.js:
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
var g = new dagreD3.graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(function () { return {}; });
svg_edge_label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
edge_tspan = document.createElementNS('http://www.w3.org/2000/svg','tspan');
edge_tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
edge_tspan.setAttribute('dy', '1em');
edge_tspan.setAttribute('x', '1');
edge_link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
edge_link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://google.com/');
edge_link.setAttribute('target', '_blank');
edge_link.textContent = 'IE Capable Edge link';
edge_tspan.appendChild(edge_link);
svg_edge_label.appendChild(edge_tspan);
g.setNode(0, {label: "A"});
g.setNode(1, {label: "B"});
g.setNode(2, {label: "C"});
g.setEdge(0, 1, { labelType: "svg", label: svg_edge_label});
var render = new dagreD3.render();
var svg = d3.select("body").append("svg"),
svgGroup = svg.append("g");
render(d3.select("svg g"), g);

Related

Vue 3 ElTreeSelect Element Plus

I'm working on a personal project using Vue3, Nuxt3 and Element Plus. I'm a beginner with JS/TS and Vue3 and I'm having a problem with the Element Plus TreeSelect Component. I am trying to have the TreeSelect Components selected value be an object but it's always the label field of the object that is selected. Here is my components code.
<template>
<div>
<ClientOnly>
<el-select v-model="selectedEntityDefinitionRef">
<el-option v-for="entityDefinition in scheme.schemeDefinition.entityDefinitions"
:key="entityDefinition.label" :label="entityDefinition.label" :value="entityDefinition">
</el-option>
</el-select>
<el-tree-select check-strictly :render-after-expand="false" show-checkbox check-on-click-node
value-key="label" :data="schemeEntitiesRef" v-model="selectedParentEntityRef"/>
</ClientOnly>
<el-button style="margin-top: 12px" #click="printValues">Add</el-button>
</div>
</template>
<script lang="ts" setup>
import { ElTreeSelect, ElSelect, ElOption, ElButton } from 'element-plus';
import { ref, reactive } from 'vue';
class SchemeDefinition {
label: string
entityDefinitions: Array<EntityDefinition> = new Array<EntityDefinition>()
constructor(label: string) {
this.label = label
}
}
class EntityDefinition {
label: string
constructor(label: string) {
this.label = label
}
}
class Scheme {
schemeDefinition: SchemeDefinition
entities: Array<Entity> = new Array<Entity>()
}
class Entity {
label: string
parent: Entity
children: Array<Entity> = new Array<Entity>()
constructor(label: string) {
this.label = label;
}
}
const schemeDefinition: SchemeDefinition = new SchemeDefinition('Scheme Definition');
const fondsEntityDefinition: EntityDefinition = new EntityDefinition('Entity Definition')
schemeDefinition.entityDefinitions.push(fondsEntityDefinition)
const scheme: Scheme = new Scheme()
scheme.schemeDefinition = schemeDefinition
scheme.entities.push(new Entity('Entity'))
const selectedEntityDefinitionRef = ref<EntityDefinition>()
const selectedParentEntityRef = ref<Entity>()
const schemeEntitiesRef = reactive(scheme.entities)
const printValues = () => {
console.log(selectedEntityDefinitionRef.value)
console.log(selectedParentEntityRef.value)
}
</script>
My question is if I am doing something fundamentally wrong here or is my issue a limitation of the component itself? As a newbie any advice or guidance would be greatly appreciated. Thanks

Inline style instead of quill editor inbuilt classes as classes are not available at the time to render HTML

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

openlayers get layer from feature

I have a select interaction - to select features associated with a vector layer. My goal is to edit the feature attributes and save back to a database.
import Map from 'ol/Map';
import View from 'ol/View';
import Select from 'ol/interaction/Select.js';
...
this.map = new Map({
target: 'map',
view: new View({
center: this.$root.mapState.center,
zoom: this.$root.mapState.zoom
})
});
AddLayers(this.map, this.$root.map.layers, this.$root.register);
this.select = new Select();
this.map.addInteraction(this.select);
this.select.on('select', function(e) {
e.target.getFeatures().forEach(function(feature) {
alert('Selected ' + feature.getId());
});
});
How do I get the layer from the feature?
The answer to this question from 2015 would appear to work.
Do I really have to go through all this? In OpenLayers 2, I would refer to feature.layer - this functionality appears to have gone.
Thanks to #Mike, I added me.select.getLayer(feature) in the loop over the features.
Full solution is:
import Map from 'ol/Map';
import View from 'ol/View';
import Select from 'ol/interaction/Select.js';
...
this.map = new Map({
target: 'map',
view: new View({
center: this.$root.mapState.center,
zoom: this.$root.mapState.zoom
})
});
AddLayers(this.map, this.$root.map.layers, this.$root.register);
this.select = new Select();
this.map.addInteraction(this.select);
var me = this;
this.select.on('select', function(e) {
e.target.getFeatures().forEach(function(feature) {
var layer = me.select.getLayer(feature);
alert('Selected ' + feature.getId());
});
});

Using express-handlebars with Cytoscape.js

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.

dojo dynamic datagrid without element id

I need to great Dojo DataGrids on-the-fly in a complex RIA app. The problem is I can't use element id's. How can I create DataGrids in javascript and then insert it into the page? Here's what I'm currently doing:
Backbone.View.extend({
name: 'checkout',
template: dojo.cache('plugins.patrons.views.templates', 'actions/checkout.html'),
el: $('<div>'),
store: new dojo.store.Memory({data: [{id: 1, "accession": '1000', "title": 'my book'}]}),
initialize: function(el, data) { this.el = el; this.data = data; },
render: function()
{
dojo.parser.parse(this.el.empty().html(_.template(this.template, this.data, {variable: 'data'}))[0]);
var grid = new DataGrid({
store: ObjectStore({objectStore: this.store}),
structure: [
{name:"Accession Number", field:"accession", width: "200px"},
{name:"Title", field:"title", width: "400px"}
]
});
$('.checkout.action .data-grid', this.el).append(grid.domNode);
grid.startup();
return this;
}
});
This builds the table, but you can't see it, and there's no data.
Try giving the grid an explicit height.
var grid = new DataGrid({
height: 400px,
store: ObjectStore({objectStore: this.store}),
structure: [
{name:"Accession Number", field:"accession", width: "200px"},
{name:"Title", field:"title", width: "400px"}
]
});

Resources