Show and hide text of different posts - javascript

I have several posts each of them composed of three parts : a title, a username/date and a body. What I want to do is to show the body when I click on either the title or the username/date and hide it if I click on it again. What I've done so far works but not as expected because when I have two or more posts, it only shows the body of the last post even if I click on another post than the last one. So my goal is only to show the hidden text body corresponding to the post I'm clicking on. Here is my code:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Test page{% endblock %}</h1>
<a class="action" href="{{ url_for('main_page.create') }}">New</a>
{% endblock %}
{% block content %}
{% for post in posts %}
<article class="post">
<header>
<script language="JavaScript">
function showhide(newpost)
{var div = document.getElementById(newpost);
if (div.style.display !== "block")
{div.style.display = "block";}
else {div.style.display = "none";}}
</script>
<div onclick="showhide('newpost')">
<h1>{{ post['title'] }}</h1>
<div class="about">by {{ post['username'] }} on {{ post['created'].strftime('%d-%m-%Y') }}</div>
</div>
</header>
<div id="newpost">
<p class="body">{{ post['body'] }}</p>
</div>
</article>
{% if not loop.last %}
<hr>
{% endif %}
{% endfor %}
{% endblock %}
Of course I looked for a solution as much as I could but I'm kind of stuck plus I'm a complete beginner in HTML/JS/CSS. And one last thing, I'm currently using Python's framework Flask. Thank you by advance.

You need to give each of your posts a unique id for your approach to work.
Change your code to
<div id="{{post_id}}">
<p class="body">{{ post['body'] }}</p
</div>
where post_id is that post's unique id e.g. its id in the database you are using that you pass to the template in your view. Then, change the call to the onclick event handler to
<div onclick="showhide('{{post_id}}')">
If you don't have a unique id you can also use the for loop's index: replace all post_id instances above with loop.index. See Jinja's for loop docs for more information.

Related

(JS) Markdown issue in flask

I have a small problem with markdown in my flash project.
I want markdown to work for all posts, currently it only works for the first post. I suspect I need to use some kind of loop, but I don't know what to do to make it work.
Code:
{% extends "layout.html" %}
{% block content %}
<article class="media content-section">
<div class="media-body">
{% for post in document.posts %}
<div class="article-metadata">
<h3><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h3>
<p class="article-content">{{ post.content }}</p>
</div>
{% endfor %}
</div>
</article>
<script>
const content_text = document.querySelector(".article-content");
content_text.innerHTML = marked(content_text.innerHTML);
</script>
{% endblock content %}
Pic of the posts on website
querySelector returns the first element with the class. You need to use querySelectorAll to get all the elements and then use for loop to loop and apply markdown to each element.
const content_text = document.querySelectorAll(".article-content");
for (i = 0; i < content_text.length; i++){
content_text[i].innerHTML = marked(content_text[i].innerHTML);
}

Changing elements' CSS using jQuery after another element is changed with AJAX

