I'm new to jquery, ajax and jstree. I'm using jstree to have my <ul> elements look like a tree structure.
I have the <ul> under a div tag of id = "container". When I execute the html file, the div (id = "container") is passed to jstree function as follows:
$(function() {
$('#container').jstree();
});
My html snippet is as follows:
<div id="container">
<ul id = "treeNodes">
<li>Parent
<ul>
<li>Child1
<ul>
<li>child2-1</li>
<li>child2-2</li>
<li>child2-3</li>
<li>child2-4</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
The tree structure is being displayed fine.
I'm trying to write a jquery function that gets the li element's name as an argument.
For example: when I click Parent, the function should recieve "Parent" as an argument or when I click child2-3, the function should get "child2-3" as the argument.
I attempted to create that function, but it doesn't seem to work. Here's my attempt -
$("#treeNodes li").click(function() {
console.log("hello");
console.log(this.innerHTML);
});
The control seems to go to the function calling the jstree(), but the other function doesn't seem to work.
Any help or tips would be appreciated. Thanks in advance.
Making your structure into a JSTree causes new HTML to be created and those new elements have custom classes and new APIs. So, you have to read the documentation to understand how to use the new structure.
If you look at this documentation page, you'll see an example of what you are after, which hinges on a custom changed event. I've reproduced that example, customizing it for your HTML and console output.
$(function() {
$('#container')
// listen for the custom "changed" event on any jstree
.on('changed.jstree', function (e, data) {
// When you click on a JSTree the event appears to fire on the entire tree
// You'll have to iterate the tree nodes for the selected one.
var i, j, r = [];
for(i = 0, j = data.selected.length; i < j; i++) {
r.push(data.instance.get_node(data.selected[i]).text);
}
console.clear();
console.log('Selected: ' + r.join(', '));
})
// create the instance
.jstree();
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.5/jstree.min.js"></script>
<div id="container">
<ul id = "treeNodes">
<li>Parent
<ul>
<li>Child1
<ul>
<li>child2-1</li>
<li>child2-2</li>
<li>child2-3</li>
<li>child2-4</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
I have read the documentation from the jstree page: https://www.jstree.com/
There is a class from the jstree called jstree-children, from that class you can obtain the value from the list, like this:
$(document).on('click', '.jstree-children ul li', function (e) {
console.log($(this).html());
});
Try this: https://jsfiddle.net/Mantixd/0jwpz2r1/
Related
I want to hide a single item unless a category is selected. I'm using the filteringStart callback to do this. How do I get the active categories array from the filterizr object?
It doesn't look like there's a public method to get active filters in the Filterizr library. It isn't too difficult to write the JavaScript required to figure it out though.
Using one of their examples, the html would look as follows:
<ul class="nav nav-gallery filters-filteringModeSingle" id="filteringModeSingle">
<li class="filtr-button filtr" data-fltr="all">All</li>
<li class="filtr-button filtr" data-fltr="green">Green</li>
<li class="filtr-button filtr filtr-active" data-fltr="orange">Orange</li>
<li class="filtr-button filtr" data-fltr="purple">Purple</li>
<li class="filtr-button filtr" data-fltr="mix">Mix</li>
</ul>
You could get an array of selected values as follows:
var selected = $.map($(".filtr-active").toArray(), function(el, i) {
return $(el).data("fltr");
});
To do something based on a specific value being selected, you could do the following:
if (selected.indexOf("green") !== -1) {
console.log("You selected green!");
}
I hope that makes sense!
Edit:
You could get the unselected filters by tweaking the selector.
var notSelected = $.map($(".filtr:not(.filtr-active)").toArray(), function (el, i) {
return $(el).data("fltr");
});
try this code
$(function () {
console.log($(this)[0].getAttribute("data-filter"));
});
I have a piece of code that closes a drop down menu, if you click somehwere on the document other than the opened menu itself. I would like to get rid of jQuery, but I'm not sure how to translate this code to pure javascript.
$(document).ready(function() {
$(document).click(function(event) {
if (!$(event.target).closest('li.main').length) {
if ($('li.main').is(":visible")) {
$('#dropdown').hide();
}
}
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="main" onclick="ToggleMainMenu();"><span>All categories</span>
</li>
<li> Item 1
</li>
<li> Item 2
</li>
<li> Item 3
</li>
</ul>
Your click handler is doing the following:
if ( clicked object is a descendent of "li.main" AND "li.main" is visible)
hide "#dropdown"
If you add the onclick attribute to the node "li.main" or one of its descendents - as you added ToggleMainMenu in your comment - then you guarantee:
- The clicked item is "li.main" or is a descendent of "li.main"
- "li.main" is visible (since you cannot click an invisible item)
At this point you do not need comparisons any more and you only need to hide "#dropdown" in ToggleMainMenu function's body. Copying from javascript hide/show element :
document.getElementById("dropdown").style.display = "none";
p.s. I used jquery selector notation for brevity
Sometimes it's easier than you think. I found a solution:
document.addEventListener("DOMContentLoaded", function (event) {
document.addEventListener('click', function (e) {
var mainMenu = document.getElementById('main');
if (!mainMenu.contains(e.target)) {
document.getElementById('dropdown').style.display = 'none';
}
}, false);
});
I didn't know about contains.
I am currently developing a program. It includes a 3 option navigation bar. It uses <li> and does not have id's, when i try to add id's to them it messes up the order, and doesent even work with a click! Im starting to loose faith with it.. can anyone help me on this one,
my GOAL is to have it alert different things on different clicks, so than I could link different html pages,
fiddle used HERE.
<ul class="ui-module menu-selector" id="menu-selector">
<li>Home</li>
<li class="js-is-active">Notif's</li>
<li>Profile</li>
</ul>
Since you don't have ids, I suppose that childNodes property will help a lot.
For example, you can use:
var lis = document.getElementById('menu-selector').childNodes;
// or you can select lis directly...
// var lis = document.querySelectorAll('#menu-selector li');
Array.prototype.slice.call(lis)
.forEach(function(li) {
// do something... like
li.onclick = function () {
console.log(this);
}
});
Note: childNodes (or querySelectorAll return) is NodeList type, and I use Array.prototype.slice.call() in order to use forEach() method on it.
See childNodes for more details.
if you don't want to have ids on your li elements for some reason you can use the following logic to select active li:
$("#menu-selector li.active").on("click", function(){
alert($(this).text())
});
I added id's for you, not sure what you meant by it messing up the order.
HTML
<div class="ui-items">
<header class="ui-module app-header">VoiceBox <i class="entypo-user-add"></i>
<i class="entypo-pencil"></i>
</header>
<div id="outer">
<ul class="ui-module menu-selector" id="menu-selector">
<li id="home_li">Home</li>
<li id="notif_li" class="js-is-active">Notif's</li>
<li id="profile_li">Profile</li>
</ul>
</div>
</div>
Javascript
var listItem = $('#menu-selector > li');
$(listItem).click(function() {
$(listItem).removeClass('js-is-active');
$(this).toggleClass('js-is-active');
});
$('#home_li').click(function(){
alert('home clicked')
})
$('#notif_li').click(function(){
alert('notifs clicked')
})
$('#profile_li').click(function(){
alert('profile clicked')
})
Fiddle http://jsfiddle.net/1swep9oq/2/
I tried asking this before, but I guess I wasn't specific enough. Suppose I have HTML code that looks like this. How do I ONLY target the tags within the the horizontalNAV using pure JavaScript? Okay I know I could do this using jQuery like this...
<script type="text/javascript">
$(document).ready(function(){
$('#horizontalNAV li a').click(function(){
//jQuery code here...
});
});
</script>
However I do NOT want a jQuery answer, because I want to know how you target ('#horizontalNAV li a') using pure javaScript.
or you can tell me how to do it for the verticalNav portion, either way I'll get it, if I see an example or if its explained to me. If I'm not mistaken you would have to use the document.querySelectorAll method, if so, how does that work in the above example.
<div id="wrapper">
<div id="horizontalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
<div class="sideBar">
<div class="verticalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
</div>
</div>
Without jQuery it would look like this
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
var elems = document.querySelectorAll('#horizontalNav li a');
for (var i = elems.length; i--;)
elems[i].addEventListener("click", handler, false);
}, false);
function handler(event) {
//javascript code here...
this.style.color = 'red';
}
</script>
FIDDLE
If #horizontalNAV is a UL or OL element, then it can only have LI element children so you can skip that part of the selector. The following doesn't use querySelectorAll so will work in browsers, that don't support it:
<script>
window.onload = function() {
var list = document.getElementById('#horizontalNAV');
var links = list && list.getElementsByTagName(‘a’);
if (links) {
for (var i=0, iLen=links.length; i<iLen; i++) {
links[i].onclick = listener;
}
}
}
function listener() {
// do stuff
}
</script>
If you want to include more than one listener for an event, you’ll need to use addEventListener or some other strategy instead of assigning the function directly to the element, but in most cases only one listener is required per event type and keeping things simple has its benefits.
The listener function is declared outside the function doing the assignment to avoid a closure and circular reference, so it should have less chance of creating a memory leak.
I've tried using the jQuery.mmenu-plugin, found here http://mmenu.frebsite.nl/. It works great with pre-defined lists, but how do I handle lists which are updated with jQuery?
Here's an example of an initialized mmenu:
<nav id="menu" class="mm-menu mm-horizontal mm-ismenu mm-hasheader mm-hassearch mm-current mm-opened">
<div class="mm-panel mm-opened mm-current" id="mm-m1-p0">
<ul id="list" class="mm-list">
<li id="1"><a>item 1</a></li>
<li id="2"><a>item 2</a></li>
<li id="3"><a>item 3</a></li>
</ul>
</div>
</nav>
Then I append items to the list the following way:
$("#list").append('<li id="4"><a>"item 4"</a></li>');
The appended (fourth) li-item won't get the same behavior as the li-items defined before initialize the mmenu. This means that items added after the initialization won't work with the search field, as an example.
Is there a way to reinitiate the mmenu or to update the li-items connected to it?
Having looked through the Plugin's (mmenu.js) code briefly, you could alter the JavaScript to listen to the DOM for new <a[href="#id"']> elements:
Adjust:
click( $('a[href="#' + id + '"]', that.$menu), function( e ) {
$opening.trigger( evt );
}
to:
click( $(document).find('a[href="#' + id + '"]', that.$menu ), function( e ) {
$opening.trigger( evt );
}
This'll make sure that the $menu can be used for any Loaded & Non-Loaded DOM elements.
Alternatively, You could reinitialise it:
var $Mmenu = $('#menu'),
$Container = $Mmenu.parent(),
$List = $('#menu #list');
$List.append('<li id="4"><a>"item 4"</a></li>');
var newHtml = $Mmenu.html();
$Mmenu.remove();
$Container.append( newHtml );
$(document).find('#menu').mmenu();
The instance of the plugin is attached to the menu. The counter addon registers an update function on the plugin that is used by the search addon to affect changes in other plugins. e.g. when you type into the search box, it will prune the visible children of the submenus and update the counter.
To wire into this you need the instance of the plugin that is attached to your menu element (because there is an array with the registered update functions)
So, if you have an element like this:
<nav id="menu"></nav>
that you initialized via:
$("#menu").mmenu();
then call the _update() method on the plugin object:
$("#menu").data('mmenu')._update();
'menu' is the id of my menu element
'mmenu' is the name of the plugin
_update() is the magic function that will call all the update functions registered in the updates array