Multiple div refresh on different timings in jquery/ajax? - javascript

I want to set up two div entries on a page that are refreshed from a database at different rates.
I'd like to have one div display random entries from the database every second, and below that, every 10 seconds a random entry is selected and has 500 points added to its score.
I can do the second (lottery_Winner):
<div id="lottery_Winner" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"WINNER"}}</a> </li>
<li class = "lot"> <span id="entry-text">{{ entry.text }}</span> <span id="score">{{ entry.score }}</span></li>
<script>
$(document).ready(function() {
var currentid = {{entry.id}};
var args = {'lotteryid':currentid};
$.get("/lotteryWinner/", args).done(function(data) {
$("#score").text(data);
});
});
</script>
{% endfor %}
</div>
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Winner"),
success: function(data){
$("#lottery_Winner").html(data);
}
});
}, 5000);
</script>
but when I do the first (lottery_Cycle), I get unexpected results - they both refresh the same time (undesired), there is a "ghost" element for one or both of the divs, and the lottery_cycle div entry can get the 500 points, the Winner and Cycle have the same entries and the page refresh cascades until it hangs periodically.
Here's the code I tried:
<div id="lottery_Cycle" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"LOTTERY"}}</a> </li>
<li><a href="/entries/{{ entry.id }}/"> <div class = "lot" style = "text-align: left";>{{ entry.text }}
<div style="float: right">{{ entry.score }}</div></a></li>
{% endfor %}
</div>
<div id="lottery_Winner" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"*** LOTTERY WINNER ***"}}</a> </li>
<li class = "lot"> <span id="entry-text">{{ entry.text }}</span> <span id="score">{{ entry.score }}</span></li>
<script>
$(document).ready(function() {
var currentid = {{entry.id}};
var args = {'lotteryid':currentid};
$.get("/lotteryWinner/", args).done(function(data) {
$("#score").text(data);
});
});
</script>
{% endfor %}
</div>
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Winner"),
success: function(data){
$("#lottery_Winner").html(data);
}
});
}, 5000);
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Cycle"),
success: function(data){
$("#lottery_Cycle").html(data);
}
});
}, 1000);
</script>
and here is relevant part of views.py;
def lottery(request):
context = {
'lottery_cycle': Entry.objects.random(),
'lottery_winner': Entry.objects.random(),
}
return render(request, 'entries/lottery.html', context);
def lotteryCycle(request):
c = Entry.objects.random()[0]
return HttpResponse("%s,%s,%s" % (c.id, c.text, c.score))
def lotteryWinner(request):
lottery_id = request.GET.get('lotteryid')
if request.method=='GET':
l = Entry.objects.get(pk=lottery_id)
l.score +=500
l.save()
return HttpResponse(l.score)
else:
pass
return HttpResponse('done')
(I tried setInterval as well as setTimeout, same result) Is there any advice on getting the two div refreshes working properly on different timings?

Related

Loading category tags with load more button

I am new to jQuery. I have implemented a "load more" button on my blog app using jQuery, however the categories tags doesn't get displayed on the html when I click on that button.
Everything works fine so far, I can't just display the tags on the post card, it keeps returning undefined.
Note: I'm getting my categories from a many to many field relationship
Here are my views:
def home(request):
post = BlogPost.objects.all()[0:5]
total_post = BlogPost.objects.count()
context = {'post': post, 'total_post':total_post}
return render(request,'blog/home.html', context)
def load_more(request):
# get total items currently being displayed
total_item = int(request.GET.get('total_item'))
# amount of additional posts to be displayed when i click on load more
limit = 3
posts = list(BlogPost.objects.values()[total_item:total_item+limit])
print(BlogPost.objects.all())
data = {
'posts':posts,
}
return JsonResponse(data=data)
Template:
<div class="blogpost-container">
<div class="blogposts" id="blog-content">
{% for post in post %}
<div class="post">
<img id="img-src" src="{{post.image.url}} " image-url="{{post.image.url}}" alt="">
<p><strong>{{post.title}}</strong></p>
{% for category in post.category.all%}
<h3>{{category}}</h3>
{%endfor%}
<a id="post-detail-link" href="{% url 'detail' post.id %}" detail-url="{% url 'detail' post.id %}"><h2>{{post.summary}}</h2></a>
</div>
{%endfor%}
</div>
</div>
<div class="add-more" data-url='{% url "load_more" %}'id="add-btn">
<button type="button" class="more-content">load more</button>
</div>
<div class="alert no-more-data" role="alert" id="alert">
No more post to load!!!
</div>
{{total_post|json_script:"json-total"}}
JS file:
const loadBtn = document.getElementById('add-btn')
const total_post = JSON.parse(document.getElementById('json-total').textContent);
const alert = document.getElementById('alert')
function loadmorePost(){
const content_container = document.getElementById('blog-content');
var _current_item =$('.post').length;
$.ajax({
url:$('.add-more').attr('data-url'),
type:'GET',
data:{
'total_item':_current_item
},
beforeSend:function(){
alert.classList.add('no-more-data')
},
success:function(response){
const data = response.posts
alert.classList.add('no-more-data')
data.forEach(posts => {
const imageurl = 'media/'+posts.image
const detailurl = 'post/'+posts.id;
const category = posts.category;
content_container.innerHTML +=`<div class="post" id=${posts.id}>
<img id="img-src" src=${imageurl} image-url="{{post.image.url}alt="">
<p><strong>${posts.title}</strong></p>
<h3>${category}</h3>
<a id="post-detail-link" href=${detailurl}><h2>${posts.summary}</h2></a>
</div>`
})
if (_current_item == total_post){
alert.classList.remove('no-more-data')
loadBtn.classList.add('no-more-data')
}
else{ loadBtn.classList.remove('no-more-data')
alert.classList.add('no-more-data')
}
},
error:function(err){
console.log(err);
},
});
};
loadBtn.addEventListener('click', () => {
loadmorePost()
});

