Unable to remove css class and add a new one - javascript

I have this function that goes through each breadcrumb in a navbar and I want to change the styling of the breadcrumb depending what page they are on.
Here is the basic HTML of the breadcrumb navbar
<div id="WCBar">
<div class="bc_nav current span" id="bc_main">
<a class="bc_1" id="lnkCrumb" href="javascript:__doPostBack('ctl00$breadcrumbnav1$ctl00$lnkCrumb','')">
<li>Account Info</li></a>
<span class="step-arrow"></span>
<input name="ctl00$breadcrumbnav1$ctl00$hdnPageName" id="hdnPageName" type="hidden" value="WCQuoteMain2.aspx">
</div>
<div class="bc_nav a" id="bc_main">
<a class="aspNetDisabled bc_2" id="lnkCrumb"> <li>Rate</li></a>
<span class="step-arrow"></span>
<input name="ctl00$breadcrumbnav1$ctl01$hdnPageName" id="hdnPageName" type="hidden" value="WCQuoteRatingV4.aspx">
</div>
<div class="bc_nav a" id="bc_main">
<a class="aspNetDisabled bc_3" id="lnkCrumb"><li>Questions</li></a>
<span class="step-arrow"></span>
<input name="ctl00$breadcrumbnav1$ctl02$hdnPageName" id="hdnPageName" type="hidden" value="questions.aspx"></div>
<div class="bc_nav last" id="bc_main">
<a class="aspNetDisabled bc_4" id="lnkCrumb"><li>Final</li></a>
<span class="step-arrow" style="background-image: none;"></span>
<input name="ctl00$breadcrumbnav1$ctl03$hdnPageName" id="hdnPageName" type="hidden" value="managesubmission.aspx"></div>
I then call this function in Javascript:
function WCBar(pagename, iframepagename, currentSet) {
$('.bc_nav', $('#WCBar')).each(function () {
iframepagename = $(this).find('input[id*="hdnPageName"]').attr('value');
var bcMain = $(this).find('div[id*="bc_main"]');
var lnkCrumb = $(this).find('a[id*="lnkCrumb"]');
if (pagename == iframepagename) {
//bcMain.addClass("current span");
bcMain.attr("class", "current span");
currentSet = 1;
// notify server
$.ajax({
type: "POST",
url: window.location.pathname + "/UpdateIFrameBreadcrumb",
data: "{'pagename':'" + iframepagename + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// alert(msg.d);
},
error: function (msg) {
// alert(msg.d);
}
});
}
else {
if (lnkCrumb[0].href.length > 1) { //&& currentSet == 0
//bcMain.attr("class", "bc_nav enabled span");
bcMain.removeClass("bc_nav");
bcMain.addClass("bc_nav enabled span");
}
else {
//bcMain.attr("class", "bc_nav a");
bcMain.removeClass();
bcMain.addClass("bc_nav a");
}
}
});
}
When I mouse over bc_Main during a debugging session, context > className shows the proper class but trying to determine if bc_main has a class results in
?bcMain.hasClass('bc_nav');
false
in Visual Studio's Immediate window.
Furthermore, trying to determine what the values are in class gets me an undefined error.
var x = bcMain.attr('class');
undefined
No class is ever removed from bc_main, no matter if I try .removeClass() and leave it empty or try .removeClass('bc_nav');
I have checked to make sure nothing is defaulting elsewhere and can't find anything.
Thanks for your help.

