@@ -1,5 +1,5 @@
|
||||
/* jshint esnext: true */
|
||||
import { APP_NAME, $document, $barba } from './utils/environment';
|
||||
import { APP_NAME, $document, $pjaxWrapper } from './utils/environment';
|
||||
|
||||
import globals from './globals';
|
||||
|
||||
@@ -106,8 +106,8 @@ class App {
|
||||
$moduleEls = $document.find('[data-module]');
|
||||
} else if (event.$scope instanceof jQuery && event.$scope.length > 0) {
|
||||
$moduleEls = event.$scope.find('[data-module]');
|
||||
} else if (event.isBarba) {
|
||||
$moduleEls = $barba.find('[data-module]');
|
||||
} else if (event.isPjax) {
|
||||
$moduleEls = $pjaxWrapper.find('[data-module]');
|
||||
}
|
||||
|
||||
// Loop through elements
|
||||
|
||||
@@ -14,13 +14,17 @@ export default class extends AbstractModule {
|
||||
super(options);
|
||||
|
||||
// Declaration of properties
|
||||
console.log('🔨 [module]:constructor - Example');
|
||||
|
||||
}
|
||||
|
||||
init() {
|
||||
// Set events and such
|
||||
|
||||
}
|
||||
|
||||
destroy() {
|
||||
console.log('❌ [module]:destroy - Example');
|
||||
super.destroy();
|
||||
this.$el.off(`.${EVENT_NAMESPACE}`);
|
||||
}
|
||||
|
||||
82
assets/scripts/transitions/BaseTransition.js
Normal file
82
assets/scripts/transitions/BaseTransition.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import { APP_NAME, $document, $html, $body, isDebug, $pjaxWrapper } from '../utils/environment';
|
||||
|
||||
const MODULE_NAME = 'Transition';
|
||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
||||
|
||||
const EVENT = {
|
||||
CLICK: `click.${EVENT_NAMESPACE}`,
|
||||
READYTOREMOVE: `readyToRemove.${EVENT_NAMESPACE}`,
|
||||
READYTODESTROY: `readyToDestroy.${EVENT_NAMESPACE}`
|
||||
};
|
||||
|
||||
export default class {
|
||||
constructor(options) {
|
||||
|
||||
this.options = options;
|
||||
this.wrapper = options.wrapper;
|
||||
this.overrideClass = options.overrideClass ? options.overrideClass : '';
|
||||
this.clickedLink = options.clickedLink;
|
||||
|
||||
}
|
||||
|
||||
launch() {
|
||||
if(isDebug) {
|
||||
console.log("---- Launch transition 👊 -----");
|
||||
}
|
||||
|
||||
$html
|
||||
.removeClass('dom-is-loaded dom-is-animated ')
|
||||
.addClass(`dom-is-loading ${this.overrideClass}`);
|
||||
|
||||
}
|
||||
|
||||
hideView(oldView, newView) {
|
||||
if(isDebug) {
|
||||
console.log('----- ❌ [VIEW]:hide - ', oldView.getAttribute('data-template'));
|
||||
}
|
||||
|
||||
// launch it at the end (animations...)
|
||||
$document.triggerHandler({
|
||||
type:EVENT.READYTOREMOVE,
|
||||
oldView: oldView,
|
||||
newView: newView
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
displayView(view) {
|
||||
|
||||
if(isDebug) {
|
||||
console.log('----- ✅ [VIEW]:display :', view.getAttribute('data-template'));
|
||||
}
|
||||
|
||||
$html.attr('data-template', view.getAttribute('data-template'));
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
$html
|
||||
.addClass('dom-is-loaded')
|
||||
.removeClass('dom-is-loading');
|
||||
|
||||
setTimeout(() => {
|
||||
$html
|
||||
.removeClass(this.overrideClass)
|
||||
.addClass('dom-is-animated');
|
||||
}, 1000);
|
||||
|
||||
// launch it at the end (animations...)
|
||||
$document.triggerHandler({
|
||||
type:EVENT.READYTODESTROY
|
||||
});
|
||||
|
||||
},1000);
|
||||
}
|
||||
|
||||
|
||||
destroy() {
|
||||
if(isDebug) {
|
||||
console.log("---- ❌ [transition]:destroy -----");
|
||||
}
|
||||
}
|
||||
}
|
||||
22
assets/scripts/transitions/CustomTransition.js
Normal file
22
assets/scripts/transitions/CustomTransition.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { APP_NAME, $document, $html, isDebug, $pjaxWrapper } from '../utils/environment';
|
||||
import BaseTransition from './BaseTransition';
|
||||
|
||||
const MODULE_NAME = 'Transition';
|
||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
||||
|
||||
const EVENT = {
|
||||
CLICK: `click.${EVENT_NAMESPACE}`,
|
||||
READYTOREMOVE: `readyToRemove.${EVENT_NAMESPACE}`,
|
||||
READYTODISPLAY: `readyToDisplay.${EVENT_NAMESPACE}`,
|
||||
READYTODESTROY: `readyToDestroy.${EVENT_NAMESPACE}`
|
||||
};
|
||||
|
||||
|
||||
export default class extends BaseTransition{
|
||||
constructor(options) {
|
||||
super(options);
|
||||
|
||||
this.overrideClass = '-custom-transition';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/* jshint esnext: true */
|
||||
import { APP_NAME, $document, $html, $barba } from '../utils/environment';
|
||||
import { EVENT as APP_EVENT } from '../App';
|
||||
|
||||
function DefaultTransition(options) {
|
||||
options = options || {};
|
||||
const startCallback = (typeof options.startCallback === 'function') ? options.startCallback : function(){};
|
||||
const overrideClass = (typeof options.overrideClass === 'string') ? options.overrideClass : '';
|
||||
|
||||
return Barba.BaseTransition.extend({
|
||||
start: function() {
|
||||
$html
|
||||
.removeClass('dom-is-loaded dom-is-animated')
|
||||
.addClass(`dom-is-loading ${overrideClass}`);
|
||||
|
||||
startCallback();
|
||||
|
||||
/* Close any overlays */
|
||||
|
||||
setTimeout(() => {
|
||||
Promise
|
||||
.all([this.newContainerLoading])
|
||||
.then(this.finish.bind(this));
|
||||
}, 1000);
|
||||
},
|
||||
finish: function() {
|
||||
$document.triggerHandler({
|
||||
type: APP_EVENT.DELETE_SCOPED_MODULES,
|
||||
$scope: $barba
|
||||
});
|
||||
|
||||
this.done();
|
||||
|
||||
const $el = $(this.newContainer);
|
||||
|
||||
// Get the template name of the new container and set it to the DOM
|
||||
$html.attr('data-template', $el.data('template'));
|
||||
|
||||
$document.triggerHandler({
|
||||
type: APP_EVENT.INIT_SCOPED_MODULES,
|
||||
isBarba: true
|
||||
});
|
||||
|
||||
$html
|
||||
.addClass('dom-is-loaded')
|
||||
.removeClass('dom-is-loading');
|
||||
|
||||
setTimeout(() => {
|
||||
$html
|
||||
.removeClass(overrideClass)
|
||||
.addClass('dom-is-animated');
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default DefaultTransition;
|
||||
@@ -1,81 +1,199 @@
|
||||
/* jshint esnext: true */
|
||||
import { APP_NAME, $document, $html, isDebug } from '../utils/environment';
|
||||
import { APP_NAME, $document, $html, isDebug, $pjaxWrapper } from '../utils/environment';
|
||||
import { EVENT as APP_EVENT } from '../App';
|
||||
|
||||
import DefaultTransition from './DefaultTransition';
|
||||
//List here all of your transitions
|
||||
import * as transitions from './transitions';
|
||||
|
||||
const MODULE_NAME = 'TransitionManager';
|
||||
const MODULE_NAME = 'Transition';
|
||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
||||
|
||||
const EVENT = {
|
||||
GOTO: `goto.${EVENT_NAMESPACE}`
|
||||
CLICK: `click.${EVENT_NAMESPACE}`,
|
||||
READYTOREMOVE: `readyToRemove.${EVENT_NAMESPACE}`,
|
||||
READYTODESTROY: `readyToDestroy.${EVENT_NAMESPACE}`
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@todo :
|
||||
|
||||
- ✅ get data-transition on clicked link -> launch() and add switch(){}
|
||||
- ❌ add goto listener
|
||||
- ❌ add newPageReady functon with google analytics send (maybe pjax do that?)
|
||||
- ✅ add overrideClass system for all transitions
|
||||
- ✅ add base class manager like old DefaultTransition (dom-is-loaded, dom-is-loading etc..)
|
||||
|
||||
|
||||
|
||||
======= SCHEMA =======
|
||||
|
||||
[] : listener
|
||||
* : trigger event
|
||||
|
||||
[pjax:send] -> (transition) launch()
|
||||
|
||||
[pjax:switch] (= new view is loaded) -> (transition) hideView()-> hide animations & *readyToRemove
|
||||
|
||||
[readyToRemove] -> remove() -> delete modules
|
||||
-> remove oldView from the DOM, and innerHTMl newView
|
||||
-> display()
|
||||
|
||||
display() -> (transition) displayView() -> display animations & *readyToRemove
|
||||
-> init new modules
|
||||
|
||||
[readyToRemove] -> reinit()
|
||||
|
||||
*/
|
||||
|
||||
export default class {
|
||||
constructor() {
|
||||
let clickedLink = undefined;
|
||||
let transition = '';
|
||||
|
||||
|
||||
// jQuery ondomready
|
||||
$(() => {
|
||||
this.load()
|
||||
this.load();
|
||||
});
|
||||
|
||||
$document.on(EVENT.GOTO, (event) => {
|
||||
if (!window.history.pushState) {
|
||||
window.location = event.options.location;
|
||||
} else {
|
||||
transition = event.options.transition;
|
||||
Barba.Pjax.goTo(event.options.location);
|
||||
}
|
||||
this.transition = new transitions['BaseTransition']({
|
||||
wrapper: this.wrapper
|
||||
});
|
||||
|
||||
// Define different page transitions
|
||||
Barba.Pjax.getTransition = function() {
|
||||
transition = (clickedLink instanceof Node) ? clickedLink.getAttribute('data-transition') : (typeof transition === 'string' ? transition : '');
|
||||
/*
|
||||
===== PJAX CONFIGURATION =====
|
||||
*/
|
||||
|
||||
let TransitionObject;
|
||||
this.containerClass = '.js-pjax-container';
|
||||
this.wrapperId = 'js-pjax-wrapper';
|
||||
this.noPjaxRequestClass = 'no-transition';
|
||||
this.wrapper = document.getElementById(this.wrapperId);
|
||||
|
||||
switch (transition) {
|
||||
default:
|
||||
TransitionObject = DefaultTransition();
|
||||
}
|
||||
this.options = {
|
||||
debug: false,
|
||||
cacheBust: false,
|
||||
elements: [`a:not(.${this.noPjaxRequestClass})`,'form[action]'],
|
||||
selectors: ['title',`${this.containerClass}`],
|
||||
switches: {}
|
||||
};
|
||||
this.options.switches[this.containerClass] = (oldEl, newEl, options) => this.switch(oldEl, newEl, options)
|
||||
this.pjax = new Pjax(this.options);
|
||||
|
||||
clickedLink = undefined;
|
||||
transition = '';
|
||||
/*
|
||||
===== LISTENERS =====
|
||||
*/
|
||||
|
||||
return TransitionObject;
|
||||
document.addEventListener('pjax:send',(e) => this.send(e));
|
||||
|
||||
|
||||
$document.on(EVENT.READYTOREMOVE,(event) => {
|
||||
this.remove(event.oldView, event.newView);
|
||||
});
|
||||
$document.on(EVENT.READYTODESTROY,(event) => {
|
||||
this.reinit();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (PJAX) Launch when pjax receive a request
|
||||
* get & manage data-transition,init and launch it
|
||||
* @param {event}
|
||||
* @return void
|
||||
*/
|
||||
send(e) {
|
||||
if(isDebug) {
|
||||
console.log("---- Launch request 🙌 -----");
|
||||
}
|
||||
|
||||
Barba.Dispatcher.on('linkClicked', (HTMLElement, MouseEvent) => {
|
||||
clickedLink = HTMLElement;
|
||||
let el = e.triggerElement;
|
||||
|
||||
let transition = el.getAttribute('data-transition') ? el.getAttribute('data-transition') : 'BaseTransition';
|
||||
$html.attr('data-transition',transition);
|
||||
|
||||
// options available : wrapper, overrideClass
|
||||
this.transition = new transitions[transition]({
|
||||
wrapper: this.wrapper,
|
||||
clickedLink: el
|
||||
});
|
||||
|
||||
Barba.Dispatcher.on('newPageReady', (currentStatus, prevStatus, container, currentHTML) => {
|
||||
// Fetch any inline script elements.
|
||||
const scripts = container.querySelectorAll('script.js-inline');
|
||||
this.transition.launch();
|
||||
|
||||
if (scripts instanceof window.NodeList) {
|
||||
let i = 0;
|
||||
let len = scripts.length;
|
||||
for (; i < len; i++) {
|
||||
eval(scripts[i].innerHTML);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute any third party features.
|
||||
*/
|
||||
/**
|
||||
* (PJAX) Launch when new page is loaded
|
||||
* @param {js dom element},
|
||||
* @param {js dom element}
|
||||
* @param {options : pjax options}
|
||||
* @return void
|
||||
*/
|
||||
switch(oldView, newView, options) {
|
||||
if(isDebug) {
|
||||
console.log('---- Next view loaded 👌 -----');
|
||||
}
|
||||
this.transition.hideView(oldView, newView);
|
||||
|
||||
// Google Analytics
|
||||
if (window.ga && !isDebug) {
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
this.pjax.onSwitch();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch when you trigger EVENT.READYTOREMOVE in your transition -> hideView(), at the end
|
||||
* after oldView hidden, delete modules and launch this.display()
|
||||
* @param {js dom element},
|
||||
* @param {js dom element}
|
||||
* @return void
|
||||
*/
|
||||
remove(oldView, newView) {
|
||||
|
||||
$document.triggerHandler({
|
||||
type: APP_EVENT.DELETE_SCOPED_MODULES,
|
||||
$scope: $pjaxWrapper
|
||||
});
|
||||
|
||||
Barba.Pjax.Dom.containerClass = 'js-barba-container';
|
||||
Barba.Pjax.Dom.wrapperId = 'js-barba-wrapper';
|
||||
oldView.remove();
|
||||
|
||||
Barba.Pjax.start();
|
||||
this.display(newView);
|
||||
}
|
||||
|
||||
/**
|
||||
* launch after this.remove()
|
||||
* @param {js dom element},
|
||||
* @return void
|
||||
*/
|
||||
display(view) {
|
||||
this.wrapper.innerHTML = view.outerHTML;
|
||||
|
||||
// Fetch any inline script elements.
|
||||
const scripts = view.querySelectorAll('script.js-inline');
|
||||
|
||||
if (scripts instanceof window.NodeList) {
|
||||
let i = 0;
|
||||
let len = scripts.length;
|
||||
for (; i < len; i++) {
|
||||
eval(scripts[i].innerHTML);
|
||||
}
|
||||
}
|
||||
|
||||
$document.triggerHandler({
|
||||
type: APP_EVENT.INIT_SCOPED_MODULES,
|
||||
isPjax: true
|
||||
});
|
||||
|
||||
this.transition.displayView(view);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch when you trigger EVENT.READYTODESTROY in your transition -> displayView(), at the end
|
||||
* @return void
|
||||
*/
|
||||
reinit() {
|
||||
this.transition.destroy();
|
||||
$html.attr('data-transition','');
|
||||
this.transition = new transitions['BaseTransition']({
|
||||
wrapper: this.wrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
2
assets/scripts/transitions/transitions.js
Normal file
2
assets/scripts/transitions/transitions.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export {default as BaseTransition} from './BaseTransition';
|
||||
export {default as CustomTransition} from './CustomTransition';
|
||||
@@ -5,8 +5,8 @@ const $document = $(document);
|
||||
const $window = $(window);
|
||||
const $html = $(document.documentElement).removeClass('has-no-js').addClass('has-js');
|
||||
const $body = $(document.body);
|
||||
const $barba = $('#js-barba-wrapper');
|
||||
const $pjaxWrapper = $('#js-pjax-wrapper');
|
||||
|
||||
const isDebug = !!$html.data('debug');
|
||||
|
||||
export { APP_NAME, DATA_API_KEY, $document, $window, $html, $body, isDebug, $barba };
|
||||
export { APP_NAME, DATA_API_KEY, $document, $window, $html, $body, isDebug, $pjaxWrapper };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
options: {
|
||||
open : false,
|
||||
proxy : 'localhost',
|
||||
proxy : 'locomotive-boilerplate.test',
|
||||
port : 3000,
|
||||
watchTask : true,
|
||||
notify : false
|
||||
@@ -12,7 +12,8 @@ module.exports = {
|
||||
'<%= paths.css.dist %>/**/*.css',
|
||||
'<%= paths.js.dist %>/**/*.js',
|
||||
'<%= paths.img.dist %>/**/*.svg',
|
||||
'**/*.php'
|
||||
'**/*.php',
|
||||
'**/*.html',
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports = {
|
||||
},
|
||||
src : [
|
||||
'<%= paths.js.src %>/vendors/**/*.js',
|
||||
'<%= paths.npm %>/barba.js/dist/barba.js',
|
||||
'<%= paths.npm %>/pjax/pjax.js',
|
||||
'<%= paths.npm %>/svg4everybody/dist/svg4everybody.js'
|
||||
],
|
||||
dest : '<%= paths.js.dist %>/vendors.js'
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"version": "1.0.0",
|
||||
"author": "Locomotive <info@locomotive.ca>",
|
||||
"dependencies": {
|
||||
"barba.js": "0.0.0",
|
||||
"pjax": "0.0.0",
|
||||
"svg4everybody": "0.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<!--[if lte IE 9]> <html lang="fr" class="has-no-js ie9"> <![endif]-->
|
||||
<!--[if gt IE 9]><!--> <html lang="fr" class="has-no-js"> <!--<![endif]-->
|
||||
<!--[if gt IE 9]><!--> <html lang="fr" class="has-no-js" data-debug> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#f2f2f2">
|
||||
<title>Boilerplate</title>
|
||||
<title>Home | Boilerplate </title>
|
||||
|
||||
<link rel="apple-touch-icon" href="assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" href="assets/images/favicon.png">
|
||||
@@ -15,9 +15,24 @@
|
||||
<link rel="stylesheet" href="assets/styles/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="js-barba-wrapper">
|
||||
<div class="js-barba-container" data-template="home">
|
||||
<div data-module="Example"></div>
|
||||
|
||||
<header>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="page.html" data-transition="CustomTransition">Page</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="page.html" class="no-transition">No transition link</a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-pjax-wrapper">
|
||||
<div class="js-pjax-container" data-template="home" >
|
||||
<div data-module="Example">Home page with Example module</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
45
www/page.html
Normal file
45
www/page.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!doctype html>
|
||||
<!--[if lte IE 9]> <html lang="fr" class="has-no-js ie9"> <![endif]-->
|
||||
<!--[if gt IE 9]><!--> <html lang="fr" class="has-no-js"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#f2f2f2">
|
||||
<title>Page | Boilerplate</title>
|
||||
|
||||
<link rel="apple-touch-icon" href="assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" href="assets/images/favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="assets/styles/main.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="page.html" data-transition="CustomTransition">Page</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="page.html" class="no-transition">No transition link</a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-pjax-wrapper">
|
||||
<div class="js-pjax-container" data-template="page" data-transition="pageTransition">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus tempore officia temporibus error rem id, vel perspiciatis eveniet placeat, ducimus fugit vitae sequi, quas deserunt ab eius expedita quia nulla.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="assets/scripts/jquery-3.2.1.min.js"><\/script>')</script>
|
||||
<script src="assets/scripts/vendors.js"></script>
|
||||
<script src="assets/scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user