how can i create a table entry in django views

I want to make a system of likes on the site, and I need to create an entry in the table on the button. When a person clicks on like, the table writes row 1 and when dislike 0
views.py
def forum(requset):
model = Quetions.objects.all()
answer = Answer.objects.all()
count = Answer.objects.all().count()
count_answer = Quetions.objects.all().count()
paginator = Paginator(model, 1) # Show 25 contacts per page.
page_number = requset.GET.get('page')
question_id = requset.GET.get('id',False)
page_obj = paginator.get_page(page_number)
requestanswer = requset.GET.get('id',False)
like_disli = like.objects.filter(like_dislike = "1").count()
dislike = like.objects.filter(like_dislike = "0").count()
createlike =
objects = {
'model': page_obj,
'answer':answer,
'count':count,
'count_question':count_answer,
'page_obj':page_obj,
'question':question_id,
'id':model,
'request':requestanswer,
'like':like_disli,
'dislike':dislike,
'createlike':createlike,
}
return render(requset,'forum.html',objects)
forum.html
<span>
<i class="fas fa-thumbs-up" style="color: blue;margin-right: 5px;" onclick="incrementClick()"></i>{{like}}<i class="fas fa-thumbs-down" style="color: red;margin-right: 5px;margin-left: 10px;" onclick="dislikeclick()"></i>{{dislike}}
</span>
{% block js %}
<script>
var a = "{{createlike}}"
function incrementClick() {
a
}
function dislikeclick() {
dislikedisplay(++dislikecounter);
}
function updateDisplay(val) {
document.getElementById("counter-label").innerHTML = val;
}
function dislikedisplay(val){
document.getElementById("counter").innerHTML = val
}
</script>
{% endblock js %}
tell me how to do it???

How do I correctly load a specific jQuery script

