How to include custom data into vis.js timeline item - javascript

I have been using vis.js timeline to keep items in a time order.
I use the following to add timeline items :
timeline_items.add({
id : entity_id + uuidv4(),
group : "timeline_video_group_id",
start : start_date,
end : end_date,
content : "<img src='" + element_src_link + "'></img>",
className : 'imagecontainer'
});
However, I cannot add any custom data into this add function.
How may I add custom data, so it may hold information such as entity-uuid=xxxx inside the div below ?
<div class="vis-item vis-range imagecontainer vis-editable" style="transform...">
<div class="vis-item-overflow">
<div class="vis-item-content" style="transform: translateX(0px);">
<img src="image_src">
</div>
<div class="vis-item-visible-frame">
</div>
</div>
</div>

You can update the content to the full HTML you would like, including an image and text, then store this in the DataSet. The vis.js example named 'Custom Styling' here uses this approach.
content: '<div>Mail from boss</div><img src="../resources/img/mail-icon.png" style="width:32px; height:32px;">',
Alternatively you could add custom data to the items in the DataSet, then use the template feature described in the documentation here to construct the HTML. This is the approach I would use.
An example of a template is incorporated into the post below and also at https://jsfiddle.net/xm95u40f/. The example adds a property named imageColor to each item in the DataSet, this is used in combination with the text from the content to display the item. You could store and use your entity-uuid value in a similar way.
// DOM element where the Timeline will be attached
var container = document.getElementById("visualization");
// Create a DataSet (allows two way data-binding)
var items = new vis.DataSet();
items.add([
{ id: 1, content: "item 1", start: "2021-12-21", end: "2021-12-23", imageColor: "0000FF" },
{ id: 2, content: "item 2", start: "2021-12-14", end: "2021-12-17", imageColor: "FFFFFF" },
{ id: 3, content: "item 3", start: "2021-12-18", end: "2021-12-20", imageColor: "0000FF" },
{ id: 4, content: "item 4", start: "2021-12-16", end: "2021-12-21", imageColor: "FFFFFF" },
{ id: 5, content: "item 5", start: "2021-12-25", end: "2021-12-27", imageColor: "000000" },
{ id: 6, content: "item 6", start: "2021-12-27", end: "2021-12-28", imageColor: "008000" },
]);
// Configuration for the Timeline
var options = {
// Define a template function which constructions the HTML for each item
template: function (item, element, data) {
var html = "<img class='timeline-image' src='https://via.placeholder.com/40/" + item.imageColor + "'><div>" + item.content + "</div>"
return html;
},
// Using a template requires any attributes to be whitelisted to prevent XSS
// More details at https://github.com/visjs/vis-timeline/pull/1010
xss: {
disabled: false,
filterOptions: {
whiteList: { img: ['src', 'class'], div: 'class' }
},
},
};
// Create a Timeline
var timeline = new vis.Timeline(container, items, options);
body,
html {
font-family: sans-serif;
}
/*
Timeline image is defined with a fixed height and width.
When the timeline loads it determines the size of items
then uses this to place them, as the images won't be
loaded at this point the size must be set to ensure the
spacing is correct
*/
.timeline-image {
height: 40px;
width: 40px
}
<script src="https://visjs.github.io/vis-timeline/standalone/umd/vis-timeline-graph2d.min.js"></script>
<link href="https://visjs.github.io/vis-timeline/styles/vis-timeline-graph2d.min.css" rel="stylesheet"/>
<div id="visualization"></div>

Related

Fullcalendar.js Resource Timeline, render HTML tags into Resource Titles

