Simple pagination in FreeMarker with Spark Framework - pagination

I implement a simple blog use Spark Framework with FreeMarker. I need implement pagination in order to show only 5 entries per page, and it is not necessary to show page numbers, with next and previous buttons would be fine. However, I don't even know where to begin in the pagination. This my current code to show all the entries:
<#list entries as art>
<h2>
${art.getTitle()}
</h2>
<p>
Author: ${art.getAuthor().getName()}
</p>
<p><span class="glyphicon glyphicon-time"></span>${art.getDate()}</p>
<hr>
<#assign body=art.getBody()>
<#if body?length < 70>
${body}
<#else>
${body?substring(0,70) + "..."}
</#if>
<br><br>
<a class="btn btn-primary" href="/Entrada/${art_index}">Read More<span class="glyphicon glyphicon-chevron-right"></span></a>
<hr>
</#list>
Also, here is the backend code in Spark Framework:
get("/Home", (request, response) -> {
Map<String, Object> attributes = new HashMap<>();
attributes.put("entries", entrie.getEntries());
return new ModelAndView(attributes, "index.ftl");
}, freeMarkerEngine);
Any help would be appreciated, thanks in advance!

Usually you paginate before putting the list into the model, because then you can avoid loading the entries that you won't show anyway. So simply only pass the list of entries that you will actually show on the current page (as opposed to the whole list), and also pass a pageNumber and totalPages variable (two numbers) that you can use in the template.
BTW, in the template, art.getAuthor().getName() can be written as art.author.name. body?substring(0,70) can be written as body[0 .. 70].

Related

How can I render specific piece of data from my mongodb into my html?