I've been given a script by my e-commerce provider that will allow me to dynamically change the stock levels based on the product option selected by the user from a simple select element.
While the code seems strait forward, it will not run properly. As I am fairly new to jQuery, I'm assuming this is due to me not properly initializing the script within my html. The code itself is a default code that my e-commerce provider hands out, but does not support it in any way.
Here is the script
<script>
// <![CDATA[
var selectCallback = function(variant, selector) {
if (variant) {
if (variant.available) {
// Selected a valid variant that is available.
$('#add-to-cart').removeClass('disabled').removeAttr('disabled').val('Add to Cart').fadeTo(200,1);
} else {
// Variant is sold out.
$('#add-to-cart').val('Sold Out').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
// Whether the variant is in stock or not, we can update the price and compare at price.
if ( variant.compare_at_price > variant.price ) {
$('#product_price').html('<span class="product-price on-sale">'+ Shopify.formatMoney(variant.price, "") +'</span>'+' <s class="product-compare-price">'+Shopify.formatMoney(variant.compare_at_price, "")+ '</s>');
} else {
$('#product_price').html('<span class="product-price">'+ Shopify.formatMoney(variant.price, "") + '</span>' );
}
} else {
// variant doesn't exist.
$('#add-to-cart').val('Unavailable').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
}
// initialize multi selector for product
jQuery(function($) {
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
});
// ]]>
</script>
Any ideas on why this might not be working? You can see this script live on my site:
http://www.yandasmusic.com/products/fender-american-standard-stratocaster?variant=1178632565
EDIT:
Upon further inspection, I have found a second piece of code that also calls up the product option selection box. I can tell that this code also serves the function of changing the currently shown product image based on the current option selected:
<script>
var selectCallback = function(variant, selector) {
if (variant && variant.available) {
jQuery('#add-to-cart').removeAttr('disabled').removeClass('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
if(variant.price < variant.compare_at_price){
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span><span class="money compare-at-price">' + Shopify.formatMoney(variant.compare_at_price, "{{ shop.money_format }}") + '</span>');
} else {
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span>');
}
} else {
jQuery('#add-to-cart').addClass('disabled').attr('disabled', 'disabled'); // set add-to-cart button to unavailable class and disable button
var message = variant ? "Sold Out" : "Unavailable";
jQuery('#product_price .price').text(message);
}
// if (variant && variant.featured_image) {
// var originalImage = $(".zoomWrapper img");
// var newImage = variant.featured_image;
// var element = originalImage[0];
// Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
// $(element).parents('a').attr('href', newImageSizedSrc);
// $(element).attr('src', newImageSizedSrc);
// });
// };
if (variant && variant.featured_image) {
var originalImage = $("#elevatezoom_big");
var newImage = variant.featured_image;
var element = originalImage[0];
Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
$(element).attr('src', newImageSizedSrc);
$("#elevatezoom_gallery a").each(function(){
if ( $(this).attr('data-zoom-image') == newImageSizedSrc ) {
$(this).trigger('click')
};
});
});
};
};
jQuery(document).ready(function($){
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });
// Add label if only one product option and it isn't 'Title'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
{% endif %}
// Auto-select first available variant on page load.
{% assign found_one_in_stock = false %}
{% for variant in product.variants %}
{% if variant.available and found_one_in_stock == false %}
{% assign found_one_in_stock = true %}
{% for option in product.options %}
$('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
{% endfor %}
{% endif %}
{% endfor %}
});
</script>
If I run both scripts, the page shows two select boxes for the product options. Is it possible to combine them?
You have a JavaScript error on your page because of this line of code:
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
According to this reference document: https://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/linked-product-options, that line of code should actually look like this:
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });

Double buffering divs flicker when refreshing in Ajax

