I have a small problem with a "treeview" done in JS
The treeview works fine, but now I need to apply some restrictions.
The treeview has the following structure:
Parent> node> sunode
The restriction is that I can not select more than one "node" within the "parent", and in turn, within its "node", I can not select more than one "subnode". That is, I can only mark between each parent node a checkbox.
If I set another checkbox inside the "subnode", you have to deselect the checkbox that had and mark the new one (like a radio button).
And the same with the "node", can only have marked a node within each "parent"
<div id="treeview-container">
<ul>
<li>Parent 1</li>
<li>Parent 2
<ul>
<li>node 2.1</li>
<li>node 2.2
<ul>
<li data-value="2.2.1">subnode 2.2.1</li>
<li data-value="2.2.2">subnode 2.2.2</li>
<li data-value="2.2.3">subnode 2.2.3</li>
</ul>
</li>
<li>node 2.3</li>
</ul>
</li>
<li>parent 3
<ul>
<li data-value="3.1">node 3.1</li>
<li data-value="3.2">node 3.2</li>
</ul>
</li>
</ul>
</div>
Here the JS:
(function( $ ){
var plugin = {
name: 'TreeView',
version: '1.0.0'
}
var defaults = {
debug : false,
autoExpand : false,
css : {
list : 'fa-ul',
listItem : 'fa-li fa',
collapsed : 'fa-caret-right',
expanded : 'fa-caret-down'
}
}
var settings;
var debug, me = null;
function __changeHandler( e ) {
var currentTarget = $(this);
var isChecked = currentTarget.is(':checked');
debug.log(currentTarget);
debug.log("Checked ", isChecked)
if (!isChecked) {
debug.log('Uncheck all childs');
currentTarget.parent()
.find('input.tw-control')
.prop('checked', false);
}
if (isChecked) {
debug.log('Check my parents tree');
currentTarget.parents('li')
.find('>input.tw-control')
.prop('checked', true);
}
_toggleCollapse( currentTarget );
me.trigger('treeview.change', currentTarget, me);
}
function _toggleCollapse ( element ) {
debug.log("Toggle collapse");
var chk = $('input[type="checkbox"]:checked');
if (chk.is(':checked')) {
debug.log('Open checked branchs');
chk.parent()
.find('>ul.collapse')
.collapse('show')
.parent()
.find('>i.fa-li')
.removeClass(settings.css.collapsed)
.addClass(settings.css.expanded);
}
if (!element.is(':checked')) {
debug.log('Hide branch');
element.parent()
.find('ul.collapse')
.collapse('hide')
.parent()
.find('i.fa-li')
.removeClass(settings.css.expanded)
.addClass(settings.css.collapsed);
}
}
function _init() {
debug.log( "Initializing plugin" );
me.on('change', 'input.tw-control', __changeHandler);
debug.log("Collapsing tree");
me.find('>ul')
.addClass(settings.css.list)
.find('ul')
.addClass('collapse ' + settings.css.list)
.parent()
.prepend(
$('<i></i>').addClass(settings.css.listItem + ' ' +
settings.css.collapsed)
);
if (settings.autoExpand) {
me.find('ul.collapse').collapse('show');
}
debug.log("Adding checkbox");
me.find('li').each(function( index, element ) {
var elmt = $(element);
var chk = $('<input/>').prop('type', 'checkbox')
.prop('class', 'tw-control')
.prop('value', elmt.attr('data-value'));
debug.log("Checking if the element is selected");
var isChecked = elmt.attr('data-checked');
elmt.prepend(chk);
if ( isChecked ) {
debug.log('Toggle checkbox');
chk.prop('checked', true);
chk.trigger('change');
}
});
}
function _fill( data ) {
$( data ).each(function (index, element) {
me.find('input[value="' + element + '"]')
.prop('checked', true)
.trigger('change');
});
}
var publicMethods = {
init : function( options ) {
me = this;
settings = $.extend( defaults, options );
debug = $.Logger(settings.debug, plugin);
_init();
debug.log('Ready');
_fill ( options.data );
return this;
},
selectedValues: function() {
debug.log("Getting selected values");
var chk = me.find('input[type="checkbox"]:checked');
var output = [];
chk.each(function(index, item) {
var item = $(item);
if(typeof item.parent().attr('data-value') !== typeof undefined) {
output.push(item.attr('value'));
}
})
return output;
}
}
$.fn.treeview = function (options) {
if ( publicMethods[options] ) {
return publicMethods[ options ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof options === 'object' || ! options ) {
// Default to "init"
return publicMethods.init.apply( this, arguments );
} else {
$.error( 'Method ' + options + ' does not exist on jQuery.treeview' );
}
}
}( jQuery ));
$('#treeview-container').treeview({
debug : true,
data : ['3.2', '2.2.3']
});
http://codepen.io/vilacactus/pen/BpMjOp?editors=1010#0
You may listen for the treeview.change event and set checked to false for all the siblings:
$('#treeview-container').treeview({
debug : false,
data : ['3.2', '2.2.3']
});
$('#treeview-container').on("treeview.change", function (e, ele) {
if ($(ele).parents('ul').length > 1) { // not on root elements
$(ele).closest('li').siblings().find(':checkbox').prop('checked', false);
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="http://www.jqueryscript.net/demo/Checkable-Collapsible-jQuery-Tree-View-Plugin-Treeview/dev/logger.js"></script>
<script src="http://www.jqueryscript.net/demo/Checkable-Collapsible-jQuery-Tree-View-Plugin-Treeview/dev/treeview.js"></script>
<div id="treeview-container">
<ul>
<li>Parent 1</li>
<li>Parent 2
<ul>
<li>node 2.1</li>
<li>node 2.2
<ul>
<li data-value="2.2.1">subnode 2.2.1</li>
<li data-value="2.2.2">subnode 2.2.2</li>
<li data-value="2.2.3">subnode 2.2.3</li>
</ul>
</li>
<li>node 2.3</li>
</ul>
</li>
<li>Parent 3
<ul>
<li data-value="3.1">node 3.1</li>
<li data-value="3.2">node 3.2</li>
</ul>
</li>
</ul>
</div>
Related
I'm working with the Docsify.js markdown parser framework and it automatically creates a sidebar from the headings in a document (unless you manually create a sidebar).
I have some CSS that numbers list elements, but want to convert it to JS as there are rendering issues when classes are added as the page scrolls (ie. adding .active).
Originally, I was trialling using this snippet but it doesn't output it as an auto incrementing hierarchical number system:
The sidebar that is generated is in the following format:
var li = document.getElementsByTagName( 'li' );
for( var i = 0; i < li.length; i++ ) {
var prefix = '1.';
li[i].innerHTML = prefix + ' Title ' + i;
prefix++;
}
<aside class="sidebar">
<div class="sidebar-nav">
<ul>
<li>Title 1</li>
<ul>
<li>Title 2</li>
<ul>
<li>Title 3</li>
<ul>
<li>Title 4</li>
<ul>
<li>Title 5</li>
<ul>
<li>Title 6</li>
</ul>
</ul>
</ul>
</ul>
</ul>
<li>Title 1</li>
<li>Title 1</li>
<ul>
<li>Title 2</li>
<li>Title 2</li>
<ul>
<li>Title 3</li>
<ul>
<li>Title 4</li>
<ul>
<li>Title 5</li>
<ul>
<li>Title 6</li>
</ul>
</ul>
</ul>
</ul>
</ul>
</ul>
</div>
</aside>
I understand the HTML structure isn't valid with <ul> being a descendant of an <ul> but this is the code that is outputted and I have no control over it.
However, I want to be able to number the headings with sections and sub-sections:
1. Title 1
1.1. Title 2
1.1.1. Title 3
1.1.1.1. Title 4
1.1.1.1.1. Title 5
1.1.1.1.1.1. Title 6
2. Title 1
3. Title 1
3.1. Title 2
3.2. Title 2
3.2.1. Title 3
3.2.1.1. Title 4
3.2.1.1.1. Title 5
3.2.1.1.1.1. Title 6
I am struggling to find a way to be able to target the first <li> (or the H1), and then being able to access the next <ul> via .nextElementSibling to continue the loop and prepend the numbering.
As far as I have gotten to at the moment is: document.querySelectorAll( 'div.sidebar-nav > ul' ) and it's not much to go on!
I think I'm really out of my depth for javascript here, and was hoping that I'd be able to get some help on being able to loop through the <li> and <ul> elements to prepend the numbers.
Following is JavaScript to apply nested index numbers. At max there are only 6 header tags, 6 levels, so we can use recursive solution:
let startLevel = 1;
let endLevel = 5;
function indexsify() {
let children = document.querySelectorAll('#sidebar > ul');
let numbers = new Array(7).fill(0);
let depth = 0;
children.forEach((element, index) => {
recurse(element, ++depth, numbers);
});
}
function recurse(element, depth, numbers) { //ul
let children = Array.from(element.children);
children.forEach((element, index) => {
if (element.localName.toUpperCase() === 'LI') {
numbers[depth]++;
addNumberString(element, depth, numbers);
} else if (element.localName.toUpperCase() === 'UL') {
if (depth < endLevel) {
recurse(element, depth + 1, numbers, startLevel);
numbers.fill(0, depth + 1); //reset all next numbers
}
}
});
}
function addNumberString(element, depth, numbers) {
let strNumber = "";
numbers.forEach((num, index) => {
if (index > depth || index <= startLevel) return;
strNumber += `${num}.`;
});
element.firstElementChild.innerText = strNumber +
element.firstElementChild.innerText;
}
indexsify();
ul,
li {
list-style-type: none;
}
<div id="sidebar">
<ul>
<li><a>Home</a></li>
<ul>
<li><a>Chapter a</a></li>
<ul>
<li><a> Section a</a></li>
<li><a>Section b</a></li>
</ul>
<li><a>Chapter b</a></li>
<li><a>Chapter c</a></li>
<ul>
<li><a>Section a</a></li>
<li><a>Section b</a></li>
<ul>
<li><a>Sub-section a</a></li>
</ul>
</ul>
<li><a>Chapter D</a></li>
</ul>
</ul>
</div>
Modify markdown itself: As per the Docsify plugin documentation there is no direct provision to influence the sidebar content. Your plugin uses hook.afterEach(function(html, next) and the sidebar is generated separately. So you are trying to manipulate generated sidebar also. You are trying to do similar operation two times.
Why not use hook.beforeEach(function(content) and manipulate markdown itself. That way you'll have to do the numbering operations only once.
Here is a demo site and the code sandbox link for following sample plugin that manipulates markdown content:
<!DOCTYPE html>
<html>
<body>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/docsify#4/themes/vue.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/docsify/themes/dark.css"
/>
<div id="app">Please wait...</div>
<script>
window.$docsify = {
el: "#app",
loadSidebar: true,
maxLevel: 4,
subMaxLevel: 5,
homepage: "readme.md"
};
</script>
<script>
//plugin
let myPlugin = function (hook, vm) {
hook.init(function () {
//remove '-' before Table of content entries
let customStyles = document.createElement("style");
customStyles.type = "text/css";
customStyles.textContent = `.app-sub-sidebar li::before {
content: '' !important;
padding-right: 4px;
float: left;
}`;
document.body.appendChild(customStyles);
});
//update markdown content before docsify parsing
hook.beforeEach(function (content) {
let lines = content.split("\n");
let numbers = new Array(6).fill(0);
let depth = 0;
lines.forEach((line, index) => {
let level = getLevel(line);
//if not a header continue to next line
if (level === -1) return;
if (level > depth) {
depth++; //increase depth
} else {
depth = level; //decrease depth
numbers.fill(0, depth + 1); //set all next depth to 0
}
numbers[depth]++;
let strNumber = "";
numbers.forEach((num, index) => {
if (index > depth || index < startLevel) return;
strNumber += `${num}.`;
});
if (depth < endLevel) {
lines[index] =
levels[level] + strNumber + line.substr(depth + 1, line.length);
}
});
//update original content
content = lines.join("\n");
return content;
});
let levels = ["# ", "## ", "### ", "#### ", "##### ", "###### "];
let startLevel = 1;
let endLevel = 4;
let regEx = new RegExp(`^#{1,${endLevel}}\\s+.*`);
function getLevel(line) {
if (!regEx.test(line)) return -1; //not a header line
if (line.startsWith(levels[0])) return 0; //h1
if (line.startsWith(levels[1])) return 1;
if (line.startsWith(levels[2])) return 2;
if (line.startsWith(levels[3])) return 3;
if (line.startsWith(levels[4])) return 4;
if (line.startsWith(levels[5])) return 5; //h6
}
};
window.$docsify.plugins = [myPlugin];
</script>
<script src="https://cdn.jsdelivr.net/npm/docsify#4"></script>
</body>
</html>
We need to override default CSS in hook.init(function ()) to remove leading - in table of contents.
Old answer: You can have numbers directly on anchors<a> tags :
.sidebar ul>li {
counter-increment: item;
}
.sidebar ul>li:first-child {
counter-reset: item;
}
.sidebar ul>li a::before {
content: counters(item, ".") " ";
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify#4/themes/vue.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify/themes/dark.css" />
<div id="app">Please wait...</div>
<script>
window.$docsify = {
el: "#app",
loadSidebar: false,
homepage: 'https://gist.githubusercontent.com/OnkarRuikar/bb1d986f279dddceea9004a4bde3844b/raw/80fe153d6b8c1bb2b8e7035be7df1bb908779061/readme.md'
}
</script>
<script src="https://cdn.jsdelivr.net/npm/docsify#4"></script>
If you generate numbers for titles in main section then they may get populated automatically in the sidebar. You can use markdown setting to write the script. Or you can try something like: https://github.com/markbattistella/docsify-autoHeaders
You want to "do something" to every child of the outer UL, depending on its type - either increment the index at the current level and then prepend a label, if it's an LI; or else recurse to the next level, if it's a UL. Given the HTML provided by the OP, this bit of code produces exactly the desired result:
function addLabels(element, prefix) {
var index = 0;
Array.from(element.children).forEach(element => {
if (element.localName.toUpperCase() === 'LI') {
index += 1;
element.innerText = prefix + index + '. ' + element.innerText;
} else if (element.localName.toUpperCase() === 'UL') {
addLabels(element, prefix + index + '.');
}
});
}
document.querySelectorAll('div.sidebar-nav > ul').forEach(
element => addLabels(element, '')
);
Also, you mentioned the idea of using nextElementSibling to get the UL's from the LI's. That would work, but I think you'd end up with code that is less robust, less performant, and not particularly clearer. But for the record, that could look something like this:
function addLabels2(element, prefix) {
Array.from(element.querySelectorAll(':scope > li')).forEach((element, index) => {
var label = prefix + (index+1) + '.';
var sibling = element.nextElementSibling;
element.innerText = label + ' ' + element.innerText;
if (sibling && sibling.localName.toUpperCase() === 'UL') {
addLabels2(sibling, label);
}
});
}
document.querySelectorAll('div.sidebar-nav > ul').forEach(
element => addLabels2(element, '')
);
I have a JS code that filters the list with an input field. Currently, the filter is a case sensitive. For example, if you have "item1" you have to type the exact word to filter.
$(function(){
$('input.search').keyup(function(){
var searchText = $(this).val();
$('ul.tabs-menu > li').each(function(){
var currentLiText = $(this).text(),
showCurrentLi = currentLiText.indexOf(searchText) !== -1;
$(this).toggle(showCurrentLi);
});
});
});
Is there any way to optimize it?
Here's a link: http://jsfiddle.net/EFTZR/897/
You can convert the items to lowerCase before comparing like this
$(function() {
$('input.search').keyup(function() {
var searchText = $(this).val();
$('ul.tabs-menu > li').each(function() {
var currentLiText = $(this).text(),
showCurrentLi = currentLiText.toLowerCase().indexOf(searchText.toLowerCase()) !== -1;
$(this).toggle(showCurrentLi);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="search" />
<ul class="tabs-menu" id="category1">
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
<ul class="tabs-menu">
<li>item27</li>
<li>item28</li>
</ul>
I add some visual feedback to see what you are looking for in your list (with the same code as the other anwser for the searching function) and change your item list to see it better.
$(function() {
$('input.search').keyup(function() {
var searchText = $(this).val().trim();
$('ul.tabs-menu > li').each(function() {
var currentLiText = $(this).text(),
showCurrentLi = currentLiText.toLowerCase().indexOf(searchText.toLowerCase()) !== -1;
$(this).toggle(showCurrentLi);
$(this).html(currentLiText.replace(searchText, "<span class='bold'>" + searchText + "</span>"))
});
});
});
.bold {
font-weight: bold;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="search" />
<ul class="tabs-menu" id="category1">
<li>first item</li>
<li>second item</li>
<li>one more item</li>
</ul>
<ul class="tabs-menu">
<li>item test</li>
<li>check item</li>
</ul>
Here is a clean and optimized way to do that ( It is case-insensitive ):
$(function(){
var timer;
function search( searchText ) {
$('ul.tabs-menu > li').each(function(){
var $this = $(this),
currentLiText = $this.text().trim().toLowerCase(),
showCurrentLi = currentLiText.indexOf( searchText ) !== -1;
$this.toggle( showCurrentLi );
});
}
$('input.search').keyup(function(){
var searchText = $(this).val().trim().toLowerCase();
// Checks the value of searchText.
if (searchText) {
// Clears the timer.
if ( timer ){
clearTimeout(timer);
}
// Gives the user 1 second to finish typing.
timer = setTimeout( search.bind(this, searchText ), 1000 );
}
});
});
I hope you like it : JSFiddle
I'm implementing sortable plugin of jQuery UI.
There are two columns and we can drag and drop an element from one column to another column.
I have the following javascript code:
$(function () {
$("#sortable1, #sortable2").sortable({
connectWith: ".connectedSortable",
update: function () {
var order1 = $('#sortable1').sortable('toArray').toString();
var order2 = $('#sortable2').sortable('toArray').toString();
alert("Order 1:" + order1 + "\n Order 2:" + order2);
$.ajax({
type: "POST",
url: "/echo/json/",
data: "order1=" + order1 + "&order2=" + order2,
dataType: "json",
success: function (data) {
}
});
}
}).disableSelection();
});
And HTML:
<ul id="sortable1" class="connectedSortable">
<li class="ui-state-default" id='item1'>Item 1</li>
<li class="ui-state-default" id='item2'>Item 2</li>
<li class="ui-state-default" id='item3'>Item 3</li>
<li class="ui-state-default" id='item4'>Item 4</li>
<li class="ui-state-default" id='item5'>Item 5</li>
</ul>
<ul id="sortable2" class="connectedSortable">
<li class="ui-state-highlight" id='item6'>Item 6</li>
<li class="ui-state-highlight" id='item7'>Item 7</li>
<li class="ui-state-highlight" id='item8'>Item 8</li>
<li class="ui-state-highlight" id='item9'>Item 9</li>
<li class="ui-state-highlight" id='item10'>Item 10</li>
</ul>
From above javascript, I can get the order of column 1 and column 2 after change as a whole. However, I would like to know the individual item that has been changed.
Like, in this image below, I have Item3 dragged from Column 1 to Column 2. I want to get output like - Item3_before=Column1,Item3_after=Column2.
In the javascript code above, by using start event like the update event, we can get the Before status of the elements, but not the individual element; it gives before status of all elements.
Few steps to take. I setup an Object to store the values at Activation, Pre-Sorting, and Post-Sorting for both lists. Once that was done, I used this method to determine the difference: JavaScript array difference
Working Example: https://jsfiddle.net/Twisty/kfedekmj/
jQuery
$(function() {
var items = {
"act": {
1: [],
2: []
},
"pre": {
1: [],
2: []
},
"post": {
1: [],
2: []
}
}
function log(et) {
if (!et) {
console.log("Activation");
console.log(" - order1: ", items.act[1].toString());
console.log(" - order2: ", items.act[2].toString());
}
if (et == "sortstart") {
console.log("Pre-Sort");
console.log(" - order1: ", items.pre[1].toString());
console.log(" - order2: ", items.pre[2].toString());
}
if (et == "sortupdate") {
console.log("Post-Sort");
console.log(" - order1: ", items.post[1].toString());
console.log(" - order2: ", items.post[2].toString());
}
}
function determineChange(a1, a2) {
var a = {},
diff = [],
i = 0;
for (i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
$.each(a, function(k, v) {
diff.push(k);
});
return diff[0];
}
$("#sortable1, #sortable2").sortable({
connectWith: ".connectedSortable",
start: function(e, ui) {
// Start of Sort Order
items.pre[1] = $('#sortable1').sortable('toArray')
items.pre[2] = $('#sortable2').sortable('toArray')
log(e.type);
},
update: function(e, ui) {
// End of Sort Order
items.post[1] = $('#sortable1').sortable('toArray');
items.post[2] = $('#sortable2').sortable('toArray');
log(e.type);
/*
$.ajax({
type: "POST",
url: "/echo/json/",
data: "order1=" + order1 + "&order2=" + order2,
dataType: "json",
success: function(data) {}
});
*/
var newItem1 = determineChange(items.pre[1], items.post[1]);
console.log(newItem1);
}
}).disableSelection();
// Activation Order
items.act[1] = $('#sortable1').sortable('toArray');
items.act[2] = $('#sortable2').sortable('toArray');
log();
});
Leaving them as Arrays makes it a lot easier to compare and manipulate. Storing each part in an object simply makes it easier to gather all the info.
The only thing to be mindful of is that update runs 2 times. When an item is removed from list 1, out and added to list 2, receive. It does not make a difference in the end, but it's something to be mindful of just in case.
I'm using this JessicaWhite free webtemplate (http://www.html5xcss3.com/2014/02/jessicawhite-responsive-html5-theme.html). I'm trying to set a filter in my image portfolio in order to show images of defined filter by default and not all images.
I've tried many things (data-plugin-options='{"filter": ".category01")'), but no luck.
HTML:
<ul id="filters" class="option-set" data-option-key="filter" data-plugin-options='{"filter": ".category01"}'>
<li>All</li>
<li>Category01</li>
<li>Category02</li>
</ul>
I have also tried to switch ' for " within the data-plugin-options, but no luck.
Here is the JS for "option-set":
/* SORTING */
$(function(){
var $container = $('.projects');
$container.isotope({
itemSelector : '.element'
});
var $optionSets = $('#options .option-set'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('.option-set');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
// parse 'false' as false boolean
value = value === 'false' ? false : value;
options[ key ] = value;
if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {
// changes in layout modes need extra logic
changeLayoutMode( $this, options )
} else {
// otherwise, apply new options
$container.isotope( options );
}
return false;
});
});
Per the below comments, try the following:
Remove the 'data-category' attribute from your portfolio items, it's not being used.
Change your 'filter buttons' markup to the following -
<ul id="filters">
<li><a class="filter-button" href="#filter" data-filter="*" class="btn btn-mini">All</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category01" class="btn btn-mini selected">Category01</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category02" class="btn btn-mini">Category02</a></li>
</ul>
Comment out the entire "sorting" JS function and replace with this -
var $projects = $('.projects').isotope({
filter: '.category 01'
});
$('.filter-button').on( 'click', function() {
var filteredVal = $(this).attr('data-filter');
$projects.isotope({ filter: filteredVal });
$('.filter-button.selected').removeClass('selected');
$(this).addClass('selected');
});
jstree v1.0
I have just made modification on checkbox example: http://www.jstree.com/documentation/checkbox
My goal:
When checking any of the nodes I want all parent node to be checked (default behavior is not OK, because that is something partially selected which is not good for me)
based on tips and documentation i have extended the original example but I have found that the check_node method is not working. I have not noticed any effect.
Any tips or advice is welcomed.
<div id="demo1" class="demo">
<ul>
<li id="phtml_1">
Root node 1
<ul>
<li id="phtml_2" >
Child node 1
</li>
<li id="phtml_3">
A Child node 2
</li>
</ul>
</li>
<li id="phtml_4">
Root node 2
</li>
<li id="phtml_5">
Root node 1
<ul>
<li id="phtml_51">
Child node 1
</li>
<li id="phtml_52">
A Child node 2
</li>
</ul>
</li>
<li id="phtml_6">
Root node 1
<ul>
<li id="phtml_61">
Child node 1
</li>
<li id="phtml_62">
A Child node 2
</li>
</ul>
</li>
</ul>
</div>
<script type="text/javascript" class="source">
$(function () {
var x = $("#demo1");
$(x).jstree({
"checkbox" :{
real_checkboxes:false,
override_ui:true,
two_state:false,
},
"plugins" : [ "themes", "html_data", "checkbox", "ui" ]
}).bind('check_node.jstree', function (e, data) {
console.log('check_node.jstree ----------------------------------------------');
console.log(e);
var all_selected = $(x).jstree('get_checked')
console.log('all_selected='+all_selected);
for(var i=0;i<all_selected.length;i++){
var paths = $(x).jstree('get_path', all_selected[i], true);
console.log(' paths='+paths);
for(var j=0; j< paths.length;j++){
console.log(' checking node (not working)='+paths[j]);
$(x).jstree('check_node',paths[j]);
}
}
});
console.log('programaticcaly checking last parent node (not working)')
//$(x).jstree('check_node',$('li#phtml_6'));
$.jstree._reference("#demo1").check_node('li#phtml_6');
});
</script>
The following code was working for me...
var contact_list = $('#compose_contact_list');
contact_list.jstree({
"checkbox" : {
"keep_selected_style" : false,
"tie_selection" : false
},
"plugins" : [ "checkbox" ]
});
contact_list.on("check_node.jstree", function(event, data){
alert(data.node.text);
});
try this,
.bind('check_node.jstree', function(e, data) {
var currentNode = data.rslt.obj.attr("id");
var parentNode = data.inst._get_parent(data.rslt.obj).attr("id");
jQuery.jstree._reference($("#tree")).check_node('#'+parentNode);
});
if you want example refer this http://jsfiddle.net/bwTrP/3/
jstree-3.2.1
/**
* check tree node
* treeid:tree id
* nodeids:node id, id or id array
*/
function checkTreeNodes (treeid, nodeids) {
// Tree
var tree = $("#" + treeid);
// IE
tree.jstree(true).check_node(nodeids);
// Chrome or Firefox
tree.on("loaded.jstree", function (e, data) {
tree.jstree(true).check_node(nodeids);
}).jstree();
}
https://github.com/vakata/jstree/issues/1266
just include a simple click function as follows.
$(x).on("click", function () {
$(x).jstree("select_all");
});