I am creating a Resource Timeline with fullcalendar.js to display upcoming shows and would like to add the price under the show title. Here is an example of the necessary part of code:
`resourceLabelText: 'Shows',
resources: [
{ id: '17',
title: 'Test Show',
regularPrice: '$45.45',
salePrice: '$39.99'
},
],`
If possible I want to add html tags like a or around the price for styling. Searching the documentation I haven't found a way to do this. Any help appreciated.
Well I figured this out for anyone who wants to know. Fullcalendar has a function resourceRender. I was able to add the element with appendChild. First I needed to also add my fields to resources with extendedProps.
resourceLabelText: 'Shows',
resources: [
{ id: '17',
title: 'Test Show',
extendedProps: {
regularPrice: '$45.45',
salePrice: '$39.99',
},
},
],
resourceRender: function(info) {
var z = document.createElement('div');
z.innerHTML = info.resource.extendedProps.regularPrice;
info.el.querySelector('.fc-cell-text').appendChild(z);
},
To add HTML tags in the title field, you can use the html property of the event object:
resourceLabelText: 'Shows',
resources: [
{ id: '17',
title: 'Test Show',
regularPrice: '$45.45',
salePrice: '$39.99'
},
],
eventRender: function(event, element) {
element.find('.fc-title').html(event.title + '<br>' + event.regularPrice + ' | ' + event.salePrice + '');
},
This will add the regular and sale prices as links under the show title in the resource timeline. You can customize the HTML tags and their attributes as needed.

Get dinamically table header and dinamically add rows

I need to create a table with dynamically adding rows.
But I need to have a fixed table header that I got dynamically from JSON and table body also generated dynamically.
Here is JSON example
data = [
{
id: 0,
title: "control0",
text: "text 0"
},
{
id: 1,
title: "control1",
text: "text 1"
},
{
id: 2,
title: "control2",
text: "text 2"
},
{
id: 3,
title: "control3",
text: "text 3"
}
]
I try to create method, but I get new column instead of ROW
addRow(index, name) {
this.newDynamic = { id: index, name: name, text: "name" + index };
this.data.push(this.newDynamic);
return true;
}
Here is how now it is looking
But I need like this
When we click on button ADD ROW, I want to add new row but without title (like on picture), but update JSON with new object.
Here is stackblitz for example

Converting Handlebars expressing to lowercase and dashes

I am trying to reuse some of the data in my handlebars template on the front end.
To do this, I need to convert one of my expressions to lowercase, and use dashes instead of space. Is this easily done?
For example, in my JSON file I have the following:
var items = [{
id: '1',
title: "Item Number One",
},
{
id: '2',
title: "Item Number Two",
},
];
And on the Handbars template on the front-end I would like to do this:
<script type="text/x-handlebars" id="items">
<h1>
{{title}}
</h1>
<img src="{{unbound title}}.png" />
</script>
This will output the image page as <img src="Item Number One.png" /> which is no good. So is there an easy way of converting this to lowercase, and remove spaces?
Make a custom Handlebars Helper:
Handlebars.registerHelper("noSpaces", function(input) {
var output = input.toLowerCase();
return output.replace(" ", "");
});
And then call it as:
<img src="{{noSpaces title}}.png" />
You can map your items array and apply the template to that modified array like so:
var items = [
{
id: '1',
title: "Item Number One",
},
{
id: '2',
title: "Item Number Two",
},
];
items = items.map(function(el) {
el.title = el.title.toLowerCase().replace(/\s+/g, '-');
return el;
});
// items = [{id:"1",title:"item-number-one"},{id:"2",title:"item-number-two"}]
If you need to retain the original array just assign the mapped array to a different variable.

Kendo grid drag and drop issue

