1- import StorageInterface from "./storage/storageInterface" ;
2- import LikeInstancesStorage from "./storage/likeInstancesStorage" ;
3-
4- const likeIconSelector : string = '[data-like-icon]' ;
5- const likedIconClass : string = 'material-symbols--filled' ;
6- const postIdAttribute : string = 'data-post-id' ;
7- const postTypeAttribute : string = 'data-post-type' ;
8- const blogIdAttribute : string = 'data-blog-id' ;
9- const tooltipAttribute : string = 'data-tooltip' ;
10- const iconWrapperAttribute : string = 'data-js-like-icon-wrapper' ;
11- const likeIconInitializedAttribute : string = 'data-like-icon-initialized' ;
12-
13- export default class Like {
14- private hasTooltip : boolean ;
15- private key : string ;
16- constructor (
17- private likeStorage : StorageInterface ,
18- private likeInstancesStorage : LikeInstancesStorage ,
19- private button : Element ,
20- private wrapper : Element | null ,
21- private postId : string ,
22- private postType : string ,
23- private tooltipLike : string ,
24- private tooltipUnlike : string ,
25- private blogId : string
26- ) {
27- this . key = `${ this . blogId } -${ this . postId } ` ;
28- this . hasTooltip = Boolean ( this . wrapper && ( ! ! this . tooltipLike || ! ! this . tooltipUnlike ) ) ;
29- this . updateLikedStatus ( ) ;
30- this . setTooltip ( ) ;
31- this . setListener ( ) ;
32- }
33-
34- // Sets the event listener for the like button
35- private setListener ( ) {
36- this . button . addEventListener ( 'click' , ( e ) => {
371 e . preventDefault ( ) ;
38- e . stopPropagation ( ) ;
39- this . likeStorage . set ( this . postId , this . postType , this . blogId ) ;
40- this . toggleLiked ( ) ;
41- window . dispatchEvent ( this . likedPostsUpdatedEvent ( ) ) ;
42- } ) ;
43- }
44-
45- // Sets the tooltip for the like button
46- private setTooltip ( ) {
47- if ( ! this . hasTooltip ) {
48- return ;
49- }
50-
51- const isLiked = this . likeStorage . get ( ) [ this . key ] ;
52-
53- if ( isLiked ) {
54- if ( this . tooltipUnlike ) {
55- this . wrapper ! . setAttribute ( tooltipAttribute , this . tooltipUnlike ) ;
56- } else {
57- this . wrapper ! . removeAttribute ( tooltipAttribute ) ;
58- }
59- } else {
60- if ( this . tooltipLike ) {
61- this . wrapper ! . setAttribute ( tooltipAttribute , this . tooltipLike ) ;
62- } else {
63- this . wrapper ! . removeAttribute ( tooltipAttribute ) ;
64- }
65- }
66- }
67-
68- // Toggles the like button (liked/not liked) and updates all like buttons with the same postId
69- private toggleLiked ( ) {
70- this . likeInstancesStorage . getInstances ( this . key ) . forEach ( ( instance ) => {
71- instance . updateLikedStatus ( ) ;
72- instance . setTooltip ( ) ;
73- } ) ;
74- }
75-
76- // Updates the state of the like button (liked/not liked)
77- public updateLikedStatus ( ) {
78- const isLiked = this . likeStorage . get ( ) [ this . key ] ;
79- if ( isLiked ) {
80- this . button . classList . add ( likedIconClass ) ;
81- } else {
82- this . button . classList . remove ( likedIconClass ) ;
83- }
84- }
85-
86- // Custom event to update liked posts length
87- public likedPostsUpdatedEvent ( ) {
88- return new CustomEvent ( 'likedPostsLengthUpdated' , { } ) ;
89- }
90- }
91-
92- // Initialize like buttons/icons
93- export function initializeLikeButtons (
94- likeStorage : StorageInterface ,
95- likeInstancesStorage : LikeInstancesStorage ,
96- tooltipLike : string ,
97- tooltipUnlike : string
98- ) {
99- const createLikeInstance = ( button : Element ) => {
100- const postId = button . getAttribute ( postIdAttribute ) ;
101- const postType = button . getAttribute ( postTypeAttribute ) ;
102- const blogId = button . getAttribute ( blogIdAttribute )
103-
104- if ( ! postId || ! postType || ! blogId ) {
105- console . warn ( 'Like button is missing required blogId for likeable post' , button ) ;
106- return ;
107- }
108-
109-
110- const wrapper = button . closest ( `[${ iconWrapperAttribute } ]` ) ;
111-
112- likeInstancesStorage . addInstance (
113- `${ blogId } -${ postId } ` ,
114- new Like (
115- likeStorage ,
116- likeInstancesStorage ,
117- button ,
118- wrapper ,
119- postId ,
120- postType ,
121- tooltipLike ,
122- tooltipUnlike ,
123- blogId
124- )
125- ) ;
126- } ;
127-
128- document . querySelectorAll ( likeIconSelector ) . forEach ( ( button ) => {
129- createLikeInstance ( button ) ;
130- } ) ;
131-
132- const observer = new MutationObserver ( ( mutations ) => {
133- mutations . forEach ( ( mutation ) => {
134- if ( mutation . type === 'childList' && mutation . addedNodes . length > 0 ) {
135- [ ...mutation . addedNodes ] . forEach ( ( node ) => {
136- if ( node . nodeType === Node . ELEMENT_NODE ) {
137- const element = node as Element ;
138-
139- if ( element . matches ( likeIconSelector ) ) {
140- if ( element . hasAttribute ( likeIconInitializedAttribute ) ) {
141- return ;
142- }
143-
144- element . setAttribute ( likeIconInitializedAttribute , 'true' ) ;
145- createLikeInstance ( element ) ;
146- } else {
147- element . querySelectorAll ( likeIconSelector ) . forEach ( ( button ) => {
148- if ( button . hasAttribute ( likeIconInitializedAttribute ) ) {
149- return ;
150- }
151-
152- button . setAttribute ( likeIconInitializedAttribute , 'true' ) ;
153- createLikeInstance ( button ) ;
154- } ) ;
155- }
156-
157- }
158- } ) ;
159- }
160- } ) ;
161- } ) ;
162-
163- observer . observe ( document . body , { childList : true , subtree : true } ) ;
164- }
0 commit comments