first
2
.browserslistrc
Normal file
@@ -0,0 +1,2 @@
|
||||
last 2 major versions
|
||||
Firefox ESR
|
||||
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*{js,pug,scss,json}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
quote_type = single
|
||||
0
.eslintignore
Normal file
197
.eslintrc.js
Normal file
@@ -0,0 +1,197 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true
|
||||
},
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
legacyDecorators: true
|
||||
}
|
||||
},
|
||||
globals: {
|
||||
$: true,
|
||||
jQuery: true,
|
||||
Plugin: true,
|
||||
__webpack_require__: true
|
||||
},
|
||||
rules: {
|
||||
// recommended
|
||||
'for-direction': 2,
|
||||
'getter-return': 2,
|
||||
'no-compare-neg-zero': 2,
|
||||
'no-cond-assign': [2, 'always'],
|
||||
'no-console': [1, {
|
||||
allow: ['warn', 'error']
|
||||
}],
|
||||
'no-constant-condition': 2,
|
||||
'no-control-regex': 1,
|
||||
'no-debugger': 1,
|
||||
'no-dupe-args': 2,
|
||||
'no-dupe-keys': 2,
|
||||
'no-duplicate-case': 2,
|
||||
'no-empty': 1,
|
||||
'no-empty-character-class': 1,
|
||||
'no-ex-assign': 2,
|
||||
'no-extra-boolean-cast': 1,
|
||||
'no-extra-semi': 2,
|
||||
'no-func-assign': 2,
|
||||
'no-inner-declarations': 2,
|
||||
'no-invalid-regexp': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-obj-calls': 2,
|
||||
'no-regex-spaces': 1,
|
||||
'no-sparse-arrays': 2,
|
||||
'no-unexpected-multiline': 2,
|
||||
'no-unreachable': 2,
|
||||
'no-unsafe-finally': 2,
|
||||
'no-unsafe-negation': 2,
|
||||
'use-isnan': 1,
|
||||
'valid-typeof': [2, {
|
||||
"requireStringLiterals": true
|
||||
}],
|
||||
'no-case-declarations': 2,
|
||||
'no-empty-pattern': 2,
|
||||
'no-fallthrough': 2,
|
||||
'no-global-assign': 2,
|
||||
'no-octal': 2,
|
||||
'no-redeclare': [2, {
|
||||
'builtinGlobals': true
|
||||
}],
|
||||
'no-self-assign': 2,
|
||||
'no-unused-labels': 1,
|
||||
'no-useless-escape': 1,
|
||||
'no-delete-var': 2,
|
||||
'no-undef': 2,
|
||||
'no-unused-vars': 1,
|
||||
'no-mixed-spaces-and-tabs': 1,
|
||||
'constructor-super': 2,
|
||||
'no-class-assign': 2,
|
||||
'no-const-assign': 2,
|
||||
'no-dupe-class-members': 2,
|
||||
'no-new-symbol': 2,
|
||||
'no-this-before-super': 2,
|
||||
'require-yield': 2,
|
||||
|
||||
// error
|
||||
'no-async-promise-executor': 2,
|
||||
'no-misleading-character-class': 2,
|
||||
'require-atomic-updates': 2,
|
||||
'accessor-pairs': 2,
|
||||
'block-scoped-var': 2,
|
||||
'curly': 2,
|
||||
'dot-location': [2, 'property'],
|
||||
'eqeqeq': [2, 'always'],
|
||||
'no-caller': 2,
|
||||
'no-eq-null': 2,
|
||||
'no-eval': 2,
|
||||
'no-implied-eval': 2,
|
||||
'no-iterator': 2,
|
||||
'no-labels': 2,
|
||||
'no-lone-blocks': 2,
|
||||
'no-loop-func': 2,
|
||||
'no-multi-str': 2,
|
||||
'no-new-func': 2,
|
||||
'no-new-wrappers': 2,
|
||||
'no-octal-escape': 2,
|
||||
'no-param-reassign': 2,
|
||||
'no-proto': 2,
|
||||
'no-return-assign': [2, 'always'],
|
||||
'no-return-await': 2,
|
||||
'no-self-compare': 2,
|
||||
'no-sequences': 2,
|
||||
'no-with': 2,
|
||||
'vars-on-top': 2,
|
||||
'wrap-iife': [2, 'inside', {
|
||||
functionPrototypeMethods: true
|
||||
}],
|
||||
'no-label-var': 2,
|
||||
'no-use-before-define': 2,
|
||||
|
||||
// Warning
|
||||
'no-await-in-loop': 1,
|
||||
'array-callback-return': 1,
|
||||
'class-methods-use-this': 1,
|
||||
'consistent-return': [1, {
|
||||
treatUndefinedAsUnspecified: true
|
||||
}],
|
||||
'dot-notation': [0, {
|
||||
allowKeywords: false
|
||||
}],
|
||||
'guard-for-in': 1,
|
||||
'no-alert': 1,
|
||||
'no-div-regex': 1,
|
||||
'no-else-return': 1,
|
||||
'no-empty-function': 1,
|
||||
'no-extra-bind': 1,
|
||||
'no-extra-label': 1,
|
||||
'no-floating-decimal': 1,
|
||||
'no-multi-spaces': [1, {
|
||||
ignoreEOLComments: true,
|
||||
exceptions: {
|
||||
Property: false,
|
||||
BinaryExpression: true,
|
||||
VariableDeclarator: true,
|
||||
ImportDeclaration: true
|
||||
}
|
||||
}],
|
||||
'no-script-url': 1,
|
||||
'no-useless-call': 1,
|
||||
'no-useless-concat': 1,
|
||||
'no-useless-return': 1,
|
||||
'no-void': 1,
|
||||
'require-await': 1,
|
||||
'no-undef-init': 1,
|
||||
'no-undefined': 1,
|
||||
|
||||
// Stylist
|
||||
'block-spacing': 1,
|
||||
'brace-style': 1,
|
||||
'comma-spacing': 1,
|
||||
'comma-style': 1,
|
||||
'computed-property-spacing': 1,
|
||||
'func-call-spacing': 1,
|
||||
'indent': [1, 2, {
|
||||
SwitchCase: 1,
|
||||
MemberExpression: 'off'
|
||||
}],
|
||||
'key-spacing': 1,
|
||||
'keyword-spacing': 1,
|
||||
'lines-between-class-members': 1,
|
||||
'max-len': [1, {
|
||||
code: 80,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
ignoreStrings: true
|
||||
}],
|
||||
'no-lonely-if': 1,
|
||||
'no-multi-assign': 1,
|
||||
'no-multiple-empty-lines': [1, {
|
||||
max: 2,
|
||||
maxEOF: 1,
|
||||
maxBOF: 0
|
||||
}],
|
||||
'no-trailing-spaces': 1,
|
||||
'no-unneeded-ternary': [1, {
|
||||
defaultAssignment: false
|
||||
}],
|
||||
'no-whitespace-before-property': 1,
|
||||
'quotes': [1, 'single', {
|
||||
allowTemplateLiterals: true
|
||||
}],
|
||||
'semi-spacing': 1,
|
||||
'semi': 1,
|
||||
'space-infix-ops': 1,
|
||||
'switch-colon-spacing': 1,
|
||||
'no-duplicate-imports': [1, {
|
||||
includeExports: true
|
||||
}],
|
||||
'no-useless-computed-key': 1,
|
||||
'no-var': 1,
|
||||
'object-shorthand': 1,
|
||||
'prefer-template': 1,
|
||||
'template-curly-spacing': 1
|
||||
}
|
||||
}
|
||||
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.json text eol=lf
|
||||
*.js text eol=lf
|
||||
*.pug text eol=lf
|
||||
*.scss text eol=lf
|
||||
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
.git
|
||||
npm-debug.log
|
||||
.publish
|
||||
.vscode
|
||||
static
|
||||
dist
|
||||
node_modules
|
||||
src/locales/*.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
.idea/
|
||||
112
README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
WEB TEMPLATE
|
||||
===================
|
||||
|
||||
Web template use es6, pug, scss
|
||||
|
||||
## 1. Installation
|
||||
```bash
|
||||
npm i
|
||||
```
|
||||
|
||||
## 2. Configuration
|
||||
- Every configuration is stored in `./gulpfile.js/config/**`
|
||||
|
||||
## 3. Constructor
|
||||
```bash
|
||||
src/
|
||||
| assets/
|
||||
| | # All files and folders (except site folder) will be copied to /dist
|
||||
| | favicon/
|
||||
| | # All content in this folder will be copied direct to /dist
|
||||
| |
|
||||
| |
|
||||
| scrips/
|
||||
| | _lib/
|
||||
| | | # Store custom libraries,
|
||||
| | | # which cannot be downloaded through npm
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | *.js # These files is the entry file to compile with webpack
|
||||
| |
|
||||
| |
|
||||
| styles/
|
||||
| | _*/
|
||||
| | | # Every files in folders have start name, is _,
|
||||
| | | # won't be compiled.
|
||||
| | | # It only use to store many libraries or variables
|
||||
| | |
|
||||
| | |
|
||||
| | $*/
|
||||
| | | # Every files in folders have start name, is $,
|
||||
| | | # won't be compiled.
|
||||
| | | # It only use to merge into apps.css
|
||||
| | |
|
||||
| | |
|
||||
| | ... # Others will be compiled to /dist/css/
|
||||
| |
|
||||
| |
|
||||
| views/
|
||||
| _*/
|
||||
| | # Every files in folders have start name, is _,
|
||||
| | # won't be compiled.
|
||||
| | # It only use to store many reusable components
|
||||
| |
|
||||
| |
|
||||
| $*/
|
||||
| | # Every files in folders have start name, is $,
|
||||
| | # won't be compiled.
|
||||
| | # It only use to store many main/page components
|
||||
| |
|
||||
| |
|
||||
| ... # Others will be compiled to /dist/
|
||||
|
|
||||
|
|
||||
gulpfile.js/
|
||||
| .... # Manage build tasks and configuration
|
||||
|
|
||||
|
|
||||
server/
|
||||
| .... # Manage server side render views
|
||||
|
|
||||
|
|
||||
dist/
|
||||
| # Store compiled html, css, js (production build)
|
||||
|
|
||||
|
|
||||
static/
|
||||
| # Store compiled css, js (work on dev)
|
||||
|
|
||||
|
|
||||
.browserslistrc
|
||||
.eslintrc.js
|
||||
.gitignore
|
||||
.gitattributes
|
||||
index.html
|
||||
package.json
|
||||
README.md
|
||||
```
|
||||
|
||||
|
||||
## 4. Tasks
|
||||
- `npm start`: Shorthand for `npm run dev`
|
||||
- `npm run dev`: Build Project + Watch + Node Server
|
||||
- `npm run build`: Build Project (min)
|
||||
- `npm run serve`: Run production local server
|
||||
|
||||
|
||||
## 5. Pug global variables
|
||||
- `$translator`: object variable get value from `app/locales/#{lang}.json`
|
||||
- `$localeName`: variable get value equal name of current using locale json
|
||||
|
||||
|
||||
## 6. JS Dynamic import path (chunks files)
|
||||
At `src/views/_layouts/layout.pug`, there is a script with variable `staticJsAssetsPath`, update that variable to server js path, and it will load correctly chunks files
|
||||
|
||||
|
||||
## 7. Single language mode
|
||||
Just remove folder `src/locales`
|
||||
|
||||
|
||||
## 8. Site favicon
|
||||
Use this online tool: https://realfavicongenerator.net/ to get the site favicon package and put it in `app/assets/site`
|
||||
13
babel.config.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-runtime", {
|
||||
"helpers": true,
|
||||
"regenerator": true,
|
||||
"version": "^7.7.4"
|
||||
}],
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-proposal-class-properties", { "loose": false }],
|
||||
"@babel/plugin-proposal-private-methods"
|
||||
]
|
||||
}
|
||||
20
gulpfile.js/config/browser-sync-prod.js
Normal file
@@ -0,0 +1,20 @@
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const compression = require('compression');
|
||||
|
||||
const { output } = require('./directories');
|
||||
const server = require('./server');
|
||||
|
||||
module.exports = {
|
||||
server: output,
|
||||
port: server.PROD_PORT,
|
||||
ui: {
|
||||
port: server.PROD_DASHBOARD_PORT,
|
||||
},
|
||||
open: 'local',
|
||||
ghostMode: false,
|
||||
logPrefix: 'SYNC',
|
||||
middleware: [
|
||||
compression(),
|
||||
],
|
||||
};
|
||||
12
gulpfile.js/config/browser-sync.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const server = require('./server');
|
||||
|
||||
module.exports = {
|
||||
port: server.DEV_PORT,
|
||||
proxy: `http://localhost:${server.STATIC_PORT}`,
|
||||
ui: {
|
||||
port: server.DASHBOARD_PORT,
|
||||
},
|
||||
open: true,
|
||||
ghostMode: false,
|
||||
logPrefix: 'SYNC',
|
||||
};
|
||||
77
gulpfile.js/config/directories.js
Normal file
@@ -0,0 +1,77 @@
|
||||
const { addPath } = require('../utils');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const ignoreTemplate = ['$*/**/*', '_*/**/*'];
|
||||
|
||||
const nodeModules = 'node_modules/';
|
||||
exports.nodeModules = nodeModules;
|
||||
|
||||
const src = 'src/';
|
||||
exports.src = src;
|
||||
|
||||
const dest = 'static/';
|
||||
const dist = 'dist/';
|
||||
const output = isProduction ? dist : dest;
|
||||
exports.output = output;
|
||||
|
||||
const srcLocales = `${src}locales/`;
|
||||
exports.srcLocales = srcLocales;
|
||||
|
||||
const srcAsset = `${src}assets/`;
|
||||
exports.srcAsset = srcAsset;
|
||||
|
||||
const filesCopy = addPath(srcAsset, '**', 'favicon/**');
|
||||
const filesFavicon = addPath(srcAsset, 'favicon/**');
|
||||
const filesAssets = filesCopy
|
||||
.concat(filesFavicon)
|
||||
.concat(isProduction ? 'index.html' : []);
|
||||
exports.filesAssets = filesAssets;
|
||||
|
||||
const srcScript = `${src}scripts/`;
|
||||
exports.srcScript = srcScript;
|
||||
|
||||
const filesJs = addPath(srcScript, '**/*.js', ignoreTemplate);
|
||||
exports.filesJs = filesJs;
|
||||
|
||||
const filesJsES6 = `${srcScript}*.js`;
|
||||
exports.filesJsES6 = filesJsES6;
|
||||
|
||||
const outputScript = `${output}js/`;
|
||||
exports.outputScript = outputScript;
|
||||
|
||||
const outputChunkScripts = `${outputScript}chunks/`;
|
||||
exports.outputChunkScripts = outputChunkScripts;
|
||||
|
||||
const filesChunkJs = addPath(outputChunkScripts, '*.js', '*.backup.js');
|
||||
exports.filesChunkJs = filesChunkJs;
|
||||
|
||||
const srcStyle = `${src}styles/`;
|
||||
exports.srcStyle = srcStyle;
|
||||
|
||||
const filesScssBuilt = addPath(
|
||||
srcStyle,
|
||||
'**/*.scss',
|
||||
['$*/**/*.scss', '_*/**/*.scss'],
|
||||
);
|
||||
exports.filesScssBuilt = filesScssBuilt;
|
||||
|
||||
const filesScssPartial = addPath(
|
||||
srcStyle,
|
||||
['$*/**/*.scss', '_*/**/*.scss'],
|
||||
);
|
||||
exports.filesScssPartial = filesScssPartial;
|
||||
|
||||
const outputStyle = `${output}css/`;
|
||||
exports.outputStyle = outputStyle;
|
||||
|
||||
const filesCssBuilt = addPath(outputStyle, '*.css', '*-rtl.css');
|
||||
exports.filesCssBuilt = filesCssBuilt;
|
||||
|
||||
const srcView = `${src}views/`;
|
||||
exports.srcView = srcView;
|
||||
|
||||
const filesPugBuilt = addPath(srcView, '**/*.pug', ['$*/**/*', '_*/**/*']);
|
||||
exports.filesPugBuilt = filesPugBuilt;
|
||||
|
||||
const filesPug = addPath(srcView, '**/*.pug');
|
||||
exports.filesPug = filesPug;
|
||||
8
gulpfile.js/config/externals-js.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const { srcScript } = require('./directories');
|
||||
|
||||
const libPath = `${srcScript}_libs/`;
|
||||
|
||||
module.exports = [
|
||||
`${libPath}modernizr-custom-3.6.0.js`,
|
||||
`node_modules/detectizr/dist/detectizr.js`,
|
||||
];
|
||||
6
gulpfile.js/config/nodemon.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
script: 'server/index.js',
|
||||
watch: [
|
||||
'server/',
|
||||
],
|
||||
};
|
||||
4
gulpfile.js/config/pug.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
pretty: true,
|
||||
doctype: 'html',
|
||||
};
|
||||
11
gulpfile.js/config/rename.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
rtl: {
|
||||
suffix: '-rtl',
|
||||
},
|
||||
min: {
|
||||
suffix: '.min',
|
||||
},
|
||||
backup: {
|
||||
suffix: '.backup',
|
||||
},
|
||||
};
|
||||
3
gulpfile.js/config/sass.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
outputStyle: 'expanded',
|
||||
};
|
||||
20
gulpfile.js/config/server.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const PORT = 4999;
|
||||
|
||||
module.exports = {
|
||||
PROD_PORT: 8080,
|
||||
STATIC_PORT: PORT,
|
||||
|
||||
get DEV_PORT() {
|
||||
return this.STATIC_PORT + 1;
|
||||
},
|
||||
|
||||
get DASHBOARD_PORT() {
|
||||
return this.STATIC_PORT - 1;
|
||||
},
|
||||
|
||||
get PROD_DASHBOARD_PORT() {
|
||||
return this.PROD_PORT - 1;
|
||||
},
|
||||
|
||||
DEFAULT_LANG: 'en',
|
||||
};
|
||||
9
gulpfile.js/config/usemin.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Change this value to false if you don't wanna use cache
|
||||
const { DEFAULT_LANG } = require('./server');
|
||||
|
||||
module.exports = {
|
||||
css: `dist/css/styles.min.css?v=${Date.now()}`,
|
||||
'css-rtl': `dist/css/styles-rtl.min.css?v=${Date.now()}`,
|
||||
js: `dist/js/scripts.min.js?v=${Date.now()}`,
|
||||
redirect: `<meta http-equiv="refresh" content="0;url=./${DEFAULT_LANG}/sitemap.html">`,
|
||||
};
|
||||
51
gulpfile.js/config/webpack.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/* eslint-disable-next-line */
|
||||
const { resolve, join } = require('path');
|
||||
const { ProvidePlugin } = require('webpack');
|
||||
|
||||
const { srcScript, output, outputScript } = require('./directories');
|
||||
|
||||
const nodeEnv = process.env.NODE_ENV;
|
||||
const isDevelopment = nodeEnv === 'development';
|
||||
|
||||
module.exports = {
|
||||
mode: 'none',
|
||||
context: join(__dirname, '../../', output),
|
||||
output: {
|
||||
path: join(__dirname, '../../', outputScript),
|
||||
filename: '[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(srcScript),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new ProvidePlugin({
|
||||
Plugin: ['@/cores/plugin', 'default'],
|
||||
jQuery: 'jquery', // replace by using external jquery
|
||||
$: ['jquery'],
|
||||
}),
|
||||
],
|
||||
optimization: {
|
||||
nodeEnv,
|
||||
chunkIds: 'total-size',
|
||||
concatenateModules: true,
|
||||
flagIncludedChunks: true,
|
||||
moduleIds: 'size',
|
||||
sideEffects: true,
|
||||
splitChunks: false,
|
||||
},
|
||||
devtool: isDevelopment && 'source-map',
|
||||
};
|
||||
11
gulpfile.js/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const requireDir = require('require-dir');
|
||||
|
||||
const task = process.argv[2];
|
||||
|
||||
process.env.NODE_ENV = ~['build'].indexOf(task) ? 'production' : 'development';
|
||||
|
||||
const tasks = requireDir('./tasks');
|
||||
|
||||
Object.keys(tasks).forEach((name) => {
|
||||
exports[name] = tasks[name];
|
||||
});
|
||||
15
gulpfile.js/private-tasks/backup--chunk-scripts.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const rename = require('gulp-rename');
|
||||
|
||||
const { filesChunkJs, outputChunkScripts } = require('../config/directories');
|
||||
const { backup } = require('../config/rename');
|
||||
|
||||
function backupChunkScripts() {
|
||||
return src(filesChunkJs)
|
||||
.pipe(rename(backup))
|
||||
.pipe(dest(outputChunkScripts));
|
||||
}
|
||||
|
||||
backupChunkScripts.displayName = 'backup:chunk-scripts';
|
||||
|
||||
module.exports = backupChunkScripts;
|
||||
20
gulpfile.js/private-tasks/build--assets.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { series } = require('gulp');
|
||||
const buildLocales = require('./build--locales');
|
||||
const copyAssets = require('./copy--assets');
|
||||
const lintScripts = require('./lint--scripts');
|
||||
const buildScriptsES6 = require('./build--scripts-es6');
|
||||
const buildScriptsExternal = require('./build--scripts-external');
|
||||
const buildStyles = require('./build--styles');
|
||||
const buildStylesRtl = require('./build--styles-rtl');
|
||||
|
||||
const buildAssets = series(
|
||||
buildLocales,
|
||||
copyAssets,
|
||||
lintScripts,
|
||||
buildScriptsES6,
|
||||
buildScriptsExternal,
|
||||
buildStyles,
|
||||
buildStylesRtl,
|
||||
);
|
||||
|
||||
module.exports = buildAssets;
|
||||
37
gulpfile.js/private-tasks/build--locales.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const { src, dest, parallel } = require('gulp');
|
||||
const merge = require('gulp-merge-json');
|
||||
|
||||
const { srcLocales } = require('../config/directories');
|
||||
const { getFolders } = require('../utils');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function generateBuildTmpFn(folder) {
|
||||
function buildLocale() {
|
||||
return src(`${srcLocales}/${folder}/**/*.json`)
|
||||
.pipe(merge({
|
||||
fileName: `${folder}.json`,
|
||||
jsonSpace: ' ',
|
||||
}))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(srcLocales));
|
||||
}
|
||||
|
||||
buildLocale.displayName = `build:locale:${folder}`;
|
||||
|
||||
return buildLocale;
|
||||
}
|
||||
|
||||
function buildLocales(cb) {
|
||||
const folders = getFolders(srcLocales);
|
||||
|
||||
if (folders[0]) {
|
||||
process.env.MULTI_LANGUAGE = folders;
|
||||
return parallel(...folders.map(generateBuildTmpFn))(cb);
|
||||
}
|
||||
|
||||
return cb();
|
||||
}
|
||||
|
||||
buildLocales.displayName = 'build:locales';
|
||||
|
||||
module.exports = buildLocales;
|
||||
24
gulpfile.js/private-tasks/build--scripts-es6.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const gulpWebpack = require('webpack-stream');
|
||||
const webpack = require('webpack');
|
||||
const vinylNamed = require('vinyl-named');
|
||||
|
||||
const { filesJsES6, outputScript } = require('../config/directories');
|
||||
const option = require('../config/webpack');
|
||||
const { list, handleError } = require('../utils/errors');
|
||||
|
||||
function buildScriptsES6(cb) {
|
||||
if (!list.isJSValid) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
return src(filesJsES6)
|
||||
.pipe(vinylNamed())
|
||||
.pipe(gulpWebpack(option, webpack))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputScript));
|
||||
}
|
||||
|
||||
buildScriptsES6.displayName = 'build:scripts-es6';
|
||||
|
||||
module.exports = buildScriptsES6;
|
||||
22
gulpfile.js/private-tasks/build--scripts-external.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const concat = require('gulp-concat');
|
||||
|
||||
const jsExternalPaths = require('../config/externals-js');
|
||||
const { outputScript } = require('../config/directories');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||
|
||||
/**
|
||||
* Building libraries scripts
|
||||
*/
|
||||
function buildScriptsExternal () {
|
||||
return src(jsExternalPaths, { sourcemaps: isDevelopment })
|
||||
.pipe(concat('externals.js'))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputScript, { sourcemaps: isDevelopment && '.' }));
|
||||
}
|
||||
|
||||
buildScriptsExternal.displayName = 'build:scripts-external';
|
||||
|
||||
module.exports = buildScriptsExternal;
|
||||
27
gulpfile.js/private-tasks/build--styles-rtl.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const { src, dest, lastRun } = require('gulp');
|
||||
const rtlcss = require('gulp-rtlcss');
|
||||
const rename = require('gulp-rename');
|
||||
|
||||
const {
|
||||
outputStyle,
|
||||
filesCssBuilt,
|
||||
} = require('../config/directories');
|
||||
const { rtl: renameOpts } = require('../config/rename');
|
||||
const browserSync = require('../utils/browser-sync');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function buildStylesRtl() {
|
||||
return src(filesCssBuilt, {
|
||||
since: lastRun(buildStylesRtl),
|
||||
})
|
||||
.pipe(rtlcss())
|
||||
.on('error', handleError)
|
||||
.pipe(rename(renameOpts))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputStyle))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
buildStylesRtl.displayName = 'build:styles-rtl';
|
||||
|
||||
module.exports = buildStylesRtl;
|
||||
35
gulpfile.js/private-tasks/build--styles.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const { src, dest } = require('gulp');
|
||||
// const sass = require('sass');
|
||||
// const gulpSass = require('gulp-sass');
|
||||
const sass = require('gulp-sass')(require('sass'));
|
||||
const cached = require('gulp-cached');
|
||||
const sassUnicode = require('gulp-sass-unicode');
|
||||
const autoprefixer = require('gulp-autoprefixer');
|
||||
// const header = require('gulp-header');
|
||||
|
||||
// gulpSass.compiler = sass;
|
||||
|
||||
const {
|
||||
filesScssBuilt,
|
||||
outputStyle,
|
||||
} = require('../config/directories');
|
||||
const sassOpts = require('../config/sass');
|
||||
const browserSync = require('../utils/browser-sync');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function buildStyles() {
|
||||
return src(filesScssBuilt)
|
||||
.pipe(cached('scss'))
|
||||
.pipe(sass(sassOpts))
|
||||
.on('error', handleError)
|
||||
.pipe(sassUnicode())
|
||||
.on('error', handleError)
|
||||
.pipe(autoprefixer())
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputStyle))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
buildStyles.displayName = 'build:styles';
|
||||
|
||||
module.exports = buildStyles;
|
||||
20
gulpfile.js/private-tasks/build--views-min.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
const gulp = require('gulp');
|
||||
const htmlReplace = require('gulp-html-replace');
|
||||
|
||||
const useminOpts = require('../config/usemin');
|
||||
const { output } = require('../config/directories');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function buildViewsMin() {
|
||||
return gulp
|
||||
.src(`${output}**/*.html`)
|
||||
.pipe(htmlReplace(useminOpts, {
|
||||
resolvePaths: true,
|
||||
}))
|
||||
.on('error', handleError)
|
||||
.pipe(gulp.dest(output));
|
||||
}
|
||||
|
||||
buildViewsMin.displayName = 'build:views-min';
|
||||
|
||||
module.exports = buildViewsMin;
|
||||
47
gulpfile.js/private-tasks/build--views.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const { src, dest, parallel } = require('gulp');
|
||||
const pug = require('gulp-pug');
|
||||
|
||||
const { srcLocales, filesPugBuilt, output } = require('../config/directories');
|
||||
const options = require('../config/pug');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function generateBuildTmpFn(lang) {
|
||||
let outputPath = output;
|
||||
const pugOpts = {
|
||||
...options,
|
||||
locals: {
|
||||
$translator: {},
|
||||
$localeName: lang,
|
||||
},
|
||||
};
|
||||
|
||||
if (lang) {
|
||||
outputPath = `${output + lang}/`;
|
||||
/* eslint-disable-next-line */
|
||||
pugOpts.locals.$translator = require(`../../${srcLocales + lang}.json`);
|
||||
}
|
||||
|
||||
function buildView() {
|
||||
return src(filesPugBuilt)
|
||||
.pipe(pug(pugOpts))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputPath));
|
||||
}
|
||||
|
||||
buildView.displayName = `build:views:${lang || 'single-lang'}`;
|
||||
return buildView;
|
||||
}
|
||||
|
||||
function buildViews(cb) {
|
||||
const folders = process.env.MULTI_LANGUAGE;
|
||||
|
||||
if (folders) {
|
||||
return parallel(...folders.split(',').map(generateBuildTmpFn))(cb);
|
||||
}
|
||||
|
||||
return generateBuildTmpFn()();
|
||||
}
|
||||
|
||||
buildViews.displayName = 'build:views';
|
||||
|
||||
module.exports = buildViews;
|
||||
27
gulpfile.js/private-tasks/bundle--scripts.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const concat = require('gulp-concat');
|
||||
const rename = require('gulp-rename');
|
||||
const uglify = require('gulp-uglify');
|
||||
|
||||
const { outputScript } = require('../config/directories');
|
||||
const { handleError } = require('../utils/errors');
|
||||
const { min } = require('../config/rename');
|
||||
|
||||
function bundleScripts() {
|
||||
return src([`${outputScript}externals.js`, `${outputScript}*.js`])
|
||||
.pipe(concat('scripts.js'))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputScript))
|
||||
.pipe(rename(min))
|
||||
.pipe(uglify({
|
||||
mangle: {
|
||||
keep_fnames: true,
|
||||
},
|
||||
}))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputScript));
|
||||
}
|
||||
|
||||
bundleScripts.displayName = 'bundle:scripts';
|
||||
|
||||
module.exports = bundleScripts;
|
||||
25
gulpfile.js/private-tasks/bundle--styles.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const concat = require('gulp-concat');
|
||||
|
||||
const { outputStyle } = require('../config/directories');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function bundleStyles(isRTL) {
|
||||
const suffix = isRTL ? '-rtl' : '';
|
||||
const libsCss = `${outputStyle}$libs${suffix}.css`;
|
||||
const appsCss = `${outputStyle}apps${suffix}.css`;
|
||||
const concatCss = `styles${suffix}.css`;
|
||||
|
||||
function bundleStyle() {
|
||||
return src([libsCss, appsCss])
|
||||
.pipe(concat(concatCss))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputStyle));
|
||||
}
|
||||
|
||||
bundleStyle.displayName = `bundle:styles:${isRTL ? 'rtl' : 'origin'}`;
|
||||
|
||||
return bundleStyle;
|
||||
}
|
||||
|
||||
module.exports = bundleStyles;
|
||||
9
gulpfile.js/private-tasks/clean--output.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const del = require('del');
|
||||
|
||||
const { output } = require('../config/directories');
|
||||
|
||||
const cleanOutput = () => del(output);
|
||||
|
||||
cleanOutput.displayName = 'clean:output';
|
||||
|
||||
module.exports = cleanOutput;
|
||||
14
gulpfile.js/private-tasks/clean--temp-scripts.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const del = require('del');
|
||||
|
||||
const { outputScript } = require('../config/directories');
|
||||
|
||||
const cleanTempScripts = () => del([
|
||||
`${outputScript}*.js`,
|
||||
`${outputScript}*.map`,
|
||||
`!${outputScript}scripts.js`,
|
||||
`!${outputScript}scripts.min.js`,
|
||||
]);
|
||||
|
||||
cleanTempScripts.displayName = 'clean:temp-scripts';
|
||||
|
||||
module.exports = cleanTempScripts;
|
||||
14
gulpfile.js/private-tasks/clean--temp-styles.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const del = require('del');
|
||||
|
||||
const { outputStyle } = require('../config/directories');
|
||||
|
||||
const cleanTempStyles = () => del([
|
||||
`${outputStyle}$libs.css`,
|
||||
`${outputStyle}$libs-rtl.css`,
|
||||
`${outputStyle}apps.css`,
|
||||
`${outputStyle}apps-rtl.css`,
|
||||
]);
|
||||
|
||||
cleanTempStyles.displayName = 'clean:temp-styles';
|
||||
|
||||
module.exports = cleanTempStyles;
|
||||
12
gulpfile.js/private-tasks/copy--assets.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const { src, dest, lastRun } = require('gulp');
|
||||
const { filesAssets, output } = require('../config/directories');
|
||||
|
||||
function copyAssets() {
|
||||
return src(filesAssets, {
|
||||
since: lastRun(copyAssets),
|
||||
}).pipe(dest(output));
|
||||
}
|
||||
|
||||
copyAssets.displayName = 'copy:assets';
|
||||
|
||||
module.exports = copyAssets;
|
||||
26
gulpfile.js/private-tasks/lint--scripts.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { src } = require('gulp');
|
||||
const eslint = require('gulp-eslint');
|
||||
const cached = require('gulp-cached');
|
||||
|
||||
const { filesJs } = require('../config/directories');
|
||||
const { handleESLintError } = require('../utils/errors');
|
||||
const stream = require('../utils/browser-sync');
|
||||
|
||||
function lintScripts() {
|
||||
const gulpInstance = src(filesJs)
|
||||
.pipe(cached('eslint'))
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.results(handleESLintError));
|
||||
|
||||
if (stream.isStreaming) {
|
||||
return gulpInstance;
|
||||
}
|
||||
|
||||
return gulpInstance
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failOnError());
|
||||
}
|
||||
|
||||
lintScripts.displayName = 'lint:scripts';
|
||||
|
||||
module.exports = lintScripts;
|
||||
20
gulpfile.js/private-tasks/minify--chunk-scripts.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const uglify = require('gulp-uglify');
|
||||
|
||||
const { filesChunkJs, outputChunkScripts } = require('../config/directories');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function minifyChunkScripts() {
|
||||
return src(filesChunkJs)
|
||||
.pipe(uglify({
|
||||
mangle: {
|
||||
keep_fnames: true,
|
||||
},
|
||||
}))
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputChunkScripts));
|
||||
}
|
||||
|
||||
minifyChunkScripts.displayName = 'minify:chunk-scripts';
|
||||
|
||||
module.exports = minifyChunkScripts;
|
||||
19
gulpfile.js/private-tasks/minify--styles.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const rename = require('gulp-rename');
|
||||
const cleanCss = require('gulp-clean-css');
|
||||
|
||||
const { outputStyle } = require('../config/directories');
|
||||
const { min } = require('../config/rename');
|
||||
const { handleError } = require('../utils/errors');
|
||||
|
||||
function minifyStyles() {
|
||||
return src(`${outputStyle}**/*.css`)
|
||||
.pipe(rename(min))
|
||||
.pipe(cleanCss())
|
||||
.on('error', handleError)
|
||||
.pipe(dest(outputStyle));
|
||||
}
|
||||
|
||||
minifyStyles.displayName = 'minify:styles';
|
||||
|
||||
module.exports = minifyStyles;
|
||||
64
gulpfile.js/private-tasks/print--results.js
Normal file
@@ -0,0 +1,64 @@
|
||||
const notify = require('gulp-notify');
|
||||
const stripIndent = require('strip-indent');
|
||||
|
||||
const { pluralText } = require('../utils');
|
||||
const errors = require('../utils/errors');
|
||||
|
||||
const { log } = console;
|
||||
|
||||
notify.logLevel(0);
|
||||
|
||||
function printResults(cb) {
|
||||
const errList = errors.list;
|
||||
const {
|
||||
totalError, totalWarning, totalIssue, data,
|
||||
} = errList;
|
||||
const errorString = `${totalError} ${pluralText('error', totalError)}`;
|
||||
const warningString = `${totalWarning} ${pluralText('warning', totalWarning)}`;
|
||||
const resultString = `The project has ${errorString} & ${warningString}`;
|
||||
const resultStr = resultString; // Improve Performance Node
|
||||
const dashChar = ''.padEnd(resultStr.length + 4, '=');
|
||||
|
||||
log(stripIndent(`
|
||||
${dashChar}
|
||||
|
||||
${resultStr}
|
||||
|
||||
${dashChar}
|
||||
`));
|
||||
|
||||
if (!totalIssue) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
const infoLogs = stripIndent(data.map(({
|
||||
message, code, title, type,
|
||||
}, i) => {
|
||||
if (type !== 'Warning') {
|
||||
notify.onError({
|
||||
title,
|
||||
message,
|
||||
})();
|
||||
}
|
||||
|
||||
return `
|
||||
---[ ${type} ${i + 1} ]-------------------------
|
||||
| Path : ${message}
|
||||
| ${code}
|
||||
`;
|
||||
}).join(`
|
||||
`));
|
||||
|
||||
log((`
|
||||
${infoLogs}
|
||||
${dashChar}
|
||||
`).replace(/^ {2}/gm, ''));
|
||||
|
||||
errors.resetError();
|
||||
|
||||
return cb();
|
||||
}
|
||||
|
||||
printResults.displayName = 'print:results';
|
||||
|
||||
module.exports = printResults;
|
||||
10
gulpfile.js/private-tasks/reload.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const browserSync = require('../utils/browser-sync');
|
||||
|
||||
function reload(cb) {
|
||||
browserSync.reload();
|
||||
cb();
|
||||
}
|
||||
|
||||
reload.displayName = 'reload';
|
||||
|
||||
module.exports = reload;
|
||||
8
gulpfile.js/private-tasks/run--dev-server.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const { parallel } = require('gulp');
|
||||
|
||||
const runViews = require('./run--views');
|
||||
const runWatchers = require('./run--watchers');
|
||||
|
||||
const runDevServer = parallel(runViews, runWatchers);
|
||||
|
||||
module.exports = runDevServer;
|
||||
35
gulpfile.js/private-tasks/run--views.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const nodemon = require('gulp-nodemon');
|
||||
|
||||
const browserSync = require('../utils/browser-sync');
|
||||
const options = require('../config/nodemon');
|
||||
const browserSyncOpts = require('../config/browser-sync');
|
||||
|
||||
function runViews(cb) {
|
||||
let started = false;
|
||||
|
||||
nodemon({
|
||||
...options,
|
||||
env: {
|
||||
MULTI_LANGUAGE: process.env.MULTI_LANGUAGE,
|
||||
},
|
||||
})
|
||||
.on('start', () => {
|
||||
if (started) {
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
started = true;
|
||||
|
||||
setTimeout(() => {
|
||||
browserSync.isStreaming = true;
|
||||
browserSync.init(browserSyncOpts);
|
||||
|
||||
cb();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
runViews.displayName = 'run:views';
|
||||
|
||||
module.exports = runViews;
|
||||
71
gulpfile.js/private-tasks/run--watchers.js
Normal file
@@ -0,0 +1,71 @@
|
||||
const { series, parallel, watch } = require('gulp');
|
||||
const cached = require('gulp-cached');
|
||||
|
||||
const reload = require('./reload');
|
||||
const buildLocales = require('./build--locales');
|
||||
const printResults = require('./print--results');
|
||||
const buildStyles = require('./build--styles');
|
||||
const buildScriptsExternal = require('./build--scripts-external');
|
||||
const lintScripts = require('./lint--scripts');
|
||||
const buildScriptsES6 = require('./build--scripts-es6');
|
||||
const copyAssets = require('./copy--assets');
|
||||
|
||||
const {
|
||||
filesPug,
|
||||
srcLocales,
|
||||
filesScssBuilt,
|
||||
filesScssPartial,
|
||||
filesJs,
|
||||
filesAssets,
|
||||
} = require('../config/directories');
|
||||
const jsExternalPaths = require('../config/externals-js');
|
||||
|
||||
function runWatchers(cb) {
|
||||
const reloadAndShowResults = parallel(printResults, reload);
|
||||
|
||||
// HTML --------------------
|
||||
watch(filesPug, reload);
|
||||
|
||||
// LOCALE --------------------
|
||||
watch(`${srcLocales}*/*.json`, series(
|
||||
buildLocales,
|
||||
reloadAndShowResults,
|
||||
));
|
||||
|
||||
// CSS --------------------
|
||||
watch(filesScssBuilt, series(
|
||||
buildStyles,
|
||||
printResults,
|
||||
));
|
||||
|
||||
watch(filesScssPartial, series(
|
||||
buildStyles,
|
||||
printResults,
|
||||
)).on('change', () => delete cached.caches.scss);
|
||||
|
||||
// JS --------------------
|
||||
watch(jsExternalPaths, series(
|
||||
buildScriptsExternal,
|
||||
reloadAndShowResults
|
||||
));
|
||||
|
||||
watch(filesJs, series(
|
||||
lintScripts,
|
||||
buildScriptsES6,
|
||||
reloadAndShowResults,
|
||||
));
|
||||
|
||||
// ASSETS --------------------
|
||||
watch(filesAssets, series(
|
||||
copyAssets,
|
||||
reloadAndShowResults,
|
||||
));
|
||||
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
runWatchers.displayName = 'run:watchers';
|
||||
|
||||
module.exports = runWatchers;
|
||||
15
gulpfile.js/private-tasks/versionfy.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const { src, dest } = require('gulp');
|
||||
const header = require('gulp-header');
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
const { outputScript, outputStyle } = require('../config/directories');
|
||||
|
||||
function versionfy() {
|
||||
return src([`${outputScript}/**/*.js`, `${outputStyle}/**/*.css`])
|
||||
.pipe(header(`/* version: ${dayjs().format('DD-MM-YYYY HH:mm:ss')} */`))
|
||||
.pipe(dest((file) => file.base));
|
||||
}
|
||||
|
||||
versionfy.displayName = 'versionfy';
|
||||
|
||||
module.exports = versionfy;
|
||||
34
gulpfile.js/tasks/build.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const { series } = require('gulp');
|
||||
|
||||
const cleanOutput = require('../private-tasks/clean--output');
|
||||
const buildAssets = require('../private-tasks/build--assets');
|
||||
const bundleScripts = require('../private-tasks/bundle--scripts');
|
||||
const cleanTempScripts = require('../private-tasks/clean--temp-scripts');
|
||||
const backupChunkScripts = require('../private-tasks/backup--chunk-scripts');
|
||||
const minifyChunkScripts = require('../private-tasks/minify--chunk-scripts');
|
||||
const bundleStyles = require('../private-tasks/bundle--styles');
|
||||
const cleanTempStyles = require('../private-tasks/clean--temp-styles');
|
||||
const minifyStyles = require('../private-tasks/minify--styles');
|
||||
const versionfy = require('../private-tasks/versionfy');
|
||||
const buildViews = require('../private-tasks/build--views');
|
||||
const buildViewsMin = require('../private-tasks/build--views-min');
|
||||
const printResults = require('../private-tasks/print--results');
|
||||
|
||||
const tasks = [
|
||||
cleanOutput,
|
||||
buildAssets,
|
||||
bundleScripts,
|
||||
cleanTempScripts,
|
||||
backupChunkScripts,
|
||||
minifyChunkScripts,
|
||||
bundleStyles(),
|
||||
bundleStyles(true),
|
||||
cleanTempStyles,
|
||||
minifyStyles,
|
||||
versionfy,
|
||||
buildViews,
|
||||
buildViewsMin,
|
||||
printResults,
|
||||
];
|
||||
|
||||
module.exports = series(...tasks);
|
||||
15
gulpfile.js/tasks/default.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const { series } = require('gulp');
|
||||
|
||||
const cleanOutput = require('../private-tasks/clean--output');
|
||||
const buildAssets = require('../private-tasks/build--assets');
|
||||
const printResults = require('../private-tasks/print--results');
|
||||
const runDevServer = require('../private-tasks/run--dev-server');
|
||||
|
||||
const tasks = [
|
||||
cleanOutput,
|
||||
buildAssets,
|
||||
printResults,
|
||||
runDevServer,
|
||||
];
|
||||
|
||||
module.exports = series(...tasks);
|
||||
7
gulpfile.js/utils/browser-sync.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const browserSync = require('browser-sync');
|
||||
|
||||
const browserSyncInstance = browserSync.create();
|
||||
|
||||
browserSyncInstance.isStreaming = false;
|
||||
|
||||
module.exports = browserSyncInstance;
|
||||
63
gulpfile.js/utils/errors.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const cached = require('gulp-cached');
|
||||
|
||||
const list = {
|
||||
get totalIssue() {
|
||||
return this.totalError + this.totalWarning;
|
||||
},
|
||||
};
|
||||
exports.list = list;
|
||||
|
||||
function pushError(info) {
|
||||
list.data.push(info);
|
||||
list[info.type === 'Error' ? 'totalError' : 'totalWarning'] += 1;
|
||||
}
|
||||
|
||||
function handleError({ plugin, message, codeFrame = '' } = {}) {
|
||||
pushError({
|
||||
type: 'Error',
|
||||
plugin: plugin.toUpperCase(),
|
||||
message: message.trim(),
|
||||
code: codeFrame,
|
||||
});
|
||||
|
||||
if (typeof this.emit === 'function') {
|
||||
this.emit('end');
|
||||
} else if (typeof this === 'function') {
|
||||
this();
|
||||
}
|
||||
}
|
||||
|
||||
exports.handleError = handleError;
|
||||
|
||||
exports.handleESLintError = (results) => {
|
||||
results.forEach(({ filePath, messages } = {}) => {
|
||||
messages.forEach(({
|
||||
severity, line, column, message,
|
||||
} = {}) => {
|
||||
const type = severity === 2 ? 'Error' : 'Warning';
|
||||
|
||||
pushError({
|
||||
type,
|
||||
plugin: `ES Lint ${type}`,
|
||||
message: filePath,
|
||||
code: `[${line}:${column}] ${message}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
list.isJSValid = !results.errorCount;
|
||||
|
||||
if (results.errorCount || results.warningCount) {
|
||||
delete cached.caches.eslint;
|
||||
}
|
||||
};
|
||||
|
||||
function resetError() {
|
||||
list.data = [];
|
||||
list.totalError = 0;
|
||||
list.totalWarning = 0;
|
||||
list.isJSValid = true;
|
||||
}
|
||||
exports.resetError = resetError;
|
||||
|
||||
resetError();
|
||||
46
gulpfile.js/utils/index.js
Normal file
@@ -0,0 +1,46 @@
|
||||
const { readdirSync, lstatSync } = require('fs');
|
||||
|
||||
const pushPath = (src, paths, wontInclude) => {
|
||||
const not = wontInclude ? '!' : '';
|
||||
|
||||
return [].concat(paths || []).map((item) => not + src + item);
|
||||
};
|
||||
|
||||
exports.addPath = (src, paths, notIncludePaths) => {
|
||||
if (typeof src === 'undefined') {
|
||||
return '**/*';
|
||||
}
|
||||
|
||||
if (typeof paths === 'undefined') {
|
||||
return `${src}**/*`;
|
||||
}
|
||||
|
||||
const includePaths = pushPath(src, paths, false);
|
||||
const notICPath = pushPath(src, notIncludePaths, true);
|
||||
|
||||
return includePaths.concat(notICPath);
|
||||
};
|
||||
|
||||
exports.getFolders = (dir) => {
|
||||
try {
|
||||
return readdirSync(dir)
|
||||
.filter((folder) => lstatSync(dir + folder).isDirectory());
|
||||
} catch (err) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
exports.pluralText = (text, number) => text + (number > 1 ? 's' : '');
|
||||
|
||||
exports.renderErrorHTML = (msg) => `
|
||||
<body>
|
||||
<style>
|
||||
html {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
<pre>${msg}</pre>
|
||||
</body>
|
||||
`;
|
||||
1
index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><!-- build:redirect --><!-- endbuild --></head><body></body></html>
|
||||
10
jsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["./src/scripts/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
96
package.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"name": "web-template",
|
||||
"title": "Web Template",
|
||||
"description": "Web template use es6, pug, scss, bootstrap",
|
||||
"version": "4.0.0",
|
||||
"author": "",
|
||||
"homepage": "",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
},
|
||||
"keywords": [
|
||||
"web",
|
||||
"template",
|
||||
"es6",
|
||||
"pug",
|
||||
"scss",
|
||||
"bootstrap"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=7"
|
||||
},
|
||||
"scripts": {
|
||||
"list-tasks": "gulp --tasks",
|
||||
"start": "gulp",
|
||||
"dev": "gulp",
|
||||
"build": "gulp build",
|
||||
"serve": "browser-sync start -c 'gulpfile.js/config/browser-sync-prod.js'",
|
||||
"upload": "gulp build && gh-pages -d dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.13.17",
|
||||
"bootstrap": "^5.1.3",
|
||||
"bootstrap-datepicker": "^1.9.0",
|
||||
"bootstrap-select": "^1.13.18",
|
||||
"dayjs": "1.10.4",
|
||||
"debounce": "^1.2.1",
|
||||
"detectizr": "^2.2.0",
|
||||
"html-to-image": "^1.9.0",
|
||||
"jquery": "^3.6.0",
|
||||
"jquery-mask-plugin": "^1.14.16",
|
||||
"jquery-validation": "^1.19.3",
|
||||
"moment": "^2.29.1",
|
||||
"parsleyjs": "^2.9.2",
|
||||
"slick-carousel": "^1.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.16.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.16.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.16.0",
|
||||
"@babel/plugin-proposal-pipeline-operator": "^7.16.0",
|
||||
"@babel/plugin-proposal-private-methods": "^7.16.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.6.2",
|
||||
"@babel/preset-env": "^7.16.4",
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-loader": "^8.2.3",
|
||||
"browser-sync": "^2.27.7",
|
||||
"compression": "^1.7.4",
|
||||
"del": "^6.0.0",
|
||||
"eslint-config-airbnb-base": "14.2.1",
|
||||
"eslint-import-resolver-webpack": "0.13.0",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"express": "4.17.1",
|
||||
"gh-pages": "^3.2.3",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-autoprefixer": "^6.1.0",
|
||||
"gulp-cached": "1.1.1",
|
||||
"gulp-clean-css": "4.3.0",
|
||||
"gulp-cli": "2.3.0",
|
||||
"gulp-concat": "2.6.1",
|
||||
"gulp-eslint": "6.0.0",
|
||||
"gulp-header": "2.0.9",
|
||||
"gulp-html-replace": "1.6.2",
|
||||
"gulp-merge-json": "2.1.1",
|
||||
"gulp-nodemon": "^2.2.1",
|
||||
"gulp-notify": "^4.0.0",
|
||||
"gulp-pug": "^5.0.0",
|
||||
"gulp-rename": "2.0.0",
|
||||
"gulp-rtlcss": "^2.0.0",
|
||||
"gulp-sass": "^5.1.0",
|
||||
"gulp-sass-unicode": "^1.0.2",
|
||||
"gulp-uglify": "3.0.2",
|
||||
"pug": "3.0.2",
|
||||
"require-dir": "1.2.0",
|
||||
"sass": "^1.51.0",
|
||||
"strip-indent": "3.0.0",
|
||||
"vinyl-named": "1.1.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-stream": "6.1.2"
|
||||
}
|
||||
}
|
||||
35
server/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const express = require('express');
|
||||
const pug = require('pug');
|
||||
|
||||
const route = require('./route');
|
||||
const { STATIC_PORT } = require('../gulpfile.js/config/server');
|
||||
const { srcView, output } = require('../gulpfile.js/config/directories');
|
||||
const pugOptions = require('../gulpfile.js/config/pug');
|
||||
const { renderErrorHTML } = require('../gulpfile.js/utils');
|
||||
|
||||
const app = express();
|
||||
app.locals.moment = require('moment');
|
||||
const { log } = console;
|
||||
|
||||
app.engine('pug', (path, options, callback) => {
|
||||
const opts = { ...pugOptions, ...options };
|
||||
|
||||
pug.renderFile(path, opts, (err, result) => {
|
||||
const data = result || renderErrorHTML(err.message);
|
||||
|
||||
callback(null, data);
|
||||
});
|
||||
});
|
||||
|
||||
app.set('views', srcView);
|
||||
app.set('view engine', 'pug');
|
||||
app.use(express.static(output));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({
|
||||
extended: true,
|
||||
}));
|
||||
app.use('/', route);
|
||||
|
||||
const logPort = `----- View server is running at http://localhost:${STATIC_PORT} -----`;
|
||||
|
||||
app.listen(STATIC_PORT, () => log(logPort));
|
||||
83
server/route.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/* eslint-disable-next-line */
|
||||
const { join } = require('path');
|
||||
const express = require('express');
|
||||
|
||||
const router = express.Router();
|
||||
const { output, srcLocales } = require('../gulpfile.js/config/directories');
|
||||
const { renderErrorHTML } = require('../gulpfile.js/utils');
|
||||
const { DEFAULT_LANG } = require('../gulpfile.js/config/server');
|
||||
|
||||
const multiLang = process.env.MULTI_LANGUAGE;
|
||||
|
||||
function forceRequire(path) {
|
||||
const realPath = join(__dirname, path);
|
||||
|
||||
delete require.cache[realPath];
|
||||
|
||||
/* eslint-disable-next-line */
|
||||
return require(path);
|
||||
}
|
||||
|
||||
router.get('/', (_, res) => {
|
||||
const defautLangPath = multiLang ? `/${DEFAULT_LANG}` : '';
|
||||
|
||||
res.redirect(`${defautLangPath}/index.html`);
|
||||
});
|
||||
|
||||
router.get('/*.html', (req, res) => {
|
||||
try {
|
||||
let lang;
|
||||
let match;
|
||||
let localeLang;
|
||||
let { path: url } = req;
|
||||
|
||||
if (multiLang) {
|
||||
const testLang = /^\/([^/]+)\//.exec(url);
|
||||
|
||||
if (!testLang) {
|
||||
throw new Error('No language in the url');
|
||||
}
|
||||
|
||||
[match, lang] = testLang;
|
||||
localeLang = forceRequire(`../${srcLocales + lang}.json`);
|
||||
|
||||
url = url.replace(match, '');
|
||||
}
|
||||
|
||||
const testFile = /[/]?(.+)\.html/.exec(url);
|
||||
|
||||
if (!testFile) {
|
||||
throw new Error('Not found');
|
||||
}
|
||||
|
||||
res.render(testFile[1], {
|
||||
$translator: localeLang || {},
|
||||
$localeName: lang,
|
||||
$path: req.url,
|
||||
}, (err, html) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
res.send(html);
|
||||
});
|
||||
} catch (err) {
|
||||
res.send(renderErrorHTML(err)).status(404);
|
||||
}
|
||||
});
|
||||
|
||||
router.get(/^\/.*[^(.html)]$/, (req, res) => {
|
||||
res.redirect(join(req.path, 'index.html'));
|
||||
});
|
||||
|
||||
router.post('*', (req, res) => {
|
||||
try {
|
||||
const json = forceRequire(join(__dirname, '..', output, req.url));
|
||||
|
||||
res.send(json);
|
||||
} catch (err) {
|
||||
res.send(renderErrorHTML(err)).status(404);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
0
src/assets/data/.gitkeep
Normal file
BIN
src/assets/favicon/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/favicon/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
src/assets/favicon/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
9
src/assets/favicon/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#ffc40d</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
BIN
src/assets/favicon/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 970 B |
BIN
src/assets/favicon/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/assets/favicon/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/favicon/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
53
src/assets/favicon/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="553.000000pt" height="553.000000pt" viewBox="0 0 553.000000 553.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,553.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M3505 5519 c-21 -11 -54 -45 -499 -503 -143 -148 -278 -285 -298
|
||||
-305 -83 -81 -82 -192 1 -235 81 -42 106 -29 297 168 546 560 651 670 666 704
|
||||
29 62 3 138 -56 166 -39 18 -82 20 -111 5z"/>
|
||||
<path d="M2084 5486 c-64 -28 -94 -95 -72 -159 16 -46 437 -483 484 -503 65
|
||||
-27 145 10 165 76 23 76 9 100 -131 244 -70 72 -172 177 -226 232 -127 131
|
||||
-148 141 -220 110z"/>
|
||||
<path d="M2734 5484 c-48 -24 -70 -71 -66 -146 2 -31 107 -150 153 -174 107
|
||||
-55 220 60 169 172 -9 22 -42 63 -73 92 -79 74 -121 87 -183 56z"/>
|
||||
<path d="M2749 4093 c-14 -10 -68 -61 -119 -113 -247 -254 -304 -310 -310
|
||||
-310 -4 0 -87 84 -186 186 -98 102 -187 190 -197 195 -31 17 -79 18 -113 4
|
||||
-67 -28 -95 -127 -54 -190 10 -16 98 -111 194 -209 l174 -180 -113 -115 c-63
|
||||
-64 -127 -131 -144 -150 l-30 -33 -167 170 c-174 179 -204 200 -268 188 -69
|
||||
-13 -118 -108 -90 -175 7 -17 71 -91 142 -164 72 -72 146 -149 165 -169 l36
|
||||
-37 -87 -89 c-295 -302 -311 -320 -317 -355 -10 -51 2 -90 37 -126 32 -33 46
|
||||
-36 120 -32 23 1 65 42 593 586 149 153 304 313 345 355 319 326 556 573 563
|
||||
586 27 49 14 124 -28 164 -33 31 -110 38 -146 13z"/>
|
||||
<path d="M3609 4058 c-38 -10 -34 -6 -704 -696 -88 -91 -198 -204 -245 -252
|
||||
-47 -48 -206 -213 -355 -365 -148 -153 -306 -315 -350 -360 -199 -204 -615
|
||||
-633 -642 -662 -41 -44 -57 -85 -49 -128 14 -75 89 -124 159 -104 35 9 72 46
|
||||
667 659 151 156 309 318 350 360 41 42 199 204 350 359 151 156 316 325 365
|
||||
376 419 427 583 600 598 627 22 43 22 85 -3 125 -35 57 -79 76 -141 61z"/>
|
||||
<path d="M4055 3555 c-17 -7 -81 -66 -144 -131 -63 -66 -238 -247 -390 -402
|
||||
-152 -156 -307 -316 -346 -356 -61 -63 -547 -563 -720 -741 -120 -123 -602
|
||||
-620 -684 -704 -46 -47 -152 -156 -235 -241 -84 -85 -160 -167 -170 -182 -25
|
||||
-39 -23 -101 5 -143 38 -54 100 -71 157 -41 23 12 167 157 587 591 68 70 601
|
||||
618 715 735 41 42 199 204 350 360 151 155 319 328 374 384 120 124 636 653
|
||||
655 673 22 23 26 104 7 141 -30 59 -100 84 -161 57z"/>
|
||||
<path d="M4096 2635 c-26 -9 -72 -49 -150 -128 -189 -195 -608 -626 -671 -691
|
||||
-65 -67 -605 -622 -720 -741 -164 -168 -617 -634 -703 -723 -52 -54 -98 -108
|
||||
-103 -121 -5 -13 -9 -44 -8 -68 4 -72 75 -126 151 -115 33 5 53 25 453 437
|
||||
306 315 342 352 695 715 140 144 296 304 345 355 245 251 623 640 729 748 65
|
||||
67 125 137 133 156 20 46 10 109 -23 144 -14 15 -26 27 -27 27 -1 0 -16 4 -33
|
||||
9 -20 6 -43 4 -68 -4z"/>
|
||||
<path d="M4065 1640 c-17 -7 -155 -146 -545 -550 -30 -31 -175 -180 -321 -331
|
||||
-147 -151 -328 -337 -403 -414 -75 -77 -140 -151 -144 -165 -12 -35 -6 -87 12
|
||||
-116 31 -46 68 -61 142 -55 20 1 147 124 367 354 36 37 67 63 69 58 7 -20 319
|
||||
-333 345 -346 37 -20 71 -19 112 3 40 21 71 73 71 117 0 51 -22 77 -286 346
|
||||
l-65 65 142 147 142 147 39 -43 c170 -182 313 -318 344 -326 68 -19 136 21
|
||||
155 91 20 75 9 90 -278 379 l-85 86 62 64 c34 35 110 114 169 174 59 61 113
|
||||
119 118 130 46 86 -15 196 -109 194 -18 0 -42 -4 -53 -9z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
19
src/assets/favicon/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
0
src/assets/fonts/.gitkeep
Normal file
BIN
src/assets/fonts/icomoon/icomoon.eot
Normal file
12
src/assets/fonts/icomoon/icomoon.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="infomation" d="M512 192c-28.16 0-51.2 23.040-51.2 51.2v204.8c0 28.16 23.040 51.2 51.2 51.2s51.2-23.040 51.2-51.2v-204.8c0-28.16-23.040-51.2-51.2-51.2zM512.512-64c282.624 0 511.488 229.376 511.488 512s-228.864 512-511.488 512c-283.136 0-512.512-229.376-512.512-512s229.376-512 512.512-512zM512 857.6c226.304 0 409.6-183.296 409.6-409.6s-183.296-409.6-409.6-409.6c-226.304 0-409.6 183.296-409.6 409.6s183.296 409.6 409.6 409.6zM460.8 652.8c0 28.277 22.923 51.2 51.2 51.2v0c28.277 0 51.2-22.923 51.2-51.2v0c0-28.277-22.923-51.2-51.2-51.2v0c-28.277 0-51.2 22.923-51.2 51.2v0z" />
|
||||
<glyph unicode="" glyph-name="arrow-down" horiz-adv-x="1365" d="M120.515 548.053l442.028-442.027c66.56-66.56 174.080-66.56 240.64 0l442.027 442.027c107.52 107.52 30.72 291.84-121.173 291.84h-884.053c-151.894 0-226.987-184.32-119.468-291.84z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/fonts/icomoon/icomoon.ttf
Normal file
BIN
src/assets/fonts/icomoon/icomoon.woff
Normal file
BIN
src/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/images/transparent.png
Normal file
|
After Width: | Height: | Size: 68 B |
0
src/scripts/_libs/.gitkeep
Normal file
55
src/scripts/_libs/jquery.fullPage.min.js
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* fullPage 2.6.6
|
||||
* https://github.com/alvarotrigo/fullPage.js
|
||||
* MIT licensed
|
||||
*
|
||||
* Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
|
||||
*/
|
||||
(function(c,l){"function"===typeof define&&define.amd?define(["jquery"],function(k){return l(k,c,c.document,c.Math)}):"undefined"!==typeof exports?module.exports=l(require("jquery"),c,c.document,c.Math):l(jQuery,c,c.document,c.Math)})("undefined"!==typeof window?window:this,function(c,l,k,n,H){var m=c(l),r=c(k);c.fn.fullpage=function(d){function Ia(a){a.find(".fp-slides").after('<div class="fp-controlArrow fp-prev"></div><div class="fp-controlArrow fp-next"></div>');"#fff"!=d.controlArrowColor&&(a.find(".fp-controlArrow.fp-next").css("border-color",
|
||||
"transparent transparent transparent "+d.controlArrowColor),a.find(".fp-controlArrow.fp-prev").css("border-color","transparent "+d.controlArrowColor+" transparent transparent"));d.loopHorizontal||a.find(".fp-controlArrow.fp-prev").hide()}function Ja(){p.append('<div id="fp-nav"><ul></ul></div>');z=c("#fp-nav");z.addClass(function(){return d.showActiveTooltip?"fp-show-active "+d.navigationPosition:d.navigationPosition});for(var a=0;a<c(".fp-section").length;a++){var b="";d.anchors.length&&(b=d.anchors[a]);
|
||||
var b='<li><a href="#'+b+'"><span></span></a>',g=d.navigationTooltips[a];"undefined"!==typeof g&&""!==g&&(b+='<div class="fp-tooltip '+d.navigationPosition+'">'+g+"</div>");b+="</li>";z.find("ul").append(b)}}function da(){c(".fp-section").each(function(){var a=c(this).find(".fp-slide");a.length?a.each(function(){I(c(this))}):I(c(this))});ea()}function ea(){var a=c(".fp-section.active"),b=a.find("SLIDES_WRAPPER"),g=a.find(".fp-scrollable");b.length&&(g=b.find(".fp-slide.active"));g.mouseover();fa(a);
|
||||
c.isFunction(d.afterLoad)&&d.afterLoad.call(a,a.data("anchor"),a.index(".fp-section")+1);c.isFunction(d.afterRender)&&d.afterRender.call(this)}function ga(){var a;if(!d.autoScrolling||d.scrollBar){for(var b=m.scrollTop(),g=0,J=n.abs(b-k.querySelectorAll(".fp-section")[0].offsetTop),e=k.querySelectorAll(".fp-section"),f=0;f<e.length;++f){var h=n.abs(b-e[f].offsetTop);h<J&&(g=f,J=h)}a=c(e).eq(g)}if(!d.autoScrolling||d.scrollBar){if(!a.hasClass("active")){U=!0;b=c(".fp-section.active");g=b.index(".fp-section")+
|
||||
1;J=V(a);e=a.data("anchor");f=a.index(".fp-section")+1;h=a.find(".fp-slide.active");if(h.length)var l=h.data("anchor"),p=h.index();u&&(a.addClass("active").siblings().removeClass("active"),c.isFunction(d.onLeave)&&d.onLeave.call(b,g,f,J),c.isFunction(d.afterLoad)&&d.afterLoad.call(a,e,f),K(e,f-1),d.anchors.length&&(A=e,W(p,l,e,f)));clearTimeout(ha);ha=setTimeout(function(){U=!1},100)}d.fitToSection&&(clearTimeout(ia),ia=setTimeout(function(){u&&(c(".fp-section.active").is(a)&&(v=!0),B(a),v=!1)},1E3))}}
|
||||
function ja(a){return a.find(".fp-slides").length?a.find(".fp-slide.active").find(".fp-scrollable"):a.find(".fp-scrollable")}function L(a,b){if(h.m[a]){var d,c;"down"==a?(d="bottom",c=e.moveSectionDown):(d="top",c=e.moveSectionUp);if(0<b.length)if(d="top"===d?!b.scrollTop():"bottom"===d?b.scrollTop()+1+b.innerHeight()>=b[0].scrollHeight:void 0,d)c();else return!0;else c()}}function Ka(a){var b=a.originalEvent;if(!ka(a.target)&&X(b)){d.autoScrolling&&a.preventDefault();a=c(".fp-section.active");var g=
|
||||
ja(a);u&&!w&&(b=la(b),D=b.y,M=b.x,a.find(".fp-slides").length&&n.abs(N-M)>n.abs(E-D)?n.abs(N-M)>m.width()/100*d.touchSensitivity&&(N>M?h.m.right&&e.moveSlideRight():h.m.left&&e.moveSlideLeft()):d.autoScrolling&&n.abs(E-D)>m.height()/100*d.touchSensitivity&&(E>D?L("down",g):D>E&&L("up",g)))}}function ka(a,b){b=b||0;var g=c(a).parent();return b<d.normalScrollElementTouchThreshold&&g.is(d.normalScrollElements)?!0:b==d.normalScrollElementTouchThreshold?!1:ka(g,++b)}function X(a){return"undefined"===typeof a.pointerType||
|
||||
"mouse"!=a.pointerType}function La(a){a=a.originalEvent;d.fitToSection&&x.stop();X(a)&&(a=la(a),E=a.y,N=a.x)}function ma(a,b){for(var d=0,c=a.slice(n.max(a.length-b,1)),e=0;e<c.length;e++)d+=c[e];return n.ceil(d/b)}function t(a){var b=(new Date).getTime();if(d.autoScrolling&&!O){a=l.event||a;var g=a.wheelDelta||-a.deltaY||-a.detail,e=n.max(-1,n.min(1,g));149<C.length&&C.shift();C.push(n.abs(g));d.scrollBar&&(a.preventDefault?a.preventDefault():a.returnValue=!1);a=c(".fp-section.active");a=ja(a);g=
|
||||
b-na;na=b;200<g&&(C=[]);u&&(b=ma(C,10),g=ma(C,70),b>=g&&(0>e?L("down",a):L("up",a)));return!1}d.fitToSection&&x.stop()}function oa(a){var b=c(".fp-section.active").find(".fp-slides"),g=b.find(".fp-slide").length;if(!(!b.length||w||2>g)){var g=b.find(".fp-slide.active"),e=null,e="prev"===a?g.prev(".fp-slide"):g.next(".fp-slide");if(!e.length){if(!d.loopHorizontal)return;e="prev"===a?g.siblings(":last"):g.siblings(":first")}w=!0;F(b,e)}}function pa(){c(".fp-slide.active").each(function(){Y(c(this),
|
||||
"internal")})}function B(a,b,g){var e=a.position();if("undefined"!==typeof e&&(b={element:a,callback:b,isMovementUp:g,dest:e,dtop:e.top,yMovement:V(a),anchorLink:a.data("anchor"),sectionIndex:a.index(".fp-section"),activeSlide:a.find(".fp-slide.active"),activeSection:c(".fp-section.active"),leavingSection:c(".fp-section.active").index(".fp-section")+1,localIsResizing:v},!(b.activeSection.is(a)&&!v||d.scrollBar&&m.scrollTop()===b.dtop))){if(b.activeSlide.length)var f=b.activeSlide.data("anchor"),h=
|
||||
b.activeSlide.index();d.autoScrolling&&d.continuousVertical&&"undefined"!==typeof b.isMovementUp&&(!b.isMovementUp&&"up"==b.yMovement||b.isMovementUp&&"down"==b.yMovement)&&(b.isMovementUp?c(".fp-section.active").before(b.activeSection.nextAll(".fp-section")):c(".fp-section.active").after(b.activeSection.prevAll(".fp-section").get().reverse()),y(c(".fp-section.active").position().top),pa(),b.wrapAroundElements=b.activeSection,b.dest=b.element.position(),b.dtop=b.dest.top,b.yMovement=V(b.element));
|
||||
if(c.isFunction(d.onLeave)&&!b.localIsResizing){if(!1===d.onLeave.call(b.activeSection,b.leavingSection,b.sectionIndex+1,b.yMovement))return;Ma(b.activeSection)}a.addClass("active").siblings().removeClass("active");u=!1;W(h,f,b.anchorLink,b.sectionIndex);Na(b);A=b.anchorLink;K(b.anchorLink,b.sectionIndex)}}function Na(a){if(d.css3&&d.autoScrolling&&!d.scrollBar)qa("translate3d(0px, -"+a.dtop+"px, 0px)",!0),d.scrollingSpeed?setTimeout(function(){Z(a)},d.scrollingSpeed):Z(a);else{var b=Oa(a);c(b.element).animate(b.options,
|
||||
d.scrollingSpeed,d.easing).promise().done(function(){Z(a)})}}function Oa(a){var b={};d.autoScrolling&&!d.scrollBar?(b.options={top:-a.dtop},b.element=".fullpage-wrapper"):(b.options={scrollTop:a.dtop},b.element="html, body");return b}function Z(a){a.wrapAroundElements&&a.wrapAroundElements.length&&(a.isMovementUp?c(".fp-section:first").before(a.wrapAroundElements):c(".fp-section:last").after(a.wrapAroundElements),y(c(".fp-section.active").position().top),pa());a.element.find(".fp-scrollable").mouseover();
|
||||
c.isFunction(d.afterLoad)&&!a.localIsResizing&&d.afterLoad.call(a.element,a.anchorLink,a.sectionIndex+1);fa(a.element);Pa(a.element);u=!0;c.isFunction(a.callback)&&a.callback.call(this)}function fa(a){a.find("img[data-src], video[data-src], audio[data-src]").each(function(){c(this).attr("src",c(this).data("src"));c(this).removeAttr("data-src")})}function Pa(a){a.find("video, audio").each(function(){var a=c(this).get(0);a.hasAttribute("autoplay")&&"function"===typeof a.play&&a.play()})}function Ma(a){a.find("video, audio").each(function(){var a=
|
||||
c(this).get(0);a.hasAttribute("data-ignore")||"function"!==typeof a.pause||a.pause()})}function ra(){if(!U&&!d.lockAnchors){var a=l.location.hash.replace("#","").split("/"),b=a[0],a=a[1];if(b.length){var c="undefined"===typeof A,e="undefined"===typeof A&&"undefined"===typeof a&&!w;(b&&b!==A&&!c||e||!w&&aa!=a)&&ba(b,a)}}}function Qa(a){u&&(a.pageY<P?e.moveSectionUp():a.pageY>P&&e.moveSectionDown());P=a.pageY}function F(a,b){var g=b.position(),e=b.index(),f=a.closest(".fp-section"),h=f.index(".fp-section"),
|
||||
k=f.data("anchor"),l=f.find(".fp-slidesNav"),m=sa(b),p=v;if(d.onSlideLeave){var t=f.find(".fp-slide.active"),q=t.index(),r;r=q==e?"none":q>e?"left":"right";if(!p&&"none"!==r&&c.isFunction(d.onSlideLeave)&&!1===d.onSlideLeave.call(t,k,h+1,q,r,e)){w=!1;return}}b.addClass("active").siblings().removeClass("active");!d.loopHorizontal&&d.controlArrows&&(f.find(".fp-controlArrow.fp-prev").toggle(0!==e),f.find(".fp-controlArrow.fp-next").toggle(!b.is(":last-child")));f.hasClass("active")&&W(e,m,k,h);var u=
|
||||
function(){p||c.isFunction(d.afterSlideLoad)&&d.afterSlideLoad.call(b,k,h+1,m,e);w=!1};d.css3?(g="translate3d(-"+n.round(g.left)+"px, 0px, 0px)",ta(a.find(".fp-slidesContainer"),0<d.scrollingSpeed).css(ua(g)),setTimeout(function(){u()},d.scrollingSpeed,d.easing)):a.animate({scrollLeft:n.round(g.left)},d.scrollingSpeed,d.easing,function(){u()});l.find(".active").removeClass("active");l.find("li").eq(e).find("a").addClass("active")}function va(){wa();if(Q){var a=c(k.activeElement);a.is("textarea")||
|
||||
a.is("input")||a.is("select")||(a=m.height(),n.abs(a-ca)>20*n.max(ca,a)/100&&(e.reBuild(!0),ca=a))}else clearTimeout(xa),xa=setTimeout(function(){e.reBuild(!0)},350)}function wa(){var a=d.responsive||d.responsiveWidth,b=d.responsiveHeight;a&&e.setResponsive(m.width()<a);b&&(f.hasClass("fp-responsive")||e.setResponsive(m.height()<b))}function ta(a){var b="all "+d.scrollingSpeed+"ms "+d.easingcss3;a.removeClass("fp-notransition");return a.css({"-webkit-transition":b,transition:b})}function Ra(a,b){if(825>
|
||||
a||900>b){var d=n.min(100*a/825,100*b/900).toFixed(2);p.css("font-size",d+"%")}else p.css("font-size","100%")}function K(a,b){d.menu&&(c(d.menu).find(".active").removeClass("active"),c(d.menu).find('[data-menuanchor="'+a+'"]').addClass("active"));d.navigation&&(c("#fp-nav").find(".active").removeClass("active"),a?c("#fp-nav").find('a[href="#'+a+'"]').addClass("active"):c("#fp-nav").find("li").eq(b).find("a").addClass("active"))}function V(a){var b=c(".fp-section.active").index(".fp-section");a=a.index(".fp-section");
|
||||
return b==a?"none":b>a?"up":"down"}function I(a){a.css("overflow","hidden");var b=a.closest(".fp-section"),c=a.find(".fp-scrollable"),e;c.length?e=c.get(0).scrollHeight:(e=a.get(0).scrollHeight,d.verticalCentered&&(e=a.find(".fp-tableCell").get(0).scrollHeight));b=q-parseInt(b.css("padding-bottom"))-parseInt(b.css("padding-top"));e>b?c.length?c.css("height",b+"px").parent().css("height",b+"px"):(d.verticalCentered?a.find(".fp-tableCell").wrapInner('<div class="fp-scrollable" />'):a.wrapInner('<div class="fp-scrollable" />'),
|
||||
a.find(".fp-scrollable").slimScroll({allowPageScroll:!0,height:b+"px",size:"10px",alwaysVisible:!0})):ya(a);a.css("overflow","")}function ya(a){a.find(".fp-scrollable").children().first().unwrap().unwrap();a.find(".slimScrollBar").remove();a.find(".slimScrollRail").remove()}function za(a){a.addClass("fp-table").wrapInner('<div class="fp-tableCell" style="height:'+Aa(a)+'px;" />')}function Aa(a){var b=q;if(d.paddingTop||d.paddingBottom)b=a,b.hasClass("fp-section")||(b=a.closest(".fp-section")),a=parseInt(b.css("padding-top"))+
|
||||
parseInt(b.css("padding-bottom")),b=q-a;return b}function qa(a,b){b?ta(f):f.addClass("fp-notransition");f.css(ua(a));setTimeout(function(){f.removeClass("fp-notransition")},10)}function Ba(a){var b=c('.fp-section[data-anchor="'+a+'"]');b.length||(b=c(".fp-section").eq(a-1));return b}function ba(a,b){var d=Ba(a);"undefined"===typeof b&&(b=0);a===A||d.hasClass("active")?Ca(d,b):B(d,function(){Ca(d,b)})}function Ca(a,b){if("undefined"!==typeof b){var d=a.find(".fp-slides"),c;c=a.find(".fp-slides");var e=
|
||||
c.find('.fp-slide[data-anchor="'+b+'"]');e.length||(e=c.find(".fp-slide").eq(b));c=e;c.length&&F(d,c)}}function Sa(a,b){a.append('<div class="fp-slidesNav"><ul></ul></div>');var c=a.find(".fp-slidesNav");c.addClass(d.slidesNavPosition);for(var e=0;e<b;e++)c.find("ul").append('<li><a href="#"><span></span></a></li>');c.css("margin-left","-"+c.width()/2+"px");c.find("li").first().find("a").addClass("active")}function W(a,b,c,e){e="";d.anchors.length&&!d.lockAnchors&&(a?("undefined"!==typeof c&&(e=c),
|
||||
"undefined"===typeof b&&(b=a),aa=b,Da(e+"/"+b)):("undefined"!==typeof a&&(aa=b),Da(c)));Ea()}function Da(a){if(d.recordHistory)location.hash=a;else if(Q||R)history.replaceState(H,H,"#"+a);else{var b=l.location.href.split("#")[0];l.location.replace(b+"#"+a)}}function sa(a){var b=a.data("anchor");a=a.index();"undefined"===typeof b&&(b=a);return b}function Ea(){var a=c(".fp-section.active"),b=a.find(".fp-slide.active"),e=a.data("anchor"),f=sa(b),a=a.index(".fp-section"),a=String(a);d.anchors.length&&
|
||||
(a=e);b.length&&(a=a+"-"+f);a=a.replace("/","-").replace("#","");p[0].className=p[0].className.replace(RegExp("\\b\\s?fp-viewing-[^\\s]+\\b","g"),"");p.addClass("fp-viewing-"+a)}function Ta(){var a=k.createElement("p"),b,c={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};k.body.insertBefore(a,null);for(var d in c)a.style[d]!==H&&(a.style[d]="translate3d(1px,1px,1px)",b=l.getComputedStyle(a).getPropertyValue(c[d]));
|
||||
k.body.removeChild(a);return b!==H&&0<b.length&&"none"!==b}function Ua(){if(Q||R){var a=Fa();c(".fullpage-wrapper").off("touchstart "+a.down).on("touchstart "+a.down,La);c(".fullpage-wrapper").off("touchmove "+a.move).on("touchmove "+a.move,Ka)}}function Va(){if(Q||R){var a=Fa();c(".fullpage-wrapper").off("touchstart "+a.down);c(".fullpage-wrapper").off("touchmove "+a.move)}}function Fa(){return l.PointerEvent?{down:"pointerdown",move:"pointermove"}:{down:"MSPointerDown",move:"MSPointerMove"}}function la(a){var b=
|
||||
[];b.y="undefined"!==typeof a.pageY&&(a.pageY||a.pageX)?a.pageY:a.touches[0].pageY;b.x="undefined"!==typeof a.pageX&&(a.pageY||a.pageX)?a.pageX:a.touches[0].pageX;R&&X(a)&&(b.y=a.touches[0].pageY,b.x=a.touches[0].pageX);return b}function Y(a,b){e.setScrollingSpeed(0,"internal");"undefined"!==typeof b&&(v=!0);F(a.closest(".fp-slides"),a);"undefined"!==typeof b&&(v=!1);e.setScrollingSpeed(G.scrollingSpeed,"internal")}function y(a){d.scrollBar?f.scrollTop(a):d.css3?qa("translate3d(0px, -"+a+"px, 0px)",
|
||||
!1):f.css("top",-a)}function ua(a){return{"-webkit-transform":a,"-moz-transform":a,"-ms-transform":a,transform:a}}function Ga(a,b,c){switch(b){case "up":h[c].up=a;break;case "down":h[c].down=a;break;case "left":h[c].left=a;break;case "right":h[c].right=a;break;case "all":"m"==c?e.setAllowScrolling(a):e.setKeyboardScrolling(a)}}function Wa(){y(0);c("#fp-nav, .fp-slidesNav, .fp-controlArrow").remove();c(".fp-section").css({height:"","background-color":"",padding:""});c(".fp-slide").css({width:""});
|
||||
f.css({height:"",position:"","-ms-touch-action":"","touch-action":""});c(".fp-section, .fp-slide").each(function(){ya(c(this));c(this).removeClass("fp-table active")});f.addClass("fp-notransition");f.find(".fp-tableCell, .fp-slidesContainer, .fp-slides").each(function(){c(this).replaceWith(this.childNodes)});x.scrollTop(0)}function S(a,b,c){d[a]=b;"internal"!==c&&(G[a]=b)}function T(a,b){console&&console[a]&&console[a]("fullPage: "+b)}var x=c("html, body"),p=c("body"),e=c.fn.fullpage;d=c.extend({menu:!1,
|
||||
anchors:[],lockAnchors:!1,navigation:!1,navigationPosition:"right",navigationTooltips:[],showActiveTooltip:!1,slidesNavigation:!1,slidesNavPosition:"bottom",scrollBar:!1,css3:!0,scrollingSpeed:700,autoScrolling:!0,fitToSection:!0,easing:"easeInOutCubic",easingcss3:"ease",loopBottom:!1,loopTop:!1,loopHorizontal:!0,continuousVertical:!1,normalScrollElements:null,scrollOverflow:!1,touchSensitivity:5,normalScrollElementTouchThreshold:5,keyboardScrolling:!0,animateAnchor:!0,recordHistory:!0,controlArrows:!0,
|
||||
controlArrowColor:"#fff",verticalCentered:!0,resize:!1,sectionsColor:[],paddingTop:0,paddingBottom:0,fixedElements:null,responsive:0,responsiveWidth:0,responsiveHeight:0,sectionSelector:".section",slideSelector:".slide",afterLoad:null,onLeave:null,afterRender:null,afterResize:null,afterReBuild:null,afterSlideLoad:null,onSlideLeave:null},d);(function(){d.continuousVertical&&(d.loopTop||d.loopBottom)&&(d.continuousVertical=!1,T("warn","Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled"));
|
||||
d.continuousVertical&&d.scrollBar&&(d.continuousVertical=!1,T("warn","Option `scrollBar` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled"));c.each(d.anchors,function(a,b){(c("#"+b).length||c('[name="'+b+'"]').length)&&T("error","data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).")})})();c.extend(c.easing,{easeInOutCubic:function(a,b,c,d,e){return 1>(b/=e/2)?d/2*b*b*b+c:d/2*((b-=2)*b*b+2)+c}});c.extend(c.easing,{easeInQuart:function(a,
|
||||
b,c,d,e){return d*(b/=e)*b*b*b+c}});e.setAutoScrolling=function(a,b){S("autoScrolling",a,b);var g=c(".fp-section.active");d.autoScrolling&&!d.scrollBar?(x.css({overflow:"hidden",height:"100%"}),e.setRecordHistory(d.recordHistory,"internal"),f.css({"-ms-touch-action":"none","touch-action":"none"}),g.length&&y(g.position().top)):(x.css({overflow:"visible",height:"initial"}),e.setRecordHistory(!1,"internal"),f.css({"-ms-touch-action":"","touch-action":""}),y(0),g.length&&x.scrollTop(g.position().top))};
|
||||
e.setRecordHistory=function(a,b){S("recordHistory",a,b)};e.setScrollingSpeed=function(a,b){S("scrollingSpeed",a,b)};e.setFitToSection=function(a,b){S("fitToSection",a,b)};e.setLockAnchors=function(a){d.lockAnchors=a};e.setMouseWheelScrolling=function(a){a?k.addEventListener?(k.addEventListener("mousewheel",t,!1),k.addEventListener("wheel",t,!1),k.addEventListener("DOMMouseScroll",t,!1)):k.attachEvent("onmousewheel",t):k.addEventListener?(k.removeEventListener("mousewheel",t,!1),k.removeEventListener("wheel",
|
||||
t,!1),k.removeEventListener("DOMMouseScroll",t,!1)):k.detachEvent("onmousewheel",t)};e.setAllowScrolling=function(a,b){"undefined"!==typeof b?(b=b.replace(/ /g,"").split(","),c.each(b,function(b,c){Ga(a,c,"m")})):a?(e.setMouseWheelScrolling(!0),Ua()):(e.setMouseWheelScrolling(!1),Va())};e.setKeyboardScrolling=function(a,b){"undefined"!==typeof b?(b=b.replace(/ /g,"").split(","),c.each(b,function(b,c){Ga(a,c,"k")})):d.keyboardScrolling=a};e.moveSectionUp=function(){var a=c(".fp-section.active").prev(".fp-section");
|
||||
a.length||!d.loopTop&&!d.continuousVertical||(a=c(".fp-section").last());a.length&&B(a,null,!0)};e.moveSectionDown=function(){var a=c(".fp-section.active").next(".fp-section");a.length||!d.loopBottom&&!d.continuousVertical||(a=c(".fp-section").first());!a.length||d.onBeforeMoveSection&&c.isFunction(d.onBeforeMoveSection)&&!1===d.onBeforeMoveSection.call(this,direction,currentSlide,destiny,slides,activeSection)||B(a,null,!1)};e.silentMoveTo=function(a,b){e.setScrollingSpeed(0,"internal");e.moveTo(a,
|
||||
b);e.setScrollingSpeed(G.scrollingSpeed,"internal")};e.moveTo=function(a,b){var c=Ba(a);"undefined"!==typeof b?ba(a,b):0<c.length&&B(c)};e.moveSlideRight=function(){oa("next")};e.moveSlideLeft=function(){oa("prev")};e.reBuild=function(a){if(!f.hasClass("fp-destroyed")){v=!0;var b=m.width();q=m.height();d.resize&&Ra(q,b);c(".fp-section").each(function(){var a=c(this).find(".fp-slides"),b=c(this).find(".fp-slide");d.verticalCentered&&c(this).find(".fp-tableCell").css("height",Aa(c(this))+"px");c(this).css("height",
|
||||
q+"px");d.scrollOverflow&&(b.length?b.each(function(){I(c(this))}):I(c(this)));1<b.length&&F(a,a.find(".fp-slide.active"))});(b=c(".fp-section.active").index(".fp-section"))&&e.silentMoveTo(b+1);v=!1;c.isFunction(d.afterResize)&&a&&d.afterResize.call(f);c.isFunction(d.afterReBuild)&&!a&&d.afterReBuild.call(f)}};e.setResponsive=function(a){var b=f.hasClass("fp-responsive");a?b||(e.setAutoScrolling(!1,"internal"),e.setFitToSection(!1,"internal"),c("#fp-nav").hide(),f.addClass("fp-responsive")):b&&(e.setAutoScrolling(G.autoScrolling,
|
||||
"internal"),e.setFitToSection(G.autoScrolling,"internal"),c("#fp-nav").show(),f.removeClass("fp-responsive"))};var w=!1,Q=navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/),R="ontouchstart"in l||0<navigator.msMaxTouchPoints||navigator.maxTouchPoints,f=c(this),q=m.height(),v=!1,A,aa,u=!0,C=[],z,O,h={m:{up:!0,down:!0,left:!0,right:!0}};h.k=c.extend(!0,{},h.m);var G=c.extend(!0,{},d);c(this).length?(f.css({height:"100%",
|
||||
position:"relative"}),f.addClass("fullpage-wrapper"),c("html").addClass("fp-enabled")):T("error","Error! Fullpage.js needs to be initialized with a selector. For example: $('#myContainer').fullpage();");d.css3&&(d.css3=Ta());e.setAllowScrolling(!0);f.removeClass("fp-destroyed");c(d.sectionSelector).each(function(){c(this).addClass("fp-section")});c(d.slideSelector).each(function(){c(this).addClass("fp-slide")});d.navigation&&Ja();c(".fp-section").each(function(a){var b=c(this),e=c(this).find(".fp-slide"),
|
||||
f=e.length;a||0!==c(".fp-section.active").length||c(this).addClass("active");c(this).css("height",q+"px");d.paddingTop&&c(this).css("padding-top",d.paddingTop);d.paddingBottom&&c(this).css("padding-bottom",d.paddingBottom);"undefined"!==typeof d.sectionsColor[a]&&c(this).css("background-color",d.sectionsColor[a]);"undefined"!==typeof d.anchors[a]&&(c(this).attr("data-anchor",d.anchors[a]),c(this).hasClass("active")&&K(d.anchors[a],a));if(0<f){a=100*f;var h=100/f;e.wrapAll('<div class="fp-slidesContainer" />');
|
||||
e.parent().wrap('<div class="fp-slides" />');c(this).find(".fp-slidesContainer").css("width",a+"%");1<f&&(d.controlArrows&&Ia(c(this)),d.slidesNavigation&&Sa(c(this),f));e.each(function(a){c(this).css("width",h+"%");d.verticalCentered&&za(c(this))});b=b.find(".fp-slide.active");b.length?Y(b):e.eq(0).addClass("active")}else d.verticalCentered&&za(c(this))}).promise().done(function(){e.setAutoScrolling(d.autoScrolling,"internal");var a=c(".fp-section.active").find(".fp-slide.active");a.length&&(0!==
|
||||
c(".fp-section.active").index(".fp-section")||0===c(".fp-section.active").index(".fp-section")&&0!==a.index())&&Y(a);d.fixedElements&&d.css3&&c(d.fixedElements).appendTo(p);d.navigation&&(z.css("margin-top","-"+z.height()/2+"px"),z.find("li").eq(c(".fp-section.active").index(".fp-section")).find("a").addClass("active"));d.menu&&d.css3&&c(d.menu).closest(".fullpage-wrapper").length&&c(d.menu).appendTo(p);d.scrollOverflow?("complete"===k.readyState&&da(),m.on("load",da)):ea();wa();if(!d.animateAnchor&&
|
||||
(a=l.location.hash.replace("#","").split("/")[0],a.length)){var b=c('[data-anchor="'+a+'"]');b.length&&(d.autoScrolling?y(b.position().top):(y(0),x.scrollTop(b.position().top)),K(a,null),c.isFunction(d.afterLoad)&&d.afterLoad.call(b,a,b.index(".fp-section")+1),b.addClass("active").siblings().removeClass("active"))}Ea();m.on("load",function(){var a=l.location.hash.replace("#","").split("/"),b=a[0],a=a[1];b&&ba(b,a)})});var ha,ia,U=!1;m.on("scroll",ga);var E=0,N=0,D=0,M=0,na=(new Date).getTime();m.on("hashchange",
|
||||
ra);r.keydown(function(a){clearTimeout(Ha);var b=c(":focus");b.is("textarea")||b.is("input")||b.is("select")||!d.keyboardScrolling||!d.autoScrolling||(-1<c.inArray(a.which,[40,38,32,33,34])&&a.preventDefault(),Ha=setTimeout(function(){var b=a.shiftKey;O=a.ctrlKey;switch(a.which){case 38:case 33:h.k.up&&e.moveSectionUp();break;case 32:if(b&&h.k.up){e.moveSectionUp();break}case 40:case 34:h.k.down&&e.moveSectionDown();break;case 36:h.k.up&&e.moveTo(1);break;case 35:h.k.down&&e.moveTo(c(".fp-section").length);
|
||||
break;case 37:h.k.left&&e.moveSlideLeft();break;case 39:h.k.right&&e.moveSlideRight()}},150))});r.keyup(function(a){O=a.ctrlKey});c(l).blur(function(){O=!1});var Ha;f.mousedown(function(a){2==a.which&&(P=a.pageY,f.on("mousemove",Qa))});f.mouseup(function(a){2==a.which&&f.off("mousemove")});var P=0;r.on("click touchstart","#fp-nav a",function(a){a.preventDefault();a=c(this).parent().index();B(c(".fp-section").eq(a))});r.on("click touchstart",".fp-slidesNav a",function(a){a.preventDefault();a=c(this).closest(".fp-section").find(".fp-slides");
|
||||
var b=a.find(".fp-slide").eq(c(this).closest("li").index());F(a,b)});d.normalScrollElements&&(r.on("mouseenter",d.normalScrollElements,function(){e.setMouseWheelScrolling(!1)}),r.on("mouseleave",d.normalScrollElements,function(){e.setMouseWheelScrolling(!0)}));c(".fp-section").on("click touchstart",".fp-controlArrow",function(){c(this).hasClass("fp-prev")?h.m.left&&e.moveSlideLeft():h.m.right&&e.moveSlideRight()});m.resize(va);var ca=q,xa;e.destroy=function(a){e.setAutoScrolling(!1,"internal");e.setAllowScrolling(!1);
|
||||
e.setKeyboardScrolling(!1);f.addClass("fp-destroyed");m.off("scroll",ga).off("hashchange",ra).off("resize",va);r.off("click","#fp-nav a").off("mouseenter","#fp-nav li").off("mouseleave","#fp-nav li").off("click",".fp-slidesNav a").off("mouseover",d.normalScrollElements).off("mouseout",d.normalScrollElements);c(".fp-section").off("click",".fp-controlArrow");a&&Wa()}}});
|
||||
774
src/scripts/_libs/modernizr-custom-3.6.0.js
Normal file
@@ -0,0 +1,774 @@
|
||||
/*!
|
||||
* modernizr v3.6.0
|
||||
* Build https://modernizr.com/download?-touchevents-addtest-setclasses-dontmin
|
||||
*
|
||||
* Copyright (c)
|
||||
* Faruk Ates
|
||||
* Paul Irish
|
||||
* Alex Sexton
|
||||
* Ryan Seddon
|
||||
* Patrick Kettner
|
||||
* Stu Cox
|
||||
* Richard Herrera
|
||||
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modernizr tests which native CSS3 and HTML5 features are available in the
|
||||
* current UA and makes the results available to you in two ways: as properties on
|
||||
* a global `Modernizr` object, and as classes on the `<html>` element. This
|
||||
* information allows you to progressively enhance your pages with a granular level
|
||||
* of control over the experience.
|
||||
*/
|
||||
|
||||
;(function(window, document, undefined){
|
||||
var classes = [];
|
||||
|
||||
|
||||
var tests = [];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* ModernizrProto is the constructor for Modernizr
|
||||
*
|
||||
* @class
|
||||
* @access public
|
||||
*/
|
||||
|
||||
var ModernizrProto = {
|
||||
// The current version, dummy
|
||||
_version: '3.6.0',
|
||||
|
||||
// Any settings that don't work as separate modules
|
||||
// can go in here as configuration.
|
||||
_config: {
|
||||
'classPrefix': '',
|
||||
'enableClasses': true,
|
||||
'enableJSClass': true,
|
||||
'usePrefixes': true
|
||||
},
|
||||
|
||||
// Queue of tests
|
||||
_q: [],
|
||||
|
||||
// Stub these for people who are listening
|
||||
on: function(test, cb) {
|
||||
// I don't really think people should do this, but we can
|
||||
// safe guard it a bit.
|
||||
// -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
|
||||
// This is in case people listen to synchronous tests. I would leave it out,
|
||||
// but the code to *disallow* sync tests in the real version of this
|
||||
// function is actually larger than this.
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
cb(self[test]);
|
||||
}, 0);
|
||||
},
|
||||
|
||||
addTest: function(name, fn, options) {
|
||||
tests.push({name: name, fn: fn, options: options});
|
||||
},
|
||||
|
||||
addAsyncTest: function(fn) {
|
||||
tests.push({name: null, fn: fn});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Fake some of Object.create so we can force non test results to be non "own" properties.
|
||||
var Modernizr = function() {};
|
||||
Modernizr.prototype = ModernizrProto;
|
||||
|
||||
// Leak modernizr globally when you `require` it rather than force it here.
|
||||
// Overwrite name so constructor name is nicer :D
|
||||
Modernizr = new Modernizr();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* is returns a boolean if the typeof an obj is exactly type.
|
||||
*
|
||||
* @access private
|
||||
* @function is
|
||||
* @param {*} obj - A thing we want to check the type of
|
||||
* @param {string} type - A string to compare the typeof against
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
function is(obj, type) {
|
||||
return typeof obj === type;
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
* Run through all tests and detect their support in the current UA.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
|
||||
function testRunner() {
|
||||
var featureNames;
|
||||
var feature;
|
||||
var aliasIdx;
|
||||
var result;
|
||||
var nameIdx;
|
||||
var featureName;
|
||||
var featureNameSplit;
|
||||
|
||||
for (var featureIdx in tests) {
|
||||
if (tests.hasOwnProperty(featureIdx)) {
|
||||
featureNames = [];
|
||||
feature = tests[featureIdx];
|
||||
// run the test, throw the return value into the Modernizr,
|
||||
// then based on that boolean, define an appropriate className
|
||||
// and push it into an array of classes we'll join later.
|
||||
//
|
||||
// If there is no name, it's an 'async' test that is run,
|
||||
// but not directly added to the object. That should
|
||||
// be done with a post-run addTest call.
|
||||
if (feature.name) {
|
||||
featureNames.push(feature.name.toLowerCase());
|
||||
|
||||
if (feature.options && feature.options.aliases && feature.options.aliases.length) {
|
||||
// Add all the aliases into the names list
|
||||
for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
|
||||
featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test, or use the raw value if it's not a function
|
||||
result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
|
||||
|
||||
|
||||
// Set each of the names on the Modernizr object
|
||||
for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
|
||||
featureName = featureNames[nameIdx];
|
||||
// Support dot properties as sub tests. We don't do checking to make sure
|
||||
// that the implied parent tests have been added. You must call them in
|
||||
// order (either in the test, or make the parent test a dependency).
|
||||
//
|
||||
// Cap it to TWO to make the logic simple and because who needs that kind of subtesting
|
||||
// hashtag famous last words
|
||||
featureNameSplit = featureName.split('.');
|
||||
|
||||
if (featureNameSplit.length === 1) {
|
||||
Modernizr[featureNameSplit[0]] = result;
|
||||
} else {
|
||||
// cast to a Boolean, if not one already
|
||||
if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
|
||||
Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
|
||||
}
|
||||
|
||||
Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
|
||||
}
|
||||
|
||||
classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
* docElement is a convenience wrapper to grab the root element of the document
|
||||
*
|
||||
* @access private
|
||||
* @returns {HTMLElement|SVGElement} The root element of the document
|
||||
*/
|
||||
|
||||
var docElement = document.documentElement;
|
||||
|
||||
|
||||
/**
|
||||
* A convenience helper to check if the document we are running in is an SVG document
|
||||
*
|
||||
* @access private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
var isSVG = docElement.nodeName.toLowerCase() === 'svg';
|
||||
|
||||
|
||||
/**
|
||||
* setClasses takes an array of class names and adds them to the root element
|
||||
*
|
||||
* @access private
|
||||
* @function setClasses
|
||||
* @param {string[]} classes - Array of class names
|
||||
*/
|
||||
|
||||
// Pass in an and array of class names, e.g.:
|
||||
// ['no-webp', 'borderradius', ...]
|
||||
function setClasses(classes) {
|
||||
var className = docElement.className;
|
||||
var classPrefix = Modernizr._config.classPrefix || '';
|
||||
|
||||
if (isSVG) {
|
||||
className = className.baseVal;
|
||||
}
|
||||
|
||||
// Change `no-js` to `js` (independently of the `enableClasses` option)
|
||||
// Handle classPrefix on this too
|
||||
if (Modernizr._config.enableJSClass) {
|
||||
var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
|
||||
className = className.replace(reJS, '$1' + classPrefix + 'js$2');
|
||||
}
|
||||
|
||||
if (Modernizr._config.enableClasses) {
|
||||
// Add the new classes
|
||||
className += ' ' + classPrefix + classes.join(' ' + classPrefix);
|
||||
if (isSVG) {
|
||||
docElement.className.baseVal = className;
|
||||
} else {
|
||||
docElement.className = className;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support
|
||||
*
|
||||
* @author kangax
|
||||
* @access private
|
||||
* @function hasOwnProp
|
||||
* @param {object} object - The object to check for a property
|
||||
* @param {string} property - The property to check for
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
// hasOwnProperty shim by kangax needed for Safari 2.0 support
|
||||
var hasOwnProp;
|
||||
|
||||
(function() {
|
||||
var _hasOwnProperty = ({}).hasOwnProperty;
|
||||
/* istanbul ignore else */
|
||||
/* we have no way of testing IE 5.5 or safari 2,
|
||||
* so just assume the else gets hit */
|
||||
if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
|
||||
hasOwnProp = function(object, property) {
|
||||
return _hasOwnProperty.call(object, property);
|
||||
};
|
||||
}
|
||||
else {
|
||||
hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
|
||||
return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
// _l tracks listeners for async tests, as well as tests that execute after the initial run
|
||||
ModernizrProto._l = {};
|
||||
|
||||
/**
|
||||
* Modernizr.on is a way to listen for the completion of async tests. Being
|
||||
* asynchronous, they may not finish before your scripts run. As a result you
|
||||
* will get a possibly false negative `undefined` value.
|
||||
*
|
||||
* @memberof Modernizr
|
||||
* @name Modernizr.on
|
||||
* @access public
|
||||
* @function on
|
||||
* @param {string} feature - String name of the feature detect
|
||||
* @param {function} cb - Callback function returning a Boolean - true if feature is supported, false if not
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.on('flash', function( result ) {
|
||||
* if (result) {
|
||||
* // the browser has flash
|
||||
* } else {
|
||||
* // the browser does not have flash
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
ModernizrProto.on = function(feature, cb) {
|
||||
// Create the list of listeners if it doesn't exist
|
||||
if (!this._l[feature]) {
|
||||
this._l[feature] = [];
|
||||
}
|
||||
|
||||
// Push this test on to the listener list
|
||||
this._l[feature].push(cb);
|
||||
|
||||
// If it's already been resolved, trigger it on next tick
|
||||
if (Modernizr.hasOwnProperty(feature)) {
|
||||
// Next Tick
|
||||
setTimeout(function() {
|
||||
Modernizr._trigger(feature, Modernizr[feature]);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* _trigger is the private function used to signal test completion and run any
|
||||
* callbacks registered through [Modernizr.on](#modernizr-on)
|
||||
*
|
||||
* @memberof Modernizr
|
||||
* @name Modernizr._trigger
|
||||
* @access private
|
||||
* @function _trigger
|
||||
* @param {string} feature - string name of the feature detect
|
||||
* @param {function|boolean} [res] - A feature detection function, or the boolean =
|
||||
* result of a feature detection function
|
||||
*/
|
||||
|
||||
ModernizrProto._trigger = function(feature, res) {
|
||||
if (!this._l[feature]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cbs = this._l[feature];
|
||||
|
||||
// Force async
|
||||
setTimeout(function() {
|
||||
var i, cb;
|
||||
for (i = 0; i < cbs.length; i++) {
|
||||
cb = cbs[i];
|
||||
cb(res);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
// Don't trigger these again
|
||||
delete this._l[feature];
|
||||
};
|
||||
|
||||
/**
|
||||
* addTest allows you to define your own feature detects that are not currently
|
||||
* included in Modernizr (under the covers it's the exact same code Modernizr
|
||||
* uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)). Just like the offical detects, the result
|
||||
* will be added onto the Modernizr object, as well as an appropriate className set on
|
||||
* the html element when configured to do so
|
||||
*
|
||||
* @memberof Modernizr
|
||||
* @name Modernizr.addTest
|
||||
* @optionName Modernizr.addTest()
|
||||
* @optionProp addTest
|
||||
* @access public
|
||||
* @function addTest
|
||||
* @param {string|object} feature - The string name of the feature detect, or an
|
||||
* object of feature detect names and test
|
||||
* @param {function|boolean} test - Function returning true if feature is supported,
|
||||
* false if not. Otherwise a boolean representing the results of a feature detection
|
||||
* @example
|
||||
*
|
||||
* The most common way of creating your own feature detects is by calling
|
||||
* `Modernizr.addTest` with a string (preferably just lowercase, without any
|
||||
* punctuation), and a function you want executed that will return a boolean result
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.addTest('itsTuesday', function() {
|
||||
* var d = new Date();
|
||||
* return d.getDay() === 2;
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,
|
||||
* and to `false` every other day of the week. One thing to notice is that the names of
|
||||
* feature detect functions are always lowercased when added to the Modernizr object. That
|
||||
* means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.
|
||||
*
|
||||
*
|
||||
* Since we only look at the returned value from any feature detection function,
|
||||
* you do not need to actually use a function. For simple detections, just passing
|
||||
* in a statement that will return a boolean value works just fine.
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.addTest('hasJquery', 'jQuery' in window);
|
||||
* ```
|
||||
*
|
||||
* Just like before, when the above runs `Modernizr.hasjquery` will be true if
|
||||
* jQuery has been included on the page. Not using a function saves a small amount
|
||||
* of overhead for the browser, as well as making your code much more readable.
|
||||
*
|
||||
* Finally, you also have the ability to pass in an object of feature names and
|
||||
* their tests. This is handy if you want to add multiple detections in one go.
|
||||
* The keys should always be a string, and the value can be either a boolean or
|
||||
* function that returns a boolean.
|
||||
*
|
||||
* ```js
|
||||
* var detects = {
|
||||
* 'hasjquery': 'jQuery' in window,
|
||||
* 'itstuesday': function() {
|
||||
* var d = new Date();
|
||||
* return d.getDay() === 2;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Modernizr.addTest(detects);
|
||||
* ```
|
||||
*
|
||||
* There is really no difference between the first methods and this one, it is
|
||||
* just a convenience to let you write more readable code.
|
||||
*/
|
||||
|
||||
function addTest(feature, test) {
|
||||
|
||||
if (typeof feature == 'object') {
|
||||
for (var key in feature) {
|
||||
if (hasOwnProp(feature, key)) {
|
||||
addTest(key, feature[ key ]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
feature = feature.toLowerCase();
|
||||
var featureNameSplit = feature.split('.');
|
||||
var last = Modernizr[featureNameSplit[0]];
|
||||
|
||||
// Again, we don't check for parent test existence. Get that right, though.
|
||||
if (featureNameSplit.length == 2) {
|
||||
last = last[featureNameSplit[1]];
|
||||
}
|
||||
|
||||
if (typeof last != 'undefined') {
|
||||
// we're going to quit if you're trying to overwrite an existing test
|
||||
// if we were to allow it, we'd do this:
|
||||
// var re = new RegExp("\\b(no-)?" + feature + "\\b");
|
||||
// docElement.className = docElement.className.replace( re, '' );
|
||||
// but, no rly, stuff 'em.
|
||||
return Modernizr;
|
||||
}
|
||||
|
||||
test = typeof test == 'function' ? test() : test;
|
||||
|
||||
// Set the value (this is the magic, right here).
|
||||
if (featureNameSplit.length == 1) {
|
||||
Modernizr[featureNameSplit[0]] = test;
|
||||
} else {
|
||||
// cast to a Boolean, if not one already
|
||||
if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
|
||||
Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
|
||||
}
|
||||
|
||||
Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;
|
||||
}
|
||||
|
||||
// Set a single class (either `feature` or `no-feature`)
|
||||
setClasses([(!!test && test != false ? '' : 'no-') + featureNameSplit.join('-')]);
|
||||
|
||||
// Trigger the event
|
||||
Modernizr._trigger(feature, test);
|
||||
}
|
||||
|
||||
return Modernizr; // allow chaining.
|
||||
}
|
||||
|
||||
// After all the tests are run, add self to the Modernizr prototype
|
||||
Modernizr._q.push(function() {
|
||||
ModernizrProto.addTest = addTest;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List of property values to set for css tests. See ticket #21
|
||||
* http://git.io/vUGl4
|
||||
*
|
||||
* @memberof Modernizr
|
||||
* @name Modernizr._prefixes
|
||||
* @optionName Modernizr._prefixes
|
||||
* @optionProp prefixes
|
||||
* @access public
|
||||
* @example
|
||||
*
|
||||
* Modernizr._prefixes is the internal list of prefixes that we test against
|
||||
* inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
|
||||
* an array of kebab-case vendor prefixes you can use within your code.
|
||||
*
|
||||
* Some common use cases include
|
||||
*
|
||||
* Generating all possible prefixed version of a CSS property
|
||||
* ```js
|
||||
* var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
|
||||
*
|
||||
* rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
|
||||
* ```
|
||||
*
|
||||
* Generating all possible prefixed version of a CSS value
|
||||
* ```js
|
||||
* rule = 'display:' + Modernizr._prefixes.join('flex; display:') + 'flex';
|
||||
*
|
||||
* rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
|
||||
* ```
|
||||
*/
|
||||
|
||||
// we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
|
||||
// values in feature detects to continue to work
|
||||
var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
|
||||
|
||||
// expose these for the plugin API. Look in the source for how to join() them against your input
|
||||
ModernizrProto._prefixes = prefixes;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* createElement is a convenience wrapper around document.createElement. Since we
|
||||
* use createElement all over the place, this allows for (slightly) smaller code
|
||||
* as well as abstracting away issues with creating elements in contexts other than
|
||||
* HTML documents (e.g. SVG documents).
|
||||
*
|
||||
* @access private
|
||||
* @function createElement
|
||||
* @returns {HTMLElement|SVGElement} An HTML or SVG element
|
||||
*/
|
||||
|
||||
function createElement() {
|
||||
if (typeof document.createElement !== 'function') {
|
||||
// This is the case in IE7, where the type of createElement is "object".
|
||||
// For this reason, we cannot call apply() as Object is not a Function.
|
||||
return document.createElement(arguments[0]);
|
||||
} else if (isSVG) {
|
||||
return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
|
||||
} else {
|
||||
return document.createElement.apply(document, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* getBody returns the body of a document, or an element that can stand in for
|
||||
* the body if a real body does not exist
|
||||
*
|
||||
* @access private
|
||||
* @function getBody
|
||||
* @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
|
||||
* artificially created element that stands in for the body
|
||||
*/
|
||||
|
||||
function getBody() {
|
||||
// After page load injecting a fake body doesn't work so check if body exists
|
||||
var body = document.body;
|
||||
|
||||
if (!body) {
|
||||
// Can't use the real body create a fake one.
|
||||
body = createElement(isSVG ? 'svg' : 'body');
|
||||
body.fake = true;
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* injectElementWithStyles injects an element with style element and some CSS rules
|
||||
*
|
||||
* @access private
|
||||
* @function injectElementWithStyles
|
||||
* @param {string} rule - String representing a css rule
|
||||
* @param {function} callback - A function that is used to test the injected element
|
||||
* @param {number} [nodes] - An integer representing the number of additional nodes you want injected
|
||||
* @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
function injectElementWithStyles(rule, callback, nodes, testnames) {
|
||||
var mod = 'modernizr';
|
||||
var style;
|
||||
var ret;
|
||||
var node;
|
||||
var docOverflow;
|
||||
var div = createElement('div');
|
||||
var body = getBody();
|
||||
|
||||
if (parseInt(nodes, 10)) {
|
||||
// In order not to give false positives we create a node for each test
|
||||
// This also allows the method to scale for unspecified uses
|
||||
while (nodes--) {
|
||||
node = createElement('div');
|
||||
node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
|
||||
div.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
style = createElement('style');
|
||||
style.type = 'text/css';
|
||||
style.id = 's' + mod;
|
||||
|
||||
// IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
|
||||
// Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
|
||||
(!body.fake ? div : body).appendChild(style);
|
||||
body.appendChild(div);
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = rule;
|
||||
} else {
|
||||
style.appendChild(document.createTextNode(rule));
|
||||
}
|
||||
div.id = mod;
|
||||
|
||||
if (body.fake) {
|
||||
//avoid crashing IE8, if background image is used
|
||||
body.style.background = '';
|
||||
//Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
|
||||
body.style.overflow = 'hidden';
|
||||
docOverflow = docElement.style.overflow;
|
||||
docElement.style.overflow = 'hidden';
|
||||
docElement.appendChild(body);
|
||||
}
|
||||
|
||||
ret = callback(div, rule);
|
||||
// If this is done after page load we don't want to remove the body so check if body exists
|
||||
if (body.fake) {
|
||||
body.parentNode.removeChild(body);
|
||||
docElement.style.overflow = docOverflow;
|
||||
// Trigger layout so kinetic scrolling isn't disabled in iOS6+
|
||||
// eslint-disable-next-line
|
||||
docElement.offsetHeight;
|
||||
} else {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
|
||||
return !!ret;
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* testStyles injects an element with style element and some CSS rules
|
||||
*
|
||||
* @memberof Modernizr
|
||||
* @name Modernizr.testStyles
|
||||
* @optionName Modernizr.testStyles()
|
||||
* @optionProp testStyles
|
||||
* @access public
|
||||
* @function testStyles
|
||||
* @param {string} rule - String representing a css rule
|
||||
* @param {function} callback - A function that is used to test the injected element
|
||||
* @param {number} [nodes] - An integer representing the number of additional nodes you want injected
|
||||
* @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
|
||||
* @returns {boolean}
|
||||
* @example
|
||||
*
|
||||
* `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
|
||||
* along with (possibly multiple) DOM elements. This lets you check for features
|
||||
* that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules).
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
|
||||
* // elem is the first DOM node in the page (by default #modernizr)
|
||||
* // rule is the first argument you supplied - the CSS rule in string form
|
||||
*
|
||||
* addTest('widthworks', elem.style.width === '9px')
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* If your test requires multiple nodes, you can include a third argument
|
||||
* indicating how many additional div elements to include on the page. The
|
||||
* additional nodes are injected as children of the `elem` that is returned as
|
||||
* the first argument to the callback.
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
|
||||
* document.getElementById('modernizr').style.width === '1px'; // true
|
||||
* document.getElementById('modernizr2').style.width === '2px'; // true
|
||||
* elem.firstChild === document.getElementById('modernizr2'); // true
|
||||
* }, 1);
|
||||
* ```
|
||||
*
|
||||
* By default, all of the additional elements have an ID of `modernizr[n]`, where
|
||||
* `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
|
||||
* the second additional is `#modernizr3`, etc.).
|
||||
* If you want to have more meaningful IDs for your function, you can provide
|
||||
* them as the fourth argument, as an array of strings
|
||||
*
|
||||
* ```js
|
||||
* Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
|
||||
* elem.firstChild === document.getElementById('foo'); // true
|
||||
* elem.lastChild === document.getElementById('bar'); // true
|
||||
* }, 2, ['foo', 'bar']);
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
|
||||
var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
|
||||
|
||||
/*!
|
||||
{
|
||||
"name": "Touch Events",
|
||||
"property": "touchevents",
|
||||
"caniuse" : "touch",
|
||||
"tags": ["media", "attribute"],
|
||||
"notes": [{
|
||||
"name": "Touch Events spec",
|
||||
"href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
|
||||
}],
|
||||
"warnings": [
|
||||
"Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
|
||||
],
|
||||
"knownBugs": [
|
||||
"False-positive on some configurations of Nokia N900",
|
||||
"False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
|
||||
]
|
||||
}
|
||||
!*/
|
||||
/* DOC
|
||||
Indicates if the browser supports the W3C Touch Events API.
|
||||
|
||||
This *does not* necessarily reflect a touchscreen device:
|
||||
|
||||
* Older touchscreen devices only emulate mouse events
|
||||
* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
|
||||
* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
|
||||
* Future browsers may implement other event models for touch interactions
|
||||
|
||||
See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
|
||||
|
||||
It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
|
||||
|
||||
This test will also return `true` for Firefox 4 Multitouch support.
|
||||
*/
|
||||
|
||||
// Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
|
||||
Modernizr.addTest('touchevents', function() {
|
||||
var bool;
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
|
||||
bool = true;
|
||||
} else {
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
|
||||
testStyles(query, function(node) {
|
||||
bool = node.offsetTop === 9;
|
||||
});
|
||||
}
|
||||
return bool;
|
||||
});
|
||||
|
||||
|
||||
// Run each test
|
||||
testRunner();
|
||||
|
||||
// Remove the "no-js" class if it exists
|
||||
setClasses(classes);
|
||||
|
||||
delete ModernizrProto.addTest;
|
||||
delete ModernizrProto.addAsyncTest;
|
||||
|
||||
// Run the things that are supposed to run after the tests
|
||||
for (var i = 0; i < Modernizr._q.length; i++) {
|
||||
Modernizr._q[i]();
|
||||
}
|
||||
|
||||
// Leak Modernizr namespace
|
||||
window.Modernizr = Modernizr;
|
||||
|
||||
|
||||
;
|
||||
|
||||
})(window, document);
|
||||
6210
src/scripts/_libs/select2.js
Normal file
97
src/scripts/cores/plugin.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const states = {
|
||||
loading: 0,
|
||||
interactive: 1,
|
||||
complete: 2
|
||||
};
|
||||
|
||||
const READY_STATE = 'DOMContentLoaded';
|
||||
|
||||
function getElementData (el) {
|
||||
const elDataset = el.dataset;
|
||||
|
||||
return Object.keys(elDataset).reduce((obj, key) => {
|
||||
let data = {};
|
||||
|
||||
if (elDataset[key]) {
|
||||
data[key] = '';
|
||||
|
||||
try {
|
||||
data[key] = JSON.parse(elDataset[key]);
|
||||
} catch (err) {
|
||||
data[key] = elDataset[key];
|
||||
}
|
||||
}
|
||||
|
||||
return { ...obj, ...data };
|
||||
}, {});
|
||||
}
|
||||
|
||||
function setupClass (Class, element, options, pluginName) {
|
||||
const _this = new Class();
|
||||
|
||||
_this.__pluginName = pluginName;
|
||||
_this.$element = $(element);
|
||||
_this.options = $.extend(
|
||||
{},
|
||||
$.fn[pluginName].defaults,
|
||||
getElementData(element),
|
||||
options
|
||||
);
|
||||
_this.props = {};
|
||||
|
||||
typeof _this.init === 'function' && _this.init();
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
export default function Plugin (param) {
|
||||
function createPlugin (Class) {
|
||||
const baseName = Class.name;
|
||||
const name = baseName.toKebabCase();
|
||||
const options = (param && param.options) || {};
|
||||
const loadEvent = (param && param.when) || READY_STATE;
|
||||
const selector = param && param.selector;
|
||||
|
||||
function init () {
|
||||
$(`[data-${name}]`)[name]();
|
||||
|
||||
if (typeof selector === 'string') {
|
||||
$(selector)[name]();
|
||||
}
|
||||
}
|
||||
|
||||
$.fn[name] = function (opts, params) {
|
||||
const instanceName = `${name}-instance`;
|
||||
|
||||
return this.each(function () {
|
||||
const instance = $.data(this, instanceName);
|
||||
|
||||
if (!(instance instanceof Class)) {
|
||||
$.data(this, instanceName, setupClass(Class, this, opts, name));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof instance[opts] !== 'function') {
|
||||
console.error(`This element has been initialized with plugin ${baseName}, please provide a correct method`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
instance[opts](params);
|
||||
});
|
||||
};
|
||||
|
||||
$.fn[name].defaults = options;
|
||||
|
||||
if (loadEvent === READY_STATE && states[document.readyState] > 0) {
|
||||
init();
|
||||
} else {
|
||||
window.addEventListener(loadEvent, init);
|
||||
}
|
||||
|
||||
return Class;
|
||||
}
|
||||
|
||||
return typeof param === 'function' ? createPlugin(param) : createPlugin;
|
||||
}
|
||||
17
src/scripts/cores/prototype.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
const PI = Math.PI;
|
||||
|
||||
String.prototype.toCamelCase = function () {
|
||||
return this.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
};
|
||||
|
||||
String.prototype.toKebabCase = function () {
|
||||
return this.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
};
|
||||
|
||||
Number.prototype.toRad = function () {
|
||||
return this * PI / 180;
|
||||
};
|
||||
|
||||
Number.prototype.toDeg = function () {
|
||||
return this * 180 / PI;
|
||||
};
|
||||
59
src/scripts/initializations/browser-detect.js
Normal file
@@ -0,0 +1,59 @@
|
||||
const { documentElement: html } = document;
|
||||
|
||||
const isTouch = 'ontouchstart' in window
|
||||
|| navigator.maxTouchPoints > 0
|
||||
|| navigator.msMaxTouchPoints > 0;
|
||||
|
||||
html.classList.add(isTouch ? 'touch' : 'no-touch');
|
||||
|
||||
if (typeof InstallTrigger !== 'undefined') {
|
||||
html.classList.add('firefox');
|
||||
}
|
||||
|
||||
const isIOSPlatform = [
|
||||
'iPad Simulator',
|
||||
'iPhone Simulator',
|
||||
'iPod Simulator',
|
||||
'iPad',
|
||||
'iPhone',
|
||||
'iPod',
|
||||
].includes(navigator.platform);
|
||||
|
||||
if (isIOSPlatform || (navigator.userAgent.includes('Mac') && isTouch)) {
|
||||
html.classList.add('ios');
|
||||
}
|
||||
|
||||
const isDeviceMobile = [
|
||||
'Android',
|
||||
'webOS',
|
||||
'iPhone',
|
||||
'iPod',
|
||||
'BlackBerry',
|
||||
'IEMobile',
|
||||
'Opera Mini',
|
||||
].includes(navigator.userAgent);
|
||||
if (isDeviceMobile) {
|
||||
html.classList.add('is-device');
|
||||
}
|
||||
|
||||
const isIE = document.documentMode;
|
||||
|
||||
if (isIE) {
|
||||
html.classList.add('ie');
|
||||
}
|
||||
|
||||
if (!isIE && window.StyleMedia) {
|
||||
html.classList.add('edge');
|
||||
}
|
||||
|
||||
const isChrome = !!window.chrome;
|
||||
|
||||
if (isChrome) {
|
||||
html.classList.add('chrome');
|
||||
}
|
||||
|
||||
if (isChrome && navigator.userAgent.indexOf('Edg') > -1) {
|
||||
html.classList.add('edge-chromium');
|
||||
}
|
||||
|
||||
export default null;
|
||||
9
src/scripts/initializations/import-jquery-plugins.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Initializations
|
||||
import '../cores/prototype';
|
||||
import 'moment';
|
||||
import 'parsleyjs';
|
||||
import 'jquery';
|
||||
|
||||
// import '../_libs/jquery.fullPage.min.js';
|
||||
|
||||
window.devj = $;
|
||||
82
src/scripts/initializations/improve-window-events.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import { throttle } from '../utils';
|
||||
import { $win } from '../utils/doms';
|
||||
import layout from '../utils/layout';
|
||||
|
||||
let passiveIfSupported = false;
|
||||
let lastWinScroll = layout.scroll;
|
||||
let resizeTimeout;
|
||||
let lastWinWidth = layout.width;
|
||||
let lastWinHeight = layout.height;
|
||||
let lastBreakpointIsDesktop = layout.isDesktop;
|
||||
|
||||
const RESIZE_TIME = 180;
|
||||
|
||||
try {
|
||||
const passive = Object.defineProperty({}, 'passive', {
|
||||
get() {
|
||||
passiveIfSupported = { passive: true };
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
window.addEventListener('test', null, passive);
|
||||
} catch (err) { /**/ }
|
||||
|
||||
window.addEventListener('scroll', throttle(() => {
|
||||
const currentWinScroll = layout.scroll;
|
||||
|
||||
if (currentWinScroll === lastWinScroll) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = currentWinScroll < lastWinScroll ? 'up' : 'down';
|
||||
|
||||
$win.trigger('scrolling', currentWinScroll);
|
||||
$win.trigger(`scroll:${name}`, currentWinScroll);
|
||||
|
||||
lastWinScroll = currentWinScroll;
|
||||
}), passiveIfSupported);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimeout);
|
||||
setTimeout(() => {
|
||||
const currentWinWidth = layout.width;
|
||||
const currentWinHeight = layout.height;
|
||||
const isWidthChanged = lastWinWidth !== currentWinWidth;
|
||||
const isHeightChanged = lastWinHeight !== currentWinHeight;
|
||||
|
||||
$win.trigger('resized', [currentWinWidth, currentWinHeight]);
|
||||
|
||||
if (isWidthChanged) {
|
||||
$win.trigger('width-change', currentWinWidth);
|
||||
|
||||
const currentBreakpointIsDesktop = layout.isDesktop;
|
||||
|
||||
if (lastBreakpointIsDesktop !== currentBreakpointIsDesktop) {
|
||||
// Prevent conflict event name with slick
|
||||
$win.trigger('breakpoint:change', currentWinWidth);
|
||||
|
||||
const breakpointEvtName = currentBreakpointIsDesktop
|
||||
? 'desktop'
|
||||
: 'mobile';
|
||||
|
||||
$win.trigger(`breakpoint:${breakpointEvtName}`, currentWinWidth);
|
||||
|
||||
lastBreakpointIsDesktop = currentBreakpointIsDesktop;
|
||||
}
|
||||
|
||||
lastWinWidth = currentWinWidth;
|
||||
}
|
||||
|
||||
if (isHeightChanged) {
|
||||
$win.trigger('height-change', currentWinHeight);
|
||||
|
||||
lastWinHeight = currentWinHeight;
|
||||
}
|
||||
|
||||
if (isWidthChanged && isHeightChanged) {
|
||||
$win.trigger('size-change', currentWinWidth, currentWinHeight);
|
||||
}
|
||||
}, RESIZE_TIME);
|
||||
}, passiveIfSupported);
|
||||
7
src/scripts/initializations/update-js-assets-path.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { staticJsAssetsPath } = window;
|
||||
|
||||
if (staticJsAssetsPath) {
|
||||
__webpack_require__.p = staticJsAssetsPath;
|
||||
}
|
||||
|
||||
export default null;
|
||||
8
src/scripts/main.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import '@/initializations/update-js-assets-path';
|
||||
import '@/initializations/browser-detect';
|
||||
import '@/initializations/import-jquery-plugins';
|
||||
import '@/initializations/improve-window-events';
|
||||
import 'slick-carousel';
|
||||
|
||||
// Plugins
|
||||
import '@/plugins/back-to-top';
|
||||
22
src/scripts/plugins/back-to-top.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { $win } from '@/utils/doms';
|
||||
|
||||
@Plugin
|
||||
export default class BackToTop {
|
||||
init() {
|
||||
const $ele = this.$element;
|
||||
|
||||
$ele.off(`click`).on(`click`, () => {
|
||||
$('html, body').animate({
|
||||
scrollTop: 0,
|
||||
});
|
||||
});
|
||||
|
||||
$win.on('scroll', () => {
|
||||
if ($win.scrollTop() > 20) {
|
||||
$ele.addClass('active');
|
||||
} else {
|
||||
$ele.removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
98
src/scripts/repositories/api.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import { transformObjectToParams } from '@/utils';
|
||||
|
||||
function getScript(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
export class ApiRepository {
|
||||
baseUrl = '';
|
||||
|
||||
scriptCacher = {};
|
||||
|
||||
getScript = getScript;
|
||||
|
||||
constructor(baseUrl = '') {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
getUrl(path, params) {
|
||||
let url = this.baseUrl + path;
|
||||
|
||||
if (typeof params === 'object') {
|
||||
url += `?${transformObjectToParams(params)}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
loadScript(url) {
|
||||
if (!this.scriptCacher[url]) {
|
||||
this.scriptCacher[url] = getScript(url);
|
||||
}
|
||||
|
||||
return this.scriptCacher[url];
|
||||
}
|
||||
|
||||
get(path, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = this.getUrl(path);
|
||||
|
||||
$.ajax({
|
||||
url,
|
||||
data,
|
||||
method: 'get',
|
||||
})
|
||||
.done(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
post(path, data = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = this.getUrl(path);
|
||||
|
||||
$.ajax({
|
||||
url,
|
||||
data,
|
||||
method: 'post',
|
||||
})
|
||||
.done(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
put(path, data = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = this.getUrl(path);
|
||||
|
||||
$.ajax({
|
||||
url,
|
||||
data,
|
||||
method: 'put',
|
||||
})
|
||||
.done(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
async resolveJSON(data) {
|
||||
if (typeof data === 'object') {
|
||||
return data;
|
||||
}
|
||||
|
||||
const response = await this.get(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApiRepository();
|
||||
40
src/scripts/utils/cookies.js
Normal file
@@ -0,0 +1,40 @@
|
||||
export default {
|
||||
set(key, value = '', days = 7) {
|
||||
if (!key) {
|
||||
console.error('no key to set cookie');
|
||||
return;
|
||||
}
|
||||
|
||||
let expires = '';
|
||||
|
||||
if (days) {
|
||||
const date = new Date();
|
||||
const expiresDate = days * 24 * 60 * 60 * 1000;
|
||||
|
||||
date.setTime(date.getTime() + expiresDate);
|
||||
expires = `; expires=${date.toUTCString()}`;
|
||||
}
|
||||
|
||||
document.cookie = `${key}=${value.toString() + expires}`;
|
||||
},
|
||||
|
||||
get(key) {
|
||||
const cookieArr = document.cookie.split(';');
|
||||
|
||||
for (let i = 0, l = cookieArr.length; i < l; i += 1) {
|
||||
const perCookie = cookieArr[i].trim();
|
||||
const indexOfSplitter = perCookie.trim().indexOf('=');
|
||||
const perCookieKey = perCookie.slice(0, indexOfSplitter);
|
||||
|
||||
if (perCookieKey === key) {
|
||||
return perCookie.slice(indexOfSplitter + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
remove(key) {
|
||||
document.cookie = `${key}=; Max-Age=-99999999;`;
|
||||
},
|
||||
};
|
||||
11
src/scripts/utils/date.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const defaultDateFormat = 'YYYY-MM-DD';
|
||||
|
||||
export function transformNumberToDate(number, format = defaultDateFormat) {
|
||||
return dayjs(number).format(format);
|
||||
}
|
||||
|
||||
export function transformDateToNumber(date) {
|
||||
return +dayjs(date, defaultDateFormat);
|
||||
}
|
||||
9
src/scripts/utils/doms.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export const $win = $(window);
|
||||
export const $doc = $(document);
|
||||
export const $html = $('html');
|
||||
export const $body = $('body');
|
||||
export const $mapKey = $('meta[name="map-key"]');
|
||||
export const $htmlAndbody = $('html, body');
|
||||
export const $canFixed = $([
|
||||
'.header',
|
||||
].join(','));
|
||||
75
src/scripts/utils/http.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import { GMAP_URL, DEFAULT_AJAX_OPTS } from './variables';
|
||||
import { wait } from './index';
|
||||
import { lang } from './layout';
|
||||
|
||||
const SCRIPT_CACHED = {};
|
||||
|
||||
function getScript (src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let script = document.createElement('script');
|
||||
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
export function loadScript (url) {
|
||||
if (!SCRIPT_CACHED[url]) {
|
||||
SCRIPT_CACHED[url] = getScript(url);
|
||||
}
|
||||
|
||||
return SCRIPT_CACHED[url];
|
||||
}
|
||||
|
||||
export function callApi (opts) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const isString = typeof opts === 'string';
|
||||
|
||||
let options = {
|
||||
...DEFAULT_AJAX_OPTS,
|
||||
data: {},
|
||||
url: isString ? opts : ''
|
||||
};
|
||||
|
||||
if (!isString) {
|
||||
options = { ...options, ...opts };
|
||||
}
|
||||
|
||||
if (!options.data.lang) {
|
||||
options.data.lang = lang;
|
||||
}
|
||||
|
||||
$.ajax(options).done(resolve).fail(reject);
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadMapApi () {
|
||||
await loadScript(GMAP_URL);
|
||||
|
||||
return window.google.maps;
|
||||
}
|
||||
|
||||
export async function download (url, fileName = '') {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $link = $('<a />', {
|
||||
href: url,
|
||||
download: fileName,
|
||||
style: 'display:none'
|
||||
});
|
||||
|
||||
$link
|
||||
.on('click', e => e.stopImmediatePropagation())
|
||||
.appendTo('body')[0]
|
||||
.click();
|
||||
|
||||
await wait();
|
||||
|
||||
$link.remove();
|
||||
}
|
||||
53
src/scripts/utils/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
export function throttle(fn, thisArg = window) {
|
||||
let scheduledAnimationFrame;
|
||||
|
||||
return () => {
|
||||
if (scheduledAnimationFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
scheduledAnimationFrame = true;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
fn.call(thisArg);
|
||||
scheduledAnimationFrame = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function transformToCamelCase(str) {
|
||||
return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
}
|
||||
|
||||
export function transformToKebabCase(str) {
|
||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
export function cloneJSON(json) {
|
||||
return JSON.parse(JSON.stringify(json));
|
||||
}
|
||||
|
||||
export function transformObjectToParams(obj) {
|
||||
return Object
|
||||
.keys(obj)
|
||||
.reduce((arr, key) => (
|
||||
arr.concat(`${key}=${encodeURIComponent(obj[key])}`)
|
||||
), [])
|
||||
.join('&');
|
||||
}
|
||||
|
||||
export function wait (ms = 10) {
|
||||
let timeout;
|
||||
|
||||
const _promise = new Promise((resolve) => {
|
||||
timeout = setTimeout(() => {
|
||||
resolve(timeout);
|
||||
}, ms);
|
||||
});
|
||||
|
||||
_promise.cancel = () => clearTimeout(timeout);
|
||||
|
||||
return _promise;
|
||||
}
|
||||
|
||||
export const waitTmp = { cancel () { /* empty fn */ } };
|
||||
225
src/scripts/utils/layout.js
Normal file
@@ -0,0 +1,225 @@
|
||||
import { $canFixed } from '@/utils/doms';
|
||||
import { RESPONSIVE_BREAKPOINTS } from './variables';
|
||||
|
||||
const { TABLET, DESKTOP } = RESPONSIVE_BREAKPOINTS;
|
||||
|
||||
const { body, documentElement: html } = document;
|
||||
|
||||
const freezeClass = '--freeze';
|
||||
const addBorderClass = '--add-fixed-border';
|
||||
|
||||
let lockTimeout;
|
||||
let lastScroll;
|
||||
let $header = $('.header');
|
||||
|
||||
function calculateScrollWidth() {
|
||||
const div = document.createElement('div');
|
||||
|
||||
div.style.position = 'absolute';
|
||||
div.style.top = '0px';
|
||||
div.style.left = '0px';
|
||||
div.style.width = '100%';
|
||||
div.style.height = '50px';
|
||||
|
||||
body.appendChild(div);
|
||||
|
||||
const fullWidth = div.offsetWidth;
|
||||
|
||||
div.style.overflowY = 'scroll';
|
||||
|
||||
const limitWidth = div.clientWidth;
|
||||
|
||||
body.removeChild(div);
|
||||
|
||||
const scrollWidth = fullWidth - limitWidth;
|
||||
|
||||
html.classList.add(`--scroll-${scrollWidth}`);
|
||||
|
||||
return scrollWidth;
|
||||
}
|
||||
|
||||
export const removeAccents = (alias) => {
|
||||
let str = alias;
|
||||
str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a')
|
||||
.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e')
|
||||
.replace(/ì|í|ị|ỉ|ĩ/g, 'i')
|
||||
.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o')
|
||||
.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u')
|
||||
.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y')
|
||||
.replace(/đ/g, 'd')
|
||||
.replace(/À|Á|Ạ|Ả|Ã|Â|Ầ|Ấ|Ậ|Ẩ|Ẫ|Ă|Ằ|Ắ|Ặ|Ẳ|Ẵ/g, 'A')
|
||||
.replace(/È|É|Ẹ|Ẻ|Ẽ|Ê|Ề|Ế|Ệ|Ể|Ễ/g, 'E')
|
||||
.replace(/Ì|Í|Ị|Ỉ|Ĩ/g, 'I')
|
||||
.replace(/Ò|Ó|Ọ|Ỏ|Õ|Ô|Ồ|Ố|Ộ|Ổ|Ỗ|Ơ|Ờ|Ớ|Ợ|Ở|Ỡ/g, 'O')
|
||||
.replace(/Ù|Ú|Ụ|Ủ|Ũ|Ư|Ừ|Ứ|Ự|Ử|Ữ/g, 'U')
|
||||
.replace(/Ỳ|Ý|Ỵ|Ỷ|Ỹ/g, 'Y')
|
||||
.replace(/Đ/g, 'D')
|
||||
.replace(/\u0300|\u0301|\u0303|\u0309|\u0323/g, '')
|
||||
.replace(/\u02C6|\u0306|\u031B/g, '')
|
||||
.replace(/[\u0300-\u036f]/g, '');
|
||||
return str;
|
||||
};
|
||||
|
||||
export const removeEscape = (value) => {
|
||||
const str = value.trim().replace(/(<([^>]+)>)|&|<|>|"|'/ig, '');
|
||||
|
||||
return removeAccents(str);
|
||||
};
|
||||
|
||||
export const regexEmail = /^([A-Za-z0-9][\._\+\-]{0,1})+[A-Za-z0-9]+@[A-Za-z0-9]+(\.{0,1}[A-Za-z0-9]){2,3}\.[a-z]{2,3}$/; //eslint-disable-line
|
||||
|
||||
export const scrollWidth = calculateScrollWidth();
|
||||
export const lang = html.getAttribute('lang') || '';
|
||||
export const isRTL = html.getAttribute('dir') === 'rtl';
|
||||
export const isIOS = html.classList.contains('ios');
|
||||
export const isIE = html.classList.contains('ie')
|
||||
|| html.classList.contains('edge');
|
||||
|
||||
export default {
|
||||
scrollWidth,
|
||||
lang,
|
||||
isRTL,
|
||||
isIOS,
|
||||
isIE,
|
||||
|
||||
get screenWidth() {
|
||||
return window.innerWidth;
|
||||
},
|
||||
|
||||
get width() {
|
||||
return body.clientWidth;
|
||||
},
|
||||
|
||||
get height() {
|
||||
return window.innerHeight;
|
||||
},
|
||||
|
||||
get bodyHeight() {
|
||||
return body.offsetHeight;
|
||||
},
|
||||
|
||||
get isFrozen() {
|
||||
return body.classList.contains(freezeClass);
|
||||
},
|
||||
|
||||
get isDesktop() {
|
||||
return this.screenWidth >= DESKTOP;
|
||||
},
|
||||
|
||||
get isSmallScreen() {
|
||||
return this.screenWidth >= TABLET;
|
||||
},
|
||||
|
||||
get isMobile() {
|
||||
return !this.isDesktop;
|
||||
},
|
||||
|
||||
get scroll() {
|
||||
return document.documentElement.scrollTop
|
||||
|| document.body.scrollTop
|
||||
|| window.pageYOffset;
|
||||
},
|
||||
|
||||
set scroll(top) {
|
||||
window.scrollTo({
|
||||
top,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
},
|
||||
|
||||
scrollImmediate(top) {
|
||||
window.scrollTo(0, top);
|
||||
},
|
||||
|
||||
scrollToElement($element, immediately) {
|
||||
if (!$element[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$header[0]) {
|
||||
$header = $('.header');
|
||||
}
|
||||
|
||||
const scrollTo = $element.offset().top - ($header.outerHeight() || 0);
|
||||
|
||||
if (immediately) {
|
||||
this.scrollImmediate(scrollTo);
|
||||
} else {
|
||||
this.scroll = $element.offset().top - ($header.outerHeight() || 0);
|
||||
}
|
||||
},
|
||||
|
||||
freeze(callback) {
|
||||
clearTimeout(lockTimeout);
|
||||
setTimeout(() => {
|
||||
window.isFreezing = true;
|
||||
|
||||
const willBeFrozen = !this.isFrozen;
|
||||
|
||||
if (!willBeFrozen) {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isIOS) {
|
||||
lastScroll = this.scroll;
|
||||
body.style.top = `${-lastScroll}px`;
|
||||
}
|
||||
|
||||
body.classList.add(freezeClass);
|
||||
|
||||
if (this.bodyHeight > this.height) {
|
||||
body.classList.add(addBorderClass);
|
||||
$canFixed.each((_, element) => {
|
||||
if (window.getComputedStyle(element).position === 'fixed') {
|
||||
element.classList.add(addBorderClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isIOS) {
|
||||
this.scrollImmediate(0);
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unfreeze(callback) {
|
||||
clearTimeout(lockTimeout);
|
||||
lockTimeout = setTimeout(() => {
|
||||
window.isFreezing = false;
|
||||
|
||||
if (!this.isFrozen) {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
body.classList.remove(freezeClass);
|
||||
body.classList.remove(addBorderClass);
|
||||
$canFixed.removeClass(addBorderClass);
|
||||
|
||||
if (this.isIOS) {
|
||||
body.style.top = '';
|
||||
this.scrollImmediate(lastScroll);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
setTimeout(() => {
|
||||
callback();
|
||||
}, 50);
|
||||
}
|
||||
} else if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
17
src/scripts/utils/variables.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { $mapKey } from '../utils/doms';
|
||||
|
||||
const GMAP_KEY = $mapKey.attr('content') || '';
|
||||
|
||||
|
||||
export const GMAP_URL = GMAP_KEY && `https://maps.googleapis.com/maps/api/js?v=3&key=${GMAP_KEY}`;
|
||||
|
||||
export const RESIZE_TIME = 180;
|
||||
|
||||
export const RESPONSIVE_BREAKPOINTS = {
|
||||
TABLET: 768,
|
||||
DESKTOP: 992
|
||||
};
|
||||
|
||||
export const DEFAULT_AJAX_OPTS = {
|
||||
cache: false
|
||||
};
|
||||
15
src/styles/$components/footer.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: rem(80);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: $color-white;
|
||||
background-color: $color-black;
|
||||
padding: 0 rem(20);
|
||||
font-size: 16px;
|
||||
|
||||
img {
|
||||
max-width: rem(60);
|
||||
}
|
||||
}
|
||||
31
src/styles/$components/header.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
.header {
|
||||
width: 100%;
|
||||
padding: rem(10) rem(20);
|
||||
color: $color-black;
|
||||
background-color: $color-black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
img {
|
||||
max-width: 60px;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
color: $color-white;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
padding: 0 rem(10);
|
||||
|
||||
a {
|
||||
color: $color-white;
|
||||
font-size: rem(16);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/styles/$libs.scss
Normal file
@@ -0,0 +1,8 @@
|
||||
@import "_utils/index";
|
||||
@import "_cores/layout";
|
||||
|
||||
@import "../../node_modules/bootstrap/scss/bootstrap";
|
||||
@import "../../node_modules/bootstrap-select/dist/css/bootstrap-select";
|
||||
@import "../../node_modules/slick-carousel/slick/slick";
|
||||
@import "../../node_modules/slick-carousel/slick/slick-theme";
|
||||
// @import "_libs/jquery.fullPage";
|
||||
55
src/styles/_cores/layout.scss
Normal file
@@ -0,0 +1,55 @@
|
||||
html {
|
||||
font-family: $font-family-default;
|
||||
font-size: $font-size-rem;
|
||||
scroll-behavior: smooth;
|
||||
// height: 100%;
|
||||
height: -webkit-fill-available;
|
||||
|
||||
// Fix modernizr bug
|
||||
&.safari {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
font-size: $font-size-default;
|
||||
font-family: $font-family-default;
|
||||
--bs-body-font-family: $font-family-default;
|
||||
|
||||
.main {
|
||||
min-height: calc(100vh - 145px);
|
||||
}
|
||||
|
||||
&.freeze {
|
||||
height: 100%;
|
||||
overflow: hidden !important; /* stylelint-disable-line */
|
||||
|
||||
html.ios & {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&[class*="--scroll-"] {
|
||||
border-right-style: solid;
|
||||
border-right-color: $color-white;
|
||||
}
|
||||
|
||||
@for $i from 13 through 18 {
|
||||
&.\--scroll-#{$i} {
|
||||
border-right-width: $i * 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
|
||||
&:not([src]),
|
||||
&[src=""] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
0
src/styles/_libs/.gitkeep
Normal file
203
src/styles/_libs/jquery.fullPage.css
Normal file
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* fullPage 2.6.6
|
||||
* https://github.com/alvarotrigo/fullPage.js
|
||||
* MIT licensed
|
||||
*
|
||||
* Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
|
||||
*/
|
||||
html.fp-enabled,
|
||||
.fp-enabled body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow:hidden;
|
||||
|
||||
/*Avoid flicker on slides transitions for mobile phones #336 */
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
#superContainer {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
/* Touch detection for Windows 8 */
|
||||
-ms-touch-action: none;
|
||||
|
||||
/* IE 11 on Windows Phone 8.1*/
|
||||
touch-action: none;
|
||||
}
|
||||
.fp-section {
|
||||
position: relative;
|
||||
-webkit-box-sizing: border-box; /* Safari<=5 Android<=3 */
|
||||
-moz-box-sizing: border-box; /* <=28 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.fp-slide {
|
||||
float: left;
|
||||
}
|
||||
.fp-slide, .fp-slidesContainer {
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
.fp-slides {
|
||||
z-index:1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
-webkit-transition: all 0.3s ease-out; /* Safari<=6 Android<=4.3 */
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.fp-section.fp-table, .fp-slide.fp-table {
|
||||
display: table;
|
||||
table-layout:fixed;
|
||||
width: 100%;
|
||||
}
|
||||
.fp-tableCell {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.fp-slidesContainer {
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.fp-controlArrow {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
top: 50%;
|
||||
cursor: pointer;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
margin-top: -38px;
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
-ms-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
.fp-controlArrow.fp-prev {
|
||||
left: 15px;
|
||||
width: 0;
|
||||
border-width: 38.5px 34px 38.5px 0;
|
||||
border-color: transparent #fff transparent transparent;
|
||||
}
|
||||
.fp-controlArrow.fp-next {
|
||||
right: 15px;
|
||||
border-width: 38.5px 0 38.5px 34px;
|
||||
border-color: transparent transparent transparent #fff;
|
||||
}
|
||||
.fp-scrollable {
|
||||
overflow: scroll;
|
||||
}
|
||||
.fp-notransition {
|
||||
-webkit-transition: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
#fp-nav {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
margin-top: -32px;
|
||||
top: 50%;
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
}
|
||||
#fp-nav.right {
|
||||
right: 17px;
|
||||
}
|
||||
#fp-nav.left {
|
||||
left: 17px;
|
||||
}
|
||||
.fp-slidesNav{
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
left: 50%;
|
||||
opacity: 1;
|
||||
}
|
||||
.fp-slidesNav.bottom {
|
||||
bottom: 17px;
|
||||
}
|
||||
.fp-slidesNav.top {
|
||||
top: 17px;
|
||||
}
|
||||
#fp-nav ul,
|
||||
.fp-slidesNav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#fp-nav ul li,
|
||||
.fp-slidesNav ul li {
|
||||
display: block;
|
||||
width: 14px;
|
||||
height: 13px;
|
||||
margin: 7px;
|
||||
position:relative;
|
||||
}
|
||||
.fp-slidesNav ul li {
|
||||
display: inline-block;
|
||||
}
|
||||
#fp-nav ul li a,
|
||||
.fp-slidesNav ul li a {
|
||||
display: block;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
#fp-nav ul li a.active span,
|
||||
.fp-slidesNav ul li a.active span,
|
||||
#fp-nav ul li:hover a.active span,
|
||||
.fp-slidesNav ul li:hover a.active span{
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
margin: -6px 0 0 -6px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
#fp-nav ul li a span,
|
||||
.fp-slidesNav ul li a span {
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
border: 0;
|
||||
background: #333;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin: -2px 0 0 -2px;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
-moz-transition: all 0.1s ease-in-out;
|
||||
-o-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
#fp-nav ul li:hover a span,
|
||||
.fp-slidesNav ul li:hover a span{
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: -5px 0px 0px -5px;
|
||||
}
|
||||
#fp-nav ul li .fp-tooltip {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-family: arial, helvetica, sans-serif;
|
||||
white-space: nowrap;
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
}
|
||||
#fp-nav ul li:hover .fp-tooltip,
|
||||
#fp-nav.fp-show-active a.active + .fp-tooltip {
|
||||
-webkit-transition: opacity 0.2s ease-in;
|
||||
transition: opacity 0.2s ease-in;
|
||||
width: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
#fp-nav ul li .fp-tooltip.right {
|
||||
right: 20px;
|
||||
}
|
||||
#fp-nav ul li .fp-tooltip.left {
|
||||
left: 20px;
|
||||
}
|
||||
21
src/styles/_utils/common.scss
Normal file
@@ -0,0 +1,21 @@
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
bottom: 45px;
|
||||
right: 45px;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
|
||||
img {
|
||||
max-width: 60px;
|
||||
}
|
||||
|
||||
@include mq('md', max) {
|
||||
right: 25px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
43
src/styles/_utils/functions.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
@use 'sass:math';
|
||||
|
||||
$unit-range: (
|
||||
'px': 1px,
|
||||
'em': 1em,
|
||||
'rem': 1rem,
|
||||
);
|
||||
|
||||
@function addUnit($value, $unit) {
|
||||
@if type-of($unit) != 'string' {
|
||||
@error 'Value for unit should be a string.';
|
||||
}
|
||||
|
||||
$matched-unit: map-get($unit-range, $unit);
|
||||
|
||||
@if $matched-unit {
|
||||
@return $value * $matched-unit;
|
||||
} @else {
|
||||
@error 'Value for unit not a valid unit.';
|
||||
}
|
||||
}
|
||||
|
||||
@function px2unit($unit, $pixels, $context) {
|
||||
@if $unit {
|
||||
@if (unitless($pixels)) {
|
||||
$pixels: $pixels * 1px;
|
||||
}
|
||||
|
||||
@if (unitless($context)) {
|
||||
$context: $context * 1px;
|
||||
}
|
||||
|
||||
@return addUnit(math.div($pixels, $context), $unit);
|
||||
}
|
||||
}
|
||||
|
||||
@function em($pixels, $context) {
|
||||
@return px2unit('em', $pixels, $context);
|
||||
}
|
||||
|
||||
@function rem($pixels, $context: $font-size-rem) {
|
||||
@return px2unit('rem', $pixels, $context);
|
||||
}
|
||||