How to create a group in fabric.js - html5-canvas

I want to create a group that will contain a combination of Image and Text and will behave as one, however when I do that:
https://gist.github.com/1682293
I can't move that group. To make it work I need to first add image and text to canvas, then create a group with these image and text, and then delete the image and text added separately.
What am I doing wrong there?

This seems to have been fixed in the latest version of fabric.js. I was able to get it to work with version 0.9.15:
function drawImage(name, left, top) {
fabric.Image.fromURL('../nav-host.png', function (img) {
var oImg = img.scale(4);
var caption = new fabric.Text(name, {
fontFamily: 'Arial'
});
var group = new fabric.Group([oImg, caption], { left: left, top: top });
canvas.add(group);
});
}

I came up this to add part of the text being generated dynamically from a counter script.
This code will add a group made from an image and text. The text is set to be above the image and it updates itself with every click of the button as it adds them to your canvas. So when you click the button the first time the text will say Sticky Card #1. The next click will give you your second group with the text saying Sticky card #2. The image was only 30px X 30px.
This is the counter script in the head of my page.
$(window).load(function(){
$('.stickycard').click(function() {
$('#cardcount').html(function(i, val) { return val*1+1; });
});
});
This is my fabric.js code that I used inside the kitchensink.js.
if ($(element).hasClass('image1')) {
fabric.Image.fromURL('toolimg/yellow-stickycard.png', function(img) {
var yellcard = img.scale(1.0).set({ left: 22, top: 15 });
var cardcount = $('#cardcount').text();
var sticky = new fabric.Text('Sticky Card #'+ (cardcount), {
fontSize: 12,
cornerSize: 6
});
var group = new fabric.Group([ sticky, yellcard ], {
left: 150,
top: 100,
cornerSize: 6
});
group.set({
left: left,
top: top,
});
canvas.add(group);
});
}
This is my HTML for the button and the div that shows the count.
<button type="button" class="btn image1 stickycard" id="yellstickycard"><img src="toolimg/yellow-stickycard.png" /></button>
<div id="cardcount">0</div>

Related

How to Show 30 days in Day View with Horizontal Scrollbar in Dhtmlx Scheduler?

