Django and waypoints Infinite scroll not working - javascript

I have tried all the answers on stack and the infinite scroll is still not working. My home.html is still displaying the pagination. I suspect the problem is with jquery or the js files or with how the static file is loaded?
Here is my home.html:
{% block content %}
{% load static %}
<div class="infinite-container">
{% for post in posts %}
<div class="infinite-item">
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"F d, Y" }}</small>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
</div>
{% endfor %}
</div>
<div class="d-flex d-none position-fixed" style="top:35vh;left:46vw">
<button class="btn btn-primary loading">
<span class="spinner-border spinner-border-sm"></span>
Please wait...
</button>
</div>
<!--pagination logic -->
<div class="col-12">
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</div>
<script src="/static/js/jquery.waypoints.min.js"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
offset: 'bottom-in-view',
onBeforePageLoad: function () {
$('.loading').show();
},
onAfterPageLoad: function () {
$('.loading').hide();
}
});
</script>
{% endblock content %}
In my settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [Path(BASE_DIR, 'static'),]
The directory of my js files.
I have added the following within my base.html at the bottom.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
here is my class based view in view.py:
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5

Related

AJAX - Show a <div> on a button click

As I am implementing AJAX, I would like this whole <div> to show up as a consequence of clicking the button in the script below :
<div class="col-12" id="deleteVote">
<div class="row mb-2" >
<div class="col-12">
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
<a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm deleteVote" data-toggle="deleteConfirmation">
<i class="bi bi-trash"></i> {{ 'vote-delete' | trans }}
</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
Here is the script, I don't really know why the .show is not working :
<script>
$(document).on('click', '.votedFullAgreement', function (){
$.ajax({
url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
$('#deleteVote').show();
},
error: function (resultat, statut, erreur) {
}
});
return false;
});
</script>
Btw the script is probably not optimised at all but it's my first one and it's working and sending data...
Thank you !
EDIT 2 :
I don't understand why this if/else doesn't work. When there's a vote, the if works, the button is there when we come back/reload the page, but when there is no vote yet, the .show(); doesn't activate the else which is in display:none.
Is it because as soon as I vote, the if becomes true? (and .show(); needs something previously hidden to display but can't find any...)
{# Standard loop #}
{% if proposal.votedByUser(app.user) %}
<div class="col-12">
<div class="row mb-2">
<div class="col-12">
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
<a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation">
<i class="bi bi-trash"></i> {{ 'vote-delete' | trans }}
</a>
{% endfor %}
</div>
</div>
</div>
{% else %}
{# AJAX loop #}
<div class="col-12">
<div class="row mb-2">
<div class="col-12">
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
{# ID deleteVote here, which has display:none in the CSS #}
<a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" id="deleteVote" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation">
<i class="bi bi-trash"></i> {{ 'vote-delete' | trans }}
</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
If I split both loops, the AJAX one works only when there is already a vote registered (and the button of the standard loop is already there)

Shopify Store Refresh cart content. AJAX request

I have product page on which I have shop now btn. When user clicks on this button, page opens cart drawer with custom ajax template content.
I rewrited click event with my own logic. I use AJAX and send request for adding product by myself. Products are adding but is not showing in the cart drawer. Only after reloading page it is appearing.
Question is to can I refresh cart content? I'm trying to past content template via inner html. But it is looks like not liquid format.
Here is the template
<script id="CartTemplate" type="text/template">
{% render 'banana-stand-cart-top-container' %}
{% raw %}
<div class="drawer__scrollable">
{{#items}}
<div class="ajaxcart__product appear-animation appear-delay-{{animationRow}}">
<div class="ajaxcart__row">
<div class="grid">
<div class="grid__item one-third">
<img src="{{img}}" alt="{{name}}">
</div>
<div class="grid__item two-thirds">
<div class="ajaxcart__product-name--wrapper">
{{{name}}}
{{#if variation}}
<div class="ajaxcart__product-meta">{{variation}}</div>
{{/if}}
{{#if selling_plan_name}}
<div class="ajaxcart__product-meta">{{selling_plan_name}}</div>
{{/if}}
{{#properties}}
{{#each this}}
{{#if this}}
<span class="ajaxcart__product-meta">{{#key}}: {{this}}</span>
{{/if}}
{{/each}}
{{/properties}}
</div>
<div class="grid grid--full display-table">
<div class="grid__item display-table-cell one-half">
<label for="updates_{{key}}" class="visually-hidden">{% endraw %}{{ 'products.product.quantity' | t }}{% raw %}</label>
<div class="js-qty__wrapper">
<input type="text" id="updates_{{key}}"
class="js-qty__num"
value="{{itemQty}}"
data-id="{{key}}"
min="0"
aria-label="quantity"
pattern="[0-9]*"
name="updates[]">
<button type="button"
class="js-qty__adjust js-qty__adjust--minus"
aria-label="{% endraw %}{{ 'cart.general.reduce_quantity' | t }}{% raw %}">
{% endraw %}<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-minus" viewBox="0 0 20 20"><path fill="#444" d="M17.543 11.029H2.1A1.032 1.032 0 0 1 1.071 10c0-.566.463-1.029 1.029-1.029h15.443c.566 0 1.029.463 1.029 1.029 0 .566-.463 1.029-1.029 1.029z"/></svg>{% raw %}
<span class="icon__fallback-text" aria-hidden="true">−</span>
</button>
<button type="button"
class="js-qty__adjust js-qty__adjust--plus"
aria-label="{% endraw %}{{ 'cart.general.increase_quantity' | t }}{% raw %}">
{% endraw %}<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-plus" viewBox="0 0 20 20"><path fill="#444" d="M17.409 8.929h-6.695V2.258c0-.566-.506-1.029-1.071-1.029s-1.071.463-1.071 1.029v6.671H1.967C1.401 8.929.938 9.435.938 10s.463 1.071 1.029 1.071h6.605V17.7c0 .566.506 1.029 1.071 1.029s1.071-.463 1.071-1.029v-6.629h6.695c.566 0 1.029-.506 1.029-1.071s-.463-1.071-1.029-1.071z"/></svg>{% raw %}
<span class="icon__fallback-text" aria-hidden="true">+</span>
</button>
</div>
</div>
<div class="grid__item display-table-cell one-half text-right">
{{#if discountsApplied}}
<small class="cart__price--strikethrough">{{{price}}}</small>
<span class="ajaxcart__price">
{{{discountedPrice}}}
</span>
{{else}}
<span class="ajaxcart__price">
{{{price}}}
</span>
{{/if}}
</div>
</div>
<div class="grid grid--full display-table">
{{#if discountsApplied}}
<div class="grid__item text-right">
{{#each discounts}}
<small class="ajaxcart__discount cart__discount">
{{this.discount_application.title}} (-{{{this.formattedAmount}}})
</small>
{{/each}}
</div>
{{/if}}
{{#if unitBase}}
<div class="grid__item text-right">
<div class="product__unit-price">
{{{ unitPrice }}}/{{{ unitBase }}}
</div>
</div>
{{/if}}
</div>
</div>
</div>
</div>
</div>
{{/items}}
{% endraw %}{% if settings.cart_notes_enable %}{% raw %}
<div class="appear-animation appear-delay-{{lastAnimationRow}}">
<label for="CartSpecialInstructions" class="ajaxcart__note">{% endraw %}{{ 'cart.general.note' | t }}{% raw %}</label>
<textarea name="note" class="input-full cart-notes" id="CartSpecialInstructions">{{note}}</textarea>
</div>
{% endraw %}{% endif %}{% raw %}
</div>
<div class="drawer__footer appear-animation appear-delay-{{lastAnimationRow}}">
{{#if cartDiscounts }}
<div class="grid grid--full">
<div class="grid__item one-half">
<p class="ajaxcart__subtotal">{% endraw %}{{ 'cart.general.discounts' | t }}{% raw %}</p>
</div>
<div class="grid__item one-half text-right">
{{#each cartDiscounts}}
<p class="ajaxcart__price cart__discount">
{{this.title}} (-{{{this.formattedAmount}}})
</p>
{{/each}}
</div>
</div>
{{/if}}
<div class="grid grid--full">
<div class="grid__item one-half">
<p class="ajaxcart__subtotal">{% endraw %}{{ 'cart.general.subtotal' | t }}{% raw %}</p>
</div>
<div class="grid__item one-half text-right">
<p class="ajaxcart__price"><span class="tdf-cart-total-parent">{{totalPrice}}</span></p>
</div>
</div>
<p class="ajaxcart__note">
{% endraw %}{{ 'cart.general.shipping_at_checkout' | t }}{% raw %}
</p>
{% endraw %}{% if settings.cart_terms_conditions_enable %}
<p class="ajaxcart__note ajaxcart__note--terms">
<input type="checkbox" id="CartAgree" />
<label for="CartAgree">
{% if settings.cart_terms_conditions_link != blank %}
{{ 'cart.general.terms_html' | t: url: settings.cart_terms_conditions_link }}
{% else %}
{{ 'cart.general.terms' | t }}
{% endif %}
</label>
</p>
{% endif %}{% raw %}
{% endraw %}
{% if additional_checkout_buttons and settings.cart_additional_buttons %}
<div class="additional-checkout-buttons additional-checkout-buttons--vertical">{{ content_for_additional_checkout_buttons }}</div>
{% endif %}
{% raw %}
<button type="submit" class="btn btn--full cart__checkout{% endraw %}{% if settings.cart_terms_conditions_enable %}{% raw %} cart__checkout--ajax{% endraw %}{% endif %}{% raw %}" name="checkout">
{% endraw %}{{ 'cart.general.checkout' | t }}{% raw %}
</button>
</div>
{% endraw %}
Usually, there is some way (js-function) that allows you to rebuild the cart with new items.
You need to check the js-code that is responsible for showing the drawer-cart
So, need fire some event that you can find in your theme.js file. In my case I needed to add this:
document.dispatchEvent(new CustomEvent('cart:build', {
detail: {
cart: cart
}
}));

How to change the id of any tag wiht javascript?

Html Code:-
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<h2><a id="post_title" class="article-title" href="{% url 'post-detail' post.slug %}">{{ post.title }}</a></h2>
<div class="article-metadata">
<a class="mr-2" href="{% url 'blog-profile' name=post.author %}">{{ post.author }}</a>
<div class="float-right">
<small class="text-muted">Category</small>
<small class="text-muted">{{ post.date_posted }}</small>
</div>
<div style="float:right;">
<img style="height:19px; width:18px;" src="{% static "blog/viewicon.png" %}">
<p style="float: right; display: inline !important;" id="ViewCount">
</p>
</img>
</div>
</div>
<p class="article-content">{{ post.content|truncatechars:200|safe }}</p>
</div>
<script>
function changeid ()
{
var e = document.getElementById('post_title');
e.id = 'post_title_1';
var e = document.getElementById('ViewCount');
e.id = 'ViewCount_1';
}
</script>
</article>
{% endfor %}
I am trying to change the id of those two tags but, this script doesn't seem to work, or it's been not exected. I want to change that id because I want to insert some data to them from the server. Since we can't have the same id the data which I am trying to embed is embedded by defaut to only the first run of the loop.
You don't need to change the id in each iteration using JavaScript. You can achieve the same using Django's inbuilt forloop.counter template tag.
( https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#for )
So in your case, it would be something like:
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<h2><a id="post_title_{{ forloop.counter }}" class="article-title" href="{% url 'post-detail' post.slug %}">{{ post.title }}</a></h2>
<div class="article-metadata">
<a class="mr-2" href="{% url 'blog-profile' name=post.author %}">{{ post.author }}</a>
<div class="float-right">
<small class="text-muted">Category</small>
<small class="text-muted">{{ post.date_posted }}</small>
</div>
<div style="float:right;">
<img style="height:19px; width:18px;" src="{% static " blog/viewicon.png " %}">
<p style="float: right; display: inline !important;" id="ViewCount__{{ forloop.counter }}">
</p>
</img>
</div>
</div>
<p class="article-content">{{ post.content|truncatechars:200|safe }}</p>
</div>
</article>
{% endfor %}
Use an IIFE - An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.
<script>
(() => {
let a = document.getElementById('post_title');
a.setAttribute("id", 'post_title_1');
let b = document.getElementById('ViewCount');
b.setAttribute("id", 'ViewCount_1');
})();
</script>
try using document.getElementById('footer').setAttribute('id','post_title_1')
Also Make sure you are calling the changeid() function
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<h2><a id="post_title" class="article-title" href="{% url 'post-detail' post.slug %}">{{ post.title }}</a></h2>
<div class="article-metadata">
<a class="mr-2" href="{% url 'blog-profile' name=post.author %}">{{ post.author }}</a>
<div class="float-right">
<small class="text-muted">Category</small>
<small class="text-muted">{{ post.date_posted }}</small>
</div>
<div style="float:right;">
<img style="height:19px; width:18px;" src="{% static "blog/viewicon.png" %}">
<p style="float: right; display: inline !important;" id="ViewCount">
</p>
</img>
</div>
</div>
<p class="article-content">{{ post.content|truncatechars:200|safe }}</p>
</div>
<script>
function changeid ()
{
document.getElementById('post_title').setAttribute('id','post_title_1');
document.getElementById('ViewCount').setAttribute('id','ViewCount_1')
}
</script>
</article>
{% endfor %}

Adding Django MultipleChoiceField one after the other using Javascript

I am working on a Django views based on the following form:
class MyForm(forms.Form):
def __init__(self, data, examen, *args, **kwargs):
super(MyForm, self).__init__(data, *args, **kwargs)
self.fields['q1'] = forms.MultipleChoiceField(
label=mark_safe("Label question 1"),
required=True,
widget=forms.CheckboxSelectMultiple,
choices=(('1', 'answer 1'), ('2', 'answer 2'), ('3', 'answer 3'))
)
self.fields['q2'] = forms.MultipleChoiceField(
label=mark_safe("Label question 2"),
required=True,
widget=forms.CheckboxSelectMultiple,
choices=(('1', 'answer 4'), ('2', 'answer 5'), ('3', 'answer 6'))
)
... #TODO : add questions q3 to q9
self.fields['q10'] = forms.MultipleChoiceField(
label=mark_safe("Label question 10"),
required=True,
widget=forms.CheckboxSelectMultiple,
choices=(('1', 'answer 28'), ('2', 'answer 29'), ('3', 'answer 30'))
)
Il would like to display on a single view self.fields['q1'] with a [submit] button. The idea is for the user to select the answer he considers as correct and the hit the [submit] button. Following that self.fields['q1'] will turn into read-only and self.fields['q2'] will display just below with again a [submit] button... and son on until self.fields['q10'].
I do believe that the only way to achieve that is to use Javascript (and even JQuery or any other library). The problem is that I'm not very familiar with Javascript and would gladly appreciate hints on how to tackle that issue.
Thank you for what you can do!
PS: I'm happy to change my Django design if you think this is not the proper way to achieve my goal.
EDIT 29/11/2019: my current template looks like:
<form action="{% url 'quizz' my_exam %}" method="post">
{% csrf_token %}
{% for field in form %}
{% ifequal forloop.counter0 0 %}
<div class="card text-white bg-primary mb-3">
<div class="card-body">
<h6 class="card-title">{{ field.label|linebreaksbr }}</h6>
</div>
</div>
{% else %}
<div class="card">
<h5 class="card-header">{{field.name}}</h5>
<div class="card-body">
<h6 class="card-title">{{ field.label|linebreaksbr }}</h6>
<p class="card-text">{{ field }}</p>
</div>
</div>
{% endifequal %}
{% endfor %}
<input type="submit" value="Submit" class="btn btn-primary"/>
</form>
EDIT 30/11/2019: new template based on #Phanti suggestions:
<script>
{% block jquery %}
$("#submit_2").click(function() {
$("#questions_container").find(":hidden").show().next();
}
{% endblock %}
</script>
{% block content %}
<form action="{% url 'quizz' exam %}" method="post">
{% csrf_token %}
<div id="questions_container">
{% for field in form %}
{% ifequal forloop.counter 1 %}
<div class="card text-white bg-primary mb-3">
<div class="card-body">
<h6 class="card-title">{{ field.label|linebreaksbr }}</h6>
</div>
</div>
{% else %}
{% ifequal forloop.counter 2 %}
<div id="question_{{ forloop.counter }}" class="card" style="display: block;">
<h5 class="card-header">{{field.name}}</h5>
<div class="card-body">
<h6 class="card-title">{{ field.label|linebreaksbr }}</h6>
<p class="card-text">{{ field }}</p>
</div>
</div>
<input id="submit_{{ forloop.counter }}" value="Valider" class="btn btn-primary" style="display: block;"/>
{% else %}
<div id="question_{{ forloop.counter }}" class="card" style="display: none;">
<h5 class="card-header">{{field.name}}</h5>
<div class="card-body">
<h6 class="card-title">{{ field.label|linebreaksbr }}</h6>
<p class="card-text">{{ field }}</p>
</div>
</div>
{% if not forloop.last %}
<input id="submit_{{ forloop.counter }}" value="Submit" class="btn btn-primary" style="display: none;"/>
{% else %}
<input id="submit_{{ forloop.counter }}" type="submit" value="Submit" class="btn btn-primary" style="display: none;"/>
{% endif %}
{% endifequal %}
{% endifequal %}
{% endfor %}
</div>
</form>
{% endblock %}

Python Django project - move div class footer into body

I'm creating a blog with python and django. Most of it has been fine up until i've just tried to create the footer. The footer display's fine on the home page but when you click into the blog post the footer gets constrained by the content container and row div class.
When you look at this in firefox dev inspector and DOM it's showing that my footer div is sat within the content container and row, and not in the body. Most things i've usually managed to find the answer for but this is driving me nuts. I think i'm either missing something or i'm not asking the right question.
I don't understand why it's just the footer div that has been put within the content container / row div and nothing else that is effected in the same way.
Is there anyway to amend this without using jquery / jscript and changing the parentElement node?
If i have to amend this with jscript, where exactly do i have to amend it, and with what?
Thanks
.footer {
height: 50px;
background-color: #000000;
color: #ffffff;
padding: 10px;
text-align: center;
clear: both;
}
<div class="content container">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
<footer>
<div class="footer">
Copyright &copy 2017
</div>
</footer>
firefox dev inspector image - sat in row div
firefox dev inspector image - moved to body
This could happen if there are opening tags that don't have closing tags. For example, if your blog looked like this,
{% block content %}
<div id="open_tag_1">
<div id="open_tag_2">
{% endblock %}
The tags that you expect to be closing <div class="content container"> and <div class="row"> will actually be used to close <div id="open_tag_1"> and <div id="open_tag_2">.
<footer> will then be inside <div class="row">.
This is the blog post detail page
{% extends 'blog/base.html' %}
{% block content %}
{% if post.published_date %}
{{ post.published_date }}
by Matt Cheetham
{% else %}
<a class="btn btn-default" href="{% url 'blog.views.post_publish' pk=post.pk %}">Publish</a>
{% endif %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
{% endif %}
<div class="postview">
{{ post.title }}
</div>
<p>{{ post.text|safe }}</p>
<div class="comment">
<div class="date">
<h3>Comments</h3>
<br>
<a class="btn btn-default" href="{% url 'add_comment_to_post' pk=post.pk %}">Add comment</a>
<br>
<br>
{% for comment in post.comments.all %}
{% if user.is_authenticated or comment.approved_comment %}
{{ comment.created_date }}
{% if not comment.approved_comment %}
<a class="btn btn-default" href="{% url 'comment_remove' pk=comment.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-default" href="{% url 'comment_approve' pk=comment.pk %}"><span class="glyphicon glyphicon-ok"></span></a>
{% endif %}
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|safe }}</p>
</div>
{% endif %}
{% empty %}
<p>No comments here yet...</p>
{% endfor %}
{% endblock %}

Categories