Skip to content

Commit 6411753

Browse files
committed
Update version to 4.7. Improve code formatting in arrow.js and fix bug in example
1 parent fa1db97 commit 6411753

File tree

3 files changed

+163
-143
lines changed

3 files changed

+163
-143
lines changed

arrow.js

Lines changed: 79 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*
55
* Class to easily draw lines to connect items in the vis Timeline module.
66
*
7-
* @version 4.6.0
8-
* @date 2024-03-24
7+
* @version 4.7.1
8+
* @date 2025-09-19
99
*
1010
* @copyright (c) Javi Domenech (javdome@gmail.com)
1111
*
@@ -83,7 +83,7 @@ export default class Arrow {
8383

8484
/** @private @type {Map<string, string>} map of color to marker id */
8585
this._colorMarkers = new Map();
86-
86+
8787
this._dependency = [...dependencies];
8888

8989
/** @private @type {SVGPathElement[]} */
@@ -94,7 +94,7 @@ export default class Arrow {
9494

9595
this._initialize();
9696
}
97-
97+
9898
_initialize() {
9999
//Configures the SVG layer and add it to timeline
100100
this._svg.style.position = "absolute";
@@ -110,7 +110,7 @@ export default class Arrow {
110110
for (let i = 0; i < this._dependency.length; i++) {
111111
this._createPath(this._dependency[i].color, this._dependency[i].line);
112112
}
113-
113+
114114
//NOTE: We hijack the on "changed" event to draw the arrows.
115115
this._timeline.on("changed", () => {
116116
this._drawDependencies();
@@ -121,10 +121,10 @@ export default class Arrow {
121121
/** @private */
122122
_getOrCreateMarker(color) {
123123
const arrowColor = color || this._arrowsColor;
124-
124+
125125
if (!this._colorMarkers.has(arrowColor)) {
126126
const markerId = `arrowhead-${arrowColor.replace('#', '')}-${Math.random().toString(36).substring(2)}`;
127-
127+
128128
const arrowHead = document.createElementNS("http://www.w3.org/2000/svg", "marker");
129129
arrowHead.setAttribute("id", markerId);
130130
arrowHead.setAttribute("viewBox", "-10 -5 10 10");
@@ -134,56 +134,56 @@ export default class Arrow {
134134
arrowHead.setAttribute("markerWidth", "3");
135135
arrowHead.setAttribute("markerHeight", "3");
136136
arrowHead.setAttribute("orient", "auto-start-reverse");
137-
137+
138138
const arrowHeadPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
139139
arrowHeadPath.setAttribute("d", "M 0 0 L -10 -5 L -7.5 0 L -10 5 z");
140140
arrowHeadPath.style.fill = arrowColor;
141-
141+
142142
arrowHead.appendChild(arrowHeadPath);
143143
this._svg.appendChild(arrowHead);
144-
144+
145145
this._colorMarkers.set(arrowColor, markerId);
146146
}
147-
147+
148148
return this._colorMarkers.get(arrowColor);
149149
}
150-
150+
151151
/** @private */
152-
_createPath(color, lineType){
152+
_createPath(color, lineType) {
153153
//Add a new path to array dependencyPath and to svg
154154
let somePath = document.createElementNS(
155155
"http://www.w3.org/2000/svg",
156156
"path"
157-
);
158-
somePath.setAttribute("d", "M 0 0");
159-
somePath.style.stroke = color || this._arrowsColor;
160-
somePath.style.strokeWidth = this._arrowsStrokeWidth + "px";
161-
somePath.style.fill = "none";
162-
somePath.style.pointerEvents = "auto";
163-
164-
// Устанавливаем тип линии
165-
const line = lineType !== undefined ? lineType : 0; // По умолчанию сплошная линия
166-
if (line === 0) {
167-
// Тип 0: Сплошная линия (по умолчанию)
168-
somePath.style.strokeDasharray = "none";
169-
} else if (line === 1) {
170-
// Тип 1: Пунктирная линия
171-
somePath.style.strokeDasharray = "7,5";
172-
}
173-
// Здесь можно добавить дополнительные типы линий:
174-
// } else if (line === 2) {
175-
// // Тип 2: Точечная линия
176-
// somePath.style.strokeDasharray = "2,3";
177-
// } else if (line === 3) {
178-
// // Тип 3: Штрих-пунктир
179-
// somePath.style.strokeDasharray = "10,5,2,5";
180-
// }
181-
182-
this._dependencyPath.push(somePath);
183-
this._svg.appendChild(somePath);
157+
);
158+
somePath.setAttribute("d", "M 0 0");
159+
somePath.style.stroke = color || this._arrowsColor;
160+
somePath.style.strokeWidth = this._arrowsStrokeWidth + "px";
161+
somePath.style.fill = "none";
162+
somePath.style.pointerEvents = "auto";
163+
164+
// Set line type
165+
const line = lineType !== undefined ? lineType : 0; // Default: solid line
166+
if (line === 0) {
167+
// Type 0: Solid line (default)
168+
somePath.style.strokeDasharray = "none";
169+
} else if (line === 1) {
170+
// Type 1: Dashed line
171+
somePath.style.strokeDasharray = "7,5";
172+
}
173+
// Here you can add additional line types:
174+
// } else if (line === 2) {
175+
// // Type 2: Dotted line
176+
// somePath.style.strokeDasharray = "2,3";
177+
// } else if (line === 3) {
178+
// // Type 3: Dash-dot line
179+
// somePath.style.strokeDasharray = "10,5,2,5";
180+
// }
181+
182+
this._dependencyPath.push(somePath);
183+
this._svg.appendChild(somePath);
184184
}
185185

186-
186+
187187
/** @private */
188188
_drawDependencies() {
189189
//Create paths for the started dependency array
@@ -202,40 +202,40 @@ export default class Arrow {
202202
//if( (typeof this._timeline.itemsData._data[dep.id_item_1] !== "undefined") && (typeof this._timeline.itemsData._data[dep.id_item_2] !== "undefined") ) {
203203

204204
const bothItemsExist = (this._timeline.itemsData.get(dep.id_item_1) !== null) && (this._timeline.itemsData.get(dep.id_item_2) !== null);
205-
205+
206206
//Checks if at least one item is visible in screen
207-
let oneItemVisible = false; //Iniciamos a false
207+
let oneItemVisible = false; //Initialize as false
208208
//Checks if the groups of items are both visible
209-
let groupOf_1_isVisible = false; //Iniciamos a false
210-
let groupOf_2_isVisible = false; //Iniciamos a false
211-
if (bothItemsExist) {
209+
let groupOf_1_isVisible = false; //Initialize as false
210+
let groupOf_2_isVisible = false; //Initialize as false
211+
if (bothItemsExist) {
212212
const visibleItems = this._timeline.getVisibleItems();
213-
for (let k = 0; k < visibleItems.length ; k++) {
213+
for (let k = 0; k < visibleItems.length; k++) {
214214
if (dep.id_item_1 == visibleItems[k]) oneItemVisible = true;
215215
if (dep.id_item_2 == visibleItems[k]) oneItemVisible = true;
216216
}
217-
218-
219-
217+
218+
219+
220220
let groupOf_1 = this._timeline.itemsData.get(dep.id_item_1).group; //let groupOf_1 = items.get(dep.id_item_1).group;
221-
221+
222222
let groupOf_2 = this._timeline.itemsData.get(dep.id_item_2).group; //let groupOf_2 = items.get(dep.id_item_2).group;
223-
224-
if ( this._timeline.groupsData.get(groupOf_1) ) groupOf_1_isVisible = true;
225223

226-
if ( this._timeline.groupsData.get(groupOf_2) ) groupOf_2_isVisible = true;
224+
if (this._timeline.groupsData.get(groupOf_1)) groupOf_1_isVisible = true;
225+
226+
if (this._timeline.groupsData.get(groupOf_2)) groupOf_2_isVisible = true;
227227

228228

229229
// If groups are null then they are not visible.
230-
if (groupOf_1 == null){
230+
if (groupOf_1 == null) {
231231
groupOf_1_isVisible = false;
232232
}
233-
if (groupOf_2 == null){
233+
if (groupOf_2 == null) {
234234
groupOf_2_isVisible = false;
235235
}
236236
}
237237

238-
if ( (groupOf_1_isVisible && groupOf_2_isVisible) && (oneItemVisible || !this._hideWhenItemsNotVisible) && (bothItemsExist)) {
238+
if ((groupOf_1_isVisible && groupOf_2_isVisible) && (oneItemVisible || !this._hideWhenItemsNotVisible) && (bothItemsExist)) {
239239
var item_1 = this._getItemPos(this._timeline.itemSet.items[dep.id_item_1]);
240240
var item_2 = this._getItemPos(this._timeline.itemSet.items[dep.id_item_2]);
241241

@@ -246,18 +246,18 @@ export default class Arrow {
246246
var curveLen = item_1.height * 2; // Length of straight Bezier segment out of the item.
247247

248248
const markerId = this._getOrCreateMarker(dep.color);
249-
const direction = dep.direction !== undefined ? dep.direction : 1; // По умолчанию направление вперед
249+
const direction = dep.direction !== undefined ? dep.direction : 1; // Default: forward direction
250250

251-
// Определяем какие маркеры нужно установить в зависимости от direction
251+
// Determine which markers to set depending on direction
252252
let markerStart = "";
253253
let markerEnd = "";
254-
254+
255255
if (direction === 0) {
256-
// Без стрелок
256+
// No arrows
257257
markerStart = "";
258258
markerEnd = "";
259259
} else if (direction === 1) {
260-
// Направление вперед (по умолчанию)
260+
// Forward direction (default)
261261
if (this._followRelationships && item_2.mid_x < item_1.mid_x) {
262262
markerStart = `url(#${markerId})`;
263263
markerEnd = "";
@@ -266,7 +266,7 @@ export default class Arrow {
266266
markerEnd = `url(#${markerId})`;
267267
}
268268
} else if (direction === 2) {
269-
// Направление назад
269+
// Backward direction
270270
if (this._followRelationships && item_2.mid_x < item_1.mid_x) {
271271
markerStart = "";
272272
markerEnd = `url(#${markerId})`;
@@ -275,16 +275,16 @@ export default class Arrow {
275275
markerEnd = "";
276276
}
277277
} else if (direction === 3) {
278-
// Обе стороны
278+
// Both sides
279279
markerStart = `url(#${markerId})`;
280280
markerEnd = `url(#${markerId})`;
281281
}
282282

283283
if (this._followRelationships && item_2.mid_x < item_1.mid_x) {
284-
// Добавляем отступы только там, где есть стрелки
284+
// Add spacing only where there are arrows
285285
if (markerStart !== "") item_2.right += 10; // Space for the arrowhead at start
286286
if (markerEnd !== "") item_1.left -= 10; // Space for the arrowhead at end
287-
287+
288288
this._dependencyPath[index].setAttribute("marker-start", markerStart);
289289
this._dependencyPath[index].setAttribute("marker-end", markerEnd);
290290
this._dependencyPath[index].setAttribute(
@@ -307,10 +307,10 @@ export default class Arrow {
307307
item_1.mid_y
308308
);
309309
} else {
310-
// Добавляем отступы только там, где есть стрелки
310+
// Add spacing only where there are arrows
311311
if (markerEnd !== "") item_2.left -= 10; // Space for the arrowhead at end
312312
if (markerStart !== "") item_1.right += 10; // Space for the arrowhead at start
313-
313+
314314
this._dependencyPath[index].setAttribute("marker-end", markerEnd);
315315
this._dependencyPath[index].setAttribute("marker-start", markerStart);
316316
this._dependencyPath[index].setAttribute(
@@ -347,8 +347,8 @@ export default class Arrow {
347347

348348
}
349349

350-
/** @private Función que recibe in Item y devuelve la posición en pantalla del item. */
351-
_getItemPos (item) {
350+
/** @private Function that receives an Item and returns its screen position */
351+
_getItemPos(item) {
352352
let left_x = item.left;
353353
let top_y;
354354
if (this._timeline.options.orientation.item == "top") {
@@ -397,13 +397,13 @@ export default class Arrow {
397397
getIdArrows() {
398398
return this._dependency.map(dep => dep.id);
399399
}
400-
400+
401401
/**
402402
* Finds arrow with the given id and removes it.
403-
* Función que recibe el id de una flecha y la elimina.
403+
* Function that receives an arrow id and removes it.
404404
* @param {ArrowIdType} id arrow id
405405
*/
406-
removeArrow(id) {
406+
removeArrow(id) {
407407
const index = this._dependency.findIndex(dep => dep.id === id);
408408

409409
if (index >= 0) {
@@ -423,18 +423,18 @@ export default class Arrow {
423423

424424
/**
425425
* Finds all arrows related to one view item and removes them all.
426-
* Función que recibe el id de un item y elimina la flecha.
426+
* Function that receives an item id and removes the arrow.
427427
* @param {VisIdType} id view item id
428428
* @returns {(ArrowIdType)[]} list of removed arrow ids
429429
*/
430430
removeItemArrows(id) {
431431
let listOfRemovedArrows = [];
432432
for (let i = 0; i < this._dependency.length; i++) {
433-
if ( (this._dependency[i].id_item_1 == id) || (this._dependency[i].id_item_2 == id) ) {
433+
if ((this._dependency[i].id_item_1 == id) || (this._dependency[i].id_item_2 == id)) {
434434
listOfRemovedArrows.push(this._dependency[i].id);
435435
this.removeArrow(this._dependency[i].id);
436436
i--;
437-
}
437+
}
438438
}
439439
return listOfRemovedArrows;
440440
}
@@ -447,14 +447,14 @@ export default class Arrow {
447447
*/
448448
removeArrowsBetweenItems(itemId1, itemId2) {
449449
let listOfRemovedArrows = [];
450-
let ArrowsToDelete = this._dependency.filter(dep => (dep.id_item_1 == itemId1 && dep.id_item_2 == itemId2) )
450+
let ArrowsToDelete = this._dependency.filter(dep => (dep.id_item_1 == itemId1 && dep.id_item_2 == itemId2))
451451
ArrowsToDelete.forEach(dep => {
452452
listOfRemovedArrows.push(dep.id);
453453
this.removeArrow(dep.id)
454454
})
455455
return listOfRemovedArrows
456456
}
457-
457+
458458

459459
/**
460460
* For backward compatibility
@@ -464,4 +464,4 @@ export default class Arrow {
464464
this.removeItemArrows(id);
465465
}
466466

467-
}
467+
}

0 commit comments

Comments
 (0)