im trying to show a picture as a node to be draggable for a react projet.
Im using GoJS for that. I managed to create the node and it's draggble but the image doesnt appear in it.
Here is my code :
renderCanvas(){
try{
//1- Create a diagram (act as the view to the model/data )
let myDiagram =
$(go.Diagram, "MyDiagDiv",
{
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true
}
);
// 1- End
//4- define node template
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
{background:"#44CCFF"},
$(go.Picture,
{margin:10, width:50, height:50, background:"red"},
new go.Binding("source")
),
$(go.TextBlock,
"Default Text",
{margin:12, stroke:"white", font:"bold 16px sans-serif"},
new go.Binding("text", "name")
)
);
//4- End
// 2- Create a model (hold the data)
let myModel = $(go.Model);
myModel.nodeDataArray = [
{name: 'Alpha', source:"./Sinkv4.png"},
{name: 'Beta', source:"./Sinkv4.png"},
{}
];
//2- End
//3- Link diagram to model
myDiagram.model = myModel;
//3- End
}catch(e){
console.log("Error : ", e);
}
} //End RenderCanvas
this is the result im getting :
result
Any Idea why the pictures doesnt appear pls.
Thanks for your help
PS : the images are in the same dir as the file
Related
In CKEditor5 I am creating a plugin to insert a span element to show a tooltip. The idea is to show a tooltip with a (foot)note inside of it while the element itself will display an incremental number. In CKEditor4 I made something like this with:
CKEDITOR.dialog.add( 'footnoteDialog', function( editor ) {
return {
title: 'Footnote Properties',
minWidth: 400,
minHeight: 100,
contents: [
{
id: 'tab-basic',
label: 'Basic Settings',
elements: [
{
type: 'text',
id: 'content',
label: 'Content of footnote',
validate: CKEDITOR.dialog.validate.notEmpty( "Footnote field cannot be empty." )
}
]
}
],
onOk: function() {
var dialog = this;
var footnote = editor.document.createElement( 'span' );
footnote.setAttribute('class', 'footnote');
footnote.setAttribute('data-toggle', 'tooltip');
footnote.setAttribute( 'title', dialog.getValueOf( 'tab-basic', 'content' ) );
footnote.setText('[FN]');
editor.insertElement( footnote );
}
};
});
[FN] would be transformed in an incremental number.
Now I try to make this plugin with in CKEditor5, but with no success. There are two issues I run in to. Fist, I can't manage to insert the element inside the text. Second, when I want to use the attribute data-toggle this doesn't work because of the - syntax. This is my current code:
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import pilcrowIcon from '#ckeditor/ckeditor5-core/theme/icons/pilcrow.svg';
import ButtonView from '#ckeditor/ckeditor5-ui/src/button/buttonview';
export default class Footnote extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add( 'footnote', locale => {
const view = new ButtonView( locale );
view.set( {
label: 'Insert footnote',
icon: pilcrowIcon,
tooltip: true
} );
view.on( 'execute', () => {
const source = prompt( 'Footnote' );
editor.model.schema.register( 'span', { allowAttributes: ['class', 'data-toggle', 'title'] } );
editor.model.change( writer => {
const footnoteElement = writer.createElement( 'span', {
class: 'footnote',
// data-toggle: 'tooltip',
title: source
});
editor.model.insertContent( footnoteElement, editor.model.document.selection );
} );
} );
return view;
} );
}
}
How can I make sure my span element is inserted and also contains data-toggle="tooltip"?
For anyone who comes across this, there is a good description of how to set up inline elements in the model and view and then map between them here - How to add "target" attribute to `a` tag in ckeditor5?
Based on my experience, you will also need to set up Javascript code for a command that is run when a button is pressed. The command will insert the new information into the model, then this mapping code will convert it to the view (HTML) for display.
I am not bale to display links using GOJS and TreeModel. I am able to create nodes but not links.
I am thinking this is related to the fact GOJS uses a data array as opposed to json.
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
{ angle: 90, layerSpacing: 35 })
});
// the template we defined earlier
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
{ background: "#44CCFF" },
$(go.Picture,
{ margin: 10, width: 50, height: 50, background: "red" },
new go.Binding("source")),
$(go.TextBlock, "Default Text",
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
new go.Binding("text", "name"))
);
var model = $(go.TreeModel);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "/api/Employees/", false);
xmlhttp.send();
var nodeArray = JSON.parse(xmlhttp.responseText);
//model = nodeArray;
myDiagram.model.nodeDataArray = nodeArray;
//myDiagram.model = model;
If you check the console window, you will see this error message:
Error: ParentKey value for node data [object Object] is not a number or a string: null
That is because you set:
"parent": null
in one of your node data objects. I suggest that you remove that property.
I also suggest that you use the go-debug.js library instead of the go.js library, because the Debug version of the library will detect and warn you about more problems than the regular version of the library.
I want to make a default config file according to which I will create my view.
I am thinking of something like:
var Application = {};
Application.Config = {
ViewerModule : {
width : '60%',
height : '60%',
maxWidth : '99%',
minWidth : '1%',
iconSize : '24*24',
defaultColor : 'Green',
selectedColor : 'Orange',
fontColor : 'Black',
viewerToolColor: 'White',
defaultView : 'Fit To Screen',
Labels:{
btnZoomIn :'Zoom In',
btnZoomOut :'Zoom Out',
btnRotateLeft :'Rotate Left',
btnRotateRight:'Rotate Right',
btnFitToScreen:'Fit to Screen',
btnFullScreen :'Full Screen',
btnSaveAs :'Zoom In',
btnExport :'Zoom Out',
btnPopOut :'Rotate Left',
btnEmail :'Rotate Right',
btnPdfConverter:'Fit to Screen',
btnSetting :'Settings'
}
}
}
And so when I create my view in backbone, I can use this config value to define default values of my Backbone View.
One thing I thought was save values from config file to a backbone model and create a view with that model.
However, I am not sure if this is the right thing.
Can share me your thoughts or examples on how I can achieve it.
Have you considered using inheritance to overcome this problem? Instead of a config you could have a BaseView that has the aforementioned properties as view options. This way, these values could be overwritten in the implementation of your child view, or parsed in during construction of the child view.
Here's a crude example:
var BaseView = Backbone.View.extend({
initialize: function() {
this.options = {
'Example': 'Foobar',
'OverrideMe': 'Moo'
};
}
})
, ChildView = BaseView.extend({
initialize: function() {
this.options.Example = 'Something else';
}
})
, impl = new ChildView({'OverrideMe': 'Another thing'});
Here's a fiddle that shows it working.
You could mix in your config object into the prototype of your view with _.defaults if you want to set defaults for your views, with _.extend if you prefer to force the values.
For example,
var Application = {};
Application.Config = {};
Application.Config.ViewerModule = {
width: '60%',
height: '60%'
};
var V = Backbone.View.extend({
width: '50%'
});
_.defaults(V.prototype, Application.Config.ViewerModule);
var v = new V();
console.log(v.width, v.height);
And a demo http://jsfiddle.net/nikoshr/VX7SY/
If I understood you, i suggest You use Model defaults, and here you can see simple example. Or you can use your config like json object, but by the way you must to create empty Model and set config json to model(=new Model)
I am running a weird problem when I try to set Grid Filter list dynamically.
Let me explain by my code snippets
I have a column with filter list is defined as
{
text : 'Client',
dataIndex : 'topAccount',
itemId : 'exTopAccount',
filter: {
type: 'list',
options:[]
}
}
I initialize list from store in 'viewready'
viewready: function(cmp,eOpts){
cmp.getHeaderCt().child('#exTopAccount').initialConfig.filter.options = clientsStore.collect('topAccount');
}
===> WORKS GOOD
Now, I have to build the new client store based on the records when user moves to next page. Therefore I build the store in the 'change' event of paging
listeners: {
'change' :function( toolbar, pageData, eOpts ) {
var store = Ext.StoreManager.get('ExceptionRecords');
clientsStore.removeAll(true);
store.each(function(record){
if(clientsStore.findRecord('topAccount',record.data.topAccount.trim()) == null ) {
clientsStore.add({topAccount: record.data.topAccount.trim()})
}
})
Ext.getCmp('exceptionGridContainer').view.refresh;
Ext.getCmp('exceptionGridContainer').view.getHeaderCt().doLayout;
console.log(clientsStore);
Ext.getCmp('exceptionGridContainer').view.getHeaderCt().child('#exTopAccount').initialConfig.filter.options = clientsStore.collect('topAccount');
}
}
I can now see the new data in clientsStore . But Grid filter list is not updated. still showing old data. I tried refresh,layout etc. Nothing helps
Any help will be appreciated
Thanks
Tharahan
Just changing the value of a property does not affect the component rendered or computed state. The menu is created when the list is first initialized. The first time you do that, it works because that's before the initialization, but the second time, that's too late.
If you can grab a reference to the instantiated ListFilter, I think you could force the recreation of the menu this way:
listFilter.menu = listFilter.createMenu({
options: [ ... ] // new options
// rest of the filter config
});
So, supposing you have a reference to your target grid, you could change the options for the column with dataIndex of "topAccount" by a call similar to this:
var listFilter = grid
.findFeature('filters') // access filters feature of the grid
.get('topAccount'); // access the filter for column
listFilter.menu = listFilter.createMenu({
options: [ ... ] // new options
// rest of the filter config
});
--- Edit ---
OK, complete example. Tested, working.
Ext.widget('grid', {
renderTo: Ext.getBody()
,height: 400
,features: [{
ftype: 'filters'
,local: true
}]
,columns: [{
dataIndex: 'a'
,text: 'Column A'
,filter: {
type: 'list'
,options: ['Foo', 'Bar']
}
},{
dataIndex: 'b'
,text: 'Column B'
},{
dataIndex: 'c'
,text: 'Column C'
}]
,store: {
fields: ['a', 'b', 'c']
,autoLoad: true
,proxy: {
type: 'memory'
,reader: 'array'
,data: [
['Foo', 1, 'Bar']
,['Bar', 2, 'Baz']
,['Baz', 1, 'Bar']
,['Bat', 2, 'Baz']
]
}
}
,tbar: [{
text: 'Change list options'
,handler: function() {
var grid = this.up('grid'),
// forget about getFeature, I read the doc and found something!
filterFeature = grid.filters,
colAFilter = filterFeature.getFilter('a');
// If the filter has never been used, it won't be available
if (!colAFilter) {
// someone commented that this is the way to initialize filter
filterFeature.view.headerCt.getMenu();
colAFilter = filterFeature.getFilter('a');
}
// ok, we've got the ref, now let's try to recreate the menu
colAFilter.menu = colAFilter.createMenu({
options: ['Baz', 'Bat']
});
}
}]
});
I was solving similar problem and answers to this question helped me a lot. Local List filter menu is in fact lazy loaded (only created when clicked) and I needed to set filter menu to be reloaded if the grid store has been reloaded with different data. Solved it by destroying of menu after each reload, so on next click menu is recreated:
var on_load = function() {
var grid_header = me.gridPanel.filters.view.headerCt
if (grid_header.menu) {
grid_header.menu.destroy();
grid_header.menu = null;
}
}
I am trying to connect a dojo 1.7 objectStore or itemFileWriteStore to a grid but I;m not sure what I'm doing wrong.
When I run my code below using the ItemFileWriteStore, I get the grid headers but I dont see my data. When I use ObjectStore, the grid isnt there.
What am I doing wrong?
UPDATE: just noticed that the store.data attribute is empty. Must mean the format of of my "dataBucket" could be wrong?
require(['dojo/on'
,'dojo/ready'
,'dojo/dom'
,"dojo/data/ObjectStore"
,"dojo/store/Memory"
,"dojox/grid/DataGrid"
,"dojo/data/ItemFileWriteStore"
],
function (on,ready,dom,objStore,memStore,grid,itemStore){
ready(function(){
var dataBucket = {//idProperty: 'ID', //for object store?
identifer: 'ID', //for itemStore
items : [
{ID : '100', col2 : 'Ciao Ciao'},
{ID : '200', col2 : 'Hello'}
]};
var stuff = new itemStore({data : dataBucket});
//var stuff = new objStore({store : dataBucket});
//var stuff = new memStore({data : dataBucket});
var layout = [[
{'name':'ID','field' : 'ID','width' : '100px'},
{'name':'Stuff','field' : 'col2','width' : '100px'}
]];
var myGrid = new grid({
id: 'grid',
store: stuff,
structure: layout,
rowSelector: '20px'},
document.createElement('div')
);
dojo.byId("bottomPane").appendChild(myGrid.domNode);
myGrid.startup(); })
})
}
)
turns out the store hadnt been populated with data correctly. It constructed a store without indicating the data passed in was in the incorrect format
I think you may have made a mistake in layout definition. shouldn't second field be col2, like you defined in your dataBucket ?
also you've write:
identifer: 'ID'
and it's
identifier: 'ID'
The dojo/store/Memory go inner to dojo/store/ObjectStore
stuff = new ObjectStore({ objectStore:new Memory({ data: dataBucket }) });
and the store property of the grid
var myGrid = new grid({
id: 'grid',
store: stuff,
structure: layout,
rowSelector: '20px'},
document.createElement('div')
);