javascriptcsstreeviewtimeline

How to make treeview fully support right-to-left (RTL) & display outer (UL) as bootstrap timeline


    $.fn.extend({
        treed: function (o) {

          var openedClass = 'fa-minus-circle';
          var closedClass = 'fa-plus-circle';

          if (typeof o != 'undefined'){
            if (typeof o.openedClass != 'undefined'){
            openedClass = o.openedClass;
            }
            if (typeof o.closedClass != 'undefined'){
            closedClass = o.closedClass;
            }
          };

            //initialize each of the top levels
            var tree = $(this);
            tree.addClass("tree");
            tree.find('li').has("ul").each(function () {
                var branch = $(this); //li with children ul
                branch.prepend("<i class='indicator fas " + closedClass + "'></i>");
                branch.addClass('branch');
                branch.on('click', function (e) {
                    if (this == e.target) {
                        var icon = $(this).children('i:first');
                        icon.toggleClass(openedClass + " " + closedClass);
                        $(this).append("<div class='loading'><span class='fa fa-spinner fa-spin'</span></div>");         
                          setTimeout(()=>{
                            $(this).find('.loading').remove();
                            $(this).children().children().slideToggle(400);
                          }, 400)
                    }
                })
                branch.children().children().toggle();
            });
            //fire event from the dynamically added icon
          tree.find('.branch .indicator').each(function(){
            $(this).on('click', function () {
                $(this).closest('li').click();
            });
          });
            //fire event to open branch if the li contains an anchor instead of text
            tree.find('.branch>a').each(function () {
                $(this).on('click', function (e) {
                    $(this).closest('li').click();
                    e.preventDefault();
                });
            });
            //fire event to open branch if the li contains a button instead of text
            tree.find('.branch>button').each(function () {
                $(this).on('click', function (e) {
                    $(this).closest('li').click();
                    e.preventDefault();
                });
            });
        }
    });

    //Initialization of treeviews

    $('#tree1').treed();
$.fn.extend({
  treed: function (o) {

    var openedClass = 'fa-minus-circle';
    var closedClass = 'fa-plus-circle';

    if (typeof o != 'undefined'){
      if (typeof o.openedClass != 'undefined'){
      openedClass = o.openedClass;
      }
      if (typeof o.closedClass != 'undefined'){
      closedClass = o.closedClass;
      }
    };

//initialize each of the top levels
      var tree = $(this);
      tree.addClass("tree");
      tree.find('li').has("ul").each(function () {
          var branch = $(this); //li with children ul
          branch.prepend("<i class='indicator fas " + closedClass + "'></i>");
          branch.addClass('branch');

          // declare a flag to toggle
          let flag = false;
          branch.on('click', function (e) {
              if (this == e.target) {
                  // toggle on click
                  flag = !flag;
                  var icon = $(this).children('i:first');
                  icon.toggleClass(openedClass + " " + closedClass); 

                  // show loader only when its opened, and collpase once toggled   
                  if(flag) {
                    $(this).append("<div class='loading'><span class='fa fa-spinner fa-spin'</span></div>"); 
                    setTimeout(()=>{
                      $(this).find('.loading').remove();
                      $(this).children().children().slideToggle(400);
                    }, 400)
                  } else {
                    $(this).children().children().slideToggle(400);
                  }
              }
          })
          branch.children().children().toggle();
      });

//fire event from the dynamically added icon
    tree.find('.branch .indicator').each(function(){
      $(this).on('click', function () {
          $(this).closest('li').click();
      });
    });
      //fire event to open branch if the li contains an anchor instead of text
      tree.find('.branch>a').each(function () {
          $(this).on('click', function (e) {
              $(this).closest('li').click();
              e.preventDefault();
          });
      });
      //fire event to open branch if the li contains a button instead of text
      tree.find('.branch>button').each(function () {
          $(this).on('click', function (e) {
              $(this).closest('li').click();
              e.preventDefault();
              });
          });
      }
    });
    
    //Initialization of treeviews
    
    $('#tree1').treed();
    
    $('#tree2').treed({openedClass:'fa-folder-open', closedClass:'fa-folder'});
    .tree, .tree ul {
      margin:0;
      padding:0;
      list-style:none;
      margin-left:10px;
    }
    .tree ul {
      margin-left:1em;
      position:relative
    }
    .tree ul ul {
      margin-left:.5em
    }
    .tree ul:before {
      content:"";
      display:block;
      width:0;
      position:absolute;
      top:0;
      bottom:0;
      left:0;
      border-left:1px solid
    }
    .tree li {
      margin:0;
      padding:0 1em;
      line-height:2em;
      color:#369;
      font-weight:700;
      position:relative;
    }
    .tree ul li:before {
      content:"";
      display:block;
      width:10px;
      height:0;
      border-top:1px solid;
      margin-top:-1px;
      position:absolute;
      top:1em;
      left:0
    }
    .tree ul li:last-child:before {
      background:#fff;
      height:auto;
      top:1em;
      bottom:0
    }
    .indicator {
      margin-right:5px;
    }
    .tree li a {
      text-decoration: none;
      color:#369;
    }
    .tree li button, .tree li button:active, .tree li button:focus {
      text-decoration: none;
      color:#369;
      border:none;
      background:transparent;
      margin:0px 0px 0px 0px;
      padding:0px 0px 0px 0px;
      outline: 0;
    }

    .loading {
      font-style: italic;
    }
