JQuery Clear <ul> Two Menus Away - javascript

I have three menus: College, Department and Program. When a College is clicked, the list of Departments belonging to that College is shown. When a Department is clicked, the list of Programs belonging to that Department is shown.
My problem is that when I click a new College, the Departments re-populate in the second list but I can't get the Programs in the third column to clear out. I've tried a bunch of different things with .nextAll() and .siblings() and whatnot, but nothing has worked yet.
Here's the HTML:
<div class="row">
<div class="col-xs-4">
<h4>Colleges</h4>
<ul class="colleges-menu">
<?php CommonFunctions::getCollege('list'); ?>
</ul>
</div>
<div class="col-xs-4">
<h4>Departments</h4>
<ul id="departments" class="colleges-menu">
</ul>
</div>
<div class="col-xs-4">
<h4>Programs</h4>
<ul id="programs" class="colleges-menu">
</ul>
</div>
And the JQuery:
function ajaxLists(){
var entity = '.' + $(this).attr('class');
var nextEntity;
var value;
var data;
switch(entity){
case '.college':
nextEntity = '#departments';
value = $(this).val();
data = {list_college: value};
break;
case '.departments':
nextEntity = '#programs';
value = $(this).val();
data = {list_departments: value};
break;
default:
break;
}
//this should ONLY run if we are selecting a college or department
if(entity == '.college' || entity == '.departments'){
$("body").css("cursor", "progress");
$.ajax({
url: "sort_college.php",
type: "post",
data: data,
success: function(info){
$(nextEntity).html('');
$(nextEntity).append(info);
console.log(info);
},
error: function(){
alert("there's an error with AJAX");
}
}).done(function(){
$("body").css("cursor", "default");
}); //end ajax
}
}

As you mentioned that your code should fit further elements added in the future, you need to make sure you don't rely on hardcoded IDs, classes, etc.
This should solve your problem, or at least give you a good ground to go from there:
$(function () {
$('.col-xs-4 .colleges-menu').on('click', 'li', function () {
// Go up in this element parents until you reach the div.
// Then you go to its next sibling and grab the ul.
var nextEntity = $(this).parents('.col-xs-4').next().find('ul');
// Self explanatory.
var value = $(this).val();
// Variable to store the data.
var data = {};
// If there's a nextEntity element, it means you didn't reach the last
// set of options.
if (nextEntity) {
// Creating a property for data that is based in a variable.
data["list_" + nextEntity.attr("id")] = value;
$("body").css("cursor", "progress");
$.ajax({
url: "sort_college.php",
type: "post",
data: data,
success: function (info) {
nextEntity.html('');
nextEntity.append(info);
console.log(info);
},
error: function () {
alert("there's an error with AJAX");
}
}).done(function () {
$("body").css("cursor", "default");
});
}
});
});

Related

How can i assing a different class after a success ajax response

