Skip to content

Commit

Permalink
Remaining functionality for the various pages
Browse files Browse the repository at this point in the history
  • Loading branch information
trodrigues committed Apr 11, 2016
1 parent a8a8190 commit b6d2f83
Show file tree
Hide file tree
Showing 9 changed files with 1,207 additions and 34 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
# JavaScript Product Catalogue

This repository shows how to build a Product Catalogue with JavaScript on a website, based on the Contentful starter Product Catalogue example space.
This repository shows how to build a frontend JavaScript based application with Contentful for a Product Catalogue, based on the Contentful starter Product Catalogue example space.

This project uses no specific frameworks and is written in plain JavaScript, making use of browser APIs and HTML/CSS.

The application is split over multiple files which are included via script tags in the `index.html` file. While this approach is taken here for simplicity, **this is not advised for production deployments**. Make sure you always bundle up and minify your JavaScript code.

The only external dependencies are the [Contentful SDK](https://github.com/contentful/contentful.js) and the [marked](https://github.com/chjj/marked) Markdown library for rendering markdown content.
The only external dependencies are:
* the [Contentful SDK](https://github.com/contentful/contentful.js)
* the [marked](https://github.com/chjj/marked) Markdown library for rendering markdown content
* the [es6-promise](https://github.com/stefanpenner/es6-promise) polyfill for Promises in the browser

Feel free to look at the code and understand how to use Contentful on a bare bones, web based, JavaScript enabled website.
## Who is this for?

This application was developed in order to show a very simple way of developing a frontend JavaScript application with Contentful, without the aid of any more complex frameworks or tools.

It's also focused on users who are newer to web development in general. The code is commented and explained, so even if you are not so experienced with webdevelopment you can get an understanding of what's happening in the code.

If you'd like to see more complex examples you can look at the [React discovery app](https://github.com/contentful/discovery-app-react) and more will come in the future.

This code makes some use of Promises, which are also used by the Contentful SDK. If you are new to promises, read [this introduction](http:https://www.html5rocks.com/en/tutorials/es6/promises/) and [this article](http:https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html) to learn some more common usage patterns.

## Trying it out

Expand Down
83 changes: 74 additions & 9 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
(function () {

/**
* Initializes the application and required dependencies, such as:
* - Contentful client
* - Configuration for the application
* - History API event listeners
* - Event delegation for handling anchor links throughout the app and allowing
* navigation through the use of pushState and the History API
*/
PC.init = function () {
// Initializes the Contentful client with the required credentials for a
// product catalog space. Feel free to replace them with our own.
PC.contentfulClient = contentful.createClient({
accessToken: '0e3ec801b5af550c8a1257e8623b1c77ac9b3d8fcfc1b2b7494e3cb77878f92a',
space: 'wl1z0pal05vy'
})

// IDs of some of the Content Types used in the app
PC.config = {
productContentTypeId: '2PqfXUJwE8qSYKuM0U6w8M',
categoryContentTypeId: '6XwpTaSiiI2Ak2Ww0oi6qa'
Expand All @@ -14,46 +25,100 @@ PC.init = function () {
setupHistory()
setupNavAnchorListeners()

// main container for rendering the app
PC.container = document.getElementById('content')

// load the index page
loadPage('')
}

// Navigates to a given page via the history API
PC.navigate = function (href) {
window.history.pushState({href: href}, '', href)
loadPage(href)
}

/**
* Sets up the popstate listener
* https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate
*/
function setupHistory() {
window.onpopstate = function (ev) {
loadPage(ev.state && ev.state.href || '')
}
}

/**
* Event delegation mechanism for links throughout the app
*
* Listens to all click events in the app, and if the source element is an anchor
* tag and has a data-nav property, it cancels the event and loads the page
* referred in the href with the loadPage function, while also pushing it
* to the history API
*/
function setupNavAnchorListeners() {
document.querySelector('body').addEventListener('click', function (ev) {
ev.preventDefault()
if(ev.target.tagName.toLowerCase() === 'a' && 'nav' in ev.target.dataset) {
history.pushState({href: ev.target.href}, '', ev.target.href)
loadPage(ev.target.href)
PC.navigate(ev.target.href)
}
}, false)
}

/**
* Basic routing mechanism
*
* Removes the URL from the href (which can come from either an anchor tag or
* the popstate event), and splits it by '/'.
*/
function loadPage(href) {
href = href.replace(/(^http(s)?:\/\/\w+(:\d+)?\/|^\/)/, '')
var urlParts = href.split('/')
switch(urlParts[0]) {
var pageName = urlParts[0]
// Attempts to get the object which contains the methods to render and setup
// pages, otherwise defaults to the main page
var page = PC.pages[pageName] || PC.pages.products
var loader
switch(pageName) {
// /categories and /categories/:id
case 'categories':
PC.pages.categories()
loader = page.renderHTML({
selectedCategoryId: urlParts[1],
})
break
// /about
case 'about':
PC.pages.about()
loader = page.renderHTML()
break
// /product/:id
case 'product':
PC.pages.product(urlParts[1])
loader = page.renderHTML({
productSlug: urlParts[1]
})
break
case 'brand':
PC.pages.brand(brand)
// /brand/:id
case 'brands':
loader = page.renderHTML({
brandId: urlParts[1]
})
break
// / (index page)
default:
PC.pages.products()
loader = page.renderHTML()
}

loader.then(injectInPage).then(function () {
// after rendering is done, run the postRender method if there is one
if('postRender' in page) {
setTimeout(function () {
page.postRender()
}, 0)
}
})
}

function injectInPage (HTMLContent) {
PC.container.innerHTML = HTMLContent
}

}());
Loading

0 comments on commit b6d2f83

Please sign in to comment.