Get immediate child using nextUntil - javascript

I have some html :)
<div class="categories">
<div class="list-group">
<a class="root list-group-item" id="427" style="display: block;"><span class="glyphicon indent0 glyphicon-chevron-down"></span><span>Home</span></a>
<a class="list-group-item first active" id="428" style="display: block;"><span class="glyphicon indent1 glyphicon-chevron-right"></span><span>Images</span></a>
<a class="list-group-item child" id="431" style="display: none;"><span class="glyphicon glyphicon-chevron-right indent2"></span><span>Sub category</span></a>
<a class="list-group-item child" id="433" style="display: none;"><span class="glyphicon indent3"></span><span>Super sub</span></a>
<a class="list-group-item first" id="429" style="display: block;"><span class="glyphicon glyphicon-chevron-right indent1"></span><span>Videos</span></a>
<a class="list-group-item child" id="432" style="display: none;"><span class="glyphicon indent2"></span><span>Another sub</span></a>
<a class="list-group-item first" id="430" style="display: block;"><span class="glyphicon indent1"></span><span>Documents</span></a>
</div>
</div>
and I have this function:
$(".glyphicon", treeRoot).on('click', function (e) {
e.stopPropagation();
var $glyph = $(this);
var $item = $glyph.parent();
var indent = $item.find(".glyphicon").prop('className').match(/\b(indent\d+)\b/)[1];
if (indent != undefined) {
var $children = $item.nextUntil("a:has(." + indent + ")");
if ($glyph.hasClass("glyphicon-chevron-right")) {
$glyph
.addClass('glyphicon-chevron-down')
.removeClass("glyphicon-chevron-right");
if ($children != null) $children.show();
} else {
$glyph
.addClass('glyphicon-chevron-right')
.removeClass("glyphicon-chevron-down");
if ($children != null) $children.hide();
}
}
});
So basically, when the icon is clicked, it shows or hides the children.
The problem is, it shows all children (indent2 and indent3) but I just want it to show the immediate children (indent2 in this example).
Could someone give me some insight on how to do this?
Cheers,
/r3plica

Try
var num = parseInt(indent.match(/(\d+)$/)[1], 10);
var $children = $item.nextUntil("a:not(:has(.indent" + (num + 1) + "))");
Demo: Fiddle

Related

Text of List item <li> does not reflected correctly after edited click save button from modal pop up in Javascript