.timeline {
  border-left: 1px solid hsl(0, 0%, 90%);
  position: relative;
  list-style: none;
}

.timeline .timeline-item {
  position: relative;
}

.timeline .timeline-item:after {
  position: absolute;
  display: block;
  top: 0;
}

.timeline .timeline-item:after {
  background-color: hsl(0, 0%, 90%);
  left: -38px;
  border-radius: 50%;
  height: 11px;
  width: 11px;
  content: "";

}
    <div class="row">
        <div class="col-md-4">
           <ul id="tree2">
              <li>
                 <a href="#">TECH</a>
                 <ul>
                    <li>Company Maintenance</li>
                    <li>
                       Employees
                       <ul>
                          <li>
                             Reports
                             <ul>
                                <li>Report1 
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label for="recipient-name" class="col-form-label"> li text</label>
            <input type="text" class="form-control">
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div> </li>                            <li>Report2 
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
</li>                              <li>Report3 
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
</li>
                             </ul>
                          </li>
                          <li>Employee Maint.</li>
                       </ul>
                    </li>
                    <li>Human Resources</li>
                 </ul>
              </li>
              <li>
                 XRP
                 <ul>
                    <li>Company Maintenance</li>
                    <li>
                       Employees
                       <ul>
                          <li>
                             Reports
                             <ul>
                                <li>Report1 
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
</li>
                                <li>Report2
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
</li>
                                <li>Report3 
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
<i class="fa fa-plus"></i>
</button>
</li>
                             </ul>
                          </li>
                          <li>Employee Maint.</li>
                       </ul>
                    </li>
                    <li>Human Resources</li>
                 </ul>
              </li>
              
           </ul>
        </div>
     </div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.rtl.min.css">
   <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>

I have this Treeview and I want to make it fully support right-to-left (RTL) display. I have already included a Bootstrap CSS link to support Arabic RTL, but it did not succeed in making it support right-to-left display. Note: I also want the outer ul elements (not the inner ones that appear when the Treeview is collapsed) to be included in a Bootstrap class called "timeline" and the outer ul elements should appear as shown in this image.enter image description here


