jsTree - How set selected node after page refreshed?

53 Views Asked by At

I use the jsTree library to display a tree of categories and subcategories on the ecommerce platform. When a node is clicked, I load a certain category with an ID added to the URL like this www.site.com/admin/catalog/categories/1

When I click, the page loads a new page, but no node is selected.

How to set selected node based on id or last selected node?

Here is my script

<script>
    $(document).ready(function () {

        var jstree = $('#jstree').jstree({
            'core' : {
                'data' : {
                    'url' : '/admin/catalog/categories',
                    'data' : function (node) {
                        return { 'id' : node.id };
                    }
                }
            }
        });

        
        jstree.on('changed.jstree', function (e, data) {
            window.open('/admin/catalog/categories/'+data.node.id, '_self');
        });

    })
</script>
2

There are 2 best solutions below

0
Jan Tungli On

Are you still tired of writing procedures for selecting something? Here is the general procedure for selecting anything. You don't have to write another procedure for select anywhere. Try it, this is example:

<!DOCTYPE html>
<html>
<head>
 <script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script>

function ReplaceAll(base,told,tnew) { // replace insensitive
  if (told=="") {return base;}
  var u=base.toLowerCase();
  var t=told.toLowerCase();
  var ss=""; var p=-1; var i=0;
  p=u.indexOf(t);
  if (p>-1) {
    let mLen=told.length;
    while (p>=0) {
      ss+=base.substr(0,p)+tnew;
      i=p+mLen;
      base=base.substr(i);
      u=u.substr(i);
      p=u.indexOf(t);
    }
    ss+=base; //fix bug
    return ss;
  }
  return base;
}

function Len(pS) {return pS.length;}
function Lower(pS) {return pS.toLowerCase();}
function Upper(pS) {return pS.toUpperCase();}
function Trim(pS) {return pS.trim();}
function Sub(pS, p1, p2=0) { 
  if (p2<=0) {p2=Len(pS);}
  if (p1<=0) {p1=0;}
  return pS.substring(p1,p2); 
}
  

function IndexAt(base, t ,pos=0) { //index from position
  if (pos<0) {pos=0;}
  var x=base.substr(pos);
  var p=x.indexOf(t);
  if (p>=0) { return p+pos;} else {return -1;}
}

function NormStyle(pS) {  //normalization style
  pS=Trim(pS);
  if (Len(pS)==0) {
    return pS;
  }
  if (IndexAt(pS,":")>=0) {pS+=";";} // style+";"
  pS=ReplaceAll(pS,';;',';');
  pS=ReplaceAll(pS,' ','');  // without spaces!  -> font-name
  pS=ReplaceAll(pS,',',', ');
  //-- color:#* ->color:rgb(*), because jQuery in runtime replace style: color:#* -> rgb(*), font_size:?em -> ?px .. etc.
  var p1=0; var p2=0;
  var t1=""; var t2="";
  p1=IndexAt(pS,"color:#");
  while (p1>=0) {
   p2=IndexAt(pS,';',p1);
   if (p2>0) {
     t1=Sub(pS,p1,p2); //color:#ff0000
     t2=Sub(t1,6); //#ff0000
     t2=RGB(t2);
     pS=ReplaceAll(pS,t1,"color:"+t2);
   }
   p1=IndexAt(pS,"color:#",p0+2);
  }
  return pS;
}

function RGB(pS) {
  var rgb=pS;
  if (IndexAt(Trim(rgb),"#")==0) {
    rgb=Trim(rgb);
    rgb=rgb.padEnd(7,"0"); //#ff00 -> #ff00000
    var patt = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/;
    var matches = patt.exec(rgb);
    rgb = "rgb("+parseInt(matches[1], 16)+", "+parseInt(matches[2], 16)+", "  +parseInt(matches[3], 16)+")";
  }
  return rgb;
}