I have nested list item of <li> structured as below. What I am trying to do is to edit each item text from pop up modal and reflect change after I clicked on button Save.
However, the first list item I edited is working well, but from the second time onward, it does not work as expected.
$(document).ready(function() {
$('.modal').modal(); // modal
var child;
$('body').on('click', '.fa-pencil', function(e) {
var text = $(this).closest("li").clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text();
child = $(this).closest("li").children();
var li_element = $(this).closest('li');
console.log(li_element);
var dataActive = $(this).closest('li').attr('data-act');
var li_icon = li_element.attr('data-icon');
var modal1 = $('#modal1');
var modalBody = modal1.find('.modal-content');
modalBody.find('h4.itemdes').text('');
modalBody.find('.modalBody').html('');
var modalHeader = modalBody.find('h4.itemdes').attr('contenteditable', true).text(text);
dataActive = $(this).closest('li').attr('data-act') == 'Y' ? 'checked="checked"' : '';
ActiveOpt = '<p><label><input type="checkbox" id="active" class="filled-in" ' + dataActive + ' /><span>Active</span></label></p>';
IconOpt = '<p><i class="' + li_icon + '" id="icon_element" aria-hidden="true"></i></p>';
var datahtml = ActiveOpt + IconOpt;
modalBody.find('.modalBody').html(datahtml);
// modalBody.find('.modalBody').append(IconOpt);
$('body').on('click', '.saveChange', function() {
var textarea = $('.itemdes').text();
var appendItem = textarea;
li_element.text('').empty().append(appendItem).append(child);
// $(this).closest("li").text('').empty().append(appendItem).append(child);
ActiveOpt = '';
IconOpt = '';
// li_element = '';
});
// Function to check li data-Acive
$('body').on('change', '#active', function() {
li_element.removeAttr('data-act');
// console.log(li_element.prop('checked'));
if ($(this).prop('checked')) {
li_element.attr('data-act', 'Y');
// li_element.attr('checked','checked');
} else {
li_element.attr('data-act', 'N');
// li_element.removeAttr('checked');
}
})
});
})
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Materialized CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- Modal Trigger -->
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4 style="width: auto; float: left;"><i class="fa fa-pencil-square-o" aria-hidden="true"> </i></h4>
<h4 class="itemdes">Modal Header</h4>
<div class="modalBody">
<p>A bunch of text</p>
</div>
Save
</div>
</div>
<ol class="example example2">
<li data-formdesc="User" data-act="Y" data-icon="fa fa-heart">
<i class="fa fa-heart"></i>User<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
<li data-formdesc="Cash Withdrawal" data-act="Y" data-icon="">
<i class=""></i>Cash Withdrawal<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
<li data-formdesc="Branch1" data-act="Y" data-icon="fa fa-futbol-o">
<i class="fa fa-futbol-o"></i>Branch1<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol>
<li data-formdesc="Customer Centre" data-act="Y" data-icon="">
<i class=""></i>Customer Centre<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
<li data-formdesc="Customers Detail Listing" data-act="Y" data-icon="">
<i class=""></i>Customers Detail Listing<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
</ol>
</li>
<li data-formdesc="2 two" data-act="Y" data-icon="fa fa-linkedin">
<i class="fa fa-linkedin"></i>2 two<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol>
<li data-formdesc="Cash Withdrawal" data-act="Y" data-icon="">
<i class=""></i>Cash Withdrawal<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
<li data-formdesc="Till to Till Transfer" data-act="Y" data-icon="">
<i class=""></i>Till to Till Transfer<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol>
<li data-formdesc="Disbursement Voucher" data-act="Y" data-icon="">
<i class=""></i>Disbursement Voucher<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
</ol>
</li>
<li data-formdesc="Income Posting" data-act="Y" data-icon="">
<i class=""></i>Income Posting<i class="fa fa-pencil modal-trigger" aria-hidden="true" data-target="modal1"></i>
<ol></ol>
</li>
</ol>
</li>
</ol>
For example, first time I edit list item 'User' to 'Users', after I clicked on save, the item text changed well. But at second time I edit another item, let's say 'Cash Withdrawal' to 'Cash Withdrawaling', after clicked Save, the item I edited change to 'Cash Withdrawaling', but list item 'Users' that I edited previously, also change to 'Cash Withdrawaling' as well.
I did not know what is incorrect with my JavaScript. How can I correct that? Thanks
At every click on .fa-pencil you add again event listeners to .saveChange and #active, using local variables like li_element, which are scoped to the callback function. This means that the second time you edit an item, two callbacks are executed, but the first still uses the previous value for li_element, thus setting the new value to the previous edited element too.
You should declare all the event listeners once, and move all the needed variables to the same level as var child.
This should work
$(document).ready(function() {
$('.modal').modal(); // modal
var child;
var li_element;
$('body').on('click', '.fa-pencil', function(e) {
var text = $(this).closest("li").clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text();
child = $(this).closest("li").children();
li_element = $(this).closest('li');
console.log(li_element);
var dataActive = $(this).closest('li').attr('data-act');
var li_icon = li_element.attr('data-icon');
var modal1 = $('#modal1');
var modalBody = modal1.find('.modal-content');
modalBody.find('h4.itemdes').text('');
modalBody.find('.modalBody').html('');
var modalHeader = modalBody.find('h4.itemdes').attr('contenteditable', true).text(text);
dataActive = $(this).closest('li').attr('data-act') == 'Y' ? 'checked="checked"' : '';
ActiveOpt = '<p><label><input type="checkbox" id="active" class="filled-in" ' + dataActive + ' /><span>Active</span></label></p>';
IconOpt = '<p><i class="' + li_icon + '" id="icon_element" aria-hidden="true"></i></p>';
var datahtml = ActiveOpt + IconOpt;
modalBody.find('.modalBody').html(datahtml);
// modalBody.find('.modalBody').append(IconOpt);
});
$('body').on('click', '.saveChange', function() {
var textarea = $('.itemdes').text();
var appendItem = textarea;
li_element.text('').empty().append(appendItem).append(child);
// $(this).closest("li").text('').empty().append(appendItem).append(child);
ActiveOpt = '';
IconOpt = '';
// li_element = '';
});
// Function to check li data-Acive
$('body').on('change', '#active', function() {
li_element.removeAttr('data-act');
// console.log(li_element.prop('checked'));
if ($(this).prop('checked')) {
li_element.attr('data-act', 'Y');
// li_element.attr('checked','checked');
} else {
li_element.attr('data-act', 'N');
// li_element.removeAttr('checked');
}
})
})

