I was trying to implement like and dislike button to comments by the guidance from a tutorial, but i cannot get attributes from my code.
this is my html code including php
<a id="' . $quote->quote_id . '" data-toggle="tooltip" title="'. $language->list->tooltip->like .'" class="clickable like tooltipz"><span class="glyphicon glyphicon-plus red"></span></a>
<span class="up_votes"><?php echo ($vote_up); ?></span>
<a id="' . $quote->quote_id . '" data-toggle="tooltip" title="'. $language->list->tooltip->dislike .'" class="clickable dislike tooltipz"><span class="glyphicon glyphicon-minus red"></span></a>
<span class="up_votes"><?php echo ($vote_down); ?></span>
$quote->quote_id is integers like 1,2
$language->list->tooltip->like = Like comment
$language->list->tooltip->dislike = Dislike comment
$vote_up = total likes
$vote_up = total dislikes
this is the jquery part
//####### on button click, get user like and send it to vote_process.php using jQuery $.post().
$(".glyphicon").on('click', '.glyphicon', function (e) {
//get class name (down_button / up_button) of clicked element
var clicked_button = $(this).children().attr('class');
//get unique ID from voted parent element
var quote_id = $(this).parent().attr("id");
if(clicked_button==='glyphicon-minus') //user disliked the content
{
//prepare post content
post_data = {'quote_id':quote_id, 'vote':'down'};
//send our data to "vote_process.php" using jQuery $.post()
$.post('processing/process_votes.php', post_data, function(data) {
//replace vote down count text with new values
$('#'+quote_id+' .down_votes').text(data);
//thank user for the dislike
}).fail(function(err) {
//alert user about the HTTP server error
alert(err.statusText);
});
}
else if(clicked_button==='glyphicon-plus') //user liked the content
{
//prepare post content
post_data = {'quote_id':quote_id, 'vote':'up'};
//send our data to "vote_process.php" using jQuery $.post()
$.post('processing/process_votes.php', post_data, function(data) {
//replace vote up count text with new values
$('#'+quote_id+' .up_votes').text(data);
//thank user for liking the content
}).fail(function(err) {
//alert user about the HTTP server error
alert(err.statusText);
});
}
});
//end
});
in jquery part i am trying to know which button is clicked by user and get id of that button
.attr('class') will return all classes that are assigned to the element, which is not working as you are comparing the entire class list against a specific class (i.e 'class1 class2 class2' != 'class2').
.hasClass('specific-class') will return a boolean value depending on if that specific class has been assigned to the element in question.
Recommended Solution
You can simplify the code a little, the code below attaches a click event to anything with the class .glyphicon before using hasClass(".glyphicon-minus") or hasClass(".glyphicon-plus") to check if it is a down or up vote.
From here there are two alternatives to update the total vote for each post, you can either use your current technique (finding the closest wrapping class - I've used .post in this example) or you can add attributes to the UI elements which identify the elements that belong to that post - i.e. for="post1".
I've included the code for the second option as it is a bit shorter, but left it commented out.
There is also a check to see if the new total is 0, which then stops the process so that you cannot get negative votes. I've left this check commented out, but you can uncomment it if needed.
Hope that helps, let me know if you needed anything else.
$(".glyphicon").click(function() {
vote = 0;
// Check if negative vote
if ($(this).hasClass("glyphicon-minus")) {
vote = -1;
}
// Check if positive vote
if ($(this).hasClass("glyphicon-plus")) {
vote = 1;
}
// Update individual vote count
newVoteTotal =
parseInt($(this).closest(".post").find(".votes").text()) + parseInt(vote);
// Uncomment if statement and closing bracket if you want to stop usings from being able to give negative votes
//if ( newVoteTotal != "-1" ) {
$(this).closest(".post").find(".votes").text( newVoteTotal );
//}
// ALTERNATIVE using 'for' attributes
// postID = $(this).attr("for");
// newVoteTotal = parseInt($(".votes[for='" + postID + "']").text()) + parseInt(vote);
// $(".votes[for='" + postID + "']").text(newVoteTotal)
})
.post {
padding: 20px;
border: 1px solid black;
}
.post-body {
padding-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="post" id="post1">
<div class="post-body">
Lorem ipsum post 1.
</div>
<button class="glyphicon glyphicon-plus" for="post1">Vote Up</button>
<button class="glyphicon glyphicon-minus" for="post1">Vote Down</button>
<span class="votes" for="post1">0</span>
</div>
<div class="post" id="post2">
<div class="post-body">
Lorem ipsum post 2.
</div>
<button class="glyphicon glyphicon-plus" for="post2">Vote Up</button>
<button class="glyphicon glyphicon-minus" for="post2">Vote Down</button>
<span class="votes" for="post2">0</span>
</div>
Specific Solution
I have tried to create a specific solution for your code structure, I believe this will work. Changes include:
$(".glyphicon").on('click', function(e) { - corrected your creation of the click event
var clicked_button = $(this).attr('class') - you can gather all classes if you wish (as later we will just check for a presence of a single class) .attr() docs
if (clicked_button.includes('glyphicon-minus') - this checks the full list of classes we gathered early, to see if a specific class is present (and returns true if it is). .include() docs
I have removed all the code that sends the info server side, and replaced it with a console.log() message to prove we have gathered all the parameters you wanted. You can add your old code back in for your production site.
//####### on button click, get user like and send it to vote_process.php using jQuery $.post().
$(".glyphicon").on('click', function(e) {
//get class name (down_button / up_button) of clicked element
var clicked_button = $(this).attr('class');
//get unique ID from voted parent element
var quote_id = $(this).parent().attr("id");
if (clicked_button.includes('glyphicon-minus')) //user disliked the content
{
// POST like
console.log("Liked quote-id=" + quote_id + " (via class " + clicked_button + ")");
} else if (clicked_button.includes('glyphicon-plus')) //user liked the content
{
// POST dislike
console.log("Disliked quote-id=" + quote_id + " (via class " + clicked_button + ")");
}
});
//end
.glyphicon {
width: 50px;
height: 50px;
display: inline-block;
}
.red {
background: red;
}
.like {
border-bottom: 5px solid green;
}
.dislike {
border-bottom: 5px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a id="1" data-toggle="tooltip" title="Like comment" class="clickable like tooltipz"><span class="glyphicon glyphicon-plus red"></span></a>
<span class="up_votes">0</span>
<a id="1" data-toggle="tooltip" title="Dislike comment" class="clickable dislike tooltipz"><span class="glyphicon glyphicon-minus red"></span></a>
<span class="up_votes">0</span>
1st:
$(".glyphicon").on('click', '.glyphicon', function (e) {
//you need to change it to
$(document).on('click', '.glyphicon', function (e) { // if its dynamically generated element or you toggle `.glyphicon` class ..
// else you can just use
$('.glyphicon').on('click' , function(){
//code here
})
2nd: To check the classes you need to use hasClass
and on the next line
var clicked_button = $(this).children().attr('class');
you already in the click event of glyphicon so no need to use children() here .. and if you console.log($(this).attr('class')) it will output glyphicon glyphicon-plus red
var clicked_button = $(this);
if(clicked_button.hasClass('glyphicon-minus')){
}
Note: after change your code with my notices above .. you can then console.log(quote_id)
Related
I was trying to parse data to my controller so I can insert it into the database using JQuery and it was returning null. It's for a review star system so doesn't use conventional form fields however the network tab in inspect elements shows that data is actually posted to the controller just, not able to read it for some weird reason.
Update: The data is being inserted fine on desktop however the confirmation (flashdata) message is shown correctly not sure why. Additionally on mobile view no data or message is shown. Does anyone know why? I have updated the code below..
Here's the code from my view:
<?php if($this->session->flashdata('review_submitted')){ ?>
<div class="alert alert-success alert-dismissible container show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>Thank you!</strong> Your review has been submitted.
</div>
<?php } ?>
<form id="myForm" name="myForm">
<br>
<div class="form-group text-left div-style">
<h3 style="font-family: MontserratLight;letter-spacing: 2px; line-height: 32px;">Full Name <b>*</b></h3>
<input name="name" class="form-control" style="background: #f7f7f7; border: 1px solid #801424;" required />
</div>
<div class="rate">
<div id="1" class="btn-1 rate-btn"></div>
<div id="2" class="btn-2 rate-btn"></div>
<div id="3" class="btn-3 rate-btn"></div>
<div id="4" class="btn-4 rate-btn"></div>
<div id="5" class="btn-5 rate-btn"></div>
</div>
<script>
$(function(){
$('.rate-btn').hover(function(){
$('.rate-btn').removeClass('rate-btn-hover');
var therate = $(this).attr('id');
for (var i = therate; i >= 0; i--) {
$('.btn-'+i).addClass('rate-btn-hover');
};
});
$('.rate-btn').click(function(){
var therate = $(this).attr('id');
var dataRate = 'rate='+therate; //
$('.rate-btn').removeClass('rate-btn-active');
for (var i = therate; i >= 0; i--) {
$('.btn-'+i).addClass('rate-btn-active');
};
$('#myForm').on('submit', function(e){
var url = "<?php echo base_url(); ?>index.php/reviews/add_review";
// $('#myForm').append(therate);
var dataPost = $('#myForm').serialize() + "&rate=" + therate;
$.ajax({
type : "POST",
url : url,
data: dataPost,
success:function(){
}
});
});
});
});
</script>
and using the controller I simply use the following to get the data and add it to the database:
public function add_review(){
$name = $this->input->post('name');
$rating = $this->input->post('rate');
$dataDB = array(
'full_name' => $name,
'rating' => $rating
);
if($this->functions->submit($dataDB)){
$this->session->set_flashdata('review_submitted', true);
redirect(base_url() . 'reviews/index', 'refresh');
}
}
Here's some CSS that I used, perhaps the problem is to do with the mobile browser not having a cursor?
.rate{
width:245px; height: 40px;
margin-bottom:0px;
}
.rate .rate-btn{
width: 45px; height:40px;
float: left;
background: url(rate-btn.png) no-repeat;
cursor: pointer;
cursor:hand;
pointer-events: auto;
}
.rate .rate-btn:hover, .rate .rate-btn-hover, .rate .rate-btn-active{
background: url(rate-btn-hover.png) no-repeat;
}
When passing data through ajax, I think it is better to use JSON dataType. Reform the data type (string -> data object). Besides, I don't think it is really necessary to concat the 'to-be-sent' data into a string.
If you want dynamic data to be sent, you can push elements by condition
$.ajax({
type : "POST",
dataType: 'text' //it is not necessary if you are not returning any data (if you return json, put 'JSON'),
url : "<?php echo base_url(); ?>index.php/reviews/add_review",
data: dataRate, //change to {key:value,key:value}
success:function(data){
}
});
This is just to address your issue with your AJAX Posted Values not appearing where you are expecting them ONLY.
There are a zillion ways you can code this but here is just one which I have changed about to perform debugging. Even I learned a new trick doing this.
Just Nit Picking but what stuck out when reading your code is your use of therate when everywhere else in your JS you use camel case so it should be theRate.It's a good idea to choose a standard and stick to it.
Plus you had what appeared to be nested events in your JS. Some attempt at getting theRate to work correctly? Anyway...
First things. Get back to something basic and work your way back up. (Although in this case I didn't strip your view back to bare bones, but I did with your controller.
Your View.
I had to change this up a bit and hopefully the comments explain things.
I called it rating_view.php
<form name="my-form" id="my-form">
<div class="rate">
<div id="1" class="btn-1 rate-btn">1</div>
<div id="2" class="btn-2 rate-btn">2</div>
<div id="3" class="btn-3 rate-btn">3</div>
<div id="4" class="btn-4 rate-btn">4</div>
<div id="5" class="btn-5 rate-btn">5</div>
</div>
<input type="submit">
</form>
<!-- Added for viewing debug response -->
<div id="json-debug-output"></div>
<!-- Some styles added as non were provided -->
<style>
.rate-btn-hover {
background: blue;
}
.rate-btn-active {
background: yellow;
}
</style>
<script src= <?= base_url('assets/js/jquery_v3.4.1.js'); ?>></script>
<script>
$(document).ready(function () {
// Define your Dom Elements ONCE for efficiency etc
let domRateButton = $('.rate-btn');
let domMyForm = $('#my-form');
let theRate = 0; // Declares this as a Global Var.
let domJsonDebugOutput = $('#json-debug-output');
// Hover
domRateButton.hover(function () {
domRateButton.removeClass('rate-btn-hover');
let theRate = $(this).attr('id');
for (let i = theRate; i >= 0; i--) {
$('.btn-' + i).addClass('rate-btn-hover');
}
});
// Click
domRateButton.click(function () {
console.log('Rating Button Clicked');
theRate = $(this).attr('id');
domRateButton.removeClass('rate-btn-active');
for (let i = theRate; i >= 0; i--) {
$('.btn-' + i).addClass('rate-btn-active');
}
});
// Submit
domMyForm.on('submit', function (e) {
e.preventDefault(); // This was missing
console.log('Posting Rate = ' + theRate);
$.ajax({
type: "POST",
// dataType: 'text',
dataType: "json",
url: "<?php echo base_url(); ?>reviews/add_review",
data: {'act': 'rate', 'post_id':<?= $post_id; ?>, 'rate': theRate},
success: function (data) {
let debugData = JSON.stringify(data);
domJsonDebugOutput.text(debugData); // Display in our Debug Div
},
error: function (data) {
let debugData = JSON.stringify(data);
domJsonDebugOutput.text(debugData); // Display in our Debug Div
}
});
});
});
</script>
Note in the AJAX the changes to dataType from text to json. Also note that data is an array.
I also changed the scope of theRate from local to a global so it was "findable" amongst the functions.
NOT SURE how your form was setup but I added e.preventDefault(); to prevent the form submitting for testing.
Personally I cringe at having PHP vars embedded in any JS code and I usually have my JS as external files and pass in the values from PHP by reading them using JS but that's got it's Pros and Cons as well. So I left that alone for the sake of not going too far with this.
For your Controller - Called Reviews.php
public function show() {
$data['post_id'] = 1; // This comes from somewhere
$content = $this->load->view('rating_view', $data, TRUE);
echo $content;
}
/**
* Called by AJAX
* Do we need to test this is only called by AJAX?
*/
public function add_review() {
// Return everything that was sent for debugging
echo json_encode($this->input->post());
// var_dump($this->input->post());
exit();
}
So here I just had a method show() show the form and the add_review to simply bounce back what was sent. You can do all sorts of things with this. One nice aspect in this case is you do not need to use console.log) as you can view it all on the page (BUT ONLY FOR DEBUGGING). It's another option.
So have a play with that and start making changes to your code and see what works. Remember - get back to basics and pick on the bit that isn't working.
Next you will find you might be getting tripped up on your redirect. But that's for another post.
My HTMl file has code:
<li id="b1" onclick="myfunc(this)" class="thumbsup fa fa-thumbs-up" ></li>
Above code makes a like button whose color changes on click.
Now I want to get its color on form submission so that on php side I can add number of likes in DB accordingly. That is if user clicked this button then it's color changes to grey . So in jquery i want to see if it is grey and then in php increment value in DB accordingly. Not sure how i can retrieve color of li element in jquery.
Please note that user can click button multiple times. like first time on clicking , button turns grey and when clicked again. it turns to its default color and so on...
As #mplungjan states on the comment you don't need a color to get if it is clicked. You can write an onlick function to send an ajax request to your php file, do the query for the like there and on return you can write a very simple code to color and disable click of the button again.
Like this;
myfunc(e){
$.ajax({
type:'POST',
url:'yourphpfile.php',
data:{whatever:youwanttosend},
success:function(data){
$('#b1').css('background-color':'green');
});
}
You do not want the color of the li, you want its state. Toggle the class:
$(function() {
$(".thumbsup").on("click", function() {
$(this).toggleClass('liked'); // every time we click we set or remove
$(this).next().removeClass('disliked'); // remove from the thumbsdown
})
$(".thumbsdown").on("click", function() {
$(this).toggleClass('disliked'); // every time we click we set or remve
$(this).prev().removeClass('liked'); // remove from thumbsup
})
$("#save").on("click", function() {
var liked = $(".liked").length,
disliked = $(".disliked").length;
console.log(liked,disliked);
// ajax here - sending liked:0,disliked:0 if nothing clicked
$.post("savelike.php",{ "liked":liked,"disliked":disliked},function() {
console.log("saved");
});
})
})
.liked { background-color:green }
.disliked { background-color:red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="a1" class="thumbsup fa fa-thumbs-up">👍</li>
<li id="a2" class="thumbsdown fa fa-thumbs-down">👎</li>
</ul>
<button id="save" type="button">Save</button>
Original more complex example with more than one like/dislike set
$(function() {
$(".thumbsup").on("click", function() {
$(this).toggleClass('liked'); // every time we click we set or remove
$(this).next().removeClass('disliked'); // remove from the thumbsdown
})
$(".thumbsdown").on("click", function() {
$(this).toggleClass('disliked'); // every time we click we set or remve
$(this).prev().removeClass('liked'); // remove from thumbsup
})
$("#count").on("click", function() {
console.log($(".liked").length,"liked",
$(".disliked").length,"disliked"); // how many
// which ones - using http://api.jquery.com/map/
let likes = $('.thumbsup.liked').map(function(){ // array map
return this.id; // each ID that is liked
}).get();
let dislikes = $('.thumbsdown.disliked').map(function(){
return this.id
}).get();
// here are the arrays - use .join(",") to get a list
console.log(likes.length>0?likes:"No likes",
dislikes.length>0?dislikes:"No dislikes")
})
})
.liked { background-color:green }
.disliked { background-color:red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="a1" class="thumbsup fa fa-thumbs-up">👍</li>
<li id="a2" class="thumbsdown fa fa-thumbs-down">👎</li>
<li id="b1" class="thumbsup fa fa-thumbs-up">👍</li>
<li id="b2" class="thumbsdown fa fa-thumbs-down">👎</li>
</ul>
<button id="count" type="button">Count</button>
You can use find function of jQuery.
Suppose you have multiple li under div element than you can try the following code to get all li elements which color is grey.
$( "div.classname" ).find( "li.thumbsup" ).css( "background-color", "grey " ).
I have a listing of products each with differnt ID. Now on frontend I want to get prodouct data(say, name,price and a addtocart button) on mousover.
Here is my code:
This is in loop to get all products:
HTML:
<div class="prod">
<a class="product-image pi_470" title="Cushion Tsavorites" href="/tsavorite/cushion-tsavorites-1328.html"><img height="135" width="135" alt="Cushion Tsavorites" src="/small_image.jpg"></a>
<div style="display: none; margin: -65px 0px 0px 5px; position: absolute; z-index: 30;" class="mouse_hover_470">
<input type="hidden" id="prod_id" value="470">
<h2 class="product-name"><a title="Cushion Tsavorites" href="/tsavorite/cushion-tsavorites-1328.html">Cushion Tsavorites</a></h2>
<div class="price-box">
<span id="product-price-470" class="regular-price">
<span class="price">$387.15</span>
</span>
</div>
<div class="actions">
<button onclick="setLocation('http://dev614.trigma.us/chocolate/index.php/checkout/cart/add/uenc/aHR0cDovL2RldjYxNC50cmlnbWEudXMvY2hvY29sYXRlL2luZGV4LnBocC90c2F2b3JpdGUuaHRtbA,,/product/470/form_key/4BR7w0TqeeO9AC0g/')" class="button btn-cart" title="Add to Cart" type="button"><span><span>Add to Cart</span></span></button>
</div>
</div>
</div>
jQuery:
jQuery(document).ready(function() {
var bla = jQuery('#prod_id').val();
jQuery(".pi_" + bla).mouseover(function() {
//alert("hello");
jQuery(".mouse_hover_" + bla).css("display", "block");
});
jQuery(".pi_" + bla).mouseout(function() {
jQuery(".mouse_hover_" + bla).css("display", "none");
});
});
But Iam getting only data of first product on mouseover. Its not working for rest of products
Looks like you are executing the above block of code in a loop, once per each product. In that case the problem is jQuery('#prod_id').val(); it will always return the value of first element with id prod_id.
In your case you don't have to do that, you can
jQuery(function ($) {
$('.prod .product-image').hover(function () {
$(this).next().show();
}, function () {
$(this).next().hide();
})
});
There is a much, much easier way to do this:
jQuery(document).ready(function() {
jQuery(".product-image").hover(function() {
$(this).next().show();
}, function() {
$(this).next().hide();
});
});
Demo: JSBin
You can use each() function in jQuery
NOTE: Instead of using id="prod_id", use class, i.e class="prod_id". Since you told that the div is dynamically created it is using the same id attribute
Now loop the product div on ready function
jQuery(document).ready(function() {
jQuery('.prod').each(function(){
var bla = jQuery('.prod_id').val();
jQuery(".pi_" + bla).on('mouseover',function() {
//alert("hello");
jQuery(".mouse_hover_" + bla).css("display", "block");
});
jQuery(".pi_" + bla).on('mouseout',function() {
jQuery(".mouse_hover_" + bla).css("display", "none");
});
});
});
You can checkout this jQuery each()
Ashi,
try using
var bla = jQuery(input[id*='prod_id']).val();
instead of
var bla = jQuery('#prod_id').val();
This will give you all the hidden inputs so loop all of them and bind the mouseover event.
For example:
jQuery(input[id*='prod_id']).each(function(){
var bla = jQuery(this).val();
//carry out your logic..
// you can use jquery().live('mouseover'function(){}) for dynamically created html
});
Hope this will work!!
Cheers!!
function handler(ev) {
var target = $(ev.target);
var elId = target.attr('id');
if( target.is(".el") ) {
alert('The mouse was over'+ elId );
}
}
$(".el").mouseleave(handler);
http://jsfiddle.net/roXon/dJgf4/
I don't know if I've even asked the question properly, but I have a codeigniter application that some heaving lifting in the back end. While the app is busy executing commands(ajax commands), I'd like to show some sort of a status / message box / div. When the task is done, I'd like to clear the div / box.
What would I need to google to find a solution like this?
Thanks.
Edit:
This is what my jquery / ajax call looks like right now...
$('#availVLANS').click(function() {
$(this).attr("disabled","disabled");
$.ajax({
url:"<?php echo site_url('controller/methodABC/');?>",
type:'POST',
dataType:'json',
success: function(returnDataFromController) {
var htmlstring;
var submitFormHTML;
htmlstring = "<br><br><B>To reassign the port to a new vlan, click on a VlanId below and then click on the OK button</B><br><table class='table table-bordered table-striped'>";
htmlstring = htmlstring + "<th>VlanId</th><th>Name</th>";
for(i = 0; i < returnDataFromController.length; i++) {
//alert(returnDataFromController[i].VlanId);
htmlstring = htmlstring + "<tr><td><a href=>"+returnDataFromController[i].VlanId+"</a></td><td>"+ returnDataFromController[i].Name+"</td></tr>";
}
submitFormHTML = "<form method='post' accept-charset='utf-8' action='" + BASEPATH + "index.php/switches/changeportvlan/"+ $('#ip').val() +"/" + $('#hardwaremodel').val() +"/" + $('#port').val() + "'><input type='text' name='newVlanID' id='newVlanID' style='width:5em;height:1.5em'/> <button type='submit' class='btn' name='saveVlan' id='saveVlan' style='width:10em;height:2em'>Reassign Vlan</button></form>";
//alert(submitFormHTML);
$('#clientajaxcontainer').html(htmlstring);
$('#newvlanform').html(submitFormHTML);
}
});
$(this).removeAttr("disabled");
});
Just use an animated GIF image in an absolutely positioned DIV overlayed on top of the whole page. Just make sure that you overlay an invisible DIV over top of the entire page to prevent clicks on interface elements behind the progress window. Something like this;
╔════════════════════╗
║ #progress-overlay ║
║ ╔════════════════╗ ║
║ ║ #progress-indicator
║ ╚════════════════╝ ║
╚════════════════════╝
The #progress-overlay is a background for the indicator and what you're going for is like a LightBox2 effect but using a progress indicator and small box in the middle of the screen.
You can get animated gif's from here;
http://preloaders.net/
Make sure that your progress/something-is-happening div sits at the top level of the document structure, so somewhere at the top of the body, before any of your other container DIV's. This is done so that the #progress-overlay is rendered at the same level in the DOM as the top level element of your website. When you absolutely position the #progress-overlay, it will appear overtop of everything else on the page.
<html>
<head>
....
</head>
<body>
<div id="progress-overlay">
<div id="progress-indicator">
<img src="images/myprogress.gif" /> Please Wait...
</div>
</div><!--progress-overlay-->
<div id="website-wrapper">
.... web site, layout, content, etc...
</div>
</body>
</html>
The #progress-overlay is hidden by default and then shown overtop when needed. Something like;
#progress-overlay{
position: absolute;
width: 100%;
height: 100%;
background: #000;
opacity: 0.2;
}
#progress-indicator{
position: relative;
margin: 0 auto;
top: 40%;
width: 200px;
height: 50px;
}
Using JQuery you could easily make this appear on demand using;
$(document).ready(function(){
$('#progress-overlay').hide();
});
function showProgressIndicator()
{
$('#progress-overlay').show();
}
You can make use of onreadystatechange event:
http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp
If you're doing it through jquery, just show a div with a message and/or a spinner.
jQuery.ajaxSetup({
beforeSend: function() {
$('#loader').show();
},
complete: function(){
$('#loader').hide();
}
});
If you're using jQuery, I propose the following solution:
The jQuery:
$(document).ready(function(){
$("#the_button").click(function(){
var url = "the_controller/the_method"
var data = {the: "data"}
//before the POST takes place, fade-in the message
$("#the_message").fadeIn();
$.post(url, data, function(r){
if(r.success){
//when the post is finished, and it was successful, fade-out the message.
$("#the_message").fadeOut();
}
else console.log("something bad happened");
}, 'json');
});
});
The HTML:
<!-- HIDE IT BY DEFAULT -->
<div id='the_message' style='display:none;'>
Please wait.
</div>
The Controller:
class The_controller extends CI_Controller{
function the_method(){
$p = $this->input->post();
the_task($p);
if(the_task_success) return json_encode(array("success" => true));
else return json_encode(array("success" => false));
}
}
How I can do a foreach or similar in jQuery? I need that when the user clicks in the <span>, add the class inactive to all <div>s with the vote active class in the <ul>.
I've tried with the .each method, but it doesn't work.
I have this HTML:
<ul class="suggestions inactive">
<li id="s2">
<div class="id">2</div>
<div class="vote inactive">
<span class="up"></span>
<span class="down"></span>
</div>
<div class="text">test2</div>
<div class="rating">2</div>
</li>
<li id="s3">
<div class="id">3</div>
<div class="vote active">
<span class="up"></span>
<span class="down"></span>
</div>
<div class="text">test3</div>
<div class="rating">0</div>
</li>
</ul>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="script.js"></script>
And this script:
$(document).ready(function(){
var ul = $('ul.suggestions');
// Listening of a click on a UP or DOWN arrow:
$('div.vote span').live('click',function(){
var elem = $(this),
parent = elem.parent(),
li = elem.closest('li'),
ratingDiv = li.find('.rating'),
id = li.attr('id').replace('s',''),
v = 1,
ul2 = elem.closest('li').parent();
// If the user's already voted:
if(parent.hasClass('inactive')){
return false;
}
if(ul2.hasClass('inactive')){
return false;
}
//If the user's already voted, add following class
parent.removeClass('active').addClass('inactive');
ul2.removeClass('active').addClass('inactive');
if(elem.hasClass('down')){
v = -1;
}
// Incrementing the counter on the right:
ratingDiv.text(v + +ratingDiv.text());
// Turning all the LI elements into an array
// and sorting it on the number of votes:
var arr = $.makeArray(ul.find('li')).sort(function(l,r){
return +$('.rating',r).text() - +$('.rating',l).text();
});
// Adding the sorted LIs to the UL
ul.html(arr);
// Sending an AJAX request
$.get('ajax.php',{action:'vote',vote:v,'id':id});
});
You don't need .each() here at all.
Why? Because jQuery's selectors wonderfully select everything of a single selector type. $('p') selects every p in your HTML.
You should use
$(this).parent().addClass('active').removeClass('inactive');`
from within the scope of the
$('div.vote span').live('click',function() { ... } );
Also, remember that .live() is deprecated in jQuery 1.7+.
Are you sure you really want to add that class to ALL elements in the HTML? If so, I guess I would just do this:
$("div").addClass("inactive");
You do not need each for adding class to multiple elements. Just select them and apply addClass():
jQuery('div.vote.active').addClass('inactive');
If you insist on using .each(), then it really works. Just use it properly:
jQuery('div.vote.active').each(function(){
jQuery(this).addClass('inactive');
});
Did it help?