I have code that refreshes a div running on local server without flickering, but when hosting it on a webserver, it does flicker (disappear to background) when refreshing:
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.body,
success: function(s,x){
$(this).html(s);
}
});
}, 1000);
</script>
I've had a good look around SO and the web, and it seems I want to double buffer the div table I am refreshing - have one hidden, refresh that, then swap the display style of the two divs
I started with How to avoid blinking when updating page from ajax
moved on to http://www.brightcherry.co.uk/scribbles/jquery-auto-refresh-div-every-x-seconds/
and Trouble with dynamic refreshing div
And got some good ideas from:How to toggle between two divs
The code I am trying to get to work may be too complicated. I feels like it should work, and the tables refresh, but they flicker with a long time between display.
Divs;
<div id="id1" style="display: none";>
<div id="allTable1" class = "tableCenter">
<div id="hiTable" class = "table">
{% for entry in high_entry_list %}
<li>
<a href="/entries/{{ entry.id }}/">
<div class = "high" style = "text-align: left";>
{{ entry.text }}
<div style="float: right">
{{ entry.score }}
</div>
</div>
</a>
</li>
{% endfor %}
</div>
....and two more tables as hiTable above...
</div>
</div>
<div id="id2" style="display: block";>
<div id="allTable2" class = "tableCenter">
<div id="hiTable" class = "table">
{% for entry in high_entry_list %}
<li>
<a href="/entries/{{ entry.id }}/">
<div class = "high" style = "text-align: left";>
{{ entry.text }}
<div style="float: right">
{{ entry.score }}
</div>
</div>
</a>
</li>
{% endfor %}
</div>
....and two more tables as hiTable above...
</div>
</div>
Script:
<script>
var visible_id = 'id2';
setInterval(function() {
if(visible_id == 'id2') {
document.getElementById('id1').style.display = 'block';
document.getElementById('id2').style.display = 'none';
$.ajax({
url: "/index",
context: document.getElementById('allTable2'),
success: function (s) {
$("#allTable2").html(s).load;
}
});
visible_id = 'id1';
} else {
document.getElementById('id1').style.display = 'none';
document.getElementById('id2').style.display = 'block';
$.ajax({
url: "/index",
context: document.getElementById('allTable1'),
success: function (s) {
$("#allTable1").html(s).load;
}
});
visible_id = 'id2';
}
}, 1000);
</script>
So I have div wrappers for the two copies of three tables (one hidden, one shown), the javascript checks the visibility, swaps display style for the two wrappers, and updates the hidden one with an ajax refresh (which works). Is there an obvious logic or coding flaw that may be causing the flicker?
AJAX requests can take significantly longer than a second. You are toggling between the tables whether or not a particular AJAX request has finished, but the AJAX will still execute (perhaps 1.5 seconds later), giving you that undesired flickering behavior.
Rather than setting an interval which will execute whether or not the AJAX request has finished, set a timeout from the AJAX callback. Something like this (you'll probably need to fiddle with it some):
<script>
(function(){
var visible_id = 'id2';
function toggleDisplay(){
// toggle displayed table
document.getElementById('id1').style.display = visible_id === 'id2' ? 'block' : 'none';
document.getElementById('id2').style.display = visible_id === 'id2' ? 'none' : 'block';
var tableId = visible_id === 'id2' ? 'allTable1' : 'allTable2';
$.ajax({
url: "/index",
context: document.getElementById(tableId),
success: function (s) {
$("#" + tableId).html(s).load;
// when the ajax request has finished, initiate the next ajax request
// after a 1 second delay
window.setTimeout( toggleDisplay, 1000 );
}
});
visible_id = visible_id === 'id2' ? 'id1' : 'id2';
}
})();
</script>

Highlight each row when selecting multiple rows

I'm using the this Jquery code to select multiple rows at once. As you see I tried changing the background color with the code "lastChecked.style.background = "yellow";" but it's not working. How do I do this?
var lastChecked = null;
$(document).ready(function() {
$('.chkbox').click(function(event) {
if(!lastChecked) {
lastChecked = this;
return;
}
if(event.shiftKey) {
var start = $('.chkbox').index(this);
var end = $('.chkbox').index(lastChecked);
for(i=Math.min(start,end);i<=Math.max(start,end);i++) {
$('.chkbox')[i].checked = lastChecked.checked;
lastChecked.style.background = "yellow";
}
}
lastChecked = this;
});
});
Here's all of the code used:
{% extends "base.html" %}
{% block title %}Most Common Calls | CPRS Help{% endblock %}
{% block script %}
<script type="text/javascript">
/*<![CDATA[*/
function highlight_row(row_id,checkbox)
{
var row = document.getElementById(row_id);
row.style.background = checkbox.checked ? "yellow" : "";
}
function unhighlight_row(row_id)
{
var row = document.getElementById(row_id);
row.style.background = "white"; // background yellow
}
/*]]>*/
</script>
{% endblock %}
{% block content %}
<h2>Most Common Calls</h2>
<form action="/mark_as_uninteresting/" method="post">
{% csrf_token %}
<table class="calls">
<tr><th style="width:30px">N</th><th>Word</th><th style="width:150px;"><input class="searchbutton" type="submit" value="Mark as Uninteresting" /></th></tr>
{% for word in word_frequencies %}
<tr id="row_{{ forloop.counter }}"><td>{{ word.n }}</td><td style="padding:0;">{{ word.word }}</td><td style="text-align:center"><input type="checkbox" name="checkbox_{{ word.id }}" onclick="highlight_row('row_{{ forloop.counter }}',this)" id="id_chk{{ forloop.counter }}" class="chkbox" /></td></tr>
{% endfor %}
</table>
</form>
<script type="text/javascript" src="/media/js/jquery-1.5.2.min.js"></script>
<script type="text/javascript">
var lastChecked = null;
$(document).ready(function() {
$('.chkbox').click(function(event) {
if(!lastChecked) {
lastChecked = this;
return;
}
if(event.shiftKey) {
var start = $('.chkbox').index(this);
var end = $('.chkbox').index(lastChecked);
for(i=Math.min(start,end);i<=Math.max(start,end);i++) {
$('.chkbox')[i].checked = lastChecked.checked;
}
}
lastChecked = this;
});
});
</script>
{% endblock %}
UPDATED SOLUTION:
Ok, now that your issue is more clear, here is the correct solution:
If you want the rows to have a background color when selecting using the shift key, you need to change this line:
lastChecked.style.background = "yellow";
to →
$('.chkbox')[i].parentNode.style.backgroundColor='yellow';
OR
$('.chkbox').eq(i).parents('tr').style.backgroundColor='yellow';
Your version tries to set the background color on the checkbox. This is impossible. You need to select the checkbox's parent Node.
The first version in my solution will target the checkbox's immediate parent. This is ok to use in your case if your <tr>'s only go one level deep. If, however, your <tr>'s can go deeper (i.e. a checkbox might be in a <span> which is then inside the <tr>) you should use the second version, which searches the checkbox's ancestors for a <tr> element, then sets its background.

Categories