I am trying to create company structure.
One employee can been employeed in two sector, but this is same employee with same ID id = employee1.
Checking if is item selected or deselected and this is working.
I having problem with nodes with same id.
When selected node with id employee1, I want select/deselect all node where is id employee1.
Thank you in advance.
<div id="companyEmplyee">
<ul>
<li class="folder" id="company1">Company
<ul>
<li class="folder" id="sector1">Sector 1
<ul>
<li class="emplyee1">Emplyee 1</li>
<li id="emplyee2">Emplyee 2</li>
</ul>
</li>
<li class="folder" id="sector2">Sector 2
<ul>
<li class="emplyee1">Emplyee 1</li>
<li id="emplyee35">Emplyee 35</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<script type="text/javascript">
$(function () {
var tree = $("#companyEmplyee").fancytree({
checkbox: true,
selectMode: 2,
keyPathSeparator: "/",
clones: {
highlightClones: true
},
select: function (event, data) {
var s = data.tree.getNodeByKey(data.node.key);
var s3 = s.key;
var s2 = $.map(data.tree.getSelectedNodes(), function (node) {//
return node.key;
});
if ($.inArray(s3, s2) == -1) {//
$("tr#" + s3).addClass("deleted");
//DESELECTED
$('table#tblID tr#' + s.key).remove();
alert(s.key + ' DESELECT');
}
else {
//SELECTED
alert(s.key + ' SELECT');
}
}
});
});
</script>
id should be unique in same document, use general class emplyee1 instead :
<div id="companyEmplyee">
<ul>
<li class="folder" id="company1">Company
<ul>
<li class="folder" id="sector1">Sector 1
<ul>
<li class="emplyee1">Emplyee 1</li>
<li id="emplyee2">Emplyee 2</li>
</ul>
</li>
<li class="folder" id="sector2">Sector 2
<ul>
<li class="emplyee1">Emplyee 1</li>
<li id="emplyee35">Emplyee 35</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Or use unique ids, like you see in fancytree documentation the key (Node id) should be unique :
Node id (must be unique inside the tree)
Update :
Try to use the following hack :
select: function (event, data) {
if(data.node.extraClasses!=''){
if( $(data.node.li).find('.fancytree-node').hasClass('fancytree-selected') )
$('.'+data.node.extraClasses).addClass('fancytree-selected');
else
$('.'+data.node.extraClasses).removeClass('fancytree-selected');
}
}
Working example.
hope this helps.
Duplicated Id are invalid in HTML, violates the spec and cause problems.
https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#the-id-attribute
Assign classes instead of ids.
As noted in the previous answers, duplicate node keys are not allowed in Fancytree (and duplicate IDs are not allowed in HTML as well).
Since it is a common scenario to have multiple object instances inside one tree, there is a concept of 'clones'.
Basically you include the clones extension and pass the employee ID as refKey instead of key, e.g.
<li data-refKey="emplyee1">Emplyee 1</li>
You also need to enable the extension:
$("#tree").fancytree({
extensions: ["clones"],
checkbox: true,
selectMode: 2,
...
After that, you can access related instances like so:
select: function(event, data) {
var nodes = data.node.getCloneList();
...
},
See here for details: https://github.com/mar10/fancytree/wiki/ExtClones
and example http://wwwendt.de/tech/fancytree/demo/sample-ext-clones.html
Related
I have some listings.
Currently id is test_3, test_1, test_2. I need number (3,1,2) from id of each li and append this number in to another data attribute. Please check the result section. It will give you an idea about what I am expecting. Thanks
Html
<ul id="cat">
<li id="test_3">Text 3</li>
<li id="test_1">Text 1</li>
<li id="test_2">Text 2</li>
</ul>
Script
$('#cat').attr('id').split("-")[2];
Expected result
<ul id="cat">
<li id="test_3" data-id="3">Text 3</li>
<li id="test_1" data-id="1">Text 1</li>
<li id="test_2" data-id="2">Text 2</li>
</ul>
To achieve this you can loop over the li elements and set the data() based on the number in the id attribute. Try this:
$('#cat li').each(function() {
$(this).data('id', this.id.split('_')[1]);
}).click(function() {
console.log($(this).data('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="cat">
<li id="test_3">Text 3</li>
<li id="test_1">Text 1</li>
<li id="test_2">Text 2</li>
</ul>
You can loop through all of the children of the ul element with the id cat.
On each loop, get the ID by getting the id attribute, splitting it on _ and getting the first index.
You can then set the attribute by using JQuery's attribute function, which you can learn more about here.
$('#cat li').each(function () {
var dataId = $(this).attr('id').split('_')[1];
$(this).attr('data-id', dataId);
});
An example of this in action
$('#cat li').each(function () {
var dataId = $(this).attr('id').split('_')[1];
$(this).attr('data-id', dataId);
});
console.log($('#cat').html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="cat">
<li id="test_3">Text 3</li>
<li id="test_1">Text 1</li>
<li id="test_2">Text 2</li>
</ul>
This should some your problem.
Using $(this).attr("id").split('_') will split "cat_3" into "cat" and "3" then using [1] after will select "3"
$("#cat li").each(function(){
$(this).attr("data-id", $(this).attr("id").split('_')[1]);
})
console.log($("#cat").html())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="cat">
<li id="test_3">Text 3</li>
<li id="test_1">Text 1</li>
<li id="test_2">Text 2</li>
</ul>
You can also use a RegExpression.
var suffix = "test_2".match(/\d+/); // results --> 2
Basically it fetches out numeric value within a string value.
Usage
$('#cat li').each(function() {
$(this).data('id', this.id.match(/\d+/));
})
I have a portfolio site set up and I have my portfolio set up to shuffle through by selecting certain filters. What I want to do is set some header text, based upon which filter they choose.
The issues is when I select a link, let's say advertising, Advertising will show up as my header text. However if I select something else, say branding, it doesn't change, it stays at advertising.
here is my html
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All</li>
<li class="workFilterButtons">Advertising</li>
<li class="workFilterButtons">Branding</li>
<li class="workFilterButtons">Catalog</li>
<li class="workFilterButtons">Corporate ID</li>
<li class="workFilterButtons">Consumer Relations</li>
<li class="workFilterButtons">Incentive/Loyalty</li>
<li class="workFilterButtons">Packaging</li>
<li class="workFilterButtons">Product Launch</li>
<li class="workFilterButtons">Promotion</li>
<li class="workFilterButtons">Public Relations</li>
<li class="workFilterButtons">Sales Support</li>
<li class="workFilterButtons">Social Media</li>
<li class="workFilterButtons">Tradeshows</li>
<li class="workFilterButtons">Web/Mobile</li>
</ul>
<div id="bottomWrapper">
and here is my script
$(document).ready(function(){
$(".workFilterButtons a").click(function(){
$(".currentFilter").replaceWith($(this).append());
});
});
by default the page is set to "ALL" when loaded, but as you can see I am trying to gett he dynamic text to work within the .currentFilter span
Any help would be greatly appreciated.
If you only want text you use text() method to both get and set. Also you don't want to replace the element or it won't be found again because it will no longer exist
Try
$(".workFilterButtons a").click(function(){
$(".currentFilter").text($(this).text());
});
You don't need to replace the element with the clicked <a> element (unless you really want to), all you need to do is update the text:
$(document).ready(function () {
$(".workFilterButtons a").click(function () {
// selecting the element with the class
// of 'currentFilter', and setting its
// text (using the text() method) to
// the textContent of the clicked <a>
// element:
$(".currentFilter").text(this.textContent);
});
});
$(document).ready(function() {
$(".workFilterButtons a").click(function() {
$(".currentFilter").text(this.textContent);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All
</li>
<li class="workFilterButtons">Advertising
</li>
<li class="workFilterButtons">Branding
</li>
<li class="workFilterButtons">Catalog
</li>
<li class="workFilterButtons">Corporate ID
</li>
<li class="workFilterButtons">Consumer Relations
</li>
<li class="workFilterButtons">Incentive/Loyalty
</li>
<li class="workFilterButtons">Packaging
</li>
<li class="workFilterButtons">Product Launch
</li>
<li class="workFilterButtons">Promotion
</li>
<li class="workFilterButtons">Public Relations
</li>
<li class="workFilterButtons">Sales Support
</li>
<li class="workFilterButtons">Social Media
</li>
<li class="workFilterButtons">Tradeshows
</li>
<li class="workFilterButtons">Web/Mobile
</li>
</ul>
<div id="bottomWrapper"></div>
JS Fiddle demo.
Incidentally, the reason your original code didn't work, and couldn't work, is because of this line:
$(".currentFilter").replaceWith($(this).append());
This replaced the selected element(s) with the clicked <a> element, which meant that, in future, the there was no .currentFilter element to replace or update.
On the other hand, if you want to put the clicked <a> element into the .currentFilter span-element, then you could try the following approach:
$(document).ready(function () {
$(".workFilterButtons a").click(function () {
// finding those <li> elements whose text, when trimmed
// (removing leading and trailing white-space) is equal
// to an empty string (''):
var emptyLi = $('.workFilterButtons').filter(function () {
return $(this).text().trim() === '';
}),
// caching the '.currentFilter' element(s):
currentFilter = $('.currentFilter'),
// checking for those elements in the
// currentFilter jQuery object that have
// a descendant <a> element, and finding
// length of that collection, and then
// checking that it's greater than 0:
hasA = currentFilter.has('a').length > 0;
// appending the contents of the currentFilter
// element into the found emptyLi element:
emptyLi.append(currentFilter.contents());
// if there are no <a> elements in the
// currentFilter element(s):
if (!hasA) {
// we replace the contents (textNode 'all')
// with the clicked <a> element:
currentFilter.contents().replaceWith(this);
} else {
// otherwise we append the clicked link to
// the currentFilter; this works because
// once we get to this stage the <a> element
// if it exists has already been moved back
// to the empty <li>, therefore we can't
// use '.contents().replace()' because
// there are no contents remaining by this point
// (and yes, this was incredibly counter-intuitive
// to me for quite a long time, which is why this
// update took a while):
currentFilter.append(this);
}
});
});
$(document).ready(function() {
$(".workFilterButtons a").click(function() {
var emptyLi = $('.workFilterButtons').filter(function() {
return $(this).text().trim() === '';
}),
currentFilter = $('.currentFilter'),
hasA = currentFilter.has('a').length > 0;
emptyLi.append(currentFilter.contents());
if (!hasA) {
currentFilter.contents().replaceWith(this);
} else {
currentFilter.append(this);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All
</li>
<li class="workFilterButtons">Advertising
</li>
<li class="workFilterButtons">Branding
</li>
<li class="workFilterButtons">Catalog
</li>
<li class="workFilterButtons">Corporate ID
</li>
<li class="workFilterButtons">Consumer Relations
</li>
<li class="workFilterButtons">Incentive/Loyalty
</li>
<li class="workFilterButtons">Packaging
</li>
<li class="workFilterButtons">Product Launch
</li>
<li class="workFilterButtons">Promotion
</li>
<li class="workFilterButtons">Public Relations
</li>
<li class="workFilterButtons">Sales Support
</li>
<li class="workFilterButtons">Social Media
</li>
<li class="workFilterButtons">Tradeshows
</li>
<li class="workFilterButtons">Web/Mobile
</li>
</ul>
<div id="bottomWrapper"></div>
JS Fiddle demo.
References:
JavaScript:
Node.textContent.
String.prototype.trim().
jQuery:
append().
click().
contents().
filter().
has().
replaceWith().
text().
I changed your class="currentFilter" to id="currentFilter" so now you won't need a .each() to do what you want to do, the selector selects only 1 element and not an array of 1 element.
Also changed replaceWith() with text(), and likewise append() replaced with text().
Here's a fiddle if you want to see it in action
https://jsfiddle.net/s6bpwycn/
Currently my side menu consists of parent and child pages. To keep the menu expanded on the child page I am having to use a switch statement and check if the url is what I am looking for and if it matches show the expanded child items.
$(function () {
var url = window.location.pathname;
switch (url) {
case 'Path1':
$('#ChildOne').show();
break;
case 'Path2':
$('#ChildTwo').show();
break;
case 'Path3':
$('#ChildThree').show();
break;
...
}
});
I've got over 20 pages where I need to display the child elements. My question is, is this the only way or does someone know a better way? Thanks in advance for your help.
Note
I only want to display the relevant child elements on active child page. Suppose, I click on ChildOne when I get redirected to that page I only want to see the child elements under that parent.
My mark-up is as follows
<ul>
<li class="parent"><a style="cursor: pointer;">Parent One</a>
<ul class="child" id="ChildOne">
<li>Child Of Parent One</li>
<li>Child Of Parent One</li>
</ul>
</li>
<li class="parent"><a style="cursor: pointer;">Parent Two</a>
<ul class="child" id="ChildTwo">
<li>Child Of Parent Two</li>
<li>Child Of Parent Two</li>
<li>Child Of Parent Two</li>
</ul>
</li>
<li class="parent"><a style="cursor: pointer;">Parent Three</a>
<ul class="child" id="ChildThree">
<li>Child Of Parent Three</li>
<li>Child Of Parent Three</li>
</ul>
</li>
...
</ul>
I have added some code in order to be able to reproduce the issue. I added some classes to the parent items of the menu so that I can check them later in order to hide or not their children. The class names are the page name (final word on the url) which is unique. I get it using the substring method.
In this example, your current page is the second option, and by using the each() function of jquery, you can go through the elements without having a ton of switch cases or if statements.
Fiddle
Code snippet:
function escocha() {
var url = '/about/profile'
var n = url.lastIndexOf("/");
var myClassName = url.substring(n + 1, url.length)
alert("The url: " + url);
alert("The class name: " + myClassName);
$(".child").each(function (index) {
alert(this.id);
if (this.className.indexOf(myClassName) > -1) { // if any class name for this element contains the string 'display'
alert("I am the current page so my menu items won't collapse!");
} else {
$('#' + this.id).hide();
}
});
}
$("#esmaga").click(function () {
escocha();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="parent"><a style="cursor: pointer;">Parent One</a>
<ul class="child display" id="ChildOne">
<li>Child Of Parent One
</li>
<li>Child Of Parent One
</li>
</ul>
</li>
<li class="parent"><a style="cursor: pointer;">Parent Two</a>
<ul class="child profile" id="ChildTwo">
<li>Child Of Parent Two
</li>
<li>Child Of Parent Two
</li>
<li>Child Of Parent Two
</li>
</ul>
</li>
<li class="parent"><a style="cursor: pointer;">Parent Three</a>
<ul class="child display" id="ChildThree">
<li>Child Of Parent Three
</li>
<li>Child Of Parent Three
</li>
</ul>
</li>...</ul>
<button id="esmaga">Esmaga</button>
you can use id of ULs elements same as window.location.pathname. In this case you can call:
try{
$("#"+window.location.pathname).show();
}catch(e){
// error handling
}
but your menu is strange ;)
OK, one more version with object
var oPath = new Object({
"Path1":"ChildOne",
"Path2":"ChildTwo",
"Path3":"ChildThree"
});
try{
$("#"+ oPath[window.location.pathname]).show();
}catch(e){}
First of all I am sorry that I cannot explain the scenario as for my poor english.This is what actually I need to do.
I have a list as follows,
<ul id="sortable" class="sortable">
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
<li id="4">4</li>
</ul>
list IDs and their values are same.Normally,if I move list ID 4 to top using jquery sortable then I get the new list as,
<ul id="sortable" class="sortable">
<li id="4">4</li>
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
</ul>
But What I need to do is rename/reorder the IDs to Ascending as for current order of list.
which means
ID 4 => ID 1
ID 1 => ID 2
ID 2 => ID 3
ID 3 => ID 4
Is this possible using jQuery .sortable(). If so how would I overcome this problem?
Thanks a lot.
Yes, you can do it with any of a number of supported events. For this example I'll use stop:
$(".sortable").sortable({
stop: function(e, ui) {
$(this).children("li").each(function(idx, elt) {
$(elt).attr("id", idx);
});
}
});
However note that this (changing id-s) is generally considered bad practice, there should be a way for you to achieve your results without it. Also, if you're concerned with backward compatibility remember that id-s starting with a number are not part of the standard in HTML4.
You can sort like this
function sort_by_id(a, b) {
var sa = a.id, sb = b.id;
return sb>sa ? -1 : sb<sa ? 1 : 0;
}
function sortList(){
var list = $("#sortable > li").get();
list.sort(sort_by_id);
for (var i = 0; i < list.length; i++) {
list[i].parentNode.appendChild(list[i]);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
Sort list
<ul id="sortable" class="sortable">
<li id="4">4</li>
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
</ul>
How do i get the previous li when it is wrapped inside an ol?
I have used the following script, but it doesnt seem to work:
<script type="text/javascript">
$(document).ready(function () {
$(".categoryitem").click(function () {
alert("hihi");
$(this).parent().prev("li").css('background-color', 'red');
$(this).prev("li").css('background-color', 'red');
});
});
</script>
This is how the HTML looks like (In my real application i have set the class name on each li, but didnt do it in this example)
<ul>
<li>
Item 1
</li>
<ol>
<li>
Item 1.1
</li>
</ol>
<li>
Item 2
</li>
<ol>
<li>
Item 2.1
</li>
<ol>
<li>
Item 2.1.1
</li>
</ol>
<ol>
<li>
Item 2.1.2
</li>
</ol>
<ol>
<li>
Item 2.1.3
</li>
</ol>
<ol>
<li>
Item 2.1.4
</li>
</ol>
</ol>
</ul>
When i click on Item 1.1, the parent 1 becomes red
When i click on item 2, nothing happens, but i would like 1.1 to become red
When i click on items 2.1.1, 2.1.2, 2.1.3, 2.1.4 nothing happens
When i click on item 2.1, the parent 2 becomes red
I would like all previous LI's to become red, even if they are in higher levels
What am i doing wrong?
This is the method that creates the tree:
EDIT: I changed ol to ul, for each group
<ul>
#{
foreach(var cq in Model) {
#ShowSubItems(cq);
}
}
</ul>
#helper ShowSubItems(MvcApplication3.Models.ViewModels.Category.AllQuestionsInCategoriesViewModel MyObj)
{
<li class="categoryitem" categoryid="1">#Html.ActionLink(MyObj.Category_Number + " " + MyObj.Category_Name, "DisplayQuestions", new { categoryId = MyObj.Category_ID, page = 1 })</li>
if (MyObj.SubCategories != null && MyObj.SubCategories.Count != 0)
{
<ul>
#foreach (var subitem in MyObj.SubCategories)
{
#ShowSubItems(subitem)
}
</ul>
}
}
</ul>
To get the CLOSEST PARENT, you can simply use .closest()
<ul>
<li>
Click Me!
</li>
</ul>
$(document).ready(function() {
$('a.clickme').click(function() {
$(this).closest('li').css('background-color', 'red');
});
});
Here's the jsfiddle source of this example: http://jsfiddle.net/y36qg/