JStree open all parent nodes on load - javascript

So,
Here is a source
<ul>
<li id="1">
<a href="#">
Product root
</a>
<ul>
<li id="2">
<a href="#">
Electronicis
</a>
<ul>
<li id="445">
<a href="#">
Computers
</a>
<ul>
<li id="446">
<a href="#">
SSD
</a>
</li>
</ul>
<ul>
<li id="447">
<a href="#">
GPU
</a>
</li>
</ul>
<ul>
<li id="448">
<a href="#">
MoBo
</a>
</li>
</ul>
</li>
</ul>
<ul>
<li id="449">
<a href="#">
Navigation
</a>
</li>
</ul>
</li>
</ul>
<ul>
<li id="3">
<a href="#">
Whatever
</a>
</li>
</ul>
</li>
</ul>
Nothing fancy just couple of nested lists...
And here is my load script for jsTree
$("#jsTreeContainer")
.jstree({
"plugins": ["themes", "html_data", "ui" , "search"]
})
.bind("select_node.jstree", function(event, data) {
var selectedObj = data.selected;
alert(selectedObj.attr("id"));
})
.delegate("a", "click", function (event, data) { event.preventDefault(); });
});
What I would like to accomplish now is, to open node "Navigation" (id: 449) on page load. I've tried initally_open, initally_select parameters with no luck, I've even tried fiddling with search plugin, again no luck.
Has anyone managed to accomplish this, and how?
This must be a very common request but I can't find a solution for it.
I'm using master branch from gitHub, here... https://github.com/vakata/jstree
Cheers,
T.

You can try using $(treeid).jstree('open_node',id);
$("#tree").bind("open_node.jstree", function (event, data) {
if((data.inst._get_parent(data.rslt.obj)).length) {
data.inst._get_parent(data.rslt.obj).open_node(this, false);
}
});
see this for more details
jsTree Open a branch

Dont know if it helps. But here's what I do:
function openNode(tree, nodeId) {
$(tree).jstree("select_node", "#" + nodeId);
$(tree).jstree("toggle_expand", "#" + nodeId);
}
Just pass the jsTree DOM-element and the ID (449) to the function.

Related

Loop through DOM elements with JQuery to assign a click handler