It's my first project. I'm creating a website where administrator have the privilege to change home page texts. So I'm keeping all texts in a collection called "Texts" , each document has a text:value . When home page is rendered I use Texts.find() to return an array containing objects each has a "text" value. I link it to my home page using index.
Like this..
<h2>Texts[0].text</h2>, so if i have 100 texts I go all the way to <h2>Texts[100].text</h2>. and they are different texts and I need to put them in a specific order so I can't just throw them into my html.
I know that's so stupid , so I'm looking for some idea instead of this.
--------------Modification------------------>>>>
I tried using find method for arrays but it also is so tiring , so something simpler would be great , here's a portion of the code
<div class="card bg-dark text-white">
<img src="<%=imgsArr.find(x => x.name === 'main2').src%>" class="card-img" alt="...">
<div class="card-img-overlay ">
<h2 class="card-title"><%=textArr.find(x => x.id === 14).text%></h2>
<div class="triangle-up"></div>
<hr class="ml-0 ">
<div class="triangle-down"></div>
<p class="card-text "><%=textArr.find(x => x.id === 15).text%></p>
<div class="card-topic">
<h2 class="card-title" style=";"><%=textArr.find(x => x.id === 16).text%></h2>
<p class="card-text"><%=textArr.find(x => x.id === 17).text%></p>
</div>
<div class="card-topic">
<h2 class="card-title" style=""><%=textArr.find(x => x.id === 18).text%></h2>
<p class="card-text"><%=textArr.find(x => x.id === 19).text%></p>
</div>
<div class="btnOut ">
<button class="btn btn-lg shadow-lg ">MENU</button>
</div>
</div>
</div>
Good news is that for loops are always a good option. If you are using ejs or a similar rendering engine something like this should work, although you will have to tweak it a bit. Take a look are the EJS rendering engine documentation for an exact format, but it would look something like below and no matter how long the list gets it will render as much as it receives(if it is a lot you might want to consider using pagination)
<% for text in Texts.text %>
<% if text==="some value"%>
<h2>text</h2>
<% else %>
<p> text </p>
If your front-end is perhaps react.js or vue.js or similar the same prnciple would work but the format will be different.
No offense friend but you need to get some tutorials. But let me help you as best i can. Everything in a web application is somewhat defined. Meaning it falls into one predetermined category or another. When you get json for example you get something base on how that particular data is defined in the database. Hence you can get json data from your backend that looks
{ 'title':'sneaker', 'price':'200', 'quantity':'50' }
Now assuming it is a list of json objects what you can do is loop through this and assign them to tags based on their object key(because it gets converted to a javscript object). so again you code would look something like
<% for text in Texts.text %>
<h2>text.title</h2>
<div>
<p>text.price</p>
<p>text.quantity</p>
</div>
This would be how you would render data from your database(the format might not exactly be spot on). Dealing with forms is a whole other ball game. So get a book or some tutorial videos that discuss it. You will better understand how to handle it.
For your code you are being very rigid, at first glance there is already a pattern, work with that pattern, you code just needs a simple for loop from what i gather.
for(let i=0; let i>100; i++){
if (i%2===0){
console.log(<h2> i </h2>)
}else{
console.log(<p> i </p>
}
}
The reason i have resulted to pure javascript is so you can see what the inner workings of your render should look like. You can get the total number of ids in your database(that is what the integer 100 represents in this case), loop through one by one and produce what you want. It is still javascript, do not let the html throw you off

geb cant find checkbox element

there is this piece of code that provides a checkbox following from a link to the T&C.
<div class="checkbox accept_agreement">
<label class="control-label" for="step_data_accept_agreement">
<input type="hidden" name="step_data[accept_agreement]" value="0">
<input type="checkbox" name="step_data[accept_agreement]" id="step_data_accept_agreement" value="1">
<label for="step_data_accept_agreement">
<a target="_blank" href="/lanevillkor/">
<font><font>I agree, have read and stored the terms and conditions</font></font>
</a>
</label>
</label>
</div>
Now, I am working on a spock test using geb, and I try to retrieve the checkbox element
<input type="checkbox" name="step_data[accept_agreement]" id="step_data_accept_agreement" value="1">
to do so i have tried many things without the expected output. i was expected that something like
$("#step_data_accept_agreement").click() would be pretty straight forward but it is not. in the other side if I put $("[for='step_data_accept_agreement'] label").click() it clicks the link.
I tried to become as more specific but nothing looks to return the element correctly.
one of my last attempts was
termsAndConditionsOption(wait: true) { $("#step_data_accept_agreement", name: "step_data[accept_agreement]") }
and the error message, as in the other cases too, was in one sentence
element not visible
What do I miss?
So the solution was to use js to click the checkbox. The simpliest way is:
def agreeOnTermsAndConditionsAccept() {
String mouseClickEvt = """
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
arguments[0].dispatchEvent(evt);
"""
browser.js.exec(termsAndConditionsOption.firstElement(), mouseClickEvt)
}
Geb provides js support to work with javascript, as we find in the documentation. Also another link shows how to simulate a click event with pure javascript.
This was required as the checkbox cant be found as it is hidden. With javascript we can 'see' the position of the element and perform an action in the location that we want. iniMouseEvent can be used as well as it is documentanted here

If element hasClass, add another class to its title value

I'm using slick carousel, and once a div is active I want to open the corresponding description.
Problem I'm having is with this code:
if ($('div').hasClass('active')) {
var title = $(this).attr('title');
$('ul li').removeClass('open');
$(title).addClass('open');
}
What I'm trying to achieve:
Once a div gets class 'active', I want to take its title value, and use it as a id link to list element I want to display(add class to).
Here is a FIDDLE.
Use event handling, not class monitoring.
The slick carousel API has events for this, I believe you want to use the afterChange event to act on the active element after it has been made visible.
Check out the docs and examples, especially the section titled "Events" on Slick page: http://kenwheeler.github.io/slick/
And I think you don't want to use title attribute for this because that is for tooltips. I recommend data-* attributes instead. And element IDs should generally start with a letter and not a number (was required in HTML4 and makes life easier when mapping IDs to JavaScript variables; though if you are using HTML5 I think this requirement is no longer in effect).
HTML
<div id="carousel">
<div data-content-id="content1">
Selector 1 </div>
<div data-content-id="content2">
Selector 2 </div>
<div data-content-id="content3">
Selector 3 </div>
</div>
<ul class="content">
<li id="content1">Content 1</li>
<li id="content2">Content 2</li>
<li id="content3">Content 3</li>
</ul>
JavaScript
$('#carousel').on('afterChange', function(event, slick, currentSlide) {
// get the associated content id
var contentId = $(slick.$slides.get(currentSlide)).data("content-id");
if(contentId && contentId.length)
{
var $content = $("#" + contentId);
$(".content>li").removeClass("open"); // hide other content
$content.addClass("open"); // show target content, or whatever...
}
});
I have found a solution:
$('.slider').on('afterChange', function(event, slick, currentSlide, nextSlide){
var contentId= $(slick.$slides.get(currentSlide)).data('content');
if(contentId)
{
$(".content li").removeClass('open');
$('#' + contentId).addClass('open');
}
});
Working fiddle

additional text fields in html form after a numeric entry in another text field

Am using an html form to send data to a sql database using php.
My trouble is that I have a dynamic value for number of items which changes for each order and am trying to avoid having to add an x number of extra text fields for all orders.
A better solution would be to enter a value in a text field which then makes the same number of additional text fields appear in the form.
Is there anyway to accomplish this?
Thanks
OK. So you want to show a number of input fields at the user's request, before pressing the submit button. My first approach would be to do it in javascript.
Let's assume this form:
<form>
<p><input name="myInput1" /></p>
<button type="submit">submit</button>
</form>
You could include an extra button to add a new row:
<form>
<p><input name="myInput1" /></p>
<button type="button" onclick="addInput(this.form)">add input</button>
<button type="submit">submit</button>
</form>
... and the handler function would be something like this:
<script type="text/javascript">
function addInput(form)
{
// Create a new <p><input> node at the end of the form, throughput the DOM API:
// Get the last <p> element of the form
var paragraphs=form.getElementsByTagName("P")
var lastParagraph=paragraphs[paragraphs.length-1]
// Create a new <p> element with a <input> child:
var newParagraph=document.createElement("P")
var newInput=document.createElement("INPUT")
// Name the <input> with a numeric suffix not to produce duplicates:
newInput.name="myInput"+(1+paragraphs.length)
newParagraph.appendChild(newInput)
// Add the created <p> after the last existing <p> of the form:
form.insertBefore(newParagraph, lastParagraph.nextSibling)
}
</script>
(Notice that all the rendering logic is performed in the client side (in HTML + javascript), and when the form is finally submitted, the server will just receive a collection of pairs name + value.)

Grails search mechanism

I have the folowing gsp page:
<g:form controller="??" action="??">
<h1>Search</h1>
<g:submitButton name="search" value="Search"/>
<div id="resultsHere">
</div>
</g:form>
What i want to do is, everytime "Search is clicked", the database is searched for that record, lets imagine im looking for book titles. So everytime i write a title, the database finds the books and print every data related to the books. How can i do that=?
My idea is having something similar to this in the div:
<ul>
<g:each in="${bookList}">
<li>Name: ${it.name}, Locale: ${it.isbn}</li>
</g:each>
</ul>
So the point is, when the search button is clicked, the controller that handle that action should redirect the page to the same page, and pass the filtered list of books so it can be printed in the <g:each in="${bookList}"> tag.
I would like opinions about this being the best solution in this case. I could also render the results in the page directly, but i would like to do some css for the lookings so i think that wont be a good idea using render. Any help would be apreciated, and if possible, some lights with the code (specially the filtering part).
I would have one action in your controller, and render out the list.
ie: as pseudo-code (and not complete)
BookController {
def search = {SearchComamnd search ->
def books = []
if(search) {
books = Book.createCritera().list {
and {
title(search.title)
author(search.title)
}
}
}
render [ books:books ]
}
class SearchCommand {
def author
def title
}
}
and then when in your view
<g:form controller="??" action="??">
<h1>Search</h1>
<g:submitButton name="search" value="Search"/>
</g:form>
<g:each in="${books}">
<li class="book">Name: ${it.name}, Locale: ${it.isbn}</li>
</g:each>
you can now use css li.book to decorate the entry.

Resources