How to disable a list item based on condition - ASP.NET C#

I am looking for some advice on the best way to disable two list items based on the account being locked and the value in the state column is equal to 1.
I have a model which generates a random number:
public int IsLocked
{
get
{
var rnd = new Random();
return rnd.Next(0, 2);
}
}
This is my Partial View:
<td class="hidden-xs hidden-sm">
#if (t.IsLocked == 1)
{
<span class="glyphicon glyphicon-lock locked"></span>
}
else
{
<span class="glyphicon glyphicon-ok"></span>
}
</td>
<td class="updateTableRow text-center">
<div class="dropdownContainer btn-group text-right">
<button id="#actionWorkId" type="button" class="btn btn-primary br2 btn-xs fs12 dropdown-toggle songmanagement-btn" data-toggle="dropdown" aria-expanded="false">
Action
<span class="caret ml5"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li>
<a href="#Url.Action("Recordings", "ArtistAccount", new
{
accountcode = fullAccountCode,
songcode = t.SongId
})" id="#recordingWorkId" data-container="body" data-rowhover="editTableRow" class="js_Recordings">Recordings</a>
</li>
<li>
<a href='#Url.Action("EditSong", "ArtistAccount", new
{
songcode = t.SongId,
accountcode = fullAccountCode,
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
})' id="#editWorkId" data-container="body" data-rowhover="editTableRow" class="js_EditSong">Edit</a>
</li>
<li>
Delete
</li>
<li>
<a href="#Url.Action("TuneCodes", "ArtistAccount", new
{
accountCode = fullAccountCode,
workCode = t.SongId,
})" id="#tuneCodeId" data-container="body" data-toggle="tooltip" title="Tune Codes" data-rowhover="editTableRow">Tune Codes</a>
</li>
</ul>
</div>
</td>
</tr>
Is there a way using C# and ASP.NET that I could acheieve this?
Solved my issue using the following code:
<li>
#if (t.IsLocked == 1)
{
<a class="isDisabled" data-toggle="tooltip" title="You cannot edit this song until pending writer edits are approved">Recordings</a>
}
else
{
<a href="#Url.Action("Recordings", "ArtistAccount", new
{
accountcode = fullAccountCode,
songcode = t.SongId
})" id="#recordingWorkId" data-container="body" data-rowhover="editTableRow" class="js_Recordings">Recordings</a>
}</li>
<li>
#if (t.IsLocked == 1)
{
<a class="isDisabled" data-toggle="tooltip" title="You cannot edit this song until pending writer edits are approved">Edit</a>
}
else
{
<a href='#Url.Action("EditSong", "ArtistAccount", new
{
songcode = t.SongId,
accountcode = fullAccountCode,
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
})'
id="#editWorkId" data-container="body" data-rowhover="editTableRow" class="disabled">Edit</a>
}

To get value of the link using Jquery