I need to loop through the DOM with JQuery, and add a click handler to multiple parent elements that contain a child that will also be given a slideToggle(). I have the logic working fine when I add the click handlers manually, but now I need to be able to dynamically do this to multiple parent elements.
Here is my HTML:
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
Basically, you click on .sub-menu-link to slideToggle() .sub-menu-list.
Here is the JS that I have working so far. It targets the id's manually currently, which feels gross:
$('#sub-menu-link-1').click(function() {
$('#sub-menu-list-1').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
$('#sub-menu-link-2').click(function() {
$('#sub-menu-list-2').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
My apologies if this is something very apparent to do in JQuery. I am not at all familiar with it, and it just so happens to be a requirement of this project.
you could simply use below code.
select all list items with class name and add listener. click will be attached to all elements
$('.sub-menu-link').click(function() {
$(this).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
You already have classes, so just use them instead of the ids: use this to refer to the clicked element, .next() to get the next sibling (the li.sub-menu), and .find('.sub-menu-list') to get to the ul you want to toggle:
$('.sub-menu-link').click(function() {
const $subMenuList = $(this).next().find('.sub-menu-list');
console.log($subMenuList.text().trim());
$subMenuList.slideToggle(100);
$(this).toggleClass('active-menu-link');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
You can use jQuery's .next() like so:
$(".sub-menu-link").click(function() {
$(this).next(".sub-menu-link").slideToggle(100);
$(this).toggleClass("active-menu-link");
})
Or you can chain them and use ES6 arrow syntax to make it more concise:
$(".sub-menu-link").click(() => $(this).toggleClass("active-menu-link").next(".sub-menu-link").slideToggle(100));
You should try this if your list and link ids have similiar pattern as in the code you have shown
$('#sub-menu-link').click(function() {
var id = $(this).attr("id").replace("sub-menu-link", "")
$('#sub-menu-list-'+ id).slideToggle(100);
$(this).toggleClass('active-menu-link');
});

Dropdown menu flashes and disappeared on mobile only

I have a sub-menu inside the navbar under the Services nav-item.
The expected behavior is once the Service is clicked, the sub-menu shows up. The actual behavior is: once the Service is clicked, the sub-menu flashes and disappears.
<nav id="main-menu">
<ul class="sf-navbar">
<li>
<a href="#home">
<div data-i18n="nav.home">Home</div>
</a>
</li>
<li>
<a href="#">
<div data-i18n="nav.services.title">Title</div>
</a>
<ul>
<li>
<a href="#service">
<div data-i18n="nav.services.ourservices">Our Services</div>
</a>
</li>
<li>
<a href="#how">
<div data-i18n="nav.services.howwework">How We Work</div>
</a>
</li>
<li>
<a href="#areascontainer">
<div data-i18n="servicearea.title">Service Area</div>
</a>
</li>
<li>
<a href="#why">
<div data-i18n="why.title">Why Choose Us</div>
</a>
</li>
</ul>
</li>
.....
</nav>
JS code:
wei.header = {
init: function(){
wei.header.superfish();
},
superfish: function() {
$( main_menu ).superfish({
popUpSelector : 'ul',
delay : 250,
speed : 350
});
},
...
I have tried to debug it, but have no clue where to start.
Here is the code that I am working on.
http://weistudio.com.au/
For some reason, SuperFish fails here on touchEnd event and only for the menu shown when you at the very top of the page (it works if you scroll page a bit - there is a clone of this menu).
To prevent it you could use something like <a href="#" onTouchEnd="(function (e) {e.preventDefault()})(event)">.
Or move it to an external method and use like this (as you using jQuery already):
$('.header-container').on('touchend', '.sf-with-ul', function (e) {e.preventDefault()})

.click() functionality when clicking elements

Basically i want to click on a tab and a drop down menu appears then when you re-click the same tab or any of the others I want it to hide that tab/show the other tab if clicked on the same/other tab.
I tried
$('.click').click(function() {
$(this).find('.sub-nav-list').toggleClass('active');
});
and tried
$('.click').click(function() {
$('.sub-nav-list').removeClass('active');
$(this).find('.sub-nav-list').toggleClass('active');
});
but cant work it out! any insight? Thanks
html:
<nav class="secondary-nav">
<ul class="list clearfix">
<li class="leaders click">Leadership <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Management</li>
<li>Board of Directors</li>
</ul>
</li>
<li class="contact click">Contact Info <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Email Notification</li>
<li>Information Request</li>
</ul>
</li>
<li class="docs click">Documents <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Governance Documents</li>
<li>Press Release</li>
<li>Reports & Presentations</li>
<li>Sec Filings</li>
<li>Frenquently Asked Questions</li>
<li>Tax Information</li>
</ul>
</li>
<li class="research click">Research <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Dividends and Distributions</li>
<li>Stock Information</li>
<li>Analyst Coverage</li>
<li>Market Makers</li>
</ul>
</li>
</ul>
</nav>
I can see at least two possible issues there.
1) sub-nav-list is not a children of click element. If they are on the same level something like that might work:
$('.click').click(function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});
2) You have these elements generated dynamically - so you need use on with selector of any parent element that exists before you dynamically generate your sub-menus (let say nav-list):
$(".click").on("click", ".nav-list", function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});

How to add a submenu after X number of <li> with Javascript or Jquery?

I have in HTML
<div class="ktmsg">
<ul>
<li class="a1">
<a title="Link Tools" href="#"> … </a>
</li>
<li class="a2">
<a title="Link Tools" href="#"> … </a>
</li>
<li class="a3">
<a title="Link Tools" href="#"> … </a>
</li>
</ul>
</div>
What i want to do is to add after the second </li> an <ul>More</ul>
Final expected output should be
<div class="ktmsg">
<ul>
<li class="a1">
<a title="Link Tools" href="#"> … </a>
</li>
<li class="a2">
<a title="Link Tools" href="#"> … </a>
</li>
<ul> //Starting the sub-menu
More // The link that after i hover it will start showing the <li> starting from the third one
<li class="a3">
<a title="Link Tools" href="#"> … </a>
</li>
</ul>
</ul>
</div>
I am thinking that the javascript would look smth like this:
limenu = document.selectAll(.ktmsg)('<li>');
for(var i=1, i<2, i++)
remove.limenu
add.
.... And i am quite stuck, Please help, would be much appreciated.
Using jQuery
jQuery(function ($) {
var $lis = $('.ktmsg > ul > li');
var $a = $('<li>More</li>').insertAfter($lis.eq(1));
var $lefts = $lis.slice(2).hide();
$a.hover(function () {
clearTimeout($a.data('hoverTimer'));
$lefts.show();
}, function () {
var timer = setTimeout(function () {
$lefts.hide();
}, 200);
$a.data('hoverTimer', timer);
});
$lefts.hover(function () {
clearTimeout($a.data('hoverTimer'));
}, function () {
var timer = setTimeout(function () {
$lefts.hide();
}, 200);
$a.data('hoverTimer', timer);
});
})
Demo: Fiddle
With jQuery to add this:
<ul>More</ul>
after second li you need:
$( 'li:eq(1)' ).after( '<ul>More</ul>' );
I've created a fiddle of how this could work using jQuery. Pretty simple really, you just hide the sub menu using CSS and then show/hide it as needed using jQuery when "More" is being hovered over. I've used fadeIn() and fadeOut() but you could just as easily use hide() and show() if you don't need the animations. I've restructured your HTML slightly so if you use my solution use my new HTML.

how to create and display external template in html page using Backbone.js?

I am very new to backbone.js ,I am practicing to display templates in my 'index.html' page.
I have created a template in In 'index.html' and displaying it in a using view.It works fine with single html file i.e. everything is kept in 'index.html'.But now i want those templates to store in other file and display in my 'index.html'.
I tried to find some solution ,but all were confusing.
SO please, can anyone tell me how should i do it.
Following is my template to be display(currently in a 'index.html'):
<script type="text/template" id="cloudtag_tempalte">
<center>
<ul class="cld" ">
<li > <a class="tag1" id="t1" href="https://www.google.com" target="_blank"></a> </li>
<li > <a class="tag2" id="t2" href="#">sachin </a> </li>
<li > <a class="tag3" id="t3" href="#">Ramesh </a> </li>
<li > <a class="tag1"id="t33" href="#">Tendulkar</a></li>
<li > <a class="tag5"id="t34" href="#">Cricket</a></li>
<li > <a class="tag2"id="t35" href="#">Test</a></li>
</ul><!--/cld-->
</center>
</script>
Following is a div in which it is displayed(in same 'index.html'):
<div class="tags" id="myTags"> </div><!--/tags-->
and following is script of view(in same file 'index.html'):
<script type="text/javascript">
var cld_view=Backbone.View.extend({
initialize: function(){
},
render: function(){
// Compile the template using underscore
var template = _.template( $("#cloudtag_tempalte").html(), {} );
// Load the compiled HTML into the Backbone "el"
this.$el.html( template );
}
});
var cloudtag=new cld_view({el:$("#myTags")});
cloudtag.render();
</script>
So please, suggest me changes to be made to make this template external .
Thanx in advence . . .
Simplest way would be to use underscore.js which is suggested by backbone.js itself. If you want to go one step higher, then you could go for templating engines like :
Handlebars
Marionette
and so many others..
Personally i prefer Underscore.js. An example would be as follows :
Using underscore :
$.get('templates/your-template-file.html', function (data) {
template = _.template(data, {
data: data_you_want_to_pass_to_template
});
this.$el.html(template);
}, 'html');
As for extending this to your code :
var cld_view=Backbone.View.extend({
el:'template_div',
initialize: function(){
},
render: function(){
// Compile the external template file using underscore
$.get(App.baseUrl + 'templates/your-template-file.html', function (data) {
template = _.template(data, { });
this.$el.html(template);
}, 'html');
}
});
App.baseUrl - My full path of the project root which is set as config. You can either resuse this or remove this. But just make sure, you point to the exact template folder.
You need to specify your el tag, else you would need to hard-code the div you are focusing to render the template.
Cheers
I attach my compiled templates to the object itself. You can append extra templates to the main template
<script type="text/javascript">
var cld_view=Backbone.View.extend({
//compiled templates
template : _.template($("#cloudtag_tempalte").html()),
template2 : _.template($("#another_template").html()),
initialize: function(){
},
render: function(){
// Load the compiled HTML into the Backbone "el"
this.$el.html( this.template);
//add other templates to the main one.
this.$el.find('someSelector').append(template2 );
}
});
var cloudtag=new cld_view({el:$("#myTags")});
cloudtag.render();
</script>
.Finaly i found the solution to my problem after struggling 2 days to create and display external templates in my 'index.html' page using backbone.js.
For that i used underscore js.
Here is the process that i followed to successfully run my application:
i followed the tutorial mentioned in this video.
I created a separate template file called 'CloudTagTemplate.html' and pasted the html code mentioned in the above question in this file and saved in Templates folder where i am going to store other templates later on:
my CloudTagTemplate.html:
<center>
<ul class="cld" ">
<li > <a class="tag1" id="t1" href="https://www.google.com" target="_blank"></a> </li>
<li > <a class="tag2" id="t2" href="#"></a> </li>
<li > <a class="tag3" id="t3" href="#"></a> </li>
<li > <a class="tag2" id="t4" href="#"></a> </li>
<li > <a class="tag4" id="t5" href="#"></a> </li>
<li > <a class="tag1" id="t6" href="#"></a> </li>
<li > <a class="tag1" id="t7" href="#"></a> </li>
<li > <a class="tag5"id="t8" href="#"></a> </li>
<li > <a class="tag2"id="t9" href="#"></a></li>
<li > <a class="tag1"id="t10" href="#"></a></li>
<li > <a class="tag3"id="t11" href="#"></a></li>
<li > <a class="tag4"id="t12" href="#"> </a></li>
<li > <a class="tag1"id="t13" href="#"></a></li>
<li > <a class="tag5"id="t14" href="#"></a></li>
<li > <a class="tag1"id="t15" href="#"></a></li>
<li > <a class="tag2"id="t16" href="#"></a></li>
<li > <a class="tag1"id="t17" href="https://www.google.com"></a></li>
<li > <a class="tag2" id="t18" href="#"></a></li>
<li > <a class="tag3"id="t19" href="#"></a></li>
<li > <a class="tag2"id="t20" href="#"></a></li>
<li > <a class="tag4"id="t21" href="#"></a></li>
<li > <a class="tag1"id="t22" href="#"></a></li>
<li > <a class="tag1"id="t23" href="#"></a></li>
<li > <a class="tag5"id="t24" href="#"></a></li>
<li > <a class="tag2"id="t25" href="#"></a></li>
<li > <a class="tag1"id="t26" href="#"></a></li>
<li > <a class="tag5"id="t27" href="#"></a></li>
<li > <a class="tag3"id="t28" href="#"> </a></li>
<li > <a class="tag1"id="t29" href="#"></a></li>
<li > <a class="tag3"id="t30" href="#"></a></li>
<li > <a class="tag1"id="t31" href="#"></a></li>
<li > <a class="tag4"id="t32" href="#"></a></li>
<li > <a class="tag1"id="t33" href="#"></a></li>
<li > <a class="tag5"id="t34" href="#"></a></li>
<li > <a class="tag2"id="t35" href="#"></a></li>
</ul><!--/cld-->
</center>
Then i created a CloudTagView.js in View Folder:
my CloudTagView.js:
var cld_view=Backbone.View.extend({
el:'#myTags',
initialize: function(){
},
render: function(){
var that=this;
$.get( '/multipage/Backbone/Templates/CloudTagTemplate.html', function (data) {
template = _.template(data, { });
that.$el.html(template);
}, 'html');
}
});
var cloudtag=new cld_view();
cloudtag.render();
note that -
var that=this;
is important to put over there ,since we are defining anonymous function $.get()
and at last i linked all these required files in my 'index.html' as:
<script src="Backbone/Views/CloudTagView.js"></script>
<script src="Backbone/Views/LoginModalView.js"></script>
and finally it worked fine as i wanted. .
Thanx to #Roy M J

Categories