We are using kendo drag and drop functionality inside the kendo grid table.
1) If the user provide data on any editable fields and without saving the data, if user click/jump to other field for edit. User is loosing his updated data.
2) If the user update any records, we are refresh/regenerate table again Or if we refresh/regenerate outside from the function Or we added new records using outside the function. After that user are not able to drop row to replace with other.
Jsfiddel file
var data = [
{ Id: 1, Name: "data 1", Position: 1 },
{ Id: 2, Name: "data 2", Position: 2 },
{ Id: 3, Name: "data 3", Position: 3 }
];
var dataSource = new kendo.data.DataSource({
data: data,
schema: {
model: {
Id: "Id",
fields: {
Id: { type: "number" },
Name: { type: "string" },
Position: { type: "number" }
}
}
}
});
var grid= $("#grid").kendoGrid({
dataSource: dataSource,
scrollable: false,
editable : true,
toolbar: ["save","cancel", "create"],
columns: ["Id", "Name", "Position"]
}).data("kendoGrid");
grid.table.kendoDraggable({
filter: "tbody > tr:not(.k-grid-edit-row)",
group: "gridGroup",
cursorOffset: { top: 10, left: 10 },
hint: function(e) {
return $('<div class="k-grid k-widget"><table><tbody><tr>' + e.html() + '</tr></tbody></table></div>');
}
});
grid.table/*.find("tbody > tr")*/.kendoDropTarget({
group: "gridGroup",
drop: function (e) {
var target = dataSource.getByUid($(e.draggable.currentTarget).data("uid")),
dest = $(e.target);
if (dest.is("th")) {
return;
}
dest = dataSource.getByUid(dest.parent().data("uid"));
//not on same item
if (target.get("Id") !== dest.get("Id")) {
//reorder the items
var tmp = target.get("Position");
target.set("Position", dest.get("Position"));
dest.set("Position", tmp);
dataSource.sort({ field: "Position", dir: "asc" });
}
}
});
I've run into similar issue some time ago. And also I found the following thread on their forum - http://www.kendoui.com/forums/ui/grid/drag-and-drop-reordering.aspx#boD2qq6aG2OF1P8AAFTdxQ
So if you add one more additional column to the table and put an image there or some other element, then you'll be able to use that element as draggable target like:
grid.table.kendoDraggable({
filter: "tbody > .draggableTarget".....
The table is completely recreated in the DOM in the case when you refresh it, so you have to resubscribe your drag and drop functionality.
I was having similar issues using the newer kendoSortable with an editable grid to achieve drag/drop row sorting.
This fiddle http://jsfiddle.net/UsCFK/273/ works.
It uses a column with a drag handle as mentioned above to prevent cell edits being lost - the other cells are ignored in the setup:
grid.table.kendoSortable({
filter: ">tbody >tr",
hint: $.noop,
cursor: "move",
ignore: "TD, input",
placeholder: function (element) {
return element.clone().addClass("k-state-hover").css("opacity", 0.65);
},
container: '#grid tbody',
change: onGridRowChange
});
It also updates the position field in the datasource, rather than removing, then re-inserting the row as in some other examples - as this will cause a delete request request to the server for each row that is moved - which can cause issues when clicking the batch-editing cancel button. The position field is only shown for demonstration purposes - it should not be exposed for manual editing.

items not within the <ul></ul>

I create a menu with a javascript object and jquery. I have certain items that needs to be in the <ul></ul> but instead they're beneath it.
http://jsfiddle.net/MWBt6/
I have 'Index' for example. In there I want to append a list of items.
I know the category id is 0 and the item id is 2, i stored those things in the data attribute.
Now how can I append a ul to that one?
That's not how append works. You need to create the elements on their own. Here:
var loadPath = "resources/books/book1/";
var menu = {
data: [{
name: "the book",
id: 0,
items: [{
name: "Introduction",
id: 0,
target: "inleiding.html"
}, {
name: "Content",
id: 1
}, {
name: "Index",
id: 2
}]
}, {
name: "my stuff",
id: 1,
items: [{
name: "Notes",
id: 0
}, {
name: "Marks",
id: 1
}]
}, {
name: "other",
id: 2,
items: [{
name: "Search",
id: 0
}, {
name: "Continue Reading",
id: 1
}]
}]
}
$(document).ready(function() {
var $menu = $('#menu');
for(var i = 0; i < menu.data.length; i++) {
var categorie = menu.data[i];
var categorieName = categorie.name;
var categorieId = categorie.id;
var items = categorie.items;
console.log("categorieName: " + categorieName);
var list = $('<ul>');
for(var j = 0; j < items.length; j++) {
var itemId = items[j].id;
list.append($('<li>').attr('data-itemId', itemId).text(items[j].name));
}
$menu.append(
$('<li>').attr('data-categorieId', categorieId).append(categorieName, list)
);
}
});​
Here's the updated jsFiddle.
You are trying to append as if the DOM is a text editor. You can't append the beginning of an element with it's opening tag, then later close that element with an append of a closing tag. Only full valid elements can be inserted into the DOM.
Instead, build an html string, then only make one append after the string is completed. This method is far more efficient than doing multiple appends also
Working demo: http://jsfiddle.net/MWBt6/3/

Categories