B4J Tutorial [ABMaterial] Facebook-like timeline in less 200 lines!


Licensed User
Note: This example will be included in the upcoming 3.02 Maintenance Update.

I had a question if it was possible to create a Facebook-like WebApp with ABMaterial so I had some time to spare :rolleyes: and wrote a basic one.

Using ABMContainers and the next CloseContent/OpenContent feature introduced in 3.02, and the existing NextContent to create an infinite page, this was written in less than 200 lines of code!

It also needed a ABMCustomComponent for the 'Like' feature, of which you can find the source code under the video.


Source code for the 'Like' custom component.

You'll need also the attached zip file for the images and js/css files. Put the images and css in the /css/custom folder, the js file in the /js/custom/ folder.

Class LikeComponent
'Class module
Sub Class_Globals
   Public ABMComp As ABMCustomComponent   
   Public Counter As Int
End Sub

'Initializes the object. Countries and data are Json Strings
Public Sub Initialize(InternalPage As ABMPage, ID As String, AlreadyLiked As Int)
   ABMComp.Initialize("ABMComp", Me, InternalPage, ID)   
   Counter = AlreadyLiked
End Sub

Sub ABMComp_Build(internalID As String) As String
   Return $"<div id="${internalID} class="facebook-reaction"><!-- container div for reaction system -->
        <span class="like-btn"> <!-- Default like button -->
          <span class="like-btn-emo like-btn-default"></span> <!-- Default like button emotion-->
           <span class="like-btn-text">Like</span> <!-- Default like button text,(Like, wow, sad..) default:Like  -->
           <ul class="reactions-box"> <!-- Reaction buttons container-->
             <li class="reaction reaction-like" data-reaction="Like"></li>
             <li class="reaction reaction-love" data-reaction="Love"></li>
             <li class="reaction reaction-haha" data-reaction="HaHa"></li>
             <li class="reaction reaction-wow" data-reaction="Wow"></li>
             <li class="reaction reaction-sad" data-reaction="Sad"></li>
             <li class="reaction reaction-angry" data-reaction="Angry"></li>
         <div class="like-stat"> <!-- Like statistic container-->
           <span class="like-emo"> <!-- like emotions container -->
             <span class="like-btn-like"></span> <!-- given emotions like, wow, sad (default:Like) -->
           <span class="like-details">${Counter} others</span>
End Sub

Sub ABMComp_FirstRun(InternalPage As ABMPage, internalID As String)
   Dim script As String = $"$("#${internalID} .reaction").on("click",function(){  // like click
     var data_reaction = $(this).attr("data-reaction");
     $("#${internalID} .like-details").html("You and ${Counter} others");
     $("#${internalID} .like-btn-emo").removeClass().addClass('like-btn-emo').addClass('like-btn-'+data_reaction.toLowerCase());
     $("#${internalID} .like-btn-text").text(data_reaction).removeClass().addClass('like-btn-text').addClass('like-btn-text-'+data_reaction.toLowerCase()).addClass("active");;

     if(data_reaction == "Like") {
         $("#${internalID} .like-emo").html('<span class="like-btn-like"></span>');
     } else {
         $("#${internalID} .like-emo").html('<span class="like-btn-like"></span><span class="like-btn-'+data_reaction.toLowerCase()+'"></span>');
     var json = {'target': '${internalID}', 'like': data_reaction};
     b4j_raiseEvent('likecomponent_liked', json);
     $("#${internalID} .like-btn-text").on("click",function(){ // undo like click
       $("#${internalID} .like-btn-text").text("Like").removeClass().addClass('like-btn-text');
       $("#${internalID} .like-btn-emo").removeClass().addClass('like-btn-emo').addClass("like-btn-default");
       $("#${internalID} .like-emo").html('<span class="like-btn-like"></span>');
       $("#${internalID} .like-details").html("${Counter} others");
       var json = {'target':'${internalID}'};
         b4j_raiseEvent('likecomponent_unliked', json);

   InternalPage.ws.Eval(script, Array As Object(ABMComp.ID))
   ' flush not needed, it's done in the refresh method in the lib
End Sub

Sub ABMComp_Refresh(InternalPage As ABMPage, internalID As String)
   Dim script As String = $""$
   InternalPage.ws.Eval(script, Null)
End Sub

' do the stuff needed when the object is removed
Sub ABMComp_CleanUp(InternalPage As ABMPage, internalID As String)

End Sub


Sub Class_Globals
   Dim myLike As LikeComponent
End Sub

' adding the component
myLike.initialize(page, ID & "Like", Rnd(20, 500))
Events (the name LikeComponent is programmed fixed in the LikeComponent class:
public Sub LikeComponent_Liked(value As Map)   
   Log(value.Get("like") & " ----> " & value.Get("target"))
End Sub

public Sub LikeComponent_UnLiked(value As Map)
   Log("Unliked ----> " & value.Get("target"))
End Sub




What if you want to add a comment through some input and with a button to send the comment, should you use "AddArrayComponent" to insert a new comment?