initial commit
This commit is contained in:
commit
52aad94550
|
@ -0,0 +1,108 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title>Four Operations</title>
|
||||
<meta name="generator" content="LibreOffice 7.4.1.2 (Windows)"/>
|
||||
<meta name="author" content="buzz-lightsnack-2007"/>
|
||||
|
||||
<!-- styles -->
|
||||
<link href="node_modules/@materializecss/materialize/dist/css/materialize.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet" />
|
||||
<link href="styles/interface.css" rel="stylesheet" />
|
||||
|
||||
<!-- scripts -->
|
||||
<script src="node_modules/@materializecss/materialize/dist/js/materialize.js"></script>
|
||||
<script src="scripts/fouroperations.js"></script>
|
||||
</head>
|
||||
<body lang="en-PH" dir="ltr">
|
||||
<nav>
|
||||
<top class="nav-wrapper">
|
||||
<a class="brand-logo">FourOperations</a>
|
||||
<ul id="nav-mobile" class="right">
|
||||
<li><a id="button_submit" class="waves-effect waves-light" type="submit" onclick="displayAnswers()">Solve</a></li>
|
||||
</ul>
|
||||
</top>
|
||||
</nav>
|
||||
<main>
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<div class="col s12 m6">
|
||||
<section class="card">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="input_number_1">1<sup>st</sup> Number</label>
|
||||
<input type="number" id="input_number_1" required></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<section class="card">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="input_number_2">2<sup>nd</sup> Number</label>
|
||||
<input type="number" id="input_number_2" required></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<div class="col s12 m4">
|
||||
<section class="card green white-text">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="output_number_sum" class="white-text"><i class="mdi mdi-plus"></i> Sum</label>
|
||||
<input type="number" id="output_number_sum" placeholder="-" class="white-text" readonly></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col s12 m4">
|
||||
<section class="card red white-text">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="output_number_difference" class="white-text"><i class="mdi mdi-minus"></i> Difference</label>
|
||||
<input type="number" id="output_number_difference" placeholder="-" class="white-text" readonly></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col s12 m4">
|
||||
<section class="card purple white-text">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="output_number_quotient" class="white-text"><i class="mdi mdi-division"></i> Quotient</label>
|
||||
<input type="number" id="output_number_quotient" placeholder="-" class="white-text" readonly></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col s12 m6">
|
||||
<section class="card orange white-text">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="output_number_product" class="white-text"><i class="mdi mdi-close-thick"></i> Product</label>
|
||||
<input type="number" id="output_number_product" placeholder="-" class="white-text" readonly></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<section class="card blue white-text">
|
||||
<div class="card-content">
|
||||
<div class="input-field">
|
||||
<label for="output_number_exponential" class="white-text"><i class="mdi mdi-exponent"></i> Exponential</label>
|
||||
<input type="number" id="output_number_exponential" placeholder="-" class="white-text" readonly></input>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body></html>
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "fouroperations",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/@materializecss/materialize": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@materializecss/materialize/-/materialize-1.1.0.tgz",
|
||||
"integrity": "sha512-W2MrDC8mzpMWyP2OpS0RWTWGcLiRRBz7kn2E9TsbardPyVNFdoNvXq5sLy3NcEfAlACc1+L7Q95+pBuUX44dRg=="
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,708 @@
|
|||
const sass = require('sass');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
const concatFile = 'temp/js/materialize_concat.js.map';
|
||||
const jsFiles = [
|
||||
'js/cash.js',
|
||||
'js/waves.js',
|
||||
'js/component.js',
|
||||
'js/global.js',
|
||||
'js/anime.min.js',
|
||||
'js/collapsible.js',
|
||||
'js/dropdown.js',
|
||||
'js/modal.js',
|
||||
'js/materialbox.js',
|
||||
'js/parallax.js',
|
||||
'js/tabs.js',
|
||||
'js/tooltip.js',
|
||||
'js/toasts.js',
|
||||
'js/sidenav.js',
|
||||
'js/scrollspy.js',
|
||||
'js/autocomplete.js',
|
||||
'js/forms.js',
|
||||
'js/slider.js',
|
||||
'js/cards.js',
|
||||
'js/chips.js',
|
||||
'js/pushpin.js',
|
||||
'js/buttons.js',
|
||||
'js/datepicker.js',
|
||||
'js/timepicker.js',
|
||||
'js/characterCounter.js',
|
||||
'js/carousel.js',
|
||||
'js/tapTarget.js',
|
||||
'js/select.js',
|
||||
'js/range.js'
|
||||
];
|
||||
|
||||
// configure the tasks
|
||||
let config = {
|
||||
// Jasmine
|
||||
jasmine: {
|
||||
components: {
|
||||
src: ['bin/materialize.js'],
|
||||
options: {
|
||||
vendor: [
|
||||
'node_modules/jquery/dist/jquery.min.js'
|
||||
],
|
||||
styles: 'bin/materialize.css',
|
||||
specs: 'tests/spec/**/*Spec.js',
|
||||
helpers: 'tests/spec/helper.js',
|
||||
keepRunner: true,
|
||||
version: '3.8.0',
|
||||
page: {
|
||||
viewportSize: {
|
||||
width: 1400,
|
||||
height: 735
|
||||
}
|
||||
},
|
||||
sandboxArgs: {
|
||||
args: ['--headless', '--no-sandbox', '--disable-gpu']
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Sass
|
||||
sass: {
|
||||
|
||||
// Global options
|
||||
options: {
|
||||
implementation: sass
|
||||
},
|
||||
|
||||
// Task
|
||||
expanded: {
|
||||
// Target options
|
||||
options: {
|
||||
outputStyle: 'expanded',
|
||||
sourcemap: false
|
||||
},
|
||||
files: {
|
||||
'dist/css/materialize.css': 'sass/materialize.scss'
|
||||
}
|
||||
},
|
||||
|
||||
min: {
|
||||
options: {
|
||||
outputStyle: 'compressed',
|
||||
sourcemap: false
|
||||
},
|
||||
files: {
|
||||
'dist/css/materialize.min.css': 'sass/materialize.scss'
|
||||
}
|
||||
},
|
||||
|
||||
// Compile ghpages css
|
||||
gh: {
|
||||
options: {
|
||||
outputStyle: 'compressed',
|
||||
sourcemap: false
|
||||
},
|
||||
files: {
|
||||
'docs/css/ghpages-materialize.css': 'sass/ghpages-materialize.scss'
|
||||
}
|
||||
},
|
||||
|
||||
// Compile bin css
|
||||
bin: {
|
||||
options: {
|
||||
outputStyle: 'expanded',
|
||||
sourcemap: false
|
||||
},
|
||||
files: {
|
||||
'bin/materialize.css': 'sass/materialize.scss'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// PostCss Autoprefixer
|
||||
postcss: {
|
||||
options: {
|
||||
processors: [
|
||||
require('autoprefixer')({
|
||||
browsers: [
|
||||
'last 2 versions',
|
||||
'Chrome >= 30',
|
||||
'Firefox >= 30',
|
||||
'ie >= 10',
|
||||
'Safari >= 8'
|
||||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
expanded: {
|
||||
src: 'dist/css/materialize.css'
|
||||
},
|
||||
min: {
|
||||
src: 'dist/css/materialize.min.css'
|
||||
},
|
||||
gh: {
|
||||
src: 'docs/css/ghpages-materialize.css'
|
||||
},
|
||||
bin: {
|
||||
src: 'bin/materialize.css'
|
||||
}
|
||||
},
|
||||
|
||||
babel: {
|
||||
options: {
|
||||
sourceMap: false,
|
||||
plugins: [
|
||||
'transform-es2015-arrow-functions',
|
||||
'transform-es2015-block-scoping',
|
||||
'transform-es2015-classes',
|
||||
'transform-es2015-template-literals',
|
||||
'transform-es2015-object-super',
|
||||
'babel-plugin-transform-object-rest-spread'
|
||||
]
|
||||
},
|
||||
bin: {
|
||||
options: {
|
||||
sourceMap: true
|
||||
},
|
||||
files: {
|
||||
'bin/materialize.js': 'temp/js/materialize_concat.js'
|
||||
}
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
'dist/js/materialize.js': 'temp/js/materialize.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Browser Sync integration
|
||||
browserSync: {
|
||||
bsFiles: ['bin/*', 'css/ghpages-materialize.css', '!**/node_modules/**/*'],
|
||||
options: {
|
||||
server: {
|
||||
baseDir: './' // make server from root dir
|
||||
},
|
||||
port: 8000,
|
||||
ui: {
|
||||
port: 8080,
|
||||
weinre: {
|
||||
port: 9090
|
||||
}
|
||||
},
|
||||
open: false
|
||||
}
|
||||
},
|
||||
|
||||
// Concat
|
||||
concat: {
|
||||
options: {
|
||||
separator: ';'
|
||||
},
|
||||
dist: {
|
||||
// the files to concatenate
|
||||
src: jsFiles,
|
||||
// the location of the resulting JS file
|
||||
dest: 'temp/js/materialize.js'
|
||||
},
|
||||
temp: {
|
||||
// the files to concatenate
|
||||
options: {
|
||||
sourceMap: true,
|
||||
sourceMapStyle: 'link'
|
||||
},
|
||||
src: jsFiles,
|
||||
// the location of the resulting JS file
|
||||
dest: 'temp/js/materialize_concat.js'
|
||||
}
|
||||
},
|
||||
|
||||
// Uglify
|
||||
uglify: {
|
||||
options: {
|
||||
// Use these options when debugging
|
||||
// mangle: false,
|
||||
// compress: false,
|
||||
// beautify: true
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
'dist/js/materialize.min.js': ['dist/js/materialize.js']
|
||||
}
|
||||
},
|
||||
bin: {
|
||||
files: {
|
||||
'bin/materialize.min.js': ['bin/materialize.js']
|
||||
}
|
||||
},
|
||||
extras: {
|
||||
files: {
|
||||
'extras/noUiSlider/nouislider.min.js': ['extras/noUiSlider/nouislider.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Compress
|
||||
compress: {
|
||||
main: {
|
||||
options: {
|
||||
archive: 'bin/materialize.zip',
|
||||
level: 6
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: 'dist/', src: ['**/*'], dest: 'materialize/' },
|
||||
{ expand: true, cwd: './', src: ['LICENSE', 'README.md'], dest: 'materialize/' }
|
||||
]
|
||||
},
|
||||
|
||||
src: {
|
||||
options: {
|
||||
archive: 'bin/materialize-src.zip',
|
||||
level: 6
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: 'sass/', src: ['materialize.scss'], dest: 'materialize-src/sass/' },
|
||||
{ expand: true, cwd: 'sass/', src: ['components/**/*'], dest: 'materialize-src/sass/' },
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'js/',
|
||||
src: [
|
||||
'anime.min.js',
|
||||
'cash.js',
|
||||
'component.js',
|
||||
'global.js',
|
||||
'collapsible.js',
|
||||
'dropdown.js',
|
||||
'modal.js',
|
||||
'materialbox.js',
|
||||
'parallax.js',
|
||||
'tabs.js',
|
||||
'tooltip.js',
|
||||
'waves.js',
|
||||
'toasts.js',
|
||||
'sidenav.js',
|
||||
'scrollspy.js',
|
||||
'autocomplete.js',
|
||||
'forms.js',
|
||||
'slider.js',
|
||||
'cards.js',
|
||||
'chips.js',
|
||||
'pushpin.js',
|
||||
'buttons.js',
|
||||
'datepicker.js',
|
||||
'timepicker.js',
|
||||
'characterCounter.js',
|
||||
'carousel.js',
|
||||
'tapTarget.js',
|
||||
'select.js',
|
||||
'range.js'
|
||||
],
|
||||
dest: 'materialize-src/js/'
|
||||
},
|
||||
{ expand: true, cwd: 'dist/js/', src: ['**/*'], dest: 'materialize-src/js/bin/' },
|
||||
{ expand: true, cwd: './', src: ['LICENSE', 'README.md'], dest: 'materialize-src/' }
|
||||
]
|
||||
},
|
||||
|
||||
starter_template: {
|
||||
options: {
|
||||
archive: 'templates/starter-template.zip',
|
||||
level: 6
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: 'dist/', src: ['**/*'], dest: 'starter-template/' },
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/starter-template/',
|
||||
src: ['index.html', 'LICENSE'],
|
||||
dest: 'starter-template/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/starter-template/css',
|
||||
src: ['style.css'],
|
||||
dest: 'starter-template/css'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/starter-template/js',
|
||||
src: ['init.js'],
|
||||
dest: 'starter-template/js'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
parallax_template: {
|
||||
options: {
|
||||
archive: 'templates/parallax-template.zip',
|
||||
level: 6
|
||||
},
|
||||
files: [
|
||||
{ expand: true, cwd: 'dist/', src: ['**/*'], dest: 'parallax-template/' },
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/parallax-template/',
|
||||
src: ['index.html', 'LICENSE', 'background1.jpg', 'background2.jpg', 'background3.jpg'],
|
||||
dest: 'parallax-template/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/parallax-template/css',
|
||||
src: ['style.css'],
|
||||
dest: 'parallax-template/css'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'templates/parallax-template/js',
|
||||
src: ['init.js'],
|
||||
dest: 'parallax-template/js'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Clean
|
||||
clean: {
|
||||
temp: {
|
||||
src: ['temp/']
|
||||
}
|
||||
},
|
||||
|
||||
// Pug
|
||||
pug: {
|
||||
compile: {
|
||||
options: {
|
||||
pretty: true,
|
||||
data: {
|
||||
debug: false
|
||||
}
|
||||
},
|
||||
files: {
|
||||
'docs/index.html': 'pug/index.pug',
|
||||
'docs/icons.html': 'pug/icons.pug',
|
||||
'docs/about.html': 'pug/about.pug',
|
||||
'docs/sass.html': 'pug/sass.pug',
|
||||
'docs/getting-started.html': 'pug/getting-started.pug',
|
||||
'docs/mobile.html': 'pug/mobile.pug',
|
||||
'docs/parallax.html': 'pug/parallax.pug',
|
||||
'docs/parallax-demo.html': 'pug/parallax-demo.pug',
|
||||
'docs/typography.html': 'pug/typography.pug',
|
||||
'docs/color.html': 'pug/color.pug',
|
||||
'docs/shadow.html': 'pug/shadow.pug',
|
||||
'docs/grid.html': 'pug/grid.pug',
|
||||
'docs/media-css.html': 'pug/media-css.pug',
|
||||
'docs/table.html': 'pug/table.pug',
|
||||
'docs/helpers.html': 'pug/helpers.pug',
|
||||
'docs/buttons.html': 'pug/buttons.pug',
|
||||
'docs/navbar.html': 'pug/navbar.pug',
|
||||
'docs/cards.html': 'pug/cards.pug',
|
||||
'docs/preloader.html': 'pug/preloader.pug',
|
||||
'docs/collections.html': 'pug/collections.pug',
|
||||
'docs/badges.html': 'pug/badges.pug',
|
||||
'docs/footer.html': 'pug/footer.pug',
|
||||
'docs/modals.html': 'pug/modals.pug',
|
||||
'docs/dropdown.html': 'pug/dropdown.pug',
|
||||
'docs/tabs.html': 'pug/tabs.pug',
|
||||
'docs/toasts.html': 'pug/toasts.pug',
|
||||
'docs/tooltips.html': 'pug/tooltips.pug',
|
||||
'docs/sidenav.html': 'pug/sidenav.pug',
|
||||
'docs/pushpin.html': 'pug/pushpin.pug',
|
||||
'docs/waves.html': 'pug/waves.pug',
|
||||
'docs/media.html': 'pug/media.pug',
|
||||
'docs/collapsible.html': 'pug/collapsible.pug',
|
||||
'docs/scrollspy.html': 'pug/scrollspy.pug',
|
||||
'docs/fullscreen-slider-demo.html': 'pug/fullscreen-slider-demo.pug',
|
||||
'docs/pagination.html': 'pug/pagination.pug',
|
||||
'docs/breadcrumbs.html': 'pug/breadcrumbs.pug',
|
||||
'docs/carousel.html': 'pug/carousel.pug',
|
||||
'docs/feature-discovery.html': 'pug/feature-discovery.pug',
|
||||
'docs/pulse.html': 'pug/pulse.pug',
|
||||
'docs/pushpin-demo.html': 'pug/pushpin-demo.pug',
|
||||
'docs/css-transitions.html': 'pug/css-transitions.pug',
|
||||
'docs/404.html': 'pug/404.pug',
|
||||
'docs/autocomplete.html': 'pug/autocomplete.pug',
|
||||
'docs/checkboxes.html': 'pug/checkboxes.pug',
|
||||
'docs/chips.html': 'pug/chips.pug',
|
||||
'docs/pickers.html': 'pug/pickers.pug',
|
||||
'docs/radio-buttons.html': 'pug/radio-buttons.pug',
|
||||
'docs/range.html': 'pug/range.pug',
|
||||
'docs/select.html': 'pug/select.pug',
|
||||
'docs/switches.html': 'pug/switches.pug',
|
||||
'docs/text-inputs.html': 'pug/text-inputs.pug',
|
||||
'docs/floating-action-button.html': 'pug/floating-action-button.pug',
|
||||
'docs/auto-init.html': 'pug/auto-init.pug'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Watch Files
|
||||
watch: {
|
||||
pug: {
|
||||
files: ['pug/**/*'],
|
||||
tasks: ['pug_compile'],
|
||||
options: {
|
||||
interrupt: false,
|
||||
spawn: false
|
||||
}
|
||||
},
|
||||
|
||||
js: {
|
||||
files: ['js/**/*', '!js/init.js'],
|
||||
tasks: ['js_compile'],
|
||||
options: {
|
||||
interrupt: false,
|
||||
spawn: false
|
||||
}
|
||||
},
|
||||
|
||||
sass: {
|
||||
files: ['sass/**/*'],
|
||||
tasks: ['sass_compile'],
|
||||
options: {
|
||||
interrupt: false,
|
||||
spawn: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Concurrent
|
||||
concurrent: {
|
||||
options: {
|
||||
logConcurrentOutput: true,
|
||||
limit: 10
|
||||
},
|
||||
monitor: {
|
||||
tasks: [
|
||||
'pug_compile',
|
||||
'sass_compile',
|
||||
'js_compile',
|
||||
'watch:pug',
|
||||
'watch:js',
|
||||
'watch:sass',
|
||||
'notify:watching',
|
||||
'server'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Notifications
|
||||
notify: {
|
||||
watching: {
|
||||
options: {
|
||||
enabled: true,
|
||||
message: 'Watching Files!',
|
||||
title: 'Materialize', // defaults to the name in package.json, or will use project directory's name
|
||||
success: true, // whether successful grunt executions should be notified automatically
|
||||
duration: 1 // the duration of notification in seconds, for `notify-send only
|
||||
}
|
||||
},
|
||||
|
||||
sass_compile: {
|
||||
options: {
|
||||
enabled: true,
|
||||
message: 'Sass Compiled!',
|
||||
title: 'Materialize',
|
||||
success: true,
|
||||
duration: 1
|
||||
}
|
||||
},
|
||||
|
||||
js_compile: {
|
||||
options: {
|
||||
enabled: true,
|
||||
message: 'JS Compiled!',
|
||||
title: 'Materialize',
|
||||
success: true,
|
||||
duration: 1
|
||||
}
|
||||
},
|
||||
|
||||
pug_compile: {
|
||||
options: {
|
||||
enabled: true,
|
||||
message: 'Pug Compiled!',
|
||||
title: 'Materialize',
|
||||
success: true,
|
||||
duration: 1
|
||||
}
|
||||
},
|
||||
|
||||
server: {
|
||||
options: {
|
||||
enabled: true,
|
||||
message: 'Server Running!',
|
||||
title: 'Materialize',
|
||||
success: true,
|
||||
duration: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Replace text to update the version string
|
||||
replace: {
|
||||
version: {
|
||||
src: ['bower.json', 'package.js', 'pug/**/*.html'],
|
||||
overwrite: true,
|
||||
replacements: [
|
||||
{
|
||||
from: grunt.option('oldver'),
|
||||
to: grunt.option('newver')
|
||||
}
|
||||
]
|
||||
},
|
||||
package_json: {
|
||||
src: ['package.json'],
|
||||
overwrite: true,
|
||||
replacements: [
|
||||
{
|
||||
from: '"version": "' + grunt.option('oldver'),
|
||||
to: '"version": "' + grunt.option('newver')
|
||||
}
|
||||
]
|
||||
},
|
||||
docs: {
|
||||
src: ['.gitignore'],
|
||||
overwrite: true,
|
||||
replacements: [
|
||||
{
|
||||
from: '/docs/*.html',
|
||||
to: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Create Version Header for files
|
||||
usebanner: {
|
||||
release: {
|
||||
options: {
|
||||
position: 'top',
|
||||
banner:
|
||||
'/*!\n * Materialize v' +
|
||||
grunt.option('newver') +
|
||||
' (https://materializecss.github.io/materialize)\n * Copyright 2014-2021 Materialize\n * MIT License (https://raw.githubusercontent.com/materializecss/materialize/master/LICENSE)\n */',
|
||||
linebreak: true
|
||||
},
|
||||
files: {
|
||||
src: ['dist/css/*.css', 'dist/js/*.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Rename files
|
||||
rename: {
|
||||
rename_src: {
|
||||
src: 'bin/materialize-src' + '.zip',
|
||||
dest: 'bin/materialize-src-v' + grunt.option('newver') + '.zip',
|
||||
options: {
|
||||
ignore: true
|
||||
}
|
||||
},
|
||||
rename_compiled: {
|
||||
src: 'bin/materialize' + '.zip',
|
||||
dest: 'bin/materialize-v' + grunt.option('newver') + '.zip',
|
||||
options: {
|
||||
ignore: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
connect: {
|
||||
server: {
|
||||
options: {
|
||||
port: 9001,
|
||||
protocol: 'http',
|
||||
middleware: function(connect, options, middlewares) {
|
||||
middlewares.unshift(function(req, res, next){
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Credentials', true);
|
||||
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
||||
next();
|
||||
});
|
||||
return middlewares;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy: {
|
||||
docs: {
|
||||
files: [
|
||||
{src: 'bin/materialize.js', dest: 'docs/js/materialize.js'},
|
||||
{src: 'templates/**', dest: 'docs/'}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
grunt.initConfig(config);
|
||||
|
||||
// load the tasks
|
||||
// grunt.loadNpmTasks('grunt-gitinfo');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-pug');
|
||||
grunt.loadNpmTasks('grunt-concurrent');
|
||||
grunt.loadNpmTasks('grunt-notify');
|
||||
grunt.loadNpmTasks('grunt-text-replace');
|
||||
grunt.loadNpmTasks('grunt-banner');
|
||||
grunt.loadNpmTasks('grunt-rename-util');
|
||||
grunt.loadNpmTasks('grunt-browser-sync');
|
||||
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||
grunt.loadNpmTasks('grunt-postcss');
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
|
||||
// define the tasks
|
||||
grunt.registerTask('release', [
|
||||
'sass:expanded',
|
||||
'sass:min',
|
||||
'postcss:expanded',
|
||||
'postcss:min',
|
||||
'concat:dist',
|
||||
'babel:dist',
|
||||
'uglify:dist',
|
||||
'uglify:extras',
|
||||
'usebanner:release',
|
||||
'compress:main',
|
||||
'compress:src',
|
||||
'compress:starter_template',
|
||||
'compress:parallax_template',
|
||||
'replace:version',
|
||||
'replace:package_json',
|
||||
'rename:rename_src',
|
||||
'rename:rename_compiled',
|
||||
'clean:temp'
|
||||
]);
|
||||
|
||||
grunt.task.registerTask('configureBabel', 'configures babel options', function() {
|
||||
config.babel.bin.options.inputSourceMap = grunt.file.readJSON(concatFile);
|
||||
});
|
||||
|
||||
grunt.registerTask('pug_compile', ['pug', 'notify:pug_compile']);
|
||||
grunt.registerTask('js_compile', ['concat:temp', 'configureBabel', 'babel:bin', 'clean:temp']);
|
||||
grunt.registerTask('sass_compile', [
|
||||
'sass:gh',
|
||||
'sass:bin',
|
||||
'postcss:gh',
|
||||
'postcss:bin',
|
||||
'notify:sass_compile'
|
||||
]);
|
||||
grunt.registerTask('server', ['browserSync', 'notify:server']);
|
||||
grunt.registerTask('monitor', ['concurrent:monitor']);
|
||||
grunt.registerTask('travis', ['js_compile', 'sass_compile', 'connect', 'jasmine']);
|
||||
grunt.registerTask('jas_test', ['connect', 'jasmine']);
|
||||
grunt.registerTask('test_repeat', function(){
|
||||
const tasks = ['connect'];
|
||||
const n = 30;
|
||||
for (let i = 0; i < n; i++) {
|
||||
tasks.push('jasmine');
|
||||
}
|
||||
|
||||
grunt.task.run(tasks);
|
||||
|
||||
});
|
||||
grunt.registerTask('docs', ['js_compile', 'copy:docs', 'sass:gh', 'postcss:gh', 'pug', 'replace:docs']);
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Materialize
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,97 @@
|
|||
<p align="center">
|
||||
<a href="https://materializecss.github.io/materialize/">
|
||||
<img src="https://materializecss.github.io/materialize/res/materialize.svg" width="150">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">MaterializeCSS</h3>
|
||||
|
||||
<p align="center">
|
||||
Materialize, a CSS Framework based on material design.
|
||||
<br>
|
||||
<a href="https://materializecss.github.io/materialize/"><strong>-- Browse the docs --</strong></a>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://github.com/materializecss/materialize/actions/">
|
||||
<img src="https://github.com/materializecss/materialize/actions/workflows/nightly.yml/badge.svg" alt="GitHub Actions badge">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/@materializecss/materialize">
|
||||
<img src="https://badge.fury.io/js/%40materializecss%2Fmaterialize.svg" alt="npm version badge">
|
||||
</a>
|
||||
<a href="https://www.jsdelivr.com/package/npm/@materializecss/materialize">
|
||||
<img src="https://data.jsdelivr.com/v1/package/npm/@materializecss/materialize/badge" alt="jsDelivr version badge">
|
||||
</a>
|
||||
<a href="https://david-dm.org/materializecss/materialize">
|
||||
<img src="https://david-dm.org/materializecss/materialize/status.svg" alt="dependencies Status badge">
|
||||
</a>
|
||||
<a href="https://david-dm.org/materializecss/materialize#info=devDependencies">
|
||||
<img src="https://david-dm.org/materializecss/materialize/dev-status.svg" alt="devDependency Status badge">
|
||||
</a>
|
||||
<a href="https://gitter.im/materializecss/materialize">
|
||||
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter badge">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Table of Contents
|
||||
- [Quickstart](#quickstart)
|
||||
- [Documentation](#documentation)
|
||||
- [Build](#build)
|
||||
- [Supported Browsers](#supported-browsers)
|
||||
- [Changelog](#changelog)
|
||||
- [Testing](#testing)
|
||||
- [Contributing](#contributing)
|
||||
- [Copyright and license](#copyright-and-license)
|
||||
|
||||
## Quickstart:
|
||||
Read the [getting started guide](https://materializecss.github.io/materialize/getting-started.html) for more information on how to use materialize.
|
||||
|
||||
- [Download the latest release](https://github.com/materializecss/materialize/releases/latest) of materialize directly from GitHub. ([Beta](https://github.com/materializecss/materialize/releases/))
|
||||
- Clone the repo: `git clone https://github.com/materializecss/materialize.git`
|
||||
- Include the files via [jsDelivr](https://www.jsdelivr.com/package/npm/@materializecss/materialize).
|
||||
- Install with [npm](https://www.npmjs.com): `npm install @materializecss/materialize` (Beta: `npm install @materializecss/materialize@next`)
|
||||
|
||||
## Documentation
|
||||
The documentation can be found at <https://materializecss.github.io/materialize>. To run the documentation locally on your machine, you need [Node.js](https://nodejs.org/en/) installed on your computer.
|
||||
|
||||
### Running documentation locally
|
||||
Run these commands to set up the documentation:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/materializecss/materialize
|
||||
cd materialize
|
||||
npm install
|
||||
```
|
||||
|
||||
Then run `npm run dev` to compile the documentation. When it finishes, open a new browser window and navigate to `localhost:8000/docs`. We use [BrowserSync](https://www.browsersync.io/) to display the documentation.
|
||||
|
||||
### Documentation for previous releases
|
||||
Previous releases and their documentation are available for [download](https://github.com/materializecss/materialize/releases).
|
||||
|
||||
## Build
|
||||
If you want to build `materialize.css` or `materialize.js` from the latest commit, you can build the files with the following command after `npm install`. See `package.json` to check the current version like `1.0.0`.
|
||||
|
||||
```sh
|
||||
npm run release -- --oldver=<current_version> --newver=<new_version>
|
||||
```
|
||||
|
||||
## Supported Browsers:
|
||||
Materialize is compatible with:
|
||||
|
||||
- Chrome 35+
|
||||
- Firefox 31+
|
||||
- Safari 9+
|
||||
- Opera
|
||||
- Edge
|
||||
- IE 11+
|
||||
|
||||
## Changelog
|
||||
For changelogs, check out [the Releases section of materialize](https://github.com/materializecss/materialize/releases) or the [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
## Testing
|
||||
We use Jasmine as our testing framework and we're trying to write a robust test suite for our components. If you want to help, [here's a starting guide on how to write tests in Jasmine](CONTRIBUTING.md#jasmine-testing-guide).
|
||||
|
||||
## Contributing
|
||||
Check out the [CONTRIBUTING document](CONTRIBUTING.md) in the root of the repository to learn how you can contribute. You can also browse the [help-wanted](https://github.com/materializecss/materialize/labels/help-wanted) tag in our issue tracker to find things to do.
|
||||
|
||||
## Copyright and license
|
||||
Code Copyright 2021 Materialize. Code released under the MIT license.
|
Binary file not shown.
8632
node_modules/@materializecss/materialize/dist/css/materialize.css
generated
vendored
Executable file
8632
node_modules/@materializecss/materialize/dist/css/materialize.css
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
12
node_modules/@materializecss/materialize/dist/css/materialize.min.css
generated
vendored
Executable file
12
node_modules/@materializecss/materialize/dist/css/materialize.min.css
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
12669
node_modules/@materializecss/materialize/dist/js/materialize.js
generated
vendored
Executable file
12669
node_modules/@materializecss/materialize/dist/js/materialize.js
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
6
node_modules/@materializecss/materialize/dist/js/materialize.min.js
generated
vendored
Executable file
6
node_modules/@materializecss/materialize/dist/js/materialize.min.js
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
406
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.css
generated
vendored
Executable file
406
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.css
generated
vendored
Executable file
|
@ -0,0 +1,406 @@
|
|||
/*!
|
||||
* Materialize 1.0.0 (https://materializecss.github.io/materialize)
|
||||
* Copyright 2014-2015 Materialize
|
||||
* MIT License (https://raw.githubusercontent.com/materializecss/materialize/master/LICENSE)
|
||||
*/
|
||||
|
||||
/*! nouislider - 9.1.0 - 2016-12-10 16:00:32 */
|
||||
|
||||
|
||||
/* Functional styling;
|
||||
* These styles are required for noUiSlider to function.
|
||||
* You don't need to change these rules to apply your design.
|
||||
*/
|
||||
.noUi-target,
|
||||
.noUi-target * {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
-webkit-user-select: none;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.noUi-target {
|
||||
position: relative;
|
||||
direction: ltr;
|
||||
}
|
||||
.noUi-base {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 1; /* Fix 401 */
|
||||
}
|
||||
.noUi-connect {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.noUi-origin {
|
||||
position: absolute;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
.noUi-handle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.noUi-state-tap .noUi-connect,
|
||||
.noUi-state-tap .noUi-origin {
|
||||
-webkit-transition: top 0.25s, right 0.25s, bottom 0.25s, left 0.25s;
|
||||
transition: top 0.25s, right 0.25s, bottom 0.25s, left 0.25s;
|
||||
}
|
||||
.noUi-state-drag * {
|
||||
cursor: inherit !important;
|
||||
}
|
||||
|
||||
.noUi-handle-touch-area{
|
||||
position: relative;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
left: -15px;
|
||||
top: -15px;
|
||||
}
|
||||
/* Painting and performance;
|
||||
* Browsers can paint handles in their own layer.
|
||||
*/
|
||||
.noUi-base,
|
||||
.noUi-handle {
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
/* Slider size and handle placement;
|
||||
*/
|
||||
.noUi-horizontal {
|
||||
height: 18px;
|
||||
}
|
||||
.noUi-horizontal .noUi-handle {
|
||||
width: 34px;
|
||||
height: 28px;
|
||||
left: -17px;
|
||||
top: -6px;
|
||||
}
|
||||
.noUi-vertical {
|
||||
width: 18px;
|
||||
}
|
||||
.noUi-vertical .noUi-handle {
|
||||
width: 28px;
|
||||
height: 34px;
|
||||
left: -6px;
|
||||
top: -17px;
|
||||
}
|
||||
|
||||
/* Styling;
|
||||
*/
|
||||
.noUi-target {
|
||||
background: #cdcdcd;
|
||||
border-radius: 4px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.noUi-connect {
|
||||
background: #26A69A;
|
||||
-webkit-transition: background 450ms;
|
||||
transition: background 450ms;
|
||||
}
|
||||
|
||||
/* Handles and cursors;
|
||||
*/
|
||||
.noUi-draggable {
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.noUi-vertical .noUi-draggable {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.noUi-handle {
|
||||
border: 1px solid #D9D9D9;
|
||||
border-radius: 3px;
|
||||
background: #FFF;
|
||||
cursor: default;
|
||||
box-shadow: inset 0 0 1px #FFF,
|
||||
inset 0 1px 7px #EBEBEB,
|
||||
0 3px 6px -3px #BBB;
|
||||
}
|
||||
.noUi-active {
|
||||
box-shadow: inset 0 0 1px #FFF,
|
||||
inset 0 1px 7px #DDD,
|
||||
0 3px 6px -3px #BBB;
|
||||
}
|
||||
|
||||
/* Handle stripes
|
||||
*/
|
||||
.noUi-handle:before,
|
||||
.noUi-handle:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 14px;
|
||||
width: 1px;
|
||||
background: #E8E7E6;
|
||||
left: 14px;
|
||||
top: 6px;
|
||||
}
|
||||
.noUi-handle:after {
|
||||
left: 17px;
|
||||
}
|
||||
.noUi-vertical .noUi-handle:before,
|
||||
.noUi-vertical .noUi-handle:after {
|
||||
width: 14px;
|
||||
height: 1px;
|
||||
left: 6px;
|
||||
top: 14px;
|
||||
}
|
||||
.noUi-vertical .noUi-handle:after {
|
||||
top: 17px;
|
||||
}
|
||||
|
||||
/* Disabled state;
|
||||
*/
|
||||
|
||||
[disabled] .noUi-connect {
|
||||
background: #B8B8B8;
|
||||
}
|
||||
[disabled].noUi-target,
|
||||
[disabled].noUi-handle,
|
||||
[disabled] .noUi-handle {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
/* Base;
|
||||
*
|
||||
*/
|
||||
.noUi-pips,
|
||||
.noUi-pips * {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.noUi-pips {
|
||||
position: absolute;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Values;
|
||||
*
|
||||
*/
|
||||
.noUi-value {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.noUi-value-sub {
|
||||
color: #ccc;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* Markings;
|
||||
*
|
||||
*/
|
||||
.noUi-marker {
|
||||
position: absolute;
|
||||
background: #CCC;
|
||||
}
|
||||
.noUi-marker-sub {
|
||||
background: #AAA;
|
||||
}
|
||||
.noUi-marker-large {
|
||||
background: #AAA;
|
||||
}
|
||||
|
||||
/* Horizontal layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-horizontal {
|
||||
padding: 10px 0;
|
||||
height: 80px;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.noUi-value-horizontal {
|
||||
-webkit-transform: translate3d(-50%,50%,0);
|
||||
transform: translate3d(-50%,50%,0);
|
||||
}
|
||||
|
||||
.noUi-marker-horizontal.noUi-marker {
|
||||
margin-left: -1px;
|
||||
width: 2px;
|
||||
height: 5px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-sub {
|
||||
height: 10px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-large {
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
/* Vertical layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-vertical {
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
}
|
||||
.noUi-value-vertical {
|
||||
-webkit-transform: translate3d(0,50%,0);
|
||||
transform: translate3d(0,50%,0);
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.noUi-marker-vertical.noUi-marker {
|
||||
width: 5px;
|
||||
height: 2px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-sub {
|
||||
width: 10px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-large {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.noUi-tooltip {
|
||||
display: block;
|
||||
position: absolute;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.noUi-horizontal .noUi-tooltip {
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
left: 50%;
|
||||
bottom: 120%;
|
||||
}
|
||||
.noUi-vertical .noUi-tooltip {
|
||||
-webkit-transform: translate(0, -50%);
|
||||
transform: translate(0, -50%);
|
||||
top: 50%;
|
||||
right: 120%;
|
||||
}
|
||||
|
||||
/* Materialize Styles */
|
||||
.noUi-target {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.noUi-horizontal {
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.noUi-vertical {
|
||||
height: 100%;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.noUi-horizontal .noUi-handle,
|
||||
.noUi-vertical .noUi-handle {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
box-shadow: none;
|
||||
background-color: #26A69A;
|
||||
border: none;
|
||||
left: -5px;
|
||||
top: -6px;
|
||||
transition: width .2s cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
height .2s cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
left .2s cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
top .2s cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
}
|
||||
.noUi-handle:before {
|
||||
content: none;
|
||||
}
|
||||
.noUi-handle:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.noUi-target .noUi-active.noUi-handle {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.noUi-target.noUi-horizontal .noUi-tooltip {
|
||||
position: absolute;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
top: -17px;
|
||||
left: -2px;
|
||||
background-color: #26A69A;
|
||||
border-radius: 50%;
|
||||
transition: border-radius .25s cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
transform .25s cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transform: scale(.5) rotate(-45deg);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
.noUi-target.noUi-horizontal .noUi-active .noUi-tooltip {
|
||||
border-radius: 15px 15px 15px 0;
|
||||
transform: rotate(-45deg) translate(23px, -25px);
|
||||
}
|
||||
|
||||
.noUi-tooltip span {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: -1px;
|
||||
transition: opacity .25s cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.noUi-horizontal .noUi-tooltip span {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.noUi-vertical .noUi-tooltip span {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
|
||||
|
||||
.noUi-target.noUi-vertical .noUi-tooltip {
|
||||
position: absolute;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
top: -17px;
|
||||
left: -2px;
|
||||
background-color: #26A69A;
|
||||
border-radius: 50%;
|
||||
transition: border-radius .25s cubic-bezier(0.215, 0.610, 0.355, 1.000),
|
||||
transform .25s cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transform: scale(.5) rotate(-45deg);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
.noUi-target.noUi-vertical .noUi-active .noUi-tooltip {
|
||||
border-radius: 15px 15px 15px 0;
|
||||
transform: rotate(-135deg) translate(35px, -10px);
|
||||
}
|
||||
.noUi-vertical .noUi-tooltip span {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
transform: rotate(135deg);
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: -1px;
|
||||
transition: opacity .25s cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.noUi-horizontal .noUi-active .noUi-tooltip span,
|
||||
.noUi-vertical .noUi-active .noUi-tooltip span {
|
||||
opacity: 1;
|
||||
}
|
2147
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.js
generated
vendored
Executable file
2147
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.js
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.min.js
generated
vendored
Executable file
1
node_modules/@materializecss/materialize/extras/noUiSlider/nouislider.min.js
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
v2.2.0
|
||||
2017 Julian Garnier
|
||||
Released under the MIT license
|
||||
*/
|
||||
var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(e,r,p){if(p.get||p.set)throw new TypeError("ES3 does not support getters and setters.");e!=Array.prototype&&e!=Object.prototype&&(e[r]=p.value)};$jscomp.getGlobal=function(e){return"undefined"!=typeof window&&window===e?e:"undefined"!=typeof global&&null!=global?global:e};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
|
||||
$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(e){return $jscomp.SYMBOL_PREFIX+(e||"")+$jscomp.symbolCounter_++};
|
||||
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var e=$jscomp.global.Symbol.iterator;e||(e=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[e]&&$jscomp.defineProperty(Array.prototype,e,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(e){var r=0;return $jscomp.iteratorPrototype(function(){return r<e.length?{done:!1,value:e[r++]}:{done:!0}})};
|
||||
$jscomp.iteratorPrototype=function(e){$jscomp.initSymbolIterator();e={next:e};e[$jscomp.global.Symbol.iterator]=function(){return this};return e};$jscomp.array=$jscomp.array||{};$jscomp.iteratorFromArray=function(e,r){$jscomp.initSymbolIterator();e instanceof String&&(e+="");var p=0,m={next:function(){if(p<e.length){var u=p++;return{value:r(u,e[u]),done:!1}}m.next=function(){return{done:!0,value:void 0}};return m.next()}};m[Symbol.iterator]=function(){return m};return m};
|
||||
$jscomp.polyfill=function(e,r,p,m){if(r){p=$jscomp.global;e=e.split(".");for(m=0;m<e.length-1;m++){var u=e[m];u in p||(p[u]={});p=p[u]}e=e[e.length-1];m=p[e];r=r(m);r!=m&&null!=r&&$jscomp.defineProperty(p,e,{configurable:!0,writable:!0,value:r})}};$jscomp.polyfill("Array.prototype.keys",function(e){return e?e:function(){return $jscomp.iteratorFromArray(this,function(e){return e})}},"es6-impl","es3");var $jscomp$this=this;
|
||||
(function(r){M.anime=r()})(function(){function e(a){if(!h.col(a))try{return document.querySelectorAll(a)}catch(c){}}function r(a,c){for(var d=a.length,b=2<=arguments.length?arguments[1]:void 0,f=[],n=0;n<d;n++)if(n in a){var k=a[n];c.call(b,k,n,a)&&f.push(k)}return f}function p(a){return a.reduce(function(a,d){return a.concat(h.arr(d)?p(d):d)},[])}function m(a){if(h.arr(a))return a;
|
||||
h.str(a)&&(a=e(a)||a);return a instanceof NodeList||a instanceof HTMLCollection?[].slice.call(a):[a]}function u(a,c){return a.some(function(a){return a===c})}function C(a){var c={},d;for(d in a)c[d]=a[d];return c}function D(a,c){var d=C(a),b;for(b in a)d[b]=c.hasOwnProperty(b)?c[b]:a[b];return d}function z(a,c){var d=C(a),b;for(b in c)d[b]=h.und(a[b])?c[b]:a[b];return d}function T(a){a=a.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(a,c,d,k){return c+c+d+d+k+k});var c=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a);
|
||||
a=parseInt(c[1],16);var d=parseInt(c[2],16),c=parseInt(c[3],16);return"rgba("+a+","+d+","+c+",1)"}function U(a){function c(a,c,b){0>b&&(b+=1);1<b&&--b;return b<1/6?a+6*(c-a)*b:.5>b?c:b<2/3?a+(c-a)*(2/3-b)*6:a}var d=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(a)||/hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(a);a=parseInt(d[1])/360;var b=parseInt(d[2])/100,f=parseInt(d[3])/100,d=d[4]||1;if(0==b)f=b=a=f;else{var n=.5>f?f*(1+b):f+b-f*b,k=2*f-n,f=c(k,n,a+1/3),b=c(k,n,a);a=c(k,n,a-1/3)}return"rgba("+
|
||||
255*f+","+255*b+","+255*a+","+d+")"}function y(a){if(a=/([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(a))return a[2]}function V(a){if(-1<a.indexOf("translate")||"perspective"===a)return"px";if(-1<a.indexOf("rotate")||-1<a.indexOf("skew"))return"deg"}function I(a,c){return h.fnc(a)?a(c.target,c.id,c.total):a}function E(a,c){if(c in a.style)return getComputedStyle(a).getPropertyValue(c.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase())||"0"}function J(a,c){if(h.dom(a)&&
|
||||
u(W,c))return"transform";if(h.dom(a)&&(a.getAttribute(c)||h.svg(a)&&a[c]))return"attribute";if(h.dom(a)&&"transform"!==c&&E(a,c))return"css";if(null!=a[c])return"object"}function X(a,c){var d=V(c),d=-1<c.indexOf("scale")?1:0+d;a=a.style.transform;if(!a)return d;for(var b=[],f=[],n=[],k=/(\w+)\((.+?)\)/g;b=k.exec(a);)f.push(b[1]),n.push(b[2]);a=r(n,function(a,b){return f[b]===c});return a.length?a[0]:d}function K(a,c){switch(J(a,c)){case "transform":return X(a,c);case "css":return E(a,c);case "attribute":return a.getAttribute(c)}return a[c]||
|
||||
0}function L(a,c){var d=/^(\*=|\+=|-=)/.exec(a);if(!d)return a;var b=y(a)||0;c=parseFloat(c);a=parseFloat(a.replace(d[0],""));switch(d[0][0]){case "+":return c+a+b;case "-":return c-a+b;case "*":return c*a+b}}function F(a,c){return Math.sqrt(Math.pow(c.x-a.x,2)+Math.pow(c.y-a.y,2))}function M(a){a=a.points;for(var c=0,d,b=0;b<a.numberOfItems;b++){var f=a.getItem(b);0<b&&(c+=F(d,f));d=f}return c}function N(a){if(a.getTotalLength)return a.getTotalLength();switch(a.tagName.toLowerCase()){case "circle":return 2*
|
||||
Math.PI*a.getAttribute("r");case "rect":return 2*a.getAttribute("width")+2*a.getAttribute("height");case "line":return F({x:a.getAttribute("x1"),y:a.getAttribute("y1")},{x:a.getAttribute("x2"),y:a.getAttribute("y2")});case "polyline":return M(a);case "polygon":var c=a.points;return M(a)+F(c.getItem(c.numberOfItems-1),c.getItem(0))}}function Y(a,c){function d(b){b=void 0===b?0:b;return a.el.getPointAtLength(1<=c+b?c+b:0)}var b=d(),f=d(-1),n=d(1);switch(a.property){case "x":return b.x;case "y":return b.y;
|
||||
case "angle":return 180*Math.atan2(n.y-f.y,n.x-f.x)/Math.PI}}function O(a,c){var d=/-?\d*\.?\d+/g,b;b=h.pth(a)?a.totalLength:a;if(h.col(b))if(h.rgb(b)){var f=/rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(b);b=f?"rgba("+f[1]+",1)":b}else b=h.hex(b)?T(b):h.hsl(b)?U(b):void 0;else f=(f=y(b))?b.substr(0,b.length-f.length):b,b=c&&!/\s/g.test(b)?f+c:f;b+="";return{original:b,numbers:b.match(d)?b.match(d).map(Number):[0],strings:h.str(a)||c?b.split(d):[]}}function P(a){a=a?p(h.arr(a)?a.map(m):m(a)):[];return r(a,
|
||||
function(a,d,b){return b.indexOf(a)===d})}function Z(a){var c=P(a);return c.map(function(a,b){return{target:a,id:b,total:c.length}})}function aa(a,c){var d=C(c);if(h.arr(a)){var b=a.length;2!==b||h.obj(a[0])?h.fnc(c.duration)||(d.duration=c.duration/b):a={value:a}}return m(a).map(function(a,b){b=b?0:c.delay;a=h.obj(a)&&!h.pth(a)?a:{value:a};h.und(a.delay)&&(a.delay=b);return a}).map(function(a){return z(a,d)})}function ba(a,c){var d={},b;for(b in a){var f=I(a[b],c);h.arr(f)&&(f=f.map(function(a){return I(a,
|
||||
c)}),1===f.length&&(f=f[0]));d[b]=f}d.duration=parseFloat(d.duration);d.delay=parseFloat(d.delay);return d}function ca(a){return h.arr(a)?A.apply(this,a):Q[a]}function da(a,c){var d;return a.tweens.map(function(b){b=ba(b,c);var f=b.value,e=K(c.target,a.name),k=d?d.to.original:e,k=h.arr(f)?f[0]:k,w=L(h.arr(f)?f[1]:f,k),e=y(w)||y(k)||y(e);b.from=O(k,e);b.to=O(w,e);b.start=d?d.end:a.offset;b.end=b.start+b.delay+b.duration;b.easing=ca(b.easing);b.elasticity=(1E3-Math.min(Math.max(b.elasticity,1),999))/
|
||||
1E3;b.isPath=h.pth(f);b.isColor=h.col(b.from.original);b.isColor&&(b.round=1);return d=b})}function ea(a,c){return r(p(a.map(function(a){return c.map(function(b){var c=J(a.target,b.name);if(c){var d=da(b,a);b={type:c,property:b.name,animatable:a,tweens:d,duration:d[d.length-1].end,delay:d[0].delay}}else b=void 0;return b})})),function(a){return!h.und(a)})}function R(a,c,d,b){var f="delay"===a;return c.length?(f?Math.min:Math.max).apply(Math,c.map(function(b){return b[a]})):f?b.delay:d.offset+b.delay+
|
||||
b.duration}function fa(a){var c=D(ga,a),d=D(S,a),b=Z(a.targets),f=[],e=z(c,d),k;for(k in a)e.hasOwnProperty(k)||"targets"===k||f.push({name:k,offset:e.offset,tweens:aa(a[k],d)});a=ea(b,f);return z(c,{children:[],animatables:b,animations:a,duration:R("duration",a,c,d),delay:R("delay",a,c,d)})}function q(a){function c(){return window.Promise&&new Promise(function(a){return p=a})}function d(a){return g.reversed?g.duration-a:a}function b(a){for(var b=0,c={},d=g.animations,f=d.length;b<f;){var e=d[b],
|
||||
k=e.animatable,h=e.tweens,n=h.length-1,l=h[n];n&&(l=r(h,function(b){return a<b.end})[0]||l);for(var h=Math.min(Math.max(a-l.start-l.delay,0),l.duration)/l.duration,w=isNaN(h)?1:l.easing(h,l.elasticity),h=l.to.strings,p=l.round,n=[],m=void 0,m=l.to.numbers.length,t=0;t<m;t++){var x=void 0,x=l.to.numbers[t],q=l.from.numbers[t],x=l.isPath?Y(l.value,w*x):q+w*(x-q);p&&(l.isColor&&2<t||(x=Math.round(x*p)/p));n.push(x)}if(l=h.length)for(m=h[0],w=0;w<l;w++)p=h[w+1],t=n[w],isNaN(t)||(m=p?m+(t+p):m+(t+" "));
|
||||
else m=n[0];ha[e.type](k.target,e.property,m,c,k.id);e.currentValue=m;b++}if(b=Object.keys(c).length)for(d=0;d<b;d++)H||(H=E(document.body,"transform")?"transform":"-webkit-transform"),g.animatables[d].target.style[H]=c[d].join(" ");g.currentTime=a;g.progress=a/g.duration*100}function f(a){if(g[a])g[a](g)}function e(){g.remaining&&!0!==g.remaining&&g.remaining--}function k(a){var k=g.duration,n=g.offset,w=n+g.delay,r=g.currentTime,x=g.reversed,q=d(a);if(g.children.length){var u=g.children,v=u.length;
|
||||
if(q>=g.currentTime)for(var G=0;G<v;G++)u[G].seek(q);else for(;v--;)u[v].seek(q)}if(q>=w||!k)g.began||(g.began=!0,f("begin")),f("run");if(q>n&&q<k)b(q);else if(q<=n&&0!==r&&(b(0),x&&e()),q>=k&&r!==k||!k)b(k),x||e();f("update");a>=k&&(g.remaining?(t=h,"alternate"===g.direction&&(g.reversed=!g.reversed)):(g.pause(),g.completed||(g.completed=!0,f("complete"),"Promise"in window&&(p(),m=c()))),l=0)}a=void 0===a?{}:a;var h,t,l=0,p=null,m=c(),g=fa(a);g.reset=function(){var a=g.direction,c=g.loop;g.currentTime=
|
||||
0;g.progress=0;g.paused=!0;g.began=!1;g.completed=!1;g.reversed="reverse"===a;g.remaining="alternate"===a&&1===c?2:c;b(0);for(a=g.children.length;a--;)g.children[a].reset()};g.tick=function(a){h=a;t||(t=h);k((l+h-t)*q.speed)};g.seek=function(a){k(d(a))};g.pause=function(){var a=v.indexOf(g);-1<a&&v.splice(a,1);g.paused=!0};g.play=function(){g.paused&&(g.paused=!1,t=0,l=d(g.currentTime),v.push(g),B||ia())};g.reverse=function(){g.reversed=!g.reversed;t=0;l=d(g.currentTime)};g.restart=function(){g.pause();
|
||||
g.reset();g.play()};g.finished=m;g.reset();g.autoplay&&g.play();return g}var ga={update:void 0,begin:void 0,run:void 0,complete:void 0,loop:1,direction:"normal",autoplay:!0,offset:0},S={duration:1E3,delay:0,easing:"easeOutElastic",elasticity:500,round:0},W="translateX translateY translateZ rotate rotateX rotateY rotateZ scale scaleX scaleY scaleZ skewX skewY perspective".split(" "),H,h={arr:function(a){return Array.isArray(a)},obj:function(a){return-1<Object.prototype.toString.call(a).indexOf("Object")},
|
||||
pth:function(a){return h.obj(a)&&a.hasOwnProperty("totalLength")},svg:function(a){return a instanceof SVGElement},dom:function(a){return a.nodeType||h.svg(a)},str:function(a){return"string"===typeof a},fnc:function(a){return"function"===typeof a},und:function(a){return"undefined"===typeof a},hex:function(a){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a)},rgb:function(a){return/^rgb/.test(a)},hsl:function(a){return/^hsl/.test(a)},col:function(a){return h.hex(a)||h.rgb(a)||h.hsl(a)}},A=function(){function a(a,
|
||||
d,b){return(((1-3*b+3*d)*a+(3*b-6*d))*a+3*d)*a}return function(c,d,b,f){if(0<=c&&1>=c&&0<=b&&1>=b){var e=new Float32Array(11);if(c!==d||b!==f)for(var k=0;11>k;++k)e[k]=a(.1*k,c,b);return function(k){if(c===d&&b===f)return k;if(0===k)return 0;if(1===k)return 1;for(var h=0,l=1;10!==l&&e[l]<=k;++l)h+=.1;--l;var l=h+(k-e[l])/(e[l+1]-e[l])*.1,n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(.001<=n){for(h=0;4>h;++h){n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(0===n)break;var m=a(l,c,b)-k,l=l-m/n}k=l}else if(0===
|
||||
n)k=l;else{var l=h,h=h+.1,g=0;do m=l+(h-l)/2,n=a(m,c,b)-k,0<n?h=m:l=m;while(1e-7<Math.abs(n)&&10>++g);k=m}return a(k,d,f)}}}}(),Q=function(){function a(a,b){return 0===a||1===a?a:-Math.pow(2,10*(a-1))*Math.sin(2*(a-1-b/(2*Math.PI)*Math.asin(1))*Math.PI/b)}var c="Quad Cubic Quart Quint Sine Expo Circ Back Elastic".split(" "),d={In:[[.55,.085,.68,.53],[.55,.055,.675,.19],[.895,.03,.685,.22],[.755,.05,.855,.06],[.47,0,.745,.715],[.95,.05,.795,.035],[.6,.04,.98,.335],[.6,-.28,.735,.045],a],Out:[[.25,
|
||||
.46,.45,.94],[.215,.61,.355,1],[.165,.84,.44,1],[.23,1,.32,1],[.39,.575,.565,1],[.19,1,.22,1],[.075,.82,.165,1],[.175,.885,.32,1.275],function(b,c){return 1-a(1-b,c)}],InOut:[[.455,.03,.515,.955],[.645,.045,.355,1],[.77,0,.175,1],[.86,0,.07,1],[.445,.05,.55,.95],[1,0,0,1],[.785,.135,.15,.86],[.68,-.55,.265,1.55],function(b,c){return.5>b?a(2*b,c)/2:1-a(-2*b+2,c)/2}]},b={linear:A(.25,.25,.75,.75)},f={},e;for(e in d)f.type=e,d[f.type].forEach(function(a){return function(d,f){b["ease"+a.type+c[f]]=h.fnc(d)?
|
||||
d:A.apply($jscomp$this,d)}}(f)),f={type:f.type};return b}(),ha={css:function(a,c,d){return a.style[c]=d},attribute:function(a,c,d){return a.setAttribute(c,d)},object:function(a,c,d){return a[c]=d},transform:function(a,c,d,b,f){b[f]||(b[f]=[]);b[f].push(c+"("+d+")")}},v=[],B=0,ia=function(){function a(){B=requestAnimationFrame(c)}function c(c){var b=v.length;if(b){for(var d=0;d<b;)v[d]&&v[d].tick(c),d++;a()}else cancelAnimationFrame(B),B=0}return a}();q.version="2.2.0";q.speed=1;q.running=v;q.remove=
|
||||
function(a){a=P(a);for(var c=v.length;c--;)for(var d=v[c],b=d.animations,f=b.length;f--;)u(a,b[f].animatable.target)&&(b.splice(f,1),b.length||d.pause())};q.getValue=K;q.path=function(a,c){var d=h.str(a)?e(a)[0]:a,b=c||100;return function(a){return{el:d,property:a,totalLength:N(d)*(b/100)}}};q.setDashoffset=function(a){var c=N(a);a.setAttribute("stroke-dasharray",c);return c};q.bezier=A;q.easings=Q;q.timeline=function(a){var c=q(a);c.pause();c.duration=0;c.add=function(d){c.children.forEach(function(a){a.began=
|
||||
!0;a.completed=!0});m(d).forEach(function(b){var d=z(b,D(S,a||{}));d.targets=d.targets||a.targets;b=c.duration;var e=d.offset;d.autoplay=!1;d.direction=c.direction;d.offset=h.und(e)?b:L(e,b);c.began=!0;c.completed=!0;c.seek(d.offset);d=q(d);d.began=!0;d.completed=!0;d.duration>b&&(c.duration=d.duration);c.children.push(d)});c.seek(0);c.reset();c.autoplay&&c.restart();return c};return c};q.random=function(a,c){return Math.floor(Math.random()*(c-a+1))+a};return q});
|
|
@ -0,0 +1,479 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
data: {}, // Autocomplete data set
|
||||
limit: Infinity, // Limit of results the autocomplete shows
|
||||
onAutocomplete: null, // Callback for when autocompleted
|
||||
dropdownOptions: {
|
||||
// Default dropdown options
|
||||
autoFocus: false,
|
||||
closeOnClick: false,
|
||||
coverTrigger: false
|
||||
},
|
||||
minLength: 1, // Min characters before autocomplete starts
|
||||
sortFunction: function(a, b, inputString) {
|
||||
// Sort function for sorting autocomplete results
|
||||
return a.indexOf(inputString) - b.indexOf(inputString);
|
||||
},
|
||||
allowUnsafeHTML: false
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Autocomplete extends Component {
|
||||
/**
|
||||
* Construct Autocomplete instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Autocomplete, el, options);
|
||||
|
||||
this.el.M_Autocomplete = this;
|
||||
|
||||
/**
|
||||
* Options for the autocomplete
|
||||
* @member Autocomplete#options
|
||||
* @prop {Number} duration
|
||||
* @prop {Number} dist
|
||||
* @prop {number} shift
|
||||
* @prop {number} padding
|
||||
* @prop {Boolean} fullWidth
|
||||
* @prop {Boolean} indicators
|
||||
* @prop {Boolean} noWrap
|
||||
* @prop {Function} onCycleTo
|
||||
*/
|
||||
this.options = $.extend({}, Autocomplete.defaults, options);
|
||||
|
||||
// Setup
|
||||
this.isOpen = false;
|
||||
this.count = 0;
|
||||
this.activeIndex = -1;
|
||||
this.oldVal;
|
||||
this.$inputField = this.$el.closest('.input-field');
|
||||
this.$active = $();
|
||||
this._mousedown = false;
|
||||
this._setupDropdown();
|
||||
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Autocomplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this._removeDropdown();
|
||||
this.el.M_Autocomplete = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleInputBlurBound = this._handleInputBlur.bind(this);
|
||||
this._handleInputKeyupAndFocusBound = this._handleInputKeyupAndFocus.bind(this);
|
||||
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
|
||||
this._handleInputClickBound = this._handleInputClick.bind(this);
|
||||
this._handleContainerMousedownAndTouchstartBound = this._handleContainerMousedownAndTouchstart.bind(
|
||||
this
|
||||
);
|
||||
this._handleContainerMouseupAndTouchendBound = this._handleContainerMouseupAndTouchend.bind(
|
||||
this
|
||||
);
|
||||
|
||||
this.el.addEventListener('blur', this._handleInputBlurBound);
|
||||
this.el.addEventListener('keyup', this._handleInputKeyupAndFocusBound);
|
||||
this.el.addEventListener('focus', this._handleInputKeyupAndFocusBound);
|
||||
this.el.addEventListener('keydown', this._handleInputKeydownBound);
|
||||
this.el.addEventListener('click', this._handleInputClickBound);
|
||||
this.container.addEventListener(
|
||||
'mousedown',
|
||||
this._handleContainerMousedownAndTouchstartBound
|
||||
);
|
||||
this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
|
||||
|
||||
if (typeof window.ontouchstart !== 'undefined') {
|
||||
this.container.addEventListener(
|
||||
'touchstart',
|
||||
this._handleContainerMousedownAndTouchstartBound
|
||||
);
|
||||
this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchendBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('blur', this._handleInputBlurBound);
|
||||
this.el.removeEventListener('keyup', this._handleInputKeyupAndFocusBound);
|
||||
this.el.removeEventListener('focus', this._handleInputKeyupAndFocusBound);
|
||||
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
|
||||
this.el.removeEventListener('click', this._handleInputClickBound);
|
||||
this.container.removeEventListener(
|
||||
'mousedown',
|
||||
this._handleContainerMousedownAndTouchstartBound
|
||||
);
|
||||
this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
|
||||
|
||||
if (typeof window.ontouchstart !== 'undefined') {
|
||||
this.container.removeEventListener(
|
||||
'touchstart',
|
||||
this._handleContainerMousedownAndTouchstartBound
|
||||
);
|
||||
this.container.removeEventListener(
|
||||
'touchend',
|
||||
this._handleContainerMouseupAndTouchendBound
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup dropdown
|
||||
*/
|
||||
_setupDropdown() {
|
||||
this.container = document.createElement('ul');
|
||||
this.container.id = `autocomplete-options-${M.guid()}`;
|
||||
$(this.container).addClass('autocomplete-content dropdown-content');
|
||||
this.$inputField.append(this.container);
|
||||
this.el.setAttribute('data-target', this.container.id);
|
||||
|
||||
// Initialize dropdown
|
||||
let dropdownOptions = $.extend(
|
||||
{},
|
||||
Autocomplete.defaults.dropdownOptions,
|
||||
this.options.dropdownOptions
|
||||
);
|
||||
let userOnItemClick = dropdownOptions.onItemClick;
|
||||
|
||||
// Ensuring the selectOption call when user passes custom onItemClick function to dropdown
|
||||
dropdownOptions.onItemClick = (el) => {
|
||||
this.selectOption($(el));
|
||||
|
||||
// Handle user declared onItemClick if needed
|
||||
if (userOnItemClick && typeof userOnItemClick === 'function') {
|
||||
userOnItemClick.call(this.dropdown, this.el);
|
||||
}
|
||||
};
|
||||
|
||||
this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
|
||||
|
||||
// Sketchy removal of dropdown click handler
|
||||
this.el.removeEventListener('click', this.dropdown._handleClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dropdown
|
||||
*/
|
||||
_removeDropdown() {
|
||||
this.container.parentNode.removeChild(this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Blur
|
||||
*/
|
||||
_handleInputBlur() {
|
||||
if (!this._mousedown) {
|
||||
this.close();
|
||||
this._resetAutocomplete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Keyup and Focus
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleInputKeyupAndFocus(e) {
|
||||
if (e.type === 'keyup') {
|
||||
Autocomplete._keydown = false;
|
||||
}
|
||||
|
||||
this.count = 0;
|
||||
let val = this.el.value.toLowerCase();
|
||||
|
||||
// Don't capture enter or arrow key usage.
|
||||
if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the input isn't empty
|
||||
// Check if focus triggered by tab
|
||||
if (this.oldVal !== val && (M.tabPressed || e.type !== 'focus')) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
// Update oldVal
|
||||
this.oldVal = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleInputKeydown(e) {
|
||||
Autocomplete._keydown = true;
|
||||
|
||||
// Arrow keys and enter key usage
|
||||
let keyCode = e.keyCode,
|
||||
liElement,
|
||||
numItems = $(this.container).children('li').length;
|
||||
|
||||
// select element on Enter
|
||||
if (keyCode === M.keys.ENTER && this.activeIndex >= 0) {
|
||||
liElement = $(this.container)
|
||||
.children('li')
|
||||
.eq(this.activeIndex);
|
||||
if (liElement.length) {
|
||||
this.selectOption(liElement);
|
||||
e.preventDefault();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture up and down key
|
||||
if (keyCode === M.keys.ARROW_UP || keyCode === M.keys.ARROW_DOWN) {
|
||||
e.preventDefault();
|
||||
|
||||
if (keyCode === M.keys.ARROW_UP && this.activeIndex > 0) {
|
||||
this.activeIndex--;
|
||||
}
|
||||
|
||||
if (keyCode === M.keys.ARROW_DOWN && this.activeIndex < numItems - 1) {
|
||||
this.activeIndex++;
|
||||
}
|
||||
|
||||
this.$active.removeClass('active');
|
||||
if (this.activeIndex >= 0) {
|
||||
this.$active = $(this.container)
|
||||
.children('li')
|
||||
.eq(this.activeIndex);
|
||||
this.$active.addClass('active');
|
||||
|
||||
// Focus selected
|
||||
this.container.children[this.activeIndex].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleInputClick(e) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Container Mousedown and Touchstart
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleContainerMousedownAndTouchstart(e) {
|
||||
this._mousedown = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Container Mouseup and Touchend
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleContainerMouseupAndTouchend(e) {
|
||||
this._mousedown = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight partial match
|
||||
*/
|
||||
_highlight(input, label) {
|
||||
const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
|
||||
const end = start + input.length - 1;
|
||||
//custom filters may return results where the string does not match any part
|
||||
if (start == -1 || end == -1) {
|
||||
return [label, '', ''];
|
||||
}
|
||||
return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset current element position
|
||||
*/
|
||||
_resetCurrentElement() {
|
||||
this.activeIndex = -1;
|
||||
this.$active.removeClass('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset autocomplete elements
|
||||
*/
|
||||
_resetAutocomplete() {
|
||||
$(this.container).empty();
|
||||
this._resetCurrentElement();
|
||||
this.oldVal = null;
|
||||
this.isOpen = false;
|
||||
this._mousedown = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select autocomplete option
|
||||
* @param {Element} el Autocomplete option list item element
|
||||
*/
|
||||
selectOption(el) {
|
||||
let text = el.text().trim();
|
||||
this.el.value = text;
|
||||
this.$el.trigger('change');
|
||||
this._resetAutocomplete();
|
||||
this.close();
|
||||
|
||||
// Handle onAutocomplete callback.
|
||||
if (typeof this.options.onAutocomplete === 'function') {
|
||||
this.options.onAutocomplete.call(this, text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render dropdown content
|
||||
* @param {Object} data data set
|
||||
* @param {String} val current input value
|
||||
*/
|
||||
_renderDropdown(data, val) {
|
||||
this._resetAutocomplete();
|
||||
|
||||
let matchingData = [];
|
||||
|
||||
// Gather all matching data
|
||||
for (let key in data) {
|
||||
if (data.hasOwnProperty(key) && key.toLowerCase().indexOf(val) !== -1) {
|
||||
let entry = {
|
||||
data: data[key],
|
||||
key: key
|
||||
};
|
||||
matchingData.push(entry);
|
||||
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort
|
||||
if (this.options.sortFunction) {
|
||||
let sortFunctionBound = (a, b) => {
|
||||
return this.options.sortFunction(
|
||||
a.key.toLowerCase(),
|
||||
b.key.toLowerCase(),
|
||||
val.toLowerCase()
|
||||
);
|
||||
};
|
||||
matchingData.sort(sortFunctionBound);
|
||||
}
|
||||
|
||||
// Limit
|
||||
matchingData = matchingData.slice(0, this.options.limit);
|
||||
|
||||
// Render
|
||||
for (let i = 0; i < matchingData.length; i++) {
|
||||
const entry = matchingData[i];
|
||||
const item = document.createElement('li');
|
||||
if (!!entry.data) {
|
||||
const img = document.createElement('img');
|
||||
img.classList.add('right', 'circle');
|
||||
img.src = entry.data;
|
||||
item.appendChild(img);
|
||||
}
|
||||
|
||||
const parts = this._highlight(val, entry.key);
|
||||
const s = document.createElement('span');
|
||||
if (this.options.allowUnsafeHTML) {
|
||||
s.innerHTML = parts[0] + '<span class="highlight">' + parts[1] + '</span>' + parts[2];
|
||||
} else {
|
||||
s.appendChild(document.createTextNode(parts[0]));
|
||||
if (!!parts[1]) {
|
||||
const highlight = document.createElement('span');
|
||||
highlight.textContent = parts[1];
|
||||
highlight.classList.add('highlight');
|
||||
s.appendChild(highlight);
|
||||
s.appendChild(document.createTextNode(parts[2]));
|
||||
}
|
||||
}
|
||||
item.appendChild(s);
|
||||
|
||||
$(this.container).append(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Autocomplete Dropdown
|
||||
*/
|
||||
open() {
|
||||
let val = this.el.value.toLowerCase();
|
||||
|
||||
this._resetAutocomplete();
|
||||
|
||||
if (val.length >= this.options.minLength) {
|
||||
this.isOpen = true;
|
||||
this._renderDropdown(this.options.data, val);
|
||||
}
|
||||
|
||||
// Open dropdown
|
||||
if (!this.dropdown.isOpen) {
|
||||
this.dropdown.open();
|
||||
} else {
|
||||
// Recalculate dropdown when its already open
|
||||
this.dropdown.recalculateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Autocomplete Dropdown
|
||||
*/
|
||||
close() {
|
||||
this.dropdown.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Data
|
||||
* @param {Object} data
|
||||
*/
|
||||
updateData(data) {
|
||||
let val = this.el.value.toLowerCase();
|
||||
this.options.data = data;
|
||||
|
||||
if (this.isOpen) {
|
||||
this._renderDropdown(data, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Autocomplete
|
||||
*/
|
||||
Autocomplete._keydown = false;
|
||||
|
||||
M.Autocomplete = Autocomplete;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Autocomplete, 'autocomplete', 'M_Autocomplete');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,354 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
direction: 'top',
|
||||
hoverEnabled: true,
|
||||
toolbarEnabled: false
|
||||
};
|
||||
|
||||
$.fn.reverse = [].reverse;
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class FloatingActionButton extends Component {
|
||||
/**
|
||||
* Construct FloatingActionButton instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(FloatingActionButton, el, options);
|
||||
|
||||
this.el.M_FloatingActionButton = this;
|
||||
|
||||
/**
|
||||
* Options for the fab
|
||||
* @member FloatingActionButton#options
|
||||
* @prop {Boolean} [direction] - Direction fab menu opens
|
||||
* @prop {Boolean} [hoverEnabled=true] - Enable hover vs click
|
||||
* @prop {Boolean} [toolbarEnabled=false] - Enable toolbar transition
|
||||
*/
|
||||
this.options = $.extend({}, FloatingActionButton.defaults, options);
|
||||
|
||||
this.isOpen = false;
|
||||
this.$anchor = this.$el.children('a').first();
|
||||
this.$menu = this.$el.children('ul').first();
|
||||
this.$floatingBtns = this.$el.find('ul .btn-floating');
|
||||
this.$floatingBtnsReverse = this.$el.find('ul .btn-floating').reverse();
|
||||
this.offsetY = 0;
|
||||
this.offsetX = 0;
|
||||
|
||||
this.$el.addClass(`direction-${this.options.direction}`);
|
||||
if (this.options.direction === 'top') {
|
||||
this.offsetY = 40;
|
||||
} else if (this.options.direction === 'right') {
|
||||
this.offsetX = -40;
|
||||
} else if (this.options.direction === 'bottom') {
|
||||
this.offsetY = -40;
|
||||
} else {
|
||||
this.offsetX = 40;
|
||||
}
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_FloatingActionButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.M_FloatingActionButton = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleFABClickBound = this._handleFABClick.bind(this);
|
||||
this._handleOpenBound = this.open.bind(this);
|
||||
this._handleCloseBound = this.close.bind(this);
|
||||
|
||||
if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
|
||||
this.el.addEventListener('mouseenter', this._handleOpenBound);
|
||||
this.el.addEventListener('mouseleave', this._handleCloseBound);
|
||||
} else {
|
||||
this.el.addEventListener('click', this._handleFABClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
|
||||
this.el.removeEventListener('mouseenter', this._handleOpenBound);
|
||||
this.el.removeEventListener('mouseleave', this._handleCloseBound);
|
||||
} else {
|
||||
this.el.removeEventListener('click', this._handleFABClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle FAB Click
|
||||
*/
|
||||
_handleFABClick() {
|
||||
if (this.isOpen) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Document Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDocumentClick(e) {
|
||||
if (!$(e.target).closest(this.$menu).length) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open FAB
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.toolbarEnabled) {
|
||||
this._animateInToolbar();
|
||||
} else {
|
||||
this._animateInFAB();
|
||||
}
|
||||
this.isOpen = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close FAB
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.toolbarEnabled) {
|
||||
window.removeEventListener('scroll', this._handleCloseBound, true);
|
||||
document.body.removeEventListener('click', this._handleDocumentClickBound, true);
|
||||
this._animateOutToolbar();
|
||||
} else {
|
||||
this._animateOutFAB();
|
||||
}
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classic FAB Menu open
|
||||
*/
|
||||
_animateInFAB() {
|
||||
this.$el.addClass('active');
|
||||
|
||||
let time = 0;
|
||||
this.$floatingBtnsReverse.each((el) => {
|
||||
anim({
|
||||
targets: el,
|
||||
opacity: 1,
|
||||
scale: [0.4, 1],
|
||||
translateY: [this.offsetY, 0],
|
||||
translateX: [this.offsetX, 0],
|
||||
duration: 275,
|
||||
delay: time,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
time += 40;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Classic FAB Menu close
|
||||
*/
|
||||
_animateOutFAB() {
|
||||
this.$floatingBtnsReverse.each((el) => {
|
||||
anim.remove(el);
|
||||
anim({
|
||||
targets: el,
|
||||
opacity: 0,
|
||||
scale: 0.4,
|
||||
translateY: this.offsetY,
|
||||
translateX: this.offsetX,
|
||||
duration: 175,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.$el.removeClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toolbar transition Menu open
|
||||
*/
|
||||
_animateInToolbar() {
|
||||
let scaleFactor;
|
||||
let windowWidth = window.innerWidth;
|
||||
let windowHeight = window.innerHeight;
|
||||
let btnRect = this.el.getBoundingClientRect();
|
||||
let backdrop = $('<div class="fab-backdrop"></div>');
|
||||
let fabColor = this.$anchor.css('background-color');
|
||||
this.$anchor.append(backdrop);
|
||||
|
||||
this.offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
|
||||
this.offsetY = windowHeight - btnRect.bottom;
|
||||
scaleFactor = windowWidth / backdrop[0].clientWidth;
|
||||
this.btnBottom = btnRect.bottom;
|
||||
this.btnLeft = btnRect.left;
|
||||
this.btnWidth = btnRect.width;
|
||||
|
||||
// Set initial state
|
||||
this.$el.addClass('active');
|
||||
this.$el.css({
|
||||
'text-align': 'center',
|
||||
width: '100%',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
transform: 'translateX(' + this.offsetX + 'px)',
|
||||
transition: 'none'
|
||||
});
|
||||
this.$anchor.css({
|
||||
transform: 'translateY(' + -this.offsetY + 'px)',
|
||||
transition: 'none'
|
||||
});
|
||||
backdrop.css({
|
||||
'background-color': fabColor
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$el.css({
|
||||
transform: '',
|
||||
transition:
|
||||
'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s'
|
||||
});
|
||||
this.$anchor.css({
|
||||
overflow: 'visible',
|
||||
transform: '',
|
||||
transition: 'transform .2s'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$el.css({
|
||||
overflow: 'hidden',
|
||||
'background-color': fabColor
|
||||
});
|
||||
backdrop.css({
|
||||
transform: 'scale(' + scaleFactor + ')',
|
||||
transition: 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)'
|
||||
});
|
||||
this.$menu
|
||||
.children('li')
|
||||
.children('a')
|
||||
.css({
|
||||
opacity: 1
|
||||
});
|
||||
|
||||
// Scroll to close.
|
||||
this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
|
||||
window.addEventListener('scroll', this._handleCloseBound, true);
|
||||
document.body.addEventListener('click', this._handleDocumentClickBound, true);
|
||||
}, 100);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toolbar transition Menu close
|
||||
*/
|
||||
_animateOutToolbar() {
|
||||
let windowWidth = window.innerWidth;
|
||||
let windowHeight = window.innerHeight;
|
||||
let backdrop = this.$el.find('.fab-backdrop');
|
||||
let fabColor = this.$anchor.css('background-color');
|
||||
|
||||
this.offsetX = this.btnLeft - windowWidth / 2 + this.btnWidth / 2;
|
||||
this.offsetY = windowHeight - this.btnBottom;
|
||||
|
||||
// Hide backdrop
|
||||
this.$el.removeClass('active');
|
||||
this.$el.css({
|
||||
'background-color': 'transparent',
|
||||
transition: 'none'
|
||||
});
|
||||
this.$anchor.css({
|
||||
transition: 'none'
|
||||
});
|
||||
backdrop.css({
|
||||
transform: 'scale(0)',
|
||||
'background-color': fabColor
|
||||
});
|
||||
this.$menu
|
||||
.children('li')
|
||||
.children('a')
|
||||
.css({
|
||||
opacity: ''
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
backdrop.remove();
|
||||
|
||||
// Set initial state.
|
||||
this.$el.css({
|
||||
'text-align': '',
|
||||
width: '',
|
||||
bottom: '',
|
||||
left: '',
|
||||
overflow: '',
|
||||
'background-color': '',
|
||||
transform: 'translate3d(' + -this.offsetX + 'px,0,0)'
|
||||
});
|
||||
this.$anchor.css({
|
||||
overflow: '',
|
||||
transform: 'translate3d(0,' + this.offsetY + 'px,0)'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$el.css({
|
||||
transform: 'translate3d(0,0,0)',
|
||||
transition: 'transform .2s'
|
||||
});
|
||||
this.$anchor.css({
|
||||
transform: 'translate3d(0,0,0)',
|
||||
transition: 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)'
|
||||
});
|
||||
}, 20);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
M.FloatingActionButton = FloatingActionButton;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(
|
||||
FloatingActionButton,
|
||||
'floatingActionButton',
|
||||
'M_FloatingActionButton'
|
||||
);
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,40 @@
|
|||
(function($, anim) {
|
||||
$(document).on('click', '.card', function(e) {
|
||||
if ($(this).children('.card-reveal').length) {
|
||||
var $card = $(e.target).closest('.card');
|
||||
if ($card.data('initialOverflow') === undefined) {
|
||||
$card.data(
|
||||
'initialOverflow',
|
||||
$card.css('overflow') === undefined ? '' : $card.css('overflow')
|
||||
);
|
||||
}
|
||||
let $cardReveal = $(this).find('.card-reveal');
|
||||
if (
|
||||
$(e.target).is($('.card-reveal .card-title')) ||
|
||||
$(e.target).is($('.card-reveal .card-title i'))
|
||||
) {
|
||||
// Make Reveal animate down and display none
|
||||
anim({
|
||||
targets: $cardReveal[0],
|
||||
translateY: 0,
|
||||
duration: 225,
|
||||
easing: 'easeInOutQuad',
|
||||
complete: function(anim) {
|
||||
let el = anim.animatables[0].target;
|
||||
$(el).css({ display: 'none' });
|
||||
$card.css('overflow', $card.data('initialOverflow'));
|
||||
}
|
||||
});
|
||||
} else if ($(e.target).is($('.card .activator')) || $(e.target).is($('.card .activator i'))) {
|
||||
$card.css('overflow', 'hidden');
|
||||
$cardReveal.css({ display: 'block' });
|
||||
anim({
|
||||
targets: $cardReveal[0],
|
||||
translateY: '-100%',
|
||||
duration: 300,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,732 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
duration: 200, // ms
|
||||
dist: -100, // zoom scale TODO: make this more intuitive as an option
|
||||
shift: 0, // spacing for center image
|
||||
padding: 0, // Padding between non center items
|
||||
numVisible: 5, // Number of visible items in carousel
|
||||
fullWidth: false, // Change to full width styles
|
||||
indicators: false, // Toggle indicators
|
||||
noWrap: false, // Don't wrap around and cycle through items.
|
||||
onCycleTo: null // Callback for when a new slide is cycled to.
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Carousel extends Component {
|
||||
/**
|
||||
* Construct Carousel instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Carousel, el, options);
|
||||
|
||||
this.el.M_Carousel = this;
|
||||
|
||||
/**
|
||||
* Options for the carousel
|
||||
* @member Carousel#options
|
||||
* @prop {Number} duration
|
||||
* @prop {Number} dist
|
||||
* @prop {Number} shift
|
||||
* @prop {Number} padding
|
||||
* @prop {Number} numVisible
|
||||
* @prop {Boolean} fullWidth
|
||||
* @prop {Boolean} indicators
|
||||
* @prop {Boolean} noWrap
|
||||
* @prop {Function} onCycleTo
|
||||
*/
|
||||
this.options = $.extend({}, Carousel.defaults, options);
|
||||
|
||||
// Setup
|
||||
this.hasMultipleSlides = this.$el.find('.carousel-item').length > 1;
|
||||
this.showIndicators = this.options.indicators && this.hasMultipleSlides;
|
||||
this.noWrap = this.options.noWrap || !this.hasMultipleSlides;
|
||||
this.pressed = false;
|
||||
this.dragged = false;
|
||||
this.offset = this.target = 0;
|
||||
this.images = [];
|
||||
this.itemWidth = this.$el
|
||||
.find('.carousel-item')
|
||||
.first()
|
||||
.innerWidth();
|
||||
this.itemHeight = this.$el
|
||||
.find('.carousel-item')
|
||||
.first()
|
||||
.innerHeight();
|
||||
this.dim = this.itemWidth * 2 + this.options.padding || 1; // Make sure dim is non zero for divisions.
|
||||
this._autoScrollBound = this._autoScroll.bind(this);
|
||||
this._trackBound = this._track.bind(this);
|
||||
|
||||
// Full Width carousel setup
|
||||
if (this.options.fullWidth) {
|
||||
this.options.dist = 0;
|
||||
this._setCarouselHeight();
|
||||
|
||||
// Offset fixed items when indicators.
|
||||
if (this.showIndicators) {
|
||||
this.$el.find('.carousel-fixed-item').addClass('with-indicators');
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through slides
|
||||
this.$indicators = $('<ul class="indicators"></ul>');
|
||||
this.$el.find('.carousel-item').each((el, i) => {
|
||||
this.images.push(el);
|
||||
if (this.showIndicators) {
|
||||
let $indicator = $('<li class="indicator-item"></li>');
|
||||
|
||||
// Add active to first by default.
|
||||
if (i === 0) {
|
||||
$indicator[0].classList.add('active');
|
||||
}
|
||||
|
||||
this.$indicators.append($indicator);
|
||||
}
|
||||
});
|
||||
if (this.showIndicators) {
|
||||
this.$el.append(this.$indicators);
|
||||
}
|
||||
this.count = this.images.length;
|
||||
|
||||
// Cap numVisible at count
|
||||
this.options.numVisible = Math.min(this.count, this.options.numVisible);
|
||||
|
||||
// Setup cross browser string
|
||||
this.xform = 'transform';
|
||||
['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
|
||||
var e = prefix + 'Transform';
|
||||
if (typeof document.body.style[e] !== 'undefined') {
|
||||
this.xform = e;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
this._setupEventHandlers();
|
||||
this._scroll(this.offset);
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Carousel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.M_Carousel = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleCarouselTapBound = this._handleCarouselTap.bind(this);
|
||||
this._handleCarouselDragBound = this._handleCarouselDrag.bind(this);
|
||||
this._handleCarouselReleaseBound = this._handleCarouselRelease.bind(this);
|
||||
this._handleCarouselClickBound = this._handleCarouselClick.bind(this);
|
||||
|
||||
if (typeof window.ontouchstart !== 'undefined') {
|
||||
this.el.addEventListener('touchstart', this._handleCarouselTapBound);
|
||||
this.el.addEventListener('touchmove', this._handleCarouselDragBound);
|
||||
this.el.addEventListener('touchend', this._handleCarouselReleaseBound);
|
||||
}
|
||||
|
||||
this.el.addEventListener('mousedown', this._handleCarouselTapBound);
|
||||
this.el.addEventListener('mousemove', this._handleCarouselDragBound);
|
||||
this.el.addEventListener('mouseup', this._handleCarouselReleaseBound);
|
||||
this.el.addEventListener('mouseleave', this._handleCarouselReleaseBound);
|
||||
this.el.addEventListener('click', this._handleCarouselClickBound);
|
||||
|
||||
if (this.showIndicators && this.$indicators) {
|
||||
this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
|
||||
this.$indicators.find('.indicator-item').each((el, i) => {
|
||||
el.addEventListener('click', this._handleIndicatorClickBound);
|
||||
});
|
||||
}
|
||||
|
||||
// Resize
|
||||
let throttledResize = M.throttle(this._handleResize, 200);
|
||||
this._handleThrottledResizeBound = throttledResize.bind(this);
|
||||
|
||||
window.addEventListener('resize', this._handleThrottledResizeBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
if (typeof window.ontouchstart !== 'undefined') {
|
||||
this.el.removeEventListener('touchstart', this._handleCarouselTapBound);
|
||||
this.el.removeEventListener('touchmove', this._handleCarouselDragBound);
|
||||
this.el.removeEventListener('touchend', this._handleCarouselReleaseBound);
|
||||
}
|
||||
this.el.removeEventListener('mousedown', this._handleCarouselTapBound);
|
||||
this.el.removeEventListener('mousemove', this._handleCarouselDragBound);
|
||||
this.el.removeEventListener('mouseup', this._handleCarouselReleaseBound);
|
||||
this.el.removeEventListener('mouseleave', this._handleCarouselReleaseBound);
|
||||
this.el.removeEventListener('click', this._handleCarouselClickBound);
|
||||
|
||||
if (this.showIndicators && this.$indicators) {
|
||||
this.$indicators.find('.indicator-item').each((el, i) => {
|
||||
el.removeEventListener('click', this._handleIndicatorClickBound);
|
||||
});
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', this._handleThrottledResizeBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Carousel Tap
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCarouselTap(e) {
|
||||
// Fixes firefox draggable image bug
|
||||
if (e.type === 'mousedown' && $(e.target).is('img')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.pressed = true;
|
||||
this.dragged = false;
|
||||
this.verticalDragged = false;
|
||||
this.reference = this._xpos(e);
|
||||
this.referenceY = this._ypos(e);
|
||||
|
||||
this.velocity = this.amplitude = 0;
|
||||
this.frame = this.offset;
|
||||
this.timestamp = Date.now();
|
||||
clearInterval(this.ticker);
|
||||
this.ticker = setInterval(this._trackBound, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Carousel Drag
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCarouselDrag(e) {
|
||||
let x, y, delta, deltaY;
|
||||
if (this.pressed) {
|
||||
x = this._xpos(e);
|
||||
y = this._ypos(e);
|
||||
delta = this.reference - x;
|
||||
deltaY = Math.abs(this.referenceY - y);
|
||||
if (deltaY < 30 && !this.verticalDragged) {
|
||||
// If vertical scrolling don't allow dragging.
|
||||
if (delta > 2 || delta < -2) {
|
||||
this.dragged = true;
|
||||
this.reference = x;
|
||||
this._scroll(this.offset + delta);
|
||||
}
|
||||
} else if (this.dragged) {
|
||||
// If dragging don't allow vertical scroll.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
} else {
|
||||
// Vertical scrolling.
|
||||
this.verticalDragged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.dragged) {
|
||||
// If dragging don't allow vertical scroll.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Carousel Release
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCarouselRelease(e) {
|
||||
if (this.pressed) {
|
||||
this.pressed = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
clearInterval(this.ticker);
|
||||
this.target = this.offset;
|
||||
if (this.velocity > 10 || this.velocity < -10) {
|
||||
this.amplitude = 0.9 * this.velocity;
|
||||
this.target = this.offset + this.amplitude;
|
||||
}
|
||||
this.target = Math.round(this.target / this.dim) * this.dim;
|
||||
|
||||
// No wrap of items.
|
||||
if (this.noWrap) {
|
||||
if (this.target >= this.dim * (this.count - 1)) {
|
||||
this.target = this.dim * (this.count - 1);
|
||||
} else if (this.target < 0) {
|
||||
this.target = 0;
|
||||
}
|
||||
}
|
||||
this.amplitude = this.target - this.offset;
|
||||
this.timestamp = Date.now();
|
||||
requestAnimationFrame(this._autoScrollBound);
|
||||
|
||||
if (this.dragged) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Carousel Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCarouselClick(e) {
|
||||
// Disable clicks if carousel was dragged.
|
||||
if (this.dragged) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
} else if (!this.options.fullWidth) {
|
||||
let clickedIndex = $(e.target)
|
||||
.closest('.carousel-item')
|
||||
.index();
|
||||
let diff = this._wrap(this.center) - clickedIndex;
|
||||
|
||||
// Disable clicks if carousel was shifted by click
|
||||
if (diff !== 0) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// fixes https://github.com/materializecss/materialize/issues/180
|
||||
if (clickedIndex < 0) {
|
||||
// relative X position > center of carousel = clicked at the right part of the carousel
|
||||
if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
|
||||
this.next();
|
||||
} else {
|
||||
this.prev();
|
||||
}
|
||||
} else {
|
||||
this._cycleTo(clickedIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Indicator CLick
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleIndicatorClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
let indicator = $(e.target).closest('.indicator-item');
|
||||
if (indicator.length) {
|
||||
this._cycleTo(indicator.index());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Throttle Resize
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleResize(e) {
|
||||
if (this.options.fullWidth) {
|
||||
this.itemWidth = this.$el
|
||||
.find('.carousel-item')
|
||||
.first()
|
||||
.innerWidth();
|
||||
this.imageHeight = this.$el.find('.carousel-item.active').height();
|
||||
this.dim = this.itemWidth * 2 + this.options.padding;
|
||||
this.offset = this.center * 2 * this.itemWidth;
|
||||
this.target = this.offset;
|
||||
this._setCarouselHeight(true);
|
||||
} else {
|
||||
this._scroll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set carousel height based on first slide
|
||||
* @param {Booleam} imageOnly - true for image slides
|
||||
*/
|
||||
_setCarouselHeight(imageOnly) {
|
||||
let firstSlide = this.$el.find('.carousel-item.active').length
|
||||
? this.$el.find('.carousel-item.active').first()
|
||||
: this.$el.find('.carousel-item').first();
|
||||
let firstImage = firstSlide.find('img').first();
|
||||
if (firstImage.length) {
|
||||
if (firstImage[0].complete) {
|
||||
// If image won't trigger the load event
|
||||
let imageHeight = firstImage.height();
|
||||
if (imageHeight > 0) {
|
||||
this.$el.css('height', imageHeight + 'px');
|
||||
} else {
|
||||
// If image still has no height, use the natural dimensions to calculate
|
||||
let naturalWidth = firstImage[0].naturalWidth;
|
||||
let naturalHeight = firstImage[0].naturalHeight;
|
||||
let adjustedHeight = (this.$el.width() / naturalWidth) * naturalHeight;
|
||||
this.$el.css('height', adjustedHeight + 'px');
|
||||
}
|
||||
} else {
|
||||
// Get height when image is loaded normally
|
||||
firstImage.one('load', (el, i) => {
|
||||
this.$el.css('height', el.offsetHeight + 'px');
|
||||
});
|
||||
}
|
||||
} else if (!imageOnly) {
|
||||
let slideHeight = firstSlide.height();
|
||||
this.$el.css('height', slideHeight + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get x position from event
|
||||
* @param {Event} e
|
||||
*/
|
||||
_xpos(e) {
|
||||
// touch event
|
||||
if (e.targetTouches && e.targetTouches.length >= 1) {
|
||||
return e.targetTouches[0].clientX;
|
||||
}
|
||||
|
||||
// mouse event
|
||||
return e.clientX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get y position from event
|
||||
* @param {Event} e
|
||||
*/
|
||||
_ypos(e) {
|
||||
// touch event
|
||||
if (e.targetTouches && e.targetTouches.length >= 1) {
|
||||
return e.targetTouches[0].clientY;
|
||||
}
|
||||
|
||||
// mouse event
|
||||
return e.clientY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap index
|
||||
* @param {Number} x
|
||||
*/
|
||||
_wrap(x) {
|
||||
return x >= this.count
|
||||
? x % this.count
|
||||
: x < 0
|
||||
? this._wrap(this.count + (x % this.count))
|
||||
: x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks scrolling information
|
||||
*/
|
||||
_track() {
|
||||
let now, elapsed, delta, v;
|
||||
|
||||
now = Date.now();
|
||||
elapsed = now - this.timestamp;
|
||||
this.timestamp = now;
|
||||
delta = this.offset - this.frame;
|
||||
this.frame = this.offset;
|
||||
|
||||
v = (1000 * delta) / (1 + elapsed);
|
||||
this.velocity = 0.8 * v + 0.2 * this.velocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto scrolls to nearest carousel item.
|
||||
*/
|
||||
_autoScroll() {
|
||||
let elapsed, delta;
|
||||
|
||||
if (this.amplitude) {
|
||||
elapsed = Date.now() - this.timestamp;
|
||||
delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
|
||||
if (delta > 2 || delta < -2) {
|
||||
this._scroll(this.target - delta);
|
||||
requestAnimationFrame(this._autoScrollBound);
|
||||
} else {
|
||||
this._scroll(this.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to target
|
||||
* @param {Number} x
|
||||
*/
|
||||
_scroll(x) {
|
||||
// Track scrolling state
|
||||
if (!this.$el.hasClass('scrolling')) {
|
||||
this.el.classList.add('scrolling');
|
||||
}
|
||||
if (this.scrollingTimeout != null) {
|
||||
window.clearTimeout(this.scrollingTimeout);
|
||||
}
|
||||
this.scrollingTimeout = window.setTimeout(() => {
|
||||
this.$el.removeClass('scrolling');
|
||||
}, this.options.duration);
|
||||
|
||||
// Start actual scroll
|
||||
let i,
|
||||
half,
|
||||
delta,
|
||||
dir,
|
||||
tween,
|
||||
el,
|
||||
alignment,
|
||||
zTranslation,
|
||||
tweenedOpacity,
|
||||
centerTweenedOpacity;
|
||||
let lastCenter = this.center;
|
||||
let numVisibleOffset = 1 / this.options.numVisible;
|
||||
|
||||
this.offset = typeof x === 'number' ? x : this.offset;
|
||||
this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
|
||||
delta = this.offset - this.center * this.dim;
|
||||
dir = delta < 0 ? 1 : -1;
|
||||
tween = (-dir * delta * 2) / this.dim;
|
||||
half = this.count >> 1;
|
||||
|
||||
if (this.options.fullWidth) {
|
||||
alignment = 'translateX(0)';
|
||||
centerTweenedOpacity = 1;
|
||||
} else {
|
||||
alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
|
||||
alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
|
||||
centerTweenedOpacity = 1 - numVisibleOffset * tween;
|
||||
}
|
||||
|
||||
// Set indicator active
|
||||
if (this.showIndicators) {
|
||||
let diff = this.center % this.count;
|
||||
let activeIndicator = this.$indicators.find('.indicator-item.active');
|
||||
if (activeIndicator.index() !== diff) {
|
||||
activeIndicator.removeClass('active');
|
||||
this.$indicators
|
||||
.find('.indicator-item')
|
||||
.eq(diff)[0]
|
||||
.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
// center
|
||||
// Don't show wrapped items.
|
||||
if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
|
||||
el = this.images[this._wrap(this.center)];
|
||||
|
||||
// Add active class to center item.
|
||||
if (!$(el).hasClass('active')) {
|
||||
this.$el.find('.carousel-item').removeClass('active');
|
||||
el.classList.add('active');
|
||||
}
|
||||
let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
|
||||
this.options.shift *
|
||||
tween *
|
||||
i}px) translateZ(${this.options.dist * tween}px)`;
|
||||
this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
|
||||
}
|
||||
|
||||
for (i = 1; i <= half; ++i) {
|
||||
// right side
|
||||
if (this.options.fullWidth) {
|
||||
zTranslation = this.options.dist;
|
||||
tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
|
||||
} else {
|
||||
zTranslation = this.options.dist * (i * 2 + tween * dir);
|
||||
tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
|
||||
}
|
||||
// Don't show wrapped items.
|
||||
if (!this.noWrap || this.center + i < this.count) {
|
||||
el = this.images[this._wrap(this.center + i)];
|
||||
let transformString = `${alignment} translateX(${this.options.shift +
|
||||
(this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
||||
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
||||
}
|
||||
|
||||
// left side
|
||||
if (this.options.fullWidth) {
|
||||
zTranslation = this.options.dist;
|
||||
tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
|
||||
} else {
|
||||
zTranslation = this.options.dist * (i * 2 - tween * dir);
|
||||
tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
|
||||
}
|
||||
// Don't show wrapped items.
|
||||
if (!this.noWrap || this.center - i >= 0) {
|
||||
el = this.images[this._wrap(this.center - i)];
|
||||
let transformString = `${alignment} translateX(${-this.options.shift +
|
||||
(-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
||||
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
||||
}
|
||||
}
|
||||
|
||||
// center
|
||||
// Don't show wrapped items.
|
||||
if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
|
||||
el = this.images[this._wrap(this.center)];
|
||||
let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
|
||||
this.options.shift *
|
||||
tween}px) translateZ(${this.options.dist * tween}px)`;
|
||||
this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
|
||||
}
|
||||
|
||||
// onCycleTo callback
|
||||
let $currItem = this.$el.find('.carousel-item').eq(this._wrap(this.center));
|
||||
if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
|
||||
this.options.onCycleTo.call(this, $currItem[0], this.dragged);
|
||||
}
|
||||
|
||||
// One time callback
|
||||
if (typeof this.oneTimeCallback === 'function') {
|
||||
this.oneTimeCallback.call(this, $currItem[0], this.dragged);
|
||||
this.oneTimeCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to target
|
||||
* @param {Element} el
|
||||
* @param {Number} opacity
|
||||
* @param {Number} zIndex
|
||||
* @param {String} transform
|
||||
*/
|
||||
_updateItemStyle(el, opacity, zIndex, transform) {
|
||||
el.style[this.xform] = transform;
|
||||
el.style.zIndex = zIndex;
|
||||
el.style.opacity = opacity;
|
||||
el.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to target
|
||||
* @param {Number} n
|
||||
* @param {Function} callback
|
||||
*/
|
||||
_cycleTo(n, callback) {
|
||||
let diff = (this.center % this.count) - n;
|
||||
|
||||
// Account for wraparound.
|
||||
if (!this.noWrap) {
|
||||
if (diff < 0) {
|
||||
if (Math.abs(diff + this.count) < Math.abs(diff)) {
|
||||
diff += this.count;
|
||||
}
|
||||
} else if (diff > 0) {
|
||||
if (Math.abs(diff - this.count) < diff) {
|
||||
diff -= this.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.target = this.dim * Math.round(this.offset / this.dim);
|
||||
// Next
|
||||
if (diff < 0) {
|
||||
this.target += this.dim * Math.abs(diff);
|
||||
|
||||
// Prev
|
||||
} else if (diff > 0) {
|
||||
this.target -= this.dim * diff;
|
||||
}
|
||||
|
||||
// Set one time callback
|
||||
if (typeof callback === 'function') {
|
||||
this.oneTimeCallback = callback;
|
||||
}
|
||||
|
||||
// Scroll
|
||||
if (this.offset !== this.target) {
|
||||
this.amplitude = this.target - this.offset;
|
||||
this.timestamp = Date.now();
|
||||
requestAnimationFrame(this._autoScrollBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to next item
|
||||
* @param {Number} [n]
|
||||
*/
|
||||
next(n) {
|
||||
if (n === undefined || isNaN(n)) {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
let index = this.center + n;
|
||||
if (index >= this.count || index < 0) {
|
||||
if (this.noWrap) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = this._wrap(index);
|
||||
}
|
||||
this._cycleTo(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to previous item
|
||||
* @param {Number} [n]
|
||||
*/
|
||||
prev(n) {
|
||||
if (n === undefined || isNaN(n)) {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
let index = this.center - n;
|
||||
if (index >= this.count || index < 0) {
|
||||
if (this.noWrap) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = this._wrap(index);
|
||||
}
|
||||
|
||||
this._cycleTo(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to nth item
|
||||
* @param {Number} [n]
|
||||
* @param {Function} callback
|
||||
*/
|
||||
set(n, callback) {
|
||||
if (n === undefined || isNaN(n)) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (n > this.count || n < 0) {
|
||||
if (this.noWrap) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = this._wrap(n);
|
||||
}
|
||||
|
||||
this._cycleTo(n, callback);
|
||||
}
|
||||
}
|
||||
|
||||
M.Carousel = Carousel;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Carousel, 'carousel', 'M_Carousel');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,960 @@
|
|||
/*! cash-dom 1.3.5, https://github.com/kenwheeler/cash @license MIT */
|
||||
(function (factory) {
|
||||
window.cash = factory();
|
||||
})(function () {
|
||||
var doc = document, win = window, ArrayProto = Array.prototype, slice = ArrayProto.slice, filter = ArrayProto.filter, push = ArrayProto.push;
|
||||
|
||||
var noop = function () {}, isFunction = function (item) {
|
||||
// @see https://crbug.com/568448
|
||||
return typeof item === typeof noop && item.call;
|
||||
}, isString = function (item) {
|
||||
return typeof item === typeof "";
|
||||
};
|
||||
|
||||
var idMatch = /^#[\w-]*$/, classMatch = /^\.[\w-]*$/, htmlMatch = /<.+>/, singlet = /^\w+$/;
|
||||
|
||||
function find(selector, context) {
|
||||
context = context || doc;
|
||||
var elems = (classMatch.test(selector) ? context.getElementsByClassName(selector.slice(1)) : singlet.test(selector) ? context.getElementsByTagName(selector) : context.querySelectorAll(selector));
|
||||
return elems;
|
||||
}
|
||||
|
||||
var frag;
|
||||
function parseHTML(str) {
|
||||
if (!frag) {
|
||||
frag = doc.implementation.createHTMLDocument(null);
|
||||
var base = frag.createElement("base");
|
||||
base.href = doc.location.href;
|
||||
frag.head.appendChild(base);
|
||||
}
|
||||
|
||||
frag.body.innerHTML = str;
|
||||
|
||||
return frag.body.childNodes;
|
||||
}
|
||||
|
||||
function onReady(fn) {
|
||||
if (doc.readyState !== "loading") {
|
||||
fn();
|
||||
} else {
|
||||
doc.addEventListener("DOMContentLoaded", fn);
|
||||
}
|
||||
}
|
||||
|
||||
function Init(selector, context) {
|
||||
if (!selector) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// If already a cash collection, don't do any further processing
|
||||
if (selector.cash && selector !== win) {
|
||||
return selector;
|
||||
}
|
||||
|
||||
var elems = selector, i = 0, length;
|
||||
|
||||
if (isString(selector)) {
|
||||
elems = (idMatch.test(selector) ?
|
||||
// If an ID use the faster getElementById check
|
||||
doc.getElementById(selector.slice(1)) : htmlMatch.test(selector) ?
|
||||
// If HTML, parse it into real elements
|
||||
parseHTML(selector) :
|
||||
// else use `find`
|
||||
find(selector, context));
|
||||
|
||||
// If function, use as shortcut for DOM ready
|
||||
} else if (isFunction(selector)) {
|
||||
onReady(selector);return this;
|
||||
}
|
||||
|
||||
if (!elems) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// If a single DOM element is passed in or received via ID, return the single element
|
||||
if (elems.nodeType || elems === win) {
|
||||
this[0] = elems;
|
||||
this.length = 1;
|
||||
} else {
|
||||
// Treat like an array and loop through each item.
|
||||
length = this.length = elems.length;
|
||||
for (; i < length; i++) {
|
||||
this[i] = elems[i];
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function cash(selector, context) {
|
||||
return new Init(selector, context);
|
||||
}
|
||||
|
||||
var fn = cash.fn = cash.prototype = Init.prototype = { // jshint ignore:line
|
||||
cash: true,
|
||||
length: 0,
|
||||
push: push,
|
||||
splice: ArrayProto.splice,
|
||||
map: ArrayProto.map,
|
||||
init: Init
|
||||
};
|
||||
|
||||
Object.defineProperty(fn, "constructor", { value: cash });
|
||||
|
||||
cash.parseHTML = parseHTML;
|
||||
cash.noop = noop;
|
||||
cash.isFunction = isFunction;
|
||||
cash.isString = isString;
|
||||
|
||||
cash.extend = fn.extend = function (target) {
|
||||
target = target || {};
|
||||
|
||||
var args = slice.call(arguments), length = args.length, i = 1;
|
||||
|
||||
if (args.length === 1) {
|
||||
target = this;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (!args[i]) {
|
||||
continue;
|
||||
}
|
||||
for (var key in args[i]) {
|
||||
if (args[i].hasOwnProperty(key)) {
|
||||
target[key] = args[i][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
function each(collection, callback) {
|
||||
var l = collection.length, i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
if (callback.call(collection[i], collection[i], i, collection) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function matches(el, selector) {
|
||||
var m = el && (el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector || el.oMatchesSelector);
|
||||
return !!m && m.call(el, selector);
|
||||
}
|
||||
|
||||
function getCompareFunction(selector) {
|
||||
return (
|
||||
/* Use browser's `matches` function if string */
|
||||
isString(selector) ? matches :
|
||||
/* Match a cash element */
|
||||
selector.cash ? function (el) {
|
||||
return selector.is(el);
|
||||
} :
|
||||
/* Direct comparison */
|
||||
function (el, selector) {
|
||||
return el === selector;
|
||||
});
|
||||
}
|
||||
|
||||
function unique(collection) {
|
||||
return cash(slice.call(collection).filter(function (item, index, self) {
|
||||
return self.indexOf(item) === index;
|
||||
}));
|
||||
}
|
||||
|
||||
cash.extend({
|
||||
merge: function (first, second) {
|
||||
var len = +second.length, i = first.length, j = 0;
|
||||
|
||||
for (; j < len; i++, j++) {
|
||||
first[i] = second[j];
|
||||
}
|
||||
|
||||
first.length = i;
|
||||
return first;
|
||||
},
|
||||
|
||||
each: each,
|
||||
matches: matches,
|
||||
unique: unique,
|
||||
isArray: Array.isArray,
|
||||
isNumeric: function (n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var uid = cash.uid = "_cash" + Date.now();
|
||||
|
||||
function getDataCache(node) {
|
||||
return (node[uid] = node[uid] || {});
|
||||
}
|
||||
|
||||
function setData(node, key, value) {
|
||||
return (getDataCache(node)[key] = value);
|
||||
}
|
||||
|
||||
function getData(node, key) {
|
||||
var c = getDataCache(node);
|
||||
if (c[key] === undefined) {
|
||||
c[key] = node.dataset ? node.dataset[key] : cash(node).attr("data-" + key);
|
||||
}
|
||||
return c[key];
|
||||
}
|
||||
|
||||
function removeData(node, key) {
|
||||
var c = getDataCache(node);
|
||||
if (c) {
|
||||
delete c[key];
|
||||
} else if (node.dataset) {
|
||||
delete node.dataset[key];
|
||||
} else {
|
||||
cash(node).removeAttr("data-" + name);
|
||||
}
|
||||
}
|
||||
|
||||
fn.extend({
|
||||
data: function (name, value) {
|
||||
if (isString(name)) {
|
||||
return (value === undefined ? getData(this[0], name) : this.each(function (v) {
|
||||
return setData(v, name, value);
|
||||
}));
|
||||
}
|
||||
|
||||
for (var key in name) {
|
||||
this.data(key, name[key]);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
removeData: function (key) {
|
||||
return this.each(function (v) {
|
||||
return removeData(v, key);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var notWhiteMatch = /\S+/g;
|
||||
|
||||
function getClasses(c) {
|
||||
return isString(c) && c.match(notWhiteMatch);
|
||||
}
|
||||
|
||||
function hasClass(v, c) {
|
||||
return (v.classList ? v.classList.contains(c) : new RegExp("(^| )" + c + "( |$)", "gi").test(v.className));
|
||||
}
|
||||
|
||||
function addClass(v, c, spacedName) {
|
||||
if (v.classList) {
|
||||
v.classList.add(c);
|
||||
} else if (spacedName.indexOf(" " + c + " ")) {
|
||||
v.className += " " + c;
|
||||
}
|
||||
}
|
||||
|
||||
function removeClass(v, c) {
|
||||
if (v.classList) {
|
||||
v.classList.remove(c);
|
||||
} else {
|
||||
v.className = v.className.replace(c, "");
|
||||
}
|
||||
}
|
||||
|
||||
fn.extend({
|
||||
addClass: function (c) {
|
||||
var classes = getClasses(c);
|
||||
|
||||
return (classes ? this.each(function (v) {
|
||||
var spacedName = " " + v.className + " ";
|
||||
each(classes, function (c) {
|
||||
addClass(v, c, spacedName);
|
||||
});
|
||||
}) : this);
|
||||
},
|
||||
|
||||
attr: function (name, value) {
|
||||
if (!name) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isString(name)) {
|
||||
if (value === undefined) {
|
||||
return this[0] ? this[0].getAttribute ? this[0].getAttribute(name) : this[0][name] : undefined;
|
||||
}
|
||||
|
||||
return this.each(function (v) {
|
||||
if (v.setAttribute) {
|
||||
v.setAttribute(name, value);
|
||||
} else {
|
||||
v[name] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (var key in name) {
|
||||
this.attr(key, name[key]);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
hasClass: function (c) {
|
||||
var check = false, classes = getClasses(c);
|
||||
if (classes && classes.length) {
|
||||
this.each(function (v) {
|
||||
check = hasClass(v, classes[0]);
|
||||
return !check;
|
||||
});
|
||||
}
|
||||
return check;
|
||||
},
|
||||
|
||||
prop: function (name, value) {
|
||||
if (isString(name)) {
|
||||
return (value === undefined ? this[0][name] : this.each(function (v) {
|
||||
v[name] = value;
|
||||
}));
|
||||
}
|
||||
|
||||
for (var key in name) {
|
||||
this.prop(key, name[key]);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
removeAttr: function (name) {
|
||||
return this.each(function (v) {
|
||||
if (v.removeAttribute) {
|
||||
v.removeAttribute(name);
|
||||
} else {
|
||||
delete v[name];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeClass: function (c) {
|
||||
if (!arguments.length) {
|
||||
return this.attr("class", "");
|
||||
}
|
||||
var classes = getClasses(c);
|
||||
return (classes ? this.each(function (v) {
|
||||
each(classes, function (c) {
|
||||
removeClass(v, c);
|
||||
});
|
||||
}) : this);
|
||||
},
|
||||
|
||||
removeProp: function (name) {
|
||||
return this.each(function (v) {
|
||||
delete v[name];
|
||||
});
|
||||
},
|
||||
|
||||
toggleClass: function (c, state) {
|
||||
if (state !== undefined) {
|
||||
return this[state ? "addClass" : "removeClass"](c);
|
||||
}
|
||||
var classes = getClasses(c);
|
||||
return (classes ? this.each(function (v) {
|
||||
var spacedName = " " + v.className + " ";
|
||||
each(classes, function (c) {
|
||||
if (hasClass(v, c)) {
|
||||
removeClass(v, c);
|
||||
} else {
|
||||
addClass(v, c, spacedName);
|
||||
}
|
||||
});
|
||||
}) : this);
|
||||
} });
|
||||
|
||||
fn.extend({
|
||||
add: function (selector, context) {
|
||||
return unique(cash.merge(this, cash(selector, context)));
|
||||
},
|
||||
|
||||
each: function (callback) {
|
||||
each(this, callback);
|
||||
return this;
|
||||
},
|
||||
|
||||
eq: function (index) {
|
||||
return cash(this.get(index));
|
||||
},
|
||||
|
||||
filter: function (selector) {
|
||||
if (!selector) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var comparator = (isFunction(selector) ? selector : getCompareFunction(selector));
|
||||
|
||||
return cash(filter.call(this, function (e) {
|
||||
return comparator(e, selector);
|
||||
}));
|
||||
},
|
||||
|
||||
first: function () {
|
||||
return this.eq(0);
|
||||
},
|
||||
|
||||
get: function (index) {
|
||||
if (index === undefined) {
|
||||
return slice.call(this);
|
||||
}
|
||||
return (index < 0 ? this[index + this.length] : this[index]);
|
||||
},
|
||||
|
||||
index: function (elem) {
|
||||
var child = elem ? cash(elem)[0] : this[0], collection = elem ? this : cash(child).parent().children();
|
||||
return slice.call(collection).indexOf(child);
|
||||
},
|
||||
|
||||
last: function () {
|
||||
return this.eq(-1);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var camelCase = (function () {
|
||||
var camelRegex = /(?:^\w|[A-Z]|\b\w)/g, whiteSpace = /[\s-_]+/g;
|
||||
return function (str) {
|
||||
return str.replace(camelRegex, function (letter, index) {
|
||||
return letter[index === 0 ? "toLowerCase" : "toUpperCase"]();
|
||||
}).replace(whiteSpace, "");
|
||||
};
|
||||
}());
|
||||
|
||||
var getPrefixedProp = (function () {
|
||||
var cache = {}, doc = document, div = doc.createElement("div"), style = div.style;
|
||||
|
||||
return function (prop) {
|
||||
prop = camelCase(prop);
|
||||
if (cache[prop]) {
|
||||
return cache[prop];
|
||||
}
|
||||
|
||||
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), prefixes = ["webkit", "moz", "ms", "o"], props = (prop + " " + (prefixes).join(ucProp + " ") + ucProp).split(" ");
|
||||
|
||||
each(props, function (p) {
|
||||
if (p in style) {
|
||||
cache[p] = prop = cache[prop] = p;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return cache[prop];
|
||||
};
|
||||
}());
|
||||
|
||||
cash.prefixedProp = getPrefixedProp;
|
||||
cash.camelCase = camelCase;
|
||||
|
||||
fn.extend({
|
||||
css: function (prop, value) {
|
||||
if (isString(prop)) {
|
||||
prop = getPrefixedProp(prop);
|
||||
return (arguments.length > 1 ? this.each(function (v) {
|
||||
return v.style[prop] = value;
|
||||
}) : win.getComputedStyle(this[0])[prop]);
|
||||
}
|
||||
|
||||
for (var key in prop) {
|
||||
this.css(key, prop[key]);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function compute(el, prop) {
|
||||
return parseInt(win.getComputedStyle(el[0], null)[prop], 10) || 0;
|
||||
}
|
||||
|
||||
each(["Width", "Height"], function (v) {
|
||||
var lower = v.toLowerCase();
|
||||
|
||||
fn[lower] = function () {
|
||||
return this[0].getBoundingClientRect()[lower];
|
||||
};
|
||||
|
||||
fn["inner" + v] = function () {
|
||||
return this[0]["client" + v];
|
||||
};
|
||||
|
||||
fn["outer" + v] = function (margins) {
|
||||
return this[0]["offset" + v] + (margins ? compute(this, "margin" + (v === "Width" ? "Left" : "Top")) + compute(this, "margin" + (v === "Width" ? "Right" : "Bottom")) : 0);
|
||||
};
|
||||
});
|
||||
|
||||
function registerEvent(node, eventName, callback) {
|
||||
var eventCache = getData(node, "_cashEvents") || setData(node, "_cashEvents", {});
|
||||
eventCache[eventName] = eventCache[eventName] || [];
|
||||
eventCache[eventName].push(callback);
|
||||
node.addEventListener(eventName, callback);
|
||||
}
|
||||
|
||||
function removeEvent(node, eventName, callback) {
|
||||
var events = getData(node, "_cashEvents"), eventCache = (events && events[eventName]), index;
|
||||
|
||||
if (!eventCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
node.removeEventListener(eventName, callback);
|
||||
index = eventCache.indexOf(callback);
|
||||
if (index >= 0) {
|
||||
eventCache.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
each(eventCache, function (event) {
|
||||
node.removeEventListener(eventName, event);
|
||||
});
|
||||
eventCache = [];
|
||||
}
|
||||
}
|
||||
|
||||
fn.extend({
|
||||
off: function (eventName, callback) {
|
||||
return this.each(function (v) {
|
||||
return removeEvent(v, eventName, callback);
|
||||
});
|
||||
},
|
||||
|
||||
on: function (eventName, delegate, callback, runOnce) {
|
||||
// jshint ignore:line
|
||||
var originalCallback;
|
||||
if (!isString(eventName)) {
|
||||
for (var key in eventName) {
|
||||
this.on(key, delegate, eventName[key]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
if (isFunction(delegate)) {
|
||||
callback = delegate;
|
||||
delegate = null;
|
||||
}
|
||||
|
||||
if (eventName === "ready") {
|
||||
onReady(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (delegate) {
|
||||
originalCallback = callback;
|
||||
callback = function (e) {
|
||||
var t = e.target;
|
||||
while (!matches(t, delegate)) {
|
||||
if (t === this || t === null) {
|
||||
return (t = false);
|
||||
}
|
||||
|
||||
t = t.parentNode;
|
||||
}
|
||||
|
||||
if (t) {
|
||||
originalCallback.call(t, e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return this.each(function (v) {
|
||||
var finalCallback = callback;
|
||||
if (runOnce) {
|
||||
finalCallback = function () {
|
||||
callback.apply(this, arguments);
|
||||
removeEvent(v, eventName, finalCallback);
|
||||
};
|
||||
}
|
||||
registerEvent(v, eventName, finalCallback);
|
||||
});
|
||||
},
|
||||
|
||||
one: function (eventName, delegate, callback) {
|
||||
return this.on(eventName, delegate, callback, true);
|
||||
},
|
||||
|
||||
ready: onReady,
|
||||
|
||||
/**
|
||||
* Modified
|
||||
* Triggers browser event
|
||||
* @param String eventName
|
||||
* @param Object data - Add properties to event object
|
||||
*/
|
||||
trigger: function (eventName, data) {
|
||||
if (document.createEvent) {
|
||||
let evt = document.createEvent('HTMLEvents');
|
||||
evt.initEvent(eventName, true, false);
|
||||
evt = this.extend(evt, data);
|
||||
return this.each(function (v) {
|
||||
return v.dispatchEvent(evt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function encode(name, value) {
|
||||
return "&" + encodeURIComponent(name) + "=" + encodeURIComponent(value).replace(/%20/g, "+");
|
||||
}
|
||||
|
||||
function getSelectMultiple_(el) {
|
||||
var values = [];
|
||||
each(el.options, function (o) {
|
||||
if (o.selected) {
|
||||
values.push(o.value);
|
||||
}
|
||||
});
|
||||
return values.length ? values : null;
|
||||
}
|
||||
|
||||
function getSelectSingle_(el) {
|
||||
var selectedIndex = el.selectedIndex;
|
||||
return selectedIndex >= 0 ? el.options[selectedIndex].value : null;
|
||||
}
|
||||
|
||||
function getValue(el) {
|
||||
var type = el.type;
|
||||
if (!type) {
|
||||
return null;
|
||||
}
|
||||
switch (type.toLowerCase()) {
|
||||
case "select-one":
|
||||
return getSelectSingle_(el);
|
||||
case "select-multiple":
|
||||
return getSelectMultiple_(el);
|
||||
case "radio":
|
||||
return (el.checked) ? el.value : null;
|
||||
case "checkbox":
|
||||
return (el.checked) ? el.value : null;
|
||||
default:
|
||||
return el.value ? el.value : null;
|
||||
}
|
||||
}
|
||||
|
||||
fn.extend({
|
||||
serialize: function () {
|
||||
var query = "";
|
||||
|
||||
each(this[0].elements || this, function (el) {
|
||||
if (el.disabled || el.tagName === "FIELDSET") {
|
||||
return;
|
||||
}
|
||||
var name = el.name;
|
||||
switch (el.type.toLowerCase()) {
|
||||
case "file":
|
||||
case "reset":
|
||||
case "submit":
|
||||
case "button":
|
||||
break;
|
||||
case "select-multiple":
|
||||
var values = getValue(el);
|
||||
if (values !== null) {
|
||||
each(values, function (value) {
|
||||
query += encode(name, value);
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
var value = getValue(el);
|
||||
if (value !== null) {
|
||||
query += encode(name, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return query.substr(1);
|
||||
},
|
||||
|
||||
val: function (value) {
|
||||
if (value === undefined) {
|
||||
return getValue(this[0]);
|
||||
}
|
||||
|
||||
return this.each(function (v) {
|
||||
return v.value = value;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function insertElement(el, child, prepend) {
|
||||
if (prepend) {
|
||||
var first = el.childNodes[0];
|
||||
el.insertBefore(child, first);
|
||||
} else {
|
||||
el.appendChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
function insertContent(parent, child, prepend) {
|
||||
var str = isString(child);
|
||||
|
||||
if (!str && child.length) {
|
||||
each(child, function (v) {
|
||||
return insertContent(parent, v, prepend);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
each(parent, str ? function (v) {
|
||||
return v.insertAdjacentHTML(prepend ? "afterbegin" : "beforeend", child);
|
||||
} : function (v, i) {
|
||||
return insertElement(v, (i === 0 ? child : child.cloneNode(true)), prepend);
|
||||
});
|
||||
}
|
||||
|
||||
fn.extend({
|
||||
after: function (selector) {
|
||||
cash(selector).insertAfter(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
append: function (content) {
|
||||
insertContent(this, content);
|
||||
return this;
|
||||
},
|
||||
|
||||
appendTo: function (parent) {
|
||||
insertContent(cash(parent), this);
|
||||
return this;
|
||||
},
|
||||
|
||||
before: function (selector) {
|
||||
cash(selector).insertBefore(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
clone: function () {
|
||||
return cash(this.map(function (v) {
|
||||
return v.cloneNode(true);
|
||||
}));
|
||||
},
|
||||
|
||||
empty: function () {
|
||||
this.html("");
|
||||
return this;
|
||||
},
|
||||
|
||||
html: function (content) {
|
||||
if (content === undefined) {
|
||||
return this[0].innerHTML;
|
||||
}
|
||||
var source = (content.nodeType ? content[0].outerHTML : content);
|
||||
return this.each(function (v) {
|
||||
return v.innerHTML = source;
|
||||
});
|
||||
},
|
||||
|
||||
insertAfter: function (selector) {
|
||||
var _this = this;
|
||||
|
||||
|
||||
cash(selector).each(function (el, i) {
|
||||
var parent = el.parentNode, sibling = el.nextSibling;
|
||||
_this.each(function (v) {
|
||||
parent.insertBefore((i === 0 ? v : v.cloneNode(true)), sibling);
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
insertBefore: function (selector) {
|
||||
var _this2 = this;
|
||||
cash(selector).each(function (el, i) {
|
||||
var parent = el.parentNode;
|
||||
_this2.each(function (v) {
|
||||
parent.insertBefore((i === 0 ? v : v.cloneNode(true)), el);
|
||||
});
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
prepend: function (content) {
|
||||
insertContent(this, content, true);
|
||||
return this;
|
||||
},
|
||||
|
||||
prependTo: function (parent) {
|
||||
insertContent(cash(parent), this, true);
|
||||
return this;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
return this.each(function (v) {
|
||||
if (!!v.parentNode) {
|
||||
return v.parentNode.removeChild(v);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
text: function (content) {
|
||||
if (content === undefined) {
|
||||
return this[0].textContent;
|
||||
}
|
||||
return this.each(function (v) {
|
||||
return v.textContent = content;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var docEl = doc.documentElement;
|
||||
|
||||
fn.extend({
|
||||
position: function () {
|
||||
var el = this[0];
|
||||
return {
|
||||
left: el.offsetLeft,
|
||||
top: el.offsetTop
|
||||
};
|
||||
},
|
||||
|
||||
offset: function () {
|
||||
var rect = this[0].getBoundingClientRect();
|
||||
return {
|
||||
top: rect.top + win.pageYOffset - docEl.clientTop,
|
||||
left: rect.left + win.pageXOffset - docEl.clientLeft
|
||||
};
|
||||
},
|
||||
|
||||
offsetParent: function () {
|
||||
return cash(this[0].offsetParent);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
fn.extend({
|
||||
children: function (selector) {
|
||||
var elems = [];
|
||||
this.each(function (el) {
|
||||
push.apply(elems, el.children);
|
||||
});
|
||||
elems = unique(elems);
|
||||
|
||||
return (!selector ? elems : elems.filter(function (v) {
|
||||
return matches(v, selector);
|
||||
}));
|
||||
},
|
||||
|
||||
closest: function (selector) {
|
||||
if (!selector || this.length < 1) {
|
||||
return cash();
|
||||
}
|
||||
if (this.is(selector)) {
|
||||
return this.filter(selector);
|
||||
}
|
||||
return this.parent().closest(selector);
|
||||
},
|
||||
|
||||
is: function (selector) {
|
||||
if (!selector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var match = false, comparator = getCompareFunction(selector);
|
||||
|
||||
this.each(function (el) {
|
||||
match = comparator(el, selector);
|
||||
return !match;
|
||||
});
|
||||
|
||||
return match;
|
||||
},
|
||||
|
||||
find: function (selector) {
|
||||
if (!selector || selector.nodeType) {
|
||||
return cash(selector && this.has(selector).length ? selector : null);
|
||||
}
|
||||
|
||||
var elems = [];
|
||||
this.each(function (el) {
|
||||
push.apply(elems, find(selector, el));
|
||||
});
|
||||
|
||||
return unique(elems);
|
||||
},
|
||||
|
||||
has: function (selector) {
|
||||
var comparator = (isString(selector) ? function (el) {
|
||||
return find(selector, el).length !== 0;
|
||||
} : function (el) {
|
||||
return el.contains(selector);
|
||||
});
|
||||
|
||||
return this.filter(comparator);
|
||||
},
|
||||
|
||||
next: function () {
|
||||
return cash(this[0].nextElementSibling);
|
||||
},
|
||||
|
||||
not: function (selector) {
|
||||
if (!selector) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var comparator = getCompareFunction(selector);
|
||||
|
||||
return this.filter(function (el) {
|
||||
return !comparator(el, selector);
|
||||
});
|
||||
},
|
||||
|
||||
parent: function () {
|
||||
var result = [];
|
||||
|
||||
this.each(function (item) {
|
||||
if (item && item.parentNode) {
|
||||
result.push(item.parentNode);
|
||||
}
|
||||
});
|
||||
|
||||
return unique(result);
|
||||
},
|
||||
|
||||
parents: function (selector) {
|
||||
var last, result = [];
|
||||
|
||||
this.each(function (item) {
|
||||
last = item;
|
||||
|
||||
while (last && last.parentNode && last !== doc.body.parentNode) {
|
||||
last = last.parentNode;
|
||||
|
||||
if (!selector || (selector && matches(last, selector))) {
|
||||
result.push(last);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return unique(result);
|
||||
},
|
||||
|
||||
prev: function () {
|
||||
return cash(this[0].previousElementSibling);
|
||||
},
|
||||
|
||||
siblings: function (selector) {
|
||||
var collection = this.parent().children(selector), el = this[0];
|
||||
|
||||
return collection.filter(function (i) {
|
||||
return i !== el;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
return cash;
|
||||
});
|
136
node_modules/@materializecss/materialize/js/characterCounter.js
generated
vendored
Executable file
136
node_modules/@materializecss/materialize/js/characterCounter.js
generated
vendored
Executable file
|
@ -0,0 +1,136 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class CharacterCounter extends Component {
|
||||
/**
|
||||
* Construct CharacterCounter instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(CharacterCounter, el, options);
|
||||
|
||||
this.el.M_CharacterCounter = this;
|
||||
|
||||
/**
|
||||
* Options for the character counter
|
||||
*/
|
||||
this.options = $.extend({}, CharacterCounter.defaults, options);
|
||||
|
||||
this.isInvalid = false;
|
||||
this.isValidLength = false;
|
||||
this._setupCounter();
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_CharacterCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.CharacterCounter = undefined;
|
||||
this._removeCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleUpdateCounterBound = this.updateCounter.bind(this);
|
||||
|
||||
this.el.addEventListener('focus', this._handleUpdateCounterBound, true);
|
||||
this.el.addEventListener('input', this._handleUpdateCounterBound, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('focus', this._handleUpdateCounterBound, true);
|
||||
this.el.removeEventListener('input', this._handleUpdateCounterBound, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup counter element
|
||||
*/
|
||||
_setupCounter() {
|
||||
this.counterEl = document.createElement('span');
|
||||
$(this.counterEl)
|
||||
.addClass('character-counter')
|
||||
.css({
|
||||
float: 'right',
|
||||
'font-size': '12px',
|
||||
height: 1
|
||||
});
|
||||
|
||||
this.$el.parent().append(this.counterEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove counter element
|
||||
*/
|
||||
_removeCounter() {
|
||||
$(this.counterEl).remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update counter
|
||||
*/
|
||||
updateCounter() {
|
||||
let maxLength = +this.$el.attr('data-length'),
|
||||
actualLength = this.el.value.length;
|
||||
this.isValidLength = actualLength <= maxLength;
|
||||
let counterString = actualLength;
|
||||
|
||||
if (maxLength) {
|
||||
counterString += '/' + maxLength;
|
||||
this._validateInput();
|
||||
}
|
||||
|
||||
$(this.counterEl).html(counterString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add validation classes
|
||||
*/
|
||||
_validateInput() {
|
||||
if (this.isValidLength && this.isInvalid) {
|
||||
this.isInvalid = false;
|
||||
this.$el.removeClass('invalid');
|
||||
} else if (!this.isValidLength && !this.isInvalid) {
|
||||
this.isInvalid = true;
|
||||
this.$el.removeClass('valid');
|
||||
this.$el.addClass('invalid');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M.CharacterCounter = CharacterCounter;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(CharacterCounter, 'characterCounter', 'M_CharacterCounter');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,486 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
data: [],
|
||||
placeholder: '',
|
||||
secondaryPlaceholder: '',
|
||||
autocompleteOptions: {},
|
||||
autocompleteOnly: false,
|
||||
limit: Infinity,
|
||||
onChipAdd: null,
|
||||
onChipSelect: null,
|
||||
onChipDelete: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} chip
|
||||
* @property {String} tag chip tag string
|
||||
* @property {String} [image] chip avatar image string
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Chips extends Component {
|
||||
/**
|
||||
* Construct Chips instance and set up overlay
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Chips, el, options);
|
||||
|
||||
this.el.M_Chips = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Chips#options
|
||||
* @prop {Array} data
|
||||
* @prop {String} placeholder
|
||||
* @prop {String} secondaryPlaceholder
|
||||
* @prop {Object} autocompleteOptions
|
||||
*/
|
||||
this.options = $.extend({}, Chips.defaults, options);
|
||||
|
||||
this.$el.addClass('chips input-field');
|
||||
this.chipsData = [];
|
||||
this.$chips = $();
|
||||
this._setupInput();
|
||||
this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;
|
||||
|
||||
// Set input id
|
||||
if (!this.$input.attr('id')) {
|
||||
this.$input.attr('id', M.guid());
|
||||
}
|
||||
|
||||
// Render initial chips
|
||||
if (this.options.data.length) {
|
||||
this.chipsData = this.options.data;
|
||||
this._renderChips(this.chipsData);
|
||||
}
|
||||
|
||||
// Setup autocomplete if needed
|
||||
if (this.hasAutocomplete) {
|
||||
this._setupAutocomplete();
|
||||
}
|
||||
|
||||
this._setPlaceholder();
|
||||
this._setupLabel();
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Chips;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Chips Data
|
||||
*/
|
||||
getData() {
|
||||
return this.chipsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.$chips.remove();
|
||||
this.el.M_Chips = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleChipClickBound = this._handleChipClick.bind(this);
|
||||
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
|
||||
this._handleInputFocusBound = this._handleInputFocus.bind(this);
|
||||
this._handleInputBlurBound = this._handleInputBlur.bind(this);
|
||||
|
||||
this.el.addEventListener('click', this._handleChipClickBound);
|
||||
document.addEventListener('keydown', Chips._handleChipsKeydown);
|
||||
document.addEventListener('keyup', Chips._handleChipsKeyup);
|
||||
this.el.addEventListener('blur', Chips._handleChipsBlur, true);
|
||||
this.$input[0].addEventListener('focus', this._handleInputFocusBound);
|
||||
this.$input[0].addEventListener('blur', this._handleInputBlurBound);
|
||||
this.$input[0].addEventListener('keydown', this._handleInputKeydownBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleChipClickBound);
|
||||
document.removeEventListener('keydown', Chips._handleChipsKeydown);
|
||||
document.removeEventListener('keyup', Chips._handleChipsKeyup);
|
||||
this.el.removeEventListener('blur', Chips._handleChipsBlur, true);
|
||||
this.$input[0].removeEventListener('focus', this._handleInputFocusBound);
|
||||
this.$input[0].removeEventListener('blur', this._handleInputBlurBound);
|
||||
this.$input[0].removeEventListener('keydown', this._handleInputKeydownBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Chip Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleChipClick(e) {
|
||||
let $chip = $(e.target).closest('.chip');
|
||||
let clickedClose = $(e.target).is('.close');
|
||||
if ($chip.length) {
|
||||
let index = $chip.index();
|
||||
if (clickedClose) {
|
||||
// delete chip
|
||||
this.deleteChip(index);
|
||||
this.$input[0].focus();
|
||||
} else {
|
||||
// select chip
|
||||
this.selectChip(index);
|
||||
}
|
||||
|
||||
// Default handle click to focus on input
|
||||
} else {
|
||||
this.$input[0].focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Chips Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _handleChipsKeydown(e) {
|
||||
Chips._keydown = true;
|
||||
|
||||
let $chips = $(e.target).closest('.chips');
|
||||
let chipsKeydown = e.target && $chips.length;
|
||||
|
||||
// Don't handle keydown inputs on input and textarea
|
||||
if ($(e.target).is('input, textarea') || !chipsKeydown) {
|
||||
return;
|
||||
}
|
||||
|
||||
let currChips = $chips[0].M_Chips;
|
||||
|
||||
// backspace and delete
|
||||
if (e.keyCode === 8 || e.keyCode === 46) {
|
||||
e.preventDefault();
|
||||
|
||||
let selectIndex = currChips.chipsData.length;
|
||||
if (currChips._selectedChip) {
|
||||
let index = currChips._selectedChip.index();
|
||||
currChips.deleteChip(index);
|
||||
currChips._selectedChip = null;
|
||||
|
||||
// Make sure selectIndex doesn't go negative
|
||||
selectIndex = Math.max(index - 1, 0);
|
||||
}
|
||||
|
||||
if (currChips.chipsData.length) {
|
||||
currChips.selectChip(selectIndex);
|
||||
} else {
|
||||
currChips.$input[0].focus();
|
||||
}
|
||||
|
||||
// left arrow key
|
||||
} else if (e.keyCode === 37) {
|
||||
if (currChips._selectedChip) {
|
||||
let selectIndex = currChips._selectedChip.index() - 1;
|
||||
if (selectIndex < 0) {
|
||||
return;
|
||||
}
|
||||
currChips.selectChip(selectIndex);
|
||||
}
|
||||
|
||||
// right arrow key
|
||||
} else if (e.keyCode === 39) {
|
||||
if (currChips._selectedChip) {
|
||||
let selectIndex = currChips._selectedChip.index() + 1;
|
||||
|
||||
if (selectIndex >= currChips.chipsData.length) {
|
||||
currChips.$input[0].focus();
|
||||
} else {
|
||||
currChips.selectChip(selectIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Chips Keyup
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _handleChipsKeyup(e) {
|
||||
Chips._keydown = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Chips Blur
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _handleChipsBlur(e) {
|
||||
if (!Chips._keydown && document.hidden) {
|
||||
let $chips = $(e.target).closest('.chips');
|
||||
let currChips = $chips[0].M_Chips;
|
||||
|
||||
currChips._selectedChip = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Focus
|
||||
*/
|
||||
_handleInputFocus() {
|
||||
this.$el.addClass('focus');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Blur
|
||||
*/
|
||||
_handleInputBlur() {
|
||||
this.$el.removeClass('focus');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Input Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleInputKeydown(e) {
|
||||
Chips._keydown = true;
|
||||
|
||||
// enter
|
||||
if (e.keyCode === 13) {
|
||||
// Override enter if autocompleting.
|
||||
if (this.hasAutocomplete && this.autocomplete && this.autocomplete.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
if (!this.hasAutocomplete || (this.hasAutocomplete && !this.options.autocompleteOnly)) {
|
||||
this.addChip({
|
||||
tag: this.$input[0].value
|
||||
});
|
||||
}
|
||||
this.$input[0].value = '';
|
||||
|
||||
// delete or left
|
||||
} else if (
|
||||
(e.keyCode === 8 || e.keyCode === 37) &&
|
||||
this.$input[0].value === '' &&
|
||||
this.chipsData.length
|
||||
) {
|
||||
e.preventDefault();
|
||||
this.selectChip(this.chipsData.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Chip
|
||||
* @param {chip} chip
|
||||
* @return {Element}
|
||||
*/
|
||||
_renderChip(chip) {
|
||||
if (!chip.tag) {
|
||||
return;
|
||||
}
|
||||
|
||||
let renderedChip = document.createElement('div');
|
||||
let closeIcon = document.createElement('i');
|
||||
renderedChip.classList.add('chip');
|
||||
renderedChip.textContent = chip.tag;
|
||||
renderedChip.setAttribute('tabindex', 0);
|
||||
$(closeIcon).addClass('material-icons close');
|
||||
closeIcon.textContent = 'close';
|
||||
|
||||
// attach image if needed
|
||||
if (chip.image) {
|
||||
let img = document.createElement('img');
|
||||
img.setAttribute('src', chip.image);
|
||||
renderedChip.insertBefore(img, renderedChip.firstChild);
|
||||
}
|
||||
|
||||
renderedChip.appendChild(closeIcon);
|
||||
return renderedChip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Chips
|
||||
*/
|
||||
_renderChips() {
|
||||
this.$chips.remove();
|
||||
for (let i = 0; i < this.chipsData.length; i++) {
|
||||
let chipEl = this._renderChip(this.chipsData[i]);
|
||||
this.$el.append(chipEl);
|
||||
this.$chips.add(chipEl);
|
||||
}
|
||||
|
||||
// move input to end
|
||||
this.$el.append(this.$input[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Autocomplete
|
||||
*/
|
||||
_setupAutocomplete() {
|
||||
this.options.autocompleteOptions.onAutocomplete = (val) => {
|
||||
this.addChip({
|
||||
tag: val
|
||||
});
|
||||
this.$input[0].value = '';
|
||||
this.$input[0].focus();
|
||||
};
|
||||
|
||||
this.autocomplete = M.Autocomplete.init(this.$input[0], this.options.autocompleteOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Input
|
||||
*/
|
||||
_setupInput() {
|
||||
this.$input = this.$el.find('input');
|
||||
if (!this.$input.length) {
|
||||
this.$input = $('<input></input>');
|
||||
this.$el.append(this.$input);
|
||||
}
|
||||
|
||||
this.$input.addClass('input');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Label
|
||||
*/
|
||||
_setupLabel() {
|
||||
this.$label = this.$el.find('label');
|
||||
if (this.$label.length) {
|
||||
this.$label[0].setAttribute('for', this.$input.attr('id'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set placeholder
|
||||
*/
|
||||
_setPlaceholder() {
|
||||
if (this.chipsData !== undefined && !this.chipsData.length && this.options.placeholder) {
|
||||
$(this.$input).prop('placeholder', this.options.placeholder);
|
||||
} else if (
|
||||
(this.chipsData === undefined || !!this.chipsData.length) &&
|
||||
this.options.secondaryPlaceholder
|
||||
) {
|
||||
$(this.$input).prop('placeholder', this.options.secondaryPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if chip is valid
|
||||
* @param {chip} chip
|
||||
*/
|
||||
_isValid(chip) {
|
||||
if (chip.hasOwnProperty('tag') && chip.tag !== '') {
|
||||
let exists = false;
|
||||
for (let i = 0; i < this.chipsData.length; i++) {
|
||||
if (this.chipsData[i].tag === chip.tag) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !exists;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add chip
|
||||
* @param {chip} chip
|
||||
*/
|
||||
addChip(chip) {
|
||||
if (!this._isValid(chip) || this.chipsData.length >= this.options.limit) {
|
||||
return;
|
||||
}
|
||||
|
||||
let renderedChip = this._renderChip(chip);
|
||||
this.$chips.add(renderedChip);
|
||||
this.chipsData.push(chip);
|
||||
$(this.$input).before(renderedChip);
|
||||
this._setPlaceholder();
|
||||
|
||||
// fire chipAdd callback
|
||||
if (typeof this.options.onChipAdd === 'function') {
|
||||
this.options.onChipAdd.call(this, this.$el, renderedChip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete chip
|
||||
* @param {Number} chip
|
||||
*/
|
||||
deleteChip(chipIndex) {
|
||||
let $chip = this.$chips.eq(chipIndex);
|
||||
this.$chips.eq(chipIndex).remove();
|
||||
this.$chips = this.$chips.filter(function(el) {
|
||||
return $(el).index() >= 0;
|
||||
});
|
||||
this.chipsData.splice(chipIndex, 1);
|
||||
this._setPlaceholder();
|
||||
|
||||
// fire chipDelete callback
|
||||
if (typeof this.options.onChipDelete === 'function') {
|
||||
this.options.onChipDelete.call(this, this.$el, $chip[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select chip
|
||||
* @param {Number} chip
|
||||
*/
|
||||
selectChip(chipIndex) {
|
||||
let $chip = this.$chips.eq(chipIndex);
|
||||
this._selectedChip = $chip;
|
||||
$chip[0].focus();
|
||||
|
||||
// fire chipSelect callback
|
||||
if (typeof this.options.onChipSelect === 'function') {
|
||||
this.options.onChipSelect.call(this, this.$el, $chip[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Chips
|
||||
*/
|
||||
Chips._keydown = false;
|
||||
|
||||
M.Chips = Chips;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Chips, 'chips', 'M_Chips');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Handle removal of static chips.
|
||||
$(document.body).on('click', '.chip .close', function() {
|
||||
let $chips = $(this).closest('.chips');
|
||||
if ($chips.length && $chips[0].M_Chips) {
|
||||
return;
|
||||
}
|
||||
$(this)
|
||||
.closest('.chip')
|
||||
.remove();
|
||||
});
|
||||
});
|
||||
})(cash);
|
|
@ -0,0 +1,275 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
accordion: true,
|
||||
onOpenStart: undefined,
|
||||
onOpenEnd: undefined,
|
||||
onCloseStart: undefined,
|
||||
onCloseEnd: undefined,
|
||||
inDuration: 300,
|
||||
outDuration: 300
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Collapsible extends Component {
|
||||
/**
|
||||
* Construct Collapsible instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Collapsible, el, options);
|
||||
|
||||
this.el.M_Collapsible = this;
|
||||
|
||||
/**
|
||||
* Options for the collapsible
|
||||
* @member Collapsible#options
|
||||
* @prop {Boolean} [accordion=false] - Type of the collapsible
|
||||
* @prop {Function} onOpenStart - Callback function called before collapsible is opened
|
||||
* @prop {Function} onOpenEnd - Callback function called after collapsible is opened
|
||||
* @prop {Function} onCloseStart - Callback function called before collapsible is closed
|
||||
* @prop {Function} onCloseEnd - Callback function called after collapsible is closed
|
||||
* @prop {Number} inDuration - Transition in duration in milliseconds.
|
||||
* @prop {Number} outDuration - Transition duration in milliseconds.
|
||||
*/
|
||||
this.options = $.extend({}, Collapsible.defaults, options);
|
||||
|
||||
// Setup tab indices
|
||||
this.$headers = this.$el.children('li').children('.collapsible-header');
|
||||
this.$headers.attr('tabindex', 0);
|
||||
|
||||
this._setupEventHandlers();
|
||||
|
||||
// Open first active
|
||||
let $activeBodies = this.$el.children('li.active').children('.collapsible-body');
|
||||
if (this.options.accordion) {
|
||||
// Handle Accordion
|
||||
$activeBodies.first().css('display', 'block');
|
||||
} else {
|
||||
// Handle Expandables
|
||||
$activeBodies.css('display', 'block');
|
||||
}
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Collapsible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.M_Collapsible = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleCollapsibleClickBound = this._handleCollapsibleClick.bind(this);
|
||||
this._handleCollapsibleKeydownBound = this._handleCollapsibleKeydown.bind(this);
|
||||
this.el.addEventListener('click', this._handleCollapsibleClickBound);
|
||||
this.$headers.each((header) => {
|
||||
header.addEventListener('keydown', this._handleCollapsibleKeydownBound);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleCollapsibleClickBound);
|
||||
this.$headers.each((header) => {
|
||||
header.removeEventListener('keydown', this._handleCollapsibleKeydownBound);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Collapsible Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCollapsibleClick(e) {
|
||||
let $header = $(e.target).closest('.collapsible-header');
|
||||
if (e.target && $header.length) {
|
||||
let $collapsible = $header.closest('.collapsible');
|
||||
if ($collapsible[0] === this.el) {
|
||||
let $collapsibleLi = $header.closest('li');
|
||||
let $collapsibleLis = $collapsible.children('li');
|
||||
let isActive = $collapsibleLi[0].classList.contains('active');
|
||||
let index = $collapsibleLis.index($collapsibleLi);
|
||||
|
||||
if (isActive) {
|
||||
this.close(index);
|
||||
} else {
|
||||
this.open(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Collapsible Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCollapsibleKeydown(e) {
|
||||
if (e.keyCode === 13) {
|
||||
this._handleCollapsibleClickBound(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in collapsible slide
|
||||
* @param {Number} index - 0th index of slide
|
||||
*/
|
||||
_animateIn(index) {
|
||||
let $collapsibleLi = this.$el.children('li').eq(index);
|
||||
if ($collapsibleLi.length) {
|
||||
let $body = $collapsibleLi.children('.collapsible-body');
|
||||
|
||||
anim.remove($body[0]);
|
||||
$body.css({
|
||||
display: 'block',
|
||||
overflow: 'hidden',
|
||||
height: 0,
|
||||
paddingTop: '',
|
||||
paddingBottom: ''
|
||||
});
|
||||
|
||||
let pTop = $body.css('padding-top');
|
||||
let pBottom = $body.css('padding-bottom');
|
||||
let finalHeight = $body[0].scrollHeight;
|
||||
$body.css({
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0
|
||||
});
|
||||
|
||||
anim({
|
||||
targets: $body[0],
|
||||
height: finalHeight,
|
||||
paddingTop: pTop,
|
||||
paddingBottom: pBottom,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeInOutCubic',
|
||||
complete: (anim) => {
|
||||
$body.css({
|
||||
overflow: '',
|
||||
paddingTop: '',
|
||||
paddingBottom: '',
|
||||
height: ''
|
||||
});
|
||||
|
||||
// onOpenEnd callback
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, $collapsibleLi[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate out collapsible slide
|
||||
* @param {Number} index - 0th index of slide to open
|
||||
*/
|
||||
_animateOut(index) {
|
||||
let $collapsibleLi = this.$el.children('li').eq(index);
|
||||
if ($collapsibleLi.length) {
|
||||
let $body = $collapsibleLi.children('.collapsible-body');
|
||||
anim.remove($body[0]);
|
||||
$body.css('overflow', 'hidden');
|
||||
anim({
|
||||
targets: $body[0],
|
||||
height: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeInOutCubic',
|
||||
complete: () => {
|
||||
$body.css({
|
||||
height: '',
|
||||
overflow: '',
|
||||
padding: '',
|
||||
display: ''
|
||||
});
|
||||
|
||||
// onCloseEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, $collapsibleLi[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Collapsible
|
||||
* @param {Number} index - 0th index of slide
|
||||
*/
|
||||
open(index) {
|
||||
let $collapsibleLi = this.$el.children('li').eq(index);
|
||||
if ($collapsibleLi.length && !$collapsibleLi[0].classList.contains('active')) {
|
||||
// onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, $collapsibleLi[0]);
|
||||
}
|
||||
|
||||
// Handle accordion behavior
|
||||
if (this.options.accordion) {
|
||||
let $collapsibleLis = this.$el.children('li');
|
||||
let $activeLis = this.$el.children('li.active');
|
||||
$activeLis.each((el) => {
|
||||
let index = $collapsibleLis.index($(el));
|
||||
this.close(index);
|
||||
});
|
||||
}
|
||||
|
||||
// Animate in
|
||||
$collapsibleLi[0].classList.add('active');
|
||||
this._animateIn(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Collapsible
|
||||
* @param {Number} index - 0th index of slide
|
||||
*/
|
||||
close(index) {
|
||||
let $collapsibleLi = this.$el.children('li').eq(index);
|
||||
if ($collapsibleLi.length && $collapsibleLi[0].classList.contains('active')) {
|
||||
// onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, $collapsibleLi[0]);
|
||||
}
|
||||
|
||||
// Animate out
|
||||
$collapsibleLi[0].classList.remove('active');
|
||||
this._animateOut(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M.Collapsible = Collapsible;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Collapsible, 'collapsible', 'M_Collapsible');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,44 @@
|
|||
class Component {
|
||||
/**
|
||||
* Generic constructor for all components
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(classDef, el, options) {
|
||||
// Display error if el is valid HTML Element
|
||||
if (!(el instanceof Element)) {
|
||||
console.error(Error(el + ' is not an HTML Element'));
|
||||
}
|
||||
|
||||
// If exists, destroy and reinitialize in child
|
||||
let ins = classDef.getInstance(el);
|
||||
if (!!ins) {
|
||||
ins.destroy();
|
||||
}
|
||||
|
||||
this.el = el;
|
||||
this.$el = cash(el);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes components
|
||||
* @param {class} classDef
|
||||
* @param {Element | NodeList | jQuery} els
|
||||
* @param {Object} options
|
||||
*/
|
||||
static init(classDef, els, options) {
|
||||
let instances = null;
|
||||
if (els instanceof Element) {
|
||||
instances = new classDef(els, options);
|
||||
} else if (!!els && (els.jquery || els.cash || els instanceof NodeList)) {
|
||||
let instancesArr = [];
|
||||
for (let i = 0; i < els.length; i++) {
|
||||
instancesArr.push(new classDef(els[i], options));
|
||||
}
|
||||
instances = instancesArr;
|
||||
}
|
||||
|
||||
return instances;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,983 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
// Close when date is selected
|
||||
autoClose: false,
|
||||
|
||||
// the default output format for the input field value
|
||||
format: 'mmm dd, yyyy',
|
||||
|
||||
// Used to create date object from current input string
|
||||
parse: null,
|
||||
|
||||
// The initial date to view when first opened
|
||||
defaultDate: null,
|
||||
|
||||
// Make the `defaultDate` the initial selected value
|
||||
setDefaultDate: false,
|
||||
|
||||
disableWeekends: false,
|
||||
|
||||
disableDayFn: null,
|
||||
|
||||
// First day of week (0: Sunday, 1: Monday etc)
|
||||
firstDay: 0,
|
||||
|
||||
// The earliest date that can be selected
|
||||
minDate: null,
|
||||
// Thelatest date that can be selected
|
||||
maxDate: null,
|
||||
|
||||
// Number of years either side, or array of upper/lower range
|
||||
yearRange: 10,
|
||||
|
||||
// used internally (don't config outside)
|
||||
minYear: 0,
|
||||
maxYear: 9999,
|
||||
minMonth: undefined,
|
||||
maxMonth: undefined,
|
||||
|
||||
startRange: null,
|
||||
endRange: null,
|
||||
|
||||
isRTL: false,
|
||||
|
||||
// Render the month after year in the calendar title
|
||||
showMonthAfterYear: false,
|
||||
|
||||
// Render days of the calendar grid that fall in the next or previous month
|
||||
showDaysInNextAndPreviousMonths: false,
|
||||
|
||||
// Specify a DOM element to render the calendar in
|
||||
container: null,
|
||||
|
||||
// Show clear button
|
||||
showClearBtn: false,
|
||||
|
||||
// internationalization
|
||||
i18n: {
|
||||
cancel: 'Cancel',
|
||||
clear: 'Clear',
|
||||
done: 'Ok',
|
||||
previousMonth: '‹',
|
||||
nextMonth: '›',
|
||||
months: [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
],
|
||||
monthsShort: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
],
|
||||
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
weekdaysAbbrev: ['S', 'M', 'T', 'W', 'T', 'F', 'S']
|
||||
},
|
||||
|
||||
// events array
|
||||
events: [],
|
||||
|
||||
// callback function
|
||||
onSelect: null,
|
||||
onOpen: null,
|
||||
onClose: null,
|
||||
onDraw: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Datepicker extends Component {
|
||||
/**
|
||||
* Construct Datepicker instance and set up overlay
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Datepicker, el, options);
|
||||
|
||||
this.el.M_Datepicker = this;
|
||||
|
||||
this.options = $.extend({}, Datepicker.defaults, options);
|
||||
|
||||
// make sure i18n defaults are not lost when only few i18n option properties are passed
|
||||
if (!!options && options.hasOwnProperty('i18n') && typeof options.i18n === 'object') {
|
||||
this.options.i18n = $.extend({}, Datepicker.defaults.i18n, options.i18n);
|
||||
}
|
||||
|
||||
// Remove time component from minDate and maxDate options
|
||||
if (this.options.minDate) this.options.minDate.setHours(0, 0, 0, 0);
|
||||
if (this.options.maxDate) this.options.maxDate.setHours(0, 0, 0, 0);
|
||||
|
||||
this.id = M.guid();
|
||||
|
||||
this._setupVariables();
|
||||
this._insertHTMLIntoDOM();
|
||||
this._setupModal();
|
||||
|
||||
this._setupEventHandlers();
|
||||
|
||||
if (!this.options.defaultDate) {
|
||||
this.options.defaultDate = new Date(Date.parse(this.el.value));
|
||||
}
|
||||
|
||||
let defDate = this.options.defaultDate;
|
||||
if (Datepicker._isDate(defDate)) {
|
||||
if (this.options.setDefaultDate) {
|
||||
this.setDate(defDate, true);
|
||||
this.setInputValue();
|
||||
} else {
|
||||
this.gotoDate(defDate);
|
||||
}
|
||||
} else {
|
||||
this.gotoDate(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes open/close state of datepicker
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
static _isDate(obj) {
|
||||
return /Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
|
||||
}
|
||||
|
||||
static _isWeekend(date) {
|
||||
let day = date.getDay();
|
||||
return day === 0 || day === 6;
|
||||
}
|
||||
|
||||
static _setToStartOfDay(date) {
|
||||
if (Datepicker._isDate(date)) date.setHours(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static _getDaysInMonth(year, month) {
|
||||
return [31, Datepicker._isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][
|
||||
month
|
||||
];
|
||||
}
|
||||
|
||||
static _isLeapYear(year) {
|
||||
// solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
|
||||
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||
}
|
||||
|
||||
static _compareDates(a, b) {
|
||||
// weak date comparison (use setToStartOfDay(date) to ensure correct result)
|
||||
return a.getTime() === b.getTime();
|
||||
}
|
||||
|
||||
static _setToStartOfDay(date) {
|
||||
if (Datepicker._isDate(date)) date.setHours(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Datepicker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.modal.destroy();
|
||||
$(this.modalEl).remove();
|
||||
this.destroySelects();
|
||||
this.el.M_Datepicker = undefined;
|
||||
}
|
||||
|
||||
destroySelects() {
|
||||
let oldYearSelect = this.calendarEl.querySelector('.orig-select-year');
|
||||
if (oldYearSelect) {
|
||||
M.FormSelect.getInstance(oldYearSelect).destroy();
|
||||
}
|
||||
let oldMonthSelect = this.calendarEl.querySelector('.orig-select-month');
|
||||
if (oldMonthSelect) {
|
||||
M.FormSelect.getInstance(oldMonthSelect).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
_insertHTMLIntoDOM() {
|
||||
if (this.options.showClearBtn) {
|
||||
$(this.clearBtn).css({ visibility: '' });
|
||||
this.clearBtn.innerHTML = this.options.i18n.clear;
|
||||
}
|
||||
|
||||
this.doneBtn.innerHTML = this.options.i18n.done;
|
||||
this.cancelBtn.innerHTML = this.options.i18n.cancel;
|
||||
|
||||
if (this.options.container) {
|
||||
const optEl = this.options.container;
|
||||
this.options.container =
|
||||
optEl instanceof HTMLElement ? optEl : document.querySelector(optEl);
|
||||
this.$modalEl.appendTo(this.options.container);
|
||||
} else {
|
||||
this.$modalEl.insertBefore(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
_setupModal() {
|
||||
this.modalEl.id = 'modal-' + this.id;
|
||||
this.modal = M.Modal.init(this.modalEl, {
|
||||
onCloseEnd: () => {
|
||||
this.isOpen = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toString(format) {
|
||||
format = format || this.options.format;
|
||||
if (typeof format === 'function') {
|
||||
return format(this.date);
|
||||
}
|
||||
|
||||
if (!Datepicker._isDate(this.date)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let formatArray = format.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
|
||||
let formattedDate = formatArray
|
||||
.map((label) => {
|
||||
if (this.formats[label]) {
|
||||
return this.formats[label]();
|
||||
}
|
||||
|
||||
return label;
|
||||
})
|
||||
.join('');
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
setDate(date, preventOnSelect) {
|
||||
if (!date) {
|
||||
this.date = null;
|
||||
this._renderDateDisplay();
|
||||
return this.draw();
|
||||
}
|
||||
if (typeof date === 'string') {
|
||||
date = new Date(Date.parse(date));
|
||||
}
|
||||
if (!Datepicker._isDate(date)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let min = this.options.minDate,
|
||||
max = this.options.maxDate;
|
||||
|
||||
if (Datepicker._isDate(min) && date < min) {
|
||||
date = min;
|
||||
} else if (Datepicker._isDate(max) && date > max) {
|
||||
date = max;
|
||||
}
|
||||
|
||||
this.date = new Date(date.getTime());
|
||||
|
||||
this._renderDateDisplay();
|
||||
|
||||
Datepicker._setToStartOfDay(this.date);
|
||||
this.gotoDate(this.date);
|
||||
|
||||
if (!preventOnSelect && typeof this.options.onSelect === 'function') {
|
||||
this.options.onSelect.call(this, this.date);
|
||||
}
|
||||
}
|
||||
|
||||
setInputValue() {
|
||||
this.el.value = this.toString();
|
||||
this.$el.trigger('change', { firedBy: this });
|
||||
}
|
||||
|
||||
_renderDateDisplay() {
|
||||
let displayDate = Datepicker._isDate(this.date) ? this.date : new Date();
|
||||
let i18n = this.options.i18n;
|
||||
let day = i18n.weekdaysShort[displayDate.getDay()];
|
||||
let month = i18n.monthsShort[displayDate.getMonth()];
|
||||
let date = displayDate.getDate();
|
||||
this.yearTextEl.innerHTML = displayDate.getFullYear();
|
||||
this.dateTextEl.innerHTML = `${day}, ${month} ${date}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* change view to a specific date
|
||||
*/
|
||||
gotoDate(date) {
|
||||
let newCalendar = true;
|
||||
|
||||
if (!Datepicker._isDate(date)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.calendars) {
|
||||
let firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
|
||||
lastVisibleDate = new Date(
|
||||
this.calendars[this.calendars.length - 1].year,
|
||||
this.calendars[this.calendars.length - 1].month,
|
||||
1
|
||||
),
|
||||
visibleDate = date.getTime();
|
||||
// get the end of the month
|
||||
lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1);
|
||||
lastVisibleDate.setDate(lastVisibleDate.getDate() - 1);
|
||||
newCalendar =
|
||||
visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate;
|
||||
}
|
||||
|
||||
if (newCalendar) {
|
||||
this.calendars = [
|
||||
{
|
||||
month: date.getMonth(),
|
||||
year: date.getFullYear()
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
this.adjustCalendars();
|
||||
}
|
||||
|
||||
adjustCalendars() {
|
||||
this.calendars[0] = this.adjustCalendar(this.calendars[0]);
|
||||
this.draw();
|
||||
}
|
||||
|
||||
adjustCalendar(calendar) {
|
||||
if (calendar.month < 0) {
|
||||
calendar.year -= Math.ceil(Math.abs(calendar.month) / 12);
|
||||
calendar.month += 12;
|
||||
}
|
||||
if (calendar.month > 11) {
|
||||
calendar.year += Math.floor(Math.abs(calendar.month) / 12);
|
||||
calendar.month -= 12;
|
||||
}
|
||||
return calendar;
|
||||
}
|
||||
|
||||
nextMonth() {
|
||||
this.calendars[0].month++;
|
||||
this.adjustCalendars();
|
||||
}
|
||||
|
||||
prevMonth() {
|
||||
this.calendars[0].month--;
|
||||
this.adjustCalendars();
|
||||
}
|
||||
|
||||
render(year, month, randId) {
|
||||
let opts = this.options,
|
||||
now = new Date(),
|
||||
days = Datepicker._getDaysInMonth(year, month),
|
||||
before = new Date(year, month, 1).getDay(),
|
||||
data = [],
|
||||
row = [];
|
||||
Datepicker._setToStartOfDay(now);
|
||||
if (opts.firstDay > 0) {
|
||||
before -= opts.firstDay;
|
||||
if (before < 0) {
|
||||
before += 7;
|
||||
}
|
||||
}
|
||||
let previousMonth = month === 0 ? 11 : month - 1,
|
||||
nextMonth = month === 11 ? 0 : month + 1,
|
||||
yearOfPreviousMonth = month === 0 ? year - 1 : year,
|
||||
yearOfNextMonth = month === 11 ? year + 1 : year,
|
||||
daysInPreviousMonth = Datepicker._getDaysInMonth(yearOfPreviousMonth, previousMonth);
|
||||
let cells = days + before,
|
||||
after = cells;
|
||||
while (after > 7) {
|
||||
after -= 7;
|
||||
}
|
||||
cells += 7 - after;
|
||||
let isWeekSelected = false;
|
||||
for (let i = 0, r = 0; i < cells; i++) {
|
||||
let day = new Date(year, month, 1 + (i - before)),
|
||||
isSelected = Datepicker._isDate(this.date)
|
||||
? Datepicker._compareDates(day, this.date)
|
||||
: false,
|
||||
isToday = Datepicker._compareDates(day, now),
|
||||
hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
|
||||
isEmpty = i < before || i >= days + before,
|
||||
dayNumber = 1 + (i - before),
|
||||
monthNumber = month,
|
||||
yearNumber = year,
|
||||
isStartRange = opts.startRange && Datepicker._compareDates(opts.startRange, day),
|
||||
isEndRange = opts.endRange && Datepicker._compareDates(opts.endRange, day),
|
||||
isInRange =
|
||||
opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
|
||||
isDisabled =
|
||||
(opts.minDate && day < opts.minDate) ||
|
||||
(opts.maxDate && day > opts.maxDate) ||
|
||||
(opts.disableWeekends && Datepicker._isWeekend(day)) ||
|
||||
(opts.disableDayFn && opts.disableDayFn(day));
|
||||
|
||||
if (isEmpty) {
|
||||
if (i < before) {
|
||||
dayNumber = daysInPreviousMonth + dayNumber;
|
||||
monthNumber = previousMonth;
|
||||
yearNumber = yearOfPreviousMonth;
|
||||
} else {
|
||||
dayNumber = dayNumber - days;
|
||||
monthNumber = nextMonth;
|
||||
yearNumber = yearOfNextMonth;
|
||||
}
|
||||
}
|
||||
|
||||
let dayConfig = {
|
||||
day: dayNumber,
|
||||
month: monthNumber,
|
||||
year: yearNumber,
|
||||
hasEvent: hasEvent,
|
||||
isSelected: isSelected,
|
||||
isToday: isToday,
|
||||
isDisabled: isDisabled,
|
||||
isEmpty: isEmpty,
|
||||
isStartRange: isStartRange,
|
||||
isEndRange: isEndRange,
|
||||
isInRange: isInRange,
|
||||
showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths
|
||||
};
|
||||
|
||||
row.push(this.renderDay(dayConfig));
|
||||
|
||||
if (++r === 7) {
|
||||
data.push(this.renderRow(row, opts.isRTL, isWeekSelected));
|
||||
row = [];
|
||||
r = 0;
|
||||
isWeekSelected = false;
|
||||
}
|
||||
}
|
||||
return this.renderTable(opts, data, randId);
|
||||
}
|
||||
|
||||
renderDay(opts) {
|
||||
let arr = [];
|
||||
let ariaSelected = 'false';
|
||||
if (opts.isEmpty) {
|
||||
if (opts.showDaysInNextAndPreviousMonths) {
|
||||
arr.push('is-outside-current-month');
|
||||
arr.push('is-selection-disabled');
|
||||
} else {
|
||||
return '<td class="is-empty"></td>';
|
||||
}
|
||||
}
|
||||
if (opts.isDisabled) {
|
||||
arr.push('is-disabled');
|
||||
}
|
||||
|
||||
if (opts.isToday) {
|
||||
arr.push('is-today');
|
||||
}
|
||||
if (opts.isSelected) {
|
||||
arr.push('is-selected');
|
||||
ariaSelected = 'true';
|
||||
}
|
||||
if (opts.hasEvent) {
|
||||
arr.push('has-event');
|
||||
}
|
||||
if (opts.isInRange) {
|
||||
arr.push('is-inrange');
|
||||
}
|
||||
if (opts.isStartRange) {
|
||||
arr.push('is-startrange');
|
||||
}
|
||||
if (opts.isEndRange) {
|
||||
arr.push('is-endrange');
|
||||
}
|
||||
return (
|
||||
`<td data-day="${opts.day}" class="${arr.join(' ')}" aria-selected="${ariaSelected}">` +
|
||||
`<button class="datepicker-day-button" type="button" data-year="${opts.year}" data-month="${opts.month}" data-day="${opts.day}">${opts.day}</button>` +
|
||||
'</td>'
|
||||
);
|
||||
}
|
||||
|
||||
renderRow(days, isRTL, isRowSelected) {
|
||||
return (
|
||||
'<tr class="datepicker-row' +
|
||||
(isRowSelected ? ' is-selected' : '') +
|
||||
'">' +
|
||||
(isRTL ? days.reverse() : days).join('') +
|
||||
'</tr>'
|
||||
);
|
||||
}
|
||||
|
||||
renderTable(opts, data, randId) {
|
||||
return (
|
||||
'<div class="datepicker-table-wrapper"><table cellpadding="0" cellspacing="0" class="datepicker-table" role="grid" aria-labelledby="' +
|
||||
randId +
|
||||
'">' +
|
||||
this.renderHead(opts) +
|
||||
this.renderBody(data) +
|
||||
'</table></div>'
|
||||
);
|
||||
}
|
||||
|
||||
renderHead(opts) {
|
||||
let i,
|
||||
arr = [];
|
||||
for (i = 0; i < 7; i++) {
|
||||
arr.push(
|
||||
`<th scope="col"><abbr title="${this.renderDayName(opts, i)}">${this.renderDayName(
|
||||
opts,
|
||||
i,
|
||||
true
|
||||
)}</abbr></th>`
|
||||
);
|
||||
}
|
||||
return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
|
||||
}
|
||||
|
||||
renderBody(rows) {
|
||||
return '<tbody>' + rows.join('') + '</tbody>';
|
||||
}
|
||||
|
||||
renderTitle(instance, c, year, month, refYear, randId) {
|
||||
let i,
|
||||
j,
|
||||
arr,
|
||||
opts = this.options,
|
||||
isMinYear = year === opts.minYear,
|
||||
isMaxYear = year === opts.maxYear,
|
||||
html =
|
||||
'<div id="' +
|
||||
randId +
|
||||
'" class="datepicker-controls" role="heading" aria-live="assertive">',
|
||||
monthHtml,
|
||||
yearHtml,
|
||||
prev = true,
|
||||
next = true;
|
||||
|
||||
for (arr = [], i = 0; i < 12; i++) {
|
||||
arr.push(
|
||||
'<option value="' +
|
||||
(year === refYear ? i - c : 12 + i - c) +
|
||||
'"' +
|
||||
(i === month ? ' selected="selected"' : '') +
|
||||
((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth)
|
||||
? 'disabled="disabled"'
|
||||
: '') +
|
||||
'>' +
|
||||
opts.i18n.months[i] +
|
||||
'</option>'
|
||||
);
|
||||
}
|
||||
|
||||
monthHtml =
|
||||
'<select class="datepicker-select orig-select-month" tabindex="-1">' +
|
||||
arr.join('') +
|
||||
'</select>';
|
||||
|
||||
if ($.isArray(opts.yearRange)) {
|
||||
i = opts.yearRange[0];
|
||||
j = opts.yearRange[1] + 1;
|
||||
} else {
|
||||
i = year - opts.yearRange;
|
||||
j = 1 + year + opts.yearRange;
|
||||
}
|
||||
|
||||
for (arr = []; i < j && i <= opts.maxYear; i++) {
|
||||
if (i >= opts.minYear) {
|
||||
arr.push(`<option value="${i}" ${i === year ? 'selected="selected"' : ''}>${i}</option>`);
|
||||
}
|
||||
}
|
||||
if (opts.yearRangeReverse) {
|
||||
arr.reverse();
|
||||
}
|
||||
|
||||
yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join(
|
||||
''
|
||||
)}</select>`;
|
||||
|
||||
let leftArrow =
|
||||
'<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/><path d="M0-.5h24v24H0z" fill="none"/></svg>';
|
||||
html += `<button class="month-prev${
|
||||
prev ? '' : ' is-disabled'
|
||||
}" type="button">${leftArrow}</button>`;
|
||||
|
||||
html += '<div class="selects-container">';
|
||||
if (opts.showMonthAfterYear) {
|
||||
html += yearHtml + monthHtml;
|
||||
} else {
|
||||
html += monthHtml + yearHtml;
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
if (isMinYear && (month === 0 || opts.minMonth >= month)) {
|
||||
prev = false;
|
||||
}
|
||||
|
||||
if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
|
||||
next = false;
|
||||
}
|
||||
|
||||
let rightArrow =
|
||||
'<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/><path d="M0-.25h24v24H0z" fill="none"/></svg>';
|
||||
html += `<button class="month-next${
|
||||
next ? '' : ' is-disabled'
|
||||
}" type="button">${rightArrow}</button>`;
|
||||
|
||||
return (html += '</div>');
|
||||
}
|
||||
|
||||
/**
|
||||
* refresh the HTML
|
||||
*/
|
||||
draw(force) {
|
||||
if (!this.isOpen && !force) {
|
||||
return;
|
||||
}
|
||||
let opts = this.options,
|
||||
minYear = opts.minYear,
|
||||
maxYear = opts.maxYear,
|
||||
minMonth = opts.minMonth,
|
||||
maxMonth = opts.maxMonth,
|
||||
html = '',
|
||||
randId;
|
||||
|
||||
if (this._y <= minYear) {
|
||||
this._y = minYear;
|
||||
if (!isNaN(minMonth) && this._m < minMonth) {
|
||||
this._m = minMonth;
|
||||
}
|
||||
}
|
||||
if (this._y >= maxYear) {
|
||||
this._y = maxYear;
|
||||
if (!isNaN(maxMonth) && this._m > maxMonth) {
|
||||
this._m = maxMonth;
|
||||
}
|
||||
}
|
||||
|
||||
randId =
|
||||
'datepicker-title-' +
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.replace(/[^a-z]+/g, '')
|
||||
.substr(0, 2);
|
||||
|
||||
for (let c = 0; c < 1; c++) {
|
||||
this._renderDateDisplay();
|
||||
html +=
|
||||
this.renderTitle(
|
||||
this,
|
||||
c,
|
||||
this.calendars[c].year,
|
||||
this.calendars[c].month,
|
||||
this.calendars[0].year,
|
||||
randId
|
||||
) + this.render(this.calendars[c].year, this.calendars[c].month, randId);
|
||||
}
|
||||
|
||||
this.destroySelects();
|
||||
|
||||
this.calendarEl.innerHTML = html;
|
||||
|
||||
// Init Materialize Select
|
||||
let yearSelect = this.calendarEl.querySelector('.orig-select-year');
|
||||
let monthSelect = this.calendarEl.querySelector('.orig-select-month');
|
||||
M.FormSelect.init(yearSelect, {
|
||||
classes: 'select-year',
|
||||
dropdownOptions: { container: document.body, constrainWidth: false }
|
||||
});
|
||||
M.FormSelect.init(monthSelect, {
|
||||
classes: 'select-month',
|
||||
dropdownOptions: { container: document.body, constrainWidth: false }
|
||||
});
|
||||
|
||||
// Add change handlers for select
|
||||
yearSelect.addEventListener('change', this._handleYearChange.bind(this));
|
||||
monthSelect.addEventListener('change', this._handleMonthChange.bind(this));
|
||||
|
||||
if (typeof this.options.onDraw === 'function') {
|
||||
this.options.onDraw(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
|
||||
this._handleInputClickBound = this._handleInputClick.bind(this);
|
||||
this._handleInputChangeBound = this._handleInputChange.bind(this);
|
||||
this._handleCalendarClickBound = this._handleCalendarClick.bind(this);
|
||||
this._finishSelectionBound = this._finishSelection.bind(this);
|
||||
this._handleMonthChange = this._handleMonthChange.bind(this);
|
||||
this._closeBound = this.close.bind(this);
|
||||
|
||||
this.el.addEventListener('click', this._handleInputClickBound);
|
||||
this.el.addEventListener('keydown', this._handleInputKeydownBound);
|
||||
this.el.addEventListener('change', this._handleInputChangeBound);
|
||||
this.calendarEl.addEventListener('click', this._handleCalendarClickBound);
|
||||
this.doneBtn.addEventListener('click', this._finishSelectionBound);
|
||||
this.cancelBtn.addEventListener('click', this._closeBound);
|
||||
|
||||
if (this.options.showClearBtn) {
|
||||
this._handleClearClickBound = this._handleClearClick.bind(this);
|
||||
this.clearBtn.addEventListener('click', this._handleClearClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
_setupVariables() {
|
||||
this.$modalEl = $(Datepicker._template);
|
||||
this.modalEl = this.$modalEl[0];
|
||||
|
||||
this.calendarEl = this.modalEl.querySelector('.datepicker-calendar');
|
||||
|
||||
this.yearTextEl = this.modalEl.querySelector('.year-text');
|
||||
this.dateTextEl = this.modalEl.querySelector('.date-text');
|
||||
if (this.options.showClearBtn) {
|
||||
this.clearBtn = this.modalEl.querySelector('.datepicker-clear');
|
||||
}
|
||||
this.doneBtn = this.modalEl.querySelector('.datepicker-done');
|
||||
this.cancelBtn = this.modalEl.querySelector('.datepicker-cancel');
|
||||
|
||||
this.formats = {
|
||||
d: () => {
|
||||
return this.date.getDate();
|
||||
},
|
||||
dd: () => {
|
||||
let d = this.date.getDate();
|
||||
return (d < 10 ? '0' : '') + d;
|
||||
},
|
||||
ddd: () => {
|
||||
return this.options.i18n.weekdaysShort[this.date.getDay()];
|
||||
},
|
||||
dddd: () => {
|
||||
return this.options.i18n.weekdays[this.date.getDay()];
|
||||
},
|
||||
m: () => {
|
||||
return this.date.getMonth() + 1;
|
||||
},
|
||||
mm: () => {
|
||||
let m = this.date.getMonth() + 1;
|
||||
return (m < 10 ? '0' : '') + m;
|
||||
},
|
||||
mmm: () => {
|
||||
return this.options.i18n.monthsShort[this.date.getMonth()];
|
||||
},
|
||||
mmmm: () => {
|
||||
return this.options.i18n.months[this.date.getMonth()];
|
||||
},
|
||||
yy: () => {
|
||||
return ('' + this.date.getFullYear()).slice(2);
|
||||
},
|
||||
yyyy: () => {
|
||||
return this.date.getFullYear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleInputClickBound);
|
||||
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
|
||||
this.el.removeEventListener('change', this._handleInputChangeBound);
|
||||
this.calendarEl.removeEventListener('click', this._handleCalendarClickBound);
|
||||
}
|
||||
|
||||
_handleInputClick() {
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleInputKeydown(e) {
|
||||
if (e.which === M.keys.ENTER) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
_handleCalendarClick(e) {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
let $target = $(e.target);
|
||||
if (!$target.hasClass('is-disabled')) {
|
||||
if (
|
||||
$target.hasClass('datepicker-day-button') &&
|
||||
!$target.hasClass('is-empty') &&
|
||||
!$target.parent().hasClass('is-disabled')
|
||||
) {
|
||||
this.setDate(
|
||||
new Date(
|
||||
e.target.getAttribute('data-year'),
|
||||
e.target.getAttribute('data-month'),
|
||||
e.target.getAttribute('data-day')
|
||||
)
|
||||
);
|
||||
if (this.options.autoClose) {
|
||||
this._finishSelection();
|
||||
}
|
||||
} else if ($target.closest('.month-prev').length) {
|
||||
this.prevMonth();
|
||||
} else if ($target.closest('.month-next').length) {
|
||||
this.nextMonth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_handleClearClick() {
|
||||
this.date = null;
|
||||
this.setInputValue();
|
||||
this.close();
|
||||
}
|
||||
|
||||
_handleMonthChange(e) {
|
||||
this.gotoMonth(e.target.value);
|
||||
}
|
||||
|
||||
_handleYearChange(e) {
|
||||
this.gotoYear(e.target.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* change view to a specific month (zero-index, e.g. 0: January)
|
||||
*/
|
||||
gotoMonth(month) {
|
||||
if (!isNaN(month)) {
|
||||
this.calendars[0].month = parseInt(month, 10);
|
||||
this.adjustCalendars();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* change view to a specific full year (e.g. "2012")
|
||||
*/
|
||||
gotoYear(year) {
|
||||
if (!isNaN(year)) {
|
||||
this.calendars[0].year = parseInt(year, 10);
|
||||
this.adjustCalendars();
|
||||
}
|
||||
}
|
||||
|
||||
_handleInputChange(e) {
|
||||
let date;
|
||||
|
||||
// Prevent change event from being fired when triggered by the plugin
|
||||
if (e.firedBy === this) {
|
||||
return;
|
||||
}
|
||||
if (this.options.parse) {
|
||||
date = this.options.parse(this.el.value, this.options.format);
|
||||
} else {
|
||||
date = new Date(Date.parse(this.el.value));
|
||||
}
|
||||
|
||||
if (Datepicker._isDate(date)) {
|
||||
this.setDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
renderDayName(opts, day, abbr) {
|
||||
day += opts.firstDay;
|
||||
while (day >= 7) {
|
||||
day -= 7;
|
||||
}
|
||||
return abbr ? opts.i18n.weekdaysAbbrev[day] : opts.i18n.weekdays[day];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input value to the selected date and close Datepicker
|
||||
*/
|
||||
_finishSelection() {
|
||||
this.setInputValue();
|
||||
this.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Datepicker
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
if (typeof this.options.onOpen === 'function') {
|
||||
this.options.onOpen.call(this);
|
||||
}
|
||||
this.draw();
|
||||
this.modal.open();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Datepicker
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
if (typeof this.options.onClose === 'function') {
|
||||
this.options.onClose.call(this);
|
||||
}
|
||||
this.modal.close();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Datepicker._template = [
|
||||
'<div class= "modal datepicker-modal">',
|
||||
'<div class="modal-content datepicker-container">',
|
||||
'<div class="datepicker-date-display">',
|
||||
'<span class="year-text"></span>',
|
||||
'<span class="date-text"></span>',
|
||||
'</div>',
|
||||
'<div class="datepicker-calendar-container">',
|
||||
'<div class="datepicker-calendar"></div>',
|
||||
'<div class="datepicker-footer">',
|
||||
'<button class="btn-flat datepicker-clear waves-effect" style="visibility: hidden;" type="button"></button>',
|
||||
'<div class="confirmation-btns">',
|
||||
'<button class="btn-flat datepicker-cancel waves-effect" type="button"></button>',
|
||||
'<button class="btn-flat datepicker-done waves-effect" type="button"></button>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
M.Datepicker = Datepicker;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Datepicker, 'datepicker', 'M_Datepicker');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,669 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
alignment: 'left',
|
||||
autoFocus: true,
|
||||
constrainWidth: true,
|
||||
container: null,
|
||||
coverTrigger: true,
|
||||
closeOnClick: true,
|
||||
hover: false,
|
||||
inDuration: 150,
|
||||
outDuration: 250,
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null,
|
||||
onItemClick: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
class Dropdown extends Component {
|
||||
constructor(el, options) {
|
||||
super(Dropdown, el, options);
|
||||
|
||||
this.el.M_Dropdown = this;
|
||||
Dropdown._dropdowns.push(this);
|
||||
|
||||
this.id = M.getIdFromTrigger(el);
|
||||
this.dropdownEl = document.getElementById(this.id);
|
||||
this.$dropdownEl = $(this.dropdownEl);
|
||||
|
||||
/**
|
||||
* Options for the dropdown
|
||||
* @member Dropdown#options
|
||||
* @prop {String} [alignment='left'] - Edge which the dropdown is aligned to
|
||||
* @prop {Boolean} [autoFocus=true] - Automatically focus dropdown el for keyboard
|
||||
* @prop {Boolean} [constrainWidth=true] - Constrain width to width of the button
|
||||
* @prop {Element} container - Container element to attach dropdown to (optional)
|
||||
* @prop {Boolean} [coverTrigger=true] - Place dropdown over trigger
|
||||
* @prop {Boolean} [closeOnClick=true] - Close on click of dropdown item
|
||||
* @prop {Boolean} [hover=false] - Open dropdown on hover
|
||||
* @prop {Number} [inDuration=150] - Duration of open animation in ms
|
||||
* @prop {Number} [outDuration=250] - Duration of close animation in ms
|
||||
* @prop {Function} onOpenStart - Function called when dropdown starts opening
|
||||
* @prop {Function} onOpenEnd - Function called when dropdown finishes opening
|
||||
* @prop {Function} onCloseStart - Function called when dropdown starts closing
|
||||
* @prop {Function} onCloseEnd - Function called when dropdown finishes closing
|
||||
*/
|
||||
this.options = $.extend({}, Dropdown.defaults, options);
|
||||
|
||||
/**
|
||||
* Describes open/close state of dropdown
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isOpen = false;
|
||||
|
||||
/**
|
||||
* Describes if dropdown content is scrollable
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isScrollable = false;
|
||||
|
||||
/**
|
||||
* Describes if touch moving on dropdown content
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isTouchMoving = false;
|
||||
|
||||
this.focusedIndex = -1;
|
||||
this.filterQuery = [];
|
||||
|
||||
// Move dropdown-content after dropdown-trigger
|
||||
this._moveDropdown();
|
||||
|
||||
this._makeDropdownFocusable();
|
||||
this._resetFilterQueryBound = this._resetFilterQuery.bind(this);
|
||||
this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
|
||||
this._handleDocumentTouchmoveBound = this._handleDocumentTouchmove.bind(this);
|
||||
this._handleDropdownClickBound = this._handleDropdownClick.bind(this);
|
||||
this._handleDropdownKeydownBound = this._handleDropdownKeydown.bind(this);
|
||||
this._handleTriggerKeydownBound = this._handleTriggerKeydown.bind(this);
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Dropdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._resetDropdownStyles();
|
||||
this._removeEventHandlers();
|
||||
Dropdown._dropdowns.splice(Dropdown._dropdowns.indexOf(this), 1);
|
||||
this.el.M_Dropdown = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
// Trigger keydown handler
|
||||
this.el.addEventListener('keydown', this._handleTriggerKeydownBound);
|
||||
|
||||
// Item click handler
|
||||
this.dropdownEl.addEventListener('click', this._handleDropdownClickBound);
|
||||
|
||||
// Hover event handlers
|
||||
if (this.options.hover) {
|
||||
this._handleMouseEnterBound = this._handleMouseEnter.bind(this);
|
||||
this.el.addEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this._handleMouseLeaveBound = this._handleMouseLeave.bind(this);
|
||||
this.el.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.dropdownEl.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
|
||||
// Click event handlers
|
||||
} else {
|
||||
this._handleClickBound = this._handleClick.bind(this);
|
||||
this.el.addEventListener('click', this._handleClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('keydown', this._handleTriggerKeydownBound);
|
||||
this.dropdownEl.removeEventListener('click', this._handleDropdownClickBound);
|
||||
|
||||
if (this.options.hover) {
|
||||
this.el.removeEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.dropdownEl.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
} else {
|
||||
this.el.removeEventListener('click', this._handleClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
_setupTemporaryEventHandlers() {
|
||||
// Use capture phase event handler to prevent click
|
||||
document.body.addEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.addEventListener('touchmove', this._handleDocumentTouchmoveBound);
|
||||
this.dropdownEl.addEventListener('keydown', this._handleDropdownKeydownBound);
|
||||
}
|
||||
|
||||
_removeTemporaryEventHandlers() {
|
||||
// Use capture phase event handler to prevent click
|
||||
document.body.removeEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.removeEventListener('touchmove', this._handleDocumentTouchmoveBound);
|
||||
this.dropdownEl.removeEventListener('keydown', this._handleDropdownKeydownBound);
|
||||
}
|
||||
|
||||
_handleClick(e) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleMouseEnter() {
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleMouseLeave(e) {
|
||||
let toEl = e.toElement || e.relatedTarget;
|
||||
let leaveToDropdownContent = !!$(toEl).closest('.dropdown-content').length;
|
||||
let leaveToActiveDropdownTrigger = false;
|
||||
|
||||
let $closestTrigger = $(toEl).closest('.dropdown-trigger');
|
||||
if (
|
||||
$closestTrigger.length &&
|
||||
!!$closestTrigger[0].M_Dropdown &&
|
||||
$closestTrigger[0].M_Dropdown.isOpen
|
||||
) {
|
||||
leaveToActiveDropdownTrigger = true;
|
||||
}
|
||||
|
||||
// Close hover dropdown if mouse did not leave to either active dropdown-trigger or dropdown-content
|
||||
if (!leaveToActiveDropdownTrigger && !leaveToDropdownContent) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
_handleDocumentClick(e) {
|
||||
let $target = $(e.target);
|
||||
if (
|
||||
this.options.closeOnClick &&
|
||||
$target.closest('.dropdown-content').length &&
|
||||
!this.isTouchMoving
|
||||
) {
|
||||
// isTouchMoving to check if scrolling on mobile.
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 0);
|
||||
} else if (
|
||||
$target.closest('.dropdown-trigger').length ||
|
||||
!$target.closest('.dropdown-content').length
|
||||
) {
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 0);
|
||||
}
|
||||
this.isTouchMoving = false;
|
||||
}
|
||||
|
||||
_handleTriggerKeydown(e) {
|
||||
// ARROW DOWN OR ENTER WHEN SELECT IS CLOSED - open Dropdown
|
||||
if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ENTER) && !this.isOpen) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Document Touchmove
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDocumentTouchmove(e) {
|
||||
let $target = $(e.target);
|
||||
if ($target.closest('.dropdown-content').length) {
|
||||
this.isTouchMoving = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Dropdown Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDropdownClick(e) {
|
||||
// onItemClick callback
|
||||
if (typeof this.options.onItemClick === 'function') {
|
||||
let itemEl = $(e.target).closest('li')[0];
|
||||
this.options.onItemClick.call(this, itemEl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Dropdown Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDropdownKeydown(e) {
|
||||
if (e.which === M.keys.TAB) {
|
||||
e.preventDefault();
|
||||
this.close();
|
||||
|
||||
// Navigate down dropdown list
|
||||
} else if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) && this.isOpen) {
|
||||
e.preventDefault();
|
||||
let direction = e.which === M.keys.ARROW_DOWN ? 1 : -1;
|
||||
let newFocusedIndex = this.focusedIndex;
|
||||
let foundNewIndex = false;
|
||||
do {
|
||||
newFocusedIndex = newFocusedIndex + direction;
|
||||
|
||||
if (
|
||||
!!this.dropdownEl.children[newFocusedIndex] &&
|
||||
this.dropdownEl.children[newFocusedIndex].tabIndex !== -1
|
||||
) {
|
||||
foundNewIndex = true;
|
||||
break;
|
||||
}
|
||||
} while (newFocusedIndex < this.dropdownEl.children.length && newFocusedIndex >= 0);
|
||||
|
||||
if (foundNewIndex) {
|
||||
// Remove active class from old element
|
||||
if (this.focusedIndex >= 0)
|
||||
this.dropdownEl.children[this.focusedIndex].classList.remove('active');
|
||||
this.focusedIndex = newFocusedIndex;
|
||||
this._focusFocusedItem();
|
||||
}
|
||||
|
||||
// ENTER selects choice on focused item
|
||||
} else if (e.which === M.keys.ENTER && this.isOpen) {
|
||||
// Search for <a> and <button>
|
||||
let focusedElement = this.dropdownEl.children[this.focusedIndex];
|
||||
let $activatableElement = $(focusedElement)
|
||||
.find('a, button')
|
||||
.first();
|
||||
|
||||
// Click a or button tag if exists, otherwise click li tag
|
||||
if (!!$activatableElement.length) {
|
||||
$activatableElement[0].click();
|
||||
} else if (!!focusedElement) {
|
||||
focusedElement.click();
|
||||
}
|
||||
|
||||
// Close dropdown on ESC
|
||||
} else if (e.which === M.keys.ESC && this.isOpen) {
|
||||
e.preventDefault();
|
||||
this.close();
|
||||
}
|
||||
|
||||
// CASE WHEN USER TYPE LETTERS
|
||||
let letter = String.fromCharCode(e.which).toLowerCase(),
|
||||
nonLetters = [9, 13, 27, 38, 40];
|
||||
if (letter && nonLetters.indexOf(e.which) === -1) {
|
||||
this.filterQuery.push(letter);
|
||||
|
||||
let string = this.filterQuery.join(''),
|
||||
newOptionEl = $(this.dropdownEl)
|
||||
.find('li')
|
||||
.filter((el) => {
|
||||
return (
|
||||
$(el)
|
||||
.text()
|
||||
.toLowerCase()
|
||||
.indexOf(string) === 0
|
||||
);
|
||||
})[0];
|
||||
|
||||
if (newOptionEl) {
|
||||
this.focusedIndex = $(newOptionEl).index();
|
||||
this._focusFocusedItem();
|
||||
}
|
||||
}
|
||||
|
||||
this.filterTimeout = setTimeout(this._resetFilterQueryBound, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup dropdown
|
||||
*/
|
||||
_resetFilterQuery() {
|
||||
this.filterQuery = [];
|
||||
}
|
||||
|
||||
_resetDropdownStyles() {
|
||||
this.$dropdownEl.css({
|
||||
display: '',
|
||||
width: '',
|
||||
height: '',
|
||||
left: '',
|
||||
top: '',
|
||||
'transform-origin': '',
|
||||
transform: '',
|
||||
opacity: ''
|
||||
});
|
||||
}
|
||||
|
||||
// Move dropdown after container or trigger
|
||||
_moveDropdown(containerEl) {
|
||||
if (!!this.options.container) {
|
||||
$(this.options.container).append(this.dropdownEl);
|
||||
} else if (containerEl) {
|
||||
if (!containerEl.contains(this.dropdownEl)) {
|
||||
$(containerEl).append(this.dropdownEl);
|
||||
}
|
||||
} else {
|
||||
this.$el.after(this.dropdownEl);
|
||||
}
|
||||
}
|
||||
|
||||
_makeDropdownFocusable() {
|
||||
// Needed for arrow key navigation
|
||||
this.dropdownEl.tabIndex = 0;
|
||||
|
||||
// Only set tabindex if it hasn't been set by user
|
||||
$(this.dropdownEl)
|
||||
.children()
|
||||
.each(function(el) {
|
||||
if (!el.getAttribute('tabindex')) {
|
||||
el.setAttribute('tabindex', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_focusFocusedItem() {
|
||||
if (
|
||||
this.focusedIndex >= 0 &&
|
||||
this.focusedIndex < this.dropdownEl.children.length &&
|
||||
this.options.autoFocus
|
||||
) {
|
||||
this.dropdownEl.children[this.focusedIndex].focus({
|
||||
preventScroll: true
|
||||
});
|
||||
this.dropdownEl.children[this.focusedIndex].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_getDropdownPosition(closestOverflowParent) {
|
||||
let offsetParentBRect = this.el.offsetParent.getBoundingClientRect();
|
||||
let triggerBRect = this.el.getBoundingClientRect();
|
||||
let dropdownBRect = this.dropdownEl.getBoundingClientRect();
|
||||
|
||||
let idealHeight = dropdownBRect.height;
|
||||
let idealWidth = dropdownBRect.width;
|
||||
let idealXPos = triggerBRect.left - dropdownBRect.left;
|
||||
let idealYPos = triggerBRect.top - dropdownBRect.top;
|
||||
|
||||
let dropdownBounds = {
|
||||
left: idealXPos,
|
||||
top: idealYPos,
|
||||
height: idealHeight,
|
||||
width: idealWidth
|
||||
};
|
||||
|
||||
let alignments = M.checkPossibleAlignments(
|
||||
this.el,
|
||||
closestOverflowParent,
|
||||
dropdownBounds,
|
||||
this.options.coverTrigger ? 0 : triggerBRect.height
|
||||
);
|
||||
|
||||
let verticalAlignment = 'top';
|
||||
let horizontalAlignment = this.options.alignment;
|
||||
idealYPos += this.options.coverTrigger ? 0 : triggerBRect.height;
|
||||
|
||||
// Reset isScrollable
|
||||
this.isScrollable = false;
|
||||
|
||||
if (!alignments.top) {
|
||||
if (alignments.bottom) {
|
||||
verticalAlignment = 'bottom';
|
||||
|
||||
if (!this.options.coverTrigger) {
|
||||
idealYPos -= triggerBRect.height;
|
||||
}
|
||||
} else {
|
||||
this.isScrollable = true;
|
||||
|
||||
// Determine which side has most space and cutoff at correct height
|
||||
idealHeight -= 20; // Add padding when cutoff
|
||||
if (alignments.spaceOnTop > alignments.spaceOnBottom) {
|
||||
verticalAlignment = 'bottom';
|
||||
idealHeight += alignments.spaceOnTop;
|
||||
idealYPos -= this.options.coverTrigger
|
||||
? alignments.spaceOnTop - 20
|
||||
: alignments.spaceOnTop - 20 + triggerBRect.height;
|
||||
} else {
|
||||
idealHeight += alignments.spaceOnBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If preferred horizontal alignment is possible
|
||||
if (!alignments[horizontalAlignment]) {
|
||||
let oppositeAlignment = horizontalAlignment === 'left' ? 'right' : 'left';
|
||||
if (alignments[oppositeAlignment]) {
|
||||
horizontalAlignment = oppositeAlignment;
|
||||
} else {
|
||||
// Determine which side has most space and cutoff at correct height
|
||||
if (alignments.spaceOnLeft > alignments.spaceOnRight) {
|
||||
horizontalAlignment = 'right';
|
||||
idealWidth += alignments.spaceOnLeft;
|
||||
idealXPos -= alignments.spaceOnLeft;
|
||||
} else {
|
||||
horizontalAlignment = 'left';
|
||||
idealWidth += alignments.spaceOnRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verticalAlignment === 'bottom') {
|
||||
idealYPos =
|
||||
idealYPos - dropdownBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
|
||||
}
|
||||
if (horizontalAlignment === 'right') {
|
||||
idealXPos = idealXPos - dropdownBRect.width + triggerBRect.width;
|
||||
}
|
||||
return {
|
||||
x: idealXPos,
|
||||
y: idealYPos,
|
||||
verticalAlignment: verticalAlignment,
|
||||
horizontalAlignment: horizontalAlignment,
|
||||
height: idealHeight,
|
||||
width: idealWidth
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in dropdown
|
||||
*/
|
||||
_animateIn() {
|
||||
anim.remove(this.dropdownEl);
|
||||
anim({
|
||||
targets: this.dropdownEl,
|
||||
opacity: {
|
||||
value: [0, 1],
|
||||
easing: 'easeOutQuad'
|
||||
},
|
||||
scaleX: [0.3, 1],
|
||||
scaleY: [0.3, 1],
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuint',
|
||||
complete: (anim) => {
|
||||
if (this.options.autoFocus) {
|
||||
this.dropdownEl.focus();
|
||||
}
|
||||
|
||||
// onOpenEnd callback
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate out dropdown
|
||||
*/
|
||||
_animateOut() {
|
||||
anim.remove(this.dropdownEl);
|
||||
anim({
|
||||
targets: this.dropdownEl,
|
||||
opacity: {
|
||||
value: 0,
|
||||
easing: 'easeOutQuint'
|
||||
},
|
||||
scaleX: 0.3,
|
||||
scaleY: 0.3,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuint',
|
||||
complete: (anim) => {
|
||||
this._resetDropdownStyles();
|
||||
|
||||
// onCloseEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Place dropdown
|
||||
*/
|
||||
_placeDropdown() {
|
||||
/**
|
||||
* Get closest ancestor that satisfies the condition
|
||||
* @param {Element} el Element to find ancestors on
|
||||
* @param {Function} condition Function that given an ancestor element returns true or false
|
||||
* @returns {Element} Return closest ancestor or null if none satisfies the condition
|
||||
*/
|
||||
const getClosestAncestor = function(el, condition) {
|
||||
let ancestor = el.parentNode;
|
||||
while (ancestor !== null && !$(ancestor).is(document)) {
|
||||
if (condition(ancestor)) {
|
||||
return ancestor;
|
||||
}
|
||||
ancestor = ancestor.parentNode;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Container here will be closest ancestor with overflow: hidden
|
||||
let closestOverflowParent = getClosestAncestor(this.dropdownEl, (ancestor) => {
|
||||
return $(ancestor).css('overflow') !== 'visible';
|
||||
});
|
||||
// Fallback
|
||||
if (!closestOverflowParent) {
|
||||
closestOverflowParent = !!this.dropdownEl.offsetParent
|
||||
? this.dropdownEl.offsetParent
|
||||
: this.dropdownEl.parentNode;
|
||||
}
|
||||
if ($(closestOverflowParent).css('position') === 'static')
|
||||
$(closestOverflowParent).css('position', 'relative');
|
||||
|
||||
this._moveDropdown(closestOverflowParent);
|
||||
|
||||
// Set width before calculating positionInfo
|
||||
let idealWidth = this.options.constrainWidth
|
||||
? this.el.getBoundingClientRect().width
|
||||
: this.dropdownEl.getBoundingClientRect().width;
|
||||
this.dropdownEl.style.width = idealWidth + 'px';
|
||||
|
||||
let positionInfo = this._getDropdownPosition(closestOverflowParent);
|
||||
this.dropdownEl.style.left = positionInfo.x + 'px';
|
||||
this.dropdownEl.style.top = positionInfo.y + 'px';
|
||||
this.dropdownEl.style.height = positionInfo.height + 'px';
|
||||
this.dropdownEl.style.width = positionInfo.width + 'px';
|
||||
this.dropdownEl.style.transformOrigin = `${
|
||||
positionInfo.horizontalAlignment === 'left' ? '0' : '100%'
|
||||
} ${positionInfo.verticalAlignment === 'top' ? '0' : '100%'}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Dropdown
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
this.isOpen = true;
|
||||
|
||||
// onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, this.el);
|
||||
}
|
||||
|
||||
// Reset styles
|
||||
this._resetDropdownStyles();
|
||||
this.dropdownEl.style.display = 'block';
|
||||
|
||||
this._placeDropdown();
|
||||
this._animateIn();
|
||||
this._setupTemporaryEventHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Dropdown
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
this.focusedIndex = -1;
|
||||
|
||||
// onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, this.el);
|
||||
}
|
||||
|
||||
this._animateOut();
|
||||
this._removeTemporaryEventHandlers();
|
||||
|
||||
if (this.options.autoFocus) {
|
||||
this.el.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate dimensions
|
||||
*/
|
||||
recalculateDimensions() {
|
||||
if (this.isOpen) {
|
||||
this.$dropdownEl.css({
|
||||
width: '',
|
||||
height: '',
|
||||
left: '',
|
||||
top: '',
|
||||
'transform-origin': ''
|
||||
});
|
||||
this._placeDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Dropdown
|
||||
*/
|
||||
Dropdown._dropdowns = [];
|
||||
|
||||
M.Dropdown = Dropdown;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,275 @@
|
|||
(function($) {
|
||||
// Function to update labels of text fields
|
||||
M.updateTextFields = function() {
|
||||
let input_selector =
|
||||
'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], input[type=date], input[type=time], textarea';
|
||||
$(input_selector).each(function(element, index) {
|
||||
let $this = $(this);
|
||||
if (
|
||||
element.value.length > 0 ||
|
||||
$(element).is(':focus') ||
|
||||
element.autofocus ||
|
||||
$this.attr('placeholder') !== null
|
||||
) {
|
||||
$this.siblings('label').addClass('active');
|
||||
} else if (element.validity) {
|
||||
$this.siblings('label').toggleClass('active', element.validity.badInput === true);
|
||||
} else {
|
||||
$this.siblings('label').removeClass('active');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
M.validate_field = function(object) {
|
||||
let hasLength = object.attr('data-length') !== null;
|
||||
let lenAttr = parseInt(object.attr('data-length'));
|
||||
let len = object[0].value.length;
|
||||
|
||||
if (len === 0 && object[0].validity.badInput === false && !object.is(':required')) {
|
||||
if (object.hasClass('validate')) {
|
||||
object.removeClass('valid');
|
||||
object.removeClass('invalid');
|
||||
}
|
||||
} else {
|
||||
if (object.hasClass('validate')) {
|
||||
// Check for character counter attributes
|
||||
if (
|
||||
(object.is(':valid') && hasLength && len <= lenAttr) ||
|
||||
(object.is(':valid') && !hasLength)
|
||||
) {
|
||||
object.removeClass('invalid');
|
||||
object.addClass('valid');
|
||||
} else {
|
||||
object.removeClass('valid');
|
||||
object.addClass('invalid');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
M.textareaAutoResize = function($textarea) {
|
||||
// Wrap if native element
|
||||
if ($textarea instanceof Element) {
|
||||
$textarea = $($textarea);
|
||||
}
|
||||
|
||||
if (!$textarea.length) {
|
||||
console.error('No textarea element found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Textarea Auto Resize
|
||||
let hiddenDiv = $('.hiddendiv').first();
|
||||
if (!hiddenDiv.length) {
|
||||
hiddenDiv = $('<div class="hiddendiv common"></div>');
|
||||
$('body').append(hiddenDiv);
|
||||
}
|
||||
|
||||
// Set font properties of hiddenDiv
|
||||
let fontFamily = $textarea.css('font-family');
|
||||
let fontSize = $textarea.css('font-size');
|
||||
let lineHeight = $textarea.css('line-height');
|
||||
|
||||
// Firefox can't handle padding shorthand.
|
||||
let paddingTop = $textarea.css('padding-top');
|
||||
let paddingRight = $textarea.css('padding-right');
|
||||
let paddingBottom = $textarea.css('padding-bottom');
|
||||
let paddingLeft = $textarea.css('padding-left');
|
||||
|
||||
if (fontSize) {
|
||||
hiddenDiv.css('font-size', fontSize);
|
||||
}
|
||||
if (fontFamily) {
|
||||
hiddenDiv.css('font-family', fontFamily);
|
||||
}
|
||||
if (lineHeight) {
|
||||
hiddenDiv.css('line-height', lineHeight);
|
||||
}
|
||||
if (paddingTop) {
|
||||
hiddenDiv.css('padding-top', paddingTop);
|
||||
}
|
||||
if (paddingRight) {
|
||||
hiddenDiv.css('padding-right', paddingRight);
|
||||
}
|
||||
if (paddingBottom) {
|
||||
hiddenDiv.css('padding-bottom', paddingBottom);
|
||||
}
|
||||
if (paddingLeft) {
|
||||
hiddenDiv.css('padding-left', paddingLeft);
|
||||
}
|
||||
|
||||
// Set original-height, if none
|
||||
if (!$textarea.data('original-height')) {
|
||||
$textarea.data('original-height', $textarea.height());
|
||||
}
|
||||
|
||||
if ($textarea.attr('wrap') === 'off') {
|
||||
hiddenDiv.css('overflow-wrap', 'normal').css('white-space', 'pre');
|
||||
}
|
||||
|
||||
hiddenDiv.text($textarea[0].value + '\n');
|
||||
let content = hiddenDiv.html().replace(/\n/g, '<br>');
|
||||
hiddenDiv.html(content);
|
||||
|
||||
// When textarea is hidden, width goes crazy.
|
||||
// Approximate with half of window size
|
||||
|
||||
if ($textarea[0].offsetWidth > 0 && $textarea[0].offsetHeight > 0) {
|
||||
hiddenDiv.css('width', $textarea.width() + 'px');
|
||||
} else {
|
||||
hiddenDiv.css('width', window.innerWidth / 2 + 'px');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize if the new height is greater than the
|
||||
* original height of the textarea
|
||||
*/
|
||||
if ($textarea.data('original-height') <= hiddenDiv.innerHeight()) {
|
||||
$textarea.css('height', hiddenDiv.innerHeight() + 'px');
|
||||
} else if ($textarea[0].value.length < $textarea.data('previous-length')) {
|
||||
/**
|
||||
* In case the new height is less than original height, it
|
||||
* means the textarea has less text than before
|
||||
* So we set the height to the original one
|
||||
*/
|
||||
$textarea.css('height', $textarea.data('original-height') + 'px');
|
||||
}
|
||||
$textarea.data('previous-length', $textarea[0].value.length);
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
// Text based inputs
|
||||
let input_selector =
|
||||
'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], input[type=date], input[type=time], textarea';
|
||||
|
||||
// Add active if form auto complete
|
||||
$(document).on('change', input_selector, function() {
|
||||
if (this.value.length !== 0 || $(this).attr('placeholder') !== null) {
|
||||
$(this)
|
||||
.siblings('label')
|
||||
.addClass('active');
|
||||
}
|
||||
M.validate_field($(this));
|
||||
});
|
||||
|
||||
// Add active if input element has been pre-populated on document ready
|
||||
$(document).ready(function() {
|
||||
M.updateTextFields();
|
||||
});
|
||||
|
||||
// HTML DOM FORM RESET handling
|
||||
$(document).on('reset', function(e) {
|
||||
let formReset = $(e.target);
|
||||
if (formReset.is('form')) {
|
||||
formReset
|
||||
.find(input_selector)
|
||||
.removeClass('valid')
|
||||
.removeClass('invalid');
|
||||
formReset.find(input_selector).each(function(e) {
|
||||
if (this.value.length) {
|
||||
$(this)
|
||||
.siblings('label')
|
||||
.removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Reset select (after native reset)
|
||||
setTimeout(function() {
|
||||
formReset.find('select').each(function() {
|
||||
// check if initialized
|
||||
if (this.M_FormSelect) {
|
||||
$(this).trigger('change');
|
||||
}
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add active when element has focus
|
||||
* @param {Event} e
|
||||
*/
|
||||
document.addEventListener(
|
||||
'focus',
|
||||
function(e) {
|
||||
if ($(e.target).is(input_selector)) {
|
||||
$(e.target)
|
||||
.siblings('label, .prefix')
|
||||
.addClass('active');
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Remove active when element is blurred
|
||||
* @param {Event} e
|
||||
*/
|
||||
document.addEventListener(
|
||||
'blur',
|
||||
function(e) {
|
||||
let $inputElement = $(e.target);
|
||||
if ($inputElement.is(input_selector)) {
|
||||
let selector = '.prefix';
|
||||
|
||||
if (
|
||||
$inputElement[0].value.length === 0 &&
|
||||
$inputElement[0].validity.badInput !== true &&
|
||||
$inputElement.attr('placeholder') === null
|
||||
) {
|
||||
selector += ', label';
|
||||
}
|
||||
$inputElement.siblings(selector).removeClass('active');
|
||||
M.validate_field($inputElement);
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// Radio and Checkbox focus class
|
||||
let radio_checkbox = 'input[type=radio], input[type=checkbox]';
|
||||
$(document).on('keyup', radio_checkbox, function(e) {
|
||||
// TAB, check if tabbing to radio or checkbox.
|
||||
if (e.which === M.keys.TAB) {
|
||||
$(this).addClass('tabbed');
|
||||
let $this = $(this);
|
||||
$this.one('blur', function(e) {
|
||||
$(this).removeClass('tabbed');
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
let text_area_selector = '.materialize-textarea';
|
||||
$(text_area_selector).each(function() {
|
||||
let $textarea = $(this);
|
||||
/**
|
||||
* Resize textarea on document load after storing
|
||||
* the original height and the original length
|
||||
*/
|
||||
$textarea.data('original-height', $textarea.height());
|
||||
$textarea.data('previous-length', this.value.length);
|
||||
M.textareaAutoResize($textarea);
|
||||
});
|
||||
|
||||
$(document).on('keyup', text_area_selector, function() {
|
||||
M.textareaAutoResize($(this));
|
||||
});
|
||||
$(document).on('keydown', text_area_selector, function() {
|
||||
M.textareaAutoResize($(this));
|
||||
});
|
||||
|
||||
// File Input Path
|
||||
$(document).on('change', '.file-field input[type="file"]', function() {
|
||||
let file_field = $(this).closest('.file-field');
|
||||
let path_input = file_field.find('input.file-path');
|
||||
let files = $(this)[0].files;
|
||||
let file_names = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
file_names.push(files[i].name);
|
||||
}
|
||||
path_input[0].value = file_names.join(', ');
|
||||
path_input.trigger('change');
|
||||
});
|
||||
}); // End of $(document).ready
|
||||
})(cash);
|
|
@ -0,0 +1,424 @@
|
|||
// Required for Meteor package, the use of window prevents export by Meteor
|
||||
(function(window) {
|
||||
if (window.Package) {
|
||||
M = {};
|
||||
} else {
|
||||
window.M = {};
|
||||
}
|
||||
|
||||
// Check for jQuery
|
||||
M.jQueryLoaded = !!window.jQuery;
|
||||
})(window);
|
||||
|
||||
// AMD
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define('M', [], function() {
|
||||
return M;
|
||||
});
|
||||
|
||||
// Common JS
|
||||
} else if (typeof exports !== 'undefined' && !exports.nodeType) {
|
||||
if (typeof module !== 'undefined' && !module.nodeType && module.exports) {
|
||||
exports = module.exports = M;
|
||||
}
|
||||
exports.default = M;
|
||||
}
|
||||
|
||||
M.version = '1.0.0';
|
||||
|
||||
M.keys = {
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
ESC: 27,
|
||||
ARROW_UP: 38,
|
||||
ARROW_DOWN: 40
|
||||
};
|
||||
|
||||
/**
|
||||
* TabPress Keydown handler
|
||||
*/
|
||||
M.tabPressed = false;
|
||||
M.keyDown = false;
|
||||
let docHandleKeydown = function(e) {
|
||||
M.keyDown = true;
|
||||
if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) {
|
||||
M.tabPressed = true;
|
||||
}
|
||||
};
|
||||
let docHandleKeyup = function(e) {
|
||||
M.keyDown = false;
|
||||
if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) {
|
||||
M.tabPressed = false;
|
||||
}
|
||||
};
|
||||
let docHandleFocus = function(e) {
|
||||
if (M.keyDown) {
|
||||
document.body.classList.add('keyboard-focused');
|
||||
}
|
||||
};
|
||||
let docHandleBlur = function(e) {
|
||||
document.body.classList.remove('keyboard-focused');
|
||||
};
|
||||
document.addEventListener('keydown', docHandleKeydown, true);
|
||||
document.addEventListener('keyup', docHandleKeyup, true);
|
||||
document.addEventListener('focus', docHandleFocus, true);
|
||||
document.addEventListener('blur', docHandleBlur, true);
|
||||
|
||||
/**
|
||||
* Initialize jQuery wrapper for plugin
|
||||
* @param {Class} plugin javascript class
|
||||
* @param {string} pluginName jQuery plugin name
|
||||
* @param {string} classRef Class reference name
|
||||
*/
|
||||
M.initializeJqueryWrapper = function(plugin, pluginName, classRef) {
|
||||
jQuery.fn[pluginName] = function(methodOrOptions) {
|
||||
// Call plugin method if valid method name is passed in
|
||||
if (plugin.prototype[methodOrOptions]) {
|
||||
let params = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
// Getter methods
|
||||
if (methodOrOptions.slice(0, 3) === 'get') {
|
||||
let instance = this.first()[0][classRef];
|
||||
return instance[methodOrOptions].apply(instance, params);
|
||||
}
|
||||
|
||||
// Void methods
|
||||
return this.each(function() {
|
||||
let instance = this[classRef];
|
||||
instance[methodOrOptions].apply(instance, params);
|
||||
});
|
||||
|
||||
// Initialize plugin if options or no argument is passed in
|
||||
} else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
|
||||
plugin.init(this, arguments[0]);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Return error if an unrecognized method name is passed in
|
||||
jQuery.error(`Method ${methodOrOptions} does not exist on jQuery.${pluginName}`);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Automatically initialize components
|
||||
* @param {Element} context DOM Element to search within for components
|
||||
*/
|
||||
M.AutoInit = function(context) {
|
||||
// Use document.body if no context is given
|
||||
let root = !!context ? context : document.body;
|
||||
|
||||
let registry = {
|
||||
Autocomplete: root.querySelectorAll('.autocomplete:not(.no-autoinit)'),
|
||||
Carousel: root.querySelectorAll('.carousel:not(.no-autoinit)'),
|
||||
Chips: root.querySelectorAll('.chips:not(.no-autoinit)'),
|
||||
Collapsible: root.querySelectorAll('.collapsible:not(.no-autoinit)'),
|
||||
Datepicker: root.querySelectorAll('.datepicker:not(.no-autoinit)'),
|
||||
Dropdown: root.querySelectorAll('.dropdown-trigger:not(.no-autoinit)'),
|
||||
Materialbox: root.querySelectorAll('.materialboxed:not(.no-autoinit)'),
|
||||
Modal: root.querySelectorAll('.modal:not(.no-autoinit)'),
|
||||
Parallax: root.querySelectorAll('.parallax:not(.no-autoinit)'),
|
||||
Pushpin: root.querySelectorAll('.pushpin:not(.no-autoinit)'),
|
||||
ScrollSpy: root.querySelectorAll('.scrollspy:not(.no-autoinit)'),
|
||||
FormSelect: root.querySelectorAll('select:not(.no-autoinit)'),
|
||||
Sidenav: root.querySelectorAll('.sidenav:not(.no-autoinit)'),
|
||||
Tabs: root.querySelectorAll('.tabs:not(.no-autoinit)'),
|
||||
TapTarget: root.querySelectorAll('.tap-target:not(.no-autoinit)'),
|
||||
Timepicker: root.querySelectorAll('.timepicker:not(.no-autoinit)'),
|
||||
Tooltip: root.querySelectorAll('.tooltipped:not(.no-autoinit)'),
|
||||
FloatingActionButton: root.querySelectorAll('.fixed-action-btn:not(.no-autoinit)')
|
||||
};
|
||||
|
||||
for (let pluginName in registry) {
|
||||
let plugin = M[pluginName];
|
||||
plugin.init(registry[pluginName]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate approximated selector string for a jQuery object
|
||||
* @param {jQuery} obj jQuery object to be parsed
|
||||
* @returns {string}
|
||||
*/
|
||||
M.objectSelectorString = function(obj) {
|
||||
let tagStr = obj.prop('tagName') || '';
|
||||
let idStr = obj.attr('id') || '';
|
||||
let classStr = obj.attr('class') || '';
|
||||
return (tagStr + idStr + classStr).replace(/\s/g, '');
|
||||
};
|
||||
|
||||
// Unique Random ID
|
||||
M.guid = (function() {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return function() {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Escapes hash from special characters
|
||||
* @param {string} hash String returned from this.hash
|
||||
* @returns {string}
|
||||
*/
|
||||
M.escapeHash = function(hash) {
|
||||
return hash.replace(/(:|\.|\[|\]|,|=|\/)/g, '\\$1');
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} Edges
|
||||
* @property {Boolean} top If the top edge was exceeded
|
||||
* @property {Boolean} right If the right edge was exceeded
|
||||
* @property {Boolean} bottom If the bottom edge was exceeded
|
||||
* @property {Boolean} left If the left edge was exceeded
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Bounding
|
||||
* @property {Number} left left offset coordinate
|
||||
* @property {Number} top top offset coordinate
|
||||
* @property {Number} width
|
||||
* @property {Number} height
|
||||
*/
|
||||
|
||||
/**
|
||||
* Escapes hash from special characters
|
||||
* @param {Element} container Container element that acts as the boundary
|
||||
* @param {Bounding} bounding element bounding that is being checked
|
||||
* @param {Number} offset offset from edge that counts as exceeding
|
||||
* @returns {Edges}
|
||||
*/
|
||||
M.checkWithinContainer = function(container, bounding, offset) {
|
||||
let edges = {
|
||||
top: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
left: false
|
||||
};
|
||||
|
||||
let containerRect = container.getBoundingClientRect();
|
||||
// If body element is smaller than viewport, use viewport height instead.
|
||||
let containerBottom =
|
||||
container === document.body
|
||||
? Math.max(containerRect.bottom, window.innerHeight)
|
||||
: containerRect.bottom;
|
||||
|
||||
let scrollLeft = container.scrollLeft;
|
||||
let scrollTop = container.scrollTop;
|
||||
|
||||
let scrolledX = bounding.left - scrollLeft;
|
||||
let scrolledY = bounding.top - scrollTop;
|
||||
|
||||
// Check for container and viewport for each edge
|
||||
if (scrolledX < containerRect.left + offset || scrolledX < offset) {
|
||||
edges.left = true;
|
||||
}
|
||||
|
||||
if (
|
||||
scrolledX + bounding.width > containerRect.right - offset ||
|
||||
scrolledX + bounding.width > window.innerWidth - offset
|
||||
) {
|
||||
edges.right = true;
|
||||
}
|
||||
|
||||
if (scrolledY < containerRect.top + offset || scrolledY < offset) {
|
||||
edges.top = true;
|
||||
}
|
||||
|
||||
if (
|
||||
scrolledY + bounding.height > containerBottom - offset ||
|
||||
scrolledY + bounding.height > window.innerHeight - offset
|
||||
) {
|
||||
edges.bottom = true;
|
||||
}
|
||||
|
||||
return edges;
|
||||
};
|
||||
|
||||
M.checkPossibleAlignments = function(el, container, bounding, offset) {
|
||||
let canAlign = {
|
||||
top: true,
|
||||
right: true,
|
||||
bottom: true,
|
||||
left: true,
|
||||
spaceOnTop: null,
|
||||
spaceOnRight: null,
|
||||
spaceOnBottom: null,
|
||||
spaceOnLeft: null
|
||||
};
|
||||
|
||||
let containerAllowsOverflow = getComputedStyle(container).overflow === 'visible';
|
||||
let containerRect = container.getBoundingClientRect();
|
||||
let containerHeight = Math.min(containerRect.height, window.innerHeight);
|
||||
let containerWidth = Math.min(containerRect.width, window.innerWidth);
|
||||
let elOffsetRect = el.getBoundingClientRect();
|
||||
|
||||
let scrollLeft = container.scrollLeft;
|
||||
let scrollTop = container.scrollTop;
|
||||
|
||||
let scrolledX = bounding.left - scrollLeft;
|
||||
let scrolledYTopEdge = bounding.top - scrollTop;
|
||||
let scrolledYBottomEdge = bounding.top + elOffsetRect.height - scrollTop;
|
||||
|
||||
// Check for container and viewport for left
|
||||
canAlign.spaceOnRight = !containerAllowsOverflow
|
||||
? containerWidth - (scrolledX + bounding.width)
|
||||
: window.innerWidth - (elOffsetRect.left + bounding.width);
|
||||
if (canAlign.spaceOnRight < 0) {
|
||||
canAlign.left = false;
|
||||
}
|
||||
|
||||
// Check for container and viewport for Right
|
||||
canAlign.spaceOnLeft = !containerAllowsOverflow
|
||||
? scrolledX - bounding.width + elOffsetRect.width
|
||||
: elOffsetRect.right - bounding.width;
|
||||
if (canAlign.spaceOnLeft < 0) {
|
||||
canAlign.right = false;
|
||||
}
|
||||
|
||||
// Check for container and viewport for Top
|
||||
canAlign.spaceOnBottom = !containerAllowsOverflow
|
||||
? containerHeight - (scrolledYTopEdge + bounding.height + offset)
|
||||
: window.innerHeight - (elOffsetRect.top + bounding.height + offset);
|
||||
if (canAlign.spaceOnBottom < 0) {
|
||||
canAlign.top = false;
|
||||
}
|
||||
|
||||
// Check for container and viewport for Bottom
|
||||
canAlign.spaceOnTop = !containerAllowsOverflow
|
||||
? scrolledYBottomEdge - (bounding.height - offset)
|
||||
: elOffsetRect.bottom - (bounding.height + offset);
|
||||
if (canAlign.spaceOnTop < 0) {
|
||||
canAlign.bottom = false;
|
||||
}
|
||||
|
||||
return canAlign;
|
||||
};
|
||||
|
||||
M.getOverflowParent = function(element) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (element === document.body || getComputedStyle(element).overflow !== 'visible') {
|
||||
return element;
|
||||
}
|
||||
|
||||
return M.getOverflowParent(element.parentElement);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets id of component from a trigger
|
||||
* @param {Element} trigger trigger
|
||||
* @returns {string}
|
||||
*/
|
||||
M.getIdFromTrigger = function(trigger) {
|
||||
let id = trigger.getAttribute('data-target');
|
||||
if (!id) {
|
||||
id = trigger.getAttribute('href');
|
||||
if (id) {
|
||||
id = id.slice(1);
|
||||
} else {
|
||||
id = '';
|
||||
}
|
||||
}
|
||||
return id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Multi browser support for document scroll top
|
||||
* @returns {Number}
|
||||
*/
|
||||
M.getDocumentScrollTop = function() {
|
||||
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Multi browser support for document scroll left
|
||||
* @returns {Number}
|
||||
*/
|
||||
M.getDocumentScrollLeft = function() {
|
||||
return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} Edges
|
||||
* @property {Boolean} top If the top edge was exceeded
|
||||
* @property {Boolean} right If the right edge was exceeded
|
||||
* @property {Boolean} bottom If the bottom edge was exceeded
|
||||
* @property {Boolean} left If the left edge was exceeded
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Bounding
|
||||
* @property {Number} left left offset coordinate
|
||||
* @property {Number} top top offset coordinate
|
||||
* @property {Number} width
|
||||
* @property {Number} height
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get time in ms
|
||||
* @license https://raw.github.com/jashkenas/underscore/master/LICENSE
|
||||
* @type {function}
|
||||
* @return {number}
|
||||
*/
|
||||
let getTime =
|
||||
Date.now ||
|
||||
function() {
|
||||
return new Date().getTime();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a function, that, when invoked, will only be triggered at most once
|
||||
* during a given window of time. Normally, the throttled function will run
|
||||
* as much as it can, without ever going more than once per `wait` duration;
|
||||
* but if you'd like to disable the execution on the leading edge, pass
|
||||
* `{leading: false}`. To disable execution on the trailing edge, ditto.
|
||||
* @license https://raw.github.com/jashkenas/underscore/master/LICENSE
|
||||
* @param {function} func
|
||||
* @param {number} wait
|
||||
* @param {Object=} options
|
||||
* @returns {Function}
|
||||
*/
|
||||
M.throttle = function(func, wait, options) {
|
||||
let context, args, result;
|
||||
let timeout = null;
|
||||
let previous = 0;
|
||||
options || (options = {});
|
||||
let later = function() {
|
||||
previous = options.leading === false ? 0 : getTime();
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
};
|
||||
return function() {
|
||||
let now = getTime();
|
||||
if (!previous && options.leading === false) previous = now;
|
||||
let remaining = wait - (now - previous);
|
||||
context = this;
|
||||
args = arguments;
|
||||
if (remaining <= 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
} else if (!timeout && options.trailing !== false) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
/* Feature detection */
|
||||
var passiveIfSupported = false;
|
||||
try {
|
||||
window.addEventListener("test", null,
|
||||
Object.defineProperty({}, "passive", {
|
||||
get: function() { passiveIfSupported = { passive: false }; }
|
||||
}
|
||||
));
|
||||
} catch(err) {}
|
|
@ -0,0 +1,453 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
inDuration: 275,
|
||||
outDuration: 200,
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Materialbox extends Component {
|
||||
/**
|
||||
* Construct Materialbox instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Materialbox, el, options);
|
||||
|
||||
this.el.M_Materialbox = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Materialbox#options
|
||||
* @prop {Number} [inDuration=275] - Length in ms of enter transition
|
||||
* @prop {Number} [outDuration=200] - Length in ms of exit transition
|
||||
* @prop {Function} onOpenStart - Callback function called before materialbox is opened
|
||||
* @prop {Function} onOpenEnd - Callback function called after materialbox is opened
|
||||
* @prop {Function} onCloseStart - Callback function called before materialbox is closed
|
||||
* @prop {Function} onCloseEnd - Callback function called after materialbox is closed
|
||||
*/
|
||||
this.options = $.extend({}, Materialbox.defaults, options);
|
||||
|
||||
this.overlayActive = false;
|
||||
this.doneAnimating = true;
|
||||
this.placeholder = $('<div></div>').addClass('material-placeholder');
|
||||
this.originalWidth = 0;
|
||||
this.originalHeight = 0;
|
||||
this.originInlineStyles = this.$el.attr('style');
|
||||
this.caption = this.el.getAttribute('data-caption') || '';
|
||||
|
||||
// Wrap
|
||||
this.$el.before(this.placeholder);
|
||||
this.placeholder.append(this.$el);
|
||||
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Materialbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.M_Materialbox = undefined;
|
||||
|
||||
// Unwrap image
|
||||
$(this.placeholder)
|
||||
.after(this.el)
|
||||
.remove();
|
||||
|
||||
this.$el.removeAttr('style');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleMaterialboxClickBound = this._handleMaterialboxClick.bind(this);
|
||||
this.el.addEventListener('click', this._handleMaterialboxClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleMaterialboxClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Materialbox Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleMaterialboxClick(e) {
|
||||
// If already modal, return to original
|
||||
if (this.doneAnimating === false || (this.overlayActive && this.doneAnimating)) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Window Scroll
|
||||
*/
|
||||
_handleWindowScroll() {
|
||||
if (this.overlayActive) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Window Resize
|
||||
*/
|
||||
_handleWindowResize() {
|
||||
if (this.overlayActive) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Window Resize
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleWindowEscape(e) {
|
||||
// ESC key
|
||||
if (e.keyCode === 27 && this.doneAnimating && this.overlayActive) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find ancestors with overflow: hidden; and make visible
|
||||
*/
|
||||
_makeAncestorsOverflowVisible() {
|
||||
this.ancestorsChanged = $();
|
||||
let ancestor = this.placeholder[0].parentNode;
|
||||
while (ancestor !== null && !$(ancestor).is(document)) {
|
||||
let curr = $(ancestor);
|
||||
if (curr.css('overflow') !== 'visible') {
|
||||
curr.css('overflow', 'visible');
|
||||
if (this.ancestorsChanged === undefined) {
|
||||
this.ancestorsChanged = curr;
|
||||
} else {
|
||||
this.ancestorsChanged = this.ancestorsChanged.add(curr);
|
||||
}
|
||||
}
|
||||
ancestor = ancestor.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate image in
|
||||
*/
|
||||
_animateImageIn() {
|
||||
let animOptions = {
|
||||
targets: this.el,
|
||||
height: [this.originalHeight, this.newHeight],
|
||||
width: [this.originalWidth, this.newWidth],
|
||||
left:
|
||||
M.getDocumentScrollLeft() +
|
||||
this.windowWidth / 2 -
|
||||
this.placeholder.offset().left -
|
||||
this.newWidth / 2,
|
||||
top:
|
||||
M.getDocumentScrollTop() +
|
||||
this.windowHeight / 2 -
|
||||
this.placeholder.offset().top -
|
||||
this.newHeight / 2,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.doneAnimating = true;
|
||||
|
||||
// onOpenEnd callback
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Override max-width or max-height if needed
|
||||
this.maxWidth = this.$el.css('max-width');
|
||||
this.maxHeight = this.$el.css('max-height');
|
||||
if (this.maxWidth !== 'none') {
|
||||
animOptions.maxWidth = this.newWidth;
|
||||
}
|
||||
if (this.maxHeight !== 'none') {
|
||||
animOptions.maxHeight = this.newHeight;
|
||||
}
|
||||
|
||||
anim(animOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate image out
|
||||
*/
|
||||
_animateImageOut() {
|
||||
let animOptions = {
|
||||
targets: this.el,
|
||||
width: this.originalWidth,
|
||||
height: this.originalHeight,
|
||||
left: 0,
|
||||
top: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.placeholder.css({
|
||||
height: '',
|
||||
width: '',
|
||||
position: '',
|
||||
top: '',
|
||||
left: ''
|
||||
});
|
||||
|
||||
// Revert to width or height attribute
|
||||
if (this.attrWidth) {
|
||||
this.$el.attr('width', this.attrWidth);
|
||||
}
|
||||
if (this.attrHeight) {
|
||||
this.$el.attr('height', this.attrHeight);
|
||||
}
|
||||
|
||||
this.$el.removeAttr('style');
|
||||
this.originInlineStyles && this.$el.attr('style', this.originInlineStyles);
|
||||
|
||||
// Remove class
|
||||
this.$el.removeClass('active');
|
||||
this.doneAnimating = true;
|
||||
|
||||
// Remove overflow overrides on ancestors
|
||||
if (this.ancestorsChanged.length) {
|
||||
this.ancestorsChanged.css('overflow', '');
|
||||
}
|
||||
|
||||
// onCloseEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
anim(animOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update open and close vars
|
||||
*/
|
||||
_updateVars() {
|
||||
this.windowWidth = window.innerWidth;
|
||||
this.windowHeight = window.innerHeight;
|
||||
this.caption = this.el.getAttribute('data-caption') || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Materialbox
|
||||
*/
|
||||
open() {
|
||||
this._updateVars();
|
||||
this.originalWidth = this.el.getBoundingClientRect().width;
|
||||
this.originalHeight = this.el.getBoundingClientRect().height;
|
||||
|
||||
// Set states
|
||||
this.doneAnimating = false;
|
||||
this.$el.addClass('active');
|
||||
this.overlayActive = true;
|
||||
|
||||
// onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, this.el);
|
||||
}
|
||||
|
||||
// Set positioning for placeholder
|
||||
this.placeholder.css({
|
||||
width: this.placeholder[0].getBoundingClientRect().width + 'px',
|
||||
height: this.placeholder[0].getBoundingClientRect().height + 'px',
|
||||
position: 'relative',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
|
||||
this._makeAncestorsOverflowVisible();
|
||||
|
||||
// Set css on origin
|
||||
this.$el.css({
|
||||
position: 'absolute',
|
||||
'z-index': 1000,
|
||||
'will-change': 'left, top, width, height'
|
||||
});
|
||||
|
||||
// Change from width or height attribute to css
|
||||
this.attrWidth = this.$el.attr('width');
|
||||
this.attrHeight = this.$el.attr('height');
|
||||
if (this.attrWidth) {
|
||||
this.$el.css('width', this.attrWidth + 'px');
|
||||
this.$el.removeAttr('width');
|
||||
}
|
||||
if (this.attrHeight) {
|
||||
this.$el.css('width', this.attrHeight + 'px');
|
||||
this.$el.removeAttr('height');
|
||||
}
|
||||
|
||||
// Add overlay
|
||||
this.$overlay = $('<div id="materialbox-overlay"></div>')
|
||||
.css({
|
||||
opacity: 0
|
||||
})
|
||||
.one('click', () => {
|
||||
if (this.doneAnimating) {
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Put before in origin image to preserve z-index layering.
|
||||
this.$el.before(this.$overlay);
|
||||
|
||||
// Set dimensions if needed
|
||||
let overlayOffset = this.$overlay[0].getBoundingClientRect();
|
||||
this.$overlay.css({
|
||||
width: this.windowWidth + 'px',
|
||||
height: this.windowHeight + 'px',
|
||||
left: -1 * overlayOffset.left + 'px',
|
||||
top: -1 * overlayOffset.top + 'px'
|
||||
});
|
||||
|
||||
anim.remove(this.el);
|
||||
anim.remove(this.$overlay[0]);
|
||||
|
||||
// Animate Overlay
|
||||
anim({
|
||||
targets: this.$overlay[0],
|
||||
opacity: 1,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
|
||||
// Add and animate caption if it exists
|
||||
if (this.caption !== '') {
|
||||
if (this.$photocaption) {
|
||||
anim.remove(this.$photoCaption[0]);
|
||||
}
|
||||
this.$photoCaption = $('<div class="materialbox-caption"></div>');
|
||||
this.$photoCaption.text(this.caption);
|
||||
$('body').append(this.$photoCaption);
|
||||
this.$photoCaption.css({ display: 'inline' });
|
||||
|
||||
anim({
|
||||
targets: this.$photoCaption[0],
|
||||
opacity: 1,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
|
||||
// Resize Image
|
||||
let ratio = 0;
|
||||
let widthPercent = this.originalWidth / this.windowWidth;
|
||||
let heightPercent = this.originalHeight / this.windowHeight;
|
||||
this.newWidth = 0;
|
||||
this.newHeight = 0;
|
||||
|
||||
if (widthPercent > heightPercent) {
|
||||
ratio = this.originalHeight / this.originalWidth;
|
||||
this.newWidth = this.windowWidth * 0.9;
|
||||
this.newHeight = this.windowWidth * 0.9 * ratio;
|
||||
} else {
|
||||
ratio = this.originalWidth / this.originalHeight;
|
||||
this.newWidth = this.windowHeight * 0.9 * ratio;
|
||||
this.newHeight = this.windowHeight * 0.9;
|
||||
}
|
||||
|
||||
this._animateImageIn();
|
||||
|
||||
// Handle Exit triggers
|
||||
this._handleWindowScrollBound = this._handleWindowScroll.bind(this);
|
||||
this._handleWindowResizeBound = this._handleWindowResize.bind(this);
|
||||
this._handleWindowEscapeBound = this._handleWindowEscape.bind(this);
|
||||
|
||||
window.addEventListener('scroll', this._handleWindowScrollBound);
|
||||
window.addEventListener('resize', this._handleWindowResizeBound);
|
||||
window.addEventListener('keyup', this._handleWindowEscapeBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Materialbox
|
||||
*/
|
||||
close() {
|
||||
this._updateVars();
|
||||
this.doneAnimating = false;
|
||||
|
||||
// onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, this.el);
|
||||
}
|
||||
|
||||
anim.remove(this.el);
|
||||
anim.remove(this.$overlay[0]);
|
||||
|
||||
if (this.caption !== '') {
|
||||
anim.remove(this.$photoCaption[0]);
|
||||
}
|
||||
|
||||
// disable exit handlers
|
||||
window.removeEventListener('scroll', this._handleWindowScrollBound);
|
||||
window.removeEventListener('resize', this._handleWindowResizeBound);
|
||||
window.removeEventListener('keyup', this._handleWindowEscapeBound);
|
||||
|
||||
anim({
|
||||
targets: this.$overlay[0],
|
||||
opacity: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.overlayActive = false;
|
||||
this.$overlay.remove();
|
||||
}
|
||||
});
|
||||
|
||||
this._animateImageOut();
|
||||
|
||||
// Remove Caption + reset css settings on image
|
||||
if (this.caption !== '') {
|
||||
anim({
|
||||
targets: this.$photoCaption[0],
|
||||
opacity: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.$photoCaption.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M.Materialbox = Materialbox;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Materialbox, 'materialbox', 'M_Materialbox');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,382 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
opacity: 0.5,
|
||||
inDuration: 250,
|
||||
outDuration: 250,
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null,
|
||||
preventScrolling: true,
|
||||
dismissible: true,
|
||||
startingTop: '4%',
|
||||
endingTop: '10%'
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Modal extends Component {
|
||||
/**
|
||||
* Construct Modal instance and set up overlay
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Modal, el, options);
|
||||
|
||||
this.el.M_Modal = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Modal#options
|
||||
* @prop {Number} [opacity=0.5] - Opacity of the modal overlay
|
||||
* @prop {Number} [inDuration=250] - Length in ms of enter transition
|
||||
* @prop {Number} [outDuration=250] - Length in ms of exit transition
|
||||
* @prop {Function} onOpenStart - Callback function called before modal is opened
|
||||
* @prop {Function} onOpenEnd - Callback function called after modal is opened
|
||||
* @prop {Function} onCloseStart - Callback function called before modal is closed
|
||||
* @prop {Function} onCloseEnd - Callback function called after modal is closed
|
||||
* @prop {Boolean} [dismissible=true] - Allow modal to be dismissed by keyboard or overlay click
|
||||
* @prop {String} [startingTop='4%'] - startingTop
|
||||
* @prop {String} [endingTop='10%'] - endingTop
|
||||
*/
|
||||
this.options = $.extend({}, Modal.defaults, options);
|
||||
|
||||
/**
|
||||
* Describes open/close state of modal
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isOpen = false;
|
||||
|
||||
this.id = this.$el.attr('id');
|
||||
this._openingTrigger = undefined;
|
||||
this.$overlay = $('<div class="modal-overlay"></div>');
|
||||
this.el.tabIndex = 0;
|
||||
this._nthModalOpened = 0;
|
||||
|
||||
Modal._count++;
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Modal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
Modal._count--;
|
||||
this._removeEventHandlers();
|
||||
this.el.removeAttribute('style');
|
||||
this.$overlay.remove();
|
||||
this.el.M_Modal = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleOverlayClickBound = this._handleOverlayClick.bind(this);
|
||||
this._handleModalCloseClickBound = this._handleModalCloseClick.bind(this);
|
||||
|
||||
if (Modal._count === 1) {
|
||||
document.body.addEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
this.$overlay[0].addEventListener('click', this._handleOverlayClickBound);
|
||||
this.el.addEventListener('click', this._handleModalCloseClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
if (Modal._count === 0) {
|
||||
document.body.removeEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
this.$overlay[0].removeEventListener('click', this._handleOverlayClickBound);
|
||||
this.el.removeEventListener('click', this._handleModalCloseClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Trigger Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleTriggerClick(e) {
|
||||
let $trigger = $(e.target).closest('.modal-trigger');
|
||||
if ($trigger.length) {
|
||||
let modalId = M.getIdFromTrigger($trigger[0]);
|
||||
let modalInstance = document.getElementById(modalId).M_Modal;
|
||||
if (modalInstance) {
|
||||
modalInstance.open($trigger);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Overlay Click
|
||||
*/
|
||||
_handleOverlayClick() {
|
||||
if (this.options.dismissible) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Modal Close Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleModalCloseClick(e) {
|
||||
let $closeTrigger = $(e.target).closest('.modal-close');
|
||||
if ($closeTrigger.length) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleKeydown(e) {
|
||||
// ESC key
|
||||
if (e.keyCode === 27 && this.options.dismissible) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Focus
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleFocus(e) {
|
||||
// Only trap focus if this modal is the last model opened (prevents loops in nested modals).
|
||||
if (!this.el.contains(e.target) && this._nthModalOpened === Modal._modalsOpen) {
|
||||
this.el.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in modal
|
||||
*/
|
||||
_animateIn() {
|
||||
// Set initial styles
|
||||
$.extend(this.el.style, {
|
||||
display: 'block',
|
||||
opacity: 0
|
||||
});
|
||||
$.extend(this.$overlay[0].style, {
|
||||
display: 'block',
|
||||
opacity: 0
|
||||
});
|
||||
|
||||
// Animate overlay
|
||||
anim({
|
||||
targets: this.$overlay[0],
|
||||
opacity: this.options.opacity,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
|
||||
// Define modal animation options
|
||||
let enterAnimOptions = {
|
||||
targets: this.el,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutCubic',
|
||||
// Handle modal onOpenEnd callback
|
||||
complete: () => {
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, this.el, this._openingTrigger);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Bottom sheet animation
|
||||
if (this.el.classList.contains('bottom-sheet')) {
|
||||
$.extend(enterAnimOptions, {
|
||||
bottom: 0,
|
||||
opacity: 1
|
||||
});
|
||||
anim(enterAnimOptions);
|
||||
|
||||
// Normal modal animation
|
||||
} else {
|
||||
$.extend(enterAnimOptions, {
|
||||
top: [this.options.startingTop, this.options.endingTop],
|
||||
opacity: 1,
|
||||
scaleX: [0.8, 1],
|
||||
scaleY: [0.8, 1]
|
||||
});
|
||||
anim(enterAnimOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate out modal
|
||||
*/
|
||||
_animateOut() {
|
||||
// Animate overlay
|
||||
anim({
|
||||
targets: this.$overlay[0],
|
||||
opacity: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuart'
|
||||
});
|
||||
|
||||
// Define modal animation options
|
||||
let exitAnimOptions = {
|
||||
targets: this.el,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutCubic',
|
||||
// Handle modal ready callback
|
||||
complete: () => {
|
||||
this.el.style.display = 'none';
|
||||
this.$overlay.remove();
|
||||
|
||||
// Call onCloseEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Bottom sheet animation
|
||||
if (this.el.classList.contains('bottom-sheet')) {
|
||||
$.extend(exitAnimOptions, {
|
||||
bottom: '-100%',
|
||||
opacity: 0
|
||||
});
|
||||
anim(exitAnimOptions);
|
||||
|
||||
// Normal modal animation
|
||||
} else {
|
||||
$.extend(exitAnimOptions, {
|
||||
top: [this.options.endingTop, this.options.startingTop],
|
||||
opacity: 0,
|
||||
scaleX: 0.8,
|
||||
scaleY: 0.8
|
||||
});
|
||||
anim(exitAnimOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Modal
|
||||
* @param {cash} [$trigger]
|
||||
*/
|
||||
open($trigger) {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
Modal._modalsOpen++;
|
||||
this._nthModalOpened = Modal._modalsOpen;
|
||||
|
||||
// Set Z-Index based on number of currently open modals
|
||||
this.$overlay[0].style.zIndex = 1000 + Modal._modalsOpen * 2;
|
||||
this.el.style.zIndex = 1000 + Modal._modalsOpen * 2 + 1;
|
||||
|
||||
// Set opening trigger, undefined indicates modal was opened by javascript
|
||||
this._openingTrigger = !!$trigger ? $trigger[0] : undefined;
|
||||
|
||||
// onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, this.el, this._openingTrigger);
|
||||
}
|
||||
|
||||
if (this.options.preventScrolling) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
this.el.classList.add('open');
|
||||
this.el.insertAdjacentElement('afterend', this.$overlay[0]);
|
||||
|
||||
if (this.options.dismissible) {
|
||||
this._handleKeydownBound = this._handleKeydown.bind(this);
|
||||
this._handleFocusBound = this._handleFocus.bind(this);
|
||||
document.addEventListener('keydown', this._handleKeydownBound);
|
||||
document.addEventListener('focus', this._handleFocusBound, true);
|
||||
}
|
||||
|
||||
anim.remove(this.el);
|
||||
anim.remove(this.$overlay[0]);
|
||||
this._animateIn();
|
||||
|
||||
// Focus modal
|
||||
this.el.focus();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Modal
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
Modal._modalsOpen--;
|
||||
this._nthModalOpened = 0;
|
||||
|
||||
// Call onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, this.el);
|
||||
}
|
||||
|
||||
this.el.classList.remove('open');
|
||||
|
||||
// Enable body scrolling only if there are no more modals open.
|
||||
if (Modal._modalsOpen === 0) {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
if (this.options.dismissible) {
|
||||
document.removeEventListener('keydown', this._handleKeydownBound);
|
||||
document.removeEventListener('focus', this._handleFocusBound, true);
|
||||
}
|
||||
|
||||
anim.remove(this.el);
|
||||
anim.remove(this.$overlay[0]);
|
||||
this._animateOut();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Modal
|
||||
*/
|
||||
Modal._modalsOpen = 0;
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Modal
|
||||
*/
|
||||
Modal._count = 0;
|
||||
|
||||
M.Modal = Modal;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Modal, 'modal', 'M_Modal');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,138 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
responsiveThreshold: 0 // breakpoint for swipeable
|
||||
};
|
||||
|
||||
class Parallax extends Component {
|
||||
constructor(el, options) {
|
||||
super(Parallax, el, options);
|
||||
|
||||
this.el.M_Parallax = this;
|
||||
|
||||
/**
|
||||
* Options for the Parallax
|
||||
* @member Parallax#options
|
||||
* @prop {Number} responsiveThreshold
|
||||
*/
|
||||
this.options = $.extend({}, Parallax.defaults, options);
|
||||
this._enabled = window.innerWidth > this.options.responsiveThreshold;
|
||||
|
||||
this.$img = this.$el.find('img').first();
|
||||
this.$img.each(function() {
|
||||
let el = this;
|
||||
if (el.complete) $(el).trigger('load');
|
||||
});
|
||||
|
||||
this._updateParallax();
|
||||
this._setupEventHandlers();
|
||||
this._setupStyles();
|
||||
|
||||
Parallax._parallaxes.push(this);
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Parallax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
Parallax._parallaxes.splice(Parallax._parallaxes.indexOf(this), 1);
|
||||
this.$img[0].style.transform = '';
|
||||
this._removeEventHandlers();
|
||||
|
||||
this.$el[0].M_Parallax = undefined;
|
||||
}
|
||||
|
||||
static _handleScroll() {
|
||||
for (let i = 0; i < Parallax._parallaxes.length; i++) {
|
||||
let parallaxInstance = Parallax._parallaxes[i];
|
||||
parallaxInstance._updateParallax.call(parallaxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
static _handleWindowResize() {
|
||||
for (let i = 0; i < Parallax._parallaxes.length; i++) {
|
||||
let parallaxInstance = Parallax._parallaxes[i];
|
||||
parallaxInstance._enabled =
|
||||
window.innerWidth > parallaxInstance.options.responsiveThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
_setupEventHandlers() {
|
||||
this._handleImageLoadBound = this._handleImageLoad.bind(this);
|
||||
this.$img[0].addEventListener('load', this._handleImageLoadBound);
|
||||
|
||||
if (Parallax._parallaxes.length === 0) {
|
||||
Parallax._handleScrollThrottled = M.throttle(Parallax._handleScroll, 5);
|
||||
window.addEventListener('scroll', Parallax._handleScrollThrottled);
|
||||
|
||||
Parallax._handleWindowResizeThrottled = M.throttle(Parallax._handleWindowResize, 5);
|
||||
window.addEventListener('resize', Parallax._handleWindowResizeThrottled);
|
||||
}
|
||||
}
|
||||
|
||||
_removeEventHandlers() {
|
||||
this.$img[0].removeEventListener('load', this._handleImageLoadBound);
|
||||
|
||||
if (Parallax._parallaxes.length === 0) {
|
||||
window.removeEventListener('scroll', Parallax._handleScrollThrottled);
|
||||
window.removeEventListener('resize', Parallax._handleWindowResizeThrottled);
|
||||
}
|
||||
}
|
||||
|
||||
_setupStyles() {
|
||||
this.$img[0].style.opacity = 1;
|
||||
}
|
||||
|
||||
_handleImageLoad() {
|
||||
this._updateParallax();
|
||||
}
|
||||
|
||||
_updateParallax() {
|
||||
let containerHeight = this.$el.height() > 0 ? this.el.parentNode.offsetHeight : 500;
|
||||
let imgHeight = this.$img[0].offsetHeight;
|
||||
let parallaxDist = imgHeight - containerHeight;
|
||||
let bottom = this.$el.offset().top + containerHeight;
|
||||
let top = this.$el.offset().top;
|
||||
let scrollTop = M.getDocumentScrollTop();
|
||||
let windowHeight = window.innerHeight;
|
||||
let windowBottom = scrollTop + windowHeight;
|
||||
let percentScrolled = (windowBottom - top) / (containerHeight + windowHeight);
|
||||
let parallax = parallaxDist * percentScrolled;
|
||||
|
||||
if (!this._enabled) {
|
||||
this.$img[0].style.transform = '';
|
||||
} else if (bottom > scrollTop && top < scrollTop + windowHeight) {
|
||||
this.$img[0].style.transform = `translate3D(-50%, ${parallax}px, 0)`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Parallax
|
||||
*/
|
||||
Parallax._parallaxes = [];
|
||||
|
||||
M.Parallax = Parallax;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Parallax, 'parallax', 'M_Parallax');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,148 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
top: 0,
|
||||
bottom: Infinity,
|
||||
offset: 0,
|
||||
onPositionChange: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Pushpin extends Component {
|
||||
/**
|
||||
* Construct Pushpin instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Pushpin, el, options);
|
||||
|
||||
this.el.M_Pushpin = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Pushpin#options
|
||||
*/
|
||||
this.options = $.extend({}, Pushpin.defaults, options);
|
||||
|
||||
this.originalOffset = this.el.offsetTop;
|
||||
Pushpin._pushpins.push(this);
|
||||
this._setupEventHandlers();
|
||||
this._updatePosition();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Pushpin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this.el.style.top = null;
|
||||
this._removePinClasses();
|
||||
|
||||
// Remove pushpin Inst
|
||||
let index = Pushpin._pushpins.indexOf(this);
|
||||
Pushpin._pushpins.splice(index, 1);
|
||||
if (Pushpin._pushpins.length === 0) {
|
||||
this._removeEventHandlers();
|
||||
}
|
||||
this.el.M_Pushpin = undefined;
|
||||
}
|
||||
|
||||
static _updateElements() {
|
||||
for (let elIndex in Pushpin._pushpins) {
|
||||
let pInstance = Pushpin._pushpins[elIndex];
|
||||
pInstance._updatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
_setupEventHandlers() {
|
||||
document.addEventListener('scroll', Pushpin._updateElements);
|
||||
}
|
||||
|
||||
_removeEventHandlers() {
|
||||
document.removeEventListener('scroll', Pushpin._updateElements);
|
||||
}
|
||||
|
||||
_updatePosition() {
|
||||
let scrolled = M.getDocumentScrollTop() + this.options.offset;
|
||||
|
||||
if (
|
||||
this.options.top <= scrolled &&
|
||||
this.options.bottom >= scrolled &&
|
||||
!this.el.classList.contains('pinned')
|
||||
) {
|
||||
this._removePinClasses();
|
||||
this.el.style.top = `${this.options.offset}px`;
|
||||
this.el.classList.add('pinned');
|
||||
|
||||
// onPositionChange callback
|
||||
if (typeof this.options.onPositionChange === 'function') {
|
||||
this.options.onPositionChange.call(this, 'pinned');
|
||||
}
|
||||
}
|
||||
|
||||
// Add pin-top (when scrolled position is above top)
|
||||
if (scrolled < this.options.top && !this.el.classList.contains('pin-top')) {
|
||||
this._removePinClasses();
|
||||
this.el.style.top = 0;
|
||||
this.el.classList.add('pin-top');
|
||||
|
||||
// onPositionChange callback
|
||||
if (typeof this.options.onPositionChange === 'function') {
|
||||
this.options.onPositionChange.call(this, 'pin-top');
|
||||
}
|
||||
}
|
||||
|
||||
// Add pin-bottom (when scrolled position is below bottom)
|
||||
if (scrolled > this.options.bottom && !this.el.classList.contains('pin-bottom')) {
|
||||
this._removePinClasses();
|
||||
this.el.classList.add('pin-bottom');
|
||||
this.el.style.top = `${this.options.bottom - this.originalOffset}px`;
|
||||
|
||||
// onPositionChange callback
|
||||
if (typeof this.options.onPositionChange === 'function') {
|
||||
this.options.onPositionChange.call(this, 'pin-bottom');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_removePinClasses() {
|
||||
// IE 11 bug (can't remove multiple classes in one line)
|
||||
this.el.classList.remove('pin-top');
|
||||
this.el.classList.remove('pinned');
|
||||
this.el.classList.remove('pin-bottom');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Pushpin
|
||||
*/
|
||||
Pushpin._pushpins = [];
|
||||
|
||||
M.Pushpin = Pushpin;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Pushpin, 'pushpin', 'M_Pushpin');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,263 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Range extends Component {
|
||||
/**
|
||||
* Construct Range instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Range, el, options);
|
||||
|
||||
this.el.M_Range = this;
|
||||
|
||||
/**
|
||||
* Options for the range
|
||||
* @member Range#options
|
||||
*/
|
||||
this.options = $.extend({}, Range.defaults, options);
|
||||
|
||||
this._mousedown = false;
|
||||
|
||||
// Setup
|
||||
this._setupThumb();
|
||||
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this._removeThumb();
|
||||
this.el.M_Range = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleRangeChangeBound = this._handleRangeChange.bind(this);
|
||||
this._handleRangeMousedownTouchstartBound = this._handleRangeMousedownTouchstart.bind(this);
|
||||
this._handleRangeInputMousemoveTouchmoveBound = this._handleRangeInputMousemoveTouchmove.bind(
|
||||
this
|
||||
);
|
||||
this._handleRangeMouseupTouchendBound = this._handleRangeMouseupTouchend.bind(this);
|
||||
this._handleRangeBlurMouseoutTouchleaveBound = this._handleRangeBlurMouseoutTouchleave.bind(
|
||||
this
|
||||
);
|
||||
|
||||
this.el.addEventListener('change', this._handleRangeChangeBound);
|
||||
|
||||
this.el.addEventListener('mousedown', this._handleRangeMousedownTouchstartBound);
|
||||
this.el.addEventListener('touchstart', this._handleRangeMousedownTouchstartBound);
|
||||
|
||||
this.el.addEventListener('input', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
this.el.addEventListener('mousemove', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
this.el.addEventListener('touchmove', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
|
||||
this.el.addEventListener('mouseup', this._handleRangeMouseupTouchendBound);
|
||||
this.el.addEventListener('touchend', this._handleRangeMouseupTouchendBound);
|
||||
|
||||
this.el.addEventListener('blur', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
this.el.addEventListener('mouseout', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
this.el.addEventListener('touchleave', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('change', this._handleRangeChangeBound);
|
||||
|
||||
this.el.removeEventListener('mousedown', this._handleRangeMousedownTouchstartBound);
|
||||
this.el.removeEventListener('touchstart', this._handleRangeMousedownTouchstartBound);
|
||||
|
||||
this.el.removeEventListener('input', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
this.el.removeEventListener('mousemove', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
this.el.removeEventListener('touchmove', this._handleRangeInputMousemoveTouchmoveBound);
|
||||
|
||||
this.el.removeEventListener('mouseup', this._handleRangeMouseupTouchendBound);
|
||||
this.el.removeEventListener('touchend', this._handleRangeMouseupTouchendBound);
|
||||
|
||||
this.el.removeEventListener('blur', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
this.el.removeEventListener('mouseout', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
this.el.removeEventListener('touchleave', this._handleRangeBlurMouseoutTouchleaveBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Range Change
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleRangeChange() {
|
||||
$(this.value).html(this.$el.val());
|
||||
|
||||
if (!$(this.thumb).hasClass('active')) {
|
||||
this._showRangeBubble();
|
||||
}
|
||||
|
||||
let offsetLeft = this._calcRangeOffset();
|
||||
$(this.thumb)
|
||||
.addClass('active')
|
||||
.css('left', offsetLeft + 'px');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Range Mousedown and Touchstart
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleRangeMousedownTouchstart(e) {
|
||||
// Set indicator value
|
||||
$(this.value).html(this.$el.val());
|
||||
|
||||
this._mousedown = true;
|
||||
this.$el.addClass('active');
|
||||
|
||||
if (!$(this.thumb).hasClass('active')) {
|
||||
this._showRangeBubble();
|
||||
}
|
||||
|
||||
if (e.type !== 'input') {
|
||||
let offsetLeft = this._calcRangeOffset();
|
||||
$(this.thumb)
|
||||
.addClass('active')
|
||||
.css('left', offsetLeft + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Range Input, Mousemove and Touchmove
|
||||
*/
|
||||
_handleRangeInputMousemoveTouchmove() {
|
||||
if (this._mousedown) {
|
||||
if (!$(this.thumb).hasClass('active')) {
|
||||
this._showRangeBubble();
|
||||
}
|
||||
|
||||
let offsetLeft = this._calcRangeOffset();
|
||||
$(this.thumb)
|
||||
.addClass('active')
|
||||
.css('left', offsetLeft + 'px');
|
||||
$(this.value).html(this.$el.val());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Range Mouseup and Touchend
|
||||
*/
|
||||
_handleRangeMouseupTouchend() {
|
||||
this._mousedown = false;
|
||||
this.$el.removeClass('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Range Blur, Mouseout and Touchleave
|
||||
*/
|
||||
_handleRangeBlurMouseoutTouchleave() {
|
||||
if (!this._mousedown) {
|
||||
let paddingLeft = parseInt(this.$el.css('padding-left'));
|
||||
let marginLeft = 7 + paddingLeft + 'px';
|
||||
|
||||
if ($(this.thumb).hasClass('active')) {
|
||||
anim.remove(this.thumb);
|
||||
anim({
|
||||
targets: this.thumb,
|
||||
height: 0,
|
||||
width: 0,
|
||||
top: 10,
|
||||
easing: 'easeOutQuad',
|
||||
marginLeft: marginLeft,
|
||||
duration: 100
|
||||
});
|
||||
}
|
||||
$(this.thumb).removeClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup dropdown
|
||||
*/
|
||||
_setupThumb() {
|
||||
this.thumb = document.createElement('span');
|
||||
this.value = document.createElement('span');
|
||||
$(this.thumb).addClass('thumb');
|
||||
$(this.value).addClass('value');
|
||||
$(this.thumb).append(this.value);
|
||||
this.$el.after(this.thumb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dropdown
|
||||
*/
|
||||
_removeThumb() {
|
||||
$(this.thumb).remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* morph thumb into bubble
|
||||
*/
|
||||
_showRangeBubble() {
|
||||
let paddingLeft = parseInt(
|
||||
$(this.thumb)
|
||||
.parent()
|
||||
.css('padding-left')
|
||||
);
|
||||
let marginLeft = -7 + paddingLeft + 'px'; // TODO: fix magic number?
|
||||
anim.remove(this.thumb);
|
||||
anim({
|
||||
targets: this.thumb,
|
||||
height: 30,
|
||||
width: 30,
|
||||
top: -30,
|
||||
marginLeft: marginLeft,
|
||||
duration: 300,
|
||||
easing: 'easeOutQuint'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the offset of the thumb
|
||||
* @return {Number} offset in pixels
|
||||
*/
|
||||
_calcRangeOffset() {
|
||||
let width = this.$el.width() - 15;
|
||||
let max = parseFloat(this.$el.attr('max')) || 100; // Range default max
|
||||
let min = parseFloat(this.$el.attr('min')) || 0; // Range default min
|
||||
let percent = (parseFloat(this.$el.val()) - min) / (max - min);
|
||||
return percent * width;
|
||||
}
|
||||
}
|
||||
|
||||
M.Range = Range;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Range, 'range', 'M_Range');
|
||||
}
|
||||
|
||||
Range.init($('input[type=range]'));
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,295 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
throttle: 100,
|
||||
scrollOffset: 200, // offset - 200 allows elements near bottom of page to scroll
|
||||
activeClass: 'active',
|
||||
getActiveElement: function(id) {
|
||||
return 'a[href="#' + id + '"]';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class ScrollSpy extends Component {
|
||||
/**
|
||||
* Construct ScrollSpy instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(ScrollSpy, el, options);
|
||||
|
||||
this.el.M_ScrollSpy = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Modal#options
|
||||
* @prop {Number} [throttle=100] - Throttle of scroll handler
|
||||
* @prop {Number} [scrollOffset=200] - Offset for centering element when scrolled to
|
||||
* @prop {String} [activeClass='active'] - Class applied to active elements
|
||||
* @prop {Function} [getActiveElement] - Used to find active element
|
||||
*/
|
||||
this.options = $.extend({}, ScrollSpy.defaults, options);
|
||||
|
||||
// setup
|
||||
ScrollSpy._elements.push(this);
|
||||
ScrollSpy._count++;
|
||||
ScrollSpy._increment++;
|
||||
this.tickId = -1;
|
||||
this.id = ScrollSpy._increment;
|
||||
this._setupEventHandlers();
|
||||
this._handleWindowScroll();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_ScrollSpy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
ScrollSpy._elements.splice(ScrollSpy._elements.indexOf(this), 1);
|
||||
ScrollSpy._elementsInView.splice(ScrollSpy._elementsInView.indexOf(this), 1);
|
||||
ScrollSpy._visibleElements.splice(ScrollSpy._visibleElements.indexOf(this.$el), 1);
|
||||
ScrollSpy._count--;
|
||||
this._removeEventHandlers();
|
||||
$(this.options.getActiveElement(this.$el.attr('id'))).removeClass(this.options.activeClass);
|
||||
this.el.M_ScrollSpy = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
let throttledResize = M.throttle(this._handleWindowScroll, 200);
|
||||
this._handleThrottledResizeBound = throttledResize.bind(this);
|
||||
this._handleWindowScrollBound = this._handleWindowScroll.bind(this);
|
||||
if (ScrollSpy._count === 1) {
|
||||
window.addEventListener('scroll', this._handleWindowScrollBound);
|
||||
window.addEventListener('resize', this._handleThrottledResizeBound);
|
||||
document.body.addEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
if (ScrollSpy._count === 0) {
|
||||
window.removeEventListener('scroll', this._handleWindowScrollBound);
|
||||
window.removeEventListener('resize', this._handleThrottledResizeBound);
|
||||
document.body.removeEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Trigger Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleTriggerClick(e) {
|
||||
let $trigger = $(e.target);
|
||||
for (let i = ScrollSpy._elements.length - 1; i >= 0; i--) {
|
||||
let scrollspy = ScrollSpy._elements[i];
|
||||
if ($trigger.is('a[href="#' + scrollspy.$el.attr('id') + '"]')) {
|
||||
e.preventDefault();
|
||||
let offset = scrollspy.$el.offset().top + 1;
|
||||
|
||||
anim({
|
||||
targets: [document.documentElement, document.body],
|
||||
scrollTop: offset - scrollspy.options.scrollOffset,
|
||||
duration: 400,
|
||||
easing: 'easeOutCubic'
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Window Scroll
|
||||
*/
|
||||
_handleWindowScroll() {
|
||||
// unique tick id
|
||||
ScrollSpy._ticks++;
|
||||
|
||||
// viewport rectangle
|
||||
let top = M.getDocumentScrollTop(),
|
||||
left = M.getDocumentScrollLeft(),
|
||||
right = left + window.innerWidth,
|
||||
bottom = top + window.innerHeight;
|
||||
|
||||
// determine which elements are in view
|
||||
let intersections = ScrollSpy._findElements(top, right, bottom, left);
|
||||
for (let i = 0; i < intersections.length; i++) {
|
||||
let scrollspy = intersections[i];
|
||||
let lastTick = scrollspy.tickId;
|
||||
if (lastTick < 0) {
|
||||
// entered into view
|
||||
scrollspy._enter();
|
||||
}
|
||||
|
||||
// update tick id
|
||||
scrollspy.tickId = ScrollSpy._ticks;
|
||||
}
|
||||
|
||||
for (let i = 0; i < ScrollSpy._elementsInView.length; i++) {
|
||||
let scrollspy = ScrollSpy._elementsInView[i];
|
||||
let lastTick = scrollspy.tickId;
|
||||
if (lastTick >= 0 && lastTick !== ScrollSpy._ticks) {
|
||||
// exited from view
|
||||
scrollspy._exit();
|
||||
scrollspy.tickId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// remember elements in view for next tick
|
||||
ScrollSpy._elementsInView = intersections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find elements that are within the boundary
|
||||
* @param {number} top
|
||||
* @param {number} right
|
||||
* @param {number} bottom
|
||||
* @param {number} left
|
||||
* @return {Array.<ScrollSpy>} A collection of elements
|
||||
*/
|
||||
static _findElements(top, right, bottom, left) {
|
||||
let hits = [];
|
||||
for (let i = 0; i < ScrollSpy._elements.length; i++) {
|
||||
let scrollspy = ScrollSpy._elements[i];
|
||||
let currTop = top + scrollspy.options.scrollOffset || 200;
|
||||
|
||||
if (scrollspy.$el.height() > 0) {
|
||||
let elTop = scrollspy.$el.offset().top,
|
||||
elLeft = scrollspy.$el.offset().left,
|
||||
elRight = elLeft + scrollspy.$el.width(),
|
||||
elBottom = elTop + scrollspy.$el.height();
|
||||
|
||||
let isIntersect = !(
|
||||
elLeft > right ||
|
||||
elRight < left ||
|
||||
elTop > bottom ||
|
||||
elBottom < currTop
|
||||
);
|
||||
|
||||
if (isIntersect) {
|
||||
hits.push(scrollspy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
|
||||
_enter() {
|
||||
ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter(function(value) {
|
||||
return value.height() != 0;
|
||||
});
|
||||
|
||||
if (ScrollSpy._visibleElements[0]) {
|
||||
$(this.options.getActiveElement(ScrollSpy._visibleElements[0].attr('id'))).removeClass(
|
||||
this.options.activeClass
|
||||
);
|
||||
if (
|
||||
ScrollSpy._visibleElements[0][0].M_ScrollSpy &&
|
||||
this.id < ScrollSpy._visibleElements[0][0].M_ScrollSpy.id
|
||||
) {
|
||||
ScrollSpy._visibleElements.unshift(this.$el);
|
||||
} else {
|
||||
ScrollSpy._visibleElements.push(this.$el);
|
||||
}
|
||||
} else {
|
||||
ScrollSpy._visibleElements.push(this.$el);
|
||||
}
|
||||
|
||||
$(this.options.getActiveElement(ScrollSpy._visibleElements[0].attr('id'))).addClass(
|
||||
this.options.activeClass
|
||||
);
|
||||
}
|
||||
|
||||
_exit() {
|
||||
ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter(function(value) {
|
||||
return value.height() != 0;
|
||||
});
|
||||
|
||||
if (ScrollSpy._visibleElements[0]) {
|
||||
$(this.options.getActiveElement(ScrollSpy._visibleElements[0].attr('id'))).removeClass(
|
||||
this.options.activeClass
|
||||
);
|
||||
|
||||
ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter((el) => {
|
||||
return el.attr('id') != this.$el.attr('id');
|
||||
});
|
||||
if (ScrollSpy._visibleElements[0]) {
|
||||
// Check if empty
|
||||
$(this.options.getActiveElement(ScrollSpy._visibleElements[0].attr('id'))).addClass(
|
||||
this.options.activeClass
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
* @type {Array.<ScrollSpy>}
|
||||
*/
|
||||
ScrollSpy._elements = [];
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
* @type {Array.<ScrollSpy>}
|
||||
*/
|
||||
ScrollSpy._elementsInView = [];
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
* @type {Array.<cash>}
|
||||
*/
|
||||
ScrollSpy._visibleElements = [];
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
*/
|
||||
ScrollSpy._count = 0;
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
*/
|
||||
ScrollSpy._increment = 0;
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof ScrollSpy
|
||||
*/
|
||||
ScrollSpy._ticks = 0;
|
||||
|
||||
M.ScrollSpy = ScrollSpy;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(ScrollSpy, 'scrollSpy', 'M_ScrollSpy');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,310 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
classes: '',
|
||||
dropdownOptions: {}
|
||||
};
|
||||
|
||||
class FormSelect extends Component {
|
||||
constructor(el, options) {
|
||||
super(FormSelect, el, options);
|
||||
if (this.$el.hasClass('browser-default')) return;
|
||||
this.el.M_FormSelect = this;
|
||||
this.options = $.extend({}, FormSelect.defaults, options);
|
||||
this.isMultiple = this.$el.prop('multiple');
|
||||
this.el.tabIndex = -1;
|
||||
this._values = [];
|
||||
this._setupDropdown();
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_FormSelect;
|
||||
}
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this._removeDropdown();
|
||||
this.el.M_FormSelect = undefined;
|
||||
}
|
||||
_setupEventHandlers() {
|
||||
this._handleSelectChangeBound = this._handleSelectChange.bind(this);
|
||||
this._handleOptionClickBound = this._handleOptionClick.bind(this);
|
||||
this._handleInputClickBound = this._handleInputClick.bind(this);
|
||||
$(this.dropdownOptions)
|
||||
.find('li:not(.optgroup)')
|
||||
.each((el) => {
|
||||
el.addEventListener('click', this._handleOptionClickBound);
|
||||
});
|
||||
this.el.addEventListener('change', this._handleSelectChangeBound);
|
||||
this.input.addEventListener('click', this._handleInputClickBound);
|
||||
}
|
||||
_removeEventHandlers() {
|
||||
$(this.dropdownOptions)
|
||||
.find('li:not(.optgroup)')
|
||||
.each((el) => {
|
||||
el.removeEventListener('click', this._handleOptionClickBound);
|
||||
});
|
||||
this.el.removeEventListener('change', this._handleSelectChangeBound);
|
||||
this.input.removeEventListener('click', this._handleInputClickBound);
|
||||
}
|
||||
_handleSelectChange(e) {
|
||||
this._setValueToInput();
|
||||
}
|
||||
_handleOptionClick(e) {
|
||||
e.preventDefault();
|
||||
let virtualOption = $(e.target).closest('li')[0];
|
||||
this._selectOptionElement(virtualOption);
|
||||
e.stopPropagation();
|
||||
}
|
||||
_arraysEqual(a, b) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < a.length; ++i) if (a[i] !== b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
_selectOptionElement(virtualOption) {
|
||||
if (!$(virtualOption).hasClass('disabled') && !$(virtualOption).hasClass('optgroup')) {
|
||||
const value = this._values.filter((value) => value.optionEl === virtualOption)[0];
|
||||
const previousSelectedValues = this.getSelectedValues();
|
||||
if (this.isMultiple) {
|
||||
// Multi-Select
|
||||
this._toggleEntryFromArray(value);
|
||||
} else {
|
||||
// Single-Select
|
||||
this._deselectAll();
|
||||
this._selectValue(value);
|
||||
}
|
||||
// Refresh Input-Text
|
||||
this._setValueToInput();
|
||||
// Trigger Change-Event only when data is different
|
||||
const actualSelectedValues = this.getSelectedValues();
|
||||
const selectionHasChanged = !this._arraysEqual(
|
||||
previousSelectedValues,
|
||||
actualSelectedValues
|
||||
);
|
||||
if (selectionHasChanged) this.$el.trigger('change');
|
||||
}
|
||||
if (!this.isMultiple) this.dropdown.close();
|
||||
}
|
||||
_handleInputClick() {
|
||||
if (this.dropdown && this.dropdown.isOpen) {
|
||||
this._setValueToInput();
|
||||
this._setSelectedStates();
|
||||
}
|
||||
}
|
||||
_setupDropdown() {
|
||||
this.wrapper = document.createElement('div');
|
||||
$(this.wrapper).addClass('select-wrapper ' + this.options.classes);
|
||||
this.$el.before($(this.wrapper));
|
||||
|
||||
// Move actual select element into overflow hidden wrapper
|
||||
let $hideSelect = $('<div class="hide-select"></div>');
|
||||
$(this.wrapper).append($hideSelect);
|
||||
$hideSelect[0].appendChild(this.el);
|
||||
|
||||
if (this.el.disabled) this.wrapper.classList.add('disabled');
|
||||
|
||||
// Create dropdown
|
||||
this.$selectOptions = this.$el.children('option, optgroup');
|
||||
this.dropdownOptions = document.createElement('ul');
|
||||
this.dropdownOptions.id = `select-options-${M.guid()}`;
|
||||
$(this.dropdownOptions).addClass(
|
||||
'dropdown-content select-dropdown ' + (this.isMultiple ? 'multiple-select-dropdown' : '')
|
||||
);
|
||||
|
||||
// Create dropdown structure
|
||||
if (this.$selectOptions.length) {
|
||||
this.$selectOptions.each((realOption) => {
|
||||
if ($(realOption).is('option')) {
|
||||
// Option
|
||||
const virtualOption = this._createAndAppendOptionWithIcon(
|
||||
realOption,
|
||||
this.isMultiple ? 'multiple' : undefined
|
||||
);
|
||||
this._addOptionToValues(realOption, virtualOption);
|
||||
} else if ($(realOption).is('optgroup')) {
|
||||
// Optgroup
|
||||
const selectOptions = $(realOption).children('option');
|
||||
$(this.dropdownOptions).append(
|
||||
$(
|
||||
'<li class="optgroup"><span>' + realOption.getAttribute('label') + '</span></li>'
|
||||
)[0]
|
||||
);
|
||||
selectOptions.each((realOption) => {
|
||||
const virtualOption = this._createAndAppendOptionWithIcon(
|
||||
realOption,
|
||||
'optgroup-option'
|
||||
);
|
||||
this._addOptionToValues(realOption, virtualOption);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
$(this.wrapper).append(this.dropdownOptions);
|
||||
|
||||
// Add input dropdown
|
||||
this.input = document.createElement('input');
|
||||
$(this.input).addClass('select-dropdown dropdown-trigger');
|
||||
this.input.setAttribute('type', 'text');
|
||||
this.input.setAttribute('readonly', 'true');
|
||||
this.input.setAttribute('data-target', this.dropdownOptions.id);
|
||||
if (this.el.disabled) $(this.input).prop('disabled', 'true');
|
||||
|
||||
$(this.wrapper).prepend(this.input);
|
||||
this._setValueToInput();
|
||||
|
||||
// Add caret
|
||||
let dropdownIcon = $(
|
||||
'<svg class="caret" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'
|
||||
);
|
||||
$(this.wrapper).prepend(dropdownIcon[0]);
|
||||
// Initialize dropdown
|
||||
if (!this.el.disabled) {
|
||||
let dropdownOptions = $.extend({}, this.options.dropdownOptions);
|
||||
dropdownOptions.coverTrigger = false;
|
||||
let userOnOpenEnd = dropdownOptions.onOpenEnd;
|
||||
// Add callback for centering selected option when dropdown content is scrollable
|
||||
dropdownOptions.onOpenEnd = (el) => {
|
||||
let selectedOption = $(this.dropdownOptions)
|
||||
.find('.selected')
|
||||
.first();
|
||||
if (selectedOption.length) {
|
||||
// Focus selected option in dropdown
|
||||
M.keyDown = true;
|
||||
this.dropdown.focusedIndex = selectedOption.index();
|
||||
this.dropdown._focusFocusedItem();
|
||||
M.keyDown = false;
|
||||
// Handle scrolling to selected option
|
||||
if (this.dropdown.isScrollable) {
|
||||
let scrollOffset =
|
||||
selectedOption[0].getBoundingClientRect().top -
|
||||
this.dropdownOptions.getBoundingClientRect().top; // scroll to selected option
|
||||
scrollOffset -= this.dropdownOptions.clientHeight / 2; // center in dropdown
|
||||
this.dropdownOptions.scrollTop = scrollOffset;
|
||||
}
|
||||
}
|
||||
// Handle user declared onOpenEnd if needed
|
||||
if (userOnOpenEnd && typeof userOnOpenEnd === 'function')
|
||||
userOnOpenEnd.call(this.dropdown, this.el);
|
||||
};
|
||||
// Prevent dropdown from closing too early
|
||||
dropdownOptions.closeOnClick = false;
|
||||
this.dropdown = M.Dropdown.init(this.input, dropdownOptions);
|
||||
}
|
||||
// Add initial selections
|
||||
this._setSelectedStates();
|
||||
}
|
||||
_addOptionToValues(realOption, virtualOption) {
|
||||
this._values.push({ el: realOption, optionEl: virtualOption });
|
||||
}
|
||||
_removeDropdown() {
|
||||
$(this.wrapper)
|
||||
.find('.caret')
|
||||
.remove();
|
||||
$(this.input).remove();
|
||||
$(this.dropdownOptions).remove();
|
||||
$(this.wrapper).before(this.$el);
|
||||
$(this.wrapper).remove();
|
||||
}
|
||||
_createAndAppendOptionWithIcon(realOption, type) {
|
||||
const li = document.createElement('li');
|
||||
if (realOption.disabled) li.classList.add('disabled');
|
||||
if (type === 'optgroup-option') li.classList.add(type);
|
||||
// Text / Checkbox
|
||||
const span = document.createElement('span');
|
||||
if (this.isMultiple)
|
||||
span.innerHTML = `<label><input type="checkbox"${
|
||||
realOption.disabled ? ' disabled="disabled"' : ''
|
||||
}><span>${realOption.innerHTML}</span></label>`;
|
||||
else span.innerHTML = realOption.innerHTML;
|
||||
li.appendChild(span);
|
||||
// add Icon
|
||||
const iconUrl = realOption.getAttribute('data-icon');
|
||||
const classes = realOption.getAttribute('class');
|
||||
if (iconUrl) {
|
||||
const img = $(`<img alt="" class="${classes}" src="${iconUrl}">`);
|
||||
li.prepend(img[0]);
|
||||
}
|
||||
// Check for multiple type
|
||||
$(this.dropdownOptions).append(li);
|
||||
return li;
|
||||
}
|
||||
|
||||
_selectValue(value) {
|
||||
value.el.selected = true;
|
||||
value.optionEl.classList.add('selected');
|
||||
const checkbox = value.optionEl.querySelector('input[type="checkbox"]');
|
||||
if (checkbox) checkbox.checked = true;
|
||||
}
|
||||
_deselectValue(value) {
|
||||
value.el.selected = false;
|
||||
value.optionEl.classList.remove('selected');
|
||||
const checkbox = value.optionEl.querySelector('input[type="checkbox"]');
|
||||
if (checkbox) checkbox.checked = false;
|
||||
}
|
||||
_deselectAll() {
|
||||
this._values.forEach((value) => {
|
||||
this._deselectValue(value);
|
||||
});
|
||||
}
|
||||
_isValueSelected(value) {
|
||||
const realValues = this.getSelectedValues();
|
||||
return realValues.some((realValue) => realValue === value.el.value);
|
||||
}
|
||||
_toggleEntryFromArray(value) {
|
||||
const isSelected = this._isValueSelected(value);
|
||||
if (isSelected) this._deselectValue(value);
|
||||
else this._selectValue(value);
|
||||
}
|
||||
_getSelectedOptions() {
|
||||
return Array.prototype.filter.call(this.el.selectedOptions, (realOption) => realOption);
|
||||
}
|
||||
|
||||
_setValueToInput() {
|
||||
const realOptions = this._getSelectedOptions();
|
||||
const values = this._values.filter((value) => realOptions.indexOf(value.el) >= 0);
|
||||
const texts = values.map((value) => value.optionEl.querySelector('span').innerText.trim());
|
||||
// Set input-text to first Option with empty value which indicates a description like "choose your option"
|
||||
if (texts.length === 0) {
|
||||
const firstDisabledOption = this.$el.find('option:disabled').eq(0);
|
||||
if (firstDisabledOption.length > 0 && firstDisabledOption[0].value === '') {
|
||||
this.input.value = firstDisabledOption.text();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.input.value = texts.join(', ');
|
||||
}
|
||||
_setSelectedStates() {
|
||||
this._values.forEach((value) => {
|
||||
const optionIsSelected = $(value.el).prop('selected');
|
||||
$(value.optionEl)
|
||||
.find('input[type="checkbox"]')
|
||||
.prop('checked', optionIsSelected);
|
||||
if (optionIsSelected) {
|
||||
this._activateOption($(this.dropdownOptions), $(value.optionEl));
|
||||
} else $(value.optionEl).removeClass('selected');
|
||||
});
|
||||
}
|
||||
_activateOption(ul, li) {
|
||||
if (!li) return;
|
||||
if (!this.isMultiple) ul.find('li.selected').removeClass('selected');
|
||||
$(li).addClass('selected');
|
||||
}
|
||||
|
||||
getSelectedValues() {
|
||||
return this._getSelectedOptions().map((realOption) => realOption.value);
|
||||
}
|
||||
}
|
||||
|
||||
M.FormSelect = FormSelect;
|
||||
|
||||
if (M.jQueryLoaded) M.initializeJqueryWrapper(FormSelect, 'formSelect', 'M_FormSelect');
|
||||
})(cash);
|
|
@ -0,0 +1,583 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
edge: 'left',
|
||||
draggable: true,
|
||||
dragTargetWidth: '10px',
|
||||
inDuration: 250,
|
||||
outDuration: 200,
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null,
|
||||
preventScrolling: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
class Sidenav extends Component {
|
||||
/**
|
||||
* Construct Sidenav instance and set up overlay
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Sidenav, el, options);
|
||||
|
||||
this.el.M_Sidenav = this;
|
||||
this.id = this.$el.attr('id');
|
||||
|
||||
/**
|
||||
* Options for the Sidenav
|
||||
* @member Sidenav#options
|
||||
* @prop {String} [edge='left'] - Side of screen on which Sidenav appears
|
||||
* @prop {Boolean} [draggable=true] - Allow swipe gestures to open/close Sidenav
|
||||
* @prop {String} [dragTargetWidth='10px'] - Width of the area where you can start dragging
|
||||
* @prop {Number} [inDuration=250] - Length in ms of enter transition
|
||||
* @prop {Number} [outDuration=200] - Length in ms of exit transition
|
||||
* @prop {Function} onOpenStart - Function called when sidenav starts entering
|
||||
* @prop {Function} onOpenEnd - Function called when sidenav finishes entering
|
||||
* @prop {Function} onCloseStart - Function called when sidenav starts exiting
|
||||
* @prop {Function} onCloseEnd - Function called when sidenav finishes exiting
|
||||
*/
|
||||
this.options = $.extend({}, Sidenav.defaults, options);
|
||||
|
||||
/**
|
||||
* Describes open/close state of Sidenav
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isOpen = false;
|
||||
|
||||
/**
|
||||
* Describes if Sidenav is fixed
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isFixed = this.el.classList.contains('sidenav-fixed');
|
||||
|
||||
/**
|
||||
* Describes if Sidenav is being draggeed
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isDragged = false;
|
||||
|
||||
// Window size variables for window resize checks
|
||||
this.lastWindowWidth = window.innerWidth;
|
||||
this.lastWindowHeight = window.innerHeight;
|
||||
|
||||
this._createOverlay();
|
||||
this._createDragTarget();
|
||||
this._setupEventHandlers();
|
||||
this._setupClasses();
|
||||
this._setupFixed();
|
||||
|
||||
Sidenav._sidenavs.push(this);
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Sidenav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this._enableBodyScrolling();
|
||||
this._overlay.parentNode.removeChild(this._overlay);
|
||||
this.dragTarget.parentNode.removeChild(this.dragTarget);
|
||||
this.el.M_Sidenav = undefined;
|
||||
this.el.style.transform = '';
|
||||
|
||||
let index = Sidenav._sidenavs.indexOf(this);
|
||||
if (index >= 0) {
|
||||
Sidenav._sidenavs.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
_createOverlay() {
|
||||
let overlay = document.createElement('div');
|
||||
this._closeBound = this.close.bind(this);
|
||||
overlay.classList.add('sidenav-overlay');
|
||||
|
||||
overlay.addEventListener('click', this._closeBound);
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
this._overlay = overlay;
|
||||
}
|
||||
|
||||
_setupEventHandlers() {
|
||||
if (Sidenav._sidenavs.length === 0) {
|
||||
document.body.addEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
|
||||
this._handleDragTargetDragBound = this._handleDragTargetDrag.bind(this);
|
||||
this._handleDragTargetReleaseBound = this._handleDragTargetRelease.bind(this);
|
||||
this._handleCloseDragBound = this._handleCloseDrag.bind(this);
|
||||
this._handleCloseReleaseBound = this._handleCloseRelease.bind(this);
|
||||
this._handleCloseTriggerClickBound = this._handleCloseTriggerClick.bind(this);
|
||||
|
||||
this.dragTarget.addEventListener('touchmove', this._handleDragTargetDragBound, passiveIfSupported);
|
||||
this.dragTarget.addEventListener('touchend', this._handleDragTargetReleaseBound);
|
||||
this._overlay.addEventListener('touchmove', this._handleCloseDragBound, passiveIfSupported);
|
||||
this._overlay.addEventListener('touchend', this._handleCloseReleaseBound);
|
||||
this.el.addEventListener('touchmove', this._handleCloseDragBound, passiveIfSupported);
|
||||
this.el.addEventListener('touchend', this._handleCloseReleaseBound);
|
||||
this.el.addEventListener('click', this._handleCloseTriggerClickBound);
|
||||
|
||||
// Add resize for side nav fixed
|
||||
if (this.isFixed) {
|
||||
this._handleWindowResizeBound = this._handleWindowResize.bind(this);
|
||||
window.addEventListener('resize', this._handleWindowResizeBound);
|
||||
}
|
||||
}
|
||||
|
||||
_removeEventHandlers() {
|
||||
if (Sidenav._sidenavs.length === 1) {
|
||||
document.body.removeEventListener('click', this._handleTriggerClick);
|
||||
}
|
||||
|
||||
this.dragTarget.removeEventListener('touchmove', this._handleDragTargetDragBound);
|
||||
this.dragTarget.removeEventListener('touchend', this._handleDragTargetReleaseBound);
|
||||
this._overlay.removeEventListener('touchmove', this._handleCloseDragBound);
|
||||
this._overlay.removeEventListener('touchend', this._handleCloseReleaseBound);
|
||||
this.el.removeEventListener('touchmove', this._handleCloseDragBound);
|
||||
this.el.removeEventListener('touchend', this._handleCloseReleaseBound);
|
||||
this.el.removeEventListener('click', this._handleCloseTriggerClickBound);
|
||||
|
||||
// Remove resize for side nav fixed
|
||||
if (this.isFixed) {
|
||||
window.removeEventListener('resize', this._handleWindowResizeBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Trigger Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleTriggerClick(e) {
|
||||
let $trigger = $(e.target).closest('.sidenav-trigger');
|
||||
if (e.target && $trigger.length) {
|
||||
let sidenavId = M.getIdFromTrigger($trigger[0]);
|
||||
|
||||
let sidenavInstance = document.getElementById(sidenavId).M_Sidenav;
|
||||
if (sidenavInstance) {
|
||||
sidenavInstance.open($trigger);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variables needed at the beginning of drag
|
||||
* and stop any current transition.
|
||||
* @param {Event} e
|
||||
*/
|
||||
_startDrag(e) {
|
||||
let clientX = e.targetTouches[0].clientX;
|
||||
this.isDragged = true;
|
||||
this._startingXpos = clientX;
|
||||
this._xPos = this._startingXpos;
|
||||
this._time = Date.now();
|
||||
this._width = this.el.getBoundingClientRect().width;
|
||||
this._overlay.style.display = 'block';
|
||||
this._initialScrollTop = this.isOpen ? this.el.scrollTop : M.getDocumentScrollTop();
|
||||
this._verticallyScrolling = false;
|
||||
anim.remove(this.el);
|
||||
anim.remove(this._overlay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variables needed at each drag move update tick
|
||||
* @param {Event} e
|
||||
*/
|
||||
_dragMoveUpdate(e) {
|
||||
let clientX = e.targetTouches[0].clientX;
|
||||
let currentScrollTop = this.isOpen ? this.el.scrollTop : M.getDocumentScrollTop();
|
||||
this.deltaX = Math.abs(this._xPos - clientX);
|
||||
this._xPos = clientX;
|
||||
this.velocityX = this.deltaX / (Date.now() - this._time);
|
||||
this._time = Date.now();
|
||||
if (this._initialScrollTop !== currentScrollTop) {
|
||||
this._verticallyScrolling = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Dragging of Sidenav
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDragTargetDrag(e) {
|
||||
// Check if draggable
|
||||
if (!this.options.draggable || this._isCurrentlyFixed() || this._verticallyScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not being dragged, set initial drag start variables
|
||||
if (!this.isDragged) {
|
||||
this._startDrag(e);
|
||||
}
|
||||
|
||||
// Run touchmove updates
|
||||
this._dragMoveUpdate(e);
|
||||
|
||||
// Calculate raw deltaX
|
||||
let totalDeltaX = this._xPos - this._startingXpos;
|
||||
|
||||
// dragDirection is the attempted user drag direction
|
||||
let dragDirection = totalDeltaX > 0 ? 'right' : 'left';
|
||||
|
||||
// Don't allow totalDeltaX to exceed Sidenav width or be dragged in the opposite direction
|
||||
totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
|
||||
if (this.options.edge === dragDirection) {
|
||||
totalDeltaX = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* transformX is the drag displacement
|
||||
* transformPrefix is the initial transform placement
|
||||
* Invert values if Sidenav is right edge
|
||||
*/
|
||||
let transformX = totalDeltaX;
|
||||
let transformPrefix = 'translateX(-100%)';
|
||||
if (this.options.edge === 'right') {
|
||||
transformPrefix = 'translateX(100%)';
|
||||
transformX = -transformX;
|
||||
}
|
||||
|
||||
// Calculate open/close percentage of sidenav, with open = 1 and close = 0
|
||||
this.percentOpen = Math.min(1, totalDeltaX / this._width);
|
||||
|
||||
// Set transform and opacity styles
|
||||
this.el.style.transform = `${transformPrefix} translateX(${transformX}px)`;
|
||||
this._overlay.style.opacity = this.percentOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Drag Target Release
|
||||
*/
|
||||
_handleDragTargetRelease() {
|
||||
if (this.isDragged) {
|
||||
if (this.percentOpen > 0.2) {
|
||||
this.open();
|
||||
} else {
|
||||
this._animateOut();
|
||||
}
|
||||
|
||||
this.isDragged = false;
|
||||
this._verticallyScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Close Drag
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleCloseDrag(e) {
|
||||
if (this.isOpen) {
|
||||
// Check if draggable
|
||||
if (!this.options.draggable || this._isCurrentlyFixed() || this._verticallyScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not being dragged, set initial drag start variables
|
||||
if (!this.isDragged) {
|
||||
this._startDrag(e);
|
||||
}
|
||||
|
||||
// Run touchmove updates
|
||||
this._dragMoveUpdate(e);
|
||||
|
||||
// Calculate raw deltaX
|
||||
let totalDeltaX = this._xPos - this._startingXpos;
|
||||
|
||||
// dragDirection is the attempted user drag direction
|
||||
let dragDirection = totalDeltaX > 0 ? 'right' : 'left';
|
||||
|
||||
// Don't allow totalDeltaX to exceed Sidenav width or be dragged in the opposite direction
|
||||
totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
|
||||
if (this.options.edge !== dragDirection) {
|
||||
totalDeltaX = 0;
|
||||
}
|
||||
|
||||
let transformX = -totalDeltaX;
|
||||
if (this.options.edge === 'right') {
|
||||
transformX = -transformX;
|
||||
}
|
||||
|
||||
// Calculate open/close percentage of sidenav, with open = 1 and close = 0
|
||||
this.percentOpen = Math.min(1, 1 - totalDeltaX / this._width);
|
||||
|
||||
// Set transform and opacity styles
|
||||
this.el.style.transform = `translateX(${transformX}px)`;
|
||||
this._overlay.style.opacity = this.percentOpen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Close Release
|
||||
*/
|
||||
_handleCloseRelease() {
|
||||
if (this.isOpen && this.isDragged) {
|
||||
if (this.percentOpen > 0.8) {
|
||||
this._animateIn();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
|
||||
this.isDragged = false;
|
||||
this._verticallyScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles closing of Sidenav when element with class .sidenav-close
|
||||
*/
|
||||
_handleCloseTriggerClick(e) {
|
||||
let $closeTrigger = $(e.target).closest('.sidenav-close');
|
||||
if ($closeTrigger.length && !this._isCurrentlyFixed()) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Window Resize
|
||||
*/
|
||||
_handleWindowResize() {
|
||||
// Only handle horizontal resizes
|
||||
if (this.lastWindowWidth !== window.innerWidth) {
|
||||
if (window.innerWidth > 992) {
|
||||
this.open();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
this.lastWindowWidth = window.innerWidth;
|
||||
this.lastWindowHeight = window.innerHeight;
|
||||
}
|
||||
|
||||
_setupClasses() {
|
||||
if (this.options.edge === 'right') {
|
||||
this.el.classList.add('right-aligned');
|
||||
this.dragTarget.classList.add('right-aligned');
|
||||
}
|
||||
}
|
||||
|
||||
_removeClasses() {
|
||||
this.el.classList.remove('right-aligned');
|
||||
this.dragTarget.classList.remove('right-aligned');
|
||||
}
|
||||
|
||||
_setupFixed() {
|
||||
if (this._isCurrentlyFixed()) {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
_isCurrentlyFixed() {
|
||||
return this.isFixed && window.innerWidth > 992;
|
||||
}
|
||||
|
||||
_createDragTarget() {
|
||||
let dragTarget = document.createElement('div');
|
||||
dragTarget.classList.add('drag-target');
|
||||
dragTarget.style.width = this.options.dragTargetWidth;
|
||||
document.body.appendChild(dragTarget);
|
||||
this.dragTarget = dragTarget;
|
||||
}
|
||||
|
||||
_preventBodyScrolling() {
|
||||
let body = document.body;
|
||||
body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
_enableBodyScrolling() {
|
||||
let body = document.body;
|
||||
body.style.overflow = '';
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this.isOpen === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
|
||||
// Run onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, this.el);
|
||||
}
|
||||
|
||||
// Handle fixed Sidenav
|
||||
if (this._isCurrentlyFixed()) {
|
||||
anim.remove(this.el);
|
||||
anim({
|
||||
targets: this.el,
|
||||
translateX: 0,
|
||||
duration: 0,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
this._enableBodyScrolling();
|
||||
this._overlay.style.display = 'none';
|
||||
|
||||
// Handle non-fixed Sidenav
|
||||
} else {
|
||||
if (this.options.preventScrolling) {
|
||||
this._preventBodyScrolling();
|
||||
}
|
||||
|
||||
if (!this.isDragged || this.percentOpen != 1) {
|
||||
this._animateIn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.isOpen === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
|
||||
// Run onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, this.el);
|
||||
}
|
||||
|
||||
// Handle fixed Sidenav
|
||||
if (this._isCurrentlyFixed()) {
|
||||
let transformX = this.options.edge === 'left' ? '-105%' : '105%';
|
||||
this.el.style.transform = `translateX(${transformX})`;
|
||||
|
||||
// Handle non-fixed Sidenav
|
||||
} else {
|
||||
this._enableBodyScrolling();
|
||||
|
||||
if (!this.isDragged || this.percentOpen != 0) {
|
||||
this._animateOut();
|
||||
} else {
|
||||
this._overlay.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_animateIn() {
|
||||
this._animateSidenavIn();
|
||||
this._animateOverlayIn();
|
||||
}
|
||||
|
||||
_animateSidenavIn() {
|
||||
let slideOutPercent = this.options.edge === 'left' ? -1 : 1;
|
||||
if (this.isDragged) {
|
||||
slideOutPercent =
|
||||
this.options.edge === 'left'
|
||||
? slideOutPercent + this.percentOpen
|
||||
: slideOutPercent - this.percentOpen;
|
||||
}
|
||||
|
||||
anim.remove(this.el);
|
||||
anim({
|
||||
targets: this.el,
|
||||
translateX: [`${slideOutPercent * 100}%`, 0],
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
// Run onOpenEnd callback
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_animateOverlayIn() {
|
||||
let start = 0;
|
||||
if (this.isDragged) {
|
||||
start = this.percentOpen;
|
||||
} else {
|
||||
$(this._overlay).css({
|
||||
display: 'block'
|
||||
});
|
||||
}
|
||||
|
||||
anim.remove(this._overlay);
|
||||
anim({
|
||||
targets: this._overlay,
|
||||
opacity: [start, 1],
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
|
||||
_animateOut() {
|
||||
this._animateSidenavOut();
|
||||
this._animateOverlayOut();
|
||||
}
|
||||
|
||||
_animateSidenavOut() {
|
||||
let endPercent = this.options.edge === 'left' ? -1 : 1;
|
||||
let slideOutPercent = 0;
|
||||
if (this.isDragged) {
|
||||
slideOutPercent =
|
||||
this.options.edge === 'left'
|
||||
? endPercent + this.percentOpen
|
||||
: endPercent - this.percentOpen;
|
||||
}
|
||||
|
||||
anim.remove(this.el);
|
||||
anim({
|
||||
targets: this.el,
|
||||
translateX: [`${slideOutPercent * 100}%`, `${endPercent * 105}%`],
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
// Run onOpenEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_animateOverlayOut() {
|
||||
anim.remove(this._overlay);
|
||||
anim({
|
||||
targets: this._overlay,
|
||||
opacity: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
$(this._overlay).css('display', 'none');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Sidenav
|
||||
* @type {Array.<Sidenav>}
|
||||
*/
|
||||
Sidenav._sidenavs = [];
|
||||
|
||||
M.Sidenav = Sidenav;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Sidenav, 'sidenav', 'M_Sidenav');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,359 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
indicators: true,
|
||||
height: 400,
|
||||
duration: 500,
|
||||
interval: 6000
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Slider extends Component {
|
||||
/**
|
||||
* Construct Slider instance and set up overlay
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Slider, el, options);
|
||||
|
||||
this.el.M_Slider = this;
|
||||
|
||||
/**
|
||||
* Options for the modal
|
||||
* @member Slider#options
|
||||
* @prop {Boolean} [indicators=true] - Show indicators
|
||||
* @prop {Number} [height=400] - height of slider
|
||||
* @prop {Number} [duration=500] - Length in ms of slide transition
|
||||
* @prop {Number} [interval=6000] - Length in ms of slide interval
|
||||
*/
|
||||
this.options = $.extend({}, Slider.defaults, options);
|
||||
|
||||
// setup
|
||||
this.$slider = this.$el.find('.slides');
|
||||
this.$slides = this.$slider.children('li');
|
||||
this.activeIndex = this.$slides
|
||||
.filter(function(item) {
|
||||
return $(item).hasClass('active');
|
||||
})
|
||||
.first()
|
||||
.index();
|
||||
if (this.activeIndex != -1) {
|
||||
this.$active = this.$slides.eq(this.activeIndex);
|
||||
}
|
||||
|
||||
this._setSliderHeight();
|
||||
|
||||
// Set initial positions of captions
|
||||
this.$slides.find('.caption').each((el) => {
|
||||
this._animateCaptionIn(el, 0);
|
||||
});
|
||||
|
||||
// Move img src into background-image
|
||||
this.$slides.find('img').each((el) => {
|
||||
let placeholderBase64 =
|
||||
'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
|
||||
if ($(el).attr('src') !== placeholderBase64) {
|
||||
$(el).css('background-image', 'url("' + $(el).attr('src') + '")');
|
||||
$(el).attr('src', placeholderBase64);
|
||||
}
|
||||
});
|
||||
|
||||
this._setupIndicators();
|
||||
|
||||
// Show active slide
|
||||
if (this.$active) {
|
||||
this.$active.css('display', 'block');
|
||||
} else {
|
||||
this.$slides.first().addClass('active');
|
||||
anim({
|
||||
targets: this.$slides.first()[0],
|
||||
opacity: 1,
|
||||
duration: this.options.duration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
|
||||
this.activeIndex = 0;
|
||||
this.$active = this.$slides.eq(this.activeIndex);
|
||||
|
||||
// Update indicators
|
||||
if (this.options.indicators) {
|
||||
this.$indicators.eq(this.activeIndex).addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust height to current slide
|
||||
this.$active.find('img').each((el) => {
|
||||
anim({
|
||||
targets: this.$active.find('.caption')[0],
|
||||
opacity: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
duration: this.options.duration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
});
|
||||
|
||||
this._setupEventHandlers();
|
||||
|
||||
// auto scroll
|
||||
this.start();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Slider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this.pause();
|
||||
this._removeIndicators();
|
||||
this._removeEventHandlers();
|
||||
this.el.M_Slider = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleIntervalBound = this._handleInterval.bind(this);
|
||||
this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
|
||||
|
||||
if (this.options.indicators) {
|
||||
this.$indicators.each((el) => {
|
||||
el.addEventListener('click', this._handleIndicatorClickBound);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
if (this.options.indicators) {
|
||||
this.$indicators.each((el) => {
|
||||
el.removeEventListener('click', this._handleIndicatorClickBound);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle indicator click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleIndicatorClick(e) {
|
||||
let currIndex = $(e.target).index();
|
||||
this.set(currIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Interval
|
||||
*/
|
||||
_handleInterval() {
|
||||
let newActiveIndex = this.$slider.find('.active').index();
|
||||
if (this.$slides.length === newActiveIndex + 1) newActiveIndex = 0;
|
||||
// loop to start
|
||||
else newActiveIndex += 1;
|
||||
|
||||
this.set(newActiveIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in caption
|
||||
* @param {Element} caption
|
||||
* @param {Number} duration
|
||||
*/
|
||||
_animateCaptionIn(caption, duration) {
|
||||
let animOptions = {
|
||||
targets: caption,
|
||||
opacity: 0,
|
||||
duration: duration,
|
||||
easing: 'easeOutQuad'
|
||||
};
|
||||
|
||||
if ($(caption).hasClass('center-align')) {
|
||||
animOptions.translateY = -100;
|
||||
} else if ($(caption).hasClass('right-align')) {
|
||||
animOptions.translateX = 100;
|
||||
} else if ($(caption).hasClass('left-align')) {
|
||||
animOptions.translateX = -100;
|
||||
}
|
||||
|
||||
anim(animOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set height of slider
|
||||
*/
|
||||
_setSliderHeight() {
|
||||
// If fullscreen, do nothing
|
||||
if (!this.$el.hasClass('fullscreen')) {
|
||||
if (this.options.indicators) {
|
||||
// Add height if indicators are present
|
||||
this.$el.css('height', this.options.height + 40 + 'px');
|
||||
} else {
|
||||
this.$el.css('height', this.options.height + 'px');
|
||||
}
|
||||
this.$slider.css('height', this.options.height + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup indicators
|
||||
*/
|
||||
_setupIndicators() {
|
||||
if (this.options.indicators) {
|
||||
this.$indicators = $('<ul class="indicators"></ul>');
|
||||
this.$slides.each((el, index) => {
|
||||
let $indicator = $('<li class="indicator-item"></li>');
|
||||
this.$indicators.append($indicator[0]);
|
||||
});
|
||||
this.$el.append(this.$indicators[0]);
|
||||
this.$indicators = this.$indicators.children('li.indicator-item');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove indicators
|
||||
*/
|
||||
_removeIndicators() {
|
||||
this.$el.find('ul.indicators').remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle to nth item
|
||||
* @param {Number} index
|
||||
*/
|
||||
set(index) {
|
||||
// Wrap around indices.
|
||||
if (index >= this.$slides.length) index = 0;
|
||||
else if (index < 0) index = this.$slides.length - 1;
|
||||
|
||||
// Only do if index changes
|
||||
if (this.activeIndex != index) {
|
||||
this.$active = this.$slides.eq(this.activeIndex);
|
||||
let $caption = this.$active.find('.caption');
|
||||
this.$active.removeClass('active');
|
||||
|
||||
anim({
|
||||
targets: this.$active[0],
|
||||
opacity: 0,
|
||||
duration: this.options.duration,
|
||||
easing: 'easeOutQuad',
|
||||
complete: () => {
|
||||
this.$slides.not('.active').each((el) => {
|
||||
anim({
|
||||
targets: el,
|
||||
opacity: 0,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
duration: 0,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this._animateCaptionIn($caption[0], this.options.duration);
|
||||
|
||||
// Update indicators
|
||||
if (this.options.indicators) {
|
||||
this.$indicators.eq(this.activeIndex).removeClass('active');
|
||||
this.$indicators.eq(index).addClass('active');
|
||||
}
|
||||
|
||||
anim({
|
||||
targets: this.$slides.eq(index)[0],
|
||||
opacity: 1,
|
||||
duration: this.options.duration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
|
||||
anim({
|
||||
targets: this.$slides.eq(index).find('.caption')[0],
|
||||
opacity: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
duration: this.options.duration,
|
||||
delay: this.options.duration,
|
||||
easing: 'easeOutQuad'
|
||||
});
|
||||
|
||||
this.$slides.eq(index).addClass('active');
|
||||
this.activeIndex = index;
|
||||
|
||||
// Reset interval
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause slider interval
|
||||
*/
|
||||
pause() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start slider interval
|
||||
*/
|
||||
start() {
|
||||
clearInterval(this.interval);
|
||||
this.interval = setInterval(
|
||||
this._handleIntervalBound,
|
||||
this.options.duration + this.options.interval
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to next slide
|
||||
*/
|
||||
next() {
|
||||
let newIndex = this.activeIndex + 1;
|
||||
|
||||
// Wrap around indices.
|
||||
if (newIndex >= this.$slides.length) newIndex = 0;
|
||||
else if (newIndex < 0) newIndex = this.$slides.length - 1;
|
||||
|
||||
this.set(newIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to previous slide
|
||||
*/
|
||||
prev() {
|
||||
let newIndex = this.activeIndex - 1;
|
||||
|
||||
// Wrap around indices.
|
||||
if (newIndex >= this.$slides.length) newIndex = 0;
|
||||
else if (newIndex < 0) newIndex = this.$slides.length - 1;
|
||||
|
||||
this.set(newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
M.Slider = Slider;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Slider, 'slider', 'M_Slider');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,402 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
duration: 300,
|
||||
onShow: null,
|
||||
swipeable: false,
|
||||
responsiveThreshold: Infinity // breakpoint for swipeable
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Tabs extends Component {
|
||||
/**
|
||||
* Construct Tabs instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Tabs, el, options);
|
||||
|
||||
this.el.M_Tabs = this;
|
||||
|
||||
/**
|
||||
* Options for the Tabs
|
||||
* @member Tabs#options
|
||||
* @prop {Number} duration
|
||||
* @prop {Function} onShow
|
||||
* @prop {Boolean} swipeable
|
||||
* @prop {Number} responsiveThreshold
|
||||
*/
|
||||
this.options = $.extend({}, Tabs.defaults, options);
|
||||
|
||||
// Setup
|
||||
this.$tabLinks = this.$el.children('li.tab').children('a');
|
||||
this.index = 0;
|
||||
this._setupActiveTabLink();
|
||||
|
||||
// Setup tabs content
|
||||
if (this.options.swipeable) {
|
||||
this._setupSwipeableTabs();
|
||||
} else {
|
||||
this._setupNormalTabs();
|
||||
}
|
||||
|
||||
// Setup tabs indicator after content to ensure accurate widths
|
||||
this._setTabsAndTabWidth();
|
||||
this._createIndicator();
|
||||
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this._indicator.parentNode.removeChild(this._indicator);
|
||||
|
||||
if (this.options.swipeable) {
|
||||
this._teardownSwipeableTabs();
|
||||
} else {
|
||||
this._teardownNormalTabs();
|
||||
}
|
||||
|
||||
this.$el[0].M_Tabs = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleWindowResizeBound = this._handleWindowResize.bind(this);
|
||||
window.addEventListener('resize', this._handleWindowResizeBound);
|
||||
|
||||
this._handleTabClickBound = this._handleTabClick.bind(this);
|
||||
this.el.addEventListener('click', this._handleTabClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
window.removeEventListener('resize', this._handleWindowResizeBound);
|
||||
this.el.removeEventListener('click', this._handleTabClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle window Resize
|
||||
*/
|
||||
_handleWindowResize() {
|
||||
this._setTabsAndTabWidth();
|
||||
|
||||
if (this.tabWidth !== 0 && this.tabsWidth !== 0) {
|
||||
this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
|
||||
this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tab click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleTabClick(e) {
|
||||
let tab = $(e.target).closest('li.tab');
|
||||
let tabLink = $(e.target).closest('a');
|
||||
|
||||
// Handle click on tab link only
|
||||
if (!tabLink.length || !tabLink.parent().hasClass('tab')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tab.hasClass('disabled')) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// Act as regular link if target attribute is specified.
|
||||
if (!!tabLink.attr('target')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the old tab inactive.
|
||||
this.$activeTabLink.removeClass('active');
|
||||
let $oldContent = this.$content;
|
||||
|
||||
// Update the variables with the new link and content
|
||||
this.$activeTabLink = tabLink;
|
||||
this.$content = $(M.escapeHash(tabLink[0].hash));
|
||||
this.$tabLinks = this.$el.children('li.tab').children('a');
|
||||
|
||||
// Make the tab active.
|
||||
this.$activeTabLink.addClass('active');
|
||||
let prevIndex = this.index;
|
||||
this.index = Math.max(this.$tabLinks.index(tabLink), 0);
|
||||
|
||||
// Swap content
|
||||
if (this.options.swipeable) {
|
||||
if (this._tabsCarousel) {
|
||||
this._tabsCarousel.set(this.index, () => {
|
||||
if (typeof this.options.onShow === 'function') {
|
||||
this.options.onShow.call(this, this.$content[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (this.$content.length) {
|
||||
this.$content[0].style.display = 'block';
|
||||
this.$content.addClass('active');
|
||||
if (typeof this.options.onShow === 'function') {
|
||||
this.options.onShow.call(this, this.$content[0]);
|
||||
}
|
||||
|
||||
if ($oldContent.length && !$oldContent.is(this.$content)) {
|
||||
$oldContent[0].style.display = 'none';
|
||||
$oldContent.removeClass('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update widths after content is swapped (scrollbar bugfix)
|
||||
this._setTabsAndTabWidth();
|
||||
|
||||
// Update indicator
|
||||
this._animateIndicator(prevIndex);
|
||||
|
||||
// Prevent the anchor's default click action
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate elements for tab indicator.
|
||||
*/
|
||||
_createIndicator() {
|
||||
let indicator = document.createElement('li');
|
||||
indicator.classList.add('indicator');
|
||||
|
||||
this.el.appendChild(indicator);
|
||||
this._indicator = indicator;
|
||||
|
||||
setTimeout(() => {
|
||||
this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
|
||||
this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup first active tab link.
|
||||
*/
|
||||
_setupActiveTabLink() {
|
||||
// If the location.hash matches one of the links, use that as the active tab.
|
||||
this.$activeTabLink = $(this.$tabLinks.filter('[href="' + location.hash + '"]'));
|
||||
|
||||
// If no match is found, use the first link or any with class 'active' as the initial active tab.
|
||||
if (this.$activeTabLink.length === 0) {
|
||||
this.$activeTabLink = this.$el
|
||||
.children('li.tab')
|
||||
.children('a.active')
|
||||
.first();
|
||||
}
|
||||
if (this.$activeTabLink.length === 0) {
|
||||
this.$activeTabLink = this.$el
|
||||
.children('li.tab')
|
||||
.children('a')
|
||||
.first();
|
||||
}
|
||||
|
||||
this.$tabLinks.removeClass('active');
|
||||
this.$activeTabLink[0].classList.add('active');
|
||||
|
||||
this.index = Math.max(this.$tabLinks.index(this.$activeTabLink), 0);
|
||||
|
||||
if (this.$activeTabLink.length) {
|
||||
this.$content = $(M.escapeHash(this.$activeTabLink[0].hash));
|
||||
this.$content.addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup swipeable tabs
|
||||
*/
|
||||
_setupSwipeableTabs() {
|
||||
// Change swipeable according to responsive threshold
|
||||
if (window.innerWidth > this.options.responsiveThreshold) {
|
||||
this.options.swipeable = false;
|
||||
}
|
||||
|
||||
let $tabsContent = $();
|
||||
this.$tabLinks.each((link) => {
|
||||
let $currContent = $(M.escapeHash(link.hash));
|
||||
$currContent.addClass('carousel-item');
|
||||
$tabsContent = $tabsContent.add($currContent);
|
||||
});
|
||||
|
||||
let $tabsWrapper = $('<div class="tabs-content carousel carousel-slider"></div>');
|
||||
$tabsContent.first().before($tabsWrapper);
|
||||
$tabsWrapper.append($tabsContent);
|
||||
$tabsContent[0].style.display = '';
|
||||
|
||||
// Keep active tab index to set initial carousel slide
|
||||
let activeTabIndex = this.$activeTabLink.closest('.tab').index();
|
||||
|
||||
this._tabsCarousel = M.Carousel.init($tabsWrapper[0], {
|
||||
fullWidth: true,
|
||||
noWrap: true,
|
||||
onCycleTo: (item) => {
|
||||
let prevIndex = this.index;
|
||||
this.index = $(item).index();
|
||||
this.$activeTabLink.removeClass('active');
|
||||
this.$activeTabLink = this.$tabLinks.eq(this.index);
|
||||
this.$activeTabLink.addClass('active');
|
||||
this._animateIndicator(prevIndex);
|
||||
if (typeof this.options.onShow === 'function') {
|
||||
this.options.onShow.call(this, this.$content[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set initial carousel slide to active tab
|
||||
this._tabsCarousel.set(activeTabIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown normal tabs.
|
||||
*/
|
||||
_teardownSwipeableTabs() {
|
||||
let $tabsWrapper = this._tabsCarousel.$el;
|
||||
this._tabsCarousel.destroy();
|
||||
|
||||
// Unwrap
|
||||
$tabsWrapper.after($tabsWrapper.children());
|
||||
$tabsWrapper.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup normal tabs.
|
||||
*/
|
||||
_setupNormalTabs() {
|
||||
// Hide Tabs Content
|
||||
this.$tabLinks.not(this.$activeTabLink).each((link) => {
|
||||
if (!!link.hash) {
|
||||
let $currContent = $(M.escapeHash(link.hash));
|
||||
if ($currContent.length) {
|
||||
$currContent[0].style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown normal tabs.
|
||||
*/
|
||||
_teardownNormalTabs() {
|
||||
// show Tabs Content
|
||||
this.$tabLinks.each((link) => {
|
||||
if (!!link.hash) {
|
||||
let $currContent = $(M.escapeHash(link.hash));
|
||||
if ($currContent.length) {
|
||||
$currContent[0].style.display = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* set tabs and tab width
|
||||
*/
|
||||
_setTabsAndTabWidth() {
|
||||
this.tabsWidth = this.$el.width();
|
||||
this.tabWidth = Math.max(this.tabsWidth, this.el.scrollWidth) / this.$tabLinks.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds right attribute for indicator based on active tab.
|
||||
* @param {cash} el
|
||||
*/
|
||||
_calcRightPos(el) {
|
||||
return Math.ceil(this.tabsWidth - el.position().left - el[0].getBoundingClientRect().width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds left attribute for indicator based on active tab.
|
||||
* @param {cash} el
|
||||
*/
|
||||
_calcLeftPos(el) {
|
||||
return Math.floor(el.position().left);
|
||||
}
|
||||
|
||||
updateTabIndicator() {
|
||||
this._setTabsAndTabWidth();
|
||||
this._animateIndicator(this.index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates Indicator to active tab.
|
||||
* @param {Number} prevIndex
|
||||
*/
|
||||
_animateIndicator(prevIndex) {
|
||||
let leftDelay = 0,
|
||||
rightDelay = 0;
|
||||
|
||||
if (this.index - prevIndex >= 0) {
|
||||
leftDelay = 90;
|
||||
} else {
|
||||
rightDelay = 90;
|
||||
}
|
||||
|
||||
// Animate
|
||||
let animOptions = {
|
||||
targets: this._indicator,
|
||||
left: {
|
||||
value: this._calcLeftPos(this.$activeTabLink),
|
||||
delay: leftDelay
|
||||
},
|
||||
right: {
|
||||
value: this._calcRightPos(this.$activeTabLink),
|
||||
delay: rightDelay
|
||||
},
|
||||
duration: this.options.duration,
|
||||
easing: 'easeOutQuad'
|
||||
};
|
||||
anim.remove(this._indicator);
|
||||
anim(animOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select tab.
|
||||
* @param {String} tabId
|
||||
*/
|
||||
select(tabId) {
|
||||
let tab = this.$tabLinks.filter('[href="#' + tabId + '"]');
|
||||
if (tab.length) {
|
||||
tab.trigger('click');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M.Tabs = Tabs;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,315 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
onOpen: undefined,
|
||||
onClose: undefined
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class TapTarget extends Component {
|
||||
/**
|
||||
* Construct TapTarget instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(TapTarget, el, options);
|
||||
|
||||
this.el.M_TapTarget = this;
|
||||
|
||||
/**
|
||||
* Options for the select
|
||||
* @member TapTarget#options
|
||||
* @prop {Function} onOpen - Callback function called when feature discovery is opened
|
||||
* @prop {Function} onClose - Callback function called when feature discovery is closed
|
||||
*/
|
||||
this.options = $.extend({}, TapTarget.defaults, options);
|
||||
|
||||
this.isOpen = false;
|
||||
|
||||
// setup
|
||||
this.$origin = $('#' + this.$el.attr('data-target'));
|
||||
this._setup();
|
||||
|
||||
this._calculatePositioning();
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_TapTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.el.TapTarget = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
|
||||
this._handleTargetClickBound = this._handleTargetClick.bind(this);
|
||||
this._handleOriginClickBound = this._handleOriginClick.bind(this);
|
||||
|
||||
this.el.addEventListener('click', this._handleTargetClickBound);
|
||||
this.originEl.addEventListener('click', this._handleOriginClickBound);
|
||||
|
||||
// Resize
|
||||
let throttledResize = M.throttle(this._handleResize, 200);
|
||||
this._handleThrottledResizeBound = throttledResize.bind(this);
|
||||
|
||||
window.addEventListener('resize', this._handleThrottledResizeBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleTargetClickBound);
|
||||
this.originEl.removeEventListener('click', this._handleOriginClickBound);
|
||||
window.removeEventListener('resize', this._handleThrottledResizeBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Target Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleTargetClick(e) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Origin Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleOriginClick(e) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Resize
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleResize(e) {
|
||||
this._calculatePositioning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Resize
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDocumentClick(e) {
|
||||
if (!$(e.target).closest('.tap-target-wrapper').length) {
|
||||
this.close();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Tap Target
|
||||
*/
|
||||
_setup() {
|
||||
// Creating tap target
|
||||
this.wrapper = this.$el.parent()[0];
|
||||
this.waveEl = $(this.wrapper).find('.tap-target-wave')[0];
|
||||
this.originEl = $(this.wrapper).find('.tap-target-origin')[0];
|
||||
this.contentEl = this.$el.find('.tap-target-content')[0];
|
||||
|
||||
// Creating wrapper
|
||||
if (!$(this.wrapper).hasClass('.tap-target-wrapper')) {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('tap-target-wrapper');
|
||||
this.$el.before($(this.wrapper));
|
||||
this.wrapper.append(this.el);
|
||||
}
|
||||
|
||||
// Creating content
|
||||
if (!this.contentEl) {
|
||||
this.contentEl = document.createElement('div');
|
||||
this.contentEl.classList.add('tap-target-content');
|
||||
this.$el.append(this.contentEl);
|
||||
}
|
||||
|
||||
// Creating foreground wave
|
||||
if (!this.waveEl) {
|
||||
this.waveEl = document.createElement('div');
|
||||
this.waveEl.classList.add('tap-target-wave');
|
||||
|
||||
// Creating origin
|
||||
if (!this.originEl) {
|
||||
this.originEl = this.$origin.clone(true, true);
|
||||
this.originEl.addClass('tap-target-origin');
|
||||
this.originEl.removeAttr('id');
|
||||
this.originEl.removeAttr('style');
|
||||
this.originEl = this.originEl[0];
|
||||
this.waveEl.append(this.originEl);
|
||||
}
|
||||
|
||||
this.wrapper.append(this.waveEl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate positioning
|
||||
*/
|
||||
_calculatePositioning() {
|
||||
// Element or parent is fixed position?
|
||||
let isFixed = this.$origin.css('position') === 'fixed';
|
||||
if (!isFixed) {
|
||||
let parents = this.$origin.parents();
|
||||
for (let i = 0; i < parents.length; i++) {
|
||||
isFixed = $(parents[i]).css('position') == 'fixed';
|
||||
if (isFixed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculating origin
|
||||
let originWidth = this.$origin.outerWidth();
|
||||
let originHeight = this.$origin.outerHeight();
|
||||
let originTop = isFixed
|
||||
? this.$origin.offset().top - M.getDocumentScrollTop()
|
||||
: this.$origin.offset().top;
|
||||
let originLeft = isFixed
|
||||
? this.$origin.offset().left - M.getDocumentScrollLeft()
|
||||
: this.$origin.offset().left;
|
||||
|
||||
// Calculating screen
|
||||
let windowWidth = window.innerWidth;
|
||||
let windowHeight = window.innerHeight;
|
||||
let scrollBarWidth = windowWidth - document.documentElement.clientWidth;
|
||||
let centerX = windowWidth / 2;
|
||||
let centerY = windowHeight / 2;
|
||||
let isLeft = originLeft <= centerX;
|
||||
let isRight = originLeft > centerX;
|
||||
let isTop = originTop <= centerY;
|
||||
let isBottom = originTop > centerY;
|
||||
let isCenterX = originLeft >= windowWidth * 0.25 && originLeft <= windowWidth * 0.75;
|
||||
|
||||
// Calculating tap target
|
||||
let tapTargetWidth = this.$el.outerWidth();
|
||||
let tapTargetHeight = this.$el.outerHeight();
|
||||
let tapTargetTop = originTop + originHeight / 2 - tapTargetHeight / 2;
|
||||
let tapTargetLeft = originLeft + originWidth / 2 - tapTargetWidth / 2;
|
||||
let tapTargetPosition = isFixed ? 'fixed' : 'absolute';
|
||||
|
||||
// Calculating content
|
||||
let tapTargetTextWidth = isCenterX ? tapTargetWidth : tapTargetWidth / 2 + originWidth;
|
||||
let tapTargetTextHeight = tapTargetHeight / 2;
|
||||
let tapTargetTextTop = isTop ? tapTargetHeight / 2 : 0;
|
||||
let tapTargetTextBottom = 0;
|
||||
let tapTargetTextLeft = isLeft && !isCenterX ? tapTargetWidth / 2 - originWidth : 0;
|
||||
let tapTargetTextRight = 0;
|
||||
let tapTargetTextPadding = originWidth;
|
||||
let tapTargetTextAlign = isBottom ? 'bottom' : 'top';
|
||||
|
||||
// Calculating wave
|
||||
let tapTargetWaveWidth = originWidth > originHeight ? originWidth * 2 : originWidth * 2;
|
||||
let tapTargetWaveHeight = tapTargetWaveWidth;
|
||||
let tapTargetWaveTop = tapTargetHeight / 2 - tapTargetWaveHeight / 2;
|
||||
let tapTargetWaveLeft = tapTargetWidth / 2 - tapTargetWaveWidth / 2;
|
||||
|
||||
// Setting tap target
|
||||
let tapTargetWrapperCssObj = {};
|
||||
tapTargetWrapperCssObj.top = isTop ? tapTargetTop + 'px' : '';
|
||||
tapTargetWrapperCssObj.right = isRight
|
||||
? windowWidth - tapTargetLeft - tapTargetWidth - scrollBarWidth + 'px'
|
||||
: '';
|
||||
tapTargetWrapperCssObj.bottom = isBottom
|
||||
? windowHeight - tapTargetTop - tapTargetHeight + 'px'
|
||||
: '';
|
||||
tapTargetWrapperCssObj.left = isLeft ? tapTargetLeft + 'px' : '';
|
||||
tapTargetWrapperCssObj.position = tapTargetPosition;
|
||||
$(this.wrapper).css(tapTargetWrapperCssObj);
|
||||
|
||||
// Setting content
|
||||
$(this.contentEl).css({
|
||||
width: tapTargetTextWidth + 'px',
|
||||
height: tapTargetTextHeight + 'px',
|
||||
top: tapTargetTextTop + 'px',
|
||||
right: tapTargetTextRight + 'px',
|
||||
bottom: tapTargetTextBottom + 'px',
|
||||
left: tapTargetTextLeft + 'px',
|
||||
padding: tapTargetTextPadding + 'px',
|
||||
verticalAlign: tapTargetTextAlign
|
||||
});
|
||||
|
||||
// Setting wave
|
||||
$(this.waveEl).css({
|
||||
top: tapTargetWaveTop + 'px',
|
||||
left: tapTargetWaveLeft + 'px',
|
||||
width: tapTargetWaveWidth + 'px',
|
||||
height: tapTargetWaveHeight + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open TapTarget
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// onOpen callback
|
||||
if (typeof this.options.onOpen === 'function') {
|
||||
this.options.onOpen.call(this, this.$origin[0]);
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
this.wrapper.classList.add('open');
|
||||
|
||||
document.body.addEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.addEventListener('touchend', this._handleDocumentClickBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Tap Target
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// onClose callback
|
||||
if (typeof this.options.onClose === 'function') {
|
||||
this.options.onClose.call(this, this.$origin[0]);
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
this.wrapper.classList.remove('open');
|
||||
|
||||
document.body.removeEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.removeEventListener('touchend', this._handleDocumentClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
M.TapTarget = TapTarget;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(TapTarget, 'tapTarget', 'M_TapTarget');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,648 @@
|
|||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
dialRadius: 135,
|
||||
outerRadius: 105,
|
||||
innerRadius: 70,
|
||||
tickRadius: 20,
|
||||
duration: 350,
|
||||
container: null,
|
||||
defaultTime: 'now', // default time, 'now' or '13:14' e.g.
|
||||
fromNow: 0, // Millisecond offset from the defaultTime
|
||||
showClearBtn: false,
|
||||
|
||||
// internationalization
|
||||
i18n: {
|
||||
cancel: 'Cancel',
|
||||
clear: 'Clear',
|
||||
done: 'Ok'
|
||||
},
|
||||
|
||||
autoClose: false, // auto close when minute is selected
|
||||
twelveHour: true, // change to 12 hour AM/PM clock from 24 hour
|
||||
vibrate: true, // vibrate the device when dragging clock hand
|
||||
|
||||
// Callbacks
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null,
|
||||
onSelect: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Timepicker extends Component {
|
||||
constructor(el, options) {
|
||||
super(Timepicker, el, options);
|
||||
|
||||
this.el.M_Timepicker = this;
|
||||
|
||||
this.options = $.extend({}, Timepicker.defaults, options);
|
||||
|
||||
this.id = M.guid();
|
||||
this._insertHTMLIntoDOM();
|
||||
this._setupModal();
|
||||
this._setupVariables();
|
||||
this._setupEventHandlers();
|
||||
|
||||
this._clockSetup();
|
||||
this._pickerSetup();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
static _addLeadingZero(num) {
|
||||
return (num < 10 ? '0' : '') + num;
|
||||
}
|
||||
|
||||
static _createSVGEl(name) {
|
||||
let svgNS = 'http://www.w3.org/2000/svg';
|
||||
return document.createElementNS(svgNS, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Point
|
||||
* @property {number} x The X Coordinate
|
||||
* @property {number} y The Y Coordinate
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get x position of mouse or touch event
|
||||
* @param {Event} e
|
||||
* @return {Point} x and y location
|
||||
*/
|
||||
static _Pos(e) {
|
||||
if (e.targetTouches && e.targetTouches.length >= 1) {
|
||||
return { x: e.targetTouches[0].clientX, y: e.targetTouches[0].clientY };
|
||||
}
|
||||
// mouse event
|
||||
return { x: e.clientX, y: e.clientY };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Timepicker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._removeEventHandlers();
|
||||
this.modal.destroy();
|
||||
$(this.modalEl).remove();
|
||||
this.el.M_Timepicker = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
|
||||
this._handleInputClickBound = this._handleInputClick.bind(this);
|
||||
this._handleClockClickStartBound = this._handleClockClickStart.bind(this);
|
||||
this._handleDocumentClickMoveBound = this._handleDocumentClickMove.bind(this);
|
||||
this._handleDocumentClickEndBound = this._handleDocumentClickEnd.bind(this);
|
||||
|
||||
this.el.addEventListener('click', this._handleInputClickBound);
|
||||
this.el.addEventListener('keydown', this._handleInputKeydownBound);
|
||||
this.plate.addEventListener('mousedown', this._handleClockClickStartBound);
|
||||
this.plate.addEventListener('touchstart', this._handleClockClickStartBound);
|
||||
|
||||
$(this.spanHours).on('click', this.showView.bind(this, 'hours'));
|
||||
$(this.spanMinutes).on('click', this.showView.bind(this, 'minutes'));
|
||||
}
|
||||
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('click', this._handleInputClickBound);
|
||||
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
|
||||
}
|
||||
|
||||
_handleInputClick() {
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleInputKeydown(e) {
|
||||
if (e.which === M.keys.ENTER) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
_handleClockClickStart(e) {
|
||||
e.preventDefault();
|
||||
let clockPlateBR = this.plate.getBoundingClientRect();
|
||||
let offset = { x: clockPlateBR.left, y: clockPlateBR.top };
|
||||
|
||||
this.x0 = offset.x + this.options.dialRadius;
|
||||
this.y0 = offset.y + this.options.dialRadius;
|
||||
this.moved = false;
|
||||
let clickPos = Timepicker._Pos(e);
|
||||
this.dx = clickPos.x - this.x0;
|
||||
this.dy = clickPos.y - this.y0;
|
||||
|
||||
// Set clock hands
|
||||
this.setHand(this.dx, this.dy, false);
|
||||
|
||||
// Mousemove on document
|
||||
document.addEventListener('mousemove', this._handleDocumentClickMoveBound);
|
||||
document.addEventListener('touchmove', this._handleDocumentClickMoveBound);
|
||||
|
||||
// Mouseup on document
|
||||
document.addEventListener('mouseup', this._handleDocumentClickEndBound);
|
||||
document.addEventListener('touchend', this._handleDocumentClickEndBound);
|
||||
}
|
||||
|
||||
_handleDocumentClickMove(e) {
|
||||
e.preventDefault();
|
||||
let clickPos = Timepicker._Pos(e);
|
||||
let x = clickPos.x - this.x0;
|
||||
let y = clickPos.y - this.y0;
|
||||
this.moved = true;
|
||||
this.setHand(x, y, false, true);
|
||||
}
|
||||
|
||||
_handleDocumentClickEnd(e) {
|
||||
e.preventDefault();
|
||||
document.removeEventListener('mouseup', this._handleDocumentClickEndBound);
|
||||
document.removeEventListener('touchend', this._handleDocumentClickEndBound);
|
||||
let clickPos = Timepicker._Pos(e);
|
||||
let x = clickPos.x - this.x0;
|
||||
let y = clickPos.y - this.y0;
|
||||
if (this.moved && x === this.dx && y === this.dy) {
|
||||
this.setHand(x, y);
|
||||
}
|
||||
|
||||
if (this.currentView === 'hours') {
|
||||
this.showView('minutes', this.options.duration / 2);
|
||||
} else if (this.options.autoClose) {
|
||||
$(this.minutesView).addClass('timepicker-dial-out');
|
||||
setTimeout(() => {
|
||||
this.done();
|
||||
}, this.options.duration / 2);
|
||||
}
|
||||
|
||||
if (typeof this.options.onSelect === 'function') {
|
||||
this.options.onSelect.call(this, this.hours, this.minutes);
|
||||
}
|
||||
|
||||
// Unbind mousemove event
|
||||
document.removeEventListener('mousemove', this._handleDocumentClickMoveBound);
|
||||
document.removeEventListener('touchmove', this._handleDocumentClickMoveBound);
|
||||
}
|
||||
|
||||
_insertHTMLIntoDOM() {
|
||||
this.$modalEl = $(Timepicker._template);
|
||||
this.modalEl = this.$modalEl[0];
|
||||
this.modalEl.id = 'modal-' + this.id;
|
||||
|
||||
// Append popover to input by default
|
||||
const optEl = this.options.container;
|
||||
let containerEl = (optEl instanceof HTMLElement?optEl:document.querySelector(optEl));
|
||||
if (this.options.container && !!containerEl) {
|
||||
this.$modalEl.appendTo(containerEl);
|
||||
} else {
|
||||
this.$modalEl.insertBefore(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
_setupModal() {
|
||||
this.modal = M.Modal.init(this.modalEl, {
|
||||
onOpenStart: this.options.onOpenStart,
|
||||
onOpenEnd: this.options.onOpenEnd,
|
||||
onCloseStart: this.options.onCloseStart,
|
||||
onCloseEnd: () => {
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this);
|
||||
}
|
||||
this.isOpen = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_setupVariables() {
|
||||
this.currentView = 'hours';
|
||||
this.vibrate = navigator.vibrate
|
||||
? 'vibrate'
|
||||
: navigator.webkitVibrate
|
||||
? 'webkitVibrate'
|
||||
: null;
|
||||
|
||||
this._canvas = this.modalEl.querySelector('.timepicker-canvas');
|
||||
this.plate = this.modalEl.querySelector('.timepicker-plate');
|
||||
|
||||
this.hoursView = this.modalEl.querySelector('.timepicker-hours');
|
||||
this.minutesView = this.modalEl.querySelector('.timepicker-minutes');
|
||||
this.spanHours = this.modalEl.querySelector('.timepicker-span-hours');
|
||||
this.spanMinutes = this.modalEl.querySelector('.timepicker-span-minutes');
|
||||
this.spanAmPm = this.modalEl.querySelector('.timepicker-span-am-pm');
|
||||
this.footer = this.modalEl.querySelector('.timepicker-footer');
|
||||
this.amOrPm = 'PM';
|
||||
}
|
||||
|
||||
_pickerSetup() {
|
||||
let $clearBtn = $(
|
||||
`<button class="btn-flat timepicker-clear waves-effect" style="visibility: hidden;" type="button" tabindex="${
|
||||
this.options.twelveHour ? '3' : '1'
|
||||
}">${this.options.i18n.clear}</button>`
|
||||
)
|
||||
.appendTo(this.footer)
|
||||
.on('click', this.clear.bind(this));
|
||||
if (this.options.showClearBtn) {
|
||||
$clearBtn.css({ visibility: '' });
|
||||
}
|
||||
|
||||
let confirmationBtnsContainer = $('<div class="confirmation-btns"></div>');
|
||||
$(
|
||||
'<button class="btn-flat timepicker-close waves-effect" type="button" tabindex="' +
|
||||
(this.options.twelveHour ? '3' : '1') +
|
||||
'">' +
|
||||
this.options.i18n.cancel +
|
||||
'</button>'
|
||||
)
|
||||
.appendTo(confirmationBtnsContainer)
|
||||
.on('click', this.close.bind(this));
|
||||
$(
|
||||
'<button class="btn-flat timepicker-close waves-effect" type="button" tabindex="' +
|
||||
(this.options.twelveHour ? '3' : '1') +
|
||||
'">' +
|
||||
this.options.i18n.done +
|
||||
'</button>'
|
||||
)
|
||||
.appendTo(confirmationBtnsContainer)
|
||||
.on('click', this.done.bind(this));
|
||||
confirmationBtnsContainer.appendTo(this.footer);
|
||||
}
|
||||
|
||||
_clockSetup() {
|
||||
if (this.options.twelveHour) {
|
||||
this.$amBtn = $('<div class="am-btn">AM</div>');
|
||||
this.$pmBtn = $('<div class="pm-btn">PM</div>');
|
||||
this.$amBtn.on('click', this._handleAmPmClick.bind(this)).appendTo(this.spanAmPm);
|
||||
this.$pmBtn.on('click', this._handleAmPmClick.bind(this)).appendTo(this.spanAmPm);
|
||||
}
|
||||
|
||||
this._buildHoursView();
|
||||
this._buildMinutesView();
|
||||
this._buildSVGClock();
|
||||
}
|
||||
|
||||
_buildSVGClock() {
|
||||
// Draw clock hands and others
|
||||
let dialRadius = this.options.dialRadius;
|
||||
let tickRadius = this.options.tickRadius;
|
||||
let diameter = dialRadius * 2;
|
||||
|
||||
let svg = Timepicker._createSVGEl('svg');
|
||||
svg.setAttribute('class', 'timepicker-svg');
|
||||
svg.setAttribute('width', diameter);
|
||||
svg.setAttribute('height', diameter);
|
||||
let g = Timepicker._createSVGEl('g');
|
||||
g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
|
||||
let bearing = Timepicker._createSVGEl('circle');
|
||||
bearing.setAttribute('class', 'timepicker-canvas-bearing');
|
||||
bearing.setAttribute('cx', 0);
|
||||
bearing.setAttribute('cy', 0);
|
||||
bearing.setAttribute('r', 4);
|
||||
let hand = Timepicker._createSVGEl('line');
|
||||
hand.setAttribute('x1', 0);
|
||||
hand.setAttribute('y1', 0);
|
||||
let bg = Timepicker._createSVGEl('circle');
|
||||
bg.setAttribute('class', 'timepicker-canvas-bg');
|
||||
bg.setAttribute('r', tickRadius);
|
||||
g.appendChild(hand);
|
||||
g.appendChild(bg);
|
||||
g.appendChild(bearing);
|
||||
svg.appendChild(g);
|
||||
this._canvas.appendChild(svg);
|
||||
|
||||
this.hand = hand;
|
||||
this.bg = bg;
|
||||
this.bearing = bearing;
|
||||
this.g = g;
|
||||
}
|
||||
|
||||
_buildHoursView() {
|
||||
let $tick = $('<div class="timepicker-tick"></div>');
|
||||
// Hours view
|
||||
if (this.options.twelveHour) {
|
||||
for (let i = 1; i < 13; i += 1) {
|
||||
let tick = $tick.clone();
|
||||
let radian = i / 6 * Math.PI;
|
||||
let radius = this.options.outerRadius;
|
||||
tick.css({
|
||||
left:
|
||||
this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px',
|
||||
top:
|
||||
this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px'
|
||||
});
|
||||
tick.html(i === 0 ? '00' : i);
|
||||
this.hoursView.appendChild(tick[0]);
|
||||
// tick.on(mousedownEvent, mousedown);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
let tick = $tick.clone();
|
||||
let radian = i / 6 * Math.PI;
|
||||
let inner = i > 0 && i < 13;
|
||||
let radius = inner ? this.options.innerRadius : this.options.outerRadius;
|
||||
tick.css({
|
||||
left:
|
||||
this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px',
|
||||
top:
|
||||
this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px'
|
||||
});
|
||||
tick.html(i === 0 ? '00' : i);
|
||||
this.hoursView.appendChild(tick[0]);
|
||||
// tick.on(mousedownEvent, mousedown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_buildMinutesView() {
|
||||
let $tick = $('<div class="timepicker-tick"></div>');
|
||||
// Minutes view
|
||||
for (let i = 0; i < 60; i += 5) {
|
||||
let tick = $tick.clone();
|
||||
let radian = i / 30 * Math.PI;
|
||||
tick.css({
|
||||
left:
|
||||
this.options.dialRadius +
|
||||
Math.sin(radian) * this.options.outerRadius -
|
||||
this.options.tickRadius +
|
||||
'px',
|
||||
top:
|
||||
this.options.dialRadius -
|
||||
Math.cos(radian) * this.options.outerRadius -
|
||||
this.options.tickRadius +
|
||||
'px'
|
||||
});
|
||||
tick.html(Timepicker._addLeadingZero(i));
|
||||
this.minutesView.appendChild(tick[0]);
|
||||
}
|
||||
}
|
||||
|
||||
_handleAmPmClick(e) {
|
||||
let $btnClicked = $(e.target);
|
||||
this.amOrPm = $btnClicked.hasClass('am-btn') ? 'AM' : 'PM';
|
||||
this._updateAmPmView();
|
||||
}
|
||||
|
||||
_updateAmPmView() {
|
||||
if (this.options.twelveHour) {
|
||||
this.$amBtn.toggleClass('text-primary', this.amOrPm === 'AM');
|
||||
this.$pmBtn.toggleClass('text-primary', this.amOrPm === 'PM');
|
||||
}
|
||||
}
|
||||
|
||||
_updateTimeFromInput() {
|
||||
// Get the time
|
||||
let value = ((this.el.value || this.options.defaultTime || '') + '').split(':');
|
||||
if (this.options.twelveHour && !(typeof value[1] === 'undefined')) {
|
||||
if (value[1].toUpperCase().indexOf('AM') > 0) {
|
||||
this.amOrPm = 'AM';
|
||||
} else {
|
||||
this.amOrPm = 'PM';
|
||||
}
|
||||
value[1] = value[1].replace('AM', '').replace('PM', '');
|
||||
}
|
||||
if (value[0] === 'now') {
|
||||
let now = new Date(+new Date() + this.options.fromNow);
|
||||
value = [now.getHours(), now.getMinutes()];
|
||||
if (this.options.twelveHour) {
|
||||
this.amOrPm = value[0] >= 12 && value[0] < 24 ? 'PM' : 'AM';
|
||||
}
|
||||
}
|
||||
this.hours = +value[0] || 0;
|
||||
this.minutes = +value[1] || 0;
|
||||
this.spanHours.innerHTML = this.hours;
|
||||
this.spanMinutes.innerHTML = Timepicker._addLeadingZero(this.minutes);
|
||||
|
||||
this._updateAmPmView();
|
||||
}
|
||||
|
||||
showView(view, delay) {
|
||||
if (view === 'minutes' && $(this.hoursView).css('visibility') === 'visible') {
|
||||
// raiseCallback(this.options.beforeHourSelect);
|
||||
}
|
||||
let isHours = view === 'hours',
|
||||
nextView = isHours ? this.hoursView : this.minutesView,
|
||||
hideView = isHours ? this.minutesView : this.hoursView;
|
||||
this.currentView = view;
|
||||
|
||||
$(this.spanHours).toggleClass('text-primary', isHours);
|
||||
$(this.spanMinutes).toggleClass('text-primary', !isHours);
|
||||
|
||||
// Transition view
|
||||
hideView.classList.add('timepicker-dial-out');
|
||||
$(nextView)
|
||||
.css('visibility', 'visible')
|
||||
.removeClass('timepicker-dial-out');
|
||||
|
||||
// Reset clock hand
|
||||
this.resetClock(delay);
|
||||
|
||||
// After transitions ended
|
||||
clearTimeout(this.toggleViewTimer);
|
||||
this.toggleViewTimer = setTimeout(() => {
|
||||
$(hideView).css('visibility', 'hidden');
|
||||
}, this.options.duration);
|
||||
}
|
||||
|
||||
resetClock(delay) {
|
||||
let view = this.currentView,
|
||||
value = this[view],
|
||||
isHours = view === 'hours',
|
||||
unit = Math.PI / (isHours ? 6 : 30),
|
||||
radian = value * unit,
|
||||
radius =
|
||||
isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius,
|
||||
x = Math.sin(radian) * radius,
|
||||
y = -Math.cos(radian) * radius,
|
||||
self = this;
|
||||
|
||||
if (delay) {
|
||||
$(this.canvas).addClass('timepicker-canvas-out');
|
||||
setTimeout(() => {
|
||||
$(self.canvas).removeClass('timepicker-canvas-out');
|
||||
self.setHand(x, y);
|
||||
}, delay);
|
||||
} else {
|
||||
this.setHand(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
setHand(x, y, roundBy5) {
|
||||
let radian = Math.atan2(x, -y),
|
||||
isHours = this.currentView === 'hours',
|
||||
unit = Math.PI / (isHours || roundBy5 ? 6 : 30),
|
||||
z = Math.sqrt(x * x + y * y),
|
||||
inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2,
|
||||
radius = inner ? this.options.innerRadius : this.options.outerRadius;
|
||||
|
||||
if (this.options.twelveHour) {
|
||||
radius = this.options.outerRadius;
|
||||
}
|
||||
|
||||
// Radian should in range [0, 2PI]
|
||||
if (radian < 0) {
|
||||
radian = Math.PI * 2 + radian;
|
||||
}
|
||||
|
||||
// Get the round value
|
||||
let value = Math.round(radian / unit);
|
||||
|
||||
// Get the round radian
|
||||
radian = value * unit;
|
||||
|
||||
// Correct the hours or minutes
|
||||
if (this.options.twelveHour) {
|
||||
if (isHours) {
|
||||
if (value === 0) value = 12;
|
||||
} else {
|
||||
if (roundBy5) value *= 5;
|
||||
if (value === 60) value = 0;
|
||||
}
|
||||
} else {
|
||||
if (isHours) {
|
||||
if (value === 12) {
|
||||
value = 0;
|
||||
}
|
||||
value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
|
||||
} else {
|
||||
if (roundBy5) {
|
||||
value *= 5;
|
||||
}
|
||||
if (value === 60) {
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Once hours or minutes changed, vibrate the device
|
||||
if (this[this.currentView] !== value) {
|
||||
if (this.vibrate && this.options.vibrate) {
|
||||
// Do not vibrate too frequently
|
||||
if (!this.vibrateTimer) {
|
||||
navigator[this.vibrate](10);
|
||||
this.vibrateTimer = setTimeout(() => {
|
||||
this.vibrateTimer = null;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this[this.currentView] = value;
|
||||
if (isHours) {
|
||||
this['spanHours'].innerHTML = value;
|
||||
} else {
|
||||
this['spanMinutes'].innerHTML = Timepicker._addLeadingZero(value);
|
||||
}
|
||||
|
||||
// Set clock hand and others' position
|
||||
let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
|
||||
cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
|
||||
cx2 = Math.sin(radian) * radius,
|
||||
cy2 = -Math.cos(radian) * radius;
|
||||
this.hand.setAttribute('x2', cx1);
|
||||
this.hand.setAttribute('y2', cy1);
|
||||
this.bg.setAttribute('cx', cx2);
|
||||
this.bg.setAttribute('cy', cy2);
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
this._updateTimeFromInput();
|
||||
this.showView('hours');
|
||||
|
||||
this.modal.open();
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish timepicker selection.
|
||||
*/
|
||||
done(e, clearValue) {
|
||||
// Set input value
|
||||
let last = this.el.value;
|
||||
let value = clearValue
|
||||
? ''
|
||||
: Timepicker._addLeadingZero(this.hours) + ':' + Timepicker._addLeadingZero(this.minutes);
|
||||
this.time = value;
|
||||
if (!clearValue && this.options.twelveHour) {
|
||||
value = `${value} ${this.amOrPm}`;
|
||||
}
|
||||
this.el.value = value;
|
||||
|
||||
// Trigger change event
|
||||
if (value !== last) {
|
||||
this.$el.trigger('change');
|
||||
}
|
||||
|
||||
this.close();
|
||||
this.el.focus();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.done(null, true);
|
||||
}
|
||||
}
|
||||
|
||||
Timepicker._template = [
|
||||
'<div class= "modal timepicker-modal">',
|
||||
'<div class="modal-content timepicker-container">',
|
||||
'<div class="timepicker-digital-display">',
|
||||
'<div class="timepicker-text-container">',
|
||||
'<div class="timepicker-display-column">',
|
||||
'<span class="timepicker-span-hours text-primary"></span>',
|
||||
':',
|
||||
'<span class="timepicker-span-minutes"></span>',
|
||||
'</div>',
|
||||
'<div class="timepicker-display-column timepicker-display-am-pm">',
|
||||
'<div class="timepicker-span-am-pm"></div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="timepicker-analog-display">',
|
||||
'<div class="timepicker-plate">',
|
||||
'<div class="timepicker-canvas"></div>',
|
||||
'<div class="timepicker-dial timepicker-hours"></div>',
|
||||
'<div class="timepicker-dial timepicker-minutes timepicker-dial-out"></div>',
|
||||
'</div>',
|
||||
'<div class="timepicker-footer"></div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
M.Timepicker = Timepicker;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Timepicker, 'timepicker', 'M_Timepicker');
|
||||
}
|
||||
})(cash);
|
|
@ -0,0 +1,322 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
html: '',
|
||||
unsafeHTML: '',
|
||||
text: '',
|
||||
displayLength: 4000,
|
||||
inDuration: 300,
|
||||
outDuration: 375,
|
||||
classes: '',
|
||||
completeCallback: null,
|
||||
activationPercent: 0.8
|
||||
};
|
||||
|
||||
class Toast {
|
||||
constructor(options) {
|
||||
/**
|
||||
* Options for the toast
|
||||
* @member Toast#options
|
||||
*/
|
||||
this.options = $.extend({}, Toast.defaults, options);
|
||||
this.htmlMessage = this.options.html;
|
||||
// Warn when using html
|
||||
if (!!this.options.html)
|
||||
console.warn(
|
||||
'The html option is deprecated and will be removed in the future. See https://github.com/materializecss/materialize/pull/49'
|
||||
);
|
||||
// If the new unsafeHTML is used, prefer that
|
||||
if (!!this.options.unsafeHTML) {
|
||||
this.htmlMessage = this.options.unsafeHTML;
|
||||
}
|
||||
this.message = this.options.text;
|
||||
|
||||
/**
|
||||
* Describes current pan state toast
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.panning = false;
|
||||
|
||||
/**
|
||||
* Time remaining until toast is removed
|
||||
*/
|
||||
this.timeRemaining = this.options.displayLength;
|
||||
|
||||
if (Toast._toasts.length === 0) {
|
||||
Toast._createContainer();
|
||||
}
|
||||
|
||||
// Create new toast
|
||||
Toast._toasts.push(this);
|
||||
let toastElement = this._createToast();
|
||||
toastElement.M_Toast = this;
|
||||
this.el = toastElement;
|
||||
this.$el = $(toastElement);
|
||||
this._animateIn();
|
||||
this._setTimer();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Toast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append toast container and add event handlers
|
||||
*/
|
||||
static _createContainer() {
|
||||
let container = document.createElement('div');
|
||||
container.setAttribute('id', 'toast-container');
|
||||
|
||||
// Add event handler
|
||||
container.addEventListener('touchstart', Toast._onDragStart);
|
||||
container.addEventListener('touchmove', Toast._onDragMove);
|
||||
container.addEventListener('touchend', Toast._onDragEnd);
|
||||
|
||||
container.addEventListener('mousedown', Toast._onDragStart);
|
||||
document.addEventListener('mousemove', Toast._onDragMove);
|
||||
document.addEventListener('mouseup', Toast._onDragEnd);
|
||||
|
||||
document.body.appendChild(container);
|
||||
Toast._container = container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove toast container and event handlers
|
||||
*/
|
||||
static _removeContainer() {
|
||||
// Add event handler
|
||||
document.removeEventListener('mousemove', Toast._onDragMove);
|
||||
document.removeEventListener('mouseup', Toast._onDragEnd);
|
||||
|
||||
$(Toast._container).remove();
|
||||
Toast._container = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin drag handler
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _onDragStart(e) {
|
||||
if (e.target && $(e.target).closest('.toast').length) {
|
||||
let $toast = $(e.target).closest('.toast');
|
||||
let toast = $toast[0].M_Toast;
|
||||
toast.panning = true;
|
||||
Toast._draggedToast = toast;
|
||||
toast.el.classList.add('panning');
|
||||
toast.el.style.transition = '';
|
||||
toast.startingXPos = Toast._xPos(e);
|
||||
toast.time = Date.now();
|
||||
toast.xPos = Toast._xPos(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag move handler
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _onDragMove(e) {
|
||||
if (!!Toast._draggedToast) {
|
||||
e.preventDefault();
|
||||
let toast = Toast._draggedToast;
|
||||
toast.deltaX = Math.abs(toast.xPos - Toast._xPos(e));
|
||||
toast.xPos = Toast._xPos(e);
|
||||
toast.velocityX = toast.deltaX / (Date.now() - toast.time);
|
||||
toast.time = Date.now();
|
||||
|
||||
let totalDeltaX = toast.xPos - toast.startingXPos;
|
||||
let activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
|
||||
toast.el.style.transform = `translateX(${totalDeltaX}px)`;
|
||||
toast.el.style.opacity = 1 - Math.abs(totalDeltaX / activationDistance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End drag handler
|
||||
*/
|
||||
static _onDragEnd() {
|
||||
if (!!Toast._draggedToast) {
|
||||
let toast = Toast._draggedToast;
|
||||
toast.panning = false;
|
||||
toast.el.classList.remove('panning');
|
||||
|
||||
let totalDeltaX = toast.xPos - toast.startingXPos;
|
||||
let activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
|
||||
let shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
|
||||
|
||||
// Remove toast
|
||||
if (shouldBeDismissed) {
|
||||
toast.wasSwiped = true;
|
||||
toast.dismiss();
|
||||
|
||||
// Animate toast back to original position
|
||||
} else {
|
||||
toast.el.style.transition = 'transform .2s, opacity .2s';
|
||||
toast.el.style.transform = '';
|
||||
toast.el.style.opacity = '';
|
||||
}
|
||||
Toast._draggedToast = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get x position of mouse or touch event
|
||||
* @param {Event} e
|
||||
*/
|
||||
static _xPos(e) {
|
||||
if (e.targetTouches && e.targetTouches.length >= 1) {
|
||||
return e.targetTouches[0].clientX;
|
||||
}
|
||||
// mouse event
|
||||
return e.clientX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all toasts
|
||||
*/
|
||||
static dismissAll() {
|
||||
for (let toastIndex in Toast._toasts) {
|
||||
Toast._toasts[toastIndex].dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create toast and append it to toast container
|
||||
*/
|
||||
_createToast() {
|
||||
let toast = document.createElement('div');
|
||||
toast.classList.add('toast');
|
||||
|
||||
// Add custom classes onto toast
|
||||
if (!!this.options.classes.length) {
|
||||
$(toast).addClass(this.options.classes);
|
||||
}
|
||||
|
||||
// Set safe text content
|
||||
toast.textContent = this.message;
|
||||
if (
|
||||
typeof HTMLElement === 'object'
|
||||
? this.htmlMessage instanceof HTMLElement
|
||||
: this.htmlMessage &&
|
||||
typeof this.htmlMessage === 'object' &&
|
||||
this.htmlMessage !== null &&
|
||||
this.htmlMessage.nodeType === 1 &&
|
||||
typeof this.htmlMessage.nodeName === 'string'
|
||||
) {
|
||||
//if the htmlMessage is an HTML node, append it directly
|
||||
toast.appendChild(this.htmlMessage);
|
||||
} else if (!!this.htmlMessage.jquery) {
|
||||
// Check if it is jQuery object, append the node
|
||||
$(toast).append(this.htmlMessage[0]);
|
||||
} else {
|
||||
// Append as unsanitized html;
|
||||
$(toast).append(this.htmlMessage);
|
||||
}
|
||||
|
||||
// Append toast
|
||||
Toast._container.appendChild(toast);
|
||||
return toast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in toast
|
||||
*/
|
||||
_animateIn() {
|
||||
// Animate toast in
|
||||
anim({
|
||||
targets: this.el,
|
||||
top: 0,
|
||||
opacity: 1,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutCubic'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create setInterval which automatically removes toast when timeRemaining >= 0
|
||||
* has been reached
|
||||
*/
|
||||
_setTimer() {
|
||||
if (this.timeRemaining !== Infinity) {
|
||||
this.counterInterval = setInterval(() => {
|
||||
// If toast is not being dragged, decrease its time remaining
|
||||
if (!this.panning) {
|
||||
this.timeRemaining -= 20;
|
||||
}
|
||||
|
||||
// Animate toast out
|
||||
if (this.timeRemaining <= 0) {
|
||||
this.dismiss();
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss toast with animation
|
||||
*/
|
||||
dismiss() {
|
||||
window.clearInterval(this.counterInterval);
|
||||
let activationDistance = this.el.offsetWidth * this.options.activationPercent;
|
||||
|
||||
if (this.wasSwiped) {
|
||||
this.el.style.transition = 'transform .05s, opacity .05s';
|
||||
this.el.style.transform = `translateX(${activationDistance}px)`;
|
||||
this.el.style.opacity = 0;
|
||||
}
|
||||
|
||||
anim({
|
||||
targets: this.el,
|
||||
opacity: 0,
|
||||
marginTop: -40,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutExpo',
|
||||
complete: () => {
|
||||
// Call the optional callback
|
||||
if (typeof this.options.completeCallback === 'function') {
|
||||
this.options.completeCallback();
|
||||
}
|
||||
// Remove toast from DOM
|
||||
this.$el.remove();
|
||||
Toast._toasts.splice(Toast._toasts.indexOf(this), 1);
|
||||
if (Toast._toasts.length === 0) {
|
||||
Toast._removeContainer();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Toast
|
||||
* @type {Array.<Toast>}
|
||||
*/
|
||||
Toast._toasts = [];
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Toast
|
||||
*/
|
||||
Toast._container = null;
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Toast
|
||||
* @type {Toast}
|
||||
*/
|
||||
Toast._draggedToast = null;
|
||||
|
||||
M.Toast = Toast;
|
||||
M.toast = function(options) {
|
||||
return new Toast(options);
|
||||
};
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,320 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
exitDelay: 200,
|
||||
enterDelay: 0,
|
||||
html: null,
|
||||
text: '',
|
||||
unsafeHTML: null,
|
||||
margin: 5,
|
||||
inDuration: 250,
|
||||
outDuration: 200,
|
||||
position: 'bottom',
|
||||
transitionMovement: 10
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
*/
|
||||
class Tooltip extends Component {
|
||||
/**
|
||||
* Construct Tooltip instance
|
||||
* @constructor
|
||||
* @param {Element} el
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(el, options) {
|
||||
super(Tooltip, el, options);
|
||||
|
||||
this.el.M_Tooltip = this;
|
||||
this.options = $.extend({}, Tooltip.defaults, options);
|
||||
|
||||
this.isOpen = false;
|
||||
this.isHovered = false;
|
||||
this.isFocused = false;
|
||||
this._appendTooltipEl();
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Tooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
$(this.tooltipEl).remove();
|
||||
this._removeEventHandlers();
|
||||
this.el.M_Tooltip = undefined;
|
||||
}
|
||||
|
||||
_appendTooltipEl() {
|
||||
let tooltipEl = document.createElement('div');
|
||||
tooltipEl.classList.add('material-tooltip');
|
||||
this.tooltipEl = tooltipEl;
|
||||
|
||||
let tooltipContentEl = document.createElement('div');
|
||||
tooltipContentEl.classList.add('tooltip-content');
|
||||
this._setTooltipContent(tooltipContentEl);
|
||||
|
||||
tooltipEl.appendChild(tooltipContentEl);
|
||||
document.body.appendChild(tooltipEl);
|
||||
}
|
||||
|
||||
_setTooltipContent(tooltipContentEl) {
|
||||
tooltipContentEl.textContent = this.options.text;
|
||||
if (!!this.options.html) {
|
||||
// Warn when using html
|
||||
console.warn(
|
||||
'The html option is deprecated and will be removed in the future. See https://github.com/materializecss/materialize/pull/49'
|
||||
);
|
||||
$(tooltipContentEl).append(this.options.html);
|
||||
}
|
||||
if (!!this.options.unsafeHTML) {
|
||||
$(tooltipContentEl).append(this.options.unsafeHTML);
|
||||
}
|
||||
}
|
||||
|
||||
_updateTooltipContent() {
|
||||
this._setTooltipContent(this.tooltipEl.querySelector('.tooltip-content'));
|
||||
}
|
||||
|
||||
_setupEventHandlers() {
|
||||
this._handleMouseEnterBound = this._handleMouseEnter.bind(this);
|
||||
this._handleMouseLeaveBound = this._handleMouseLeave.bind(this);
|
||||
this._handleFocusBound = this._handleFocus.bind(this);
|
||||
this._handleBlurBound = this._handleBlur.bind(this);
|
||||
this.el.addEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this.el.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.el.addEventListener('focus', this._handleFocusBound, true);
|
||||
this.el.addEventListener('blur', this._handleBlurBound, true);
|
||||
}
|
||||
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.el.removeEventListener('focus', this._handleFocusBound, true);
|
||||
this.el.removeEventListener('blur', this._handleBlurBound, true);
|
||||
}
|
||||
|
||||
open(isManual) {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
isManual = isManual === undefined ? true : undefined; // Default value true
|
||||
this.isOpen = true;
|
||||
// Update tooltip content with HTML attribute options
|
||||
this.options = $.extend({}, this.options, this._getAttributeOptions());
|
||||
this._updateTooltipContent();
|
||||
this._setEnterDelayTimeout(isManual);
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isHovered = false;
|
||||
this.isFocused = false;
|
||||
this.isOpen = false;
|
||||
this._setExitDelayTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create timeout which delays when the tooltip closes
|
||||
*/
|
||||
_setExitDelayTimeout() {
|
||||
clearTimeout(this._exitDelayTimeout);
|
||||
|
||||
this._exitDelayTimeout = setTimeout(() => {
|
||||
if (this.isHovered || this.isFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._animateOut();
|
||||
}, this.options.exitDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create timeout which delays when the toast closes
|
||||
*/
|
||||
_setEnterDelayTimeout(isManual) {
|
||||
clearTimeout(this._enterDelayTimeout);
|
||||
|
||||
this._enterDelayTimeout = setTimeout(() => {
|
||||
if (!this.isHovered && !this.isFocused && !isManual) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._animateIn();
|
||||
}, this.options.enterDelay);
|
||||
}
|
||||
|
||||
_positionTooltip() {
|
||||
let origin = this.el,
|
||||
tooltip = this.tooltipEl,
|
||||
originHeight = origin.offsetHeight,
|
||||
originWidth = origin.offsetWidth,
|
||||
tooltipHeight = tooltip.offsetHeight,
|
||||
tooltipWidth = tooltip.offsetWidth,
|
||||
newCoordinates,
|
||||
margin = this.options.margin,
|
||||
targetTop,
|
||||
targetLeft;
|
||||
|
||||
(this.xMovement = 0), (this.yMovement = 0);
|
||||
|
||||
targetTop = origin.getBoundingClientRect().top + M.getDocumentScrollTop();
|
||||
targetLeft = origin.getBoundingClientRect().left + M.getDocumentScrollLeft();
|
||||
|
||||
if (this.options.position === 'top') {
|
||||
targetTop += -tooltipHeight - margin;
|
||||
targetLeft += originWidth / 2 - tooltipWidth / 2;
|
||||
this.yMovement = -this.options.transitionMovement;
|
||||
} else if (this.options.position === 'right') {
|
||||
targetTop += originHeight / 2 - tooltipHeight / 2;
|
||||
targetLeft += originWidth + margin;
|
||||
this.xMovement = this.options.transitionMovement;
|
||||
} else if (this.options.position === 'left') {
|
||||
targetTop += originHeight / 2 - tooltipHeight / 2;
|
||||
targetLeft += -tooltipWidth - margin;
|
||||
this.xMovement = -this.options.transitionMovement;
|
||||
} else {
|
||||
targetTop += originHeight + margin;
|
||||
targetLeft += originWidth / 2 - tooltipWidth / 2;
|
||||
this.yMovement = this.options.transitionMovement;
|
||||
}
|
||||
|
||||
newCoordinates = this._repositionWithinScreen(
|
||||
targetLeft,
|
||||
targetTop,
|
||||
tooltipWidth,
|
||||
tooltipHeight
|
||||
);
|
||||
$(tooltip).css({
|
||||
top: newCoordinates.y + 'px',
|
||||
left: newCoordinates.x + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
_repositionWithinScreen(x, y, width, height) {
|
||||
let scrollLeft = M.getDocumentScrollLeft();
|
||||
let scrollTop = M.getDocumentScrollTop();
|
||||
let newX = x - scrollLeft;
|
||||
let newY = y - scrollTop;
|
||||
|
||||
let bounding = {
|
||||
left: newX,
|
||||
top: newY,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
|
||||
let offset = this.options.margin + this.options.transitionMovement;
|
||||
let edges = M.checkWithinContainer(document.body, bounding, offset);
|
||||
|
||||
if (edges.left) {
|
||||
newX = offset;
|
||||
} else if (edges.right) {
|
||||
newX -= newX + width - window.innerWidth;
|
||||
}
|
||||
|
||||
if (edges.top) {
|
||||
newY = offset;
|
||||
} else if (edges.bottom) {
|
||||
newY -= newY + height - window.innerHeight;
|
||||
}
|
||||
|
||||
return {
|
||||
x: newX + scrollLeft,
|
||||
y: newY + scrollTop
|
||||
};
|
||||
}
|
||||
|
||||
_animateIn() {
|
||||
this._positionTooltip();
|
||||
this.tooltipEl.style.visibility = 'visible';
|
||||
anim.remove(this.tooltipEl);
|
||||
anim({
|
||||
targets: this.tooltipEl,
|
||||
opacity: this.options.opacity || 1,
|
||||
translateX: this.xMovement,
|
||||
translateY: this.yMovement,
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutCubic'
|
||||
});
|
||||
}
|
||||
|
||||
_animateOut() {
|
||||
anim.remove(this.tooltipEl);
|
||||
anim({
|
||||
targets: this.tooltipEl,
|
||||
opacity: 0,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutCubic'
|
||||
});
|
||||
}
|
||||
|
||||
_handleMouseEnter() {
|
||||
this.isHovered = true;
|
||||
this.isFocused = false; // Allows close of tooltip when opened by focus.
|
||||
this.open(false);
|
||||
}
|
||||
|
||||
_handleMouseLeave() {
|
||||
this.isHovered = false;
|
||||
this.isFocused = false; // Allows close of tooltip when opened by focus.
|
||||
this.close();
|
||||
}
|
||||
|
||||
_handleFocus() {
|
||||
if (M.tabPressed) {
|
||||
this.isFocused = true;
|
||||
this.open(false);
|
||||
}
|
||||
}
|
||||
|
||||
_handleBlur() {
|
||||
this.isFocused = false;
|
||||
this.close();
|
||||
}
|
||||
|
||||
_getAttributeOptions() {
|
||||
let attributeOptions = {};
|
||||
let tooltipTextOption = this.el.getAttribute('data-tooltip');
|
||||
let positionOption = this.el.getAttribute('data-position');
|
||||
|
||||
if (tooltipTextOption) {
|
||||
attributeOptions.text = tooltipTextOption;
|
||||
}
|
||||
|
||||
if (positionOption) {
|
||||
attributeOptions.position = positionOption;
|
||||
}
|
||||
return attributeOptions;
|
||||
}
|
||||
}
|
||||
|
||||
M.Tooltip = Tooltip;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Tooltip, 'tooltip', 'M_Tooltip');
|
||||
}
|
||||
})(cash, M.anime);
|
|
@ -0,0 +1,615 @@
|
|||
/*!
|
||||
* Waves v0.7.6
|
||||
* http://fian.my.id/Waves
|
||||
*
|
||||
* Copyright 2014-2018 Alfiana E. Sibuea and other contributors
|
||||
* Released under the MIT license
|
||||
* https://github.com/fians/Waves/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
;(function(window, factory) {
|
||||
'use strict';
|
||||
|
||||
// AMD. Register as an anonymous module. Wrap in function so we have access
|
||||
// to root via `this`.
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], function() {
|
||||
window.Waves = factory.call(window);
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.Waves.init();
|
||||
}, false);
|
||||
return window.Waves;
|
||||
});
|
||||
}
|
||||
|
||||
// Node. Does not work with strict CommonJS, but only CommonJS-like
|
||||
// environments that support module.exports, like Node.
|
||||
else if (typeof exports === 'object') {
|
||||
module.exports = factory.call(window);
|
||||
}
|
||||
|
||||
// Browser globals.
|
||||
else {
|
||||
window.Waves = factory.call(window);
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.Waves.init();
|
||||
}, false);
|
||||
}
|
||||
})(typeof global === 'object' ? global : this, function() {
|
||||
'use strict';
|
||||
|
||||
var Waves = Waves || {};
|
||||
var $$ = document.querySelectorAll.bind(document);
|
||||
var toString = Object.prototype.toString;
|
||||
var isTouchAvailable = 'ontouchstart' in window;
|
||||
|
||||
/* Feature detection */
|
||||
var passiveIfSupported = false;
|
||||
try {
|
||||
window.addEventListener("test", null,
|
||||
Object.defineProperty({}, "passive", {
|
||||
get: function() { passiveIfSupported = { passive: false }; }
|
||||
}
|
||||
));
|
||||
} catch(err) {}
|
||||
|
||||
// Find exact position of element
|
||||
function isWindow(obj) {
|
||||
return obj !== null && obj === obj.window;
|
||||
}
|
||||
|
||||
function getWindow(elem) {
|
||||
return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
|
||||
}
|
||||
|
||||
function isObject(value) {
|
||||
var type = typeof value;
|
||||
return type === 'function' || type === 'object' && !!value;
|
||||
}
|
||||
|
||||
function isDOMNode(obj) {
|
||||
return isObject(obj) && obj.nodeType > 0;
|
||||
}
|
||||
|
||||
function getWavesElements(nodes) {
|
||||
var stringRepr = toString.call(nodes);
|
||||
|
||||
if (stringRepr === '[object String]') {
|
||||
return $$(nodes);
|
||||
} else if (isObject(nodes) && /^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(stringRepr) && nodes.hasOwnProperty('length')) {
|
||||
return nodes;
|
||||
} else if (isDOMNode(nodes)) {
|
||||
return [nodes];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function offset(elem) {
|
||||
var docElem, win,
|
||||
box = { top: 0, left: 0 },
|
||||
doc = elem && elem.ownerDocument;
|
||||
|
||||
docElem = doc.documentElement;
|
||||
|
||||
if (typeof elem.getBoundingClientRect !== typeof undefined) {
|
||||
box = elem.getBoundingClientRect();
|
||||
}
|
||||
win = getWindow(doc);
|
||||
return {
|
||||
top: box.top + win.pageYOffset - docElem.clientTop,
|
||||
left: box.left + win.pageXOffset - docElem.clientLeft
|
||||
};
|
||||
}
|
||||
|
||||
function convertStyle(styleObj) {
|
||||
var style = '';
|
||||
|
||||
for (var prop in styleObj) {
|
||||
if (styleObj.hasOwnProperty(prop)) {
|
||||
style += (prop + ':' + styleObj[prop] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
var Effect = {
|
||||
|
||||
// Effect duration
|
||||
duration: 750,
|
||||
|
||||
// Effect delay (check for scroll before showing effect)
|
||||
delay: 200,
|
||||
|
||||
show: function(e, element, velocity) {
|
||||
|
||||
// Disable right click
|
||||
if (e.button === 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
element = element || this;
|
||||
|
||||
// Create ripple
|
||||
var ripple = document.createElement('div');
|
||||
ripple.className = 'waves-ripple waves-rippling';
|
||||
element.appendChild(ripple);
|
||||
|
||||
// Get click coordinate and element width
|
||||
var pos = offset(element);
|
||||
var relativeY = 0;
|
||||
var relativeX = 0;
|
||||
// Support for touch devices
|
||||
if('touches' in e && e.touches.length) {
|
||||
relativeY = (e.touches[0].pageY - pos.top);
|
||||
relativeX = (e.touches[0].pageX - pos.left);
|
||||
}
|
||||
//Normal case
|
||||
else {
|
||||
relativeY = (e.pageY - pos.top);
|
||||
relativeX = (e.pageX - pos.left);
|
||||
}
|
||||
// Support for synthetic events
|
||||
relativeX = relativeX >= 0 ? relativeX : 0;
|
||||
relativeY = relativeY >= 0 ? relativeY : 0;
|
||||
|
||||
var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')';
|
||||
var translate = 'translate(0,0)';
|
||||
|
||||
if (velocity) {
|
||||
translate = 'translate(' + (velocity.x) + 'px, ' + (velocity.y) + 'px)';
|
||||
}
|
||||
|
||||
// Attach data to element
|
||||
ripple.setAttribute('data-hold', Date.now());
|
||||
ripple.setAttribute('data-x', relativeX);
|
||||
ripple.setAttribute('data-y', relativeY);
|
||||
ripple.setAttribute('data-scale', scale);
|
||||
ripple.setAttribute('data-translate', translate);
|
||||
|
||||
// Set ripple position
|
||||
var rippleStyle = {
|
||||
top: relativeY + 'px',
|
||||
left: relativeX + 'px'
|
||||
};
|
||||
|
||||
ripple.classList.add('waves-notransition');
|
||||
ripple.setAttribute('style', convertStyle(rippleStyle));
|
||||
ripple.classList.remove('waves-notransition');
|
||||
|
||||
// Scale the ripple
|
||||
rippleStyle['-webkit-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-moz-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-ms-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-o-transform'] = scale + ' ' + translate;
|
||||
rippleStyle.transform = scale + ' ' + translate;
|
||||
rippleStyle.opacity = '1';
|
||||
|
||||
var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
|
||||
rippleStyle['-webkit-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['-moz-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['-o-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['transition-duration'] = duration + 'ms';
|
||||
|
||||
ripple.setAttribute('style', convertStyle(rippleStyle));
|
||||
},
|
||||
|
||||
hide: function(e, element) {
|
||||
element = element || this;
|
||||
|
||||
var ripples = element.getElementsByClassName('waves-rippling');
|
||||
|
||||
for (var i = 0, len = ripples.length; i < len; i++) {
|
||||
removeRipple(e, element, ripples[i]);
|
||||
}
|
||||
|
||||
if (isTouchAvailable) {
|
||||
element.removeEventListener('touchend', Effect.hide);
|
||||
element.removeEventListener('touchcancel', Effect.hide);
|
||||
}
|
||||
|
||||
element.removeEventListener('mouseup', Effect.hide);
|
||||
element.removeEventListener('mouseleave', Effect.hide);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Collection of wrapper for HTML element that only have single tag
|
||||
* like <input> and <img>
|
||||
*/
|
||||
var TagWrapper = {
|
||||
|
||||
// Wrap <input> tag so it can perform the effect
|
||||
input: function(element) {
|
||||
|
||||
var parent = element.parentNode;
|
||||
|
||||
// If input already have parent just pass through
|
||||
if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Put element class and style to the specified parent
|
||||
var wrapper = document.createElement('i');
|
||||
wrapper.className = element.className + ' waves-input-wrapper';
|
||||
element.className = 'waves-button-input';
|
||||
|
||||
// Put element as child
|
||||
parent.replaceChild(wrapper, element);
|
||||
wrapper.appendChild(element);
|
||||
|
||||
// Apply element color and background color to wrapper
|
||||
var elementStyle = window.getComputedStyle(element, null);
|
||||
var color = elementStyle.color;
|
||||
var backgroundColor = elementStyle.backgroundColor;
|
||||
|
||||
wrapper.setAttribute('style', 'color:' + color + ';background:' + backgroundColor);
|
||||
element.setAttribute('style', 'background-color:rgba(0,0,0,0);');
|
||||
|
||||
},
|
||||
|
||||
// Wrap <img> tag so it can perform the effect
|
||||
img: function(element) {
|
||||
|
||||
var parent = element.parentNode;
|
||||
|
||||
// If input already have parent just pass through
|
||||
if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Put element as child
|
||||
var wrapper = document.createElement('i');
|
||||
parent.replaceChild(wrapper, element);
|
||||
wrapper.appendChild(element);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the effect and remove the ripple. Must be
|
||||
* a separate function to pass the JSLint...
|
||||
*/
|
||||
function removeRipple(e, el, ripple) {
|
||||
|
||||
// Check if the ripple still exist
|
||||
if (!ripple) {
|
||||
return;
|
||||
}
|
||||
|
||||
ripple.classList.remove('waves-rippling');
|
||||
|
||||
var relativeX = ripple.getAttribute('data-x');
|
||||
var relativeY = ripple.getAttribute('data-y');
|
||||
var scale = ripple.getAttribute('data-scale');
|
||||
var translate = ripple.getAttribute('data-translate');
|
||||
|
||||
// Get delay beetween mousedown and mouse leave
|
||||
var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
|
||||
var delay = 350 - diff;
|
||||
|
||||
if (delay < 0) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
if (e.type === 'mousemove') {
|
||||
delay = 150;
|
||||
}
|
||||
|
||||
// Fade out ripple after delay
|
||||
var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
var style = {
|
||||
top: relativeY + 'px',
|
||||
left: relativeX + 'px',
|
||||
opacity: '0',
|
||||
|
||||
// Duration
|
||||
'-webkit-transition-duration': duration + 'ms',
|
||||
'-moz-transition-duration': duration + 'ms',
|
||||
'-o-transition-duration': duration + 'ms',
|
||||
'transition-duration': duration + 'ms',
|
||||
'-webkit-transform': scale + ' ' + translate,
|
||||
'-moz-transform': scale + ' ' + translate,
|
||||
'-ms-transform': scale + ' ' + translate,
|
||||
'-o-transform': scale + ' ' + translate,
|
||||
'transform': scale + ' ' + translate
|
||||
};
|
||||
|
||||
ripple.setAttribute('style', convertStyle(style));
|
||||
|
||||
setTimeout(function() {
|
||||
try {
|
||||
el.removeChild(ripple);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}, duration);
|
||||
|
||||
}, delay);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disable mousedown event for 500ms during and after touch
|
||||
*/
|
||||
var TouchHandler = {
|
||||
|
||||
/* uses an integer rather than bool so there's no issues with
|
||||
* needing to clear timeouts if another touch event occurred
|
||||
* within the 500ms. Cannot mouseup between touchstart and
|
||||
* touchend, nor in the 500ms after touchend. */
|
||||
touches: 0,
|
||||
|
||||
allowEvent: function(e) {
|
||||
|
||||
var allow = true;
|
||||
|
||||
if (/^(mousedown|mousemove)$/.test(e.type) && TouchHandler.touches) {
|
||||
allow = false;
|
||||
}
|
||||
|
||||
return allow;
|
||||
},
|
||||
registerEvent: function(e) {
|
||||
var eType = e.type;
|
||||
|
||||
if (eType === 'touchstart') {
|
||||
|
||||
TouchHandler.touches += 1; // push
|
||||
|
||||
} else if (/^(touchend|touchcancel)$/.test(eType)) {
|
||||
|
||||
setTimeout(function() {
|
||||
if (TouchHandler.touches) {
|
||||
TouchHandler.touches -= 1; // pop after 500ms
|
||||
}
|
||||
}, 500);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Delegated click handler for .waves-effect element.
|
||||
* returns null when .waves-effect element not in "click tree"
|
||||
*/
|
||||
function getWavesEffectElement(e) {
|
||||
|
||||
if (TouchHandler.allowEvent(e) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var element = null;
|
||||
var target = e.target || e.srcElement;
|
||||
|
||||
while (target.parentElement) {
|
||||
if ( (!(target instanceof SVGElement)) && target.classList.contains('waves-effect')) {
|
||||
element = target;
|
||||
break;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bubble the click and show effect if .waves-effect elem was found
|
||||
*/
|
||||
function showEffect(e) {
|
||||
|
||||
// Disable effect if element has "disabled" property on it
|
||||
// In some cases, the event is not triggered by the current element
|
||||
// if (e.target.getAttribute('disabled') !== null) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
var element = getWavesEffectElement(e);
|
||||
|
||||
if (element !== null) {
|
||||
|
||||
// Make it sure the element has either disabled property, disabled attribute or 'disabled' class
|
||||
if (element.disabled || element.getAttribute('disabled') || element.classList.contains('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
TouchHandler.registerEvent(e);
|
||||
|
||||
if (e.type === 'touchstart' && Effect.delay) {
|
||||
|
||||
var hidden = false;
|
||||
|
||||
var timer = setTimeout(function () {
|
||||
timer = null;
|
||||
Effect.show(e, element);
|
||||
}, Effect.delay);
|
||||
|
||||
var hideEffect = function(hideEvent) {
|
||||
|
||||
// if touch hasn't moved, and effect not yet started: start effect now
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
Effect.show(e, element);
|
||||
}
|
||||
if (!hidden) {
|
||||
hidden = true;
|
||||
Effect.hide(hideEvent, element);
|
||||
}
|
||||
|
||||
removeListeners();
|
||||
};
|
||||
|
||||
var touchMove = function(moveEvent) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
hideEffect(moveEvent);
|
||||
|
||||
removeListeners();
|
||||
};
|
||||
|
||||
element.addEventListener('touchmove', touchMove, passiveIfSupported);
|
||||
element.addEventListener('touchend', hideEffect, passiveIfSupported);
|
||||
element.addEventListener('touchcancel', hideEffect, passiveIfSupported);
|
||||
|
||||
var removeListeners = function() {
|
||||
element.removeEventListener('touchmove', touchMove);
|
||||
element.removeEventListener('touchend', hideEffect);
|
||||
element.removeEventListener('touchcancel', hideEffect);
|
||||
};
|
||||
} else {
|
||||
|
||||
Effect.show(e, element);
|
||||
|
||||
if (isTouchAvailable) {
|
||||
element.addEventListener('touchend', Effect.hide, passiveIfSupported);
|
||||
element.addEventListener('touchcancel', Effect.hide, passiveIfSupported);
|
||||
}
|
||||
|
||||
element.addEventListener('mouseup', Effect.hide, passiveIfSupported);
|
||||
element.addEventListener('mouseleave', Effect.hide, passiveIfSupported);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Waves.init = function(options) {
|
||||
var body = document.body;
|
||||
|
||||
options = options || {};
|
||||
|
||||
if ('duration' in options) {
|
||||
Effect.duration = options.duration;
|
||||
}
|
||||
|
||||
if ('delay' in options) {
|
||||
Effect.delay = options.delay;
|
||||
}
|
||||
|
||||
if (isTouchAvailable) {
|
||||
body.addEventListener('touchstart', showEffect, passiveIfSupported);
|
||||
body.addEventListener('touchcancel', TouchHandler.registerEvent, passiveIfSupported);
|
||||
body.addEventListener('touchend', TouchHandler.registerEvent, passiveIfSupported);
|
||||
}
|
||||
|
||||
body.addEventListener('mousedown', showEffect, passiveIfSupported);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attach Waves to dynamically loaded inputs, or add .waves-effect and other
|
||||
* waves classes to a set of elements. Set drag to true if the ripple mouseover
|
||||
* or skimming effect should be applied to the elements.
|
||||
*/
|
||||
Waves.attach = function(elements, classes) {
|
||||
|
||||
elements = getWavesElements(elements);
|
||||
|
||||
if (toString.call(classes) === '[object Array]') {
|
||||
classes = classes.join(' ');
|
||||
}
|
||||
|
||||
classes = classes ? ' ' + classes : '';
|
||||
|
||||
var element, tagName;
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
|
||||
element = elements[i];
|
||||
tagName = element.tagName.toLowerCase();
|
||||
|
||||
if (['input', 'img'].indexOf(tagName) !== -1) {
|
||||
TagWrapper[tagName](element);
|
||||
element = element.parentElement;
|
||||
}
|
||||
|
||||
if (element.className.indexOf('waves-effect') === -1) {
|
||||
element.className += ' waves-effect' + classes;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cause a ripple to appear in an element via code.
|
||||
*/
|
||||
Waves.ripple = function(elements, options) {
|
||||
elements = getWavesElements(elements);
|
||||
var elementsLen = elements.length;
|
||||
|
||||
options = options || {};
|
||||
options.wait = options.wait || 0;
|
||||
options.position = options.position || null; // default = centre of element
|
||||
|
||||
|
||||
if (elementsLen) {
|
||||
var element, pos, off, centre = {}, i = 0;
|
||||
var mousedown = {
|
||||
type: 'mousedown',
|
||||
button: 1
|
||||
};
|
||||
var hideRipple = function(mouseup, element) {
|
||||
return function() {
|
||||
Effect.hide(mouseup, element);
|
||||
};
|
||||
};
|
||||
|
||||
for (; i < elementsLen; i++) {
|
||||
element = elements[i];
|
||||
pos = options.position || {
|
||||
x: element.clientWidth / 2,
|
||||
y: element.clientHeight / 2
|
||||
};
|
||||
|
||||
off = offset(element);
|
||||
centre.x = off.left + pos.x;
|
||||
centre.y = off.top + pos.y;
|
||||
|
||||
mousedown.pageX = centre.x;
|
||||
mousedown.pageY = centre.y;
|
||||
|
||||
Effect.show(mousedown, element);
|
||||
|
||||
if (options.wait >= 0 && options.wait !== null) {
|
||||
var mouseup = {
|
||||
type: 'mouseup',
|
||||
button: 1
|
||||
};
|
||||
|
||||
setTimeout(hideRipple(mouseup, element), options.wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove all ripples from an element.
|
||||
*/
|
||||
Waves.calm = function(elements) {
|
||||
elements = getWavesElements(elements);
|
||||
var mouseup = {
|
||||
type: 'mouseup',
|
||||
button: 1
|
||||
};
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
Effect.hide(mouseup, elements[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated API fallback
|
||||
*/
|
||||
Waves.displayEffect = function(options) {
|
||||
console.error('Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect');
|
||||
Waves.init(options);
|
||||
};
|
||||
|
||||
return Waves;
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"name": "@materializecss/materialize",
|
||||
"description": "Builds Materialize distribution packages",
|
||||
"author": "Alvin Wang, Alan Chang",
|
||||
"homepage": "https://materializecss.github.io/materialize/",
|
||||
"version": "1.1.0",
|
||||
"main": "dist/js/materialize.js",
|
||||
"style": "dist/css/materialize.css",
|
||||
"sass": "sass/materialize.scss",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/materializecss/materialize.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/materializecss/materialize/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "grunt monitor",
|
||||
"test": "grunt travis",
|
||||
"release": "grunt release",
|
||||
"precommit": "lint-staged",
|
||||
"docs": "grunt docs",
|
||||
"commit": "npx cz"
|
||||
},
|
||||
"lint-staged": {
|
||||
"js/*.js": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"engine": "node >= 6",
|
||||
"devDependencies": {
|
||||
"@commitlint/config-conventional": "^12.1.1",
|
||||
"autoprefixer": "^7.1.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"commitlint": "^12.1.1",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-babel": "^6.0.0",
|
||||
"grunt-banner": "^0.6.0",
|
||||
"grunt-browser-sync": "^2.2.0",
|
||||
"grunt-concurrent": "^3.0.0",
|
||||
"grunt-contrib-clean": "^1.1.0",
|
||||
"grunt-contrib-compress": "^1.4.1",
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-connect": "^3.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-jasmine": "^3.0.0",
|
||||
"grunt-contrib-pug": "^3.0.0",
|
||||
"grunt-contrib-uglify": "^3.0.1",
|
||||
"grunt-contrib-watch": "^1.0.0",
|
||||
"grunt-notify": "^0.4.5",
|
||||
"grunt-postcss": "^0.9.0",
|
||||
"grunt-remove-logging": "^0.2.0",
|
||||
"grunt-rename-util": "^1.0.0",
|
||||
"grunt-sass": "^3.1.0",
|
||||
"grunt-text-replace": "^0.4.0",
|
||||
"husky": "^0.14.3",
|
||||
"jasmine": "^3.8.0",
|
||||
"jquery": "^3.2.1",
|
||||
"lint-staged": "^7.0.5",
|
||||
"node-archiver": "^0.3.0",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"prettier": "^1.12.1",
|
||||
"sass": "^1.35.2"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"extras",
|
||||
"js/**/*.js",
|
||||
"sass/**/*.scss",
|
||||
"Gruntfile.js",
|
||||
"LICENSE"
|
||||
],
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,929 @@
|
|||
$border-color: rgba(0,0,0,.14);
|
||||
$font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
|
||||
/***************
|
||||
HTML Styles
|
||||
***************/
|
||||
body {
|
||||
//background-color: #fcfcfc;
|
||||
color: $off-black;
|
||||
line-height: 1.6;
|
||||
font-size: 16px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
p.box {
|
||||
padding: 20px;
|
||||
}
|
||||
p {
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
h5 > span {
|
||||
font-size: 14px;
|
||||
margin-left: 15px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
nav {
|
||||
// background-color: color("materialize-red", "lighten-2");
|
||||
|
||||
a {
|
||||
color: rgba(0,0,0,.87);
|
||||
}
|
||||
ul li a:hover, ul li.active {
|
||||
background-color: color("materialize-red", "lighten-1");
|
||||
}
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
color: color("materialize-red", "lighten-2");
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.preview {
|
||||
background-color: #FFF;
|
||||
border: 1px solid #eee;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.method-header {
|
||||
font-family: 'Inconsolata', Monaco, Consolas, 'Andale Mono', monospace;
|
||||
margin-top: 15px;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
header, main, footer {
|
||||
padding-left: 300px;
|
||||
}
|
||||
.parallax-demo header,
|
||||
.parallax-demo main,
|
||||
.parallax-demo footer {
|
||||
padding-left: 0;
|
||||
}
|
||||
footer.example {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
header, main, footer {
|
||||
padding-left: 0;
|
||||
}
|
||||
h5 > span {
|
||||
display: block;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************
|
||||
Index Page Styles
|
||||
********************/
|
||||
|
||||
// custom styled sidebar
|
||||
ul.sidenav.sidenav-fixed li.logo {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 136px;
|
||||
|
||||
&:hover,
|
||||
#logo-container:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
ul.sidenav.sidenav-fixed {
|
||||
overflow: hidden;
|
||||
box-shadow: none;
|
||||
border-right: 1px solid $border-color;
|
||||
|
||||
> li:last-child {
|
||||
margin-bottom: 160px;
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
line-height: 44px;
|
||||
|
||||
&.active {
|
||||
background-color: rgba(50,50,50,.06);
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 13px;
|
||||
line-height: 44px;
|
||||
height: 44px;
|
||||
padding: 0 30px;
|
||||
|
||||
.new.badge {
|
||||
margin-top: calc(22px - 11px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.collapsible-accordion {
|
||||
background-color: #FFF;
|
||||
|
||||
a.collapsible-header {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.collapsible-body li a {
|
||||
font-weight: 400;
|
||||
padding: 0 37.5px 0 45px;
|
||||
}
|
||||
}
|
||||
|
||||
// Only show scrollbar on hover
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.bold > a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#logo-container {
|
||||
height: 57px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.current-version-number {
|
||||
color: rgba(0,0,0,0.53);
|
||||
}
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
footer.page-footer .container {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
nav.top-nav {
|
||||
height: 110px;
|
||||
box-shadow: none;
|
||||
border-bottom: 1px solid $border-color;
|
||||
background-color: transparent;
|
||||
|
||||
h1.header {
|
||||
margin: 0;
|
||||
padding-top: 22px;
|
||||
}
|
||||
}
|
||||
a.sidenav-trigger.top-nav {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
top: 28px;
|
||||
float: none;
|
||||
margin-left: 1.5rem;
|
||||
color: color("materialize-red", "lighten-3");
|
||||
font-size: 36px;
|
||||
z-index: 2;
|
||||
|
||||
i {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$small-and-down} {
|
||||
a.sidenav-trigger.top-nav {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
ul.sidenav.sidenav-fixed {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
nav .nav-wrapper {
|
||||
text-align: center;
|
||||
|
||||
a.page-title {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$medium-and-up} {
|
||||
main > .container,
|
||||
body > .page-footer > .container,
|
||||
.top-nav > .container,
|
||||
#index-banner > .container,
|
||||
.github-commit > .container {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#front-page-logo {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
#front-page-nav ul.sidenav {
|
||||
li {
|
||||
float: none;
|
||||
padding: 0 15px;
|
||||
|
||||
&:hover { background-color: #ddd; }
|
||||
.active { background-color: transparent; }
|
||||
}
|
||||
a {
|
||||
color: #444;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#responsive-img {
|
||||
width: 80%;
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#index-banner {
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
}
|
||||
.header {
|
||||
// color: #FFF;
|
||||
}
|
||||
h4 {
|
||||
margin-bottom: 40px;
|
||||
line-height: 44px;
|
||||
color: rgba(0,0,0,.7);
|
||||
}
|
||||
h1 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-down} {
|
||||
#index-banner {
|
||||
h1 {
|
||||
margin-top: 60px;
|
||||
}
|
||||
h4 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media #{$small-and-down} {
|
||||
#index-banner {
|
||||
h4 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Latest commit widget
|
||||
.github-commit {
|
||||
color: rgba(0,0,0,0.53);
|
||||
border-top: 1px solid $border-color;
|
||||
padding: 14px 0;
|
||||
height: 64px;
|
||||
line-height: 36px;
|
||||
font-size: .9rem;
|
||||
|
||||
.sha {
|
||||
margin: 0 6px 0 6px;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-down} {
|
||||
.github-commit {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
#download-button,
|
||||
#upgrade-button {
|
||||
&:hover {
|
||||
background-color: lighten(color("materialize-red", "base"), 30%);
|
||||
}
|
||||
background-color: color("materialize-red", "lighten-2");
|
||||
width: 260px;
|
||||
height: 70px;
|
||||
margin: 4px;
|
||||
padding: 0;
|
||||
line-height: 70px;
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.promo{
|
||||
width: 100%;
|
||||
|
||||
i {
|
||||
margin: 40px 0;
|
||||
color: color("materialize-red", "lighten-2");
|
||||
font-size: 7rem;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.promo-caption {
|
||||
font-size: 1.7rem;
|
||||
font-weight: 500;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 0;
|
||||
|
||||
}
|
||||
|
||||
#front-page-nav {
|
||||
background-color: #FFF;
|
||||
position: relative;
|
||||
a {
|
||||
color: color("materialize-red", "lighten-2");
|
||||
}
|
||||
li {
|
||||
&:hover {
|
||||
background-color: color("materialize-red", "lighten-5");
|
||||
}
|
||||
&.active {
|
||||
background-color: color("materialize-red", "lighten-5");
|
||||
}
|
||||
}
|
||||
.container {
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Grid doc styles
|
||||
|
||||
.col.grid-example {
|
||||
border: 1px solid #eee;
|
||||
margin: 7px 0;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
font-size: 28px;
|
||||
background-color: tomato;
|
||||
color: white;
|
||||
padding: 0;
|
||||
|
||||
span {
|
||||
font-weight: 100;
|
||||
line-height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.promo-example {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
Flat Site Mockup
|
||||
*******************/
|
||||
|
||||
#site-layout-example-left {
|
||||
background-color: color("blue-grey", "lighten-2");
|
||||
height: 300px;
|
||||
}
|
||||
#site-layout-example-right {
|
||||
background-color: color("teal", "lighten-1");
|
||||
height: 300px;
|
||||
}
|
||||
#site-layout-example-top {
|
||||
background-color: color("red", "lighten-2");
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.flat-text-header {
|
||||
height: 35px;
|
||||
width: 80%;
|
||||
background-color: rgba(255,255,255,.15);
|
||||
display: block;
|
||||
margin: 27px auto;
|
||||
}
|
||||
.flat-text {
|
||||
height: 25px;
|
||||
width: 80%;
|
||||
background-color: rgba(0,0,0,.15);
|
||||
display: block;
|
||||
margin: 27px auto;
|
||||
&.small {
|
||||
width: 25%;
|
||||
height: 25px;
|
||||
background-color: rgba(0,0,0,.15);
|
||||
}
|
||||
&.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
**********************/
|
||||
|
||||
/*****************
|
||||
Chrome Browser
|
||||
*****************/
|
||||
$bottomColor: #E2E2E1;
|
||||
$topColor: lighten($bottomColor, 2%);
|
||||
|
||||
$border: $bottomColor;
|
||||
|
||||
$width: 100%;
|
||||
$height: auto;
|
||||
|
||||
.browser-window {
|
||||
text-align: left;
|
||||
width: $width;
|
||||
height: $height;
|
||||
display: inline-block;
|
||||
border-radius: 5px 5px 2px 2px;
|
||||
background-color: #fff;
|
||||
margin: 20px 0px;
|
||||
overflow: hidden;
|
||||
|
||||
.top-bar {
|
||||
height: 30px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
border-top: thin solid lighten($topColor, 1%);
|
||||
border-bottom: thin solid darken($bottomColor, 1%);
|
||||
background: linear-gradient($topColor, $bottomColor);
|
||||
}
|
||||
}
|
||||
|
||||
.browser-window .circle {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
background-color: lighten($topColor, 10%);
|
||||
margin-right: 1px;
|
||||
}
|
||||
#close-circle {
|
||||
background-color: #FF5C5A;
|
||||
}
|
||||
#minimize-circle {
|
||||
background-color: #FFBB50;
|
||||
}
|
||||
#maximize-circle {
|
||||
background-color: #1BC656;
|
||||
}
|
||||
.browser-window .circles { margin: 5px 12px; }
|
||||
.browser-window .content {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
// min-height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 0 0 5px 5px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.browser-window .row {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.clear { clear: both; }
|
||||
|
||||
/**********************
|
||||
**********************/
|
||||
|
||||
|
||||
// Color Wheel
|
||||
.dynamic-color {
|
||||
|
||||
.red, .pink, .purple, .deep-purple, .indigo, .blue, .light-blue, .cyan, .teal, .green, .light-green, .lime, .yellow, .amber, .orange, .deep-orange, .brown , .grey, .blue-grey, .black, .white, .transparent {
|
||||
height: 55px;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.col {
|
||||
margin-bottom: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
// Icons
|
||||
.material-icons.icon-demo {
|
||||
line-height: 50px;
|
||||
}
|
||||
.icon-container i {
|
||||
font-size: 3em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.icon-container .icon-preview {
|
||||
height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
.icon-container span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.icon-holder {
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 150px;
|
||||
height: 115px;
|
||||
|
||||
float: left;
|
||||
margin: 0 0px 15px 0px;
|
||||
p {
|
||||
margin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
// tabs
|
||||
.tabs-wrapper {
|
||||
position: relative;
|
||||
height: 48px;
|
||||
@extend .hide-on-small-only;
|
||||
|
||||
.row.pinned {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tables
|
||||
thead {
|
||||
color: rgba(0, 0, 0, .6);
|
||||
}
|
||||
|
||||
|
||||
// Shadow demo styling
|
||||
.shadow-demo {
|
||||
background-color: color("teal", "lighten-1");
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 20px auto;
|
||||
|
||||
@media only screen and (max-width: $small-screen) {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
// parallax demo
|
||||
.parallax-container {
|
||||
|
||||
.text-center {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-top: -27px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Table of contents
|
||||
ul.table-of-contents {
|
||||
margin-top: 0;
|
||||
padding-top: 48px;
|
||||
|
||||
a {
|
||||
&.active {
|
||||
color: rgba(0,0,0,.8);
|
||||
}
|
||||
color: rgba(0,0,0,.55);
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Prism Styling
|
||||
code, pre {
|
||||
position: relative;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.directory-markup {
|
||||
font-size: 1rem;
|
||||
line-height: 1.1rem !important;
|
||||
}
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em .25em;
|
||||
border: solid 1px rgba(51,51,51,0.12);
|
||||
}
|
||||
|
||||
// Styles code blocks
|
||||
pre[class*="language-"] {
|
||||
&:before {
|
||||
position: absolute;
|
||||
padding: 1px 5px;
|
||||
background: hsl(30, 10%, 90%);
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-family: $font-stack;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #555;
|
||||
content:attr(class);
|
||||
font-size: .9rem;
|
||||
border: solid 1px rgba(51, 51, 51, 0.12);
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
}
|
||||
padding: 25px 12px 7px 12px;
|
||||
border: solid 1px rgba(51, 51, 51, 0.12);
|
||||
background: rgba(246, 246, 246, .2);
|
||||
}
|
||||
|
||||
pre[class*="language-"],
|
||||
code[class*="language-"] {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
// Styles one-liners
|
||||
:not(pre) > code[class*="language-"] {
|
||||
background: rgba(246, 246, 246, .3);
|
||||
}
|
||||
|
||||
// copy code icons
|
||||
.copyMessage, .copyButton {
|
||||
color: #757575;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.copyMessage {
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease-in;
|
||||
opacity: 0;
|
||||
right: 45px;
|
||||
top: 15px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
.copyButton {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toc-wrapper {
|
||||
&.pin-bottom {
|
||||
margin-top: 84px;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
margin-top: 42px;
|
||||
}
|
||||
|
||||
// Footer styling
|
||||
footer{
|
||||
font-size: .9rem;
|
||||
}
|
||||
body.parallax-demo footer {
|
||||
margin-top: 0;
|
||||
}
|
||||
.docs-footer {
|
||||
margin-top: 40px;
|
||||
background-color: transparent;
|
||||
border-top: 1px solid $border-color;
|
||||
color: inherit;
|
||||
|
||||
.footer-copyright {
|
||||
color: inherit;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
//About page styling
|
||||
.image-container {
|
||||
width: 100%;
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mobile page styling
|
||||
|
||||
.mobile-image {
|
||||
@media #{$small-and-down} {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Waves page styling
|
||||
.waves-color-demo {
|
||||
.collection-item {
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
box-sizing: content-box;
|
||||
|
||||
code {
|
||||
line-height: 37px;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&:not(.waves-light) {
|
||||
background-color: color("shades", "white");
|
||||
color: #212121;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Card Page styling
|
||||
.card-panel span, .card-content p{
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#images .card-panel .row {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
// Pushpin Demo styles
|
||||
.pushpin-demo {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
}
|
||||
#pushpin-demo-1 {
|
||||
display: block;
|
||||
height: inherit;
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
// Valign Demo
|
||||
.valign-demo {
|
||||
height: 400px;
|
||||
background-color: #ddd;
|
||||
}
|
||||
.talign-demo {
|
||||
height: 100px;
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
// Transitions demos
|
||||
#staggered-test li,
|
||||
#image-test {
|
||||
opacity: 0;
|
||||
|
||||
}
|
||||
|
||||
// Transifex Styling
|
||||
|
||||
#tx-live-lang-container {
|
||||
background-color: #fcfcfc;
|
||||
z-index: 999;
|
||||
|
||||
#tx-live-lang-picker {
|
||||
background-color: #fcfcfc;
|
||||
|
||||
li {
|
||||
color: $off-black;
|
||||
&:hover{
|
||||
color: inherit;
|
||||
background-color: color("materialize-red", "lighten-5");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.txlive-langselector-toggle {
|
||||
border-bottom: 2px solid color("materialize-red", "lighten-2");
|
||||
}
|
||||
|
||||
.txlive-langselector-current {
|
||||
color: $off-black;
|
||||
}
|
||||
|
||||
.txlive-langselector-marker {
|
||||
border-bottom: 4px solid rgba(0,0,0,.61);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Thanks for Downloading
|
||||
#download-thanks {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
// Twitter widget
|
||||
#twitter-widget-0 {
|
||||
width: 300px !important;
|
||||
}
|
||||
|
||||
// Version dropdown
|
||||
#nav-mobile li.version {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-family: "Inconsolata";
|
||||
text-align: center;
|
||||
|
||||
.dropdown-trigger {
|
||||
font-family: "Inconsolata";
|
||||
margin: 0 auto;
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
border-bottom: 1px solid rgba(0,0,0, .2);
|
||||
|
||||
.caret {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
fill: rgba(0,0,0,.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#version-dropdown {
|
||||
text-align: left;
|
||||
|
||||
li > a {
|
||||
padding: 0 10px;
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Search
|
||||
#nav-mobile li.search {
|
||||
&:hover { background-color: #fff; }
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 160px;
|
||||
margin-top: 1px;
|
||||
padding: 1px 0 0 0;
|
||||
z-index: 2;
|
||||
|
||||
.search-wrapper {
|
||||
&.focused .search-results:not(:empty) {
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
||||
color: #777;
|
||||
margin-top: -1px;
|
||||
border-top: 1px solid $border-color;
|
||||
transition: margin .25s ease;
|
||||
|
||||
input#search {
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
color: #777;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
font-weight: 300;
|
||||
width: 100%;
|
||||
height: 62px;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0 45px 0 30px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
i.material-icons {
|
||||
position: absolute;
|
||||
top: 21px;
|
||||
right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.search-results {
|
||||
margin: 0;
|
||||
border-top: 1px solid $border-color;
|
||||
background-color: #fff;
|
||||
|
||||
a {
|
||||
&:hover,
|
||||
&.focused {
|
||||
background-color: #eee;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
55
node_modules/@materializecss/materialize/sass/components/_badges.scss
generated
vendored
Executable file
55
node_modules/@materializecss/materialize/sass/components/_badges.scss
generated
vendored
Executable file
|
@ -0,0 +1,55 @@
|
|||
// Badges
|
||||
span.badge {
|
||||
min-width: 3rem;
|
||||
padding: 0 6px;
|
||||
margin-left: 14px;
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
line-height: $badge-height;
|
||||
height: $badge-height;
|
||||
color: color('grey', 'darken-1');
|
||||
float: right;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.new {
|
||||
font-weight: 300;
|
||||
font-size: 0.8rem;
|
||||
color: #fff;
|
||||
background-color: $badge-bg-color;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&.new:after {
|
||||
content: " new";
|
||||
}
|
||||
|
||||
&[data-badge-caption]::after {
|
||||
content: " " attr(data-badge-caption);
|
||||
}
|
||||
}
|
||||
|
||||
// Special cases
|
||||
nav ul a span.badge {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-left: 4px;
|
||||
line-height: $badge-height;
|
||||
height: $badge-height;
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
|
||||
// Line height centering
|
||||
.collection-item span.badge {
|
||||
margin-top: calc(#{$collection-line-height * 0.5} - #{$badge-height * 0.5});
|
||||
}
|
||||
.collapsible span.badge {
|
||||
margin-left: auto;
|
||||
}
|
||||
.sidenav span.badge {
|
||||
margin-top: calc(#{$sidenav-line-height * 0.5} - #{$badge-height * 0.5});
|
||||
}
|
||||
|
||||
table span.badge {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-left: auto;
|
||||
}
|
322
node_modules/@materializecss/materialize/sass/components/_buttons.scss
generated
vendored
Executable file
322
node_modules/@materializecss/materialize/sass/components/_buttons.scss
generated
vendored
Executable file
|
@ -0,0 +1,322 @@
|
|||
// shared styles
|
||||
.btn,
|
||||
.btn-flat {
|
||||
border: $button-border;
|
||||
border-radius: $button-radius;
|
||||
display: inline-block;
|
||||
height: $button-height;
|
||||
line-height: $button-height;
|
||||
padding: $button-padding;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
-webkit-tap-highlight-color: transparent; // Gets rid of tap active state
|
||||
}
|
||||
|
||||
// Disabled shared style
|
||||
.btn.disabled,
|
||||
.btn-floating.disabled,
|
||||
.btn-large.disabled,
|
||||
.btn-small.disabled,
|
||||
.btn-flat.disabled,
|
||||
.btn:disabled,
|
||||
.btn-floating:disabled,
|
||||
.btn-large:disabled,
|
||||
.btn-small:disabled,
|
||||
.btn-flat:disabled,
|
||||
.btn[disabled],
|
||||
.btn-floating[disabled],
|
||||
.btn-large[disabled],
|
||||
.btn-small[disabled],
|
||||
.btn-flat[disabled] {
|
||||
pointer-events: none;
|
||||
background-color: $button-disabled-background !important;
|
||||
box-shadow: none;
|
||||
color: $button-disabled-color !important;
|
||||
cursor: default;
|
||||
&:hover {
|
||||
background-color: $button-disabled-background !important;
|
||||
color: $button-disabled-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Shared icon styles
|
||||
.btn,
|
||||
.btn-floating,
|
||||
.btn-large,
|
||||
.btn-small,
|
||||
.btn-flat {
|
||||
font-size: $button-font-size;
|
||||
outline: 0;
|
||||
i {
|
||||
font-size: $button-icon-font-size;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Shared focus button style
|
||||
.btn,
|
||||
.btn-floating {
|
||||
&:focus {
|
||||
background-color: darken($button-raised-background, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
// Raised Button
|
||||
.btn {
|
||||
text-decoration: none;
|
||||
color: $button-raised-color;
|
||||
background-color: $button-raised-background;
|
||||
text-align: center;
|
||||
letter-spacing: .5px;
|
||||
@extend .z-depth-1;
|
||||
transition: background-color .2s ease-out;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: $button-raised-background-hover;
|
||||
@extend .z-depth-1-half;
|
||||
}
|
||||
}
|
||||
|
||||
// Floating button
|
||||
.btn-floating {
|
||||
&:hover {
|
||||
background-color: $button-floating-background-hover;
|
||||
@extend .z-depth-1-half;
|
||||
}
|
||||
&:before {
|
||||
border-radius: 0;
|
||||
}
|
||||
&.btn-large {
|
||||
&.halfway-fab {
|
||||
bottom: -$button-floating-large-size * 0.5;
|
||||
}
|
||||
width: $button-floating-large-size;
|
||||
height: $button-floating-large-size;
|
||||
padding: 0;
|
||||
i {
|
||||
line-height: $button-floating-large-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-small {
|
||||
&.halfway-fab {
|
||||
bottom: -$button-floating-small-size * 0.5;
|
||||
}
|
||||
width: $button-floating-small-size;
|
||||
height: $button-floating-small-size;
|
||||
i {
|
||||
line-height: $button-floating-small-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.halfway-fab {
|
||||
&.left {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
bottom: -$button-floating-size * 0.5;
|
||||
}
|
||||
display: inline-block;
|
||||
color: $button-floating-color;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
width: $button-floating-size;
|
||||
height: $button-floating-size;
|
||||
line-height: $button-floating-size;
|
||||
padding: 0;
|
||||
background-color: $button-floating-background;
|
||||
border-radius: $button-floating-radius;
|
||||
@extend .z-depth-1;
|
||||
transition: background-color .3s;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
i {
|
||||
width: inherit;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: $button-floating-color;
|
||||
font-size: $button-large-icon-font-size;
|
||||
line-height: $button-floating-size;
|
||||
}
|
||||
}
|
||||
|
||||
// button fix
|
||||
button.btn-floating {
|
||||
border: $button-border;
|
||||
}
|
||||
|
||||
// Fixed Action Button
|
||||
.fixed-action-btn {
|
||||
&.active {
|
||||
ul {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
// Directions
|
||||
&.direction-left,
|
||||
&.direction-right {
|
||||
padding: 0 0 0 15px;
|
||||
ul {
|
||||
text-align: right;
|
||||
right: 64px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 100%;
|
||||
left: auto;
|
||||
/*width 100% only goes to width of button container */
|
||||
width: 500px;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 7.5px 15px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.direction-right {
|
||||
padding: 0 15px 0 0;
|
||||
ul {
|
||||
text-align: left;
|
||||
direction: rtl;
|
||||
left: 64px;
|
||||
right: auto;
|
||||
li {
|
||||
margin: 7.5px 0 0 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.direction-bottom {
|
||||
padding: 0 0 15px 0;
|
||||
ul {
|
||||
top: 64px;
|
||||
bottom: auto;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
li {
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.toolbar {
|
||||
&.active {
|
||||
&>a i {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
padding: 0;
|
||||
height: $button-floating-large-size;
|
||||
ul {
|
||||
display: flex;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
li {
|
||||
flex: 1;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
transition: none;
|
||||
a {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
line-height: $button-floating-large-size;
|
||||
z-index: 1;
|
||||
i {
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
position: fixed;
|
||||
right: 23px;
|
||||
bottom: 23px;
|
||||
padding-top: 15px;
|
||||
margin-bottom: 0;
|
||||
z-index: 997;
|
||||
ul {
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
bottom: 64px;
|
||||
margin: 0;
|
||||
visibility: hidden;
|
||||
li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
a.btn-floating {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.fab-backdrop {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
width: $button-floating-size;
|
||||
height: $button-floating-size;
|
||||
background-color: $button-floating-background;
|
||||
border-radius: $button-floating-radius;
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Flat button
|
||||
.btn-flat {
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
color: $button-flat-color;
|
||||
cursor: pointer;
|
||||
transition: background-color .2s;
|
||||
&:focus,
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
&:focus {
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
&.disabled,
|
||||
&.btn-flat[disabled] {
|
||||
background-color: transparent !important;
|
||||
color: $button-flat-disabled-color !important;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
// Large button
|
||||
.btn-large {
|
||||
@extend .btn;
|
||||
height: $button-large-height;
|
||||
line-height: $button-large-height;
|
||||
font-size: $button-large-font-size;
|
||||
padding: 0 28px;
|
||||
|
||||
i {
|
||||
font-size: $button-large-icon-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Small button
|
||||
.btn-small {
|
||||
@extend .btn;
|
||||
height: $button-small-height;
|
||||
line-height: $button-small-height;
|
||||
font-size: $button-small-font-size;
|
||||
i {
|
||||
font-size: $button-small-icon-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Block button
|
||||
.btn-block {
|
||||
display: block;
|
||||
}
|
195
node_modules/@materializecss/materialize/sass/components/_cards.scss
generated
vendored
Executable file
195
node_modules/@materializecss/materialize/sass/components/_cards.scss
generated
vendored
Executable file
|
@ -0,0 +1,195 @@
|
|||
|
||||
|
||||
.card-panel {
|
||||
transition: box-shadow .25s;
|
||||
padding: $card-padding;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
border-radius: 2px;
|
||||
@extend .z-depth-1;
|
||||
background-color: $card-bg-color;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
background-color: $card-bg-color;
|
||||
transition: box-shadow .25s;
|
||||
border-radius: 2px;
|
||||
@extend .z-depth-1;
|
||||
|
||||
|
||||
.card-title {
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
&.activator {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// Card Sizes
|
||||
&.small, &.medium, &.large {
|
||||
position: relative;
|
||||
|
||||
.card-image {
|
||||
max-height: 60%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-image + .card-content {
|
||||
max-height: 40%;
|
||||
}
|
||||
.card-content {
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-action {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
&.medium {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
&.large {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
// Horizontal Cards
|
||||
&.horizontal {
|
||||
&.small, &.medium, &.large {
|
||||
.card-image {
|
||||
height: 100%;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
display: flex;
|
||||
|
||||
.card-image {
|
||||
max-width: 50%;
|
||||
img {
|
||||
border-radius: 2px 0 0 2px;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.card-stacked {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.card-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sticky Action Section
|
||||
&.sticky-action {
|
||||
.card-action {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-reveal {
|
||||
z-index: 1;
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.card-image {
|
||||
position: relative;
|
||||
|
||||
// Image background for content
|
||||
img {
|
||||
display: block;
|
||||
border-radius: 2px 2px 0 0;
|
||||
position: relative;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
color: $card-bg-color;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
max-width: 100%;
|
||||
padding: $card-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: $card-padding;
|
||||
border-radius: 0 0 2px 2px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
.card-title {
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
i {
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-action {
|
||||
&:last-child {
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
background-color: inherit; // Use inherit to inherit color classes
|
||||
border-top: 1px solid rgba(160,160,160,.2);
|
||||
position: relative;
|
||||
padding: 16px $card-padding;
|
||||
|
||||
a:not(.btn):not(.btn-large):not(.btn-floating) {
|
||||
color: $card-link-color;
|
||||
margin-right: $card-padding;
|
||||
transition: color .3s ease;
|
||||
text-transform: uppercase;
|
||||
|
||||
&:hover { color: $card-link-color-light; }
|
||||
}
|
||||
}
|
||||
|
||||
.card-reveal {
|
||||
padding: $card-padding;
|
||||
position: absolute;
|
||||
background-color: $card-bg-color;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
display: none;
|
||||
|
||||
.card-title {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
90
node_modules/@materializecss/materialize/sass/components/_carousel.scss
generated
vendored
Executable file
90
node_modules/@materializecss/materialize/sass/components/_carousel.scss
generated
vendored
Executable file
|
@ -0,0 +1,90 @@
|
|||
.carousel {
|
||||
&.carousel-slider {
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
.carousel-fixed-item {
|
||||
&.with-indicators {
|
||||
bottom: 68px;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 20px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: $carousel-height;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: $carousel-height;
|
||||
perspective: 500px;
|
||||
transform-style: preserve-3d;
|
||||
transform-origin: 0% 50%;
|
||||
|
||||
.carousel-item {
|
||||
visibility: hidden;
|
||||
width: $carousel-item-width;
|
||||
height: $carousel-item-height;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
& > img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.indicators {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
|
||||
.indicator-item {
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
margin: 24px 4px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
|
||||
transition: background-color .3s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// Materialbox compatibility
|
||||
&.scrolling .carousel-item .materialboxed,
|
||||
.carousel-item:not(.active) .materialboxed {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
96
node_modules/@materializecss/materialize/sass/components/_chips.scss
generated
vendored
Executable file
96
node_modules/@materializecss/materialize/sass/components/_chips.scss
generated
vendored
Executable file
|
@ -0,0 +1,96 @@
|
|||
.chip {
|
||||
&:focus {
|
||||
outline: none;
|
||||
background-color: $chip-selected-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: rgba(0,0,0,.6);
|
||||
line-height: 32px;
|
||||
padding: 0 12px;
|
||||
border-radius: 16px;
|
||||
background-color: $chip-bg-color;
|
||||
margin-bottom: $chip-margin;
|
||||
margin-right: $chip-margin;
|
||||
|
||||
> img {
|
||||
float: left;
|
||||
margin: 0 8px 0 -12px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.close {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.chips {
|
||||
border: none;
|
||||
border-bottom: 1px solid $chip-border-color;
|
||||
box-shadow: none;
|
||||
margin: $input-margin;
|
||||
min-height: 45px;
|
||||
outline: none;
|
||||
transition: all .3s;
|
||||
|
||||
&.focus {
|
||||
border-bottom: 1px solid $chip-selected-color;
|
||||
box-shadow: 0 1px 0 0 $chip-selected-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
input:not([type]):not(.browser-default).input {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: rgba(0,0,0,.6);
|
||||
display: inline-block;
|
||||
font-size: $input-font-size;
|
||||
height: $input-height;
|
||||
line-height: 32px;
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 120px;
|
||||
|
||||
&:focus {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Autocomplete
|
||||
.autocomplete-content {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Form prefix
|
||||
.prefix ~ .chips {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
// Form suffix
|
||||
.suffix ~ .chips {
|
||||
margin-right: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
.chips:empty ~ label {
|
||||
font-size: 0.8rem;
|
||||
transform: translateY(-140%);
|
||||
}
|
91
node_modules/@materializecss/materialize/sass/components/_collapsible.scss
generated
vendored
Executable file
91
node_modules/@materializecss/materialize/sass/components/_collapsible.scss
generated
vendored
Executable file
|
@ -0,0 +1,91 @@
|
|||
.collapsible {
|
||||
border-top: 1px solid $collapsible-border-color;
|
||||
border-right: 1px solid $collapsible-border-color;
|
||||
border-left: 1px solid $collapsible-border-color;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
@extend .z-depth-1;
|
||||
}
|
||||
|
||||
.collapsible-header {
|
||||
&:focus {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
line-height: 1.5;
|
||||
padding: 1rem;
|
||||
background-color: $collapsible-header-color;
|
||||
border-bottom: 1px solid $collapsible-border-color;
|
||||
|
||||
i {
|
||||
width: 2rem;
|
||||
font-size: 1.6rem;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
.keyboard-focused .collapsible-header:focus {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.collapsible-body {
|
||||
display: none;
|
||||
border-bottom: 1px solid $collapsible-border-color;
|
||||
box-sizing: border-box;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
// Sidenav collapsible styling
|
||||
.sidenav,
|
||||
.sidenav.sidenav-fixed {
|
||||
|
||||
.collapsible {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
|
||||
li { padding: 0; }
|
||||
}
|
||||
|
||||
.collapsible-header {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
line-height: inherit;
|
||||
height: inherit;
|
||||
padding: 0 $sidenav-padding;
|
||||
|
||||
&:hover { background-color: rgba(0,0,0,.05); }
|
||||
i { line-height: inherit; }
|
||||
}
|
||||
|
||||
.collapsible-body {
|
||||
border: 0;
|
||||
background-color: $collapsible-header-color;
|
||||
|
||||
li a {
|
||||
padding: 0 (7.5px + $sidenav-padding)
|
||||
0 (15px + $sidenav-padding);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Popout Collapsible
|
||||
|
||||
.collapsible.popout {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
> li {
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
// transform: scaleX(.92);
|
||||
margin: 0 24px;
|
||||
transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
}
|
||||
> li.active {
|
||||
box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15);
|
||||
margin: 16px 0;
|
||||
// transform: scaleX(1);
|
||||
}
|
||||
}
|
107
node_modules/@materializecss/materialize/sass/components/_collection.scss
generated
vendored
Executable file
107
node_modules/@materializecss/materialize/sass/components/_collection.scss
generated
vendored
Executable file
|
@ -0,0 +1,107 @@
|
|||
|
||||
// Collections
|
||||
.collection {
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
border: 1px solid $collection-border-color;
|
||||
border-radius: $collection-border-radius;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.collection-item {
|
||||
background-color: $collection-bg-color;
|
||||
line-height: $collection-line-height;
|
||||
padding: 10px 20px;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid $collection-border-color;
|
||||
|
||||
// Avatar Collection
|
||||
&.avatar {
|
||||
min-height: 84px;
|
||||
padding-left: 72px;
|
||||
position: relative;
|
||||
|
||||
// Don't style circles inside preloader classes.
|
||||
&:not(.circle-clipper) > .circle,
|
||||
:not(.circle-clipper) > .circle {
|
||||
position: absolute;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
overflow: hidden;
|
||||
left: 15px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
i.circle {
|
||||
font-size: 18px;
|
||||
line-height: 42px;
|
||||
color: #fff;
|
||||
background-color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.secondary-content {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $collection-active-bg-color;
|
||||
color: $collection-active-color;
|
||||
|
||||
.secondary-content {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
a.collection-item{
|
||||
display: block;
|
||||
transition: .25s;
|
||||
color: $collection-link-color;
|
||||
&:not(.active) {
|
||||
&:hover {
|
||||
background-color: $collection-hover-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.with-header {
|
||||
.collection-header {
|
||||
background-color: $collection-bg-color;
|
||||
border-bottom: 1px solid $collection-border-color;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.collection-item {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.collection-item.avatar {
|
||||
padding-left: 72px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Made less specific to allow easier overriding
|
||||
.secondary-content {
|
||||
float: right;
|
||||
color: $secondary-color;
|
||||
}
|
||||
.collapsible .collection {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
32
node_modules/@materializecss/materialize/sass/components/_color-classes.scss
generated
vendored
Executable file
32
node_modules/@materializecss/materialize/sass/components/_color-classes.scss
generated
vendored
Executable file
|
@ -0,0 +1,32 @@
|
|||
// Color Classes
|
||||
|
||||
@each $color_name, $color in $colors {
|
||||
@each $color_type, $color_value in $color {
|
||||
@if $color_type == "base" {
|
||||
.#{$color_name} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color_name}-text {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
||||
@else if $color_name != "shades" {
|
||||
.#{$color_name}.#{$color_type} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color_name}-text.text-#{$color_type} {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shade classes
|
||||
@each $color, $color_value in $shades {
|
||||
.#{$color} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color}-text {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
370
node_modules/@materializecss/materialize/sass/components/_color-variables.scss
generated
vendored
Executable file
370
node_modules/@materializecss/materialize/sass/components/_color-variables.scss
generated
vendored
Executable file
|
@ -0,0 +1,370 @@
|
|||
// Google Color Palette defined: http://www.google.com/design/spec/style/color.html
|
||||
|
||||
$materialize-red: (
|
||||
"base": #e51c23,
|
||||
"lighten-5": #fdeaeb,
|
||||
"lighten-4": #f8c1c3,
|
||||
"lighten-3": #f3989b,
|
||||
"lighten-2": #ee6e73,
|
||||
"lighten-1": #ea454b,
|
||||
"darken-1": #d0181e,
|
||||
"darken-2": #b9151b,
|
||||
"darken-3": #a21318,
|
||||
"darken-4": #8b1014,
|
||||
);
|
||||
|
||||
$red: (
|
||||
"base": #F44336,
|
||||
"lighten-5": #FFEBEE,
|
||||
"lighten-4": #FFCDD2,
|
||||
"lighten-3": #EF9A9A,
|
||||
"lighten-2": #E57373,
|
||||
"lighten-1": #EF5350,
|
||||
"darken-1": #E53935,
|
||||
"darken-2": #D32F2F,
|
||||
"darken-3": #C62828,
|
||||
"darken-4": #B71C1C,
|
||||
"accent-1": #FF8A80,
|
||||
"accent-2": #FF5252,
|
||||
"accent-3": #FF1744,
|
||||
"accent-4": #D50000
|
||||
);
|
||||
|
||||
$pink: (
|
||||
"base": #e91e63,
|
||||
"lighten-5": #fce4ec,
|
||||
"lighten-4": #f8bbd0,
|
||||
"lighten-3": #f48fb1,
|
||||
"lighten-2": #f06292,
|
||||
"lighten-1": #ec407a,
|
||||
"darken-1": #d81b60,
|
||||
"darken-2": #c2185b,
|
||||
"darken-3": #ad1457,
|
||||
"darken-4": #880e4f,
|
||||
"accent-1": #ff80ab,
|
||||
"accent-2": #ff4081,
|
||||
"accent-3": #f50057,
|
||||
"accent-4": #c51162
|
||||
);
|
||||
|
||||
$purple: (
|
||||
"base": #9c27b0,
|
||||
"lighten-5": #f3e5f5,
|
||||
"lighten-4": #e1bee7,
|
||||
"lighten-3": #ce93d8,
|
||||
"lighten-2": #ba68c8,
|
||||
"lighten-1": #ab47bc,
|
||||
"darken-1": #8e24aa,
|
||||
"darken-2": #7b1fa2,
|
||||
"darken-3": #6a1b9a,
|
||||
"darken-4": #4a148c,
|
||||
"accent-1": #ea80fc,
|
||||
"accent-2": #e040fb,
|
||||
"accent-3": #d500f9,
|
||||
"accent-4": #aa00ff
|
||||
);
|
||||
|
||||
$deep-purple: (
|
||||
"base": #673ab7,
|
||||
"lighten-5": #ede7f6,
|
||||
"lighten-4": #d1c4e9,
|
||||
"lighten-3": #b39ddb,
|
||||
"lighten-2": #9575cd,
|
||||
"lighten-1": #7e57c2,
|
||||
"darken-1": #5e35b1,
|
||||
"darken-2": #512da8,
|
||||
"darken-3": #4527a0,
|
||||
"darken-4": #311b92,
|
||||
"accent-1": #b388ff,
|
||||
"accent-2": #7c4dff,
|
||||
"accent-3": #651fff,
|
||||
"accent-4": #6200ea
|
||||
);
|
||||
|
||||
$indigo: (
|
||||
"base": #3f51b5,
|
||||
"lighten-5": #e8eaf6,
|
||||
"lighten-4": #c5cae9,
|
||||
"lighten-3": #9fa8da,
|
||||
"lighten-2": #7986cb,
|
||||
"lighten-1": #5c6bc0,
|
||||
"darken-1": #3949ab,
|
||||
"darken-2": #303f9f,
|
||||
"darken-3": #283593,
|
||||
"darken-4": #1a237e,
|
||||
"accent-1": #8c9eff,
|
||||
"accent-2": #536dfe,
|
||||
"accent-3": #3d5afe,
|
||||
"accent-4": #304ffe
|
||||
);
|
||||
|
||||
$blue: (
|
||||
"base": #2196F3,
|
||||
"lighten-5": #E3F2FD,
|
||||
"lighten-4": #BBDEFB,
|
||||
"lighten-3": #90CAF9,
|
||||
"lighten-2": #64B5F6,
|
||||
"lighten-1": #42A5F5,
|
||||
"darken-1": #1E88E5,
|
||||
"darken-2": #1976D2,
|
||||
"darken-3": #1565C0,
|
||||
"darken-4": #0D47A1,
|
||||
"accent-1": #82B1FF,
|
||||
"accent-2": #448AFF,
|
||||
"accent-3": #2979FF,
|
||||
"accent-4": #2962FF
|
||||
);
|
||||
|
||||
$light-blue: (
|
||||
"base": #03a9f4,
|
||||
"lighten-5": #e1f5fe,
|
||||
"lighten-4": #b3e5fc,
|
||||
"lighten-3": #81d4fa,
|
||||
"lighten-2": #4fc3f7,
|
||||
"lighten-1": #29b6f6,
|
||||
"darken-1": #039be5,
|
||||
"darken-2": #0288d1,
|
||||
"darken-3": #0277bd,
|
||||
"darken-4": #01579b,
|
||||
"accent-1": #80d8ff,
|
||||
"accent-2": #40c4ff,
|
||||
"accent-3": #00b0ff,
|
||||
"accent-4": #0091ea
|
||||
);
|
||||
|
||||
$cyan: (
|
||||
"base": #00bcd4,
|
||||
"lighten-5": #e0f7fa,
|
||||
"lighten-4": #b2ebf2,
|
||||
"lighten-3": #80deea,
|
||||
"lighten-2": #4dd0e1,
|
||||
"lighten-1": #26c6da,
|
||||
"darken-1": #00acc1,
|
||||
"darken-2": #0097a7,
|
||||
"darken-3": #00838f,
|
||||
"darken-4": #006064,
|
||||
"accent-1": #84ffff,
|
||||
"accent-2": #18ffff,
|
||||
"accent-3": #00e5ff,
|
||||
"accent-4": #00b8d4
|
||||
);
|
||||
|
||||
$teal: (
|
||||
"base": #009688,
|
||||
"lighten-5": #e0f2f1,
|
||||
"lighten-4": #b2dfdb,
|
||||
"lighten-3": #80cbc4,
|
||||
"lighten-2": #4db6ac,
|
||||
"lighten-1": #26a69a,
|
||||
"darken-1": #00897b,
|
||||
"darken-2": #00796b,
|
||||
"darken-3": #00695c,
|
||||
"darken-4": #004d40,
|
||||
"accent-1": #a7ffeb,
|
||||
"accent-2": #64ffda,
|
||||
"accent-3": #1de9b6,
|
||||
"accent-4": #00bfa5
|
||||
);
|
||||
|
||||
$green: (
|
||||
"base": #4CAF50,
|
||||
"lighten-5": #E8F5E9,
|
||||
"lighten-4": #C8E6C9,
|
||||
"lighten-3": #A5D6A7,
|
||||
"lighten-2": #81C784,
|
||||
"lighten-1": #66BB6A,
|
||||
"darken-1": #43A047,
|
||||
"darken-2": #388E3C,
|
||||
"darken-3": #2E7D32,
|
||||
"darken-4": #1B5E20,
|
||||
"accent-1": #B9F6CA,
|
||||
"accent-2": #69F0AE,
|
||||
"accent-3": #00E676,
|
||||
"accent-4": #00C853
|
||||
);
|
||||
|
||||
$light-green: (
|
||||
"base": #8bc34a,
|
||||
"lighten-5": #f1f8e9,
|
||||
"lighten-4": #dcedc8,
|
||||
"lighten-3": #c5e1a5,
|
||||
"lighten-2": #aed581,
|
||||
"lighten-1": #9ccc65,
|
||||
"darken-1": #7cb342,
|
||||
"darken-2": #689f38,
|
||||
"darken-3": #558b2f,
|
||||
"darken-4": #33691e,
|
||||
"accent-1": #ccff90,
|
||||
"accent-2": #b2ff59,
|
||||
"accent-3": #76ff03,
|
||||
"accent-4": #64dd17
|
||||
);
|
||||
|
||||
$lime: (
|
||||
"base": #cddc39,
|
||||
"lighten-5": #f9fbe7,
|
||||
"lighten-4": #f0f4c3,
|
||||
"lighten-3": #e6ee9c,
|
||||
"lighten-2": #dce775,
|
||||
"lighten-1": #d4e157,
|
||||
"darken-1": #c0ca33,
|
||||
"darken-2": #afb42b,
|
||||
"darken-3": #9e9d24,
|
||||
"darken-4": #827717,
|
||||
"accent-1": #f4ff81,
|
||||
"accent-2": #eeff41,
|
||||
"accent-3": #c6ff00,
|
||||
"accent-4": #aeea00
|
||||
);
|
||||
|
||||
$yellow: (
|
||||
"base": #ffeb3b,
|
||||
"lighten-5": #fffde7,
|
||||
"lighten-4": #fff9c4,
|
||||
"lighten-3": #fff59d,
|
||||
"lighten-2": #fff176,
|
||||
"lighten-1": #ffee58,
|
||||
"darken-1": #fdd835,
|
||||
"darken-2": #fbc02d,
|
||||
"darken-3": #f9a825,
|
||||
"darken-4": #f57f17,
|
||||
"accent-1": #ffff8d,
|
||||
"accent-2": #ffff00,
|
||||
"accent-3": #ffea00,
|
||||
"accent-4": #ffd600
|
||||
);
|
||||
|
||||
$amber: (
|
||||
"base": #ffc107,
|
||||
"lighten-5": #fff8e1,
|
||||
"lighten-4": #ffecb3,
|
||||
"lighten-3": #ffe082,
|
||||
"lighten-2": #ffd54f,
|
||||
"lighten-1": #ffca28,
|
||||
"darken-1": #ffb300,
|
||||
"darken-2": #ffa000,
|
||||
"darken-3": #ff8f00,
|
||||
"darken-4": #ff6f00,
|
||||
"accent-1": #ffe57f,
|
||||
"accent-2": #ffd740,
|
||||
"accent-3": #ffc400,
|
||||
"accent-4": #ffab00
|
||||
);
|
||||
|
||||
$orange: (
|
||||
"base": #ff9800,
|
||||
"lighten-5": #fff3e0,
|
||||
"lighten-4": #ffe0b2,
|
||||
"lighten-3": #ffcc80,
|
||||
"lighten-2": #ffb74d,
|
||||
"lighten-1": #ffa726,
|
||||
"darken-1": #fb8c00,
|
||||
"darken-2": #f57c00,
|
||||
"darken-3": #ef6c00,
|
||||
"darken-4": #e65100,
|
||||
"accent-1": #ffd180,
|
||||
"accent-2": #ffab40,
|
||||
"accent-3": #ff9100,
|
||||
"accent-4": #ff6d00
|
||||
);
|
||||
|
||||
$deep-orange: (
|
||||
"base": #ff5722,
|
||||
"lighten-5": #fbe9e7,
|
||||
"lighten-4": #ffccbc,
|
||||
"lighten-3": #ffab91,
|
||||
"lighten-2": #ff8a65,
|
||||
"lighten-1": #ff7043,
|
||||
"darken-1": #f4511e,
|
||||
"darken-2": #e64a19,
|
||||
"darken-3": #d84315,
|
||||
"darken-4": #bf360c,
|
||||
"accent-1": #ff9e80,
|
||||
"accent-2": #ff6e40,
|
||||
"accent-3": #ff3d00,
|
||||
"accent-4": #dd2c00
|
||||
);
|
||||
|
||||
$brown: (
|
||||
"base": #795548,
|
||||
"lighten-5": #efebe9,
|
||||
"lighten-4": #d7ccc8,
|
||||
"lighten-3": #bcaaa4,
|
||||
"lighten-2": #a1887f,
|
||||
"lighten-1": #8d6e63,
|
||||
"darken-1": #6d4c41,
|
||||
"darken-2": #5d4037,
|
||||
"darken-3": #4e342e,
|
||||
"darken-4": #3e2723
|
||||
);
|
||||
|
||||
$blue-grey: (
|
||||
"base": #607d8b,
|
||||
"lighten-5": #eceff1,
|
||||
"lighten-4": #cfd8dc,
|
||||
"lighten-3": #b0bec5,
|
||||
"lighten-2": #90a4ae,
|
||||
"lighten-1": #78909c,
|
||||
"darken-1": #546e7a,
|
||||
"darken-2": #455a64,
|
||||
"darken-3": #37474f,
|
||||
"darken-4": #263238
|
||||
);
|
||||
|
||||
$grey: (
|
||||
"base": #9e9e9e,
|
||||
"lighten-5": #fafafa,
|
||||
"lighten-4": #f5f5f5,
|
||||
"lighten-3": #eeeeee,
|
||||
"lighten-2": #e0e0e0,
|
||||
"lighten-1": #bdbdbd,
|
||||
"darken-1": #757575,
|
||||
"darken-2": #616161,
|
||||
"darken-3": #424242,
|
||||
"darken-4": #212121
|
||||
);
|
||||
|
||||
$shades: (
|
||||
"black": #000000,
|
||||
"white": #FFFFFF,
|
||||
"transparent": transparent
|
||||
);
|
||||
|
||||
$colors: (
|
||||
"materialize-red": $materialize-red,
|
||||
"red": $red,
|
||||
"pink": $pink,
|
||||
"purple": $purple,
|
||||
"deep-purple": $deep-purple,
|
||||
"indigo": $indigo,
|
||||
"blue": $blue,
|
||||
"light-blue": $light-blue,
|
||||
"cyan": $cyan,
|
||||
"teal": $teal,
|
||||
"green": $green,
|
||||
"light-green": $light-green,
|
||||
"lime": $lime,
|
||||
"yellow": $yellow,
|
||||
"amber": $amber,
|
||||
"orange": $orange,
|
||||
"deep-orange": $deep-orange,
|
||||
"brown": $brown,
|
||||
"blue-grey": $blue-grey,
|
||||
"grey": $grey,
|
||||
"shades": $shades
|
||||
) !default;
|
||||
|
||||
|
||||
// usage: color("name_of_color", "type_of_color")
|
||||
// to avoid to repeating map-get($colors, ...)
|
||||
|
||||
@function color($color, $type) {
|
||||
@if map-has-key($colors, $color) {
|
||||
$curr_color: map-get($colors, $color);
|
||||
@if map-has-key($curr_color, $type) {
|
||||
@return map-get($curr_color, $type);
|
||||
}
|
||||
}
|
||||
@warn "Unknown `#{$color}` - `#{$type}` in $colors.";
|
||||
@return null;
|
||||
}
|
191
node_modules/@materializecss/materialize/sass/components/_datepicker.scss
generated
vendored
Executable file
191
node_modules/@materializecss/materialize/sass/components/_datepicker.scss
generated
vendored
Executable file
|
@ -0,0 +1,191 @@
|
|||
/* Modal */
|
||||
.datepicker-modal {
|
||||
max-width: 325px;
|
||||
min-width: 300px;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.datepicker-container.modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.datepicker-controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 280px;
|
||||
margin: 0 auto;
|
||||
|
||||
.selects-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.select-wrapper {
|
||||
input {
|
||||
&:focus {
|
||||
border-bottom: none;
|
||||
}
|
||||
border-bottom: none;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.caret {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.select-year input {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.select-month input {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.month-prev, .month-next {
|
||||
margin-top: 4px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
/* Date Display */
|
||||
.datepicker-date-display {
|
||||
flex: 1 auto;
|
||||
background-color: $secondary-color;
|
||||
color: #fff;
|
||||
padding: 20px 22px;
|
||||
font-weight: 500;
|
||||
|
||||
.year-text {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
line-height: 25px;
|
||||
color: $datepicker-year;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
display: block;
|
||||
font-size: 2.8rem;
|
||||
line-height: 47px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Calendar */
|
||||
.datepicker-calendar-container {
|
||||
flex: 2.5 auto;
|
||||
}
|
||||
|
||||
.datepicker-table {
|
||||
width: 280px;
|
||||
font-size: 1rem;
|
||||
margin: 0 auto;
|
||||
|
||||
thead {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 10px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tr {
|
||||
border: none;
|
||||
}
|
||||
|
||||
abbr {
|
||||
text-decoration: none;
|
||||
color: $datepicker-calendar-header-color;
|
||||
}
|
||||
|
||||
td {
|
||||
&.is-today {
|
||||
color: $secondary-color;
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background-color: $secondary-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.is-outside-current-month,
|
||||
&.is-disabled {
|
||||
color: $datepicker-disabled-day-color;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-day-button {
|
||||
&:focus {
|
||||
background-color: $datepicker-day-focus;
|
||||
}
|
||||
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
line-height: 38px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
.datepicker-footer {
|
||||
width: 280px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.datepicker-cancel,
|
||||
.datepicker-clear,
|
||||
.datepicker-today,
|
||||
.datepicker-done {
|
||||
color: $secondary-color;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.datepicker-clear {
|
||||
color: $error-color;
|
||||
}
|
||||
|
||||
|
||||
/* Media Queries */
|
||||
@media #{$medium-and-up} {
|
||||
.datepicker-modal {
|
||||
max-width: 625px;
|
||||
}
|
||||
|
||||
.datepicker-container.modal-content {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.datepicker-date-display {
|
||||
flex: 0 1 270px;
|
||||
}
|
||||
|
||||
.datepicker-controls,
|
||||
.datepicker-table,
|
||||
.datepicker-footer {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.datepicker-day-button {
|
||||
line-height: 44px;
|
||||
}
|
||||
}
|
85
node_modules/@materializecss/materialize/sass/components/_dropdown.scss
generated
vendored
Executable file
85
node_modules/@materializecss/materialize/sass/components/_dropdown.scss
generated
vendored
Executable file
|
@ -0,0 +1,85 @@
|
|||
.dropdown-content {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
@extend .z-depth-1;
|
||||
background-color: $dropdown-bg-color;
|
||||
margin: 0;
|
||||
display: none;
|
||||
min-width: 100px;
|
||||
overflow-y: auto;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 9999; // TODO: Check if this doesn't break other things
|
||||
transform-origin: 0 0;
|
||||
|
||||
|
||||
li {
|
||||
&:hover, &.active {
|
||||
background-color: $dropdown-hover-bg-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.divider {
|
||||
min-height: 0;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
& > a, & > span {
|
||||
font-size: 16px;
|
||||
color: $dropdown-color;
|
||||
display: block;
|
||||
line-height: 22px;
|
||||
padding: (($dropdown-item-height - 22) * 0.5) 16px;
|
||||
}
|
||||
|
||||
& > span > label {
|
||||
top: 1px;
|
||||
left: 0;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
// Icon alignment override
|
||||
& > a > i {
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
float: left;
|
||||
margin: 0 24px 0 0;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
|
||||
clear: both;
|
||||
color: $off-black;
|
||||
cursor: pointer;
|
||||
min-height: $dropdown-item-height;
|
||||
line-height: 1.5rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
body.keyboard-focused {
|
||||
.dropdown-content li:focus {
|
||||
background-color: darken($dropdown-hover-bg-color, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
// Input field specificity bugfix
|
||||
.input-field.col .dropdown-content [type="checkbox"] + label {
|
||||
top: 1px;
|
||||
left: 0;
|
||||
height: 18px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.dropdown-trigger {
|
||||
cursor: pointer;
|
||||
}
|
642
node_modules/@materializecss/materialize/sass/components/_global.scss
generated
vendored
Executable file
642
node_modules/@materializecss/materialize/sass/components/_global.scss
generated
vendored
Executable file
|
@ -0,0 +1,642 @@
|
|||
//Default styles
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: $font-stack;
|
||||
}
|
||||
|
||||
ul {
|
||||
&:not(.browser-default) {
|
||||
padding-left: 0;
|
||||
list-style-type: none;
|
||||
|
||||
& > li {
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
|
||||
// Gets rid of tap active state
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
// Positioning
|
||||
.valign-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
// classic clearfix
|
||||
.clearfix {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
// Z-levels
|
||||
.z-depth-0 {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 2dp elevation modified*/
|
||||
.z-depth-1 {
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14),
|
||||
0 3px 1px -2px rgba(0,0,0,0.12),
|
||||
0 1px 5px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
.z-depth-1-half {
|
||||
box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14), 0 1px 7px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 6dp elevation modified*/
|
||||
.z-depth-2 {
|
||||
box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14),
|
||||
0 1px 10px 0 rgba(0,0,0,0.12),
|
||||
0 2px 4px -1px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* 12dp elevation modified*/
|
||||
.z-depth-3 {
|
||||
box-shadow: 0 8px 17px 2px rgba(0,0,0,0.14),
|
||||
0 3px 14px 2px rgba(0,0,0,0.12),
|
||||
0 5px 5px -3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 16dp elevation */
|
||||
.z-depth-4 {
|
||||
box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14),
|
||||
0 6px 30px 5px rgba(0,0,0,0.12),
|
||||
0 8px 10px -7px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
/* 24dp elevation */
|
||||
.z-depth-5 {
|
||||
box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14),
|
||||
0 9px 46px 8px rgba(0,0,0,0.12),
|
||||
0 11px 15px -7px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.hoverable {
|
||||
transition: box-shadow .25s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
}
|
||||
|
||||
// Dividers
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: color("grey", "lighten-2");
|
||||
}
|
||||
|
||||
|
||||
// Blockquote
|
||||
|
||||
blockquote {
|
||||
margin: 20px 0;
|
||||
padding-left: 1.5rem;
|
||||
border-left: 5px solid $primary-color;
|
||||
}
|
||||
|
||||
// Icon Styles
|
||||
|
||||
i {
|
||||
line-height: inherit;
|
||||
|
||||
&.left {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
&.right {
|
||||
float: right;
|
||||
margin-left: 15px;
|
||||
}
|
||||
&.tiny {
|
||||
font-size: 1rem;
|
||||
}
|
||||
&.small {
|
||||
font-size: 2rem;
|
||||
}
|
||||
&.medium {
|
||||
font-size: 4rem;
|
||||
}
|
||||
&.large {
|
||||
font-size: 6rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Images
|
||||
img.responsive-img,
|
||||
video.responsive-video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
// Pagination
|
||||
|
||||
.pagination {
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
height: 30px;
|
||||
|
||||
a {
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
font-size: 1.2rem;
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
&.active a { color: #fff; }
|
||||
|
||||
&.active { background-color: $primary-color; }
|
||||
|
||||
&.disabled a {
|
||||
cursor: default;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
li.pages ul li {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-down} {
|
||||
.pagination {
|
||||
width: 100%;
|
||||
|
||||
li.prev,
|
||||
li.next {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
li.pages {
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Breadcrumbs
|
||||
.breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 18px;
|
||||
color: rgba(255,255,255, .7);
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '\E5CC';
|
||||
color: rgba(255,255,255, .7);
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 25px;
|
||||
margin: 0 10px 0 8px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&:first-child:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Parallax
|
||||
.parallax-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 500px;
|
||||
|
||||
.parallax {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
|
||||
img {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
transform: translate3d(0,0,0);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pushpin
|
||||
.pin-top, .pin-bottom {
|
||||
position: relative;
|
||||
}
|
||||
.pinned {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
/*********************
|
||||
Transition Classes
|
||||
**********************/
|
||||
|
||||
ul.staggered-list li {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 0;
|
||||
transform-origin: 0 50%;
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
Media Query Classes
|
||||
**********************/
|
||||
.hide-on-small-only, .hide-on-small-and-down {
|
||||
@media #{$small-and-down} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-and-down {
|
||||
@media #{$medium-and-down} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-and-up {
|
||||
@media #{$medium-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-only {
|
||||
@media only screen and (min-width: $small-screen-up) and (max-width: $medium-screen) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-large-only {
|
||||
@media #{$large-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-extra-large-only {
|
||||
@media #{$extra-large-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.show-on-extra-large {
|
||||
@media #{$extra-large-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-large {
|
||||
@media #{$large-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium {
|
||||
@media only screen and (min-width: $small-screen-up) and (max-width: $medium-screen) {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-small {
|
||||
@media #{$small-and-down} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium-and-up {
|
||||
@media #{$medium-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium-and-down {
|
||||
@media #{$medium-and-down} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Center text on mobile
|
||||
.center-on-small-only {
|
||||
@media #{$small-and-down} {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer
|
||||
.page-footer {
|
||||
padding-top: 20px;
|
||||
color: $footer-font-color;
|
||||
background-color: $footer-bg-color;
|
||||
|
||||
.footer-copyright {
|
||||
overflow: hidden;
|
||||
min-height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0px;
|
||||
color: $footer-copyright-font-color;
|
||||
background-color: $footer-copyright-bg-color;
|
||||
}
|
||||
}
|
||||
|
||||
// Tables
|
||||
table, th, td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
table {
|
||||
width:100%;
|
||||
display: table;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
|
||||
&.striped {
|
||||
tr {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.highlight > tbody > tr {
|
||||
transition: background-color .25s ease;
|
||||
&:hover {
|
||||
background-color: $table-striped-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.centered {
|
||||
thead tr th, tbody tr td {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid $table-border-color;
|
||||
}
|
||||
|
||||
td, th{
|
||||
padding: 15px 5px;
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
// Responsive Table
|
||||
@media #{$medium-and-down} {
|
||||
|
||||
table.responsive-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
td:empty:before {
|
||||
content: '\00a0';
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th { text-align: left; }
|
||||
thead {
|
||||
display: block;
|
||||
float: left;
|
||||
|
||||
tr {
|
||||
display: block;
|
||||
padding: 0 10px 0 0;
|
||||
|
||||
th::before {
|
||||
content: "\00a0";
|
||||
}
|
||||
}
|
||||
}
|
||||
tbody {
|
||||
display: block;
|
||||
width: auto;
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
|
||||
tr {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
th {
|
||||
display: block;
|
||||
text-align: right;
|
||||
}
|
||||
td {
|
||||
display: block;
|
||||
min-height: 1.25em;
|
||||
text-align: left;
|
||||
}
|
||||
tr {
|
||||
border-bottom: none;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* sort out borders */
|
||||
thead {
|
||||
border: 0;
|
||||
border-right: 1px solid $table-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Responsive Videos
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
|
||||
iframe, object, embed {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Progress Bar
|
||||
.progress {
|
||||
position: relative;
|
||||
height: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
background-color: lighten($progress-bar-color, 40%);
|
||||
border-radius: 2px;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
overflow: hidden;
|
||||
.determinate {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: $progress-bar-color;
|
||||
transition: width .3s linear;
|
||||
}
|
||||
.indeterminate {
|
||||
background-color: $progress-bar-color;
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left:0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
// Custom bezier
|
||||
animation: indeterminate 2.1s cubic-bezier(0.650, 0.815, 0.735, 0.395) infinite;
|
||||
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left:0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
// Custom bezier
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.840, 0.440, 1.000) infinite;
|
||||
animation-delay: 1.15s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right:100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
Utility Classes
|
||||
*******************/
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// Text Align
|
||||
.left-align {
|
||||
text-align: left;
|
||||
}
|
||||
.right-align {
|
||||
text-align: right
|
||||
}
|
||||
.center, .center-align {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left !important;
|
||||
}
|
||||
.right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
// No Text Select
|
||||
.no-select {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.center-block {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
158
node_modules/@materializecss/materialize/sass/components/_grid.scss
generated
vendored
Executable file
158
node_modules/@materializecss/materialize/sass/components/_grid.scss
generated
vendored
Executable file
|
@ -0,0 +1,158 @@
|
|||
@use "sass:math";
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 1280px;
|
||||
width: 90%;
|
||||
}
|
||||
@media #{$medium-and-up} {
|
||||
.container {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
@media #{$large-and-up} {
|
||||
.container {
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
.col .row {
|
||||
margin-left: (-1 * $gutter-width * 0.5);
|
||||
margin-right: (-1 * $gutter-width * 0.5);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
&.no-pad {
|
||||
padding: 0;
|
||||
}
|
||||
&.no-pad-bot {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
&.no-pad-top {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mixins to eliminate code repetition
|
||||
@mixin reset-offset {
|
||||
margin-left: auto;
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
@mixin grid-classes($size, $i, $perc) {
|
||||
&.offset-#{$size}#{$i} {
|
||||
margin-left: $perc;
|
||||
}
|
||||
&.pull-#{$size}#{$i} {
|
||||
right: $perc;
|
||||
}
|
||||
&.push-#{$size}#{$i} {
|
||||
left: $perc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.row {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 20px;
|
||||
|
||||
// Clear floating children
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.col {
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
padding: 0 $gutter-width * 0.5;
|
||||
min-height: 1px;
|
||||
|
||||
&[class*="push-"],
|
||||
&[class*="pull-"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
&.s#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
@include grid-classes("s", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
@media #{$medium-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
&.m#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
@include grid-classes("m", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$large-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
&.l#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
@include grid-classes("l", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$extra-large-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
&.xl#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote(math.div(100, math.div($num-cols, $i)) + "%");
|
||||
@include grid-classes("xl", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
node_modules/@materializecss/materialize/sass/components/_icons-material-design.scss
generated
vendored
Executable file
5
node_modules/@materializecss/materialize/sass/components/_icons-material-design.scss
generated
vendored
Executable file
|
@ -0,0 +1,5 @@
|
|||
/* This is needed for some mobile phones to display the Google Icon font properly */
|
||||
.material-icons {
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: 'liga';
|
||||
}
|
43
node_modules/@materializecss/materialize/sass/components/_materialbox.scss
generated
vendored
Executable file
43
node_modules/@materializecss/materialize/sass/components/_materialbox.scss
generated
vendored
Executable file
|
@ -0,0 +1,43 @@
|
|||
.materialboxed {
|
||||
&:hover {
|
||||
&:not(.active) {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
display: block;
|
||||
cursor: zoom-in;
|
||||
position: relative;
|
||||
transition: opacity .4s;
|
||||
-webkit-backface-visibility: hidden;
|
||||
|
||||
&.active {
|
||||
cursor: zoom-out;
|
||||
}
|
||||
}
|
||||
|
||||
#materialbox-overlay {
|
||||
position:fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #292929;
|
||||
z-index: 1000;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
.materialbox-caption {
|
||||
position: fixed;
|
||||
display: none;
|
||||
color: #fff;
|
||||
line-height: 50px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0% 15%;
|
||||
height: 50px;
|
||||
z-index: 1000;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
97
node_modules/@materializecss/materialize/sass/components/_modal.scss
generated
vendored
Executable file
97
node_modules/@materializecss/materialize/sass/components/_modal.scss
generated
vendored
Executable file
|
@ -0,0 +1,97 @@
|
|||
.modal {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@extend .z-depth-5;
|
||||
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fafafa;
|
||||
padding: 0;
|
||||
max-height: 70%;
|
||||
width: 55%;
|
||||
margin: auto;
|
||||
overflow-y: auto;
|
||||
|
||||
border-radius: 2px;
|
||||
will-change: top, opacity;
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 24px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-radius: 0 0 2px 2px;
|
||||
background-color: #fafafa;
|
||||
padding: 4px 6px;
|
||||
height: 56px;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
|
||||
.btn, .btn-flat {
|
||||
margin: 6px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: -25%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 125%;
|
||||
width: 100%;
|
||||
background: #000;
|
||||
display: none;
|
||||
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
// Modal with fixed action footer
|
||||
.modal.modal-fixed-footer {
|
||||
padding: 0;
|
||||
height: 70%;
|
||||
|
||||
.modal-content {
|
||||
position: absolute;
|
||||
height: calc(100% - 56px);
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-top: 1px solid rgba(0,0,0,.1);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Modal Bottom Sheet Style
|
||||
.modal.bottom-sheet {
|
||||
top: auto;
|
||||
bottom: -100%;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: 45%;
|
||||
border-radius: 0;
|
||||
will-change: bottom, opacity;
|
||||
}
|
208
node_modules/@materializecss/materialize/sass/components/_navbar.scss
generated
vendored
Executable file
208
node_modules/@materializecss/materialize/sass/components/_navbar.scss
generated
vendored
Executable file
|
@ -0,0 +1,208 @@
|
|||
nav {
|
||||
&.nav-extended {
|
||||
height: auto;
|
||||
|
||||
.nav-wrapper {
|
||||
min-height: $navbar-height-mobile;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
color: $navbar-font-color;
|
||||
@extend .z-depth-1;
|
||||
background-color: $primary-color;
|
||||
width: 100%;
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
|
||||
a { color: $navbar-font-color; }
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media #{$large-and-up} {
|
||||
a.sidenav-trigger { display: none; }
|
||||
}
|
||||
|
||||
|
||||
// Collapse button
|
||||
.sidenav-trigger {
|
||||
float: left;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: $navbar-height-mobile;
|
||||
margin: 0 18px;
|
||||
|
||||
i {
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Logo
|
||||
.brand-logo {
|
||||
position: absolute;
|
||||
color: $navbar-font-color;
|
||||
display: inline-block;
|
||||
font-size: $navbar-brand-font-size;
|
||||
padding: 0;
|
||||
|
||||
&.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
&.left, &.right {
|
||||
padding: 0;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
&.left { left: 0.5rem; }
|
||||
&.right {
|
||||
right: 0.5rem;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Title
|
||||
.nav-title {
|
||||
display: inline-block;
|
||||
font-size: 32px;
|
||||
padding: 28px 0;
|
||||
}
|
||||
|
||||
|
||||
// Navbar Links
|
||||
ul {
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
transition: background-color .3s;
|
||||
float: left;
|
||||
padding: 0;
|
||||
|
||||
&.active {
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
a {
|
||||
transition: background-color .3s;
|
||||
font-size: $navbar-font-size;
|
||||
color: $navbar-font-color;
|
||||
display: block;
|
||||
padding: 0 15px;
|
||||
cursor: pointer;
|
||||
|
||||
&.btn, &.btn-large, &.btn-flat, &.btn-floating {
|
||||
margin-top: -2px;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
|
||||
& > .material-icons {
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
// Navbar Search Form
|
||||
form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
|
||||
input {
|
||||
height: 100%;
|
||||
font-size: 1.2rem;
|
||||
border: none;
|
||||
padding-left: 2rem;
|
||||
|
||||
&:focus, &[type=text]:valid, &[type=password]:valid,
|
||||
&[type=email]:valid, &[type=url]:valid, &[type=date]:valid {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
i {
|
||||
color: rgba(255,255,255,.7);
|
||||
transition: color .3s;
|
||||
}
|
||||
&.active i { color: $navbar-font-color; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed Navbar
|
||||
.navbar-fixed {
|
||||
position: relative;
|
||||
height: $navbar-height-mobile;
|
||||
z-index: 997;
|
||||
|
||||
nav {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-up} {
|
||||
nav.nav-extended .nav-wrapper {
|
||||
min-height: $navbar-height;
|
||||
}
|
||||
nav, nav .nav-wrapper i, nav a.sidenav-trigger, nav a.sidenav-trigger i {
|
||||
height: $navbar-height;
|
||||
line-height: $navbar-line-height;
|
||||
}
|
||||
.navbar-fixed {
|
||||
height: $navbar-height;
|
||||
}
|
||||
}
|
447
node_modules/@materializecss/materialize/sass/components/_normalize.scss
generated
vendored
Executable file
447
node_modules/@materializecss/materialize/sass/components/_normalize.scss
generated
vendored
Executable file
|
@ -0,0 +1,447 @@
|
|||
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
header,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the gray background on active links in IE 10.
|
||||
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent; /* 1 */
|
||||
-webkit-text-decoration-skip: objects; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the overflow in IE.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
* controls in Android 4.
|
||||
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
html [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10-.
|
||||
* 2. Remove the padding in IE 10-.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
334
node_modules/@materializecss/materialize/sass/components/_preloader.scss
generated
vendored
Executable file
334
node_modules/@materializecss/materialize/sass/components/_preloader.scss
generated
vendored
Executable file
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
@license
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
*/
|
||||
|
||||
/**************************/
|
||||
/* STYLES FOR THE SPINNER */
|
||||
/**************************/
|
||||
|
||||
/*
|
||||
* Constants:
|
||||
* STROKEWIDTH = 3px
|
||||
* ARCSIZE = 270 degrees (amount of circle the arc takes up)
|
||||
* ARCTIME = 1333ms (time it takes to expand and contract arc)
|
||||
* ARCSTARTROT = 216 degrees (how much the start location of the arc
|
||||
* should rotate each time, 216 gives us a
|
||||
* 5 pointed star shape (it's 360/5 * 3).
|
||||
* For a 7 pointed star, we might do
|
||||
* 360/7 * 3 = 154.286)
|
||||
* CONTAINERWIDTH = 28px
|
||||
* SHRINK_TIME = 400ms
|
||||
*/
|
||||
|
||||
|
||||
.preloader-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
|
||||
&.small {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
&.big {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
/* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */
|
||||
-webkit-animation: container-rotate 1568ms linear infinite;
|
||||
animation: container-rotate 1568ms linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes container-rotate {
|
||||
to { -webkit-transform: rotate(360deg) }
|
||||
}
|
||||
|
||||
@keyframes container-rotate {
|
||||
to { transform: rotate(360deg) }
|
||||
}
|
||||
|
||||
.spinner-layer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
border-color: $spinner-default-color;
|
||||
}
|
||||
|
||||
.spinner-blue,
|
||||
.spinner-blue-only {
|
||||
border-color: #4285f4;
|
||||
}
|
||||
|
||||
.spinner-red,
|
||||
.spinner-red-only {
|
||||
border-color: #db4437;
|
||||
}
|
||||
|
||||
.spinner-yellow,
|
||||
.spinner-yellow-only {
|
||||
border-color: #f4b400;
|
||||
}
|
||||
|
||||
.spinner-green,
|
||||
.spinner-green-only {
|
||||
border-color: #0f9d58;
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee):
|
||||
*
|
||||
* iOS Safari (tested on iOS 8.1) does not handle animation-delay very well - it doesn't
|
||||
* guarantee that the animation will start _exactly_ after that value. So we avoid using
|
||||
* animation-delay and instead set custom keyframes for each color (as redundant as it
|
||||
* seems).
|
||||
*
|
||||
* We write out each animation in full (instead of separating animation-name,
|
||||
* animation-duration, etc.) because under the polyfill, Safari does not recognize those
|
||||
* specific properties properly, treats them as -webkit-animation, and overrides the
|
||||
* other animation rules. See https://github.com/Polymer/platform/issues/53.
|
||||
*/
|
||||
.active .spinner-layer.spinner-blue {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-red {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-yellow {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-green {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer,
|
||||
.active .spinner-layer.spinner-blue-only,
|
||||
.active .spinner-layer.spinner-red-only,
|
||||
.active .spinner-layer.spinner-yellow-only,
|
||||
.active .spinner-layer.spinner-green-only {
|
||||
/* durations: 4 * ARCTIME */
|
||||
opacity: 1;
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fill-unfill-rotate {
|
||||
12.5% { -webkit-transform: rotate(135deg); } /* 0.5 * ARCSIZE */
|
||||
25% { -webkit-transform: rotate(270deg); } /* 1 * ARCSIZE */
|
||||
37.5% { -webkit-transform: rotate(405deg); } /* 1.5 * ARCSIZE */
|
||||
50% { -webkit-transform: rotate(540deg); } /* 2 * ARCSIZE */
|
||||
62.5% { -webkit-transform: rotate(675deg); } /* 2.5 * ARCSIZE */
|
||||
75% { -webkit-transform: rotate(810deg); } /* 3 * ARCSIZE */
|
||||
87.5% { -webkit-transform: rotate(945deg); } /* 3.5 * ARCSIZE */
|
||||
to { -webkit-transform: rotate(1080deg); } /* 4 * ARCSIZE */
|
||||
}
|
||||
|
||||
@keyframes fill-unfill-rotate {
|
||||
12.5% { transform: rotate(135deg); } /* 0.5 * ARCSIZE */
|
||||
25% { transform: rotate(270deg); } /* 1 * ARCSIZE */
|
||||
37.5% { transform: rotate(405deg); } /* 1.5 * ARCSIZE */
|
||||
50% { transform: rotate(540deg); } /* 2 * ARCSIZE */
|
||||
62.5% { transform: rotate(675deg); } /* 2.5 * ARCSIZE */
|
||||
75% { transform: rotate(810deg); } /* 3 * ARCSIZE */
|
||||
87.5% { transform: rotate(945deg); } /* 3.5 * ARCSIZE */
|
||||
to { transform: rotate(1080deg); } /* 4 * ARCSIZE */
|
||||
}
|
||||
|
||||
@-webkit-keyframes blue-fade-in-out {
|
||||
from { opacity: 1; }
|
||||
25% { opacity: 1; }
|
||||
26% { opacity: 0; }
|
||||
89% { opacity: 0; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes blue-fade-in-out {
|
||||
from { opacity: 1; }
|
||||
25% { opacity: 1; }
|
||||
26% { opacity: 0; }
|
||||
89% { opacity: 0; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes red-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
15% { opacity: 0; }
|
||||
25% { opacity: 1; }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes red-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
15% { opacity: 0; }
|
||||
25% { opacity: 1; }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes yellow-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
40% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
75% { opacity: 1; }
|
||||
76% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes yellow-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
40% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
75% { opacity: 1; }
|
||||
76% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes green-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
65% { opacity: 0; }
|
||||
75% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes green-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
65% { opacity: 0; }
|
||||
75% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the gap that appear between the two adjacent div.circle-clipper while the
|
||||
* spinner is rotating (appears on Chrome 38, Safari 7.1, and IE 11).
|
||||
*/
|
||||
.gap-patch {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 45%;
|
||||
width: 10%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
.gap-patch .circle {
|
||||
width: 1000%;
|
||||
left: -450%;
|
||||
}
|
||||
|
||||
.circle-clipper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-color: inherit;
|
||||
|
||||
.circle {
|
||||
width: 200%;
|
||||
height: 100%;
|
||||
border-width: 3px; /* STROKEWIDTH */
|
||||
border-style: solid;
|
||||
border-color: inherit;
|
||||
border-bottom-color: transparent !important;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: none;
|
||||
animation: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.left .circle {
|
||||
left: 0;
|
||||
border-right-color: transparent !important;
|
||||
-webkit-transform: rotate(129deg);
|
||||
transform: rotate(129deg);
|
||||
}
|
||||
&.right .circle {
|
||||
left: -100%;
|
||||
border-left-color: transparent !important;
|
||||
-webkit-transform: rotate(-129deg);
|
||||
transform: rotate(-129deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.active .circle-clipper.left .circle {
|
||||
/* duration: ARCTIME */
|
||||
-webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .circle-clipper.right .circle {
|
||||
/* duration: ARCTIME */
|
||||
-webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes left-spin {
|
||||
from { -webkit-transform: rotate(130deg); }
|
||||
50% { -webkit-transform: rotate(-5deg); }
|
||||
to { -webkit-transform: rotate(130deg); }
|
||||
}
|
||||
|
||||
@keyframes left-spin {
|
||||
from { transform: rotate(130deg); }
|
||||
50% { transform: rotate(-5deg); }
|
||||
to { transform: rotate(130deg); }
|
||||
}
|
||||
|
||||
@-webkit-keyframes right-spin {
|
||||
from { -webkit-transform: rotate(-130deg); }
|
||||
50% { -webkit-transform: rotate(5deg); }
|
||||
to { -webkit-transform: rotate(-130deg); }
|
||||
}
|
||||
|
||||
@keyframes right-spin {
|
||||
from { transform: rotate(-130deg); }
|
||||
50% { transform: rotate(5deg); }
|
||||
to { transform: rotate(-130deg); }
|
||||
}
|
||||
|
||||
#spinnerContainer.cooldown {
|
||||
/* duration: SHRINK_TIME */
|
||||
-webkit-animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade-out {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
34
node_modules/@materializecss/materialize/sass/components/_pulse.scss
generated
vendored
Executable file
34
node_modules/@materializecss/materialize/sass/components/_pulse.scss
generated
vendored
Executable file
|
@ -0,0 +1,34 @@
|
|||
.pulse {
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: inherit;
|
||||
border-radius: inherit;
|
||||
transition: opacity .3s, transform .3s;
|
||||
animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@keyframes pulse-animation {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
}
|
214
node_modules/@materializecss/materialize/sass/components/_sidenav.scss
generated
vendored
Executable file
214
node_modules/@materializecss/materialize/sass/components/_sidenav.scss
generated
vendored
Executable file
|
@ -0,0 +1,214 @@
|
|||
.sidenav {
|
||||
position: fixed;
|
||||
width: $sidenav-width;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
transform: translateX(-100%);
|
||||
height: 100vh;
|
||||
padding-bottom: 60px;
|
||||
background-color: $sidenav-bg-color;
|
||||
z-index: 999;
|
||||
overflow-y: auto;
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
transform: translateX(-105%);
|
||||
|
||||
@extend .z-depth-1;
|
||||
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
transform: translateX(105%);
|
||||
left: auto;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.collapsible {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
float: none;
|
||||
line-height: $sidenav-line-height;
|
||||
|
||||
&.active { background-color: rgba(0,0,0,.05); }
|
||||
}
|
||||
|
||||
li > a {
|
||||
color: $sidenav-font-color;
|
||||
display: block;
|
||||
font-size: $sidenav-font-size;
|
||||
font-weight: 500;
|
||||
height: $sidenav-item-height;
|
||||
line-height: $sidenav-line-height;
|
||||
padding: 0 ($sidenav-padding * 2);
|
||||
|
||||
&:hover { background-color: rgba(0,0,0,.05);}
|
||||
|
||||
&.btn, &.btn-large, &.btn-flat, &.btn-floating {
|
||||
margin: 10px 15px;
|
||||
}
|
||||
|
||||
&.btn,
|
||||
&.btn-large,
|
||||
&.btn-floating { color: $button-raised-color; }
|
||||
&.btn-flat { color: $button-flat-color; }
|
||||
|
||||
&.btn:hover,
|
||||
&.btn-large:hover { background-color: lighten($button-raised-background, 5%); }
|
||||
&.btn-floating:hover { background-color: $button-raised-background; }
|
||||
|
||||
& > i,
|
||||
& > [class^="mdi-"], li > a > [class*="mdi-"],
|
||||
& > i.material-icons {
|
||||
float: left;
|
||||
height: $sidenav-item-height;
|
||||
line-height: $sidenav-line-height;
|
||||
margin: 0 ($sidenav-padding * 2) 0 0;
|
||||
width: $sidenav-item-height * 0.5;
|
||||
color: rgba(0,0,0,.54);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.divider {
|
||||
margin: ($sidenav-padding * 0.5) 0 0 0;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
cursor: initial;
|
||||
pointer-events: none;
|
||||
color: rgba(0,0,0,.54);
|
||||
font-size: $sidenav-font-size;
|
||||
font-weight: 500;
|
||||
line-height: $sidenav-line-height;
|
||||
}
|
||||
|
||||
.user-view {
|
||||
position: relative;
|
||||
padding: ($sidenav-padding * 2) ($sidenav-padding * 2) 0;
|
||||
margin-bottom: $sidenav-padding * 0.5;
|
||||
|
||||
& > a {
|
||||
&:hover { background-color: transparent; }
|
||||
height: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.background {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.circle, .name, .email {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.circle {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.name,
|
||||
.email {
|
||||
font-size: $sidenav-font-size;
|
||||
line-height: $sidenav-line-height * 0.5;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-top: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.email {
|
||||
padding-bottom: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Touch interaction
|
||||
.drag-target {
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
|
||||
// Fixed Sidenav shown
|
||||
.sidenav.sidenav-fixed {
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
left: 0;
|
||||
transform: translateX(0);
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
// Fixed Sidenav hide on smaller
|
||||
@media #{$medium-and-down} {
|
||||
.sidenav {
|
||||
&.sidenav-fixed {
|
||||
transform: translateX(-105%);
|
||||
|
||||
&.right-aligned {
|
||||
transform: translateX(105%);
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
padding: 0 $sidenav-padding;
|
||||
}
|
||||
|
||||
.user-view {
|
||||
padding: $sidenav-padding $sidenav-padding 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sidenav .collapsible-body > ul:not(.collapsible) > li.active,
|
||||
.sidenav.sidenav-fixed .collapsible-body > ul:not(.collapsible) > li.active {
|
||||
background-color: $primary-color;
|
||||
a {
|
||||
color: $sidenav-bg-color;
|
||||
}
|
||||
}
|
||||
.sidenav .collapsible-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.sidenav-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
height: 120vh;
|
||||
background-color: rgba(0,0,0,.5);
|
||||
z-index: 997;
|
||||
display: none;
|
||||
}
|
92
node_modules/@materializecss/materialize/sass/components/_slider.scss
generated
vendored
Executable file
92
node_modules/@materializecss/materialize/sass/components/_slider.scss
generated
vendored
Executable file
|
@ -0,0 +1,92 @@
|
|||
.slider {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
|
||||
// Fullscreen slider
|
||||
&.fullscreen {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
ul.slides {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ul.indicators {
|
||||
z-index: 2;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.slides {
|
||||
background-color: $slider-bg-color;
|
||||
margin: 0;
|
||||
height: 400px;
|
||||
|
||||
li {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.caption {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
left: 15%;
|
||||
width: 70%;
|
||||
opacity: 0;
|
||||
|
||||
p { color: $slider-bg-color-light; }
|
||||
}
|
||||
|
||||
&.active {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.indicators {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
|
||||
.indicator-item {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: 0 12px;
|
||||
background-color: $slider-bg-color-light;
|
||||
|
||||
transition: background-color .3s;
|
||||
border-radius: 50%;
|
||||
|
||||
&.active {
|
||||
background-color: $slider-indicator-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
node_modules/@materializecss/materialize/sass/components/_table_of_contents.scss
generated
vendored
Executable file
33
node_modules/@materializecss/materialize/sass/components/_table_of_contents.scss
generated
vendored
Executable file
|
@ -0,0 +1,33 @@
|
|||
/***************
|
||||
Nav List
|
||||
***************/
|
||||
.table-of-contents {
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 2px 0;
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
font-weight: 300;
|
||||
color: #757575;
|
||||
padding-left: 16px;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
letter-spacing: .4;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
color: lighten(#757575, 20%);
|
||||
padding-left: 15px;
|
||||
border-left: 1px solid $primary-color;
|
||||
}
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
padding-left: 14px;
|
||||
border-left: 2px solid $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
99
node_modules/@materializecss/materialize/sass/components/_tabs.scss
generated
vendored
Executable file
99
node_modules/@materializecss/materialize/sass/components/_tabs.scss
generated
vendored
Executable file
|
@ -0,0 +1,99 @@
|
|||
.tabs {
|
||||
&.tabs-transparent {
|
||||
background-color: transparent;
|
||||
|
||||
.tab a,
|
||||
.tab.disabled a,
|
||||
.tab.disabled a:hover {
|
||||
color: rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
.tab a:hover,
|
||||
.tab a.active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.tabs-fixed-width {
|
||||
display: flex;
|
||||
|
||||
.tab {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
background-color: $tabs-bg-color;
|
||||
margin: 0 auto;
|
||||
white-space: nowrap;
|
||||
|
||||
.tab {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
height: 48px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
|
||||
a {
|
||||
&:focus,
|
||||
&:focus.active {
|
||||
background-color: transparentize($tabs-underline-color, .8);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: transparent;
|
||||
color: $tabs-text-color;
|
||||
}
|
||||
|
||||
color: rgba($tabs-text-color, .7);
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 24px;
|
||||
font-size: 14px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
transition: color .28s ease, background-color .28s ease;
|
||||
}
|
||||
|
||||
&.disabled a,
|
||||
&.disabled a:hover {
|
||||
color: rgba($tabs-text-color, .4);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
.indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background-color: $tabs-underline-color;
|
||||
will-change: left, right;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed Sidenav hide on smaller
|
||||
@media #{$medium-and-down} {
|
||||
.tabs {
|
||||
display: flex;
|
||||
|
||||
.tab {
|
||||
flex-grow: 1;
|
||||
|
||||
a {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
103
node_modules/@materializecss/materialize/sass/components/_tapTarget.scss
generated
vendored
Executable file
103
node_modules/@materializecss/materialize/sass/components/_tapTarget.scss
generated
vendored
Executable file
|
@ -0,0 +1,103 @@
|
|||
.tap-target-wrapper {
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
visibility: hidden;
|
||||
transition: visibility 0s .3s;
|
||||
}
|
||||
|
||||
.tap-target-wrapper.open {
|
||||
visibility: visible;
|
||||
transition: visibility 0s;
|
||||
|
||||
.tap-target {
|
||||
transform: scale(1);
|
||||
opacity: .95;
|
||||
transition:
|
||||
transform .3s cubic-bezier(.42,0,.58,1),
|
||||
opacity .3s cubic-bezier(.42,0,.58,1);
|
||||
}
|
||||
|
||||
.tap-target-wave::before {
|
||||
transform: scale(1);
|
||||
}
|
||||
.tap-target-wave::after {
|
||||
visibility: visible;
|
||||
animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
|
||||
transition:
|
||||
opacity .3s,
|
||||
transform .3s,
|
||||
visibility 0s 1s;
|
||||
}
|
||||
}
|
||||
|
||||
.tap-target {
|
||||
position: absolute;
|
||||
font-size: 1rem;
|
||||
border-radius: 50%;
|
||||
background-color: $primary-color;
|
||||
box-shadow: 0 20px 20px 0 rgba(0,0,0,0.14), 0 10px 50px 0 rgba(0,0,0,0.12), 0 30px 10px -20px rgba(0,0,0,0.2);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
transition:
|
||||
transform .3s cubic-bezier(.42,0,.58,1),
|
||||
opacity .3s cubic-bezier(.42,0,.58,1);
|
||||
}
|
||||
|
||||
.tap-target-content {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.tap-target-wave {
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
&::before {
|
||||
transform: scale(0);
|
||||
transition: transform .3s;
|
||||
}
|
||||
&::after {
|
||||
visibility: hidden;
|
||||
transition:
|
||||
opacity .3s,
|
||||
transform .3s,
|
||||
visibility 0s;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.tap-target-origin {
|
||||
&:not(.btn),
|
||||
&:not(.btn):hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
|
||||
z-index: 10002;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.tap-target, .tap-target-wrapper {
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
}
|
||||
}
|
183
node_modules/@materializecss/materialize/sass/components/_timepicker.scss
generated
vendored
Executable file
183
node_modules/@materializecss/materialize/sass/components/_timepicker.scss
generated
vendored
Executable file
|
@ -0,0 +1,183 @@
|
|||
/* Timepicker Containers */
|
||||
.timepicker-modal {
|
||||
max-width: 325px;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.timepicker-container.modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Clock Digital Display */
|
||||
.timepicker-digital-display {
|
||||
flex: 1 auto;
|
||||
background-color: $secondary-color;
|
||||
padding: 10px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.timepicker-text-container {
|
||||
font-size: 4rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.timepicker-span-hours,
|
||||
.timepicker-span-minutes,
|
||||
.timepicker-span-am-pm div {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.timepicker-span-hours {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.timepicker-span-minutes {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.timepicker-display-am-pm {
|
||||
font-size: 1.3rem;
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
/* Analog Clock Display */
|
||||
.timepicker-analog-display {
|
||||
flex: 2.5 auto;
|
||||
}
|
||||
|
||||
.timepicker-plate {
|
||||
background-color: $timepicker-clock-plate-bg;
|
||||
border-radius: 50%;
|
||||
width: 270px;
|
||||
height: 270px;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.timepicker-canvas,
|
||||
.timepicker-dial {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.timepicker-minutes {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.timepicker-tick {
|
||||
border-radius: 50%;
|
||||
color: $timepicker-clock-color;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.timepicker-tick.active,
|
||||
.timepicker-tick:hover {
|
||||
background-color: transparentize($secondary-color, .75);
|
||||
}
|
||||
.timepicker-dial {
|
||||
transition: transform 350ms, opacity 350ms;
|
||||
}
|
||||
.timepicker-dial-out {
|
||||
&.timepicker-hours {
|
||||
transform: scale(1.1, 1.1);
|
||||
}
|
||||
|
||||
&.timepicker-minutes {
|
||||
transform: scale(.8, .8);
|
||||
}
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
.timepicker-canvas {
|
||||
transition: opacity 175ms;
|
||||
|
||||
line {
|
||||
stroke: $secondary-color;
|
||||
stroke-width: 4;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
}
|
||||
.timepicker-canvas-out {
|
||||
opacity: 0.25;
|
||||
}
|
||||
.timepicker-canvas-bearing {
|
||||
stroke: none;
|
||||
fill: $secondary-color;
|
||||
}
|
||||
.timepicker-canvas-bg {
|
||||
stroke: none;
|
||||
fill: $secondary-color;
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
.timepicker-footer {
|
||||
margin: 0 auto;
|
||||
padding: 5px 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.timepicker-clear {
|
||||
color: $error-color;
|
||||
}
|
||||
|
||||
.timepicker-close {
|
||||
color: $secondary-color;
|
||||
}
|
||||
|
||||
.timepicker-clear,
|
||||
.timepicker-close {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* Media Queries */
|
||||
@media #{$medium-and-up} {
|
||||
.timepicker-modal {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.timepicker-container.modal-content {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.timepicker-text-container {
|
||||
top: 32%;
|
||||
}
|
||||
|
||||
.timepicker-display-am-pm {
|
||||
position: relative;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
text-align: center;
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
}
|
58
node_modules/@materializecss/materialize/sass/components/_toast.scss
generated
vendored
Executable file
58
node_modules/@materializecss/materialize/sass/components/_toast.scss
generated
vendored
Executable file
|
@ -0,0 +1,58 @@
|
|||
#toast-container {
|
||||
display:block;
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
|
||||
@media #{$small-and-down} {
|
||||
min-width: 100%;
|
||||
bottom: 0%;
|
||||
}
|
||||
@media #{$medium-only} {
|
||||
left: 5%;
|
||||
bottom: 7%;
|
||||
max-width: 90%;
|
||||
}
|
||||
@media #{$large-and-up} {
|
||||
top: 10%;
|
||||
right: 7%;
|
||||
max-width: 86%;
|
||||
}
|
||||
}
|
||||
|
||||
.toast {
|
||||
@extend .z-depth-1;
|
||||
border-radius: 2px;
|
||||
top: 35px;
|
||||
width: auto;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
max-width:100%;
|
||||
height: auto;
|
||||
min-height: $toast-height;
|
||||
line-height: 1.5em;
|
||||
background-color: $toast-color;
|
||||
padding: 10px 25px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 300;
|
||||
color: $toast-text-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: default;
|
||||
|
||||
.toast-action {
|
||||
color: $toast-action-color;
|
||||
font-weight: 500;
|
||||
margin-right: -25px;
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
&.rounded{
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
@media #{$small-and-down} {
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
32
node_modules/@materializecss/materialize/sass/components/_tooltip.scss
generated
vendored
Executable file
32
node_modules/@materializecss/materialize/sass/components/_tooltip.scss
generated
vendored
Executable file
|
@ -0,0 +1,32 @@
|
|||
.material-tooltip {
|
||||
padding: 10px 8px;
|
||||
font-size: 1rem;
|
||||
z-index: 2000;
|
||||
background-color: transparent;
|
||||
border-radius: 2px;
|
||||
color: #fff;
|
||||
min-height: 36px;
|
||||
line-height: 120%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
max-width: calc(100% - 4px);
|
||||
overflow: hidden;
|
||||
left: 0;
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
background-color: #323232;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
height: 7px;
|
||||
width: 14px;
|
||||
border-radius: 0 0 50% 50%;
|
||||
background-color: #323232;
|
||||
z-index: -1;
|
||||
transform-origin: 50% 0%;
|
||||
visibility: hidden;
|
||||
}
|
13
node_modules/@materializecss/materialize/sass/components/_transitions.scss
generated
vendored
Executable file
13
node_modules/@materializecss/materialize/sass/components/_transitions.scss
generated
vendored
Executable file
|
@ -0,0 +1,13 @@
|
|||
// Scale transition
|
||||
.scale-transition {
|
||||
&.scale-out {
|
||||
transform: scale(0);
|
||||
transition: transform .2s !important;
|
||||
}
|
||||
|
||||
&.scale-in {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
transition: transform .3s cubic-bezier(0.53, 0.01, 0.36, 1.63) !important;
|
||||
}
|
62
node_modules/@materializecss/materialize/sass/components/_typography.scss
generated
vendored
Executable file
62
node_modules/@materializecss/materialize/sass/components/_typography.scss
generated
vendored
Executable file
|
@ -0,0 +1,62 @@
|
|||
|
||||
@use "sass:math";
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
html{
|
||||
line-height: 1.5;
|
||||
|
||||
@media only screen and (min-width: 0) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $medium-screen-up) {
|
||||
font-size: 14.5px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $large-screen-up) {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
font-family: $font-stack;
|
||||
font-weight: normal;
|
||||
color: $off-black;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
// Header Styles
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
|
||||
h1 { font-size: $h1-fontsize; line-height: 110%; margin: math.div($h1-fontsize, 1.5) 0 math.div($h1-fontsize, 2.5) 0;}
|
||||
h2 { font-size: $h2-fontsize; line-height: 110%; margin: math.div($h2-fontsize, 1.5) 0 math.div($h2-fontsize, 2.5) 0;}
|
||||
h3 { font-size: $h3-fontsize; line-height: 110%; margin: math.div($h3-fontsize, 1.5) 0 math.div($h3-fontsize, 2.5) 0;}
|
||||
h4 { font-size: $h4-fontsize; line-height: 110%; margin: math.div($h4-fontsize, 1.5) 0 math.div($h4-fontsize, 2.5) 0;}
|
||||
h5 { font-size: $h5-fontsize; line-height: 110%; margin: math.div($h5-fontsize, 1.5) 0 math.div($h5-fontsize, 2.5) 0;}
|
||||
h6 { font-size: $h6-fontsize; line-height: 110%; margin: math.div($h6-fontsize, 1.5) 0 math.div($h6-fontsize, 2.5) 0;}
|
||||
|
||||
// Text Styles
|
||||
em { font-style: italic; }
|
||||
strong { font-weight: 500; }
|
||||
small { font-size: 75%; }
|
||||
.light { font-weight: 300; }
|
||||
.thin { font-weight: 200; }
|
||||
|
||||
|
||||
.flow-text{
|
||||
$i: 0;
|
||||
@while $i <= $intervals {
|
||||
@media only screen and (min-width : 360 + ($i * $interval-size)) {
|
||||
font-size: 1.2rem * (1 + (.02 * $i));
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
// Handle below 360px screen
|
||||
@media only screen and (max-width: 360px) {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
352
node_modules/@materializecss/materialize/sass/components/_variables.scss
generated
vendored
Executable file
352
node_modules/@materializecss/materialize/sass/components/_variables.scss
generated
vendored
Executable file
|
@ -0,0 +1,352 @@
|
|||
// ==========================================================================
|
||||
// Materialize variables
|
||||
// ==========================================================================
|
||||
//
|
||||
// Table of Contents:
|
||||
//
|
||||
// 1. Colors
|
||||
// 2. Badges
|
||||
// 3. Buttons
|
||||
// 4. Cards
|
||||
// 5. Carousel
|
||||
// 6. Collapsible
|
||||
// 7. Chips
|
||||
// 8. Date + Time Picker
|
||||
// 9. Dropdown
|
||||
// 10. Forms
|
||||
// 11. Global
|
||||
// 12. Grid
|
||||
// 13. Navigation Bar
|
||||
// 14. Side Navigation
|
||||
// 15. Photo Slider
|
||||
// 16. Spinners | Loaders
|
||||
// 17. Tabs
|
||||
// 18. Tables
|
||||
// 19. Toasts
|
||||
// 20. Typography
|
||||
// 21. Footer
|
||||
// 22. Flow Text
|
||||
// 23. Collections
|
||||
// 24. Progress Bar
|
||||
|
||||
|
||||
|
||||
// 1. Colors
|
||||
// ==========================================================================
|
||||
|
||||
@use "sass:math";
|
||||
|
||||
$primary-color: color("materialize-red", "lighten-2") !default;
|
||||
$primary-color-light: lighten($primary-color, 15%) !default;
|
||||
$primary-color-dark: darken($primary-color, 15%) !default;
|
||||
|
||||
$secondary-color: color("teal", "lighten-1") !default;
|
||||
$success-color: color("green", "base") !default;
|
||||
$error-color: color("red", "base") !default;
|
||||
$link-color: color("light-blue", "darken-1") !default;
|
||||
|
||||
|
||||
// 2. Badges
|
||||
// ==========================================================================
|
||||
|
||||
$badge-bg-color: $secondary-color !default;
|
||||
$badge-height: 22px !default;
|
||||
|
||||
|
||||
// 3. Buttons
|
||||
// ==========================================================================
|
||||
|
||||
// Shared styles
|
||||
$button-border: none !default;
|
||||
$button-background-focus: lighten($secondary-color, 4%) !default;
|
||||
$button-font-size: 14px !default;
|
||||
$button-icon-font-size: 1.3rem !default;
|
||||
$button-height: 36px !default;
|
||||
$button-padding: 0 16px !default;
|
||||
$button-radius: 2px !default;
|
||||
|
||||
// Disabled styles
|
||||
$button-disabled-background: #DFDFDF !default;
|
||||
$button-disabled-color: #9F9F9F !default;
|
||||
|
||||
// Raised buttons
|
||||
$button-raised-background: $secondary-color !default;
|
||||
$button-raised-background-hover: lighten($button-raised-background, 5%) !default;
|
||||
$button-raised-color: #fff !default;
|
||||
|
||||
// Large buttons
|
||||
$button-large-font-size: 15px !default;
|
||||
$button-large-icon-font-size: 1.6rem !default;
|
||||
$button-large-height: $button-height * 1.5 !default;
|
||||
$button-floating-large-size: 56px !default;
|
||||
|
||||
// Small buttons
|
||||
$button-small-font-size: 13px !default;
|
||||
$button-small-icon-font-size: 1.2rem !default;
|
||||
$button-small-height: $button-height * .9 !default;
|
||||
$button-floating-small-size: $button-height * .9 !default;
|
||||
|
||||
// Flat buttons
|
||||
$button-flat-color: #343434 !default;
|
||||
$button-flat-disabled-color: lighten(#999, 10%) !default;
|
||||
|
||||
// Floating buttons
|
||||
$button-floating-background: $secondary-color !default;
|
||||
$button-floating-background-hover: $button-floating-background !default;
|
||||
$button-floating-color: #fff !default;
|
||||
$button-floating-size: 40px !default;
|
||||
$button-floating-radius: 50% !default;
|
||||
|
||||
|
||||
// 4. Cards
|
||||
// ==========================================================================
|
||||
|
||||
$card-padding: 24px !default;
|
||||
$card-bg-color: #fff !default;
|
||||
$card-link-color: color("orange", "accent-2") !default;
|
||||
$card-link-color-light: lighten($card-link-color, 20%) !default;
|
||||
|
||||
|
||||
// 5. Carousel
|
||||
// ==========================================================================
|
||||
|
||||
$carousel-height: 400px !default;
|
||||
$carousel-item-height: $carousel-height * 0.5 !default;
|
||||
$carousel-item-width: $carousel-item-height !default;
|
||||
|
||||
|
||||
// 6. Collapsible
|
||||
// ==========================================================================
|
||||
|
||||
$collapsible-height: 3rem !default;
|
||||
$collapsible-line-height: $collapsible-height !default;
|
||||
$collapsible-header-color: #fff !default;
|
||||
$collapsible-border-color: #ddd !default;
|
||||
|
||||
|
||||
// 7. Chips
|
||||
// ==========================================================================
|
||||
|
||||
$chip-bg-color: #e4e4e4 !default;
|
||||
$chip-border-color: #9e9e9e !default;
|
||||
$chip-selected-color: #26a69a !default;
|
||||
$chip-margin: 5px !default;
|
||||
|
||||
|
||||
// 8. Date + Time Picker
|
||||
// ==========================================================================
|
||||
|
||||
$datepicker-display-font-size: 2.8rem;
|
||||
$datepicker-calendar-header-color: #999;
|
||||
$datepicker-weekday-color: rgba(0, 0, 0, .87) !default;
|
||||
$datepicker-weekday-bg: darken($secondary-color, 7%) !default;
|
||||
$datepicker-date-bg: $secondary-color !default;
|
||||
$datepicker-year: rgba(255, 255, 255, .7) !default;
|
||||
$datepicker-focus: rgba(0,0,0, .05) !default;
|
||||
$datepicker-selected: $secondary-color !default;
|
||||
$datepicker-selected-outfocus: desaturate(lighten($secondary-color, 35%), 15%) !default;
|
||||
$datepicker-day-focus: transparentize(desaturate($secondary-color, 5%), .75) !default;
|
||||
$datepicker-disabled-day-color: rgba(0, 0, 0, .3) !default;
|
||||
|
||||
$timepicker-clock-color: rgba(0, 0, 0, .87) !default;
|
||||
$timepicker-clock-plate-bg: #eee !default;
|
||||
|
||||
|
||||
// 9. Dropdown
|
||||
// ==========================================================================
|
||||
|
||||
$dropdown-bg-color: #fff !default;
|
||||
$dropdown-hover-bg-color: #eee !default;
|
||||
$dropdown-color: $secondary-color !default;
|
||||
$dropdown-item-height: 50px !default;
|
||||
|
||||
|
||||
// 10. Forms
|
||||
// ==========================================================================
|
||||
|
||||
// Text Inputs + Textarea
|
||||
$input-height: 3rem !default;
|
||||
$input-border-color: color("grey", "base") !default;
|
||||
$input-border: 1px solid $input-border-color !default;
|
||||
$input-background: #fff !default;
|
||||
$input-error-color: $error-color !default;
|
||||
$input-success-color: $success-color !default;
|
||||
$input-focus-color: $secondary-color !default;
|
||||
$input-font-size: 16px !default;
|
||||
$input-margin-bottom: 8px;
|
||||
$input-margin: 0 0 $input-margin-bottom 0 !default;
|
||||
$input-padding: 0 !default;
|
||||
$label-font-size: .8rem !default;
|
||||
$input-disabled-color: rgba(0,0,0, .42) !default;
|
||||
$input-disabled-solid-color: #949494 !default;
|
||||
$input-disabled-border: 1px dotted $input-disabled-color !default;
|
||||
$input-invalid-border: 1px solid $input-error-color !default;
|
||||
$input-icon-size: 2rem;
|
||||
$placeholder-text-color: lighten($input-border-color, 20%) !default;
|
||||
|
||||
// Radio Buttons
|
||||
$radio-fill-color: $secondary-color !default;
|
||||
$radio-empty-color: #5a5a5a !default;
|
||||
$radio-border: 2px solid $radio-fill-color !default;
|
||||
|
||||
// Range
|
||||
$range-height: 14px !default;
|
||||
$range-width: 14px !default;
|
||||
$track-height: 3px !default;
|
||||
|
||||
// Select
|
||||
$select-border: 1px solid #f2f2f2 !default;
|
||||
$select-background: rgba(255, 255, 255, 0.90) !default;
|
||||
$select-focus: 1px solid lighten($secondary-color, 47%) !default;
|
||||
$select-option-hover: rgba(0,0,0,.08) !default;
|
||||
$select-option-focus: rgba(0,0,0,.08) !default;
|
||||
$select-option-selected: rgba(0,0,0,.03) !default;
|
||||
$select-padding: 5px !default;
|
||||
$select-radius: 2px !default;
|
||||
$select-disabled-color: rgba(0,0,0,.3) !default;
|
||||
|
||||
// Switches
|
||||
$switch-bg-color: $secondary-color !default;
|
||||
$switch-checked-lever-bg: desaturate(lighten($switch-bg-color, 25%), 25%) !default;
|
||||
$switch-unchecked-bg: #F1F1F1 !default;
|
||||
$switch-unchecked-lever-bg: rgba(0,0,0,.38) !default;
|
||||
$switch-radius: 15px !default;
|
||||
|
||||
|
||||
// 11. Global
|
||||
// ==========================================================================
|
||||
|
||||
// Media Query Ranges
|
||||
$small-screen-up: 601px !default;
|
||||
$medium-screen-up: 993px !default;
|
||||
$large-screen-up: 1201px !default;
|
||||
$small-screen: 600.99px !default;
|
||||
$medium-screen: 992.99px !default;
|
||||
$large-screen: 1200.99px !default;
|
||||
|
||||
$medium-and-up: "only screen and (min-width : #{$small-screen-up})" !default;
|
||||
$large-and-up: "only screen and (min-width : #{$medium-screen-up})" !default;
|
||||
$extra-large-and-up: "only screen and (min-width : #{$large-screen-up})" !default;
|
||||
$small-and-down: "only screen and (max-width : #{$small-screen})" !default;
|
||||
$medium-and-down: "only screen and (max-width : #{$medium-screen})" !default;
|
||||
$medium-only: "only screen and (min-width : #{$small-screen-up}) and (max-width : #{$medium-screen})" !default;
|
||||
|
||||
|
||||
// 12. Grid
|
||||
// ==========================================================================
|
||||
|
||||
$num-cols: 12 !default;
|
||||
$gutter-width: 1.5rem !default;
|
||||
$element-top-margin: math.div($gutter-width, 3) !default;
|
||||
$element-bottom-margin: math.div($gutter-width*2, 3) !default;
|
||||
|
||||
|
||||
// 13. Navigation Bar
|
||||
// ==========================================================================
|
||||
|
||||
$navbar-height: 64px !default;
|
||||
$navbar-line-height: $navbar-height !default;
|
||||
$navbar-height-mobile: 56px !default;
|
||||
$navbar-line-height-mobile: $navbar-height-mobile !default;
|
||||
$navbar-font-size: 1rem !default;
|
||||
$navbar-font-color: #fff !default;
|
||||
$navbar-brand-font-size: 2.1rem !default;
|
||||
|
||||
// 14. Side Navigation
|
||||
// ==========================================================================
|
||||
|
||||
$sidenav-width: 300px !default;
|
||||
$sidenav-font-size: 14px !default;
|
||||
$sidenav-font-color: rgba(0,0,0,.87) !default;
|
||||
$sidenav-bg-color: #fff !default;
|
||||
$sidenav-padding: 16px !default;
|
||||
$sidenav-item-height: 48px !default;
|
||||
$sidenav-line-height: $sidenav-item-height !default;
|
||||
|
||||
|
||||
// 15. Photo Slider
|
||||
// ==========================================================================
|
||||
|
||||
$slider-bg-color: color('grey', 'base') !default;
|
||||
$slider-bg-color-light: color('grey', 'lighten-2') !default;
|
||||
$slider-indicator-color: color('green', 'base') !default;
|
||||
|
||||
|
||||
// 16. Spinners | Loaders
|
||||
// ==========================================================================
|
||||
|
||||
$spinner-default-color: $secondary-color !default;
|
||||
|
||||
|
||||
// 17. Tabs
|
||||
// ==========================================================================
|
||||
|
||||
$tabs-underline-color: $primary-color-light !default;
|
||||
$tabs-text-color: $primary-color !default;
|
||||
$tabs-bg-color: #fff !default;
|
||||
|
||||
|
||||
// 18. Tables
|
||||
// ==========================================================================
|
||||
|
||||
$table-border-color: rgba(0,0,0,.12) !default;
|
||||
$table-striped-color: rgba(242, 242, 242, 0.5) !default;
|
||||
|
||||
|
||||
// 19. Toasts
|
||||
// ==========================================================================
|
||||
|
||||
$toast-height: 48px !default;
|
||||
$toast-color: #323232 !default;
|
||||
$toast-text-color: #fff !default;
|
||||
$toast-action-color: #eeff41;
|
||||
|
||||
|
||||
// 20. Typography
|
||||
// ==========================================================================
|
||||
|
||||
$font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !default;
|
||||
$off-black: rgba(0, 0, 0, 0.87) !default;
|
||||
// Header Styles
|
||||
$h1-fontsize: 4.2rem !default;
|
||||
$h2-fontsize: 3.56rem !default;
|
||||
$h3-fontsize: 2.92rem !default;
|
||||
$h4-fontsize: 2.28rem !default;
|
||||
$h5-fontsize: 1.64rem !default;
|
||||
$h6-fontsize: 1.15rem !default;
|
||||
|
||||
|
||||
// 21. Footer
|
||||
// ==========================================================================
|
||||
|
||||
$footer-font-color: #fff !default;
|
||||
$footer-bg-color: $primary-color !default;
|
||||
$footer-copyright-font-color: rgba(255,255,255,.8) !default;
|
||||
$footer-copyright-bg-color: rgba(51,51,51,.08) !default;
|
||||
|
||||
|
||||
// 22. Flow Text
|
||||
// ==========================================================================
|
||||
|
||||
$range : $large-screen - $small-screen !default;
|
||||
$intervals: 20 !default;
|
||||
$interval-size: math.div($range, $intervals) !default;
|
||||
|
||||
|
||||
// 23. Collections
|
||||
// ==========================================================================
|
||||
|
||||
$collection-border-color: #e0e0e0 !default;
|
||||
$collection-bg-color: #fff !default;
|
||||
$collection-active-bg-color: $secondary-color !default;
|
||||
$collection-active-color: lighten($secondary-color, 55%) !default;
|
||||
$collection-hover-bg-color: #ddd !default;
|
||||
$collection-link-color: $secondary-color !default;
|
||||
$collection-line-height: 1.5rem !default;
|
||||
$collection-border-radius: 2px !default;
|
||||
|
||||
|
||||
// 24. Progress Bar
|
||||
// ==========================================================================
|
||||
|
||||
$progress-bar-color: $secondary-color !default;
|
187
node_modules/@materializecss/materialize/sass/components/_waves.scss
generated
vendored
Executable file
187
node_modules/@materializecss/materialize/sass/components/_waves.scss
generated
vendored
Executable file
|
@ -0,0 +1,187 @@
|
|||
/*!
|
||||
* Waves v0.7.6
|
||||
* http://fian.my.id/Waves
|
||||
*
|
||||
* Copyright 2014-2018 Alfiana E. Sibuea and other contributors
|
||||
* Released under the MIT license
|
||||
* https://github.com/fians/Waves/blob/master/LICENSE */
|
||||
|
||||
@mixin waves-transition($transition){
|
||||
-webkit-transition: $transition;
|
||||
-moz-transition: $transition;
|
||||
-o-transition: $transition;
|
||||
transition: $transition;
|
||||
}
|
||||
|
||||
@mixin waves-transform($string){
|
||||
-webkit-transform: $string;
|
||||
-moz-transform: $string;
|
||||
-ms-transform: $string;
|
||||
-o-transform: $string;
|
||||
transform: $string;
|
||||
}
|
||||
|
||||
@mixin waves-box-shadow($shadow){
|
||||
-webkit-box-shadow: $shadow;
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
|
||||
.waves-effect {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
.waves-ripple {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-top:-50px;
|
||||
margin-left:-50px;
|
||||
opacity: 0;
|
||||
background: rgba(0,0,0,0.2);
|
||||
$gradient: rgba(0,0,0,0.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%;
|
||||
background: -webkit-radial-gradient($gradient);
|
||||
background: -o-radial-gradient($gradient);
|
||||
background: -moz-radial-gradient($gradient);
|
||||
background: radial-gradient($gradient);
|
||||
@include waves-transition(all 0.5s ease-out);
|
||||
-webkit-transition-property: -webkit-transform, opacity;
|
||||
-moz-transition-property: -moz-transform, opacity;
|
||||
-o-transition-property: -o-transform, opacity;
|
||||
transition-property: transform, opacity;
|
||||
@include waves-transform(scale(0) translate(0,0));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.waves-light .waves-ripple {
|
||||
background: rgba(255,255,255,0.4);
|
||||
$gradient: rgba(255,255,255,0.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%;
|
||||
background: -webkit-radial-gradient($gradient);
|
||||
background: -o-radial-gradient($gradient);
|
||||
background: -moz-radial-gradient($gradient);
|
||||
background: radial-gradient($gradient);
|
||||
}
|
||||
|
||||
&.waves-classic .waves-ripple {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
&.waves-classic.waves-light .waves-ripple {
|
||||
background: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
// Waves Colors
|
||||
&.waves-light .waves-ripple {
|
||||
background-color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
&.waves-red .waves-ripple {
|
||||
background-color: rgba(244, 67, 54, .70);
|
||||
}
|
||||
&.waves-yellow .waves-ripple {
|
||||
background-color: rgba(255, 235, 59, .70);
|
||||
}
|
||||
&.waves-orange .waves-ripple {
|
||||
background-color: rgba(255, 152, 0, .70);
|
||||
}
|
||||
&.waves-purple .waves-ripple {
|
||||
background-color: rgba(156, 39, 176, 0.70);
|
||||
}
|
||||
&.waves-green .waves-ripple {
|
||||
background-color: rgba(76, 175, 80, 0.70);
|
||||
}
|
||||
&.waves-teal .waves-ripple {
|
||||
background-color: rgba(0, 150, 136, 0.70);
|
||||
}
|
||||
|
||||
// Style input button bug.
|
||||
input[type="button"], input[type="reset"], input[type="submit"] {
|
||||
border: 0;
|
||||
font-style: normal;
|
||||
font-size: inherit;
|
||||
text-transform: inherit;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.waves-notransition {
|
||||
@include waves-transition(none #{"!important"});
|
||||
}
|
||||
|
||||
.waves-button,
|
||||
.waves-circle {
|
||||
@include waves-transform(translateZ(0));
|
||||
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
|
||||
}
|
||||
|
||||
.waves-button,
|
||||
.waves-button:hover,
|
||||
.waves-button:visited,
|
||||
.waves-button-input {
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
font-size: 1em;
|
||||
line-height:1em;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.waves-button {
|
||||
padding: 0.85em 1.1em;
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
|
||||
.waves-button-input {
|
||||
margin: 0;
|
||||
padding: 0.85em 1.1em;
|
||||
}
|
||||
|
||||
.waves-input-wrapper {
|
||||
border-radius: 0.2em;
|
||||
vertical-align: bottom;
|
||||
|
||||
&.waves-button {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.waves-button-input {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.waves-circle {
|
||||
text-align: center;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
line-height: 2.5em;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.waves-float {
|
||||
-webkit-mask-image: none;
|
||||
@include waves-box-shadow(0px 1px 1.5px 1px rgba(0, 0, 0, 0.12));
|
||||
@include waves-transition(all 300ms);
|
||||
|
||||
&:active {
|
||||
@include waves-box-shadow(0px 8px 20px 1px rgba(0, 0, 0, 0.30));
|
||||
}
|
||||
}
|
||||
|
||||
.waves-block {
|
||||
display: block;
|
||||
}
|
200
node_modules/@materializecss/materialize/sass/components/forms/_checkboxes.scss
generated
vendored
Executable file
200
node_modules/@materializecss/materialize/sass/components/forms/_checkboxes.scss
generated
vendored
Executable file
|
@ -0,0 +1,200 @@
|
|||
/* Checkboxes
|
||||
========================================================================== */
|
||||
|
||||
/* Remove default checkbox */
|
||||
[type="checkbox"]:not(:checked),
|
||||
[type="checkbox"]:checked {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Checkbox Styles
|
||||
[type="checkbox"] {
|
||||
// Text Label Style
|
||||
+ span:not(.lever) {
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 1rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* checkbox aspect */
|
||||
+ span:not(.lever):before,
|
||||
&:not(.filled-in) + span:not(.lever):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
z-index: 0;
|
||||
border: 2px solid $radio-empty-color;
|
||||
border-radius: 1px;
|
||||
margin-top: 3px;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
&:not(.filled-in) + span:not(.lever):after {
|
||||
border: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
&:not(:checked):disabled + span:not(.lever):before {
|
||||
border: none;
|
||||
background-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
// Focused styles
|
||||
&.tabbed:focus + span:not(.lever):after {
|
||||
transform: scale(1);
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 10px rgba(0,0,0,.1);
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked {
|
||||
+ span:not(.lever):before {
|
||||
top: -4px;
|
||||
left: -5px;
|
||||
width: 12px;
|
||||
height: 22px;
|
||||
border-top: 2px solid transparent;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: $radio-border;
|
||||
border-bottom: $radio-border;
|
||||
transform: rotate(40deg);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
&:disabled + span:before {
|
||||
border-right: 2px solid $input-disabled-color;
|
||||
border-bottom: 2px solid $input-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
/* Indeterminate checkbox */
|
||||
[type="checkbox"]:indeterminate {
|
||||
+ span:not(.lever):before {
|
||||
top: -11px;
|
||||
left: -12px;
|
||||
width: 10px;
|
||||
height: 22px;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: $radio-border;
|
||||
border-bottom: none;
|
||||
transform: rotate(90deg);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
// Disabled indeterminate
|
||||
&:disabled + span:not(.lever):before {
|
||||
border-right: 2px solid $input-disabled-color;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// Filled in Style
|
||||
[type="checkbox"].filled-in {
|
||||
// General
|
||||
+ span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
+ span:not(.lever):before,
|
||||
+ span:not(.lever):after {
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
/* .1s delay is for check animation */
|
||||
transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// Unchecked style
|
||||
&:not(:checked) + span:not(.lever):before {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 3px solid transparent;
|
||||
left: 6px;
|
||||
top: 10px;
|
||||
transform: rotateZ(37deg);
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
&:not(:checked) + span:not(.lever):after {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: transparent;
|
||||
border: 2px solid $radio-empty-color;
|
||||
top: 0px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
// Checked style
|
||||
&:checked {
|
||||
+ span:not(.lever):before {
|
||||
top: 0;
|
||||
left: 1px;
|
||||
width: 8px;
|
||||
height: 13px;
|
||||
border-top: 2px solid transparent;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: 2px solid $input-background;
|
||||
border-bottom: 2px solid $input-background;
|
||||
transform: rotateZ(37deg);
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
+ span:not(.lever):after {
|
||||
top: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid $secondary-color;
|
||||
background-color: $secondary-color;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Focused styles
|
||||
&.tabbed:focus + span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
border-color: $radio-empty-color;
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
&.tabbed:checked:focus + span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
background-color: $secondary-color;
|
||||
border-color: $secondary-color;
|
||||
}
|
||||
|
||||
// Disabled style
|
||||
&:disabled:not(:checked) + span:not(.lever):before {
|
||||
background-color: transparent;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
&:disabled:not(:checked) + span:not(.lever):after {
|
||||
border-color: transparent;
|
||||
background-color: $input-disabled-solid-color;
|
||||
}
|
||||
|
||||
&:disabled:checked + span:not(.lever):before {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:disabled:checked + span:not(.lever):after {
|
||||
background-color: $input-disabled-solid-color;
|
||||
border-color: $input-disabled-solid-color;
|
||||
}
|
||||
}
|
44
node_modules/@materializecss/materialize/sass/components/forms/_file-input.scss
generated
vendored
Executable file
44
node_modules/@materializecss/materialize/sass/components/forms/_file-input.scss
generated
vendored
Executable file
|
@ -0,0 +1,44 @@
|
|||
/* File Input
|
||||
========================================================================== */
|
||||
|
||||
.file-field {
|
||||
position: relative;
|
||||
|
||||
.file-path-wrapper {
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
input.file-path { width: 100%; }
|
||||
|
||||
.btn {
|
||||
float: left;
|
||||
height: $input-height;
|
||||
line-height: $input-height;
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=file] {
|
||||
|
||||
// Needed to override webkit button
|
||||
&::-webkit-file-upload-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
}
|
22
node_modules/@materializecss/materialize/sass/components/forms/_forms.scss
generated
vendored
Executable file
22
node_modules/@materializecss/materialize/sass/components/forms/_forms.scss
generated
vendored
Executable file
|
@ -0,0 +1,22 @@
|
|||
// Remove Focus Boxes
|
||||
select:focus {
|
||||
outline: $select-focus;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: none;
|
||||
background-color: $button-background-focus;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: $label-font-size;
|
||||
color: $input-border-color;
|
||||
}
|
||||
|
||||
@import 'input-fields';
|
||||
@import 'radio-buttons';
|
||||
@import 'checkboxes';
|
||||
@import 'switches';
|
||||
@import 'select';
|
||||
@import 'file-input';
|
||||
@import 'range';
|
379
node_modules/@materializecss/materialize/sass/components/forms/_input-fields.scss
generated
vendored
Executable file
379
node_modules/@materializecss/materialize/sass/components/forms/_input-fields.scss
generated
vendored
Executable file
|
@ -0,0 +1,379 @@
|
|||
/* Text Inputs + Textarea
|
||||
========================================================================== */
|
||||
|
||||
/* Style Placeholders */
|
||||
|
||||
::placeholder {
|
||||
color: $placeholder-text-color;
|
||||
}
|
||||
|
||||
/* Text inputs */
|
||||
|
||||
input:not([type]):not(.browser-default),
|
||||
input[type=text]:not(.browser-default),
|
||||
input[type=password]:not(.browser-default),
|
||||
input[type=email]:not(.browser-default),
|
||||
input[type=url]:not(.browser-default),
|
||||
input[type=time]:not(.browser-default),
|
||||
input[type=date]:not(.browser-default),
|
||||
input[type=datetime]:not(.browser-default),
|
||||
input[type=datetime-local]:not(.browser-default),
|
||||
input[type=tel]:not(.browser-default),
|
||||
input[type=number]:not(.browser-default),
|
||||
input[type=search]:not(.browser-default),
|
||||
textarea.materialize-textarea {
|
||||
|
||||
// General Styles
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-bottom: $input-border;
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
height: $input-height;
|
||||
width: 100%;
|
||||
font-size: $input-font-size;
|
||||
margin: $input-margin;
|
||||
padding: $input-padding;
|
||||
box-shadow: none;
|
||||
box-sizing: content-box;
|
||||
transition: box-shadow .3s, border .3s;
|
||||
|
||||
// Disabled input style
|
||||
&:disabled,
|
||||
&[readonly="readonly"] {
|
||||
color: $input-disabled-color;
|
||||
border-bottom: $input-disabled-border;
|
||||
}
|
||||
|
||||
// Disabled label style
|
||||
&:disabled+label,
|
||||
&[readonly="readonly"]+label {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
// Focused input style
|
||||
&:focus:not([readonly]) {
|
||||
border-bottom: 1px solid $input-focus-color;
|
||||
box-shadow: 0 1px 0 0 $input-focus-color;
|
||||
}
|
||||
|
||||
// Focused label style
|
||||
&:focus:not([readonly])+label {
|
||||
color: $input-focus-color;
|
||||
}
|
||||
|
||||
// Hide helper text on data message
|
||||
&.valid ~ .helper-text[data-success],
|
||||
&:focus.valid ~ .helper-text[data-success],
|
||||
&.invalid ~ .helper-text[data-error],
|
||||
&:focus.invalid ~ .helper-text[data-error] {
|
||||
@extend %hidden-text;
|
||||
}
|
||||
|
||||
// Valid Input Style
|
||||
&.valid,
|
||||
&:focus.valid {
|
||||
@extend %valid-input-style;
|
||||
}
|
||||
|
||||
// Custom Success Message
|
||||
&.valid ~ .helper-text:after,
|
||||
&:focus.valid ~ .helper-text:after {
|
||||
@extend %custom-success-message;
|
||||
}
|
||||
&:focus.valid ~ label {
|
||||
color: $input-success-color;
|
||||
}
|
||||
|
||||
// Invalid Input Style
|
||||
&.invalid,
|
||||
&:focus.invalid {
|
||||
@extend %invalid-input-style;
|
||||
}
|
||||
|
||||
// Custom Error message
|
||||
&.invalid ~ .helper-text:after,
|
||||
&:focus.invalid ~ .helper-text:after {
|
||||
@extend %custom-error-message;
|
||||
}
|
||||
&:focus.invalid ~ label {
|
||||
color: $input-error-color;
|
||||
}
|
||||
|
||||
// Full width label when using validate for error messages
|
||||
&.validate + label {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Form Message Shared Styles
|
||||
& + label:after {
|
||||
@extend %input-after-style;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Validation Sass Placeholders */
|
||||
%valid-input-style {
|
||||
border-bottom: 1px solid $input-success-color;
|
||||
box-shadow: 0 1px 0 0 $input-success-color;
|
||||
}
|
||||
%invalid-input-style {
|
||||
border-bottom: $input-invalid-border;
|
||||
box-shadow: 0 1px 0 0 $input-error-color;
|
||||
}
|
||||
%hidden-text {
|
||||
color: transparent;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
%custom-success-message {
|
||||
content: attr(data-success);
|
||||
color: $input-success-color;
|
||||
}
|
||||
%custom-error-message {
|
||||
content: attr(data-error);
|
||||
color: $input-error-color;
|
||||
}
|
||||
%input-after-style {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: .2s opacity ease-out, .2s color ease-out;
|
||||
}
|
||||
|
||||
|
||||
// Styling for input field wrapper
|
||||
.input-field {
|
||||
// Inline styles
|
||||
&.inline {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 5px;
|
||||
|
||||
input,
|
||||
.select-dropdown {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Gutter spacing
|
||||
&.col {
|
||||
label {
|
||||
left: $gutter-width * 0.5;
|
||||
}
|
||||
|
||||
.prefix ~ label,
|
||||
.prefix ~ .validate ~ label,
|
||||
.suffix ~ label,
|
||||
.suffix ~ .validate ~ label {
|
||||
width: calc(100% - 3rem - #{$gutter-width});
|
||||
}
|
||||
}
|
||||
|
||||
position: relative;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
& > label {
|
||||
color: $input-border-color;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 1rem;
|
||||
cursor: text;
|
||||
transition: transform .2s ease-out, color .2s ease-out;
|
||||
transform-origin: 0% 100%;
|
||||
text-align: initial;
|
||||
transform: translateY(12px);
|
||||
|
||||
&:not(.label-icon).active {
|
||||
transform: translateY(-14px) scale(.8);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Autofill + date + time inputs
|
||||
& > input[type]:-webkit-autofill:not(.browser-default):not([type="search"]) + label,
|
||||
& > input[type=date]:not(.browser-default) + label,
|
||||
& > input[type=time]:not(.browser-default) + label {
|
||||
transform: translateY(-14px) scale(.8);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.helper-text {
|
||||
&::after {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
min-height: 18px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: rgba(0,0,0,.54);
|
||||
}
|
||||
|
||||
// Prefix Icons
|
||||
.prefix, .suffix {
|
||||
position: absolute;
|
||||
width: $input-height;
|
||||
font-size: $input-icon-size;
|
||||
transition: color .2s;
|
||||
top: ($input-height - $input-icon-size) * 0.5;
|
||||
|
||||
&.active { color: $input-focus-color; }
|
||||
}
|
||||
|
||||
.prefix ~ input,
|
||||
.prefix ~ textarea,
|
||||
.prefix ~ .select-wrapper,
|
||||
.prefix ~ label,
|
||||
.prefix ~ .validate ~ label,
|
||||
.prefix ~ .helper-text,
|
||||
.prefix ~ .autocomplete-content {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.prefix ~ label { margin-left: 3rem; }
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
.prefix ~ input,
|
||||
.suffix ~ input {
|
||||
width: 86%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$small-and-down} {
|
||||
.prefix ~ input,
|
||||
.suffix ~ input {
|
||||
width: 80%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Suffix Icons
|
||||
.suffix {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.suffix ~ input,
|
||||
.suffix ~ textarea,
|
||||
.suffix ~ .select-wrapper,
|
||||
.suffix ~ label,
|
||||
.suffix ~ .validate ~ label,
|
||||
.suffix ~ .helper-text,
|
||||
.suffix ~ .autocomplete-content {
|
||||
margin-right: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.suffix ~ label { margin-right: 3rem; }
|
||||
|
||||
}
|
||||
|
||||
/* Search Field */
|
||||
|
||||
.input-field input[type=search] {
|
||||
display: block;
|
||||
line-height: inherit;
|
||||
transition: .3s background-color;
|
||||
|
||||
.nav-wrapper & {
|
||||
height: inherit;
|
||||
padding-left: 4rem;
|
||||
width: calc(100% - 4rem);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:focus:not(.browser-default) {
|
||||
background-color: $input-background;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
color: #444;
|
||||
|
||||
& + label i,
|
||||
& ~ .mdi-navigation-close,
|
||||
& ~ .material-icons {
|
||||
color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
& + .label-icon {
|
||||
transform: none;
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
& ~ .mdi-navigation-close,
|
||||
& ~ .material-icons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 1rem;
|
||||
color: transparent;
|
||||
cursor: pointer;
|
||||
font-size: $input-icon-size;
|
||||
transition: .3s color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Textarea */
|
||||
|
||||
// Default textarea
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: $input-height;
|
||||
background-color: transparent;
|
||||
|
||||
&.materialize-textarea {
|
||||
line-height: normal;
|
||||
overflow-y: hidden; /* prevents scroll bar flash */
|
||||
padding: .8rem 0 .8rem 0; /* prevents text jump on Enter keypress */
|
||||
resize: none;
|
||||
min-height: $input-height;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
// For textarea autoresize
|
||||
.hiddendiv {
|
||||
visibility: hidden;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word; /* future version of deprecated 'word-wrap' */
|
||||
padding-top: 1.2rem; /* prevents text jump on Enter keypress */
|
||||
|
||||
// Reduces repaints
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
/* Autocomplete */
|
||||
.autocomplete-content {
|
||||
li {
|
||||
.highlight { color: #444; }
|
||||
|
||||
img {
|
||||
height: $dropdown-item-height - 10;
|
||||
width: $dropdown-item-height - 10;
|
||||
margin: 5px 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Character Counter */
|
||||
.character-counter {
|
||||
min-height: 18px;
|
||||
}
|
115
node_modules/@materializecss/materialize/sass/components/forms/_radio-buttons.scss
generated
vendored
Executable file
115
node_modules/@materializecss/materialize/sass/components/forms/_radio-buttons.scss
generated
vendored
Executable file
|
@ -0,0 +1,115 @@
|
|||
/* Radio Buttons
|
||||
========================================================================== */
|
||||
|
||||
// Remove default Radio Buttons
|
||||
[type="radio"]:not(:checked),
|
||||
[type="radio"]:checked {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span,
|
||||
[type="radio"]:checked + span {
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 1rem;
|
||||
transition: .28s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[type="radio"] + span:before,
|
||||
[type="radio"] + span:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
z-index: 0;
|
||||
transition: .28s ease;
|
||||
}
|
||||
|
||||
/* Unchecked styles */
|
||||
[type="radio"]:not(:checked) + span:before,
|
||||
[type="radio"]:not(:checked) + span:after,
|
||||
[type="radio"]:checked + span:before,
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:before,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span:before,
|
||||
[type="radio"]:not(:checked) + span:after {
|
||||
border: 2px solid $radio-empty-color;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span:after {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
/* Checked styles */
|
||||
[type="radio"]:checked + span:before {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:before,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
border: $radio-border;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
background-color: $radio-fill-color;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
/* Radio With gap */
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
transform: scale(.5);
|
||||
}
|
||||
|
||||
/* Focused styles */
|
||||
[type="radio"].tabbed:focus + span:before {
|
||||
box-shadow: 0 0 0 10px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
/* Disabled Radio With gap */
|
||||
[type="radio"].with-gap:disabled:checked + span:before {
|
||||
border: 2px solid $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"].with-gap:disabled:checked + span:after {
|
||||
border: none;
|
||||
background-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
/* Disabled style */
|
||||
[type="radio"]:disabled:not(:checked) + span:before,
|
||||
[type="radio"]:disabled:checked + span:before {
|
||||
background-color: transparent;
|
||||
border-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled + span {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled:not(:checked) + span:before {
|
||||
border-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled:checked + span:after {
|
||||
background-color: $input-disabled-color;
|
||||
border-color: $input-disabled-solid-color;
|
||||
}
|
161
node_modules/@materializecss/materialize/sass/components/forms/_range.scss
generated
vendored
Executable file
161
node_modules/@materializecss/materialize/sass/components/forms/_range.scss
generated
vendored
Executable file
|
@ -0,0 +1,161 @@
|
|||
/* Range
|
||||
========================================================================== */
|
||||
|
||||
.range-field {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type=range],
|
||||
input[type=range] + .thumb {
|
||||
@extend .no-select;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
padding: 0;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=range] + .thumb {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 0;
|
||||
border: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-radius: 50%;
|
||||
background-color: $radio-fill-color;
|
||||
margin-left: 7px;
|
||||
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
.value {
|
||||
display: block;
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
color: $radio-fill-color;
|
||||
font-size: 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-radius: 50% 50% 50% 0;
|
||||
|
||||
.value {
|
||||
color: $input-background;
|
||||
margin-left: -1px;
|
||||
margin-top: 8px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shared
|
||||
@mixin range-track {
|
||||
height: $track-height;
|
||||
background: #c2c0c2;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@mixin range-thumb {
|
||||
border: none;
|
||||
height: $range-height;
|
||||
width: $range-width;
|
||||
border-radius: 50%;
|
||||
background: $radio-fill-color;
|
||||
transition: box-shadow .3s;
|
||||
}
|
||||
|
||||
// WebKit
|
||||
input[type=range] {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
@include range-track;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
@include range-thumb;
|
||||
-webkit-appearance: none;
|
||||
background-color: $radio-fill-color;
|
||||
transform-origin: 50% 50%;
|
||||
margin: -5px 0 0 0;
|
||||
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
||||
|
||||
// FireFox
|
||||
input[type=range] {
|
||||
/* fix for FF unable to apply focus style bug */
|
||||
border: 1px solid white;
|
||||
|
||||
/*required for proper track sizing in FF*/
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-track {
|
||||
@include range-track;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-thumb {
|
||||
@include range-thumb;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
// hide the outline behind the border
|
||||
input[type=range]:-moz-focusring {
|
||||
outline: 1px solid #fff;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-moz-range-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
||||
|
||||
// IE 10+
|
||||
input[type=range]::-ms-track {
|
||||
height: $track-height;
|
||||
|
||||
// remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead
|
||||
background: transparent;
|
||||
|
||||
// leave room for the larger thumb to overflow with a transparent border */
|
||||
border-color: transparent;
|
||||
border-width: 6px 0;
|
||||
|
||||
/*remove default tick marks*/
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-lower {
|
||||
background: #777;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-upper {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-thumb {
|
||||
@include range-thumb;
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-ms-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
199
node_modules/@materializecss/materialize/sass/components/forms/_select.scss
generated
vendored
Executable file
199
node_modules/@materializecss/materialize/sass/components/forms/_select.scss
generated
vendored
Executable file
|
@ -0,0 +1,199 @@
|
|||
/* Select Field
|
||||
========================================================================== */
|
||||
|
||||
select.browser-default { opacity: 1; }
|
||||
select {
|
||||
opacity: 0;
|
||||
background-color: $select-background;
|
||||
width: 100%;
|
||||
padding: $select-padding;
|
||||
border: $select-border;
|
||||
border-radius: $select-radius;
|
||||
height: $input-height;
|
||||
}
|
||||
|
||||
.select-label {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.select-wrapper {
|
||||
&.valid .helper-text[data-success],
|
||||
&.invalid ~ .helper-text[data-error] {
|
||||
@extend %hidden-text;
|
||||
}
|
||||
|
||||
&.valid {
|
||||
& > input.select-dropdown {
|
||||
@extend %valid-input-style;
|
||||
}
|
||||
|
||||
& ~ .helper-text:after {
|
||||
@extend %custom-success-message;
|
||||
}
|
||||
}
|
||||
|
||||
&.invalid {
|
||||
& > input.select-dropdown,
|
||||
& > input.select-dropdown:focus {
|
||||
@extend %invalid-input-style;
|
||||
}
|
||||
|
||||
& ~ .helper-text:after {
|
||||
@extend %custom-error-message;
|
||||
}
|
||||
}
|
||||
|
||||
&.valid + label,
|
||||
&.invalid + label {
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
& + label:after {
|
||||
@extend %input-after-style;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
|
||||
input.select-dropdown {
|
||||
&:focus {
|
||||
border-bottom: 1px solid $input-focus-color;
|
||||
}
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-bottom: $input-border;
|
||||
outline: none;
|
||||
height: $input-height;
|
||||
line-height: $input-height;
|
||||
width: 100%;
|
||||
font-size: $input-font-size;
|
||||
margin: $input-margin;
|
||||
padding: 0;
|
||||
display: block;
|
||||
user-select:none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
z-index: 0;
|
||||
fill: rgba(0,0,0,.87);
|
||||
}
|
||||
|
||||
& + label {
|
||||
position: absolute;
|
||||
top: -26px;
|
||||
font-size: $label-font-size;
|
||||
}
|
||||
|
||||
// Hide select with overflow hidden instead of using display none
|
||||
// (this prevents form validation errors with hidden form elements)
|
||||
.hide-select {
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled styles
|
||||
select:disabled {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
.select-wrapper.disabled {
|
||||
+ label {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
.caret {
|
||||
fill: $input-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
.select-wrapper input.select-dropdown:disabled {
|
||||
color: $input-disabled-color;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.select-wrapper i {
|
||||
color: $select-disabled-color;
|
||||
}
|
||||
|
||||
.select-dropdown li.disabled,
|
||||
.select-dropdown li.disabled > span,
|
||||
.select-dropdown li.optgroup {
|
||||
color: $select-disabled-color;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
body.keyboard-focused {
|
||||
.select-dropdown.dropdown-content li:focus {
|
||||
background-color: $select-option-focus;
|
||||
}
|
||||
}
|
||||
|
||||
.select-dropdown.dropdown-content {
|
||||
li {
|
||||
&:hover {
|
||||
background-color: $select-option-hover;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: $select-option-selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix Icons
|
||||
.prefix ~ .select-wrapper {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.prefix ~ label { margin-left: 3rem; }
|
||||
|
||||
// Suffix Icons
|
||||
.suffix ~ .select-wrapper {
|
||||
margin-right: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.suffix ~ label { margin-right: 3rem; }
|
||||
|
||||
// Icons
|
||||
.select-dropdown li {
|
||||
img {
|
||||
height: $dropdown-item-height - 10;
|
||||
width: $dropdown-item-height - 10;
|
||||
margin: 5px 15px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Optgroup styles
|
||||
.select-dropdown li.optgroup {
|
||||
border-top: 1px solid $dropdown-hover-bg-color;
|
||||
|
||||
&.selected > span {
|
||||
color: rgba(0, 0, 0, .7);
|
||||
}
|
||||
|
||||
& > span {
|
||||
color: rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
& ~ li.optgroup-option {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
91
node_modules/@materializecss/materialize/sass/components/forms/_switches.scss
generated
vendored
Executable file
91
node_modules/@materializecss/materialize/sass/components/forms/_switches.scss
generated
vendored
Executable file
|
@ -0,0 +1,91 @@
|
|||
/* Switch
|
||||
========================================================================== */
|
||||
|
||||
.switch,
|
||||
.switch * {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.switch label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switch label input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
&:checked:not([disabled]) {
|
||||
background-color: $switch-checked-lever-bg;
|
||||
}
|
||||
|
||||
&:checked + .lever {
|
||||
&:before, &:after {
|
||||
left: 18px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
background-color: $switch-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switch label .lever {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 36px;
|
||||
height: 14px;
|
||||
background-color: $switch-unchecked-lever-bg;
|
||||
border-radius: $switch-radius;
|
||||
margin-right: 10px;
|
||||
transition: background 0.3s ease;
|
||||
vertical-align: middle;
|
||||
margin: 0 16px;
|
||||
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease;
|
||||
}
|
||||
|
||||
&:before {
|
||||
background-color: transparentize($switch-bg-color, .85);
|
||||
}
|
||||
|
||||
&:after {
|
||||
background-color: $switch-unchecked-bg;
|
||||
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch active style
|
||||
input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,
|
||||
input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before {
|
||||
transform: scale(2.4);
|
||||
background-color: transparentize($switch-bg-color, .85);
|
||||
}
|
||||
|
||||
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
||||
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before {
|
||||
transform: scale(2.4);
|
||||
background-color: rgba(0,0,0,.08);
|
||||
}
|
||||
|
||||
// Disabled Styles
|
||||
.switch input[type=checkbox][disabled] + .lever {
|
||||
cursor: default;
|
||||
background-color: rgba(0,0,0,.12);
|
||||
}
|
||||
|
||||
.switch label input[type=checkbox][disabled] + .lever:after,
|
||||
.switch label input[type=checkbox][disabled]:checked + .lever:after {
|
||||
background-color: $input-disabled-solid-color;
|
||||
}
|
7
node_modules/@materializecss/materialize/sass/ghpages-materialize.scss
generated
vendored
Executable file
7
node_modules/@materializecss/materialize/sass/ghpages-materialize.scss
generated
vendored
Executable file
|
@ -0,0 +1,7 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
// import materialize
|
||||
@import "materialize";
|
||||
|
||||
// Custom style
|
||||
@import "style";
|
42
node_modules/@materializecss/materialize/sass/materialize.scss
generated
vendored
Executable file
42
node_modules/@materializecss/materialize/sass/materialize.scss
generated
vendored
Executable file
|
@ -0,0 +1,42 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
// Color
|
||||
@import "components/color-variables";
|
||||
@import "components/color-classes";
|
||||
|
||||
// Variables;
|
||||
@import "components/variables";
|
||||
|
||||
// Reset
|
||||
@import "components/normalize";
|
||||
|
||||
// components
|
||||
@import "components/global";
|
||||
@import "components/collection";
|
||||
@import "components/badges";
|
||||
@import "components/icons-material-design";
|
||||
@import "components/grid";
|
||||
@import "components/navbar";
|
||||
@import "components/typography";
|
||||
@import "components/transitions";
|
||||
@import "components/cards";
|
||||
@import "components/toast";
|
||||
@import "components/tabs";
|
||||
@import "components/tooltip";
|
||||
@import "components/buttons";
|
||||
@import "components/dropdown";
|
||||
@import "components/waves";
|
||||
@import "components/modal";
|
||||
@import "components/collapsible";
|
||||
@import "components/chips";
|
||||
@import "components/materialbox";
|
||||
@import "components/forms/forms";
|
||||
@import "components/table_of_contents";
|
||||
@import "components/sidenav";
|
||||
@import "components/preloader";
|
||||
@import "components/slider";
|
||||
@import "components/carousel";
|
||||
@import "components/tapTarget";
|
||||
@import "components/pulse";
|
||||
@import "components/datepicker";
|
||||
@import "components/timepicker";
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "fouroperations",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@materializecss/materialize": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@materializecss/materialize": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@materializecss/materialize/-/materialize-1.1.0.tgz",
|
||||
"integrity": "sha512-W2MrDC8mzpMWyP2OpS0RWTWGcLiRRBz7kn2E9TsbardPyVNFdoNvXq5sLy3NcEfAlACc1+L7Q95+pBuUX44dRg=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@materializecss/materialize": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@materializecss/materialize/-/materialize-1.1.0.tgz",
|
||||
"integrity": "sha512-W2MrDC8mzpMWyP2OpS0RWTWGcLiRRBz7kn2E9TsbardPyVNFdoNvXq5sLy3NcEfAlACc1+L7Q95+pBuUX44dRg=="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@materializecss/materialize": "^1.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# fouroperations
|
||||
**a simple website showing the results of the four operations on the two numbers, including exponentials**
|
||||
|
||||
This project was created for [Xavier School's NExT Lab](https://github.com/XSNExTLab).
|
|
@ -0,0 +1,52 @@
|
|||
/* fouroperations.js
|
||||
Solve the four operations. */
|
||||
|
||||
function fouroperations(number1, number2) {
|
||||
const inputs_numbers = [number1, number2];
|
||||
|
||||
const operationResults = {
|
||||
'sum': null,
|
||||
'difference': null,
|
||||
'product': null,
|
||||
'quotient': null,
|
||||
'exponential': null
|
||||
};
|
||||
|
||||
/* Solve the data given. */
|
||||
operationResults.sum = (inputs_numbers[0] + inputs_numbers[1]);
|
||||
operationResults.difference = (inputs_numbers[0] - inputs_numbers[1]);
|
||||
operationResults.product = (inputs_numbers[0] * inputs_numbers[1]);
|
||||
operationResults.exponential = (inputs_numbers[0] ** inputs_numbers[1]);
|
||||
|
||||
try {
|
||||
operationResults.quotient = (number1 / number2);
|
||||
} catch(err) {
|
||||
operationResults.quotient = null;
|
||||
};
|
||||
|
||||
return (operationResults);
|
||||
};
|
||||
|
||||
function displayAnswers(number1 = null, number2 = null) {
|
||||
/* Update the numbers properly. */
|
||||
if (number1 != null) {document.getElementById("input_number_1").value = number1};
|
||||
if (number2 != null) {document.getElementById("input_number_2").value = number2};
|
||||
|
||||
/* Register the numbers now. */
|
||||
const inputs_numbers = [parseFloat(document.getElementById("input_number_1").value), parseFloat(document.getElementById("input_number_2").value)];
|
||||
|
||||
if ((inputs_numbers[0]) && (inputs_numbers[1])) {
|
||||
/* Solve the numbers. */
|
||||
operationResults = fouroperations(inputs_numbers[0], inputs_numbers[1]);
|
||||
|
||||
/* Update the display output. */
|
||||
document.getElementById("output_number_sum").value = operationResults.sum;
|
||||
document.getElementById("output_number_difference").value = operationResults.difference;
|
||||
document.getElementById("output_number_product").value = operationResults.product;
|
||||
document.getElementById("output_number_quotient").value = operationResults.quotient;
|
||||
document.getElementById("output_number_exponential").value = operationResults.exponential;
|
||||
|
||||
/* Return the values. */
|
||||
return (operationResults);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
/* interface.css
|
||||
adjust interface */
|
Loading…
Reference in New Issue