Error in element count with Jquery due to click to update - javascript

I am counting the number of elements with span class check_box and uncheck_box When the item with check-box is clicked, its span change to uncheck-box and vice versa. The counter somewhat works, however, I need to click on an element first to trigger it (the count should have already have changed) and then when i click on an element the second time, the count changes. In this instance i should have got two counts but I only get one.
How can this be rectified?
HTML:
<span>All</span>
<span>Completed</span>
<span>Incomplete</span>
<ul class="leftlist">
<li class="todo" id="1011" itemage="1"><a href="javascript:;">
<a href="javascript:;" class="strike">
<span class="check_box cb"></span>
<p>Option 1 Complete</p> </a>
</li>
<li class="todo" id="1011" itemage="1"><a href="javascript:;">
<a href="javascript:;">
<span class="uncheck_box cb"></span>
<p>Option 1 Incomplete</p> </a>
</li>
<li class="todo" id="1011" itemage="1"><a href="javascript:;">
<a href="javascript:;" class="strike">
<span class="check_box cb"></span>
<p>Option 1 Complete</p> </a>
</li>
<li class="todo" id="1011" itemage="2"><a href="javascript:;">
<a href="javascript:;">
<span class="uncheck_box cb"></span>
<p>Option 2 InComplete</p> </a>
</li>
jQuery
var $checkboxes = jQuery('li.todo a'),
$completeCount = jQuery('.complete-count'),
$incompleteCount = jQuery('.incomplete-count');
var updateCount = function(){
$completeCount.text(jQuery('.check_box').length);
$incompleteCount.text(jQuery('.uncheck_box').length);
};
$checkboxes.on('click', updateCount);
updateCount();
Jquery that changes the elements
(function($){
$('li.todo').click(function(){
if($(this).find('.uncheck_box').length >0){
var _t=$(this).find('.uncheck_box');
_t.removeClass('uncheck_box');
_t.addClass('check_box');
m_val='1';
$(this).find('a').addClass('strike');
}else{
m_val='0';
var _t=$(this).find('.check_box');
_t.removeClass('check_box');
_t.addClass('uncheck_box');
$(this).find('a').removeClass('strike');
}
var m_key=jQuery(this).attr('id');
jQuery.ajax({
type: "POST",
url: "<?php echo get_template_directory_uri(); ?>/ajax_get.php",
data: { meta_key: m_key, meta_value: m_val},
beforeSend: function( ) {
//jQuery(this).attr("disabled", true);
},
success:function(){}
})
});

The first problem here is the class change handler is registered to the li elements(making use of event bubbling) where as the counter handler is registered to the anchor element. So the anchor handler will get executed before the class is updated so attach the click handler to the li element instead of anchor element
var $checkboxes = jQuery('li.todo'),
$completeCount = jQuery('.complete-count'),
$incompleteCount = jQuery('.incomplete-count');
var updateCount = function(){
$completeCount.text(jQuery('.check_box').length);
$incompleteCount.text(jQuery('.uncheck_box').length);
};
$checkboxes.on('click', updateCount);
updateCount();
also make sure that this event handler is registered after the class change handler is registered
A better solution will be is to use a custom event which will be triggered once the class is changed
$('li.todo').click(function () {
if ($(this).find('.uncheck_box').length > 0) {
var _t = $(this).find('.uncheck_box');
_t.removeClass('uncheck_box');
_t.addClass('check_box');
m_val = '1';
$(this).find('a').addClass('strike');
} else {
m_val = '0';
var _t = $(this).find('.check_box');
_t.removeClass('check_box');
_t.addClass('uncheck_box');
$(this).find('a').removeClass('strike');
}
//trigger a custom event here
$(this).trigger('updateclass')
var m_key = jQuery(this).attr('id');
jQuery.ajax({
type: "POST",
url: "<?php echo get_template_directory_uri(); ?>/ajax_get.php",
data: {
meta_key: m_key,
meta_value: m_val
},
beforeSend: function () {
//jQuery(this).attr("disabled", true);
},
success: function () {}
})
});
then the count handler will listen to the custom event instead of the click handler
var $checkboxes = jQuery('li.todo'),
$completeCount = jQuery('.complete-count'),
$incompleteCount = jQuery('.incomplete-count');
var updateCount = function(){
$completeCount.text(jQuery('.check_box').length);
$incompleteCount.text(jQuery('.uncheck_box').length);
};
$checkboxes.on('updateclass', updateCount);
updateCount();

Related

Tweeting out a quote from Object.textContent

I've build a page where I pull a random quote from an API and all is working in that regard, but I can't seem to pull the textContent and append it to the tweet button.
Here is my code:
HTML
<div id="quote-box">
<div id="quote-copy">
<i class="fa fa-quote-left" id="quotation"> </i>
<span class="text" id="random-quote"></span>
</div>
<div id="quote-author">
- <span class="author"></span>
</div>
<div id="quote-buttons">
<a class="button" id="instagram" title="follow me on IG!" target="_blank" href="https://www.instagram.com/dopeland/"><i class="fa fa-instagram" aria-hidden="true"></i> Instagram</a>
<a class="button" id="tweet-this" title="Tweet This Quote!" href="https://twitter.com/share" target="_blank" data-size="large"><i class="fa fa-twitter" aria-hidden="true"></i> Tweet This!</a>
<a class="button" id="get-quote" title="Generate a new quote!" href="">New Quote</a>
</div>
</div>
Javascript
function getQuote(){
$.ajax({
url: 'https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1',
success: function(data) {
var post = data.shift();
$('.author').text(post.title);
$('.text').html(post.content);
},
cache: false
});
};
function changeColor(){
var colors = ['#7A918D', '#93B1A7', '#99C2A2', '#C5EDAC', '#DBFEB8'];
var randNum = Math.floor(Math.random() * (colors.length - 0));
document.body.style.background = colors[randNum];
$('#quotation').css('color', colors[randNum]);
};
$(document).ready(function() {
getQuote();
changeColor();
var randomQuote = $('#random-quote')["0"].textContent;
$('#tweet-this').click(function(){
$(this).attr('href', "https://twitter.com/intent/tweet?text=" + randomQuote);
});
$('#get-quote').on('click', function(e) {
e.preventDefault();
getQuote();
changeColor();
});
});
So my issue is that whenever I click the tweet button, I am only returned with the link "https://twitter.com/intent/tweet?text="
You can also view my CodePen here: https://codepen.io/dopeland/pen/XgwNdB
Move var randomQuote = $('#random-quote')["0"].textContent; inside of your click listener
Like so:
$('#tweet-this').click(function(){
var randomQuote = $('#random-quote')["0"].textContent;
$(this).attr('href', "https://twitter.com/intent/tweet?text=" + randomQuote);
});
randomQuote is assigned once at the beginning (set to a value of ""). Even though you are calling the click listener, the quote's text is never being written to randomQuote and always stays as "".
Forked and fixed codepen: https://codepen.io/eqwert/pen/owraVK

How to get the id of the previous element?

Here is the html:
<li>
some text
<i class="geta glyphicon glyphicon-remove-circle" onclick="deleteAnch();"></i>
</li>
<li>
other text
<i class="geta glyphicon glyphicon-remove-circle" onclick="deleteAnch();"></i>
</li>
And the jquery:
function deleteAnch () {
var the_id = $(this).prev('a').attr('id');
//also tried var the_id = $(this).closest('a').attr(id);
console.log('The id is:', the_id);
}
But in console I get
The id is: undefined
What is it wrong here and how to fix this?
p.s. I know some similar question is being asked but I still can not get it working using other answers hence the question.
You need to pass current element content i.e. this to deleteAnch inline click handler.
<i class="geta glyphicon glyphicon-remove-circle" onclick="deleteAnch(this);"></i>
Modify function as
function deleteAnch (elem) {
var the_id = $(elem).prev('a').attr('id');
console.log('The id is:', the_id);
}
However as you are using jQuery, you should bind event using it. Pass the function reference of deleteAnch and get rid of inline click handler
function deleteAnch () {
var the_id = $(this).prev('a').attr('id');
console.log('The id is:', the_id);
}
$('i.glyphicon-remove-circle').on('click', deleteAnch);
function deleteAnch() {
var the_id = $(this).prev('a').attr('id');
console.log('The id is:', the_id);
}
$('i.glyphicon-remove-circle').on('click', deleteAnch);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
some text
<i class="geta glyphicon glyphicon-remove-circle">icon</i>
</li>
<li>
other text
<i class="geta glyphicon glyphicon-remove-circle">icon</i>
</li>
</ul>

Load JSON data into a Bootstrap modal

I want to load a JSON file that creates a list inside a Bootstrap Modal. I have it set where if you click on a person's picture, the modal pops up.
<li class="project span3" data-type="pfa">
<a data-toggle="modal" data-target="#myModal" class="thumbnail">
<img src="img/anon.jpg" alt="Kenneth Atkins" />
<h1>Kenneth Atkins</h1>
<p>[Description here]</p>
</a>
</li>
Here's an example of the JSON data:
var florida_exoneration = [
{
"last_name":"Atkins",
"first_name":"Kenneth",
"age":16,
"race":"Caucasian",
"state":"FL",
"crime":"Sexual Assault",
"sentence":"10 years",
"conviction":2004,
"exonerated":2008,
"dna":"",
"mistaken witness identification":"",
"false confession":"",
"perjury/false accusation":"Y",
"false evidence":"",
"official misconduct":"",
"inadequate legal defense":"",
"compensation":""
}
]
I'd like the modal to display something like this inside the box:
Title = "first_name + last_name"
Age = "age"
Race = "race"
State = "state"
""
""
I also want to make sure the data is tied to the picture so the modal doesn't get confused. I'm sorry if this is a bit confusing. I'll try and clarify if anyone has any questions.
Method 1: using Ajax
Every time a user clicks an image, you get the id from the clicked image and then you send an Ajax request to server in order to get the JSON object.
HTML
<ul>
<li class="project span3" data-type="pfa">
<a href="#" data-id="2" class="thumbnail">
<img src="img/anon.jpg" alt="Kenneth Atkins" />
<h1>Kenneth Atkins</h1>
<p>[Description here]</p>
</a>
</li>
</ul>
JavaScript
(function($) {
var infoModal = $('#myModal');
$('.thumbnail').on('click', function(){
$.ajax({
type: "GET",
url: 'getJson.php?id='+$(this).data('id'),
dataType: 'json',
success: function(data){
htmlData = '<ul><li>title: '+data.first_name+'</li><li>age: '+data.age+'</li></ul>';
infoModal.find('.modal-body').html(htmlData);
infoModal.modal('show');
}
});
return false;
});
})(jQuery);
Method 2: using hidden div
No need to any Ajax request, but you need to create a hidden div that contain all the information you want to display in the modal
HTML
<ul>
<li class="project span3" data-type="pfa">
<a href="#" class="thumbnail">
<img src="img/anon.jpg" alt="Kenneth Atkins" />
<h1>Kenneth Atkins</h1>
<p>[Description here]</p>
<div class="profile hide">
<ul>
<li>title: Atkins Kenneth</li>
<li>Age: 16</li>
</ul>
</div>
</a>
</li>
</ul>
JavaScript
(function($) {
var infoModal = $('#myModal');
$('.thumbnail').on('click', function(){
htmlData = $(this).find('.profile').html();
infoModal.find('.modal-body').html(htmlData);
infoModal.modal('show');
return false;
});
})(jQuery);

Jquery on('click') not firing after first click

I have some HTML:
<div class="post-container self">
<a href="/user/Wiz">
<img class="avatar" alt="Profile Picture" src="">
</a>
<div class="post-body">
<div class="post" style="margin-left:0px;">
<div class="post-timestamp" style="display:inline-block;float:right">
Oct 31
</div>
<div class="post-functions dropdown displaynone" style="float:right;margin-right:5px;">
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
<i class="icon-cog">
</i>
</a>
<ul class="dropdown-menu post-dropdown" role="menu" aria-labelledby="dLabel">
<a class="post-delete" href="javascript:void(0)"><i class="icon-trash"> </i>Delete</a>
</ul>
</div>
</div>
</div>
</div>
And with that, I have some Jquery:
$('.posts-content').on('click', '.post-delete', function(e) {
$('.post-dropdown').dropdown();
if (confirm('Are you sure you want to delete this post?')) {
var $this = $(this);
$.ajax({
url: '/a/delete_post',
type: 'POST',
dataType: 'json',
data: {'p' : post_id},
success: function() {
//...
return true;
}
});
}
return false;
});
Everything works perfectly the first click, but if I go to another post, and try to click .post-delete, the event never fires, and nothing shows up in the console. It also works if I use $.click(), but I need to dynamically create elements. Why does the $.on('click') not fire the second click?
My guess is that dropdown plugin you use change the DOM structure.
$('.post-dropdown').dropdown();
BTW,
$this.parent().parent().parent().parent().parent() this is really really bad practice.
You should use closest instead.
If you are dynamically creating elements try:
$(document).on('click', '.post-delete', function(e) { });

Cannot debug jQuery button

I have this button, and when clicked, it sends an ajax call which changes the value of score_up.
I dont see what the problem is. I tried firbug, but apparently it's not even detecting the javascript? :)) Thanks.
jquery:
$('.stats').delegate('.support', 'click', function(e) {
//stop event
e.preventDefault();
//get the id
var the_id = $(this).closest('.score').attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$(this).siblings("h2.score_up").html(msg).fadeIn();
//remove down button
// and remove support button
}
});
});
html:
<ul class="stats">
<li id="support_23"class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>
//vote down button
<li id="down_23"class="score">
<h2 class="score_down">12</h2>
<span style="text-align:center;">down</span>
</li>
<li>
<button type="submit" value="Actions" class="down" title="down">
<i></i>
<span>down</span>
</button>
</li>
</ul>
It is not valid HTML for a <button> to be a direct child of a <ul>.
Children of <ul> should be <li>. I wouldn't expect things to work properly with invalid HTML.
HTML with <button> inside a <li>:
<ul class="stats">
<li id="topic_23" class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>
</ul>
jQuery, fixing some of the traversal methods:
$('.stats').delegate('.support', 'click', function(e) {
//stop event
e.preventDefault();
// cache a reference to the previous <li> element
// since it is used more than once
var $prevLi = $(this).closest('li').prev('li');
//get the id
var the_id = $prevLi.attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$prevLi.find("h2.score_up").html(msg).fadeIn();
}
});
});
Your HTML is invalid, so I would do:
<form action="javascript:alert('form')";>
<ul class="stats">
<li id="topic_23"class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i><span>Support</span></button>
</li>
</ul>
</form>
And then the jQuery (which in your original would not work, since you wanted .siblings() and not .closest() would now be:
var the_id = $(this).closest("li").siblings('.score').attr('id')
.split('_').pop();
and success:
$(this).closest("li").siblings("li.score").find("h2.score_up")
.html(msg).fadeIn();
I think you also run into troubles with prevent default, since you want to prevent default on the form, and in that case you might run into problems with delegate.
Here is what I would do with .live():
// Prevent form from submitting
$("form").live("submit", function(e) {
e.preventDefault(); });
// Run Ajax
$('button.support').live('click', function(e) {
//get the id
var $score = $(this).closest("li").siblings('.score'),
the_id = $score.attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$score.find("h2.score_up").html(msg).fadeIn();
}
});
});
​
Try it out on this jsFiddle

Categories

Resources