function NQ(pS) { //NQ("alfa 'b`c' x")=="alfa ♣♣♣♣♦ x"
  var bo=false; var mEnd=true; 
  var typ=0;
  var s="";
  for (let i=0; i<Len(pS); i++) {
    switch (pS.charAt(i)) {
     case '"': if (typ==1) {typ=0;} else { if (typ==0) {typ=1;} } break;
     case "'": if (typ==2) {typ=0;} else { if (typ==0) {typ=2;} } break;
     case "`": if (typ==3) {typ=0;} else { if (typ==0) {typ=3;} } break;
    }
    if (typ==0) {
      if (!mEnd) { mEnd=true; s+="♦"} else {s+=pS.charAt(i);} 
    } else {
      s+="♣"; mEnd=false;
    } 
  }
  if (typ>0) {s="Error:♣ Not valid string termination";}
  return s;
}

function Element(pSelector, pFilter="",pNumbers="",pTrace=1) { //pTrace: 0=no trace, 1=console.log, 2=alert trace
  switch (pTrace) {
   case 1: console.log("start trace"); break; 
   case 2: alert("start trace"); break;
  }
  //--- pNumbers ---
  
  pNumbers=Trim(pNumbers);
  var  mNumbers=""
  if (pNumbers>"") { mNumbers = "," + pNumbers + ","; }
  //--- pFilter validation for eval --- // Assignment(=) is not allowed
  pFilter=Trim(pFilter);
  if (pFilter>"") {
    let s=ReplaceAll(pFilter,"===","♠♠♠"); 
    s=ReplaceAll(s,"==","♠♠"); 
    if (IndexAt(s,"=")>0) {
      s=NQ(s);
      if (s=="Error:♣ Not valid string termination") {
        if (pTrace==1) {console.log(s+" pFilter:"+pFilter);} 
        alert(s); 
        return null;
      } else {
        if (IndexAt(s,"=")>0) { 
          let x="Error: Assignment is not allowed (=/==)";
          if (pTrace==1) {console.log(x+", "+s);} 
          alert(x+"\n"+s);
          return null;
        }
      }
    }
  }
  
  var mCnt=0;

  var mObj=$(pSelector).filter(function(){
    var bo=true; 
    var s=""; var t=""; var ss="";
    mCnt++;
    //--- pNumbers --
    if (mNumbers>"") {
      t=","+mCnt+",";
      if (IndexAt(mNumbers,t)<0) { 
        bo=false; 
      }
    }
    //-----RESULT by pNumbers ---
    if (pNumbers>"" && pTrace>0) {
      if ( !bo || (bo && pFilter=="") ) {
        switch (pTrace) {
          case 1: console.log(mCnt+". Result by numbers: "+bo+", numbers:["+pNumbers+"]"); break; 
          case 2: alert(mCnt+". Result by numbers: " +bo+", numbers:["+pNumbers+"]"); break;
        }
      }
    }

    //-------- pFilter ----
    if (bo && pFilter>"") {
      var cPrefix="{:"; var cSufix="}";
      var p1=0; var p2=0; var p3=0;
      var t1=""; var t2=""; var t3=""; var t4=""
      var r1=""; var r2="";
      var lenP=Len(cPrefix); var lenS=Len(cSufix);
      s=pFilter; ss=s;
      p1=IndexAt(s,cPrefix);
       
      while (p1>=0) {
        r1=""; p2=IndexAt(s,cSufix,p1);
        if (p2>=0) {
          t1=Sub(s,p1,p2+1)  //{:css.color} //{:html}
          t2=Sub(t1,lenP); //css.color} //html}
          t2=Sub(t2,0,Len(t2)-lenS); //css.color //html
          t2=Lower(t2);
          p3=IndexAt(t2,".");
          if (p3>0) {
            t3=Sub(t2,0,p3);  //css
            t4=Sub(t2,p3+1);  //color
            r1='$(this).'+t3+'("'+t4+'")';  //$(this).css("color")
            if (t3=='attr' && t4=='style') {
              r1='NormStyle(String($(this).attr("style"))';//exception for attr.style, because jQuery in runtime change attr style
            }
          } else {
            r1='$(this).'+t2+'()';  //html -> $(this).html()      
            if (t2=="data") {r1='JSON.stringify('+r1+')';} //exemption for data -> JSON.stringify( $(this).data() )
          }
        }
        if (t1>"" && r1>"") {s=ReplaceAll(s, t1, r1);}
        //--- evaluate only in trace mode for debug ---
        if (pTrace>0) {  
          r2=eval(r1);
          ss=ReplaceAll(ss,t1,"'"+r2+"'");
        }  
        //---  next iterate --- 
        p1=IndexAt(s,cPrefix,p1+2); 
      } 
      //  --- trace1 ---
      if (ss>"" && pTrace>0) {
        switch (pTrace) { 
          case 1: console.log(mCnt+". "+ss); break; 
          case 2: alert(mCnt+". "+ss); break; 
        }
      }
      //--- evaluate ---
      bo=eval(s);
      // --- trace2 ---
      switch (pTrace) {
        case 1: console.log(mCnt+". FILTER: "+bo+", [:"+s+"]"); break; 
        case 2: alert(mCnt+". FILTER: "+bo+"\n ["+s+"]"); break; 
      }
    }
    //--- RESULT ---
    return bo;
  })

  switch (pTrace) {
    case 1: console.log("end trace"); break; 
    case 2: alert("end trace"); break;
  }
  return mObj;   
}