I have a custom button in the a header next to a "cart" link. Website uses AJAX cart. When an item is added to cart, the cart link enlarges to include nr of items in cart. This causes the cart link to overflow and overlap the custom button next to it. Essentially what I'm trying to achieve is to add a margin to the custom button when an item is added to cart and the cart link is expanded. My first thought was to wrap both in a div and use CSS flex to adjust the sizing of both, however, and please correct me if I'm wrong, I thought it would be quicker to just write a script that would add a margin to my custom button. Definitely didn't turn out to be the quicker way as I've been stuck on it for hours now - any help would be greatly appreciated. I've browsed through similar posts and couldn't find a result that I want - any help would be greatly appreciated (I'm still new to JS and jQuery but learning). Below is the code and some of the things that I've tried.
HTML - header
<div class="header--menu">
<div class="custom-btn-container">
Quick Order
</div>
{%
render 'framework--x-menu',
js_class: 'XMenu',
align: menu_alignment,
overlap_parent: 1,
handle: menu
%}
</div>
{% endif %}
<div class="header--cart">
{% render 'snippet-cart', cart_icon: cart_icon %}
</div>
</div>
HTML - cart
{% if settings.cart--type == 'drawer' %}
<div
class="cart--open-right off-canvas--open"
data-off-canvas--open="right-sidebar"
data-off-canvas--view="cart"
aria-haspopup=”menu”
>
{% endif %}
<a
class="header--cart-link"
data-item="accent-text"
href="{{ routes.cart_url }}"
aria-label="{{ 'layout.header.cart' | t }}"
>
{% if cart_icon == 'text' %}
{{ 'layout.header.cart' | t }}
{% elsif cart_icon == 'bag' %}
{% render 'framework--icons', icon: 'bag' %}
{% else %}
{% render 'framework--icons', icon: 'cart' %}
{% endif %}
<span class="header--cart-number" data-item-count="{{ cart.item_count }}">
(<span class="cart--external--total-items">{{ cart.item_count }}</span>)
</span>
</a>
{% if settings.cart--type == 'drawer' %}
</div>
{% endif %}
And these are some of the scripts that I've tried:
window.onload = () => {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
The above is nearly what I'm after, but only works after refreshing the page.
document.ajaxComplete = () => {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
similar story
$(document).ajaxSuccess(function() {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
This didn't do anything whatsoever.
I'm sure I'm missing something small, but it's driving me mad. Again, any help will be greatly appreciated!
Best,
J

How do I populate dynamically a StringField with the value of a SelectField in Wtforms

in a wtforms, I would like my SelectField to fill up with its selected value a StringField.
I use flask, bootstrap, and python 3.7
My HTML code is as follow:
{% block body %}
<h3>Edit Bloomberg ticker details</h3>
{% from "includes/forms/_form_helpers.html" import render_field %}
<div class="form-group" id="company_id" onchange="myFunction(event)">
{{render_field(form.company_names, class_="form-control")}}
</div>
<div class="form-group" id="isin_id">
{{render_field(form.isin_id, class_="form-control")}}
</div>
<script>
function myFunction(e) {
document.getElementById("isin_id").value = e.target.value
}
</script>
{% endblock %}
And the pyhon behind is as follow:
class DefTickerForm(_Form):
choices_companies = [(1,'Facebook'), (2, 'Google') ]
company_names = _SelectField(label='Company names:', choices=choices_companies, coerce=int)
isin_id = _StringField(label='isin_id', validators=[_validators.DataRequired], default=-1)
I would like that when the user select 'Facebook', the isin SelectField to be equal to 1. But so far it does nothing.
Note that if if code:
alert(e.target.value)
I get the wanted value. so issue is to set the TextField value.
my render field code is as followed (from a youtube tutorial):
{% macro render_field(field) %}
{{ field.label }}
{{ field(**kwargs)|safe }}
{% if field.errors %}
{% for error in field.errors %}
<span class="help-inline"> {{ error }}</span>
{% endfor %}
{% endif %}
{% endmacro %}
Any help would be much apreciated as google isn't so good on these.
Best
apparently TextField only accepts strings (I guess obvious if you are used to javascript)
so code working is as follow in case someone get he same problem:
<div class="form-group" onchange="myFunction(event)">
{{render_field(form.company_names, class_="form-control")}}
</div>
<div class="form-group">
{{render_field(form.isin_id, class_="form-control")}}
</div>
<script>
function myFunction(e) {
var x = e.target.value;
alert(x);
document.getElementById("isin_id").value = x.toString();
}
</script>
As a note, Jinja or anyway my render, use the fields names as default IDs (wich i realised using Chrome inpector. Meaning I didn't have to add an id for each Div. Anyway that is the thoughts of a beginenr in Javascripts.

Toggle language of labels in flask wtforms form

I have a series of wtforms written in a flask app. One of my pages in my app will be used by people speaking English and Spanish. I would like to find a clean way of toggling the form element labels between English and Spanish with a toggle button on the webpage.
I found a nice solution to toggle languages using the HTML lang attribute here (2nd answer down, by J Grover):
Using Javascript to change website language
This encloses each language in a <span> element and then simply hides the one we don't want to see.
My problem is that the labels for the fields on my forms are coming from wtforms objects. I am unsure how to include multiple languages in my current setup. See below for an example of where I am now:
Form
class RoofCheck(FlaskForm):
"""
Class holding the form inputs for a roof check
"""
roofstate = RadioField('Roof Status',
validators=[validators.DataRequired('Please select roof closed or open')],
choices=[('closed', 'Closed'), ('open', 'Open')])
comments = TextAreaField('Comments on roof status',
[validators.optional(), validators.length(max=390)],
render_kw={"placeholder": "Enter comments here",
"rows": 4,
"style": "min-width: 100%"})
submit = SubmitField('Submit')
HTML
<div id='roof_check' class='col-md-6 padding-0'>
<form id="roof_check_form" action={{ url_for('roof_check')}} method="post" name="roof">
<fieldset class='form_group'>
{{ form1.hidden_tag() }}
<legend class='text-center'>
Daily visual check of the roof
</legend>
{% for subfield in form1.roofstate %}
<div class='form-check'>
{{ subfield }}
{{ subfield.label(class_="form-check-label") }} <br/>
</div>
{% endfor %}
<div class='form-check'>
{{ form1.comments }}
</div>
<div class='form-check'>
{% with messages = get_flashed_messages(category_filter=["form1"]) %}
{% if messages %}
{% for message in messages %}
<div> {{ message }} </div>
{% endfor %}
{% endif %}
{% endwith %}
{% for message in form1.roofstate.errors %}
<div> {{ message }} </div>
{% endfor %}
<div style="padding-top: 5px;">
{{ form1.submit(class_="btn btn-primary") }}
</div>
</div>
</fieldset>
</form>
</div>
I am not sure where to begin adding multiple labels to the RoofCheck class form objects. Any advice on how to insert support for two languages here would be great. Thanks in advance.
So it turns out that I can just add html directly to the label and place the language attribute there, then use the javascript solution in the link above to toggle the language. For example:
roof_status_text = ("<span lang='en'>Roof Status</span>"
"<span lang='es'>Estado del Techo</span>")
open_text = ("<span lang='en'>Open</span>"
"<span lang='es'>Abierto</span>")
closed_text = ("<span lang='en'>Closed</span>"
"<span lang='es'>Cerrado</span>")
roofstate = RadioField(roof_status_text,
validators=[validators.DataRequired('Please select roof closed or open')],
choices=[('closed', closed_text),
('open', open_text)])

Django-endless-pagination: apply javascript to whole html after "show more"?

views.py
class PortfolioListView(AjaxListView):
model = Portfolio
context_object_name = "portfolios"
template_name = "portfolios/portfolio_list.html"
page_template = 'portfolios/portfolio_list_page.html'
portfolio_list.html
{% extends "skeleton/base.html" %}
{% load el_pagination_tags %}
{% block content %}
<div class="test-class">
hi-1
</div>
<section>
<div class="container">
<div class="row">
<div class="col-md-offset-1 col-md-10">
{% include page_template %}
</div>
</div>
</div>
</section>
{% endblock %}
{% block custom_js %}
<script src="{% static 'el-pagination/js/el-pagination.js' %}"></script>
<script>$.endlessPaginate({});</script>
<script type="text/javascript">
$(document).ready(function(){
$(".test-class").click(function(){
alert("ji");
});
});
</script>
{% endblock %}
portfolio_list_page.html
<div>
{% lazy_paginate portfolios %}
<div class="test-class">
hi-2
</div>
<div class="test-class">
hi-3
</div>
{% show_more %}
</div>
When I load portfolio_list.html page and click hi-1, it shows alert.
But when I click show more and click hi-2 or hi-3, it doesn't show alert.
I want to show alert even I clicked hi-2 or hi-3.
How can I implement this?
p.s Actually, this is a kinda very simple code for showing clearly what I want to do.
What I eventually want to do is to execute whole javascripts code(e.g _owl_carousel(), _flexslider(), _popover(), _lightbox(), _mixitup(),, etc) after loading portfolio_list_page so that this whole javascript function also can be applied to newly loaded page

Categories

Resources