display elements from bottom to top like facebook messages - html

I want to display elements from bottom to top like how the facebook messages are displayed from bottom to top. How would I do that?
html:
<div id="message_wrapper">
<div class="message">
<p>1 Message message message....</p>
</div>
<div class="message">
<p>2 Message message message....</p>
</div>
<div class="message">
<p>3 Message message message....</p>
</div>
<div class="message">
<p>4 Message message message....</p>
</div>
</div>
So I would like it to display:
4 Message message message....
3 Message message message....
2 Message message message....
1 Message message message....
Update: Added django tempate
This the template for coversation.html:
<div id="messages_wrapper">
<!-- if there are conversation in the recent thread, then show the conversation -->
{% if conversations != 0 %}
<p><b>You have conversations:</b></p>
<!-- check the messagestate of each message of the recent_tread, if all the messages of the thread are not hidden then show the messages -->
{% if recent_thread|all_message_hidden:user %}
<p>All messages are hidden</p>
{% else %}
{% for conversation in conversations %}
{% if conversation|conversation_hidden:user %}
{% if conversation.sender == user %}
<div id="conversation" class="user_sent_conversation">
<p>{{conversation.id}}-{{conversation.body}} : Sender- {{conversation.sender}}, ID {{conversation.sender.id}}</p>
<p>Already hidden</p>
</div>
<hr/>
{% else %}
<div id="conversation" class="others_sent_conversation">
<p>{{conversation.id}}-{{conversation.body}} : Sender- {{conversation.sender}}, ID {{conversation.sender.id}}</p>
<p>Already hidden</p>
</div>
<hr/>
{% endif %}
{% else %}
{% if conversation.sender == user %}
<div id="conversation" class="user_sent_conversation">
<p>{{conversation.id}}-{{conversation.body}} : Sender- {{conversation.sender}}, ID {{conversation.sender.id}}</p>
[X]
</div>
<hr/>
{% else %}
<div id="conversation" class="others_sent_conversation">
<p>{{conversation.id}}-{{conversation.body}} : Sender- {{conversation.sender}}, ID {{conversation.sender.id}}</p>
[X]
</div>
<hr/>
{% endif %}
{% endif %}
{% endfor %}
<div id="message_form_wrapper_inside">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="/inbox/send_messages/{{recent_thread|get_user_id:user}}/" method="post">
{% csrf_token %}
<label for="recipient">To - {{recent_thread|get_user_id:user}}</label>
<label for="subject">
Subject -
{% if recent_thread.subject != '' %}
{{recent_thread.subject }}
{% else %}
No subject
{% endif %}
</label>
<label for="body">Message</label>
<textarea name="body" id="body" value=""></textarea>
<input type="submit" value="Send">
</form>
</div>
{% endif %}
{% else %}
<p>No message for this thread</p>
{% endif %}
</div>
Updated: Added the views.py
Views for displaying the message.
#login_required(login_url='/accounts/required_login/')
def message(request):
user = request.user
# Get all the threads of that user
threads = user.thread_set.all()
# Order the threads by which thread recieved the latest message
order_threads_message = threads.annotate(max_sent_date=Max('message__sent_date')).order_by('-max_sent_date')
if order_threads_message.count() > 0:
# Get the recent thread
recent_thread = order_threads_message[0]
if recent_thread.message_set.all().count() > 0:
# Get the conversations of the recent thread
recent_thread_conversations = recent_thread.message_set.all()
return render(request, 'conversations.html', {
'recent_thread':recent_thread,
'all_threads':order_threads_message,
'conversations':recent_thread_conversations,
'active': recent_thread.id
})
else:
recent_thread_conversations = 0
return render(request, 'conversations.html', {
'recent_thread':recent_thread,
'all_threads':order_threads_message,
'conversations':recent_thread_conversations,
'active': recent_thread.id
})
else:
order_threads_message = 0
recent_thread_conversations = 0
return render(request, 'conversations.html', {
'all_threads':order_threads_message,
'conversations':recent_thread_conversations,
})

The simplest solution is to loop over the messages in reversed orderr:
{% for conversation in conversations reversed %}
...
{% endfor %}

In order to get it displayed "bottoms up" use the #reverse() method on your QuerySet.
This is assuming that the threads are sorted in descending order, that is, newest message is first.
recent_thread_conversations.reverse()

Related

HTML search function using a wildcard - shopify