I want to show 30 days in Day View Scheduler with Horizontal Scrollbar. Currently, Horizontal Scrollbar is available only for Timeline View but I want it for Day View as well as Month View.
For Timeline View with Horizontal Scrollbar code:
scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24*7,
x_start: 16,
x_length: 48,
y_unit: sections,
y_property: "section_id",
render: "bar",
scrollable: true,
column_width: 70,
scroll_position:new Date(2018, 0, 15) });
Please share your ideas and Sample links
Thanks in Advance
Try using Custom View. You can remove the default Day view and display your own instead, with the number of days you want to display. This can be done like this:
First in scheduler.config.header set tab "thirty_days" instead of "day":
scheduler.config.header = [
"thirty_days",
"week",
"month",
"date",
"prev",
"today",
"next"
];
The label for the view is set as in:
scheduler.locale.labels.thirty_days_tab = "Days";
Next, set the start date of the viewing interval, as well as viewing templates. It's better to create the custom view in the onTemplatesReady event handler function so that your custom view templates are ready before the scheduler is initialized:
scheduler.attachEvent("onTemplatesReady", () => {
scheduler.date.thirty_days_start = function(date) {
const ndate = new Date(date.valueOf());
ndate.setDate(Math.floor(date.getDate()/10)*10+1);
return this.date_part(ndate);
}
scheduler.date.add_thirty_days = function(date,inc) {
return scheduler.date.add(date,inc*30,"day");
}
const format = scheduler.date.date_to_str(scheduler.config.month_day);
scheduler.templates.thirty_days_date = scheduler.templates.week_date;
scheduler.templates.thirty_days_scale_date = function(date) {
return format(date);
};
});
To add horizontal scrolling to the view, you can place the scheduler inside the scrollable element and give the scheduler the width required to display all columns. You'll need to hide a default navigation panel of the scheduler and create a custom one with HTML, so it would have a correct width and won't be affected by scrolling:
scheduler.xy.nav_height = 0;
scheduler.attachEvent("onSchedulerReady", function () {
const navBar = scheduler.$container.querySelector(".dhx_cal_navline").cloneNode(true);
navBar.style.width = "100%";
document.querySelector(".custom-scheduler-header").appendChild(navBar);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function (tab) {
tab.onclick = function () {
const name = tab.getAttribute("name");
const view = name.substr(0, name.length - 4);
scheduler.setCurrentView(null, view);
};
});
document.querySelector(".custom-scheduler-header .dhx_cal_prev_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, -1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_next_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, 1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_today_button").onclick = function () {
scheduler.setCurrentView(new Date());
};
scheduler.attachEvent("onBeforeViewChange", (oldView, oldDate, newView, newDate) => {
const innerContainer = document.getElementById("scheduler_here");
if (newView === "thirty_days") {
innerContainer.style.width = "3000px";
} else {
innerContainer.style.width = "100%";
}
return true;
});
scheduler.attachEvent("onViewChange", function (view, date) {
const dateLabel = document.querySelector(".custom-scheduler-header .dhx_cal_date");
const state = scheduler.getState();
dateLabel.innerHTML = scheduler.templates[view + "_date"](state.min_date, state.max_date);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function(tab) {
tab.classList.remove("active");
});
const activeTab = document.querySelector(".custom-scheduler-header ." + view + "_tab");
if (activeTab) {
activeTab.classList.add("active");
}
});
});
Styles that you will need:
.custom-scheduler-header .dhx_cal_navline{
display: block !important;
height: 60px !important;
}
.custom-scheduler-header .dhx_cal_navline.dhx_cal_navline_flex{
display: flex !important;
}
.dhx-scheduler {
height: 100vh;
width: 100vw;
position: relative;
overflow: hidden;
background-color: #fff;
font-family: Roboto, Arial;
font-size: 14px;
}
.dhx_cal_container .dhx_cal_navline {
display: none;
}
Please see an example: https://snippet.dhtmlx.com/znd7ffiv
You may need to fix the hour scale so that it remains visible when scrolling horizontally on the calendar. I did not implement this in the example, I think that this can be done in the same way as for the navigation panel. If you need, write to me and I will send an update in a few working days.
As for the "Month" view, the approach is the same as for the "Day" view.

OpenLayers 6 DragZoom Control - how to change condition

in OL 6 I would like to use a button, so a user can click to activate a change for the drag zoom control
so it will be available without holding down shift.
In https://openlayers.org/en/latest/apidoc/module-ol_interaction_DragZoom-DragZoom.html it lists the option 'condition' to handles this.
I could not figure out how to change and set that condition. Any examples how to do this?
Here my example, hope be usefull.
You can change the style with CSS or in your JS.
HTML code:
<style>
.ol-dragzoom {
border-color: red !important;
}
</style>
<div id="map"></div>
<div id="tool-zoom" class="shadow-sm">
<a id="tool-lupa" class="text-secondary">
<i class="icono-arg-lupa"></i>
</a>
</div>
And the JS code:
var aplica_lupa = function(e) {
const dragZoom = new ol.interaction.DragZoom({
condition : ol.events.condition.always,
})
map.addInteraction(dragZoom);
};
$("#tool-lupa").on("click",function() {
aplica_lupa();
})
If you are importing OL methods, avoid the "ol.interaction...".
And if you want to change the DragZoom style in your JS, try something like this:
const dragZoom = new ol.interaction.DragZoom({
condition : ol.events.condition.always,
style : new ol.style.Style({
fill : new ol.style.Fill({
color : 'rgba(255, 255, 255, 0.6)'
}),
stroke : new ol.style.Stroke({
color : '#CD4D64',
width : 3
})
})
});
And other option, with onclick remove interaction:
const dragZoom = new ol.interaction.DragZoom({
condition : ol.events.condition.always,
})
var aplica_lupa = function(e) {
map.addInteraction(dragZoom);
};
var remueve_lupa = function(e) {
map.removeInteraction(dragZoom);
};
$('#tool-lupa').bind('click', myHandlerFunction);
var first = true;
function myHandlerFunction(e) {
if(first){
document.body.style.cursor="all-scroll";
aplica_lupa();
}else{
document.body.style.cursor="default";
remueve_lupa();
}
first = !first;
}

Can labels be hidden by default, but shown when the node is selected?

