waypoints infinity scroll loads all pages at once - jquery-waypoints

I'm using Waypoint infinity scroll in my Django template.
<div class="infinite-container">
{% for item in arbitrase_records %}
<div class="col-lg-3 arbitrase-item">
<!-- item content -->
</div>
{% endfor %}
</div>
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}">More</a>
{% endif %}
and the javascript goes like
<script src="{% static 'theme/js/waypoints/lib/jquery.waypoints.min.js' %}"></script>
<script src="{% static 'theme/js/waypoints/lib/shortcuts/infinite.min.js' %}"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
items: '.col-lg-3.arbitrase-item',
onBeforePageLoad: function () {
$('.infinite-loading').show();
},
onAfterPageLoad: function ($items) {
$('.infinite-loading').hide();
},
offset: -30
});
</script>
for the first time, I scroll the page a little down, it loads all pages at once.
I have been trying different parameters to use with offset. setting offset to less than 30 like -20 or -10 stops the plugin to load any page.
How can I make it load only next page and wait for further scroll?
I also tried setting 'bottom-in-view' in offset (although, it is default). But then it loads all pages even without scrolling the page.

Related

Flask, WTForms - send the whole form using ajax

I am wondering how to send the whole wtform using ajax request (this one does not work):
function addReport(e){
e.preventDefault();
var serializeData = $('form').serialize();
$.ajax({
type:'GET',
url:'/reports_list',
data: serializeData,
success:function(result){
},
async: false
});
}
I have one main form, which includes another:
Reports = FieldList(FormField(ReportsForm))
The idea is to render the form under form, in case user wants to add another one. In short, it should just copy this underform and clone it, then renders to the main one.
How can I pass the entire form in ajax request?
It seems to me that you are trying to nest form elements. So you only send the innermost form. The validation errors are also not displayed when the form is sent via AJAX.
I think you can follow your approach more easily if you add the necessary form fields by cloning with JavaScript without submit.
The following example breaks the nested forms into fieldsets.
If a fieldset is to be added, the previous one is cloned and the necessary attributes are adapted to the requirements.
When removing, the last one is removed.
from flask import (
Flask,
render_template,
request
)
from flask_wtf import FlaskForm
from wtforms import FieldList, FormField, StringField, SelectField
from wtforms.validators import DataRequired
app = Flask(__name__)
app.secret_key = 'your secret here'
class ReportForm(FlaskForm):
class Meta:
csrf = False
title = StringField('Name', [DataRequired()])
lang = SelectField('Language', choices=[('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')])
class ReportsForm(FlaskForm):
reports = FieldList(FormField(ReportForm), min_entries=1)
#app.route('/reports', methods=['GET', 'POST'])
def reports():
form = ReportsForm(request.form)
if form.validate_on_submit():
for report in form.reports.data:
print(report)
return render_template('reports.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reports</title>
</head>
<body>
<form name="my-form" method="post">
{{ form.csrf_token }}
{% for subform in form.reports -%}
<fieldset name="subform">
{% for field in subform -%}
<div>
{{ field.label() }}
{{ field() }}
{% if field.errors -%}
<ul class="errors">
{% for error in field.errors -%}
<li>{{ error }}</li>
{% endfor -%}
</ul>
{% endif -%}
</div>
{% endfor -%}
</fieldset>
{% endfor -%}
<button id="btn-less" type="button">Less</button>
<button id="btn-more" type="button">More</button>
<button type="submit">Submit</button>
</form>
<script type="text/javascript">
(function() {
const btnMore = document.querySelector('#btn-more');
btnMore.addEventListener('click', function() {
// Clone the previous fieldset element.
const subform = document.querySelector('fieldset[name="subform"]:last-of-type');
const newform = subform.cloneNode(true);
// Remove possible validation error messages.
const errors = newform.querySelector('.errors');
errors && errors.remove();
// Update the necessary attributes.
const fields = newform.querySelectorAll('input, select');
fields.forEach(field => {
const attrName = field.name;
field.name = field.id = attrName.replace(/^(.*)-([0-9]+)-(\w+)$/g, (...args) => {
return [args[1], Number(args[2]) + 1, args[3]].join('-');
});
field.value = '';
const labels = newForm.querySelectorAll(`label[for="${attrName}"]`);
labels.forEach(label => label.setAttribute('for', field.id));
});
// Add the new fieldset.
subform.after(newform);
});
const btnLess = document.querySelector('#btn-less');
btnLess.addEventListener('click', function() {
const subforms = document.querySelectorAll('fieldset[name="subform"]');
if (subforms.length > 1) {
// Remove the last of the fieldset elements.
subforms[subforms.length - 1].remove();
}
});
})();
</script>
</body>
</html>

Explanation about data-apos-ajax-append outside pieces-pages

I want to implement the apostrophes Ajax features in my project but sadly I don't understand the Ajax functions not completely. I have been studying the documentation for the last week now but i don't find enough information about that topic. I want kindly ask if it's possible to use data-apos-ajax-append outside of apostrophe-pieces-pages
I created a widget like that:
lib/modules/infinite-widgets/index.js
module.exports = {
extend: 'apostrophe-widgets',
label: 'Infinite Widget',
addFields: [
{
name: 'posts',
label: 'Posts',
type: 'array',
titleField: 'name',
schema: [
{
name: 'name',
type: 'string',
label: 'Name'
},
{
name: '_image',
type: 'joinByOne',
withType: 'apostrophe-image',
label: 'Image',
required: true,
filters: {
projection: {
attachment: 1,
description: 1,
title: 1
}
}
}
]
}
]
};
lib/modules/infinite-widgets/views/widget.html
<div class="row margin">
<div class="col s12 m12">
<div class="radius
{% if data.widget.shadowOn == true %}
z-depth-1
{% endif %}
">
<div data-apos-ajax-context="infinite">
{% include "indexAjax.html" %}
</div>
</div>
</div>
</div>
lib/modules/infinite-widgets/views/indexAjax.html
<div data-apos-ajax-append>
{% for name in data.widget.posts %}
{% set image = apos.images.first(name._image) %}
<div class="card z-depth-0" style="
{%- if piece.backColor-%}
background-color:{{ piece.backColor }}
{% endif %}
">
<div class="card-image">
<img src="{{ apos.attachments.url(image, { size: 'one-sixth' }) }}" />
</div>
<div class="card-content">
{{ name.name }}
</div>
</div>
{% endfor %}
</div>
That is working pretty nice but unfortuantly It displays all posts created simultansiosly and I wasen't able to use the "Load More..." button with AJAX here
{# Load More button. Also outside data-apos-ajax-append, so it gets refreshed #}
{% if data.currentPage < data.totalPages %}
{# "Load More" button with the "append=1" flag #}
Load More...
{% endif %}
So can I modify this query, to have a load more button, or even better data-apos-ajax-infinite-scroll for content of an array created in an widget instead of an piece?
No, it is not possible to do that using data-apos-ajax-append. That feature is specifically for apostrophe-pieces-pages and there is no back end implementation waiting to talk to it for widgets, for instance.
You should instead look at writing a browser-side widget player for your widget, which gives you a place to make your own API calls back to the server. You can see that technique in the source of the apostrophe-twitter-widgets module.

Making Logo as Welcome Header in Neat Theme in Bigcartel

I am currently working on customizing the welcome page for my Bigcartel site.
I am using the Neat theme and would like to add my logo as the welcome header that appears over the slideshow, instead of just having the standard text.
The problem I am having is when I enter the code for the image, it either erases the slideshow or gives me the image with the header text still appearing.
To replace the Home page welcome text with your uploaded header image, head to Customize Design > Advanced > Home then find the following code:
{% if theme.welcome_header != blank or theme.welcome_subheader != blank %}
<div class="featured_holder">
<div class="featured">
{% if theme.welcome_subheader != blank %}<p>{{ theme.welcome_subheader }}</p>{% endif %}
{% if theme.welcome_header != blank %}<h2>{{ theme.welcome_header }}</h2>{% endif %}
Shop Now
</div>
</div>
{% endif %}
Remove that block, and replace it with the following:
<div class="featured_holder">
<div class="featured">
<img src="{{ theme.logo.url | constrain: '400' }}" alt="{{ store.name }}">
</div>
</div>

Why won't datepicker work in a twig in userfrosting?

Bit of a beginner here and this issue has been causing me a headache for over a day. I'm using userfrosting as a framework, with the usual twig files for the web pages.
I'm trying to include a datepicker (bootstrap-datepicker.js hasn't worked, neither is the current iteration using jquery-ui) in a form in a twig - but no matter what I do, I can't get it to work!
Here's the basic setup:
{% block head %}
{{ parent() }}
<script src="{{site.uri.js}}/jquery-1.11.2.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="{{site.uri.js}}/custom.js" ></script>
{% endblock %}
{% block content %}
.... {{boring stuff missed out}}
<form class="form-inline" role="form">
.... {{boring stuff missed out}}
<div class="form-group row">
<label for="datepicker" class="col-sm-3 form-control-label">Subject Date:</label>
<div class="col-sm-6">
<input type="date" class="form-control" id="datepicker" />
</div>
</div>
.... {{boring stuff missed out}}
</form>
.... {{boring stuff missed out}}
{% endblock %}
{% block javascripts %}
<script type="text/javascript">
$(document).ready(function() {
$("#datepicker").datepicker();
});
</script>
{% endblock %}
The box is on the page, you can type a date into it etc, but nothing appears when you click on it (there should be a calendar appearing.)
Anyone have any ideas? I'm at a total loss. I've tried various versions, locally and (as you can see, currently) on a CDN, but nothing works. I'm sure it's probably something basic as I'm not an experienced web dev or anything, but any advice or working examples would be gratefully received!
Uh! facepalm
Well, after some digging and serious consideration of the inspector output (thanks CTRL-SHIFT-I!) it turns out to be a simple case of script loading order and multiple scripts being loaded.
I didn't realise twig loads a whole bucketload of scripts on top of what I ask it to load in the template I was creating. Only after seeing the inspector output for the page did I see that I was trying to load two different versions of jQuery and my own custom script was being loaded out of order - I was loading them here:
{% block head %}
{{ parent() }}
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<script src="{{site.uri.js}}/custom.js" ></script>
{% endblock %}
that block should be reserved for stylesheets. Instead, I should be loading them here:
{% block page_scripts %}
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<script src="{{site.uri.js}}/custom.js"></script>
{% endblock %}
... so that they are loaded AFTER all the default Bootstrap and userfrosting scripts.
https://jqueryui.com/datepicker/ uses type="text" for the input field. When I google the matter it seems that type="date" has at least previously caused problems.
In short: I would try changing type="date" to type="text".

Nunjucks, blocks defined within "include" partial file ignored by extend

Here is my use case
I have a file that pulls pieces together (holy-grail.njs) that then is extended by the actual page I want (single.njs). Problem is that the blocks defined in included files are ignored by the actual page template. You can see the extended sidebar text is not appearing in screenshot <p>Here is some additional content for the sidebar extended in</p>
Just for grins I moved that block code from sidebar.njs to holy-grail.njs and yes it is extended by single.njs so it is indeed as I suspected.
Is the a bug?, a non-feature? How about a work around? Or will Jade do what I want? I assumed that "included" files were just included as in before further processing but maybe they are processed then included? Without being able to do this my whole groovy way of organizing my template pieces/partials and then extending/customizing the content will be a no go.
this same question was asked three years ago and no one answered
Blocks in included files not being filled by extended templates
single.njs
{% extends "layouts/holy-grail.njs" %}
{% block sidebar %}
<p>Here is some additional content for the sidebar extended in</p>
{% endblock %}
{% block article %}
{% raw %}
{{ Hugo code here to grab the article title and content }}
{% endraw %}
{% endblock %}
holy-grail.njs
{% set reg = "regions/" %}
{% set cmp = "components/" %}
{% include "regions/head.njs" %}
<body class='page'>
{% include reg + "header.njs" %}
<div class="rollover-wrapper">
{% include reg + "topbar.njs" %}
<main>
{% include reg + "sidebar.njs" %}
<section id="content">
{% block article %}
{# This is where one melds in article content #}
{% endblock %}
</section>
</main>
{% include reg + "footer.njs" %}
</div>
{% include cmp + "javascripts.njs" %}
</body>
sidebar.njs
<aside id="sidebar" class="sidebar">
<p> some sidebar content set in the sidebar.njs file </p>
{% block sidebar %}
{# This is where one melds in more sidebar content #}
{% endblock %}
</aside>
This from one of the maintainers of Nunjucks
Your guess is correct: includes operate at a "higher level" than
template inheritance. So an included template can have blocks, and can
have its own "extends" tag, and a totally separate template
inheritance hierarchy, but its blocks don't in any way interact with
the blocks of the including template's inheritance hierarchy.
So the solution I came up with is to use another tool (gulp plugin) to pre-assemble the partials then run them through nunjucks like this.
N.B my preprocessor file uses extension *.pnjs and outputs to a corresponding *.njs file which then is processed/extended in the single.njs.
var merge = require('gulp-file-include')
var rename = require("gulp-rename");
gulp.task('html:pre', function() {
gulp.src(['assets/html/nunjucks/layouts/*.pnjs'])
.pipe(merge({
prefix: '##',
basepath: 'assets/html/nunjucks'
}))
.pipe(rename({extname: ".njs"}))
.pipe(gulp.dest('assets/html/nunjucks/layouts/'));
});
var nunjucks = require('gulp-nunjucks-render');
gulp.task('html:njs',['html:pre'], function() {
gulp.src('assets/html/nunjucks/*.njs')
.pipe(nunjucks({ path: ['assets/html/nunjucks'] // String or Array
}))
.on('error', console.log)
.pipe(gulp.dest('./builds/dev/'));
});
and then you'd have to change your include syntax to that supported by gulp-file-include
like this.
##include('regions/head.njs')
<body class='page'>
##include('regions/header.njs')
<div class="rollover-wrapper">
##include('regions/topbar.njs')
<main>
##include('regions/sidebar.njs')
<section id="content">
{% block article %}
{# This is where one melds in article content #}
{% endblock %}
</section>
</main>
##include('regions/footer.njs')
</div>
##include('components/javascripts.njs')
</body>

Resources