55* https://github.com/ita-design-system/c-scrollspy.js
66*/
77const cScrollspy = {
8- defaults : {
9- options : null ,
10- callback : function ( data ) {
11- // console.log('callback par défaut invoqué');
12- }
13- } ,
14- custom_parameters : {
15- /**
16- * SCROLLER
17- * Settings for scroll snap type container
18- */
19- scroller : {
20- options : {
21- threshold : [ 0.8 ]
22- } ,
23- callback : function ( data ) {
24- // console.log(data);
25- // Id of the tracked target element
26- // const id = data[0].target.id;
27- // console.log(id, data[0].target.dataset.targetId, data[0].intersectionRatio);
28- //
29- const target_id = data [ 0 ] . target . dataset . targetId ;
30- if ( cScrollspy . custom_parameters . scroller . elements === undefined ) {
31- cScrollspy . custom_parameters . scroller . elements = { } ;
32- }
33- if ( cScrollspy . custom_parameters . scroller . elements [ target_id ] === undefined ) {
34- cScrollspy . custom_parameters . scroller . elements [ target_id ] = document . querySelector ( '#' + target_id ) ;
35- }
36- // Alias
37- const el_target_id = cScrollspy . custom_parameters . scroller . elements [ target_id ] ;
38- // Work only if a target exists
39- if ( el_target_id !== null ) {
40- // If listener is not already set
41- if ( el_target_id . onclick === null ) {
42- // Get the command (previous or next) through the attriblue aria-command
43- // aria-command="previous" adds a listerner that scroll to previous element
44- // aria-command="next" adds a listerner that scroll to next element
45- const target_command = el_target_id . getAttribute ( 'aria-command' ) ;
46- if ( target_command == 'next' || target_command == 'previous' ) {
47- el_target_id . addEventListener ( 'click' , function ( el ) {
48- // get the with of the element and use it as default increment/decrement amount of scroll
49- const width_of_el = data [ 0 ] . target . clientWidth ;
50- const current_scroll_left = data [ 0 ] . target . parentElement . scrollLeft ;
51- // console.log(width_of_el, current_scroll_left);
52- let amount_of_scroll = current_scroll_left + width_of_el ;
53- if ( target_command == 'previous' ) {
54- amount_of_scroll = current_scroll_left - width_of_el ;
55- }
56- data [ 0 ] . target . parentElement . scrollTo ( {
57- behavior : 'smooth' ,
58- left : amount_of_scroll
59- } ) ;
60- } ) ;
61- }
62- }
63- if ( data [ 0 ] . intersectionRatio > 0.8 ) {
64- el_target_id . classList . add ( 'u-disabled' ) ;
65- } else {
66- el_target_id . classList . remove ( 'u-disabled' ) ;
67- }
68- }
69- }
70- } ,
8+ callbacks : {
719 /**
7210 * ANCHORS
7311 * Options for anchors links -> HTML ids
@@ -82,18 +20,23 @@ const cScrollspy = {
8220 * @arg {(object)} data event data returned by intersectonObserver
8321 */
8422 callback : function ( data ) {
85- // Id of the tracked target element
23+ // Id of the tracked tracked element
8624 const id = data [ 0 ] . target . id ;
87- // console.log(id);
88-
89- // myScrollspy.custom_parameters.anchors.tracked_elements_y[id] = data[0].boundingClientRect.y;
90-
25+ // Optional active classes
26+ let active_class_attribute = data [ 0 ] . target . dataset . activeClass ;
27+ let origin_class_attribute = data [ 0 ] . target . getAttribute ( 'class' ) || '' ;
28+ if ( active_class_attribute === undefined ) {
29+ active_class_attribute = 'active' ;
30+ } else {
31+ // Custom class detected, save once origin class attribute
32+ if ( data [ 0 ] . target . dataset . classOrigin === undefined ) {
33+ data [ 0 ] . target . dataset . classOrigin = origin_class_attribute ;
34+ }
35+ }
9136 // Write intersection ratio into an custom object
92- cScrollspy . custom_parameters . anchors . intersections [ id ] = data [ 0 ] . intersectionRatio ;
37+ cScrollspy . callbacks . anchors . intersections [ id ] = data [ 0 ] . intersectionRatio ;
9338 // Get current id => intersection values
94- const current_intersections = cScrollspy . custom_parameters . anchors . intersections ;
95-
96-
39+ const current_intersections = cScrollspy . callbacks . anchors . intersections ;
9740 // Sort intersection values
9841 const intersections_sorted = Object . keys ( current_intersections ) . sort ( function ( a , b ) { return current_intersections [ b ] - current_intersections [ a ] } ) ;
9942 // Get the id of the first/highest intersection value
@@ -104,16 +47,24 @@ const cScrollspy = {
10447 intersections_sorted . forEach ( function ( id , index ) {
10548 // Search for all anchors links pointing to this id
10649 document . querySelectorAll ( '[href="#' + id + '"]' ) . forEach ( function ( el_anchor ) {
107- // Remove active class name
108- el_anchor . classList . remove ( 'active' ) ;
10950 // The value of the first/highest intersection
110- const first_intersection_id_value = cScrollspy . custom_parameters . anchors . intersections [ first_intersection_id ] ;
51+ const first_intersection_id_value = cScrollspy . callbacks . anchors . intersections [ first_intersection_id ] ;
11152 // The value of the second/highest intersection
112- const second_intersection_id_value = cScrollspy . custom_parameters . anchors . intersections [ second_intersection_id ] ;
113- // If it is the highest intersection, apply active class
114- // Second intersection must be inferior to first intersection value to avoid "active" class mismatch
115- if ( first_intersection_id == id && second_intersection_id_value < first_intersection_id_value ) {
116- el_anchor . classList . add ( 'active' ) ;
53+ const second_intersection_id_value = cScrollspy . callbacks . anchors . intersections [ second_intersection_id ] ;
54+ if ( Object . keys ( intersections_sorted ) . length > 1 ) {
55+ // If it is the highest intersection, apply active class
56+ // Second intersection must be inferior to first intersection value to avoid "active" class mismatch
57+ if ( first_intersection_id == id && second_intersection_id_value < first_intersection_id_value ) {
58+ el_anchor . setAttribute ( 'class' , origin_class_attribute ) ;
59+ } else {
60+ el_anchor . setAttribute ( 'class' , active_class_attribute ) ;
61+ }
62+ } else {
63+ if ( first_intersection_id_value > 0 ) {
64+ el_anchor . setAttribute ( 'class' , active_class_attribute ) ;
65+ } else {
66+ el_anchor . setAttribute ( 'class' , origin_class_attribute ) ;
67+ }
11768 }
11869 } ) ;
11970 } ) ;
@@ -128,38 +79,25 @@ const cScrollspy = {
12879 // Method to invoke at start and each time DOM has changed
12980 update : function ( ) {
13081 // Iterate all the scrollspy attributes
131- document . querySelectorAll ( '[my -scrollspy]' ) . forEach ( function ( el , index ) {
82+ document . querySelectorAll ( '[c -scrollspy]' ) . forEach ( function ( el , index ) {
13283 // Value = custom option name for the current tracked element
133- const custom_params_name = el . getAttribute ( 'my-scrollspy' ) ;
134- // Custom parameter must be an object
135- if ( typeof cScrollspy . custom_parameters [ custom_params_name ] == 'object' ) {
136- // Set default options for intersectionObserver
137- let instance_options = cScrollspy . defaults . options ;
138- // If custom options is an object, then use it
139- if ( typeof cScrollspy . custom_parameters [ custom_params_name ] [ 'options' ] == 'object' ) {
140- // console.log('options trouvées dans les paramètres');
141- instance_options = cScrollspy . custom_parameters [ custom_params_name ] [ 'options' ] ;
142- }
143- // Set default callback for intersectionObserver
144- let instance_callback = cScrollspy . defaults . callback ;
145- // If custom callback is a function, then use it
146- if ( typeof cScrollspy . custom_parameters [ custom_params_name ] [ 'callback' ] == 'function' ) {
147- // console.log('callback ok');
148- instance_callback = cScrollspy . custom_parameters [ custom_params_name ] [ 'callback' ] ;
84+ const callback_name = el . getAttribute ( 'c-scrollspy' ) ;
85+ let callback_object = cScrollspy . callbacks . anchors ;
86+ if ( typeof cScrollspyCallbacks == 'object' ) {
87+ if ( typeof cScrollspyCallbacks [ callback_name ] == 'object' ) {
88+ callback_object = cScrollspyCallbacks [ callback_name ] ;
14989 }
150- // Set default instance id
151- let instance_id = 'spy_' + index ;
152- // If tracked element has an id, use it
153- if ( el . id != '' ) {
154- instance_id = el . id ;
155- }
156- // Create intersection observer as an object into myScrollspy
157- cScrollspy . instances [ instance_id ] = new IntersectionObserver ( instance_callback , instance_options ) ;
158- // Track element
159- cScrollspy . instances [ instance_id ] . observe ( el ) ;
160- } else {
161- console . log ( 'paramètres perso non définis :' + custom_params_name ) ;
16290 }
91+ // Set default instance id
92+ let instance_id = 'cspy_' + index ;
93+ // If tracked element has an id, use it
94+ if ( el . id != '' ) {
95+ instance_id = el . id ;
96+ }
97+ // Create intersection observer as an object into myScrollspy
98+ cScrollspy . instances [ instance_id ] = new IntersectionObserver ( callback_object . callback , callback_object . options ) ;
99+ // Track element
100+ cScrollspy . instances [ instance_id ] . observe ( el ) ;
163101 } ) ;
164102 }
165103}
0 commit comments