I am a super beginner with HTML, however, I am trying to resolve an issue with my website. I am trying to concatenate a wildcard(*) to the end of whatever a consumer tries to search so that it picks up similarly tagged items, however, I cannot figure out where to add said code... Our current search query works well when pulling up items based on partial keywords, but when hitting the 'enter' button it will say it could not find any products.
Additional notes: This is a Shopify website with a theme from halothemes so most of this is coded by them.
{% assign grid_results = true %}
<div class="search-page collection-template" data-search-page>
<div class="container">
{% if search.performed %}
{% comment %}
Avoid accessing search.results before the opening paginate tag.
If you do, the pagination of results will be broken.
{% endcomment %}
{% paginate search.results by 15 %}
{% comment %}
We don't have any results to show. Feel free to show off featured products
or suggested searches here.
{% endcomment %}
{% if search.results_count == 0 %}
<header class="page-header">
<h2>
{% render 'multilang' with settings.search_1 %}
<strong> "{{ search.terms }}" </strong>
{% render 'multilang' with settings.search_2 %}
</h2>
</header>
{% else %}
<header class="page-header">
<h2>
{% render 'multilang' with settings.search_3 %}
<strong> "{{ search.terms }}" </strong>
{% render 'multilang' with settings.search_4 %}
</h2>
</header>
{% comment %}
Each result template, based on the grid_layout variable above
{% endcomment %}
<div class="block-row col-main">
{% if grid_results == false %}
<div class="product-collection products-list product-search row">
{% for product in search.results %}
<div class="grid-item col-12{% if settings.product_image_border%} grid-item-border{% endif %}">
{% render 'search-result' with product as product %}
</div>
{% endfor %}
</div>
{% else %}
<div class="products-grid product-search row product-collection">
{% for product in search.results %}
<div class="grid-item col-6 col-md-4{% unless settings.layout_style == 'layout_style_1170' %} col5 col-lg-3{% endunless %}{% if settings.product_image_border%} grid-item-border{% endif %}">
{% if settings.style_product_grid == 'style_product_grid_2' %}
{% render 'product-grid-item-style-2' with product as product %}
{% else %}
{% render 'product-grid-item' with product as product %}
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
{% if paginate.pages > 1 %}
<div class="padding">
{% render 'pagination-page' paginate: paginate %}
</div>
{% endif %}
{% endpaginate %}
{% else %}
{% comment %}
If search.performed is false, someone either accessed the page without
the q parameter, or it was blank.
Be sure to show a search form here, along with anything else you want to showcase.
{% endcomment %}
<header class="page-header">
<h2 style="text-align:center" {% if settings.enable_multilang %}data-translate="general.search.title"{%endif%}>{{ 'general.search.title' | t }}</h2>
<div class="header-search__form">
<form action="/search" method="get" class="search-bar" role="search">
<input type="hidden" name="type" value="product">
<input type="search" name="q"
{% if settings.enable_multilang %} data-translate="general.search.placeholder" translate-item="placeholder"{% endif %}
placeholder="{{ 'general.search.placeholder' | t }}"
class="input-group-field" aria-label="Search Site" autocomplete="off">
<button type="submit" class="btn icon-search">
{% render 'icon-search' %}
</button>
</form>
</div>
</header>
{% endif %}
Please let me know if you guys need any additional information! Thank you!
You can use a simple script to add a wildcard to the search query on submitting the form e.g:
var searchForm = document.querySelector(".search-bar");
searchForm.addEventListener("submit", function(e) {
var searchInput = searchForm.querySelector("[name=q]");
var q = searchInput.value;
if (!q.match(/\*$/)) {
e.preventDefault();
searchInput.value = q + "*";
searchForm.submit();
}
});

How do I show an HTML message with Flask if the Jinja for loop returns nothing