It looks like a scope issue. You are using THIS to perform your find which shouldn't find itself. Your .bc_nav elis actually your #bc_main el, so you might as well just treat $(this) as bcMain. I don't know why you are iterating on both .bc_nav and #WCBar, seems like you should only use .bc_nav.
$('.bc_nav', $('#WCBar')).each(function () {
...
var bcMain = $(this).find('div[id*="bc_main"]');
saying $(this) in this instance is the same as saying $('.bc_nav') so you are essentially doing $('.bc_nav').find('div[id*="bc_main"]'); which won't work since #bc_main isnt' a child of .bc_nav.

If you are trying to empty the class attribute use:
$('#myElementID').removeAttr('class');
or this
$('#myElementID').attr('class', '');
To remove a specific class, you have to use the class name:
$('#myElementID').removeClass('myClassName');
Also, FWIW, in the else statement, this line
bcMain.removeClass("bc_nav");
is pointless, being that it's followed by this one
bcMain.addClass("bc_nav enabled span");

Related

How do I access the list element that is appended after html was created

I am adding a list element using the append function in jQuery, how do I reference this on my onclick function? Below is my code
$(function() {
let $movies = $('#showList')
let $m = $('#show')
$.ajax({
method: 'GET',
url: 'http://api.tvmaze.com/shows',
success: function(movies) {
$.each(movies, function(i, movie) {
$movies.append('<li id="list">' + movie.name + '</li>')
})
}
})
});
$('#list').on('click', 'a', function(event) {
console.log('here');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<h1 id='bruh'>TV Shows</h1>
<ul id="showList"></ul>
<div id="show"></div>
<form id="searchForm">
<input type="text" id="search_term">
<label for="text">Search</label>
<button>Submit</button>
</form>
<a id="homelink" href="#" hidden>Back to All Shows</a>
There is no message in console when I click on the link.
The attribute id should unique in a document, you can use class instead.
Try $('body').on('click', '.list a', function(event){....
Demo:
$(function() {
let $movies = $('#showList')
let $m = $('#show')
$.ajax({
method: 'GET',
url: 'http://api.tvmaze.com/shows',
success: function(movies) {
$.each(movies, function(i, movie) {
$movies.append('<li class="list">' + movie.name + '</li>')
})
}
})
});
$('body').on('click', '.list a', function(event) {
console.log('here');
event.preventDefault();//stay on the same page
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<h1 id='bruh'>TV Shows</h1>
<ul id="showList"></ul>
<div id="show"></div>
<form id="searchForm">
<input type="text" id="search_term">
<label for="text">Search</label>
<button>Submit</button>
</form>
<a id="homelink" href="#" hidden>Back to All Shows</a>
You can give the appended divs a class then call them by it like this :
$movies.append('<li class="movie" id="list">'+ movie.name +'</li>');
//then later
let movies = $('.movie');
console.log(movies);
but if you meant to execute this script right after the ajax request
then you should call a function in the ajax success since ajax is async and the moment you execute a jquery select , the elements are still not there because ajax takes more time to retrieve the data put it in the document...
you can make a getMovies() to execute there like this:
//declare this outside the ajax
let movies = []
function getMovies(){
return $('.movie');
}
then
//ajax
success: function(){
movies = getMovies(); //add this line
}
there you go now you have movies stocked inside the 'movies' array
It seems you are running into a race condition of sorts. You are building the list using an asynchronous ajax request to an API. Before that completes, you are then attaching the Javascript code to trigger an event.
What you need to do is add the callback inside of the ready block after the list data is retrieved and the list is created.

Add class/text to a jQuery element

I'm trying to clone the following HTML template and add class/text to it.
<template id="result">
<section>
<div class="alert">
<p class="someText"></p>
</div>
</section>
</template>
So the user first submits a question:
<div id="answer"></div>
<section class="row">
<form id="form" action="/" method="GET">
<div>
<input id="question" />
</div>
</form>
</section>
Then the script executes:
$(document).ready(function () {
$('#form').on('submit', function (event) {
$.ajax({
data: {...},
type: 'GET',
url: '/result'
}).done(myFunction);
});
});
And finally it clones the template (ID #result), add a class to the element containing a class alert and add some text to the element containing a class someText, and appends it to the element containing ID #answer.
function myFunction(result) {
clone = $('#result').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
The function executes (I added a console.log() to the end of it to be sure) but nothing is appending.
Consider the following.
function create_message(result) {
var section = $("#result").children().clone();
$('.alert', section).addClass(result.status);
$('.address', section).text(result.address);
$('.extract', section).text(result.extract);
$('.question', section).text(result.question);
section.appendTo("#answer");
}
This creates a clone of all the HTML Elements inside the Template with ID result. It then finds specific classes inside the Object section and makes changes.
You can also do the following.
section.find(".alert").addClass(result.status);
See more: https://api.jquery.com/clone/
Update
Use <template> to hold some content that will be hidden...
So if you Clone the Template and append it, it will still be hidden.
Try the following:
function myFunction(result) {
clone = $('#result > section').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
Update 2
I don't use <template>, so I had to re-read some stuff. It has a content portion, so it has an HTML Fragment contained within and is not like other HTML Elements, more like an iFrame. So we need to collect the content versus cloning it.
See: How to use HTML template tag with jQuery?
Here is a working example: https://jsfiddle.net/Twisty/rpd9h0mf/20/
Your code will be something more like the following.
JavaScript
$(function() {
function showResults(results) {
var clone = $($('#result').html());
$('.alert', clone).addClass(results.class);
$('.someText', clone).text(results.answer);
clone.appendTo("#answer");
}
$('#question-form').submit(function(event) {
event.preventDefault();
$.ajax({
data: {
q: $("#question").val()
},
type: 'GET',
url: '/result',
success: showResults
});
});
});
This creates a new jQuery Object based on the HTML Content of the Template. Now you can properly edit it and append it.

How to modify values of a template html inside a variable

I have an Ajax call that gets different description, and url address of a video:
function TraerInstructivos() {
$.ajax({
type: "GET",
url: '<%= Page.ResolveUrl("~/Instructivo/Instructivos.aspx") %>' + '/TraerInstructivos',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var res = JSON.parse(response.d);
$.each(res, function (i, item) {
DibujarVideo(item);
});
},
error: function (response) {
alert("Error");
}
});
};
Now DibujarVideo is the method that will grab the template I have in my ascx, make a copy and then append it. This is the HTML of the ascx:
<div id="Videos">
</div>
<template id="video-elem">
<div class="row">
<div class="col-lg-4">
<font id="video-desc" size="3"></font>
<br />
<br />
<p><a id="video-ref" class="btn btn-secondary" href="#" role="button">Mira el Video ยป</a></p>
</div>
</div>
<br />
<hr />
</template>
Right now, the method that copies the template html looks like this:
function DibujarVideo(video) {
var elemACrear = $("#video-elem").html();
$(elemACrear).find("#video-ref").attr("href", video.DireccionVideo);
console.log(elemACrear);
$("#Videos").append(elemACrear);
}
What I see in the console log, and the page is that the value of href is not changing, but If I save this in a variable I see the changes for example:
var elem = $(elemACrear).find("#video-ref").attr("href", video.DireccionVideo);
So I reckon is not the same changing/manipulating the DOM tree in a page vs in a variable.
How can I change that href inside my elemACrear variable?
Im learning jQuery, every help appreciated.
You've already diagnosed and solved the issue without following the logic through. You simply need to provide the jQuery object you create in the elem variable to the append() call, like this:
function DibujarVideo(video) {
var elemACrear = $("#video-elem").html();
var $elem = $(elemACrear);
$elem.find("#video-ref").attr("href", video.DireccionVideo);
$("#Videos").append($elem);
}

How to create <div> with several children in loop

I created a div with a class name of div class = "postWindow".
html:
<div class = "postWindow">
<div class = "userName">Initial Name</div>
<div class = "postTitle">Init title</div>
</div>
Now, what I am trying to achieve is that I can create upto 10 of these in a single html window. (upto because the amount of posts may vary from 1-10 and the amount is dynamic)
I tried using the appendChild() method but realized it only populated the div as the new element. It did not create a new postWindow
My .js file has the following function:
function createPost(){
var count = 0;
while(count < upLimit){
$.ajax({
url: root + '/posts/'+curr,
type: "GET",
dataType: "JSON",
success: function(response){
postJson = response;
//im lost here
}
});
count++;
}
Using console.log my Json response is something like this
0: Object
title: "First post"
body: "This is a post"
id: 1
userId: 27
.
.
.
100: //same format of data as object 0
Any help would be appreciated! :D
Here's a simple fiddle to demonstrate the above: https://jsfiddle.net/LLceoLwg/
HTML:
<div class="container">
<div class = "postWindow">
<div class = "userName">Initial Name</div>
<div class = "postTitle">Init title</div>
</div>
</div>
jQuery:
$(document).ready(function(){
for(var i=0; i<10; i++){
$(".postWindow").parent().append("<div class='postWindow'><div class='userName'>Initial Name</div><div class='postTitle'>Init title</div></div>");
}
});

Why i can't append some html in to the desired element?

i hope someone can lend me a hand, i have been trying to insert some code via .post using jquery everything seem to works fine but the response data doesn't insert on the conhere div
html
<div class="ui-grid-a">
<div class="ui-block-a main">
<div data-role="fieldcontain">
<input type="checkbox" value="1##2##2##1080|2" name="pro1" id="pro1" class="checkpro">
<label for="pro1"> product description
</label>
</div>
</div>
<div class="ui-block-b side">
<div class="conhere">
</div>
</div>
</div>
javascript
$( document ).on( "change",".checkpro", function(event, ui) {
var checkedpro = $(this).is(':checked')?1:0;
if (checkedpro==1){
var variable=$(this).val().split("##");
$.post("product.php", h{row :contenedor[0],
mul : variable[1],
can : variable[2],
pri: variable[3],
id : variable[4]},
function(data){
$(this).parents(".ui-grid-a").find(".conhere").empty().append(data).trigger('create');
});
else{
$(this).parents(".ui-grid-a").find(".conhere").empty();
}
There are two issues, both with this code:
$(this).parents(".ui-block-a").find(".conhere")...
The first issue is that the .conhere element doesn't exist within .ui-block-a. It exists in .ui-block-b. (And both .ui-block-a and .ui-block-b are within .ui-grid-a.) find only looks at descendant elements of the elements in the set where it's called.
The second issue is that this is no longer what it was outside the call to $.post. So we want to capture it in a variable we close over.
Finally, in this case I would use closest, not parents:
$(this).closest(".ui-grid-a").find(".ui-block-b .conhere")...
// or
$(this).closest(".ui-grid-a").find(".conhere")...
Combining the above:
$(document).on("change", ".checkpro", function (event, ui) {
var $elm = $(this), // <== Remember $(this)
checkedpro = $elm.is(':checked') ? 1 : 0;
if (checkedpro == 1) {
var variable = $elm.val().split("##");
$.post("product.php", h {
row: contenedor[0],
mul: variable[1],
can: variable[2],
pri: variable[3],
id: variable[4]
},
function (data) {
// v-------------------------------- use it, and note 'closest'
$elm.closest(".ui-grid-a").find(".conhere").empty().append(data).trigger('create');
});
} // <== This } was also missing
else {
$elm.closest(".ui-grid-a").find(".conhere").empty();
}

Categories

Resources