Solution

  • Try this :

        $.fn.extend({
            treed: function (o) {
    
              var openedClass = 'fa-minus-circle';
              var closedClass = 'fa-plus-circle';
    
              if (typeof o != 'undefined'){
                if (typeof o.openedClass != 'undefined'){
                openedClass = o.openedClass;
                }
                if (typeof o.closedClass != 'undefined'){
                closedClass = o.closedClass;
                }
              };
    
                //initialize each of the top levels
                var tree = $(this);
                tree.addClass("tree");
                tree.find('li').has("ul").each(function () {
                    var branch = $(this); //li with children ul
                    branch.prepend("<i class='indicator fas " + closedClass + "'></i>");
                    branch.addClass('branch');
                    branch.on('click', function (e) {
                        if (this == e.target) {
                            var icon = $(this).children('i:first');
                            icon.toggleClass(openedClass + " " + closedClass);
                            $(this).append("<div class='loading'><span class='fa fa-spinner fa-spin'</span></div>");         
                              setTimeout(()=>{
                                $(this).find('.loading').remove();
                                $(this).children().children().slideToggle(400);
                              }, 400)
                        }
                    })
                    branch.children().children().toggle();
                });
                //fire event from the dynamically added icon
              tree.find('.branch .indicator').each(function(){
                $(this).on('click', function () {
                    $(this).closest('li').click();
                });
              });
                //fire event to open branch if the li contains an anchor instead of text
                tree.find('.branch>a').each(function () {
                    $(this).on('click', function (e) {
                        $(this).closest('li').click();
                        e.preventDefault();
                    });
                });
                //fire event to open branch if the li contains a button instead of text
                tree.find('.branch>button').each(function () {
                    $(this).on('click', function (e) {
                        $(this).closest('li').click();
                        e.preventDefault();
                    });
                });
            }
        });
    
        //Initialization of treeviews
    
        $('#tree1').treed();
    $.fn.extend({
      treed: function (o) {
    
        var openedClass = 'fa-minus-circle';
        var closedClass = 'fa-plus-circle';
    
        if (typeof o != 'undefined'){
          if (typeof o.openedClass != 'undefined'){
          openedClass = o.openedClass;
          }
          if (typeof o.closedClass != 'undefined'){
          closedClass = o.closedClass;
          }
        };
    
    //initialize each of the top levels
          var tree = $(this);
          tree.addClass("tree");
          tree.find('li').has("ul").each(function () {
              var branch = $(this); //li with children ul
              branch.prepend("<i class='indicator fas " + closedClass + "'></i>");
              branch.addClass('branch');
    
              // declare a flag to toggle
              let flag = false;
              branch.on('click', function (e) {
                  if (this == e.target) {
                      // toggle on click
                      flag = !flag;
                      var icon = $(this).children('i:first');
                      icon.toggleClass(openedClass + " " + closedClass); 
    
                      // show loader only when its opened, and collpase once toggled   
                      if(flag) {
                        $(this).append("<div class='loading'><span class='fa fa-spinner fa-spin'</span></div>"); 
                        setTimeout(()=>{
                          $(this).find('.loading').remove();
                          $(this).children().children().slideToggle(400);
                        }, 400)
                      } else {
                        $(this).children().children().slideToggle(400);
                      }
                  }
              })
              branch.children().children().toggle();
          });
    
    //fire event from the dynamically added icon
        tree.find('.branch .indicator').each(function(){
          $(this).on('click', function () {
              $(this).closest('li').click();
          });
        });
          //fire event to open branch if the li contains an anchor instead of text
          tree.find('.branch>a').each(function () {
              $(this).on('click', function (e) {
                  $(this).closest('li').click();
                  e.preventDefault();
              });
          });
          //fire event to open branch if the li contains a button instead of text
          tree.find('.branch>button').each(function () {
              $(this).on('click', function (e) {
                  $(this).closest('li').click();
                  e.preventDefault();
                  });
              });
          }
        });
        
        //Initialization of treeviews
        
        $('#tree1').treed();
        
        $('#tree2').treed({openedClass:'fa-folder-open', closedClass:'fa-folder'});
        .tree, .tree ul {
          margin:0;
          padding:0;
          list-style:none;
          margin-right:10px;
        }
        .tree ul {
          margin-right:1em;
          position:relative
        }
        .tree ul ul {
          margin-right:.5em
        }
        .tree ul:before {
          content:"";
          display:block;
          width:0;
          position:absolute;
          top:0;
          bottom:0;
          right:0;
          border-right:1px solid
        }
        .tree li {
          margin:0;
          padding:0 1em;
          line-height:2em;
          color:#369;
          font-weight:700;
          position:relative;
        }
        .tree ul li:before {
          content:"";
          display:block;
          width:10px;
          height:0;
          border-top:1px solid;
          margin-top:-1px;
          position:absolute;
          top:1em;
          right:0
        }
        .tree ul li:last-child:before {
          background:#fff;
          height:auto;
          top:1em;
          bottom:0
        }
        .indicator {
          margin-right:5px;
        }
        .tree li a {
          text-decoration: none;
          color:#369;
        }
        .tree li button, .tree li button:active, .tree li button:focus {
          text-decoration: none;
          color:#369;
          border:none;
          background:transparent;
          margin:0px 0px 0px 0px;
          padding:0px 0px 0px 0px;
          outline: 0;
        }
    
        .loading {
          font-style: italic;
        }
    .timeline {
      border-left: 1px solid hsl(0, 0%, 90%);
      position: relative;
      list-style: none;
    }
    
    .timeline .timeline-item {
      position: relative;
    }
    
    .timeline .timeline-item:after {
      position: absolute;
      display: block;
      top: 0;
    }
    
    .timeline .timeline-item:after {
      background-color: hsl(0, 0%, 90%);
      left: -38px;
      border-radius: 50%;
      height: 11px;
      width: 11px;
      content: "";
    
    }
        <div dir="rtl" class="row">
            <div  dir="rtl" class="col-md-4">
               <ul id="tree2">
                  <li>
                     <a href="#">TECH</a>
                     <ul>
                        <li>Company Maintenance</li>
                        <li>
                           Employees
                           <ul>
                              <li>
                                 Reports
                                 <ul>
                                    <li>Report1 
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <form>
              <div class="mb-3">
                <label for="recipient-name" class="col-form-label"> li text</label>
                <input type="text" class="form-control">
              </div>
            </form>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Send message</button>
          </div>
        </div>
      </div>
    </div> </li>                            <li>Report2 
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    </li>                              <li>Report3 
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    </li>
                                 </ul>
                              </li>
                              <li>Employee Maint.</li>
                           </ul>
                        </li>
                        <li>Human Resources</li>
                     </ul>
                  </li>
                  <li>
                     XRP
                     <ul>
                        <li>Company Maintenance</li>
                        <li>
                           Employees
                           <ul>
                              <li>
                                 Reports
                                 <ul>
                                    <li>Report1 
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    </li>
                                    <li>Report2
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    </li>
                                    <li>Report3 
    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">
    <i class="fa fa-plus"></i>
    </button>
    </li>
                                 </ul>
                              </li>
                              <li>Employee Maint.</li>
                           </ul>
                        </li>
                        <li>Human Resources</li>
                     </ul>
                  </li>
                  
               </ul>
            </div>
         </div>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.rtl.min.css">
       <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>