I want my graph has no label by default, but when I select a node its label will show up. There is chosen.label that seems promising, but I still don't know how to write the function. There is also a question about scaling.label, but as indicated in there it also seems not working.
Another approach is to have a checkbox to turn on and off the labels. See: Can the filter in the configure option specify an only option?
This can be achieved using the chosen.label option in combination with the transparent font color.
In the options object firstly set the default font color for nodes to transparent, then within chosen.label adjust it to a visible color.
var options = {
nodes: {
font: {
// Set default label font color to transparent
color: "transparent"
},
chosen: {
label: function(values, id, selected, hovering) {
// Adjust label font color so it is visible
// Updates to the values object are applied to the network
values.color = "#343434";
}
}
}
};
Working example is below.
// create an array with nodes
var nodes = new vis.DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" }
]);
// create an array with edges
var edges = new vis.DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 3, to: 3 },
]);
// create a network
var container = document.getElementById("mynetwork");
var treeData = {
nodes: nodes,
edges: edges,
};
var options = {
nodes: {
font: {
// Set default label font color to transparent
color: "transparent"
},
chosen: {
label: function(values, id, selected, hovering) {
// Adjust label font color so it is visible
// Updates to the values object are applied to the network
values.color = "#343434";
}
}
}
};
var network = new vis.Network(container, treeData, options);
#mynetwork {
width: 600px;
height: 180px;
border: 1px solid lightgray;
}
<script src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
<div id="mynetwork"></div>

c3.js - hide tooltip for specific data sets

I have a c3.js chart which has 4 datasets. Is it possible to set the tooltop only to display for 1 set of data?
From the code below I only want the tooltip to display for data4.
var chart = c3.generate({
bindto: '#chart3',
data: {
//x: 'x1',
xFormat: '%d/%m/%Y %H:%M', // how the date is parsed
xs: {
'data1': 'x1',
'data2': 'x2',
'data3': 'x3',
'data4': 'x4'
},
columns: [
x1data,
y1data,
x2data,
y2data,
x3data,
y3data,
x4data,
y4data,
],
types: {
data1: 'area',
},
},
legend: {
show: false
}
});
There is the tooltip option for show:false but that disables them all.
Can it display for just 1 dataset?
The tooltip.position() function can be used to control the position of the tooltip, and we can set the tooltip position way off the canvas as a quick hack to hide it when we do not want to see it. However, I do not know how to return the default which is not documented - maybe someone else can elaborate on that.
tooltip: {
grouped: false,
position: (data, width, height, element) => {
if (data[0].id === 'data2'){ // <- change this value to suit your needs
return { top: 40, left: 0 };
}
return { top: -1000, left: 0 };
}
}
EDIT: After digging around for a solution I found that Billboard.js (a fork of C3.js on github) provides a tooltip.onshow() function that the API docs say is 'a callback that will be invoked before the tooltip is shown'. So it would appear that Billboard.js already has the a potential solution where you could intercept the data and hide the tooltip.

How to get cursor coordinates in CKEditor

I want to know the coordinates of the mouse pointer when I r-click on CKEditor
I added a few items to the context menu of CKEditor.
i want when I select a certain item, the other a notice appeared also in place i r_click
$(document).ready(function () {
var ck = CKEDITOR.replace('txtNoidungBR', 'vi');
var $DK = $('#divAddDK');
/*Thêm điều kiện*/
ck.on('instanceReady', function (e) {
ck.addCommand("addDK", {
exec: function (ck) {
/*I want to set coordinates to $DK = coordinates of context menu when i r-click*/
$DK.css({ 'left': 600, 'top': 400 }).toggle(300);
}
});
ck.addMenuGroup('BRDT');
var addDK = {
label: 'Thêm điều kiện',
command: 'addDK',
group: 'BRDT'
};
ck.contextMenu.addListener(function (element, selection) {
return {
addDK: CKEDITOR.TRISTATE_OFF
};
});
ck.addMenuItems({
addDK: {
label: 'Thêm điều kiện',
command: 'addDK',
group: 'BRDT',
order: 1
}
});
});
});
help me. thaks
You'll need to track the mouse yourself, as ckeditor doesn't give you the mouse event.
See this answer for details on that:
How to get the mouse position without events (without moving the mouse)?

Resources