I am using Flask and I am looping through a table Buyers object in Jinja. What I want to happen is to show a message in the HTML page if there is no data in a specific field Buyers.supplier of the table.
Let's say the table has 5 entries and there are no fields present, what happens in my present code is that I see my message 5 times.
Is there a way to just show the HTML message if all of the fields are empty? Thank you!
main.html
<div class="card-deck">
{# Go through each blog post #}
{% for sched in buyer_sched|sort(attribute='time') %}
{# Only show if a supplier has been matched#}
{% if sched.supplier.company %}
<div class="row pl-3 ml-1">
<p>Show some information</p>
</div>
{% else %}
<p>There is no data</p>
{% endif %}
{% endfor %}
<div />
{% else %}
<p>Please login and register</p>
{% endif %}
{% endblock %}
I answered this in a different (perhaps not so pythonic way).
I basically iterated through the field on the python side and used a counter to count up. If the number was greater than 0, then when I passed the integer into my html template, it wouldn't show the message.
Thank you!
buyer_sched = db.session.query(Buyerschedule).\
filter(Buyerschedule.buyer_id == buyer_id).all()
# Iterate through schedule and if all are none, set
# completed to none
completed = 0
for sched in buyer_sched:
print(f'The schedule name is: {sched.id}')
if sched.supplier_id:
completed = completed + 1
print(f'completed is {completed}')
print(f'completed is equal to {completed}')
You could create a custom jinja filter (https://flask.palletsprojects.com/en/1.1.x/templating/#registering-filters) to check if all are empty before the for loop:
def all_empty(data, key):
return all(not d[key] for d in data)
app.jinja_env.filters['all_empty'] = all_empty
Once registered, you can call that function in your template:
<div class="card-deck" >
{% if data|all_empty('supplier') %}
<p>There is no data</p>
{% else %}
{% for sched in data %}
{% if sched.supplier and sched.supplier.company %}
<div class="row pl-3 ml-1">
<p>{{ sched.supplier.company }}</p>
</div>
{% endif %}
{% endfor %}
{% endif %}
</div>

Bootstrap Alert div remains when there are no messages

I have an error message alert bar in my website, I'm trying to make this only appear whenever there is a message to display as currently it remains even when there are no messages. Does anyone know how to do this?
Here is my alert..
<div class="alert alert-success">
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }} </li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
Wrap your conditions under alert div, like:
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-success">
<ul>
{% for message in messages %}
<li>{{ message }} </li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
Hope this helps!

Shopify discount code specific message to be displayed

I want to apply discount code specific messages on the shopify email templates. I tried the following code, it's showing me error - "Liquid error: Unknown operator = " in the purchase email which I receive.
<div class="row">
<div class="left-column">
{% if discounts %}Discount (code: {{ discounts.first.code }})
</div>
<div class="right-column">
{{ discounts_savings | money_with_currency }}
{% endif %}
</div>
<div class="left-column">
{% for discount in discounts %}
{% if discount.first.code = "DISCODE-2015" %}
Your $50 amazon.com gift card will be send to you soon!
{% endif %}
{% endfor %}
</div>
</div>
You are using =, but it should be ==. See here.
I think you also want discount.code where you have discount.first.code.
Try replacing this line:
{% if discount.first.code = "DISCODE-2015" %}
with this:
{% if discount.code == "DISCODE-2015" %}

Twig loop grouping divs

I want to populate a twig page with information stored in the database. I use a loop to make multiple divs containing different entries of the same tables. The only problem is that I want to group the divs by4.. and I can't stop the loop when I reach the fourth step. In the end i get a big colon of divs.
Can anyone please tell me how to group the divs by 4?
This is my twig template:
<form method="POST" id="form-book">
<section id="portfolio" class="container main">
<ul class="gallery col-4">
{% for type in typeandrooms %}
{% for t, room in type %}
<li>
{% if t == 0 %}
<div class="preview">
{% set var_id = 'bundles/twnelo/images/portfolio/thumb/item' %}
{% set var_id = var_id ~ room.getType.id %}
{% set var_id = var_id ~ '.jpg' %}
<img src="{{ asset(var_id) }}">
<div class="overlay">
</div>
</div>
<div class="desc">
<h5> {{ room.getType.name }} </h5>
<strong>Beds: </strong>Double bed<br/>
<strong>Available rooms: </strong> {{ type|length }} <br/>
<strong>Prices: </strong> {{ room.getPrice }} <br/>
<button type = "submit" name="singleapartment" value = "{{ room.getType.id }}" class="btn btn-success btn-small">Book a room !</button>
</div>
{% endif %}
{% if loop.index % 4 == 0 and loop.index > 0 %}
</li>
Al 4-lea pas
<li>
{% endif %}
</li>
{% endfor %}
{% endfor %}
</ul>
</section>
</form>
{% endfor %}
Problem is solved. This is the new template:
<form method="POST" id="form-book">
<section id="portfolio" class="container main">
<ul class="gallery col-4">
{% for rooms in typesandrooms %}
{% for room in rooms %}
{% if loop.index == 1 %}
<li>
<div class="preview">
{% set var_id = 'bundles/twnelo/images/portfolio/thumb/item' %}
{% set var_id = var_id ~ room.getType.id %}
{% set var_id = var_id ~ '.jpg' %}
<img src="{{ asset(var_id) }}">
<div class="overlay">
</div>
</div>
<div class="desc">
<h5> {{ room.getType.name }} </h5>
<strong>Facilities: </strong>{% for facility in room.getFacilities %} {% if loop.index < 4 %} {{ facility.getFacility }}; {% endif %} {% endfor %}<br/>
<strong>Available rooms: </strong> {{ rooms|length }} <br/>
<strong>Prices: </strong> {{ room.getPrice }} Lei <br/>
<button type = "submit" name="singleapartment" value = "{{ room.getType.id }}" class="btn btn-success btn-small">Book a room !</button>
</div>
</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</section>
</form>
You have to open the first row right before the loop.
{% for type in typeandrooms %}
+ <li>
{% for t, room in type %}
- <li>
And close the last one right after
{% endif %}
- </li>
{% endfor %}
+ </li>
{% endfor %}
And given this line {% if t==0 %} I reckon you'll need to use a counter instead of index.loop. Else you could end up with less than 4 room per list row. The best practice would be to parse the array first in your controller and remove the rooms with t==0 then just remove the {% if t==0 %} line in your twig template and it'll work with index.loop, you want to keep the logic in twig to a minimum.