jsTree checkbox check_node is not working - javascript

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");
});

Related

restrictions in treeview JS - Check only one checkbox

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>

Hide all elements who's status isn't part of a filterable array?

I want to hide all elements who's status doesn't exist with in a filterable array and was wondering what the most performant method would be to achieve this? Right now I filter the elements, check the status, check if it doesn't exist in the filter array then apply a hidden class. Is there a better way to do this?
JS
var filtersArray = ['working', 'rejected'],
orders = $('.js-orders').children();
var filtered = orders.filter(function(index, element) {
var status = $(element).data('status').toLowerCase(),
hiddenFilter = !_.contains(filtersArray, status);
return hiddenFilter;
});
filtered.addClass('is-hidden');
JS Fiddle https://jsfiddle.net/kyllle/xwobhnzr/
The test inside the filter function is:
filtersArray.indexOf($(element).data('status').toLowerCase()) != -1
$(function () {
var filtersArray = ['working', 'rejected'],
orders = $('.js-orders').children();
var filtered = orders.filter(function(index, element) {
return filtersArray.indexOf($(element).data('status').toLowerCase()) != -1
});
filtered.addClass('is-hidden');
});
.is-hidden {
display: none;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<ul class="js-orders">
<li data-status="working">Item 1 - Working</li>
<li data-status="pending">Item 2 - Pending</li>
<li data-status="working">Item 3 - Working</li>
<li data-status="pending">Item 4 - Pending</li>
<li data-status="working">Item 5 - Working</li>
<li data-status="pending">Item 6 - Pending</li>
<li data-status="rejected">Item 7 - Rejected</li>
<li data-status="rejected">Item 8 - Rejected</li>
</ul>

radomize ul tag not working

this is probably an easy question for you guys but I'm very new to coding and can't figure out this. I have a code that I want to randomize the given choices in the questions, and I've found a script online that does that but it's not working. I don't know what the
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function() {
means so I tried to put all id that I don't need to randomize in it but it's still not working.
Can someone help me this please? Also is there anyway I can add choice "A", choice "B", choice "C", and choice "D" in front of each given options so even after the options(answers) are randomized, the A,B,C,D options will still be in order? Thank you. Here's the code:
HTML:
<!DOCTYPE html>
<html>
<body>
<script src="JQ.js"></script>
<script src="function.js"></script>
<link href="style.css" rel="stylesheet" />
<div id="quiz_container">
<ul class="quiz_container">
<li class="single_question" data-question-id="1" data-correct-answer="1">
<div class="question">
<h1 class="title">P.1 Grammar Review</h1>
<p class="text">1. "What is your name__"</p>
</div>
<ul class="options">
<li value="1">?</li>
<li value="2">.</li>
<li value="3">,</li>
</ul>
<div class="result"></div>
</li>
<li class="single_question" data-question-id="2" data-correct-answer="b">
<div class="question">
<p class="text">2. "Do you like the banana__"</p>
</div>
<ul class="options">
<li value="a">.</li>
<li value="b">?</li>
<li value="c">,</li>
</ul>
<div class="result"></div>
</li>
</div>
</body>
</html>
JS:
$(document).ready(function () {
/*
* shuffles the array
* #param {Array} myArray array to shuffle
*/
function shuffleArray(myArray) {
for (var i = myArray.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = temp;
}
return myArray;
}
var $ul, $li, li_content, li_list;
// find all lists to shuffle
$("#quiz_container > ul").each(function () {
$ul = $(this);
li_list = [];
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function () {
// add content to the array and remove item from the DOM
li_list.push($(this).html());
$(this).remove();
});
// shuffle the list
li_list = shuffleArray(li_list);
while (li_content = li_list.pop()) {
// create <li> element and put it back to the DOM
$li = $("<li />").html(li_content);
$ul.append($li);
}
});
$("#contact_div").show();
});
$(document).on('click', '.single_question .options li', function () {
// Save the question of the clicked option
question = $(this).parents('.single_question');
// Remove If Anyother option is already selected
question.find('.selected').removeClass('selected');
// Add selected class to the clicked li
$(this).addClass('selected');
// selected option value
selected_answer_value = $(this).attr("value");
// Value of correct answer from '.single-question' attribute
correct_answer_value = question.attr("data-correct-answer");
correct_answer_text = question.find('.options').find("li[value='" + correct_answer_value + "']").text();
if (correct_answer_value == selected_answer_value)
result = "<div class='correct'> Correct ! </div>";
else
result = "<div class='wrong'> Correct answer is -> " + correct_answer_text + "</div>";
// Write the result of the question
$(this).parents('.single_question').find('.result').html(result);
// Calculate the score
score_calculator();
});
/**
* It loops through every question and increments the value when "data-correct-answer" value and "option's value" are same
*/
function score_calculator() {
score = 0;
$('.single_question').each(function () {
question = $(this);
if (question.attr('data-correct-answer') == question.find('.selected').attr("value")) {
score++;
}
});
$('.correct_answers').html(score);
}
It looks like you're using jQuery, even though the question isn't tagged as such. If that's the case, you can use a code snippet written by Chris Coyier of CSS-Tricks called shuffle children.
Here's an example of the code in action.
$.fn.shuffleChildren = function() {
$.each(this.get(), function(index, el) {
var $el = $(el);
var $find = $el.children();
$find.sort(function() {
return 0.5 - Math.random();
});
$el.empty();
$find.appendTo($el);
});
};
$("ul.randomized").shuffleChildren();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Static List:</h4>
<ul>
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
<h4>Randomized List:</h4>
<ul class="randomized">
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
In order to apply it to your own code, all you'd need to do is modify the CSS selector at the bottom of the jQuery snippet. In your case, ul.options might be a good choice.
Here are a couple of examples using your markup:
jsFiddle
Self-Contained HTML Doc

Unique "key" prop in React when returning list with multiple children

I have to render multiple lists in a react component. I create my lists in the following manner:
var jobResources = null;
if (this.state.jobResources) {
jobResources = _.map(this.state.jobResources, function(jobResource, i) {
return <ul><li key={i}>{jobResource.resource.name}</li><li key={Math.floor(Math.random() * (1000 - 100)) + 100}>{translations.resourceType[jobResource.resource.resourceType.name]}</li></ul>
})
}
When it comes to rendering, I render the list thus:
<div>
<h2>Who is Working on the Project?</h2>
{this.state.jobResources ? jobResources : null}
</div>
The resulting render is as follows:
<ul data-reactid=".0.2.0.2.1:0">
<li data-reactid=".0.2.0.2.1:0.$0">Mark Smith</li>
<li data-reactid=".0.2.0.2.1:0.$270">Hair & MakeUp</li>
</ul>
<ul data-reactid=".0.2.0.2.1:1">
<li data-reactid=".0.2.0.2.1:1.$1">John Doe</li>
<li data-reactid=".0.2.0.2.1:1.$377">Photographer</li>
</ul>
As far as I see it, the keys are unique. However, react gives me the following warning:
Warning: Each child in an array or iterator should have a unique "key"
prop. Check the render method of JobDetailPage. See
http://facebook.github.io/react/docs/multiple-components.html#dynamic-children
for more information.
Could anyone tell me what is the mistake that I am making and what would be the correct way of going about this?
Never mind, figured it out. Apparently, the list element should have a key as well. The correct way of creating the list therefore would be:
var jobResources = null;
if (this.state.jobResources) {
jobResources = _.map(this.state.jobResources, function(jobResource) {
return <ul key={jobResource.id}><li key={jobResource.resource.name}>{jobResource.resource.name}</li><li key={jobResource.resource.resourceType.name}>{translations.resourceType[jobResource.resource.resourceType.name]}</li></ul>
})
}
I usually do this
if (this.state.jobResources) {
jobResources = _.map(this.state.jobResources, function(jobResource, i) {
return (
<ul>
<li key={i.toString()}>{jobResource.resource.name}</li>
<li key={`key${i}`}>
{
translations.resourceType[
jobResource.resource.resourceType.name
]
}
</li>
</ul>
);
});
}
This utility function from lodash/underscore solves it easily:
key={_.uniqueId()}

Group list-items into sub-lists based on a data attribute

I want to append the <li> from one <ul> to another <ul> that's created on the fly. I want to group the list-items into new sub-lists based on their data-group attribute.
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
Basically I'm trying to loop through this list and grap all <li> from each group, and then move it to another <ul>.
This is what I have so far, but I'm not getting the expected results. I have done this in Excel in the past but can't get it to work with jQuery.
var listItems = $("#sortable1").children("li");
listItems.each(function (idx, li) {
var product = $(li);
//grab current li
var str = $(this).text();
if (idx > 0) {
//append li
str += str;
if ($(this).data("group") != $(this).prev().data("group")) {
//I should be getting test and test1.
//but alert is only giving test1 test1.
alert(str);
//need to break into groups
//do something with groups
}
}
});
How about something like this:
$(function() {
var sortable = $("#sortable1"),
content = $("#content");
var groups = [];
sortable.find("li").each(function() {
var group = $(this).data("group");
if($.inArray(group, groups) === -1) {
groups.push(group);
}
});
groups.forEach(function(group) {
var liElements = sortable.find("li[data-group='" + group + "']"),
groupUl = $("<ul>").append(liElements);
content.append(groupUl);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
<div id="content">
</div>
I hope I didn't misunderstand you.

Categories