I am trying to get value of linl which is generated from db using while loop.
When I prees on the link it should show alert window with its name.
while($trackResultRow = mysqli_fetch_assoc($trackResult)){?>
<li>
<a href="#" class="rem"
data-userid="<?php echo $trackResultRow['username']?>"
data-track="<?php echo $trackResultRow['track_name']?>">
<span class="glyphicon glyphicon-thumbs-down pull-right"></span>
</a>
<a href="<?php echo $trackResultRow['track_path']?>">
<span><?php echo $trackResultRow['username']?></span> -
<span><?php echo $trackResultRow['track_name']?></span>
</a>
<hr/>
</li>
<hr>
<?php
}
?>
And Jquery code
$(function() {
$(".rem").on("click", function(e) {
e.preventDefault();
var $link = $(this), // save for later
username = $(this).data("userid"),
track = $(this).data("track");
return alert (username);
});
});
But it does not work....Can anybody help me to fix this code?
You code is working for me, however I noticed that your two anchor tags are very close to each other. Are you adding event listener to first anchor tag and clicking on second? See example code below
$(function() {
$(".rem").on("click", function(e) {
e.preventDefault();
var $link = $(this), // save for later
username = $link.data("userid"),
track = $link.data("track");
return alert(username);
});
});
.glyphicon:after {
content: 'Icon'
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<ul>
<li>
<a href="#" class="rem" data-userid="USERNAME" data-track="TRACK_NAME">
<span class="glyphicon glyphicon-thumbs-down pull-right "></span>
</a>
<a href="track_path">
<span>username</span> -
<span>track_name</span>
</a>
<hr/>
</li>
<li>
<a href="#" class="rem" data-userid="USERNAME" data-track="TRACK_NAME">
<span class="glyphicon glyphicon-thumbs-down pull-right "></span>
</a> -
<a href="track_path">
<span>username</span> -
<span>track_name</span>
</a>
<hr/>
</li>
</ul>

Jquery method doesn't work after creating HTML in JQUERY

var stringhtml = $('<div class="row" id="ao-clonedata">' + '<div class="col-lg-12 form-inline ao-content-padding">' + '<div class="col-xs-1 pull-left ao-from-triggers">'+'<a class="add-link ao-minus-color" title="Remove">'+'<i class="fa fa-minus fa-lg"></i></a>'+'<a class="add-link ao-plus-color ao-spacing-icon" title="Add"><i class="fa fa-plus fa-lg"></i></a>'+'</div> '+'<div class="col-xs-5 dropdown pull-left ao-padding-zero">'+'<button class="btn dropdown-toggle ao-substitute-dropdown ao-dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">'+'<span class="pull-left" id="ao-substitute-from">Select Value</span><i class="caret pull-right custom-dropdown-caret"></i>'+'</button>'+'<ul class="dropdown-menu ao-substitute-ul-dropdown" aria-labelledby="substituteFrom">'+'<li onclick="ChangeSubstituteStatus(1,'+' "Select Value",'+' this)">Select Value</li>'+'</ul>'+'</div>'+'<div class="col-xs-1">'+'<i class="fa fa-arrow-right fa-lg ao-substitute-arrow" id="ao-arrowbutton"></i>'+'</div>'+'<div class="col-xs-5">'+'<div class="form-inline" id="ao-clonetodata">'+'<div class="dropdown ao-substitute-dropdown pull-left">'+'<button class="btn dropdown-toggle ao-substitute-dropdown ao-dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">'+'<span class="pull-left" id="ao-substitute-to">Select Value</span><i class="caret pull-right custom-dropdown-caret"></i>'+'</button>'+' <ul class="dropdown-menu ao-substitute-ul-dropdown" aria-labelledby="substituteTo">'+'<li onclick="ChangeSubstituteToStatus(1, "Select Value", this)">Select Value</li>'+'<li onclick="ChangeSubstituteToStatus(2, "About Time", this)">About Time'+'</li>'+'</ul>'+'</div>'+'</div>'+'</div>'+'</div>'+'</div>');
Creating this HTML on click of an initial(X) button, after creating this html,need to clone this html on click of ".ao-plus-color" (which is there in above HTML). so whatever method i wrote for ".ao-plus-color" is not working.
method for ".ao-plus-color" is :
$(".ao-plus-color").on('click', function () {
CCounter = $("#ao-clonewrapper > .row").length + 1;
var clonedata = $("#ao-clonedata").clone(true).attr("id", "ao-clonedata" + CCounter).appendTo("#ao-clonewrapper");
CCounter++;
var clonedatalength = $("#ao-clonewrapper > .row").length;
if (clonedatalength > 0) {
$("#ao-remove-all").show();
} });
can any one help me out to solve this? thanks in advance!
You should bind the event to already created element ao-plus-color is also dynamically created.Use document like
$(document).on('click','.ao-plus-color', function () {
You need to use event delegation for attaching events to dynamically added elemens:
$("body").on('click',".ao-plus-color", function () {
CCounter = $("#ao-clonewrapper > .row").length + 1;
var clonedata = $("#ao-clonedata").clone(true).attr("id", "ao-clonedata" + CCounter).appendTo("#ao-clonewrapper");
CCounter++;
var clonedatalength = $("#ao-clonewrapper > .row").length;
if (clonedatalength > 0) {
$("#ao-remove-all").show();
}
});

How to build a ul li dynamically from two arrays - Jquery

I have got to build a carousel dynamically from two arrays, as follows:
var arrayBarcode = [123456789, 234567891, 345678912];
var arrayPath = [/assets/image1.jpg, /assets/image2.jpg,/assets/image3.jpg];
To start with, i only have the div class flexslider
I need to build my ul li so that my final html outputs the following:
<div class="flexslider">
<ul class="slides">
<li ean="123456789">
<img src="/assets/image1.jpg" alt="pix" draggable="false">
<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons" title="Remove" href="#">
<i aria-hidden="true" class="icon icon-close-neg">
<span class="sr-only">Remove</span>
</i>
</a>
</li>
<li ean="234567891">
<img src="/assets/image2.jpg" alt="pix" draggable="false">
<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons" title="Remove" href="#">
<i aria-hidden="true" class="icon icon-close-neg">
<span class="sr-only">Remove</span>
</i>
</a>
</li>
<li ean="345678912">
<img src="/assets/image3.jpg" alt="pix" draggable="false">
<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons" title="Remove" href="#">
<i aria-hidden="true" class="icon icon-close-neg">
<span class="sr-only">Remove</span>
</i>
</a>
</li>
</ul>
Please note that the first item in arrayBarcode matches with the first item in arrayPath, etc..
Any help would much be appreciated..
Thanks..
Try this
var arrayBarcode = [123456789, 234567891, 345678912];
var arrayPath = ['/assets/image1.jpg', '/assets/image2.jpg','/assets/image3.jpg'];
var output='<ul class="slides">';
for(var i in arrayBarcode)
{
output+='<li ean="'+arrayBarcode[i]+'">\
<img src="'+arrayPath[i]+'" alt="pix" draggable="false">\
<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons"\ title="Remove" href="#">\
<i aria-hidden="true" class="icon icon-close-neg">\
<span class="sr-only">Remove</span>\
</i>\
</a>\
</li>';
}
output+='</ul>';
$('.flexslider').empty().append(output);
DEMO
Looping through a JavaScript Array is pretty simple. Think about visiting each index of arrays and assign them or a better approach, append to our UL with class slides
First answer was good but not enough since using FOR-IN for Arrays is a bad practice, of course you could choose by having all List Items inside a local variable (as Sridhar R's example) or by append individually.
Here is sample code, didn't tested:
var arrayBarcode = [123456789, 234567891, 345678912],
arrayPath = [/assets/image1.jpg, /assets/image2.jpg,/assets/image3.jpg],
$slides = $('.slides'); // If only one single class available on your HTML Doc
if (arrayBarCode.length != arrayPath.length)
{
console.log('Both array should be the same size');
return;
}
for (var i = 0; i < arrayBarcode.length; i++)
{
var html= '<li ean="' + arrayBarcode[i] + '">\
<img src="' + arrayPath[i] + '" alt="pix" draggable="false">\
<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons" title="Remove" href="#">\
<i aria-hidden="true" class="icon icon-close-neg">\
<span class="sr-only">Remove</span>\
</i>\
</a>\
</li>';
$slides.append(html);
}
Roughly, it would look as below:
$('div.flexslider').append('<ul class="slides"></ul>');
var aElement = $('<a data-statsaction="coupon-basket-remove" data-statscategory="coupon-buttons" title="Remove" href="#">
<i aria-hidden="true" class="icon icon-close-neg">
<span class="sr-only">Remove</span>
</i>
</a>');
$.each(arrayBarcode, function(index, value){
var liElement = $('<li></li>').attr('ean', value);
var imgElement = $('<img alt="pix" draggable="false">').attr('src', arrayPath[index]);
liElement.append(imgElement).append(aElement.clone());
$('ui.slides').append(liElement);
});
Plus, the array arrayPath is missing "":
var arrayPath = ['/assets/image1.jpg', '/assets/image2.jpg','/assets/image3.jpg'];

Categories

Resources