I'm working in a net core app, i made a HttpPost function to know if an user marked like.
This is the function code:
var likesCancion = (from likesCanc in _context.table
where likesCanc.SongId == idCancion && likesCanc.UserId == idUser
select likesCanc.Likes).FirstOrDefault();
if (likesCancion == 1)
{
return 1;
}
else
{
return 0;
}
I have this:
<div class="col-3 col-sm-2 col-md-2">
<i class="far fa-heart" id="heart" data-idAudio = #song.Id>
<span class="badge" >#song.Likes</span>
</i>
</div>
This is the <div> that I want to change at the start of the page if the user liked it or not.
The #song.Likes its data filled from the database.
I made an ajax request inside a for loop and get the respond of my HttpPost function:
const iconosCorazon = document.querySelectorAll('#heart');
setTimeout(function () {
let idUser = $('#inputidUsuario').val();
function makeRequest(i)
{
$.ajax({
type: "POST",
url: "checkHeart",
data: { idCancion: i, idUser: idUser },
dataType: "text",
success: function (msg) {
console.log(msg);
**if (msg == 1) {
$('.fa-heart').removeClass("far text-dark");
$('.fa-heart').addClass("fa text-danger");
}
else
{
$('.fa-heart').removeClass("fa text-danger");
$('.fa-heart').addClass("far fa-heart");
}**
},
error: function (req, status, error) {
console.log(msg);
}
});
}
for (var i=0;i<iconosCorazon.length;i++) {
let idCancion = iconosCorazon[i].getAttribute('data-idAudio');
makeRequest(idCancion);
}
I want to assign the css class to the correct element coming from the function result.
The issue here its that ajax execute all the elements at once and change the classes only with the last lopped element. So the question is how can i assign the rigth class to each div element. eg: If result == 1 paint red, if result == 0 paint other color.
Sorry for my bad english
Im trying to make this code works
You should use $(".fa-heart:eq(index)") to locate the each element with same class name. Sample code below:
$(".div_test:eq(0)").css("border","2px solid yellow");
Test Result:

Ajax search doesn't work the second time (ASP.NET MVC)

I have a problem changing items after searching.
I looked at similar threads but found no solution there :(
It looks like the first time the page loads well - the first time the entire Index.cshtml page is loaded which contains a collection of books in the selected category.
There is a search engine on the page - after searching for "manual" - ajax correctly replaces elements with those containing "manual" in the name.
Then when I enter something into the search engine a second time (for example "exercises") - the content of the page does not change any more.
I tried to debug and I see that new items are correctly downloaded from the database - the condition "if (Request.IsAjaxRequest ())" is true and the items are passed to partial view - there the "foreach" loop goes through them. Unfortunately, after _Partial, nothing happens.
I can't find a mistake - the strangest thing is that the first ajax call works fine - only the second (and subsequent) bad.
CatalogController.cs
public ActionResult Index(string categoryName = null, string searchQuery = null)
{
if (categoryName == null)
categoryName = (db.Categories.Find(1)).Name;
var category = db.Categories.Include("Books").Where(x => x.Name.ToLower() == categoryName).Single();
var books = category.Books.Where(x => (searchQuery == null || x.Title.ToLower().Contains(searchQuery.ToLower()) || x.SubTitle.ToLower().Contains(searchQuery.ToLower()) || x.Level.ToLower().Contains(searchQuery.ToLower())) && !x.Inaccessible);
if (Request.IsAjaxRequest())
return PartialView("_PartialBooksList", books);
else
return View(books);
}
Index.cshtml
<form class="o-search-form" id="search-form" method="get" data-ajax="true" data-ajax-target="#booksList">
<input class="o-search-input" id="search-filter" type="search" name="searchQuery" data-autocomplete-source="#Url.Action("SearchTips")" placeholder="Search" />
<input class="o-search-submit" type="submit" value="" />
</form>
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
#section Scripts
{
<script src="~/Scripts/jquery-3.5.0.js"></script>
<script src="~/Scripts/jquery-ui-1.12.1.js"></script>
<script>
$(function () {
var setupAutoComplete = function () {
var $input = $(this);
var options =
{
source: $input.attr("data-autocomplete-source"),
select: function (event, ui) {
$input = $(this);
$input.val(ui.item.label);
var $form = $input.parents("form:first");
$form.submit();
}
};
$input.autocomplete(options);
};
var ajaxSubmit = function () {
var $form = $(this);
var settings = {
data: $(this).serialize(),
url: $(this).attr("action"),
type: $(this).attr("method")
};
$.ajax(settings).done(function (result) {
var $targetElement = $($form.data("ajax-target"));
var $newContent = $(result);
$($targetElement).replaceWith($newContent);
$newContent.effect("slide");
});
return false;
};
$("#search-filter").each(setupAutoComplete);
$("#search-form").submit(ajaxSubmit);
});
</script>
}
_PartialBooksList
#model IEnumerable<ImpressDev.Models.Book>
#using ImpressDev.Infrastructure
<div class="row">
#foreach (var book in Model)
{
<div class="col-12 col-xl-4">
<a class="o-shop-link" href="#Url.Action("Details", "Catalog", new { bookId = book.BookId })">
<div class="o-shop-item">
<img class="o-shop-img" src="#Url.BookPhotoSourcePath(book.PhotoSource)" />
<div class="o-shop-text">
<h2>#book.Title</h2>
<h6>#book.SubTitle - #book.Level - <b>#book.Price zł.</b></h6>
+ Add to cart
</div>
</div>
</a>
</div>
}
</div>
Please help
I am not sure if this is the case, but try to change this code:
$($targetElement).replaceWith($newContent);
To this:
$($targetElement).html($newContent);
I think the problem is the div element with id="booksList" is replaced after first search. So you don't have this element in the second search.
I looked through the code step by step and found a solution to my problem.
In the first search, replace id="booksList"
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
partial view in which there was only without id = booksLists.
In the next search there was no ID in this place and there was nothing to replace.

jQuery nth-child only selecting first element

I am trying to add a on click function on the specific child of .article which will show certain wikipedia link base on the pageid received from the request. But all the .article are pointing to the same page.
HTML:
<section id="body-article">
<div id="body-container">
</div>
</section>
JavaScript(jQuery):
function SendRequest(searchEntry){
$.ajax({
url: `https://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch=${searchEntry}`,
type: 'GET',
dataType: 'jsonp',
headers: {'Api-User-Agent': 'WikiReader/0.1.0'}
}).done(function(data, status) {
console.log(data);
GenerateArticle(data);
}).fail(function(data, status) {
console.log("ERROR! " + status);
});
}
function GenerateArticle(data){
//shows all the article in a div
var totalArticleLength = data.query.search.length;
for(var i=0;i<totalArticleLength;i++){
var title= data.query.search[i].title;
var pageid=data.query.search[i].pageid;
var snippet=data.query.search[i].snippet;
//responsible for showing single data
CreateSingleArticle(title,pageid,snippet);
// PROBLEM IS WITH THE BELOW LINE
$(`.article:nth-child(${i+1})`).on("click",function(){
window.open(`https://en.wikipedia.org/?curid=${pageid}`, 'Wikipedia', 'window settings');
})
}
}
function CreateSingleArticle(title,pageid,snippet){
//creates a individual data
html =
`<div class="article">
<div class="side-bar"></div>
<div class="article-container">
<div class="article-header">
${title}
</div>
<div class="snippet">
${snippet}
</div>
</div>
</div>`
$("#body-container").append(html);
}
Answer is quite simple. You ran into javascript scope problem. Have a look at the immediate function call. Read more here. http://tobyho.com/2011/11/02/callbacks-in-loops/
for(var i=0;i<totalArticleLength;i++){
(function(index, pageId){
var title= data.query.search[index].title;
var pageid=data.query.search[index].pageid;
var snippet=data.query.search[index].snippet;
//responsible for showing single data
CreateSingleArticle(title,pageid,snippet);
// PROBLEM IS WITH THE BELOW LINE
$(`.article:nth-child(${index+1})`).on("click",function(){
window.open(`https://en.wikipedia.org/?curid=${pageId}`, 'Wikipedia', 'window settings');
})
})(i, data.query.search[i].pageid)
}

Stop .blur() function from triggering on select statement but remain on span

I am trying to create an inline edit function to trigger differently on different elements.
I have tried to use other plugins but haven't been able to get them to do exactly what I want so have decided to try to create a plugin of my own, while learning jquery along the way.
The issue I am currently having is that I have a .blur event that is triggering on a span element correctly and this is what I want but when the element is a select element I don't want the blur event to trigger. As the code is below the blur event triggers and it is not the desired result. Can anybody advise how I can only trigger the blur() event on span elements and nothing else
$('.inlineEdit-jmc').inlineEditJmc({
fieldsArray: {
table-column1: 'field-table-column1',
table-column2: 'field-table-column2'
}
});
(function ( $ ) {
$.fn.inlineEditJmc = function(options) {
//Set Default Settings
console.log(options);
var settings = $.extend({
'pk': null,
'table': null,
'field': null,
'url': null,
'type': null,
'fieldsArray': null
},options)
if(settings.fieldsArray == null){}else{
var fields = new Array();
}
function load_settings(this_selected){
settings['pk'] = this_selected.attr("data-pk"); // pk of table to be updated
settings['table'] = this_selected.attr("data-table"); // table name of table to be updated
settings['field'] = this_selected.attr("data-field"); // name of the field in the table being updated
settings['url'] = this_selected.attr("data-url"); // url for the ajax call to be sent to.
settings['type'] = this_selected.attr("data-type"); // type of input being used. Input or Select
settings['value'] = this_selected.text(); //
settings['class'] = this_selected.attr("class"); // The Class
console.log(settings['table'] +' '+ settings['value']+ ' '+ settings['class']);
// if there are optionional inserts passed lets grab them
console.log('passed options:');
if(settings.fieldsArray == null){}else{
//var fields = [];
$.each(settings.fieldsArray,function(k,v){
//console.log('settings['+k+'] '+this_selected.attr(v));
$obj={};
$obj[k] = this_selected.attr(v);
fields.push($obj);
});
}
}
$(this).on('mouseover', function(event) {
$(this).addClass("ui-state-hover");
}).on('mouseout', function(event) {
$(this).removeClass("ui-state-hover");;
});
if($(this).is('select')){
$(this).on('change', function(){
alert('changed');
alert($(this).val());
//console.log($(this));
//load_settings($(this));
var nt = $(this).text();
var jsonstring = JSON.stringify(fields);
// AJAX
});
}
if($(this).is('span')){
$(this).on("blur", function () {
alert('span');
load_settings($(this));
var nt = settings['value']
console.log('comment: '+settings['value']);
// we are going to update the db here.
console.log('Insert');
console.log(fields);
var jsonstring = JSON.stringify(fields);
console.log(jsonstring);
$.ajax({
type: 'POST',
url: settings['url'],
data: {
fieldsArray: fields,
pk: settings['pk'],
table: settings['table'],
field: settings['field'],
value: settings['value']
},
cache: false,
success: function(data,status){
console.log(data);
}
});
});
}
}
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<td class=''>
<select class='inlineEdit-jmc' ><option value='0' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore'>NO</option>
<option value='1' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore' selected>YES</option>
</select></td>
<td class=''><span class='inlineEdit-jmc' id='input' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='comment' contenteditable='true'>Text that can be edited</td>
Try this code section in place of yours that begins if($(this).is('span')){
$(this).on("blur", function ()
$("span").on("blur", function () {
// your function content here
});
$("span select").on("blur", function () {
e.stopPropagation();
});
The two alternative selectors act like a case statement in jQuery

JQuery Closest Method to change HTML

I am working on a project, i have two anchors in my View(for voting functionality),
I have a div inside which i am having a <ul> and in 3 <li> i am having anchor for upvote,vote count (in <h2>) and anchor downvote respectively
I want functionality that when i click on any anchor, the h2 html show the vote count, i've implemented the functionality but because of i am unable to do this,
this is my View
<div class="voting" style="margin-left:20px;">
<ul>
<li class="addvote"><a href="#" class="voteAnswer" answerid="#answer.AnswerID" name="Voted">
Up</a></li>
<li class="votecounter">
<h2>
#answer.AnswerLikes.Where(a => a.IsActive == true).Count()</h2>
</li>
<li class="subvote"><a href="#" class="voteAnswer" answerid="#answer.AnswerID" name="Voted">
Down</a></li>
</ul>
</div>
and this is my JS
$(".voteAnswer").click(function (event) {
var answerid = $(this).attr('answerid');
var name = $(this).attr('name');
var id = $(this).attr('id');
var output = $(this);
$.ajax({
url: ResourceAjaxUrl.VoteUnvoteTheAnswer,
type: "POST",
data: JSON.stringify({ answerID: answerid }),
dataType: "html",
contentType: "application/json; charset-utf-8",
success: function (Result) {
alert("Voted");
// $(output).html("Voted (" + Result + ")");
$(output).closest("li").find("h2").html(Result);
$(output).attr("name", "Voted");
},
error: function (msg) {
alert("Unable to Vote answer: " + msg);
}
});
event.preventDefault();
});
i have tried using $(output).closest("li").find(".votecounter") but its still not working
The UL is the closest common ancestor.
Try:
$(output).closest("UL").find(".votecounter")
there are some problems in your code .
here
$(".voteAnswer").click(function (event) {
var id = $(this).attr('id');
there is no attribute id in .voteAnswer
and also how do you differentiate upvote and downvote .
you have to check the anchor's parent li tag's class and check it is upvote or down vote .
also you can select the .votecounter
simply by
$(".votecounter").find("h2").html(Result);
or
$(output).closest("ul").find(".votecounter");

Categories