I am trying to integrate snap.svg in to Enyo and having a problem. The code below works, until render() is called. The problem seems to be that generateHtml in HTMLStringDelegate.js doesn't know about the content added by snap.svg and clears out "svg".
Uncomment "this.render();" to see it.
http://jsfiddle.net/Kloodge/g7MLS/2031/
var ready = require('enyo/ready'),
kind = require('enyo/kind'),
Toolbar = require('onyx/Toolbar'),
Application = require('enyo/Application');
ready(function() {
var MySample = kind({
name: "MySample",
paper: null,
components: [
{kind: Toolbar, content: "Your sample here."},
{tag: "svg", name:"svg"}
],
rendered: function(){
this.inherited(arguments);
if(!this.paper && this.$.svg.hasNode()){
this.paper = Snap("#"+this.$.svg.hasNode().id);
circle = this.paper.circle(10, 10, 10);
circle.attr({
fill: "#bada55",
stroke: "#000",
strokeWidth: 5,
});
//this.render();
}
}
});
new Application({view: MySample});
});
Is there any way to do this short of adding the content statically to "svg"?
Related
I'm trying to create a custom credits with a tooltip, I've found and example of setting an event listener to title and add tooltip to chart title using mouseover. But for some reason adding this event listener doesn't seem to work with my custom label created with SVGRenderer, what am I missing??
My attempt: https://jsfiddle.net/bernardo0marques/ovhx39c8/10/
Notice that in your example, in the load callback you are trying to add a custom event to the label which doesn't exist because it wasn't rendered yet.
Check console: https://jsfiddle.net/BlackLabel/u07y5gnr/
To fix it, add this logic after rendering this label: https://jsfiddle.net/BlackLabel/p4mL23yr/
chart: {
events: {
render: function() {
let chart = this,
credits = chart.options.credits;
// keep label responsive
if (chart.customLabel) chart.customLabel.destroy();
chart.customLabel = chart.renderer
.label('my custom text', 0, 0).css(credits.style)
.add();
chart.customLabel.translate(chart.plotWidth, chart.chartHeight - chart.customLabel.getBBox().height)
chart.customLabel.on('mouseover', e => {
chart.myLabel = this.renderer.label(this.title.textStr, e.x - 75, e.y - 50, 'rectangle')
.css({
color: '#FFFFFF'
})
.attr({
fill: 'rgba(0, 0, 0, 0.75)',
padding: 8,
r: 4,
})
.add()
.toFront();
});
chart.customLabel.on('mouseout', e => {
if (chart.myLabel) {
chart.myLabel.destroy();
}
})
}
},
},
I've been googling for days now, and getting kind of frustrated.. I hope anyone can help me!
What I'm trying to achieve is the controls (as shown below), which if pressing the DOWN button for example, it will show the map layer which is one "floor" below the current, and set the "0" to "-1".
<---
My current map looks like this, and I want to be able to go up and down on "floors".
This is the GROUND level
And this is -1 floor, the level beneath the above image
I have all the images etc, I have basic understanding of Leaflet, but I can't figure out how to add this control and make it load the desired level.
Anyone that could help me, or lead me in the right direction?
Kind Regards,
Andreas.
I created a working controler for you (but it is not designed):
L.LayerControl = L.Control.extend({
options: {
position: 'topright',
layerIdx: 0,
//control position - allowed: 'topleft', 'topright', 'bottomleft', 'bottomright'
},
initialize: function(layers, options) {
this.layers = layers;
L.setOptions(this, options);
},
onAdd: function (map) {
this.map = map;
var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control layercontrol');
var buttonUp = L.DomUtil.create('a', '', container);
buttonUp.innerHTML = '^';
this.text = L.DomUtil.create('a', '', container);
this.text.innerHTML = this.layers[this.options.layerIdx].name;
this.text.style.fontWeight = '900';
var buttonDown = L.DomUtil.create('a', '', container);
buttonDown.innerHTML = 'v';
L.DomEvent.disableClickPropagation(container);
L.DomEvent.on(buttonUp, 'click', this._clickUp, this);
L.DomEvent.on(buttonDown, 'click', this._clickDown, this);
this._removeAllLayers();
this.map.addLayer(this.layers[this.options.layerIdx].layer);
return container;
},
_clickUp : function () {
if(this.layers.length -1 > this.options.layerIdx){
this.map.fire('layercontrolUp', {layer: this.layers[this.options.layerIdx].layer, name: this.layers[this.options.layerIdx].name});
this.options.layerIdx++;
this.text.innerHTML = this.layers[this.options.layerIdx].name;
this._removeAllLayers();
this.map.addLayer(this.layers[this.options.layerIdx].layer);
}
},
_clickDown : function () {
if(0 < this.options.layerIdx){
this.map.fire('layercontrolDown', {layer: this.layers[this.options.layerIdx].layer, name: this.layers[this.options.layerIdx].name});
this.options.layerIdx--;
this.text.innerHTML = this.layers[this.options.layerIdx].name;
this._removeAllLayers();
this.map.addLayer(this.layers[this.options.layerIdx].layer);
}
},
_removeAllLayers: function(){
//removing all layers from the map where added from the control
this.layers.forEach(function(controlLayer){
this.map.removeLayer(controlLayer.layer);
});
}
});
var fg1 = new L.FeatureGroup();
fg1.addLayer(L.marker([51.5, -0.09]).bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup());
var fg2 = new L.FeatureGroup();
fg2.addLayer(L.circle([51.508, -0.11], 500, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
}).bindPopup("I am a circle."));
var fg3 = new L.FeatureGroup();
fg3.addLayer(L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]).bindPopup("I am a polygon."));
var layerControlLayers = [
{
name: 'KG1',
layer: fg1
},
{
name: 'KG2',
layer: fg2
},
{
name: 'EG',
layer: fg3
},
]
//layerIdx: start counting with 0 = KG1
new L.LayerControl(layerControlLayers, {layerIdx: 2}).addTo(map)
map.on('layercontrolUp', function(e){
console.log(e);
});
map.on('layercontrolDown', function(e){
console.log(e);
});
I have UML state diagram drawn using jointjs and the various states are connected through links. On hovering over the links, a cross symbol appears upon clicking which the link gets removed. I want to disable the cross symbol over the link.
You will need to create a custom link extending from joint.dia.link and use that link for your charts. Look into joint.core.js for more details and joint.shapes.uml.js
Step1. Create your custom uml link either by extending directly from joint.dia.link or by extending from the below
joint.shapes.uml.Generalization
joint.shapes.uml.Implementation
joint.shapes.uml.Aggregation
joint.shapes.uml.Composition
joint.shapes.uml.Association
joint.shapes.yourLink = joint.dia.Link.extend({
//to remove the cross that removes the link modify the toolMarkUp to not show anything as below and use your new link
toolMarkup: [
].join(''),
add the remaining attributes that you currently have for the link like source, target etc
})
sample code from my project
joint.shapes.deviceLink = joint.dia.Link.extend({
// i modified the vertexMarkup to not create vertexes.
vertexMarkup: [
'<g class="marker-vertex-group" transform="translate(<%= x %>, <%= y %>)">',
'<circle class="marker-vertex" idx="<%= idx %>" r="1" />',
'</g>'
].join(''),
defaults: joint.util.deepSupplement({
type: 'deviceLink',
connection: { name: 'orthogonal' },
attrs: {
'.connection': { stroke: '#fe854f', 'stroke-width': 3 },
sourcePort:{text:''},
targetPort:{text:''},
'.link-tools .tool-remove circle': { r: 8, fill:'#fff',position: 0.5 },
},
labels: [ { position: 0.5, attrs: { text: { text: '' } } } ]
}, joint.dia.Link.prototype.defaults),
});
joint.shapes.deviceLinkView = joint.dia.LinkView.extend({
mouseover: function (evt, x, y) {
//my custom mouseover function
},
mouseout: function (evt, x, y) {
// my custom mouseout function
});
Once a grid is rendered how can I set focus to the first item. I am running into a problem where when the grid is updated (collection changes) then focus is lost for the entire application .
I am using the moonstone library.
{
kind: "ameba.DataGridList", name: "gridList", fit: true, spacing: 20, minWidth: 300, minHeight: 270, spotlight : 'container',
scrollerOptions:
{
kind: "moon.Scroller", vertical:"scroll", horizontal: "hidden", spotlightPagingControls: true
},
components: [
{kind : "custom.GridItemControl", spotlight: true}
]
}
hightlight() is a private method for Spotlight which only adds the spotlight class but does not do the rest of the Spotlight plumbing. spot() is the method you should be using which calls highlight() internally.
#ruben-ray-vreeken is correct that DataList defers rendering. The easiest way to spot the first control is to set initialFocusIndex provided by moon.DataListSpotlightSupport.
http://jsfiddle.net/dcw7rr7r/1/
enyo.kind({
name: 'ex.App',
classes: 'moon',
bindings: [
{from: ".collection", to: ".$.gridList.collection"}
],
components: [
{name: 'gridList', kind:"moon.DataGridList", classes: 'enyo-fit', initialFocusIndex: 0, components: [
{kind:"moon.CheckboxItem", bindings: [
{from:".model.text", to:".content"},
{from:".model.selected", to: ".checked", oneWay: false}
]}
]}
],
create: enyo.inherit(function (sup) {
return function () {
sup.apply(this, arguments);
// here, at least, the app starts in pointer mode so spotting the first control
// isn't apparent (though it would resume from that control upon 5-way action).
// Turning off pointer mode does the trick.
enyo.Spotlight.setPointerMode(false);
this.set("collection", new enyo.Collection(this.generateRecords()));
};
}),
generateRecords: function () {
var records = [],
idx = this.modelIndex || 0;
for (; records.length < 20; ++idx) {
var title = (idx % 8 === 0) ? " with long title" : "";
var subTitle = (idx % 8 === 0) ? "Lorem ipsum dolor sit amet" : "Subtitle";
records.push({
selected: false,
text: "Item " + idx + title,
subText: subTitle,
url: "http://placehold.it/300x300/" + Math.floor(Math.random()*0x1000000).toString(16) + "/ffffff&text=Image " + idx
});
}
// update our internal index so it will always generate unique values
this.modelIndex = idx;
return records;
},
});
new ex.App().renderInto(document.body);
Just guessing here as I don't use Moonstone, but the plain enyo.Datalist doesn't actually render its list content when the render method is called. Instead the actual rendering task is deferred and executed at a later point by the gridList's delegate.
You might want to dive into the code of the gridList's delegate and check out how it works. You could probably create a custom delegate (by extending the original) and highlight the first child in the reset and/or refresh methods:
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
Ruben's answer adds on to my answer that I posted in the Enyo forums, which I'm including here for the sake of completeness:
Try using
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
I added a rendered() function to the Moonstone DataGridList sample in the Sampler and I found that this works:
rendered: function() {
this.inherited(arguments);
this.startJob("waitforit", function() {
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
}, 400);
},
It didn't work without the delay.
I am trying to use jsPlumb to connect questions with answers in a quiz. I have most of this working expect I want to be able to click a question and then click an answer instead of dragging from an endpoint to another endpoint. This is because dragging on a touch device is tedious. Is this possible?
Here is my jsbin with the dragging working
Here is the jquery I am using.
$(document).ready(function () {
var targetOption = {
anchor: "LeftMiddle",
isSource: false,
isTarget: true,
reattach: true,
endpoint: "Rectangle",
connector: "Straight",
connectorStyle: { strokeStyle: "#ccc", lineWidth: 5 },
paintStyle: { width: 20, height: 20, fillStyle: "#ccc" },
setDragAllowedWhenFull: true
}
var sourceOption = {
tolerance: "touch",
anchor: "RightMiddle",
maxConnections: 1,
isSource: true,
isTarget: false,
reattach: true,
endpoint: "Rectangle",
connector: "Straight",
connectorStyle: { strokeStyle: "#ccc", lineWidth: 5 },
paintStyle: { width: 20, height: 20, fillStyle: "#ccc" },
setDragAllowedWhenFull: true
}
jsPlumb.importDefaults({
ConnectionsDetachable: true,
ReattachConnections: true
});
jsPlumb.addEndpoint('match1', sourceOption);
jsPlumb.addEndpoint('match2', sourceOption);
jsPlumb.addEndpoint('match3', sourceOption);
jsPlumb.addEndpoint('match4', sourceOption);
jsPlumb.addEndpoint('answer1', targetOption);
jsPlumb.addEndpoint('answer2', targetOption);
jsPlumb.addEndpoint('answer3', targetOption);
jsPlumb.addEndpoint('answer4', targetOption);
jsPlumb.draggable('match1');
jsPlumb.draggable('answer1');
});
I think if you don't need draggable, then you shouldn't use it, and go with normal click=connect approach.
Here is an example:
http://jsbin.com/ajideh/7/
Basically what I did:
//current question clicked on
var questionSelected = null;
var questionEndpoint = null;
//remember the question you clicked on
$("ul.linematchitem > li").click( function () {
//remove endpoint if there is one
if( questionSelected !== null )
{
jsPlumb.removeAllEndpoints(questionSelected);
}
//add new endpoint
questionSelected = $(this)[0];
questionEndpoint = jsPlumb.addEndpoint(questionSelected, sourceOption);
});
//now click on an answer to link it with previously selected question
$("ul.linematchplace > li").click( function () {
//we must have previously selected question
//for this to work
if( questionSelected !== null )
{
//create endpoint
var answer = jsPlumb.addEndpoint($(this)[0], targetOption);
//link it
jsPlumb.connect({ source: questionEndpoint, target: answer });
//cleanup
questionSelected = null;
questionEndpoint = null;
}
});
When you click on the question list element - it adds endpoint, when you click on the answer element - it also adds endpoint and connects it with previously selected question.
I believe this is what you wanted to do ?
P.S. As a side note, to make this more intuitive for the user, make endpoints for questions visible first, so the user would figure out what to do - click. Once question is selected, available answer endpoints can pop-up hinting where user should click next.