Merge branch 'v2'
This commit is contained in:
12
.babelrc
12
.babelrc
@@ -1,13 +1,3 @@
|
|||||||
{
|
{
|
||||||
"presets": [
|
"presets": ["@babel/preset-env"]
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"ie": "11"
|
|
||||||
},
|
|
||||||
"useBuiltIns": "usage"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
261
README.md
261
README.md
@@ -1,12 +1,14 @@
|
|||||||
Locomotive's Front-end Boilerplate
|
<p align="center">
|
||||||
==================================
|
<a href="https://github.com/locomotivemtl/locomotive-boilerplate">
|
||||||
|
<img src="https://user-images.githubusercontent.com/4596862/54868065-c2aea200-4d5e-11e9-9ce3-e0013c15f48c.png" height="140">
|
||||||
Front-end boilerplate for projects by [Locomotive][locomtl].
|
</a>
|
||||||
|
</p>
|
||||||
|
<h1 align="center">Locomotive Boilerplate</h1>
|
||||||
|
<p align="center">Front-end boilerplate for projects by Locomotive.</p>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
```sh
|
```sh
|
||||||
# install mbp and gulp
|
npm install mbp gulp -g
|
||||||
npm install mbp gulp@next -g
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -19,140 +21,177 @@ gulp
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Change the mentions of `boilerplate` for your project's name in
|
Change the mentions of `boilerplate` for your project's name in `mconfig.json`. It is based on [modularBP](https://github.com/modularorg/modularbp).
|
||||||
- `mconfig.json`
|
|
||||||
- `assets/scripts/utils/environment.js`
|
|
||||||
|
|
||||||
## CSS
|
[Learn more](https://github.com/modularorg/modularbp)
|
||||||
|
|
||||||
- We use [Sass](http://sass-lang.com) for our CSS Preprocessor
|
## Build
|
||||||
- [itcss](http://itcss.io) CSS architecture
|
[gulp](https://github.com/gulpjs/gulp) is our build system. It compiles our styles and scripts, generate svg sprites, live reload the browser and minify everything.
|
||||||
- More Minimal BEM like CSS Syntax: `.block_element -modifier`
|
|
||||||
- [More Transparent UI Code with Namespaces](http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces)
|
|
||||||
|
|
||||||
### Sass import order
|
#### Tasks
|
||||||
|
```sh
|
||||||
|
# watch
|
||||||
|
gulp
|
||||||
|
|
||||||
* **Settings:** Global variables, site-wide settings, config switches, etc.
|
# compile
|
||||||
* **Tools:** Site-wide mixins and functions.
|
gulp compile
|
||||||
* **Generic:** Low-specificity, far-reaching rulesets (e.g. resets).
|
|
||||||
* **Base:** Unclassed HTML elements (e.g. `a {}`, `blockquote {}`, `address {}`).
|
|
||||||
* **Objects:** Objects, abstractions, and design patterns (e.g. `.o-media {}`).
|
|
||||||
* **Components:** Discrete, complete chunks of UI (e.g. `.c-carousel {}`).
|
|
||||||
* **Utilities:** High-specificity, very explicit selectors. Overrides and helper
|
|
||||||
classes (e.g. `.u-hidden {}`).
|
|
||||||
|
|
||||||
### Grid
|
# minify
|
||||||
We use [inuitcss](https://github.com/inuitcss/inuitcss/tree/6eb574fa604481ffa36272e6034e77467334ec50) layout and width system. We are using a inline-block grid system.
|
gulp build
|
||||||
|
|
||||||
Insert a `.o-layout` block and add `.o-layout_item` elements inside it. By default `o-layout_item` made 100%.
|
|
||||||
You can define different fractions in `/tools/_widths.scss` (`$widths-fractions`)
|
|
||||||
|
|
||||||
If you want a 2 columns grid, just add `.u-1/2` on your 2 `.o-layout_item`
|
|
||||||
|
|
||||||
If you want to adapt columns by media queries, by example a 2 columns grid for 1000px + resolutions, and one columns in block under 1000px :
|
|
||||||
|
|
||||||
**HTML**
|
|
||||||
```
|
```
|
||||||
<div class="o-layout">
|
|
||||||
|
[Learn more](https://github.com/modularorg/modularbp-gulp)
|
||||||
|
|
||||||
|
## Styles
|
||||||
|
[Sass](https://github.com/sass/node-sass) is our CSS preprocessor. [Autoprefixer](https://github.com/postcss/autoprefixer) is also included.
|
||||||
|
|
||||||
|
#### Architecture
|
||||||
|
[ITCSS](https://github.com/itcss) is our CSS architecture.
|
||||||
|
|
||||||
|
* `settings`: Global variables, site-wide settings, config switches, etc.
|
||||||
|
* `tools`: Site-wide mixins and functions.
|
||||||
|
* `generic`: Low-specificity, far-reaching rulesets (e.g. resets).
|
||||||
|
* `elements`: Unclassed HTML elements (e.g. `a {}`, `blockquote {}`, `address {}`).
|
||||||
|
* `objects`: Objects, abstractions, and design patterns (e.g. `.o-layout {}`).
|
||||||
|
* `components`: Discrete, complete chunks of UI (e.g. `.c-carousel {}`).
|
||||||
|
* `utilities`: High-specificity, very explicit selectors. Overrides and helper
|
||||||
|
classes (e.g. `.u-hidden {}`)
|
||||||
|
|
||||||
|
[_source_](https://github.com/inuitcss/inuitcss#css-directory-structure)
|
||||||
|
|
||||||
|
#### Naming
|
||||||
|
We use a simplified [BEM](https://github.com/bem) syntax.
|
||||||
|
|
||||||
|
`.block .block_element -modifier`
|
||||||
|
|
||||||
|
#### Namespaces
|
||||||
|
We namespace our classes for more [transparency](https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/).
|
||||||
|
|
||||||
|
* `o-`: Object that it may be used in any number of unrelated contexts to the one you can currently see it in. Making modifications to these types of class could potentially have knock-on effects in a lot of other unrelated places.
|
||||||
|
* `c-`: Component is a concrete, implementation-specific piece of UI. All of the changes you make to its styles should be detectable in the context you’re currently looking at. Modifying these styles should be safe and have no side effects.
|
||||||
|
* `u-`: Utility has a very specific role (often providing only one declaration) and should not be bound onto or changed. It can be reused and is not tied to any specific piece of UI.
|
||||||
|
* `s-`: Scope creates a new styling context. Similar to a Theme, but not necessarily cosmetic, these should be used sparingly—they can be open to abuse and lead to poor CSS if not used wisely.
|
||||||
|
* `is-`, `has-`: Is currently styled a certain way because of a state or condition. It tells us that the DOM currently has a temporary, optional, or short-lived style applied to it due to a certain state being invoked.
|
||||||
|
|
||||||
|
[_source_](https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/#the-namespaces)
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
```html
|
||||||
|
<div class="c-block -large">
|
||||||
|
<div class="c-block_layout o-layout">
|
||||||
<div class="o-layout_item u-1/2@from-medium">
|
<div class="o-layout_item u-1/2@from-medium">
|
||||||
first colum
|
<div class="c-block_heading o-h -medium">Heading</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="o-layout_item u-1/2@from-medium">
|
<div class="o-layout_item u-1/2@from-medium">
|
||||||
second colum
|
<a class="c-block_button o-button -outline" href="#">Button</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
```scss
|
||||||
|
.c-block {
|
||||||
|
&.-large {
|
||||||
|
padding: rem(60px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
**CSS** (`/tools/_widths.scss`)
|
.c-block_heading {
|
||||||
```
|
@media (max-width: $to-medium) {
|
||||||
.u-1\/2\@from-medium {
|
.c-block.-large & {
|
||||||
@media (min-width: $from-medium) {
|
margin-bottom: rem(40px);
|
||||||
width: span(1/2);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
[modularJS](https://github.com/modularorg/modularjs) is a small framework we use on top of ES modules. It compiles with [Rollup](https://github.com/rollup/rollup) and [Babel](https://github.com/babel/babel).
|
||||||
|
|
||||||
### Form
|
#### Why
|
||||||
|
- Automatically init visible modules.
|
||||||
|
- Easily call other modules methods.
|
||||||
|
- Quickly set scoped events with delegation.
|
||||||
|
- Simply select DOM elements scoped in their module.
|
||||||
|
|
||||||
We included some basic CSS styles and resets to the form elements so we can easily have custom style form elements that work on every browsers.
|
[_source_](https://github.com/modularorg/modularjs#why)
|
||||||
|
|
||||||
*[Demo][demo-form]*
|
#### Example
|
||||||
|
```html
|
||||||
|
<div data-module-example>
|
||||||
|
<div data-example="main">
|
||||||
|
<h2>Example</h2>
|
||||||
|
</div>
|
||||||
|
<button data-example="load">More</button>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
```js
|
||||||
|
import { module } from 'modujs';
|
||||||
|
|
||||||
## JavaScript
|
export default class extends module {
|
||||||
|
constructor(m) {
|
||||||
|
super(m);
|
||||||
|
|
||||||
- We use HTML data attributes to init our JavaScript modules: `data-module`
|
this.events = {
|
||||||
- All DOM related JavaScript is hooked to `js-` prefixed HTML classes
|
click: {
|
||||||
- [jQuery](https://jquery.com) is globally included
|
load: 'loadMore'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[locomtl]: https://locomotive.ca
|
loadMore() {
|
||||||
[demo-grid]: https://codepen.io/AntoineBoulanger/pen/EaLNxe
|
this.$('main').classList.add('is-loading');
|
||||||
[demo-form]: https://codepen.io/AntoineBoulanger/pen/uBJmi
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[Learn more](https://github.com/modularorg/modularjs)
|
||||||
|
|
||||||
## Page transitions
|
## Page transitions
|
||||||
We use [Pjax](https://github.com/MoOx/pjax) by MoOx.
|
[modularLoad](https://github.com/modularorg/modularload) is used for page transitions and lazy loading.
|
||||||
|
|
||||||
### Setup
|
#### Example
|
||||||
1. Create a wrapper : `.js-pjax-wrapper` and a container `.js-pjax-container` inside. When a transition is launched, the new container is put inside the wrapper, and the old one is remove.
|
```html
|
||||||
|
<nav>
|
||||||
|
<a href="/">Home</a>
|
||||||
|
<a href="/page" data-load="transitionName">Page</a>
|
||||||
|
</nav>
|
||||||
|
<div data-load-container>
|
||||||
|
<img data-load-src="assets/images/hello.jpg">
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
```js
|
||||||
|
import modularLoad from 'modularload';
|
||||||
|
|
||||||
2. Main settings are set inside `assets/scripts/transitions/TransitionManager.js`
|
this.load = new modularLoad({
|
||||||
|
enterDelay: 300,
|
||||||
|
transitions: {
|
||||||
|
transitionName: {
|
||||||
|
enterDelay: 450
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
3. `BaseTransition` is launched by default, to set a new transition (like `CustomTransition`) :
|
[Learn more](https://github.com/modularorg/modularload)
|
||||||
- create a new class `TestTransition.js` witch extends `BaseTransition` in `assets/scripts/transitions/`
|
|
||||||
- add a line in `assets/scripts/transitions/transitions.js` to add your transition
|
|
||||||
- use it like : `<a href="/yourUrl" data-transition="TestTransition">My page</a>`
|
|
||||||
- Enjoy and made everything you want in your transition, check `BaseTransition.js` or `CustomTransition.js` like example
|
|
||||||
|
|
||||||
### Schema
|
## Scroll detection
|
||||||
|
[Locomotive Scroll](https://github.com/locomotivemtl/locomotive-scroll) is used for elements in viewport detection and smooth scrolling with parallax.
|
||||||
|
|
||||||
Legend
|
#### Example
|
||||||
- `[ ]` : listener
|
```html
|
||||||
- `*` : trigger event
|
<div class="o-scroll" data-module-scroll>
|
||||||
|
<div class="js-animate">Trigger</div>
|
||||||
|
<div class="js-animate" data-speed="1">Parallax</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
```js
|
||||||
|
import ScrollManager from '../scroll/vendors/ScrollManager';
|
||||||
|
|
||||||
`[pjax:send]` -> (transition) launch()
|
this.scrollManager = new ScrollManager({
|
||||||
|
container: $(this.el),
|
||||||
`[pjax:switch]` (= new view is loaded) -> (BaseTransition) `hideView()` -> hide animations & `*readyToRemove`
|
selector: '.js-animate',
|
||||||
|
smooth: true
|
||||||
`[readyToRemove]` -> `remove()` -> delete modules, remove oldView from the DOM, innerHTML newView, init modules, `display()`
|
});
|
||||||
|
````
|
||||||
`display()` -> (BaseTransition) `displayView()` -> display animations & `*readyToDestroy`
|
|
||||||
-> init new modules
|
|
||||||
|
|
||||||
`[readyToRemove]` -> reinit()
|
|
||||||
|
|
||||||
## Locomotive Scroll
|
|
||||||
|
|
||||||

|
|
||||||
- [locomotive-scroll](https://github.com/locomotivemtl/locomotive-scroll)
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
- Create a `.o-scroll` container with `data-module="Scroll"`
|
|
||||||
- in the module `Scroll.js` you have a basic initialisation
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
Options | Type | Description
|
|
||||||
--- | --- | ---
|
|
||||||
container | $element | Scroll container (with the smooth scroll, this container will be transform)
|
|
||||||
selector | String | Every elements will be check by the scroll, can be affect by a followed data attributes
|
|
||||||
smooth | Boolean | If you want a smooth scroll
|
|
||||||
smoothMobile | Boolean | If you want a smooth scroll on mobile
|
|
||||||
mobileContainer | $element | Scroll container on mobile, document by default
|
|
||||||
getWay | Boolean | if true, the animate will determine if you scroll down or scroll up
|
|
||||||
getSpeed | Boolean | if true, the animate will calcul the velocity of your scroll. Access with `this.scroll.y`
|
|
||||||
|
|
||||||
### Data attributes
|
|
||||||
|
|
||||||
Data | Value | Description
|
|
||||||
--- | --- | ---
|
|
||||||
data-speed | number | Speed of transform for parallax elements
|
|
||||||
data-repeat | false | Determine if the "In View" class is added one or each times
|
|
||||||
data-inview-class | is-show | CSS Class when the element is in view.
|
|
||||||
data-position | top/bottom | Trigger from top/bottom of the window instead of the default from bottom to top
|
|
||||||
data-target | #id, .class | Trigger from another element
|
|
||||||
data-horizontal | false | Use transformX instead of transformY
|
|
||||||
data-sticky | false | Set $element sticky when it's in viewport
|
|
||||||
data-sticky-target | #id | Stop the element stick when the target is in viewport
|
|
||||||
data-callback | `test.Scroll(test:0)` | trigger event, with options way wich return "leave" or "enter" when $element is in viewport
|
|
||||||
data-viewport-offset | i,j | value between 0 to 1 (0.3 to start at 30% of the bottom of the viewport), useful to trigger a sequence of callbacks. (i : value wich start at the bottom, j : start at the top, j is optional)
|
|
||||||
|
|
||||||
|
[Learn more](https://github.com/locomotivemtl/locomotive-scroll)
|
||||||
|
|||||||
@@ -1,161 +1,15 @@
|
|||||||
import { APP_NAME, $document, $pjaxWrapper } from './utils/environment';
|
import modular from 'modujs';
|
||||||
|
|
||||||
import globals from './globals';
|
|
||||||
|
|
||||||
import { arrayContains, removeFromArray } from './utils/array';
|
|
||||||
import { getNodeData } from './utils/html';
|
|
||||||
import { isFunction } from './utils/is';
|
|
||||||
|
|
||||||
// Basic modules
|
|
||||||
import * as modules from './modules';
|
import * as modules from './modules';
|
||||||
|
import globals from './globals';
|
||||||
|
import { html } from './utils/environment';
|
||||||
|
|
||||||
const MODULE_NAME = 'App';
|
const app = new modular({
|
||||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
modules: modules
|
||||||
|
});
|
||||||
|
|
||||||
export const EVENT = {
|
app.init(app);
|
||||||
INIT_MODULES: `initModules.${EVENT_NAMESPACE}`,
|
globals();
|
||||||
INIT_SCOPED_MODULES: `initScopedModules.${EVENT_NAMESPACE}`,
|
|
||||||
DELETE_SCOPED_MODULES: `deleteScopedModules.${EVENT_NAMESPACE}`
|
|
||||||
};
|
|
||||||
|
|
||||||
class App {
|
html.classList.add('is-loaded is-ready');
|
||||||
constructor() {
|
html.classList.remove('is-loading');
|
||||||
this.modules = modules;
|
|
||||||
this.currentModules = [];
|
|
||||||
|
|
||||||
$document.on(EVENT.INIT_MODULES, (event) => {
|
|
||||||
this.initGlobals(event.firstBlood)
|
|
||||||
.deleteModules(event)
|
|
||||||
.initModules(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
$document.on(EVENT.INIT_SCOPED_MODULES, (event) => {
|
|
||||||
this.initModules(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
$document.on(EVENT.DELETE_SCOPED_MODULES, (event) => {
|
|
||||||
this.deleteModules(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy all existing modules or a specific scope of modules
|
|
||||||
* @param {Object} event The event being triggered.
|
|
||||||
* @return {Object} Self (allows chaining)
|
|
||||||
*/
|
|
||||||
deleteModules(event) {
|
|
||||||
let destroyAll = true;
|
|
||||||
let moduleIds = [];
|
|
||||||
|
|
||||||
// Check for scope first
|
|
||||||
if (event.$scope instanceof jQuery && event.$scope.length > 0) {
|
|
||||||
// Modules within scope
|
|
||||||
const $modules = event.$scope.find('[data-module]');
|
|
||||||
|
|
||||||
// Determine their uids
|
|
||||||
moduleIds = $.makeArray($modules.map(function(index) {
|
|
||||||
return $modules.eq(index).data('uid');
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (moduleIds.length > 0) {
|
|
||||||
destroyAll = false;
|
|
||||||
} else {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop modules and destroying all of them, or specific ones
|
|
||||||
let i = this.currentModules.length;
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
if (destroyAll || arrayContains(moduleIds, this.currentModules[i].uid)) {
|
|
||||||
removeFromArray(moduleIds, this.currentModules[i].uid);
|
|
||||||
this.currentModules[i].destroy();
|
|
||||||
this.currentModules.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute global functions and settings
|
|
||||||
* Allows you to initialize global modules only once if you need
|
|
||||||
* (ex.: when using Barba.js or SmoothState.js)
|
|
||||||
* @return {Object} Self (allows chaining)
|
|
||||||
*/
|
|
||||||
initGlobals(firstBlood) {
|
|
||||||
globals(firstBlood);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find modules and initialize them
|
|
||||||
* @param {Object} event The event being triggered.
|
|
||||||
* @return {Object} Self (allows chaining)
|
|
||||||
*/
|
|
||||||
initModules(event) {
|
|
||||||
// Elements with module
|
|
||||||
let $moduleEls = [];
|
|
||||||
|
|
||||||
// If first blood, load all modules in the DOM
|
|
||||||
// If scoped, render elements with modules
|
|
||||||
// If Barba, load modules contained in Barba container
|
|
||||||
if (event.firstBlood) {
|
|
||||||
$moduleEls = $document.find('[data-module]');
|
|
||||||
} else if (event.$scope instanceof jQuery && event.$scope.length > 0) {
|
|
||||||
$moduleEls = event.$scope.find('[data-module]');
|
|
||||||
} else if (event.isPjax) {
|
|
||||||
$moduleEls = $pjaxWrapper.find('[data-module]');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through elements
|
|
||||||
let i = 0;
|
|
||||||
const elsLen = $moduleEls.length;
|
|
||||||
|
|
||||||
for (; i < elsLen; i++) {
|
|
||||||
|
|
||||||
// Current element
|
|
||||||
let el = $moduleEls[i];
|
|
||||||
|
|
||||||
// All data- attributes considered as options
|
|
||||||
let options = getNodeData(el);
|
|
||||||
|
|
||||||
// Add current DOM element and jQuery element
|
|
||||||
options.el = el;
|
|
||||||
options.$el = $moduleEls.eq(i);
|
|
||||||
|
|
||||||
// Module does exist at this point
|
|
||||||
let attr = options.module;
|
|
||||||
|
|
||||||
// Splitting modules found in the data-attribute
|
|
||||||
let moduleIdents = attr.split(/[,\s]+/g);
|
|
||||||
|
|
||||||
// Loop modules
|
|
||||||
let j = 0;
|
|
||||||
let modulesLen = moduleIdents.length;
|
|
||||||
|
|
||||||
for (; j < modulesLen; j++) {
|
|
||||||
let moduleAttr = moduleIdents[j];
|
|
||||||
|
|
||||||
if (typeof this.modules[moduleAttr] === 'function') {
|
|
||||||
let module = new this.modules[moduleAttr](options);
|
|
||||||
this.currentModules.push(module);
|
|
||||||
module.init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IIFE for loading the application
|
|
||||||
// ==========================================================================
|
|
||||||
(function() {
|
|
||||||
new App();
|
|
||||||
$document.triggerHandler({
|
|
||||||
type: EVENT.INIT_MODULES,
|
|
||||||
firstBlood: true
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import TransitionManager from './transitions/TransitionManager';
|
|
||||||
import svg4everybody from 'svg4everybody';
|
import svg4everybody from 'svg4everybody';
|
||||||
|
|
||||||
export default function(firstBlood) {
|
export default function() {
|
||||||
svg4everybody();
|
svg4everybody();
|
||||||
|
|
||||||
if (firstBlood) {
|
|
||||||
const transitionManager = new TransitionManager();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export {default as Example} from './modules/Example';
|
export {default as Load} from './modules/Load';
|
||||||
export {default as Scroll} from './modules/Scroll';
|
export {default as Scroll} from './modules/Scroll';
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
let uid = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract Module
|
|
||||||
*/
|
|
||||||
export default class {
|
|
||||||
constructor(options) {
|
|
||||||
this.$el = options.$el || null;
|
|
||||||
this.el = options.el || null;
|
|
||||||
|
|
||||||
// Generate a unique module identifier
|
|
||||||
this.uid = 'm-' + uid++;
|
|
||||||
// Use jQuery's data API to "store it in the DOM"
|
|
||||||
this.$el.data('uid', this.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
if (this.$el) {
|
|
||||||
this.$el.removeData('uid')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +1,11 @@
|
|||||||
import { APP_NAME } from '../utils/environment';
|
import { module } from 'modujs';
|
||||||
import AbstractModule from './AbstractModule';
|
|
||||||
|
|
||||||
const MODULE_NAME = 'Example';
|
|
||||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
|
||||||
|
|
||||||
const EVENT = {
|
|
||||||
CLICK: `click.${EVENT_NAMESPACE}`
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class extends AbstractModule {
|
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
// Declaration of properties
|
|
||||||
console.log('🔨 [module]:constructor - Example');
|
|
||||||
|
|
||||||
|
export default class extends module {
|
||||||
|
constructor(m) {
|
||||||
|
super(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// Set events and such
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
|
||||||
console.log('❌ [module]:destroy - Example');
|
|
||||||
super.destroy();
|
|
||||||
this.$el.off(`.${EVENT_NAMESPACE}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,21 @@
|
|||||||
import { APP_NAME, $document } from '../utils/environment';
|
import { module } from 'modujs';
|
||||||
import AbstractModule from './AbstractModule';
|
import { $document } from '../utils/environment'
|
||||||
import ScrollManager from '../scroll/vendors/ScrollManager';
|
import ScrollManager from '../scroll/vendors/ScrollManager';
|
||||||
|
|
||||||
const MODULE_NAME = 'Scroll';
|
export default class extends module {
|
||||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
constructor(m) {
|
||||||
|
super(m);
|
||||||
export default class extends AbstractModule {
|
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
setTimeout(() => {
|
this.scroll = new ScrollManager({
|
||||||
this.scrollManager = new ScrollManager({
|
container: $(this.el),
|
||||||
container: this.$el,
|
smooth: true,
|
||||||
selector: '.js-animate',
|
inertia: 1
|
||||||
smooth: false,
|
|
||||||
smoothMobile: false,
|
|
||||||
mobileContainer: $document,
|
|
||||||
getWay: false,
|
|
||||||
getSpeed: false
|
|
||||||
});
|
});
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
super.destroy();
|
this.scroll.destroy();
|
||||||
this.scrollManager.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
assets/scripts/modules/load.js
Normal file
22
assets/scripts/modules/load.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { module } from 'modujs';
|
||||||
|
import modularLoad from 'modularload';
|
||||||
|
|
||||||
|
export default class extends module {
|
||||||
|
constructor(m) {
|
||||||
|
super(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const load = new modularLoad({
|
||||||
|
enterDelay: 0,
|
||||||
|
transitions: {
|
||||||
|
customTransition: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
load.on('loaded', (transition, oldContainer, newContainer) => {
|
||||||
|
this.call('destroy', oldContainer, 'app');
|
||||||
|
this.call('update', newContainer, 'app');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import { APP_NAME, $document, $html, $body, isDebug, $pjaxWrapper } from '../utils/environment';
|
|
||||||
|
|
||||||
import { EVENT as TransitionEvent } from './TransitionManager'
|
|
||||||
|
|
||||||
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('has-dom-loaded has-dom-animated ')
|
|
||||||
.addClass(`has-dom-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:TransitionEvent.READYTOAPPEND,
|
|
||||||
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('has-dom-loaded')
|
|
||||||
.removeClass('has-dom-loading');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
$html
|
|
||||||
.removeClass(this.overrideClass)
|
|
||||||
.addClass('has-dom-animated');
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// launch it at the end (animations...)
|
|
||||||
$document.triggerHandler({
|
|
||||||
type:TransitionEvent.READYTODESTROY
|
|
||||||
});
|
|
||||||
|
|
||||||
},1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
if(isDebug) {
|
|
||||||
console.log("---- ❌ [transition]:destroy -----");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import { APP_NAME, $document, $html, isDebug, $pjaxWrapper } from '../utils/environment';
|
|
||||||
import BaseTransition from './BaseTransition';
|
|
||||||
|
|
||||||
import { EVENT as TransitionEvent } from './TransitionManager'
|
|
||||||
|
|
||||||
export default class extends BaseTransition{
|
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this.overrideClass = '-custom-transition';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
import Pjax from 'pjax';
|
|
||||||
import { APP_NAME, $document, $html, isDebug, $pjaxWrapper, $window } from '../utils/environment';
|
|
||||||
import { EVENT as APP_EVENT } from '../app';
|
|
||||||
|
|
||||||
//List here all of your transitions
|
|
||||||
import * as transitions from './transitions';
|
|
||||||
|
|
||||||
const MODULE_NAME = 'Transition';
|
|
||||||
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
|
||||||
|
|
||||||
export const EVENT = {
|
|
||||||
CLICK: `click.${EVENT_NAMESPACE}`,
|
|
||||||
READYTOAPPEND: `readyToAppend.${EVENT_NAMESPACE}`,
|
|
||||||
READYTODESTROY: `readyToDestroy.${EVENT_NAMESPACE}`,
|
|
||||||
GOTO: `goto.${EVENT_NAMESPACE}`
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
@todo :
|
|
||||||
|
|
||||||
- ✅ get data-transition on clicked link -> launch() and add switch(){}
|
|
||||||
- ✅ add goto listener
|
|
||||||
- ✅ add overrideClass system for all transitions
|
|
||||||
- ✅ add base class manager like old DefaultTransition (has-dom-loaded, has-dom-loading etc..)
|
|
||||||
|
|
||||||
|
|
||||||
======= SCHEMA =======
|
|
||||||
|
|
||||||
[] : listener
|
|
||||||
* : trigger event
|
|
||||||
|
|
||||||
[pjax:send] -> (transition) launch()
|
|
||||||
|
|
||||||
[pjax:switch] (= new view is loaded) -> (transition) hideView()-> hide animations & *readyToAppend
|
|
||||||
|
|
||||||
[readyToAppend] -> append() -> delete modules
|
|
||||||
-> remove oldView from the DOM, and innerHTMl newView
|
|
||||||
-> change()
|
|
||||||
|
|
||||||
display() -> (transition) displayView() -> display animations & *readyToDestroy
|
|
||||||
-> init new modules
|
|
||||||
|
|
||||||
[readyToAppend] -> reinit()
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class {
|
|
||||||
constructor() {
|
|
||||||
|
|
||||||
|
|
||||||
// jQuery ondomready
|
|
||||||
$window.on('load',() => {
|
|
||||||
this.load();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.transition = new transitions['BaseTransition']({
|
|
||||||
wrapper: this.wrapper
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
===== PJAX CONFIGURATION =====
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.containerClass = '.js-pjax-container';
|
|
||||||
this.wrapperId = 'js-pjax-wrapper';
|
|
||||||
this.noPjaxRequestClass = 'no-transition';
|
|
||||||
this.wrapper = document.getElementById(this.wrapperId);
|
|
||||||
|
|
||||||
this.options = {
|
|
||||||
debug: false,
|
|
||||||
cacheBust: false,
|
|
||||||
elements: [`a:not(.${this.noPjaxRequestClass})`,'form[action]'],
|
|
||||||
selectors: ['title',`${this.containerClass}`],
|
|
||||||
switches: {},
|
|
||||||
requestOptions: {
|
|
||||||
timeout: 2000
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.options.switches[this.containerClass] = (oldEl, newEl, options) => this.switch(oldEl, newEl, options)
|
|
||||||
this.pjax = new Pjax(this.options);
|
|
||||||
|
|
||||||
/*
|
|
||||||
===== LISTENERS =====
|
|
||||||
*/
|
|
||||||
|
|
||||||
document.addEventListener('pjax:send',(e) => this.send(e));
|
|
||||||
|
|
||||||
|
|
||||||
$document.on(EVENT.READYTOAPPEND,(event) => {
|
|
||||||
this.append(event.oldView, event.newView);
|
|
||||||
});
|
|
||||||
$document.on(EVENT.READYTODESTROY,(event) => {
|
|
||||||
this.reinit();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/** goto exampe
|
|
||||||
$document.triggerHandler({
|
|
||||||
type: 'goto.Transition',
|
|
||||||
options : {
|
|
||||||
el: {{element clicked?}},
|
|
||||||
link: {{url}}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
$document.on(EVENT.GOTO, (e) => {
|
|
||||||
if(e.options.el != undefined) {
|
|
||||||
this.autoEl = e.options.el.get(0);
|
|
||||||
}
|
|
||||||
this.pjax.loadUrl(e.options.link, $.extend({}, this.pjax.options));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (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 🙌 -----");
|
|
||||||
}
|
|
||||||
|
|
||||||
let el,transition;
|
|
||||||
|
|
||||||
if(e.triggerElement != undefined) {
|
|
||||||
|
|
||||||
el = e.triggerElement;
|
|
||||||
|
|
||||||
transition = el.getAttribute('data-transition') ? el.getAttribute('data-transition') : 'BaseTransition';
|
|
||||||
$html.attr('data-transition',transition);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (this.autoEl != undefined) {
|
|
||||||
el = this.autoEl;
|
|
||||||
} else {
|
|
||||||
el = document;
|
|
||||||
}
|
|
||||||
|
|
||||||
transition = 'BaseTransition';
|
|
||||||
}
|
|
||||||
|
|
||||||
// options available : wrapper, overrideClass
|
|
||||||
this.transition = new transitions[transition]({
|
|
||||||
wrapper: this.wrapper,
|
|
||||||
clickedLink: el
|
|
||||||
});
|
|
||||||
|
|
||||||
this.transition.launch();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch when you trigger EVENT.READYTOAPPEND in your transition
|
|
||||||
* after newView append, launch this.change()
|
|
||||||
* @param {js dom element},
|
|
||||||
* @param {js dom element}
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
append(oldView, newView) {
|
|
||||||
|
|
||||||
newView.style.opacity = 0;
|
|
||||||
this.wrapper.appendChild(newView);
|
|
||||||
|
|
||||||
// Add these 2 rAF if you want to have the containers overlapped
|
|
||||||
// Useful with a image transition, to prevent flickering
|
|
||||||
// requestAnimationFrame(() => {
|
|
||||||
// requestAnimationFrame(() => {
|
|
||||||
newView.style.opacity = 1;
|
|
||||||
this.change(oldView, newView);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* launch after this.append(), remove modules, remove oldView and set the newView
|
|
||||||
* @param {js dom element},
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
change(oldView, newView) {
|
|
||||||
|
|
||||||
$document.triggerHandler({
|
|
||||||
type: APP_EVENT.DELETE_SCOPED_MODULES,
|
|
||||||
$scope: $pjaxWrapper
|
|
||||||
});
|
|
||||||
|
|
||||||
this.wrapper.innerHTML = newView.outerHTML;
|
|
||||||
|
|
||||||
oldView.remove();
|
|
||||||
|
|
||||||
// Fetch any inline script elements.
|
|
||||||
const scripts = newView.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.pjax.onSwitch();
|
|
||||||
|
|
||||||
this.transition.displayView(newView);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DOM is loaded
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
load() {
|
|
||||||
$html.addClass('has-dom-loaded');
|
|
||||||
$html.removeClass('has-dom-loading');
|
|
||||||
setTimeout(() => {
|
|
||||||
$html.addClass('has-dom-animated');
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export {default as BaseTransition} from './BaseTransition';
|
|
||||||
export {default as CustomTransition} from './CustomTransition';
|
|
||||||
@@ -3,10 +3,11 @@ const DATA_API_KEY = '.data-api';
|
|||||||
|
|
||||||
const $document = $(document);
|
const $document = $(document);
|
||||||
const $window = $(window);
|
const $window = $(window);
|
||||||
|
const html = document.documentElement;
|
||||||
const $html = $(document.documentElement).removeClass('has-no-js').addClass('has-js');
|
const $html = $(document.documentElement).removeClass('has-no-js').addClass('has-js');
|
||||||
const $body = $(document.body);
|
const $body = $(document.body);
|
||||||
const $pjaxWrapper = $('#js-pjax-wrapper');
|
const $pjaxWrapper = $('#js-pjax-wrapper');
|
||||||
|
|
||||||
const isDebug = !!$html.data('debug');
|
const isDebug = !!$html.data('debug');
|
||||||
|
|
||||||
export { APP_NAME, DATA_API_KEY, $document, $window, $html, $body, isDebug, $pjaxWrapper };
|
export { APP_NAME, DATA_API_KEY, $document, $window, html, $html, $body, isDebug, $pjaxWrapper };
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
@import "tools/mixins";
|
@import "tools/mixins";
|
||||||
@import "tools/fonts";
|
@import "tools/fonts";
|
||||||
@import "tools/layout";
|
@import "tools/layout";
|
||||||
// @import "tools/ratio";
|
@import "tools/widths";
|
||||||
// @import "tools/widths";
|
|
||||||
// @import "tools/family";
|
// @import "tools/family";
|
||||||
|
|
||||||
// Generic
|
// Generic
|
||||||
@@ -26,23 +25,23 @@
|
|||||||
@import "generic/form";
|
@import "generic/form";
|
||||||
@import "generic/button";
|
@import "generic/button";
|
||||||
|
|
||||||
// Base
|
// Elements
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@import "base/fonts";
|
@import "elements/fonts";
|
||||||
@import "base/page";
|
@import "elements/page";
|
||||||
@import "base/headings";
|
@import "elements/headings";
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@import "objects/container";
|
@import "objects/container";
|
||||||
// @import "objects/crop";
|
@import "objects/ratio";
|
||||||
// @import "objects/ratio";
|
|
||||||
// @import "objects/table";
|
|
||||||
@import "objects/layout";
|
@import "objects/layout";
|
||||||
@import "objects/form";
|
@import "objects/form";
|
||||||
@import "objects/button";
|
@import "objects/button";
|
||||||
@import "objects/pjax";
|
@import "objects/pjax";
|
||||||
@import "objects/scroll";
|
@import "objects/scroll";
|
||||||
|
// @import "objects/crop";
|
||||||
|
// @import "objects/table";
|
||||||
|
|
||||||
// Vendors
|
// Vendors
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -58,10 +57,11 @@
|
|||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@import "utilities/ratio";
|
||||||
|
@import "utilities/widths";
|
||||||
// @import "utilities/align";
|
// @import "utilities/align";
|
||||||
// @import "utilities/helpers";
|
// @import "utilities/helpers";
|
||||||
// @import "utilities/states";
|
// @import "utilities/states";
|
||||||
// @import "utilities/headings";
|
// @import "utilities/headings";
|
||||||
// @import "utilities/spacing";
|
// @import "utilities/spacing";
|
||||||
// @import "utilities/widths";
|
|
||||||
// @import "utilities/print";
|
// @import "utilities/print";
|
||||||
|
|||||||
@@ -2,20 +2,6 @@
|
|||||||
// Objects / Ratio
|
// Objects / Ratio
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
//
|
|
||||||
// @link https://github.com/inuitcss/inuitcss/blob/19d0c7e/objects/_objects.ratio.scss
|
|
||||||
//
|
|
||||||
|
|
||||||
// A list of aspect ratios that get generated as modifier classes.
|
|
||||||
|
|
||||||
$aspect-ratios: (
|
|
||||||
(2:1),
|
|
||||||
(4:3),
|
|
||||||
(16:9),
|
|
||||||
) !default;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create ratio-bound content blocks, to keep media (e.g. images, videos) in
|
* Create ratio-bound content blocks, to keep media (e.g. images, videos) in
|
||||||
* their correct aspect ratios.
|
* their correct aspect ratios.
|
||||||
@@ -38,6 +24,7 @@ $aspect-ratios: (
|
|||||||
}
|
}
|
||||||
|
|
||||||
.o-ratio_content,
|
.o-ratio_content,
|
||||||
|
.o-ratio > img,
|
||||||
.o-ratio > iframe,
|
.o-ratio > iframe,
|
||||||
.o-ratio > embed,
|
.o-ratio > embed,
|
||||||
.o-ratio > object {
|
.o-ratio > object {
|
||||||
@@ -46,34 +33,5 @@ $aspect-ratios: (
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
// height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stylelint-disable */
|
|
||||||
|
|
||||||
//
|
|
||||||
// Generate a series of ratio classes to be used like so:
|
|
||||||
//
|
|
||||||
// @example
|
|
||||||
// <div class="o-ratio -16:9">
|
|
||||||
//
|
|
||||||
//
|
|
||||||
.o-ratio {
|
|
||||||
@each $ratio in $aspect-ratios {
|
|
||||||
@each $antecedent, $consequent in $ratio {
|
|
||||||
@if (type-of($antecedent) != number) {
|
|
||||||
@error "`#{$antecedent}` needs to be a number."
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (type-of($consequent) != number) {
|
|
||||||
@error "`#{$consequent}` needs to be a number."
|
|
||||||
}
|
|
||||||
|
|
||||||
&.-#{$antecedent}\:#{$consequent}::before {
|
|
||||||
padding-bottom: ($consequent/$antecedent) * 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stylelint-enable */
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
// ==========================================================================
|
|
||||||
// Tools / Ratio Constraint
|
|
||||||
// ==========================================================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// A tool to restrain a container to a unitary or fractional proportion.
|
|
||||||
//
|
|
||||||
|
|
||||||
$data-ratios: "1/2" "0.5" 50%,
|
|
||||||
"11/20" "0.55" 55%,
|
|
||||||
"3/5" "0.6" 60%,
|
|
||||||
"13/20" "0.65" 65%,
|
|
||||||
"7/10" "0.7" 70%,
|
|
||||||
"3/4" "0.75" 75%,
|
|
||||||
"4/5" "0.8" 80%,
|
|
||||||
"17/20" "0.85" 85%,
|
|
||||||
"9/10" "0.9" 90%,
|
|
||||||
"19/20" "0.95" 95%,
|
|
||||||
"1/1" "1" 100%,
|
|
||||||
"21/20" "1.05" 105%,
|
|
||||||
"11/10" "1.1" 110%,
|
|
||||||
"23/20" "1.15" 115%,
|
|
||||||
"6/5" "1.2" 120%,
|
|
||||||
"5/4" "1.25" 125% !default;
|
|
||||||
$data-ratio-crops: "top" "bottom" "both" !default;
|
|
||||||
|
|
||||||
@mixin crop($crop) {
|
|
||||||
@if $crop == "top" {
|
|
||||||
bottom: 0;
|
|
||||||
} @else if $crop == "bottom" {
|
|
||||||
top: 0;
|
|
||||||
} @else if $crop == "both" {
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.u-ratio {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@each $ratio in $data-ratios {
|
|
||||||
$ratio-1: nth($ratio, 1);
|
|
||||||
$ratio-2: nth($ratio, 2);
|
|
||||||
&[data-ratio="#{$ratio-1}"]::before,
|
|
||||||
&[data-ratio="#{$ratio-2}"]::before {
|
|
||||||
padding-top: nth($ratio, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.u-ratio_content_container {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.u-ratio_content {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
@each $crop in $data-ratio-crops {
|
|
||||||
&[data-ratio-crop="#{$crop}"] {
|
|
||||||
@include crop($crop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
42
assets/styles/utilities/_ratio.scss
Normal file
42
assets/styles/utilities/_ratio.scss
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// ==========================================================================
|
||||||
|
// Utilities / Ratio
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
//
|
||||||
|
// @link https://github.com/inuitcss/inuitcss/blob/19d0c7e/objects/_objects.ratio.scss
|
||||||
|
//
|
||||||
|
|
||||||
|
// A list of aspect ratios that get generated as modifier classes.
|
||||||
|
|
||||||
|
$aspect-ratios: (
|
||||||
|
(2:1),
|
||||||
|
(4:3),
|
||||||
|
(16:9),
|
||||||
|
) !default;
|
||||||
|
|
||||||
|
/* stylelint-disable */
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generate a series of ratio classes to be used like so:
|
||||||
|
//
|
||||||
|
// @example
|
||||||
|
// <div class="o-ratio u-16:9">
|
||||||
|
//
|
||||||
|
//
|
||||||
|
@each $ratio in $aspect-ratios {
|
||||||
|
@each $antecedent, $consequent in $ratio {
|
||||||
|
@if (type-of($antecedent) != number) {
|
||||||
|
@error "`#{$antecedent}` needs to be a number."
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (type-of($consequent) != number) {
|
||||||
|
@error "`#{$consequent}` needs to be a number."
|
||||||
|
}
|
||||||
|
|
||||||
|
&.u-#{$antecedent}\:#{$consequent}::before {
|
||||||
|
padding-bottom: ($consequent/$antecedent) * 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stylelint-enable */
|
||||||
10
package.json
10
package.json
@@ -5,14 +5,14 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Locomotive <info@locomotive.ca>",
|
"author": "Locomotive <info@locomotive.ca>",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"locomotive-scroll": "git+https://git@github.com/locomotivemtl/locomotive-scroll.git",
|
"locomotive-scroll": "github:locomotivemtl/locomotive-scroll#v2",
|
||||||
|
"modujs": "*",
|
||||||
|
"modularload": "*",
|
||||||
"normalize.css": "*",
|
"normalize.css": "*",
|
||||||
"pjax": "*",
|
"svg4everybody": "*",
|
||||||
"smooth-scrollbar": "git+https://git@github.com/locomotivemtl/smooth-scrollbar.git#develop",
|
"virtual-scroll": "*"
|
||||||
"svg4everybody": "*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/polyfill": "*",
|
|
||||||
"gulp-concat": "*"
|
"gulp-concat": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
www/assets/scripts/abortcontroller-polyfill-only.js
Normal file
1
www/assets/scripts/abortcontroller-polyfill-only.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
!function(t){"function"==typeof define&&define.amd?define(t):t()}(function(){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function e(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}function i(t){return(i=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function l(t,e){return(l=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function u(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function c(t,e,n){return(c="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,n){var r=function(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=i(t)););return t}(t,e);if(r){var o=Object.getOwnPropertyDescriptor(r,e);return o.get?o.get.call(n):o.value}})(t,e,n||t)}var t,n,a=function(){function t(){r(this,t),Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}return e(t,[{key:"addEventListener",value:function(t,e){t in this.listeners||(this.listeners[t]=[]),this.listeners[t].push(e)}},{key:"removeEventListener",value:function(t,e){if(t in this.listeners)for(var n=this.listeners[t],r=0,o=n.length;r<o;r++)if(n[r]===e)return void n.splice(r,1)}},{key:"dispatchEvent",value:function(e){var n=this;if(e.type in this.listeners){for(var t=function(t){setTimeout(function(){return t.call(n,e)})},r=this.listeners[e.type],o=0,i=r.length;o<i;o++)t(r[o]);return!e.defaultPrevented}}}]),t}(),f=function(t){function n(){var t,e;return r(this,n),(t=!(e=i(n).call(this))||"object"!=typeof e&&"function"!=typeof e?u(this):e).listeners||a.call(u(t)),Object.defineProperty(u(t),"aborted",{value:!1,writable:!0,configurable:!0}),Object.defineProperty(u(t),"onabort",{value:null,writable:!0,configurable:!0}),t}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&l(t,e)}(n,a),e(n,[{key:"toString",value:function(){return"[object AbortSignal]"}},{key:"dispatchEvent",value:function(t){"abort"===t.type&&(this.aborted=!0,"function"==typeof this.onabort&&this.onabort.call(this,t)),c(i(n.prototype),"dispatchEvent",this).call(this,t)}}]),n}(),s=function(){function t(){r(this,t),Object.defineProperty(this,"signal",{value:new f,writable:!0,configurable:!0})}return e(t,[{key:"abort",value:function(){var e;try{e=new Event("abort")}catch(t){"undefined"!=typeof document?document.createEvent?(e=document.createEvent("Event")).initEvent("abort",!1,!1):(e=document.createEventObject()).type="abort":e={type:"abort",bubbles:!1,cancelable:!1}}this.signal.dispatchEvent(e)}},{key:"toString",value:function(){return"[object AbortController]"}}]),t}();"undefined"!=typeof Symbol&&Symbol.toStringTag&&(s.prototype[Symbol.toStringTag]="AbortController",f.prototype[Symbol.toStringTag]="AbortSignal"),((n=t="undefined"!=typeof self?self:global).__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),1):"function"==typeof n.Request&&!n.Request.prototype.hasOwnProperty("signal")||!n.AbortController)&&(t.AbortController=s,t.AbortSignal=f)});
|
||||||
File diff suppressed because one or more lines are too long
1
www/assets/scripts/app.js.map
Normal file
1
www/assets/scripts/app.js.map
Normal file
File diff suppressed because one or more lines are too long
2
www/assets/scripts/jquery-3.3.1.min.js
vendored
2
www/assets/scripts/jquery-3.3.1.min.js
vendored
File diff suppressed because one or more lines are too long
2
www/assets/scripts/jquery-3.4.1.min.js
vendored
Normal file
2
www/assets/scripts/jquery-3.4.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html class="has-no-js" lang="en" data-debug="true">
|
<html class="is-loading" lang="en" data-page="home">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Boilerplate</title>
|
<title>Boilerplate</title>
|
||||||
@@ -16,32 +16,38 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="assets/styles/main.css">
|
<link rel="stylesheet" href="assets/styles/main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body data-module-load>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
<a href="/"><h1>Boilerplate</h1></a>
|
||||||
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li><a href="page.html">Page</a></li>
|
||||||
<a href="/">Home</a>
|
<li><a href="page.html" data-load="customTransition">Custom page</a></li>
|
||||||
</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>
|
</ul>
|
||||||
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div id="js-pjax-wrapper">
|
<main>
|
||||||
<div class="js-pjax-container" data-template="home">
|
<div data-load-container>
|
||||||
<div class="o-scroll" data-module="Scroll">
|
<div data-module-scroll>
|
||||||
<div data-module="Example">Home page with Example module</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
<p>Home</p>
|
||||||
<script>window.jQuery || document.write('<script src="assets/scripts/jquery-3.3.1.min.js"><\/script>')</script>
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank">🚂</a></p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.4/polyfill.min.js" crossorigin="anonymous"></script>
|
||||||
|
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=fetch%2CCustomEvent%2CElement.prototype.matches" crossorigin="anonymous"></script>
|
||||||
|
<script nomodule src="assets/scripts/abortcontroller-polyfill-only.js"></script>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="assets/scripts/jquery-3.4.1.min.js"><\/script>')</script>
|
||||||
<script src="assets/scripts/vendors.js"></script>
|
<script src="assets/scripts/vendors.js"></script>
|
||||||
<script src="assets/scripts/app.js"></script>
|
<script src="assets/scripts/app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html class="has-no-js" lang="en" data-debug="true">
|
<html class="is-loading" lang="en" data-page="page">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Page | Boilerplate</title>
|
<title>Page | Boilerplate</title>
|
||||||
@@ -16,31 +16,38 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="assets/styles/main.css">
|
<link rel="stylesheet" href="assets/styles/main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body data-module-load>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
<a href="/"><h1>Boilerplate</h1></a>
|
||||||
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li><a href="page.html">Page</a></li>
|
||||||
<a href="/">Home</a>
|
<li><a href="page.html" data-load="customTransition">Custom page</a></li>
|
||||||
</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>
|
</ul>
|
||||||
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div id="js-pjax-wrapper">
|
<main>
|
||||||
<div class="js-pjax-container" data-template="page" data-transition="pageTransition">
|
<div data-load-container>
|
||||||
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 data-module-scroll>
|
||||||
|
|
||||||
|
<p>Page</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
<footer>
|
||||||
<script>window.jQuery || document.write('<script src="assets/scripts/jquery-3.2.1.min.js"><\/script>')</script>
|
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank">🚂</a></p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.4/polyfill.min.js" crossorigin="anonymous"></script>
|
||||||
|
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=fetch%2CCustomEvent%2CElement.prototype.matches" crossorigin="anonymous"></script>
|
||||||
|
<script nomodule src="assets/scripts/abortcontroller-polyfill-only.js"></script>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="assets/scripts/jquery-3.4.1.min.js"><\/script>')</script>
|
||||||
<script src="assets/scripts/vendors.js"></script>
|
<script src="assets/scripts/vendors.js"></script>
|
||||||
<script src="assets/scripts/app.js"></script>
|
<script src="assets/scripts/app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user