2424 * timeline-arrows may be distributed under either license.
2525 */
2626
27+ // @ts -check
28+
29+ /**
30+ * @typedef {(number | string) } VisIdType Timeline view item id. Equivalent to vis.IdType.
31+ */
32+
33+ /**
34+ * @typedef {(number | string) } ArrowIdType arrow id.
35+ */
36+
37+ /**
38+ * @typedef ArrowSpec Arrow specification
39+ * @property {ArrowIdType } id arrow id
40+ * @property {VisIdType } id_item_1 start timeline item id
41+ * @property {VisIdType } id_item_2 end timeline item id
42+ * @property {string } [title] optional arrow title
43+ */
44+
45+ /**
46+ * @typedef ArrowOptions Arrow configuration options
47+ * @property {boolean } [followRelationships] if true, arrows can point backwards and will follow the relationships set in the data
48+ * @property {(el: SVGPathElement, title: string) => string } [tooltipConfig] if arrows have a `title` property, the default behavior will add a title attribute that shows on hover. However, you might not want to use the title attribute, but instead your own tooltip configuration.
49+ This method takes two arguments, `el` - the arrow - and `title` - the content of the `title` property set in the arrow data.
50+ * @property {string } [color] arrow color
51+ * @property {number } [strokeWidth] arrow thickness in pixels
52+ */
53+
54+ /** Arrow set for a vis.js Timeline. */
2755export default class Arrow {
2856
57+ /**
58+ * Creates arrows.
59+ * @param {* } timeline timeline object
60+ * @param {ArrowSpec[] } dependencies arrows
61+ * @param {ArrowOptions } [options]
62+ */
2963 constructor ( timeline , dependencies , options ) {
3064 this . _svg = document . createElementNS ( "http://www.w3.org/2000/svg" , "svg" ) ;
3165 this . _timeline = timeline ;
3266
67+ /** @private @type {boolean | undefined } if true, arrows can point backwards and will follow the relationships set in the data */
3368 this . _followRelationships = options ?. followRelationships ;
69+ /** @private @type {((el: SVGPathElement, title: string) => string) | undefined } */
3470 this . _tooltipConfig = options ?. tooltipConfig ;
3571
72+ /** @private @type {string } color */
3673 this . _arrowsColor = options ?. color ? options . color : "#9c0000"
74+ /** @private @type {number } arrow thickness in pixels */
75+ this . _arrowsStrokeWidth = options ?. strokeWidth ?? 3 ;
3776
77+ /** @private @type {SVGMarkerElement } */
3878 this . _arrowHead = document . createElementNS (
3979 "http://www.w3.org/2000/svg" ,
4080 "marker"
4181 ) ;
82+ /** @private @type {SVGPathElement } */
4283 this . _arrowHeadPath = document . createElementNS (
4384 "http://www.w3.org/2000/svg" ,
4485 "path"
4586 ) ;
4687
4788 this . _dependency = dependencies ;
4889
90+ /** @private @type {SVGPathElement[] } */
4991 this . _dependencyPath = [ ] ;
5092
5193 this . _initialize ( ) ;
@@ -88,6 +130,7 @@ export default class Arrow {
88130
89131 }
90132
133+ /** @private */
91134 _createPath ( ) {
92135 //Add a new path to array dependencyPath and to svg
93136 let somePath = document . createElementNS (
@@ -96,36 +139,37 @@ export default class Arrow {
96139 ) ;
97140 somePath . setAttribute ( "d" , "M 0 0" ) ;
98141 somePath . style . stroke = this . _arrowsColor ;
99- somePath . style . strokeWidth = "3px ";
142+ somePath . style . strokeWidth = this . _arrowsStrokeWidth + "px ";
100143 somePath . style . fill = "none" ;
101144 somePath . style . pointerEvents = "auto" ;
102145 this . _dependencyPath . push ( somePath ) ;
103146 this . _svg . appendChild ( somePath ) ;
104147 }
105148
106149
107-
150+ /** @private */
108151 _drawDependencies ( ) {
109152 //Create paths for the started dependency array
110153 for ( let i = 0 ; i < this . _dependency . length ; i ++ ) {
111154 this . _drawArrows ( this . _dependency [ i ] , i ) ;
112155 }
113156 }
114157
158+ /**
159+ * @private
160+ * @param {ArrowSpec } dep arrow specification
161+ * @param {number } index arrow index
162+ */
115163 _drawArrows ( dep , index ) {
116164 //Checks if both items exist
117165 //if( (typeof this._timeline.itemsData._data[dep.id_item_1] !== "undefined") && (typeof this._timeline.itemsData._data[dep.id_item_2] !== "undefined") ) {
118166 //debugger;
119- if ( ( this . _timeline . itemsData . get ( dep . id_item_1 ) !== null ) && ( this . _timeline . itemsData . get ( dep . id_item_2 ) !== null ) ) {
120- var bothItemsExist = true ;
121- } else {
122- var bothItemsExist = false ;
123- }
167+ const bothItemsExist = ( this . _timeline . itemsData . get ( dep . id_item_1 ) !== null ) && ( this . _timeline . itemsData . get ( dep . id_item_2 ) !== null ) ;
124168
125169 //Checks if at least one item is visible in screen
126- var oneItemVisible = false ; //Iniciamos a false
170+ let oneItemVisible = false ; //Iniciamos a false
127171 if ( bothItemsExist ) {
128- var visibleItems = this . _timeline . getVisibleItems ( ) ;
172+ const visibleItems = this . _timeline . getVisibleItems ( ) ;
129173 for ( let k = 0 ; k < visibleItems . length ; k ++ ) {
130174 if ( dep . id_item_1 == visibleItems [ k ] ) oneItemVisible = true ;
131175 if ( dep . id_item_2 == visibleItems [ k ] ) oneItemVisible = true ;
@@ -214,7 +258,7 @@ export default class Arrow {
214258 // Adding the title if property title has been added in the dependency
215259 if ( dep . hasOwnProperty ( "title" ) ) {
216260 this . _tooltipConfig
217- ? this . _tooltipConfig ( this . _dependencyPath [ index ] , dep . title )
261+ ? this . _tooltipConfig ( this . _dependencyPath [ index ] , dep . title ?? '' )
218262 : this . _dependencyPath [ index ] . innerHTML = "<title>" + dep . title + "</title>" ;
219263 }
220264 } else {
@@ -224,7 +268,7 @@ export default class Arrow {
224268
225269 }
226270
227- // Función que recibe in Item y devuelve la posición en pantalla del item.
271+ /** @private Función que recibe in Item y devuelve la posición en pantalla del item. */
228272 _getItemPos ( item ) {
229273 let left_x = item . left ;
230274 let top_y = item . parent . top + item . parent . height - item . top - item . height ;
@@ -241,38 +285,52 @@ export default class Arrow {
241285 }
242286
243287
244- addArrow ( dep ) {
288+ /**
289+ * Adds arrow between two timeline items.
290+ * @param {ArrowSpec } dep item dependency
291+ */
292+ addArrow ( dep ) {
245293 this . _dependency . push ( dep ) ;
246294 this . _createPath ( ) ;
247295 this . _timeline . redraw ( ) ;
248296 }
249297
250- getArrow ( id ) {
251- for ( let i = 0 ; i < this . _dependency . length ; i ++ ) {
252- if ( this . _dependency [ i ] . id == id ) {
253- return this . _dependency [ i ] ;
254- }
255- }
256- return null ;
298+ /**
299+ * Get arrow by ID.
300+ * @param { ArrowIdType } id arrow ID
301+ * @returns { ArrowSpec | null } arrow spec, or null
302+ */
303+ getArrow ( id ) {
304+ return this . _dependency . find ( dep => dep . id === id ) ?? null ;
257305 }
258306
259- //Función que recibe el id de una flecha y la elimina.
307+ /**
308+ * Finds arrow with the given id and removes it.
309+ * Función que recibe el id de una flecha y la elimina.
310+ * @param {ArrowIdType } id arrow id
311+ */
260312 removeArrow ( id ) {
261- for ( let i = 0 ; i < this . _dependency . length ; i ++ ) {
262- if ( this . _dependency [ i ] . id == id ) var index = i ;
263- }
313+ const index = this . _dependency . findIndex ( dep => dep . id === id ) ;
264314
265- //var list = document.getElementsByTagName("path"); //FALTA QUE ESTA SELECCION LA HAGA PARA EL DOM DEL TIMELINE INSTANCIADO!!!!
266- var list = document . querySelectorAll ( "#" + this . _timeline . dom . container . id + " path" ) ;
315+ if ( index >= 0 ) {
267316
268- this . _dependency . splice ( index , 1 ) ; //Elimino del array dependency
269- this . _dependencyPath . splice ( index , 1 ) ; //Elimino del array dependencyPath
317+ //var list = document.getElementsByTagName("path"); //FALTA QUE ESTA SELECCION LA HAGA PARA EL DOM DEL TIMELINE INSTANCIADO!!!!
318+ const list = document . querySelectorAll ( "#" + this . _timeline . dom . container . id + " path" ) ;
319+
320+ this . _dependency . splice ( index , 1 ) ; //Elimino del array dependency
321+ this . _dependencyPath . splice ( index , 1 ) ; //Elimino del array dependencyPath
270322
271- list [ index + 1 ] . parentNode . removeChild ( list [ index + 1 ] ) ; //Lo elimino del dom
323+ list [ index + 1 ] . parentNode . removeChild ( list [ index + 1 ] ) ; //Lo elimino del dom
324+ }
272325 }
273326
274- //Función que recibe el id de un item y elimina la flecha.
275- removeArrowbyItemId ( id ) {
327+ /**
328+ * Finds all arrows related to one view item and removes them all.
329+ * Función que recibe el id de un item y elimina la flecha.
330+ * @param {VisIdType } id view item id
331+ * @returns {(ArrowIdType)[] } list of removed arrow ids
332+ */
333+ removeItemArrows ( id ) {
276334 let listOfRemovedArrows = [ ] ;
277335 for ( let i = 0 ; i < this . _dependency . length ; i ++ ) {
278336 if ( ( this . _dependency [ i ] . id_item_1 == id ) || ( this . _dependency [ i ] . id_item_2 == id ) ) {
@@ -284,6 +342,12 @@ export default class Arrow {
284342 return listOfRemovedArrows ;
285343 }
286344
287-
345+ /**
346+ * For backward compatibility
347+ * @deprecated use the removeItemArrows method instead.
348+ */
349+ removeArrowbyItemId ( id ) {
350+ this . removeItemArrows ( id ) ;
351+ }
288352
289353 }
0 commit comments