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