$(document).ready(function(){
  $("button").click(function(){
    var mObj=Element("body p a",
                     "{:css.color}==RGB('#ff00') && {:css.font-size}=='16px' && 'href='+{:attr.href} > '' ",
                     "2,3"
                    );
    if (!$.isEmptyObject(mObj)) {mObj.hide();}  // or mObj.css('display','none')
  /* 
    // --- hidden element only from selector ":hidden"
    mObj=Element('a:hidden');
    if (!$.isEmptyObject(mObj)) {mObj.show();}
  */
  
  /*
   //css.
    {:css.color} -> $(this).css("color")
    {:css.font-size} -> $(this).css("font-size")
    {:css.display}-> $(this).css("display")
   //attr.
    {:attr.href} -> $(this).attr("href")+"]"+
  * {:attr.style} -> NormStyle(String($(this).attr("style"))
    {:attr.id} -> $(this).attr("id")
    {attr.class -> $(this).attr("class")
   //spec
    {:html} -> $(this).html()
    {:index} -> $(this).index()
  * {:data} -> JSON.stringify($(this).data())
    {val} -> $(this).val()) // for value //or prop.value
   //prop    
    {:prop.checked} -> $(this).prop("checked")
    {:prop.selected} -> $(this).prop("selected")
    {:prop.selectedIndex} -> $(this).prop("selectedIndex")
    {:prop.disabled} -> $(this).prop("disabled")
   //comment 
    prop() for:  
      disabled,checked,selected,value,selectedIndex,tagName,nodeName,nodeType,ownerDocument,defaultChecked 
    val() for value 
  */

  });
});
      
</script>
</head>
<body>

<h2>jQuery.Element() for filtering "any"</h2>
<p>
  <a id="1" href="?m=1" style="color:#ff0000;font-size:16px;" class="alpha" data-x="123" data-y="123">1. ALPHA</a>
  , <a id="2" style="color:#ff0000;font-size:16px;">2. BETA </a>
  , <a id="3" href="?m=3" style="font-size:16px;">3. GAMMA</a>
</p>
<a id="4" href="?m=4" style="font-size:14px;">END</a>
<button>Click me</button>

</body>
</html>
0
Francisco On

You must enable plugin state and set state key in your jsTree config, for remembering the last selected item:

var jstree = $('#jstree').jstree({
            'core' : {
                'state': {
                    'key': 'jsTree_categories'    
                },
                'data' : {
                    'url' : '/admin/catalog/categories',
                    'data' : function (node) {
                        return { 'id' : node.id };
                    }
                }
            },
            'plugins': ['state'],
        }).on('select_node.jstree', function (event, data) {
            event.preventDefault();
            if (data && data.selected && data.selected.length) {
                selectedNode = data.instance.get_selected(true)[0];
                // make something  with selectedNode object
            } else {
                return false;
            }
        });