Ghost Custom Pagination - html

I just design a theme for ghost blogging platform, by reading the ghost theme documents. all I need now is customizing the pagination. the document says create a pagination.hbs inside the partial folder. but the problem is I don't know how should the markup be.

There's a brief post here that explains where to find the relevant bit of code for your pagination.hbs file. You'll actually be able to use the default pagination code as your template.
As that post notes, you need to copy the default pagination code from core/server/helpers/tpl/pagination.hbs in the Ghost source code and use it to create your own pagination.hbs file in the partials directory of your theme.
You'll see the markup that you need to edit there, i.e.:
<nav class="pagination" role="pagination">
{{#if prev}}
<a class="newer-posts" href="{{pageUrl prev}}">←</a>
{{/if}}
<span class="page-number">Page {{page}} of {{pages}}</span>
{{#if next}}
<a class="older-posts" href="{{pageUrl next}}">→</a>
{{/if}}
</nav>
You'll need to restart Ghost after saving your edits to see the changes.

I have created some JavaScript code that extends the default Ghost pagination. Instead of showing "Page 1 of X", it shows a row of page numbers with previous, next, first, and last buttons. It also has an ellipsis in the center for sites with a lot of pages. It is fully customizable from the Code Injection settings page.
My implementation creates a bootstrap pagination component, but I'm pretty sure you could output whatever you wanted given the classes and elements that are created (<nav> and <ul> elements).
Here is some code that I include before the {{ghost_foot}}. That way, I can override some of the settings in the Footer section of the Code Injection:
var prev;
var pages;
var page;
var next;
var pageUrlPrev;
var pageUrlNext;
var numbersSurroundingEllipses = 3;
var useSimplePagination = false;
Here is the pagination.hbs for the customized pagination that I am using on my site:
<script type="text/javascript">
// set the values that we'll use in the bootstrap-pagination.js file
{{!if there is no value for the variable, display a 0}}
prev = {{#if prev}}{{prev}}{{else}}0{{/if}};
pages = {{#if pages}}{{pages}}{{else}}0{{/if}};
page = {{#if page}}{{page}}{{else}}0{{/if}};
next = {{#if next}}{{next}}{{else}}0{{/if}};
pageUrlPrev = '{{pageUrl prev}}';
pageUrlNext = '{{pageUrl next}}';
pageUrlFirst = '{{pageUrl 1}}';
pageUrlLast = '{{pageUrl pages}}';
</script>
<nav>
<ul class="pagination bootstrap-pagination">
</ul>
</nav>
Here is the javascript code that will add the pagination to the above HTML.
Note: since these links are created on the client, they will not be available to search engines during indexing. However, it is my understanding that the search engines utilize the link rel="prev" and link rel="next" tags that Ghost outputs for each of the index pages.
Here is what they look like for my website:
<link rel="prev" href="https://cerkit.com/page/2/" />
<link rel="next" href="https://cerkit.com/page/4/" />
That leads me to believe that search engines can navigate between pages and access all links. However, I have not confirmed this with anyone who would know for sure, so do some research if you think this might be an issue.
I also made sure that I submitted my Ghost sitemap link to the search engines just to make sure.
This gives you another option when working with pagination.
Here is the full write-up on my blog that gives a few more details.
I have all of this (and a few other Ghost tricks like binding Font Awesome icons to navbar links) on my website: cerkit.com.

Related

How do you make a single header and footer on separate HTML pages that then are displayed on each subsequent page?

At a beginner level I am trying to make a frontend page that has a header and a footer on all pages. Each page can have an identical header and footer. In the header, I'd like to add a Bootstrap navbar (or similar) and in the footer, something similar. But rather than just copying that header and footer to each page I'd like to just make that a separate thing and insert it into each page when it loads. This way if I update the header or footer it updates on all pages.
In the past, I have done this with Python, but I am only using frontend for this project and I am only going to publish on GitHub (it's mostly for my own purposes).
I am using Visual Studio Code as my editor if this makes it any easier.
I will have CSS and JS folders too (if this makes any difference).
**Update Edit:
I have tried to do this, but I am missing something here.
This is what I attempted (after a quick Google search now I know what I am after):
<!--JQuery CDN-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<!--Include Content-->
<script>
$(function () {
var includes = $('[data-include]')
$.each(includes, function () {
var file = 'views/' + $(this).data('include') + '.html'
$(this).load(file)
})
})
</script>
</head>
<body>
<header>
<div data-include="header"></div>
</header>
It has been a while since I have done this, so I am rusty, but this doesn't seem to be working for some strange reason.
There are several ways to follow it, at a beginner level you can have a scheme where the content is dynamic, that is, the Header and Footer sections are filled with a variable or code insertion, at an advanced level there are template engines, if you want to start, with php is configured very easily
I used the W3 method: https://www.w3schools.com/HOWTO/howto_html_include.asp
So far it is not working with both header and footer, only header is working. I am unsure why. Will be the next problem solve.

Trying to switch between local and public webpage while looping through data

At the moment, I am trying to list projects on a website in a grid. Some of them link to another page on the site and others link to another domain page. At the moment I am using React-Router's 'Link' to go from one page to another, however this doesn't work when going to a page outside of the domain. In the JSON file, I check for the 'url' variable which returns either the URL if its public or 'project-page' if it is local. I can't figure out how to differentiate between the two in JSX; is there a work around while still utilizing the JSON file?
<div className="projects">
{projectData.map((projectDetail, index) => {
return(
<div className='project-card'>
<Link to={projectDetail.url}>
<img src={require('./images/icons/' + projectDetail.alt + '.jpg')} alt={projectDetail.title}/>
<h3>{projectDetail.title}</h3>
<p>{projectDetail.subtext}</p>
</Link>
</div>
)
})}
</div>
Well, to differentiate you can check the content of the projectDetail.url you are retrieving from that JSON in your javascript file, if that matches your domain (your website - having a project-page as you mention) or is it an external domain. You can also set a flag value in your json file. For each project set a value (e.g externalUrl: 1 or 0) and then check if projectDetail.externalUrl is 1 (it contains an external link). Then, maybe try the following for external domains:
<Link to={{ pathname: "external URL" }} target="_blank" />
In your case:
<Link to={{ pathname: projectDetail.url }} target="_blank" />
See this answer for detailed information: React-Router External link
Edit 1
If Link does not work for external websites, this would probably be related to the version of react-router you are using. Actually, to navigate to external websites you can as well use anchort tags <a> to redirect. Check what URL your project has and then conditional render a <Link> or <a>.
<a href="www.example.com" target=_blank></a>

Highlighting "current" navigation link when using template navigation menu

I'm inexperienced at coding and trying to build a pretty simple site with some HTML and CSS in Dreamweaver. I'd like my navigation menu to highlight the current page a viewer is looking at, and I've found different ways to do this. However, to make life easier as the site evolves, I've made the navigation menu an uneditable region of a template. I'm therefore finding myself unable to make the coding changes (e.g., giving a unique class to each link or a unique body id to each page) to each page that would seemingly allow me to highlight the current page link. Thanks!
A simple way to do this is with Dreamweaver template attributes which allow you to have editable tag attributes:
https://helpx.adobe.com/dreamweaver/using/defining-editable-tag-attributes-templates.html
While editing your template, if you put your cursor on the nav item class, you could then go to Modify > Templates > Make Attribute Editable.
Then, when editing the page based on the template, you'll be able to add an active class.
You could use jQuery for this to detect a word in url:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
$(document).ready(function($) {
if(window.location.href.indexOf("contact") >= 0){
$(".contactLink").addClass("active");
}
});
</script>
<style>
.active { color: black; font-weight: bold }
</style>
contact
This could add a class to the menu item that has the word "contactLink" as a class. So long as you have this js on all pages (put it in a file rather than hard coded on all pages) it will work. If you copy the above code into a page called test.html the link is normal. change the name to contact.html and it goes black..
Give each menu item a class, and then duplicate the code above for however many items you have.
There are more dynamic ways of doing it, but if you don't have millions of pages, is a nice easy way.

In Pelican, how to create a page dedicated to hosting all the blog articles?

In pelican, by default, blog articles are listed on the index.html file.
What I want instead is that I use a static page as my home page and put all the blog articles on a dedicated "Blog" page.
How can I get this done?
While there are several possible methods for achieving your desired goals, I would start with the following changes to your settings file:
SITEURL = '/blog'
OUTPUT_PATH = 'output/blog'
PAGE_URL = '../{slug}.html'
PAGE_SAVE_AS = '../{slug}.html'
DISPLAY_PAGES_ON_MENU = False
DISPLAY_CATEGORIES_ON_MENU = False
MENUITEMS = [('Home', '/'), ('Blog', '/blog/')]
Put your blog posts in content/ as usual, and then create your home page with the following headers and save as content/pages/home.md:
Title: Home
URL: ../
Save_as: ../index.html
This is the home page.
Caveats:
Dynamic navigation menu generation has been effectively turned off since it doesn't work well with this configuration. Highlighting for the currently-active menu item — a feature you normally get out-of-the-box — will not be present in this configuration and, if desired, must be implemented separately in your theme.
If your theme's base.html template has a link to your site home that depends on SITEURL (e.g., as the notmyidea theme does), you will need to change the link to point to <a href="/"> instead.
Set the following in the pelicanconf
DIRECT_TEMPLATES = ['blog']
PAGINATED_DIRECT_TEMPLATES = ['blog']
1st line will set blog.html for the articles
2nd line will allow pagination of blog.html file
For the index page, create a pages folder in the content directory and create the .md file there and set save_as:index.html this will save the md file as index.html
This is covered in the Pelican FAQ
- "How can I override the generated URL of a specific page or article?"
Basically, in your contents folder, create two subfolders:
/contents/blogs, which will store all your blog entries
/content/pages, which will store your other static pages (including your home page)
In the pages subfolder, create a file (e.g. home.rst) with the option :save_as: index.html, which will make this file your home page. E.g.:
Home
####
:date: 2015-05-22 12:30
:url:
:save_as: index.html
This is my home page
In your pelicanconf.py file, specify the following options:
DISPLAY_PAGES_ON_MENU = False
DISPLAY_CATEGORIES_ON_MENU = True
USE_FOLDER_AS_CATEGORY = True
PATH = 'content'
ARTICLE_PATHS = ['articles',]
PAGE_PATHS = ['pages',]
MENUITEMS = ()
You should now have a home page and a contents bar with a Blogs menu.
If you want to add more menus to the contents bar (for example an About or CV menu), create the corresponding files in your pages folder, and add them to MENUITEMS:
MENUITEMS = (
('About', '/pages/about.html'),
('CV', '/pages/cv.html'),
)
I have an answer similar to the one Justin Mayer gave, except in mine I change blog article urls instead of page urls.
I've been getting the following error when trying to use the answer above, so it might be useful to other people having the same issue
ERROR: Skipping volunteering.rst: file '../volunteering.html' would be written outside output path
ERROR: Skipping presentations.rst: file '../presentations.html' would be written outside output path
Make all article urls to be under 'blog/' url
ARTICLE_URL = "blog/{date:%Y}-{date:%m}-{date:%d}-{slug}.html"
ARTICLE_SAVE_AS = "blog/{date:%Y}-{date:%m}-{date:%d}-{slug}.html"
Put blog index under 'blog/' url
INDEX_SAVE_AS = "blog/index.html"
Add a explicit menu item for blog index
MENUITEMS = [
('home', '/'),
('blog', '/blog'),
]
As your page is now an index page, automatically displaying link to that page in the menu will lead to a broken link, so you will have to set the following option and specify the following flag
DISPLAY_PAGES_ON_MENU = False
For the new index page, add a directive save_as, like Justin Mayer pointed it out. Here how it looks in rst
About
=====
:slug: about
:category: About
:save_as: index.html
This should give you a home page and an index page for articles.
When you want to add more static pages, you will also need to add them in menu items that still contains '/pages' prefix in the url if you want links to the pages appear in a menu. i.e for the volunteering.rst with the following content,
Volunteering
============
:slug: about
:category: About
Your MENUITEMS variable will look like the following
MENUITEMS = [
('home', '/'),
('blog', '/blog'),
('volunteering', '/pages/volunteering'),
]
I tested this answer on pelican 4.2.0.
You can use the following settings to put the index file for example at /blog/index.html.
INDEX_SAVE_AS = 'blog/index.html'
INDEX_URL = 'blog/'
Then you created a home.md page and use "save_as: index.html" directive for the actual home page.

Dynamically load stylesheets

i know that you can have style-sheets in the head of a page, but i like to have them in a separate file. Now i'm working with a single page application.
Well in an SPA the content is dynamic, right? so i didn't want to import all the style-sheets in the head section with the link tag. Can i somehow import style-sheets as-and-when i need them?
I mean, can i have a link in the body, such that whenever my SPA loads some dynamic content, a style sheet also gets loaded? Such that i dont have to load all the stylesheets even when the dynamic content is not loaded..
I stress again: Whenever the content loads, the styles load.
I know i can do it with the help of an inline style like this:
~PSEUDO CODE
<tagname style="somestyle"></tagname>
but can i have some dynamic file imports too? Can i have the link tag in the body too? Even if it works, is it standard?
You should look into asychronously loading assets, such as the famous google-analytics code. You can load external stylesheets using Javascript.
JavaScript
(function(){
var styles = document.createElement('link');
styles.rel = 'stylesheet';
styles.type = 'text/css';
styles.media = 'screen';
styles.href = 'path/to/css/file';
document.getElementsByTagName('head')[0].appendChild(styles);
})();
Lines 1 and 7 create a new scope for variables such that local variables do not collide or override with globally scoped variables. It isn't necessary just a best practice. This solution also assumes you have a <head> tag in your html.
You can add/remove/edit link tags in your head area with java script to add/remove stylesheet files.
Code example:
Add a stylesheet to the head:
var newstyle = document.createElement("link"); // Create a new link Tag
// Set some attributes:
newstyle.setAttribute("rel", "stylesheet");
newstyle.setAttribute("type", "text/css");
newstyle.setAttribute("href", "filename.css"); // Your .css File
document.getElementsByTagName("head")[0].appendChild(newstyle);
To remove or edit a stylesheet you can give every stylesheet an id attribute and access it with this:
document.getElementById('styleid')
Or you can loop through all link tags in the head area and find the correct one but I suggest the solution with the ID ;)
Now you can change the href attribute:
document.getElementById('styleid').setAttribute("href", "newfilename.css");
Or you can remove the complete tag:
var styletorem = document.getElementById('styleid');
styletorem.parentNode.removeChild(styletorem)
I just tried to give dynamic styling to my webpage. I used a button. On click of it, the CSS will get imported using a method in Javascript.
In my html, I have:
<button type="button" onclick="changeStyle()"> CLICK TO SEE THE MAGIC!! </button>
Then in Javascript, I have a method named changeStyle():
function changeStyle()
{
var styles = document.createElement('link');
styles.type="text/css";
styles.rel="stylesheet";
styles.href="./css/style.css";
document.head.appendChild(styles);
}
It worked perfectly.