From d8315756d7324bb92bc1227613c6e25b2f9f5502 Mon Sep 17 00:00:00 2001 From: Steven Le Date: Sun, 18 Oct 2015 17:38:52 -0700 Subject: [PATCH] Initial commit of base --- .gitignore | 1 + LICENSE | 209 +------- README.md | 3 + bower.json | 25 + bower_components/smooth_scroll/.bower.json | 15 + bower_components/smooth_scroll/.gitignore | 10 + bower_components/smooth_scroll/.travis.yml | 6 + bower_components/smooth_scroll/LICENSE.md | 21 + bower_components/smooth_scroll/README.md | 253 +++++++++ .../smooth_scroll/dist/js/smooth-scroll.js | 484 ++++++++++++++++++ .../dist/js/smooth-scroll.min.js | 2 + .../docs/dist/js/smooth-scroll.js | 484 ++++++++++++++++++ .../docs/dist/js/smooth-scroll.min.js | 2 + .../smooth_scroll/docs/index.html | 86 ++++ bower_components/smooth_scroll/gulpfile.js | 226 ++++++++ bower_components/smooth_scroll/index.html | 86 ++++ bower_components/smooth_scroll/package.json | 43 ++ .../src/docs/_templates/_footer.html | 13 + .../src/docs/_templates/_header.html | 30 ++ .../smooth_scroll/src/docs/index.md | 44 ++ .../smooth_scroll/src/js/smooth-scroll.js | 477 +++++++++++++++++ .../smooth_scroll/test/karma.conf.js | 26 + .../test/spec/spec-smoothScroll.js | 131 +++++ content/pages/_blueprint.yaml | 1 + content/pages/home.yaml | 3 + dist/base.css | 1 + gulpfile.js | 54 ++ package.json | 24 + podspec.yaml | 17 + src/sass/_breakpoint.scss | 48 ++ src/sass/_content.scss | 42 ++ src/sass/_elements.scss | 40 ++ src/sass/_grid.scss | 91 ++++ src/sass/_reset.scss | 162 ++++++ src/sass/_spacing.scss | 66 +++ src/sass/_utility.scss | 44 ++ src/sass/base.scss | 20 + static/images/favicon.ico | Bin 0 -> 32038 bytes static/images/favicon.png | Bin 0 -> 1574 bytes views/_base.html | 12 + views/home.html | 430 ++++++++++++++++ 41 files changed, 3533 insertions(+), 199 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 bower.json create mode 100644 bower_components/smooth_scroll/.bower.json create mode 100644 bower_components/smooth_scroll/.gitignore create mode 100755 bower_components/smooth_scroll/.travis.yml create mode 100755 bower_components/smooth_scroll/LICENSE.md create mode 100755 bower_components/smooth_scroll/README.md create mode 100755 bower_components/smooth_scroll/dist/js/smooth-scroll.js create mode 100755 bower_components/smooth_scroll/dist/js/smooth-scroll.min.js create mode 100755 bower_components/smooth_scroll/docs/dist/js/smooth-scroll.js create mode 100755 bower_components/smooth_scroll/docs/dist/js/smooth-scroll.min.js create mode 100644 bower_components/smooth_scroll/docs/index.html create mode 100755 bower_components/smooth_scroll/gulpfile.js create mode 100644 bower_components/smooth_scroll/index.html create mode 100755 bower_components/smooth_scroll/package.json create mode 100644 bower_components/smooth_scroll/src/docs/_templates/_footer.html create mode 100644 bower_components/smooth_scroll/src/docs/_templates/_header.html create mode 100644 bower_components/smooth_scroll/src/docs/index.md create mode 100755 bower_components/smooth_scroll/src/js/smooth-scroll.js create mode 100755 bower_components/smooth_scroll/test/karma.conf.js create mode 100755 bower_components/smooth_scroll/test/spec/spec-smoothScroll.js create mode 100644 content/pages/_blueprint.yaml create mode 100644 content/pages/home.yaml create mode 100644 dist/base.css create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 podspec.yaml create mode 100644 src/sass/_breakpoint.scss create mode 100644 src/sass/_content.scss create mode 100644 src/sass/_elements.scss create mode 100644 src/sass/_grid.scss create mode 100644 src/sass/_reset.scss create mode 100644 src/sass/_spacing.scss create mode 100644 src/sass/_utility.scss create mode 100644 src/sass/base.scss create mode 100644 static/images/favicon.ico create mode 100644 static/images/favicon.png create mode 100644 views/_base.html create mode 100644 views/home.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/LICENSE b/LICENSE index 8f71f43..bd5c027 100644 --- a/LICENSE +++ b/LICENSE @@ -1,202 +1,13 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +Copyright 2015 Steven Le (stevenle08@gmail.com) - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8ac9a1f --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +#### base + +Check out https://stevenle.github.io/base/ diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..007ebf8 --- /dev/null +++ b/bower.json @@ -0,0 +1,25 @@ +{ + "name": "base", + "description": "base", + "main": "dist/base.css", + "authors": [ + { + "name": "Steven Le", + "email": "stevenle08@gmail.com", + "website": "stevenle.co" + } + ], + "license": "Apache-2.0", + "homepage": "https://stevenle.github.io/base/", + "private": true, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "smooth_scroll": "git://github.com/cferdinandi/smooth-scroll.git#~7.1.1" + } +} diff --git a/bower_components/smooth_scroll/.bower.json b/bower_components/smooth_scroll/.bower.json new file mode 100644 index 0000000..b75a470 --- /dev/null +++ b/bower_components/smooth_scroll/.bower.json @@ -0,0 +1,15 @@ +{ + "name": "smooth_scroll", + "homepage": "https://github.com/cferdinandi/smooth-scroll", + "version": "7.1.1", + "_release": "7.1.1", + "_resolution": { + "type": "version", + "tag": "v7.1.1", + "commit": "dd50d4ed49efc5662ef6ad27969bbc5b772f62d4" + }, + "_source": "git://github.com/cferdinandi/smooth-scroll.git", + "_target": "~7.1.1", + "_originalSource": "git://github.com/cferdinandi/smooth-scroll.git", + "_direct": true +} \ No newline at end of file diff --git a/bower_components/smooth_scroll/.gitignore b/bower_components/smooth_scroll/.gitignore new file mode 100644 index 0000000..62fb128 --- /dev/null +++ b/bower_components/smooth_scroll/.gitignore @@ -0,0 +1,10 @@ +# Node +node_modules +test/results +test/coverage + +## OS X +.DS_Store +._* +.Spotlight-V100 +.Trashes \ No newline at end of file diff --git a/bower_components/smooth_scroll/.travis.yml b/bower_components/smooth_scroll/.travis.yml new file mode 100755 index 0000000..11842a6 --- /dev/null +++ b/bower_components/smooth_scroll/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.10" +before_script: + - npm install -g gulp +script: gulp test \ No newline at end of file diff --git a/bower_components/smooth_scroll/LICENSE.md b/bower_components/smooth_scroll/LICENSE.md new file mode 100755 index 0000000..b5e8ef7 --- /dev/null +++ b/bower_components/smooth_scroll/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) Go Make Things, LLC + +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. \ No newline at end of file diff --git a/bower_components/smooth_scroll/README.md b/bower_components/smooth_scroll/README.md new file mode 100755 index 0000000..4073490 --- /dev/null +++ b/bower_components/smooth_scroll/README.md @@ -0,0 +1,253 @@ +# Smooth Scroll [![Build Status](https://travis-ci.org/cferdinandi/smooth-scroll.svg)](https://travis-ci.org/cferdinandi/smooth-scroll) +A lightweight script to animate scrolling to anchor links. Smooth Scroll works great with [Gumshoe](https://github.com/cferdinandi/gumshoe). + +[Download Smooth Scroll](https://github.com/cferdinandi/smooth-scroll/archive/master.zip) / [View the demo](http://cferdinandi.github.io/smooth-scroll/) + + + +## Getting Started + +Compiled and production-ready code can be found in the `dist` directory. The `src` directory contains development code. Unit tests are located in the `test` directory. + +### 1. Include Smooth Scroll on your site. + +```html + +``` + +### 2. Add the markup to your HTML. + +```html +Anchor Link +... +Bazinga! +``` + +Turn anchor links into Smooth Scroll links by adding the `[data-scroll]` data attribute. Give the anchor location an ID just like you normally would. + +### 3. Initialize Smooth Scroll. + +```html + +``` + +In the footer of your page, after the content, initialize Smooth Scroll. And that's it, you're done. Nice work! + + + +## Installing with Package Managers + +You can install Smooth Scroll with your favorite package manager. + +* **[NPM](https://www.npmjs.org/):** `npm install cferdinandi/smooth-scroll` +* **[Bower](http://bower.io/):** `bower install https://github.com/cferdinandi/smooth-scroll.git` +* **[Component](http://component.io/):** `component install cferdinandi/smooth-scroll` + + + +## Working with the Source Files + +If you would prefer, you can work with the development code in the `src` directory using the included [Gulp build system](http://gulpjs.com/). This compiles, lints, and minifies code, and runs unit tests. It's the same build system that's used by [Kraken](http://cferdinandi.github.io/kraken/), so it includes some unnecessary tasks and Sass variables but can be dropped right in to the boilerplate without any configuration. + +### Dependencies +Make sure these are installed first. + +* [Node.js](http://nodejs.org) +* [Gulp](http://gulpjs.com) `sudo npm install -g gulp` + +### Quick Start + +1. In bash/terminal/command line, `cd` into your project directory. +2. Run `npm install` to install required files. +3. When it's done installing, run one of the task runners to get going: + * `gulp` manually compiles files. + * `gulp watch` automatically compiles files when changes are made and applies changes using [LiveReload](http://livereload.com/). + * `gulp test` compiles files and runs unit tests. + + + +## Options and Settings + +Smooth Scroll includes smart defaults and works right out of the box. But if you want to customize things, it also has a robust API that provides multiple ways for you to adjust the default options and settings. + +### Global Settings + +You can pass options and callbacks into Smooth Scroll through the `init()` function: + +```javascript +smoothScroll.init({ + selector: '[data-scroll]', // Selector for links (must be a valid CSS selector) + selectorHeader: '[data-scroll-header]', // Selector for fixed headers (must be a valid CSS selector) + speed: 500, // Integer. How fast to complete the scroll in milliseconds + easing: 'easeInOutCubic', // Easing pattern to use + updateURL: true, // Boolean. Whether or not to update the URL with the anchor hash on scroll + offset: 0, // Integer. How far to offset the scrolling anchor location in pixels + callback: function ( toggle, anchor ) {} // Function to run after scrolling +}); +``` + +#### Easing Options + +**Linear** +*Moves at the same speed from start to finish.* + +* `Linear` + + +**Ease-In** +*Gradually increases in speed.* + +* `easeInQuad` +* `easeInCubic` +* `easeInQuart` +* `easeInQuint` + + +**Ease-In-Out** +*Gradually increases in speed, peaks, and then gradually slows down.* + +* `easeInOutQuad` +* `easeInOutCubic` +* `easeInOutQuart` +* `easeInOutQuint` + + +**Ease-Out** +*Gradually decreases in speed.* + +* `easeOutQuad` +* `easeOutCubic` +* `easeOutQuart` +* `easeOutQuint` + + +Learn more about the different easing patterns and what they do at [easings.net](http://easings.net/). + +### Override settings with data attributes + +Smooth Scroll also lets you override global settings on a link-by-link basis using the `[data-options]` data attribute: + +```html + + Anchor Link + +``` + +**Note:** You must use [valid JSON](http://jsonlint.com/) in order for the `data-options` feature to work. + +### Use Smooth Scroll events in your own scripts + +You can also call Smooth Scroll's scroll animation events in your own scripts. + +#### animateScroll() +Animate scrolling to an anchor. + +```javascript +smoothScroll.animateScroll( + toggle, // Node that toggles the animation. ex. document.querySelector('#toggle') + anchor, // ID of the anchor to scroll to. ex. '#bazinga' + options // Classes and callbacks. Same options as those passed into the init() function. +); +``` + +**Example 1** + +```javascript +smoothScroll.animateScroll( null, '#bazinga' ); +``` + +**Example 2** + +```javascript +var toggle = document.querySelector('#toggle'); +var options = { speed: 1000, easing: 'easeOutCubic' }; +smoothScroll.animateScroll( toggle, '#bazinga', options ); +``` + +#### destroy() +Destroy the current `smoothScroll.init()`. This is called automatically during the `init` function to remove any existing initializations. + +```javascript +smoothScroll.destroy(); +``` + + +### Fixed Headers + +Add a `[data-scroll-header]` data attribute to fixed headers. Smooth Scroll will automatically offset scroll distances by the header height. If you have multiple fixed headers, add `[data-scroll-header]` to the last one in the markup. + +```html + +``` + +### Animating links to other pages + +Smooth Scroll does not include an option to animate scrolling to links on other pages, but you can easily add this functionality using the API. + +1. Do *not* add the `data-scroll` attribute to links to other pages. Treat them like normal links, and include your anchor link hash as normal. + + ```html + + ``` +2. Add the following script to the footer of your page, after the `smoothScroll.init()` function. + + ```html + + ``` + + +## Browser Compatibility + +Smooth Scroll works in all modern browsers, and IE 9 and above. + +Smooth Scroll is built with modern JavaScript APIs, and uses progressive enhancement. If the JavaScript file fails to load, or if your site is viewed on older and less capable browsers, anchor links will jump the way they normally would. If you need to smooth scrolling for older browsers, [download the jQuery version of Smooth Scroll on GitHub](https://github.com/cferdinandi/smooth-scroll/tree/archive-v1). + + + +## Known Issues + +If the `` element has been assigned a height of `100%`, Smooth Scroll is unable to properly calculate page distances and will not scroll to the right location. The `` element can have a fixed, non-percentage based height (ex. `500px`), or a height of `auto`. + + + +## Adding `[data-scroll]` attributes to the `wp_nav_menu()` in WordPress + +Add this to your `functions.php` file: + +```js +function YOURPREFIX_custom_nav_attributes ( $atts, $item, $args ) { + $atts['data-scroll'] = 'true'; + return $atts; +} +add_filter( 'nav_menu_link_attributes', 'YOURPREFIX_custom_nav_attributes', 10, 3 ); +``` + +**Source:** http://wordpress.stackexchange.com/questions/121123/how-to-add-a-data-attribute-to-a-wordpress-menu-item + + + +## How to Contribute + +In lieu of a formal style guide, take care to maintain the existing coding style. Please apply fixes to both the development and production code. Don't forget to update the version number, and when applicable, the documentation. + + + +## License + +The code is available under the [MIT License](LICENSE.md). \ No newline at end of file diff --git a/bower_components/smooth_scroll/dist/js/smooth-scroll.js b/bower_components/smooth_scroll/dist/js/smooth-scroll.js new file mode 100755 index 0000000..20b588a --- /dev/null +++ b/bower_components/smooth_scroll/dist/js/smooth-scroll.js @@ -0,0 +1,484 @@ +/*! + * smooth-scroll v7.1.1: Animate scrolling to anchor links + * (c) 2015 Chris Ferdinandi + * MIT License + * http://github.com/cferdinandi/smooth-scroll + */ + +(function (root, factory) { + if ( typeof define === 'function' && define.amd ) { + define([], factory(root)); + } else if ( typeof exports === 'object' ) { + module.exports = factory(root); + } else { + root.smoothScroll = factory(root); + } +})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) { + + 'use strict'; + + // + // Variables + // + + var smoothScroll = {}; // Object for public APIs + var supports = 'querySelector' in document && 'addEventListener' in root; // Feature test + var settings, eventTimeout, fixedHeader, headerHeight; + + // Default settings + var defaults = { + selector: '[data-scroll]', + selectorHeader: '[data-scroll-header]', + speed: 500, + easing: 'easeInOutCubic', + offset: 0, + updateURL: true, + callback: function () {} + }; + + + // + // Methods + // + + /** + * Merge two or more objects. Returns a new object. + * @private + * @param {Boolean} deep If true, do a deep (or recursive) merge [optional] + * @param {Object} objects The objects to merge together + * @returns {Object} Merged values of defaults and options + */ + var extend = function () { + + // Variables + var extended = {}; + var deep = false; + var i = 0; + var length = arguments.length; + + // Check if a deep merge + if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { + deep = arguments[0]; + i++; + } + + // Merge the object into the extended object + var merge = function (obj) { + for ( var prop in obj ) { + if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { + // If deep merge and property is an object, merge properties + if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { + extended[prop] = extend( true, extended[prop], obj[prop] ); + } else { + extended[prop] = obj[prop]; + } + } + } + }; + + // Loop through each object and conduct a merge + for ( ; i < length; i++ ) { + var obj = arguments[i]; + merge(obj); + } + + return extended; + + }; + + /** + * Get the height of an element. + * @private + * @param {Node} elem The element to get the height of + * @return {Number} The element's height in pixels + */ + var getHeight = function ( elem ) { + return Math.max( elem.scrollHeight, elem.offsetHeight, elem.clientHeight ); + }; + + /** + * Get the closest matching element up the DOM tree. + * @private + * @param {Element} elem Starting element + * @param {String} selector Selector to match against (class, ID, data attribute, or tag) + * @return {Boolean|Element} Returns null if not match found + */ + var getClosest = function ( elem, selector ) { + + // Variables + var firstChar = selector.charAt(0); + var supports = 'classList' in document.documentElement; + var attribute, value; + + // If selector is a data attribute, split attribute from value + if ( firstChar === '[' ) { + selector = selector.substr(1, selector.length - 2); + attribute = selector.split( '=' ); + + if ( attribute.length > 1 ) { + value = true; + attribute[1] = attribute[1].replace( /"/g, '' ).replace( /'/g, '' ); + } + } + + // Get closest match + for ( ; elem && elem !== document; elem = elem.parentNode ) { + + // If selector is a class + if ( firstChar === '.' ) { + if ( supports ) { + if ( elem.classList.contains( selector.substr(1) ) ) { + return elem; + } + } else { + if ( new RegExp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test( elem.className ) ) { + return elem; + } + } + } + + // If selector is an ID + if ( firstChar === '#' ) { + if ( elem.id === selector.substr(1) ) { + return elem; + } + } + + // If selector is a data attribute + if ( firstChar === '[' ) { + if ( elem.hasAttribute( attribute[0] ) ) { + if ( value ) { + if ( elem.getAttribute( attribute[0] ) === attribute[1] ) { + return elem; + } + } else { + return elem; + } + } + } + + // If selector is a tag + if ( elem.tagName.toLowerCase() === selector ) { + return elem; + } + + } + + return null; + + }; + + /** + * Escape special characters for use with querySelector + * @private + * @param {String} id The anchor ID to escape + * @author Mathias Bynens + * @link https://github.com/mathiasbynens/CSS.escape + */ + var escapeCharacters = function ( id ) { + var string = String(id); + var length = string.length; + var index = -1; + var codeUnit; + var result = ''; + var firstCodeUnit = string.charCodeAt(0); + while (++index < length) { + codeUnit = string.charCodeAt(index); + // Note: there’s no need to special-case astral symbols, surrogate + // pairs, or lone surrogates. + + // If the character is NULL (U+0000), then throw an + // `InvalidCharacterError` exception and terminate these steps. + if (codeUnit === 0x0000) { + throw new InvalidCharacterError( + 'Invalid character: the input contains U+0000.' + ); + } + + if ( + // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is + // U+007F, […] + (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F || + // If the character is the first character and is in the range [0-9] + // (U+0030 to U+0039), […] + (index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) || + // If the character is the second character and is in the range [0-9] + // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] + ( + index === 1 && + codeUnit >= 0x0030 && codeUnit <= 0x0039 && + firstCodeUnit === 0x002D + ) + ) { + // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point + result += '\\' + codeUnit.toString(16) + ' '; + continue; + } + + // If the character is not handled by one of the above rules and is + // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or + // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to + // U+005A), or [a-z] (U+0061 to U+007A), […] + if ( + codeUnit >= 0x0080 || + codeUnit === 0x002D || + codeUnit === 0x005F || + codeUnit >= 0x0030 && codeUnit <= 0x0039 || + codeUnit >= 0x0041 && codeUnit <= 0x005A || + codeUnit >= 0x0061 && codeUnit <= 0x007A + ) { + // the character itself + result += string.charAt(index); + continue; + } + + // Otherwise, the escaped character. + // http://dev.w3.org/csswg/cssom/#escape-a-character + result += '\\' + string.charAt(index); + + } + return result; + }; + + /** + * Calculate the easing pattern + * @private + * @link https://gist.github.com/gre/1650294 + * @param {String} type Easing pattern + * @param {Number} time Time animation should take to complete + * @returns {Number} + */ + var easingPattern = function ( type, time ) { + var pattern; + if ( type === 'easeInQuad' ) pattern = time * time; // accelerating from zero velocity + if ( type === 'easeOutQuad' ) pattern = time * (2 - time); // decelerating to zero velocity + if ( type === 'easeInOutQuad' ) pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration + if ( type === 'easeInCubic' ) pattern = time * time * time; // accelerating from zero velocity + if ( type === 'easeOutCubic' ) pattern = (--time) * time * time + 1; // decelerating to zero velocity + if ( type === 'easeInOutCubic' ) pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration + if ( type === 'easeInQuart' ) pattern = time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuart' ) pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuart' ) pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration + if ( type === 'easeInQuint' ) pattern = time * time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuint' ) pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuint' ) pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration + return pattern || time; // no easing, no acceleration + }; + + /** + * Calculate how far to scroll + * @private + * @param {Element} anchor The anchor element to scroll to + * @param {Number} headerHeight Height of a fixed header, if any + * @param {Number} offset Number of pixels by which to offset scroll + * @returns {Number} + */ + var getEndLocation = function ( anchor, headerHeight, offset ) { + var location = 0; + if (anchor.offsetParent) { + do { + location += anchor.offsetTop; + anchor = anchor.offsetParent; + } while (anchor); + } + location = location - headerHeight - offset; + return location >= 0 ? location : 0; + }; + + /** + * Determine the document's height + * @private + * @returns {Number} + */ + var getDocumentHeight = function () { + return Math.max( + root.document.body.scrollHeight, root.document.documentElement.scrollHeight, + root.document.body.offsetHeight, root.document.documentElement.offsetHeight, + root.document.body.clientHeight, root.document.documentElement.clientHeight + ); + }; + + /** + * Convert data-options attribute into an object of key/value pairs + * @private + * @param {String} options Link-specific options as a data attribute string + * @returns {Object} + */ + var getDataOptions = function ( options ) { + return !options || !(typeof JSON === 'object' && typeof JSON.parse === 'function') ? {} : JSON.parse( options ); + }; + + /** + * Update the URL + * @private + * @param {Element} anchor The element to scroll to + * @param {Boolean} url Whether or not to update the URL history + */ + var updateUrl = function ( anchor, url ) { + if ( root.history.pushState && (url || url === 'true') && root.location.protocol !== 'file:' ) { + root.history.pushState( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') ); + } + }; + + var getHeaderHeight = function ( header ) { + return header === null ? 0 : ( getHeight( header ) + header.offsetTop ); + }; + + /** + * Start/stop the scrolling animation + * @public + * @param {Element} toggle The element that toggled the scroll event + * @param {Element} anchor The element to scroll to + * @param {Object} options + */ + smoothScroll.animateScroll = function ( toggle, anchor, options ) { + + // Options and overrides + var overrides = getDataOptions( toggle ? toggle.getAttribute('data-options') : null ); + var settings = extend( settings || defaults, options || {}, overrides ); // Merge user options with defaults + anchor = '#' + escapeCharacters(anchor.substr(1)); // Escape special characters and leading numbers + + // Selectors and variables + var anchorElem = anchor === '#' ? root.document.documentElement : root.document.querySelector(anchor); + var startLocation = root.pageYOffset; // Current location on the page + if ( !fixedHeader ) { fixedHeader = root.document.querySelector( settings.selectorHeader ); } // Get the fixed header if not already set + if ( !headerHeight ) { headerHeight = getHeaderHeight( fixedHeader ); } // Get the height of a fixed header if one exists and not already set + var endLocation = getEndLocation( anchorElem, headerHeight, parseInt(settings.offset, 10) ); // Scroll to location + var animationInterval; // interval timer + var distance = endLocation - startLocation; // distance to travel + var documentHeight = getDocumentHeight(); + var timeLapsed = 0; + var percentage, position; + + // Update URL + updateUrl(anchor, settings.updateURL); + + /** + * Stop the scroll animation when it reaches its target (or the bottom/top of page) + * @private + * @param {Number} position Current position on the page + * @param {Number} endLocation Scroll to location + * @param {Number} animationInterval How much to scroll on this loop + */ + var stopAnimateScroll = function (position, endLocation, animationInterval) { + var currentLocation = root.pageYOffset; + if ( position == endLocation || currentLocation == endLocation || ( (root.innerHeight + currentLocation) >= documentHeight ) ) { + clearInterval(animationInterval); + anchorElem.focus(); + settings.callback( toggle, anchor ); // Run callbacks after animation complete + } + }; + + /** + * Loop scrolling animation + * @private + */ + var loopAnimateScroll = function () { + timeLapsed += 16; + percentage = ( timeLapsed / parseInt(settings.speed, 10) ); + percentage = ( percentage > 1 ) ? 1 : percentage; + position = startLocation + ( distance * easingPattern(settings.easing, percentage) ); + root.scrollTo( 0, Math.floor(position) ); + stopAnimateScroll(position, endLocation, animationInterval); + }; + + /** + * Set interval timer + * @private + */ + var startAnimateScroll = function () { + animationInterval = setInterval(loopAnimateScroll, 16); + }; + + /** + * Reset position to fix weird iOS bug + * @link https://github.com/cferdinandi/smooth-scroll/issues/45 + */ + if ( root.pageYOffset === 0 ) { + root.scrollTo( 0, 0 ); + } + + // Start scrolling animation + startAnimateScroll(); + + }; + + /** + * If smooth scroll element clicked, animate scroll + * @private + */ + var eventHandler = function (event) { + var toggle = getClosest( event.target, settings.selector ); + if ( toggle && toggle.tagName.toLowerCase() === 'a' ) { + event.preventDefault(); // Prevent default click event + smoothScroll.animateScroll( toggle, toggle.hash, settings); // Animate scroll + } + }; + + /** + * On window scroll and resize, only run events at a rate of 15fps for better performance + * @private + * @param {Function} eventTimeout Timeout function + * @param {Object} settings + */ + var eventThrottler = function (event) { + if ( !eventTimeout ) { + eventTimeout = setTimeout(function() { + eventTimeout = null; // Reset timeout + headerHeight = getHeaderHeight( fixedHeader ); // Get the height of a fixed header if one exists + }, 66); + } + }; + + /** + * Destroy the current initialization. + * @public + */ + smoothScroll.destroy = function () { + + // If plugin isn't already initialized, stop + if ( !settings ) return; + + // Remove event listeners + root.document.removeEventListener( 'click', eventHandler, false ); + root.removeEventListener( 'resize', eventThrottler, false ); + + // Reset varaibles + settings = null; + eventTimeout = null; + fixedHeader = null; + headerHeight = null; + }; + + /** + * Initialize Smooth Scroll + * @public + * @param {Object} options User settings + */ + smoothScroll.init = function ( options ) { + + // feature test + if ( !supports ) return; + + // Destroy any existing initializations + smoothScroll.destroy(); + + // Selectors and variables + settings = extend( defaults, options || {} ); // Merge user options with defaults + fixedHeader = root.document.querySelector( settings.selectorHeader ); // Get the fixed header + headerHeight = getHeaderHeight( fixedHeader ); + + // When a toggle is clicked, run the click handler + root.document.addEventListener('click', eventHandler, false ); + if ( fixedHeader ) { root.addEventListener( 'resize', eventThrottler, false ); } + + }; + + + // + // Public APIs + // + + return smoothScroll; + +}); diff --git a/bower_components/smooth_scroll/dist/js/smooth-scroll.min.js b/bower_components/smooth_scroll/dist/js/smooth-scroll.min.js new file mode 100755 index 0000000..fb7d9ca --- /dev/null +++ b/bower_components/smooth_scroll/dist/js/smooth-scroll.min.js @@ -0,0 +1,2 @@ +/*! smooth-scroll v7.1.1 | (c) 2015 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */ +!function(e,t){"function"==typeof define&&define.amd?define([],t(e)):"object"==typeof exports?module.exports=t(e):e.smoothScroll=t(e)}("undefined"!=typeof global?global:this.window||this.global,function(e){"use strict";var t,n,o,r,a={},u="querySelector"in document&&"addEventListener"in e,c={selector:"[data-scroll]",selectorHeader:"[data-scroll-header]",speed:500,easing:"easeInOutCubic",offset:0,updateURL:!0,callback:function(){}},i=function(){var e={},t=!1,n=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(t=arguments[0],n++);for(var r=function(n){for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t&&"[object Object]"===Object.prototype.toString.call(n[o])?e[o]=i(!0,e[o],n[o]):e[o]=n[o])};o>n;n++){var a=arguments[n];r(a)}return e},s=function(e){return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight)},l=function(e,t){var n,o,r=t.charAt(0),a="classList"in document.documentElement;for("["===r&&(t=t.substr(1,t.length-2),n=t.split("="),n.length>1&&(o=!0,n[1]=n[1].replace(/"/g,"").replace(/'/g,"")));e&&e!==document;e=e.parentNode){if("."===r)if(a){if(e.classList.contains(t.substr(1)))return e}else if(new RegExp("(^|\\s)"+t.substr(1)+"(\\s|$)").test(e.className))return e;if("#"===r&&e.id===t.substr(1))return e;if("["===r&&e.hasAttribute(n[0])){if(!o)return e;if(e.getAttribute(n[0])===n[1])return e}if(e.tagName.toLowerCase()===t)return e}return null},f=function(e){for(var t,n=String(e),o=n.length,r=-1,a="",u=n.charCodeAt(0);++r=1&&31>=t||127==t||0===r&&t>=48&&57>=t||1===r&&t>=48&&57>=t&&45===u?"\\"+t.toString(16)+" ":t>=128||45===t||95===t||t>=48&&57>=t||t>=65&&90>=t||t>=97&&122>=t?n.charAt(r):"\\"+n.charAt(r)}return a},d=function(e,t){var n;return"easeInQuad"===e&&(n=t*t),"easeOutQuad"===e&&(n=t*(2-t)),"easeInOutQuad"===e&&(n=.5>t?2*t*t:-1+(4-2*t)*t),"easeInCubic"===e&&(n=t*t*t),"easeOutCubic"===e&&(n=--t*t*t+1),"easeInOutCubic"===e&&(n=.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e&&(n=t*t*t*t),"easeOutQuart"===e&&(n=1- --t*t*t*t),"easeInOutQuart"===e&&(n=.5>t?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e&&(n=t*t*t*t*t),"easeOutQuint"===e&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e&&(n=.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t),n||t},m=function(e,t,n){var o=0;if(e.offsetParent)do o+=e.offsetTop,e=e.offsetParent;while(e);return o=o-t-n,o>=0?o:0},h=function(){return Math.max(e.document.body.scrollHeight,e.document.documentElement.scrollHeight,e.document.body.offsetHeight,e.document.documentElement.offsetHeight,e.document.body.clientHeight,e.document.documentElement.clientHeight)},p=function(e){return e&&"object"==typeof JSON&&"function"==typeof JSON.parse?JSON.parse(e):{}},g=function(t,n){e.history.pushState&&(n||"true"===n)&&"file:"!==e.location.protocol&&e.history.pushState(null,null,[e.location.protocol,"//",e.location.host,e.location.pathname,e.location.search,t].join(""))},b=function(e){return null===e?0:s(e)+e.offsetTop};a.animateScroll=function(t,n,a){var u=p(t?t.getAttribute("data-options"):null),s=i(s||c,a||{},u);n="#"+f(n.substr(1));var l="#"===n?e.document.documentElement:e.document.querySelector(n),v=e.pageYOffset;o||(o=e.document.querySelector(s.selectorHeader)),r||(r=b(o));var y,O,S,I=m(l,r,parseInt(s.offset,10)),H=I-v,E=h(),L=0;g(n,s.updateURL);var j=function(o,r,a){var u=e.pageYOffset;(o==r||u==r||e.innerHeight+u>=E)&&(clearInterval(a),l.focus(),s.callback(t,n))},w=function(){L+=16,O=L/parseInt(s.speed,10),O=O>1?1:O,S=v+H*d(s.easing,O),e.scrollTo(0,Math.floor(S)),j(S,I,y)},C=function(){y=setInterval(w,16)};0===e.pageYOffset&&e.scrollTo(0,0),C()};var v=function(e){var n=l(e.target,t.selector);n&&"a"===n.tagName.toLowerCase()&&(e.preventDefault(),a.animateScroll(n,n.hash,t))},y=function(e){n||(n=setTimeout(function(){n=null,r=b(o)},66))};return a.destroy=function(){t&&(e.document.removeEventListener("click",v,!1),e.removeEventListener("resize",y,!1),t=null,n=null,o=null,r=null)},a.init=function(n){u&&(a.destroy(),t=i(c,n||{}),o=e.document.querySelector(t.selectorHeader),r=b(o),e.document.addEventListener("click",v,!1),o&&e.addEventListener("resize",y,!1))},a}); \ No newline at end of file diff --git a/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.js b/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.js new file mode 100755 index 0000000..20b588a --- /dev/null +++ b/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.js @@ -0,0 +1,484 @@ +/*! + * smooth-scroll v7.1.1: Animate scrolling to anchor links + * (c) 2015 Chris Ferdinandi + * MIT License + * http://github.com/cferdinandi/smooth-scroll + */ + +(function (root, factory) { + if ( typeof define === 'function' && define.amd ) { + define([], factory(root)); + } else if ( typeof exports === 'object' ) { + module.exports = factory(root); + } else { + root.smoothScroll = factory(root); + } +})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) { + + 'use strict'; + + // + // Variables + // + + var smoothScroll = {}; // Object for public APIs + var supports = 'querySelector' in document && 'addEventListener' in root; // Feature test + var settings, eventTimeout, fixedHeader, headerHeight; + + // Default settings + var defaults = { + selector: '[data-scroll]', + selectorHeader: '[data-scroll-header]', + speed: 500, + easing: 'easeInOutCubic', + offset: 0, + updateURL: true, + callback: function () {} + }; + + + // + // Methods + // + + /** + * Merge two or more objects. Returns a new object. + * @private + * @param {Boolean} deep If true, do a deep (or recursive) merge [optional] + * @param {Object} objects The objects to merge together + * @returns {Object} Merged values of defaults and options + */ + var extend = function () { + + // Variables + var extended = {}; + var deep = false; + var i = 0; + var length = arguments.length; + + // Check if a deep merge + if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { + deep = arguments[0]; + i++; + } + + // Merge the object into the extended object + var merge = function (obj) { + for ( var prop in obj ) { + if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { + // If deep merge and property is an object, merge properties + if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { + extended[prop] = extend( true, extended[prop], obj[prop] ); + } else { + extended[prop] = obj[prop]; + } + } + } + }; + + // Loop through each object and conduct a merge + for ( ; i < length; i++ ) { + var obj = arguments[i]; + merge(obj); + } + + return extended; + + }; + + /** + * Get the height of an element. + * @private + * @param {Node} elem The element to get the height of + * @return {Number} The element's height in pixels + */ + var getHeight = function ( elem ) { + return Math.max( elem.scrollHeight, elem.offsetHeight, elem.clientHeight ); + }; + + /** + * Get the closest matching element up the DOM tree. + * @private + * @param {Element} elem Starting element + * @param {String} selector Selector to match against (class, ID, data attribute, or tag) + * @return {Boolean|Element} Returns null if not match found + */ + var getClosest = function ( elem, selector ) { + + // Variables + var firstChar = selector.charAt(0); + var supports = 'classList' in document.documentElement; + var attribute, value; + + // If selector is a data attribute, split attribute from value + if ( firstChar === '[' ) { + selector = selector.substr(1, selector.length - 2); + attribute = selector.split( '=' ); + + if ( attribute.length > 1 ) { + value = true; + attribute[1] = attribute[1].replace( /"/g, '' ).replace( /'/g, '' ); + } + } + + // Get closest match + for ( ; elem && elem !== document; elem = elem.parentNode ) { + + // If selector is a class + if ( firstChar === '.' ) { + if ( supports ) { + if ( elem.classList.contains( selector.substr(1) ) ) { + return elem; + } + } else { + if ( new RegExp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test( elem.className ) ) { + return elem; + } + } + } + + // If selector is an ID + if ( firstChar === '#' ) { + if ( elem.id === selector.substr(1) ) { + return elem; + } + } + + // If selector is a data attribute + if ( firstChar === '[' ) { + if ( elem.hasAttribute( attribute[0] ) ) { + if ( value ) { + if ( elem.getAttribute( attribute[0] ) === attribute[1] ) { + return elem; + } + } else { + return elem; + } + } + } + + // If selector is a tag + if ( elem.tagName.toLowerCase() === selector ) { + return elem; + } + + } + + return null; + + }; + + /** + * Escape special characters for use with querySelector + * @private + * @param {String} id The anchor ID to escape + * @author Mathias Bynens + * @link https://github.com/mathiasbynens/CSS.escape + */ + var escapeCharacters = function ( id ) { + var string = String(id); + var length = string.length; + var index = -1; + var codeUnit; + var result = ''; + var firstCodeUnit = string.charCodeAt(0); + while (++index < length) { + codeUnit = string.charCodeAt(index); + // Note: there’s no need to special-case astral symbols, surrogate + // pairs, or lone surrogates. + + // If the character is NULL (U+0000), then throw an + // `InvalidCharacterError` exception and terminate these steps. + if (codeUnit === 0x0000) { + throw new InvalidCharacterError( + 'Invalid character: the input contains U+0000.' + ); + } + + if ( + // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is + // U+007F, […] + (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F || + // If the character is the first character and is in the range [0-9] + // (U+0030 to U+0039), […] + (index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) || + // If the character is the second character and is in the range [0-9] + // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] + ( + index === 1 && + codeUnit >= 0x0030 && codeUnit <= 0x0039 && + firstCodeUnit === 0x002D + ) + ) { + // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point + result += '\\' + codeUnit.toString(16) + ' '; + continue; + } + + // If the character is not handled by one of the above rules and is + // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or + // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to + // U+005A), or [a-z] (U+0061 to U+007A), […] + if ( + codeUnit >= 0x0080 || + codeUnit === 0x002D || + codeUnit === 0x005F || + codeUnit >= 0x0030 && codeUnit <= 0x0039 || + codeUnit >= 0x0041 && codeUnit <= 0x005A || + codeUnit >= 0x0061 && codeUnit <= 0x007A + ) { + // the character itself + result += string.charAt(index); + continue; + } + + // Otherwise, the escaped character. + // http://dev.w3.org/csswg/cssom/#escape-a-character + result += '\\' + string.charAt(index); + + } + return result; + }; + + /** + * Calculate the easing pattern + * @private + * @link https://gist.github.com/gre/1650294 + * @param {String} type Easing pattern + * @param {Number} time Time animation should take to complete + * @returns {Number} + */ + var easingPattern = function ( type, time ) { + var pattern; + if ( type === 'easeInQuad' ) pattern = time * time; // accelerating from zero velocity + if ( type === 'easeOutQuad' ) pattern = time * (2 - time); // decelerating to zero velocity + if ( type === 'easeInOutQuad' ) pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration + if ( type === 'easeInCubic' ) pattern = time * time * time; // accelerating from zero velocity + if ( type === 'easeOutCubic' ) pattern = (--time) * time * time + 1; // decelerating to zero velocity + if ( type === 'easeInOutCubic' ) pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration + if ( type === 'easeInQuart' ) pattern = time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuart' ) pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuart' ) pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration + if ( type === 'easeInQuint' ) pattern = time * time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuint' ) pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuint' ) pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration + return pattern || time; // no easing, no acceleration + }; + + /** + * Calculate how far to scroll + * @private + * @param {Element} anchor The anchor element to scroll to + * @param {Number} headerHeight Height of a fixed header, if any + * @param {Number} offset Number of pixels by which to offset scroll + * @returns {Number} + */ + var getEndLocation = function ( anchor, headerHeight, offset ) { + var location = 0; + if (anchor.offsetParent) { + do { + location += anchor.offsetTop; + anchor = anchor.offsetParent; + } while (anchor); + } + location = location - headerHeight - offset; + return location >= 0 ? location : 0; + }; + + /** + * Determine the document's height + * @private + * @returns {Number} + */ + var getDocumentHeight = function () { + return Math.max( + root.document.body.scrollHeight, root.document.documentElement.scrollHeight, + root.document.body.offsetHeight, root.document.documentElement.offsetHeight, + root.document.body.clientHeight, root.document.documentElement.clientHeight + ); + }; + + /** + * Convert data-options attribute into an object of key/value pairs + * @private + * @param {String} options Link-specific options as a data attribute string + * @returns {Object} + */ + var getDataOptions = function ( options ) { + return !options || !(typeof JSON === 'object' && typeof JSON.parse === 'function') ? {} : JSON.parse( options ); + }; + + /** + * Update the URL + * @private + * @param {Element} anchor The element to scroll to + * @param {Boolean} url Whether or not to update the URL history + */ + var updateUrl = function ( anchor, url ) { + if ( root.history.pushState && (url || url === 'true') && root.location.protocol !== 'file:' ) { + root.history.pushState( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') ); + } + }; + + var getHeaderHeight = function ( header ) { + return header === null ? 0 : ( getHeight( header ) + header.offsetTop ); + }; + + /** + * Start/stop the scrolling animation + * @public + * @param {Element} toggle The element that toggled the scroll event + * @param {Element} anchor The element to scroll to + * @param {Object} options + */ + smoothScroll.animateScroll = function ( toggle, anchor, options ) { + + // Options and overrides + var overrides = getDataOptions( toggle ? toggle.getAttribute('data-options') : null ); + var settings = extend( settings || defaults, options || {}, overrides ); // Merge user options with defaults + anchor = '#' + escapeCharacters(anchor.substr(1)); // Escape special characters and leading numbers + + // Selectors and variables + var anchorElem = anchor === '#' ? root.document.documentElement : root.document.querySelector(anchor); + var startLocation = root.pageYOffset; // Current location on the page + if ( !fixedHeader ) { fixedHeader = root.document.querySelector( settings.selectorHeader ); } // Get the fixed header if not already set + if ( !headerHeight ) { headerHeight = getHeaderHeight( fixedHeader ); } // Get the height of a fixed header if one exists and not already set + var endLocation = getEndLocation( anchorElem, headerHeight, parseInt(settings.offset, 10) ); // Scroll to location + var animationInterval; // interval timer + var distance = endLocation - startLocation; // distance to travel + var documentHeight = getDocumentHeight(); + var timeLapsed = 0; + var percentage, position; + + // Update URL + updateUrl(anchor, settings.updateURL); + + /** + * Stop the scroll animation when it reaches its target (or the bottom/top of page) + * @private + * @param {Number} position Current position on the page + * @param {Number} endLocation Scroll to location + * @param {Number} animationInterval How much to scroll on this loop + */ + var stopAnimateScroll = function (position, endLocation, animationInterval) { + var currentLocation = root.pageYOffset; + if ( position == endLocation || currentLocation == endLocation || ( (root.innerHeight + currentLocation) >= documentHeight ) ) { + clearInterval(animationInterval); + anchorElem.focus(); + settings.callback( toggle, anchor ); // Run callbacks after animation complete + } + }; + + /** + * Loop scrolling animation + * @private + */ + var loopAnimateScroll = function () { + timeLapsed += 16; + percentage = ( timeLapsed / parseInt(settings.speed, 10) ); + percentage = ( percentage > 1 ) ? 1 : percentage; + position = startLocation + ( distance * easingPattern(settings.easing, percentage) ); + root.scrollTo( 0, Math.floor(position) ); + stopAnimateScroll(position, endLocation, animationInterval); + }; + + /** + * Set interval timer + * @private + */ + var startAnimateScroll = function () { + animationInterval = setInterval(loopAnimateScroll, 16); + }; + + /** + * Reset position to fix weird iOS bug + * @link https://github.com/cferdinandi/smooth-scroll/issues/45 + */ + if ( root.pageYOffset === 0 ) { + root.scrollTo( 0, 0 ); + } + + // Start scrolling animation + startAnimateScroll(); + + }; + + /** + * If smooth scroll element clicked, animate scroll + * @private + */ + var eventHandler = function (event) { + var toggle = getClosest( event.target, settings.selector ); + if ( toggle && toggle.tagName.toLowerCase() === 'a' ) { + event.preventDefault(); // Prevent default click event + smoothScroll.animateScroll( toggle, toggle.hash, settings); // Animate scroll + } + }; + + /** + * On window scroll and resize, only run events at a rate of 15fps for better performance + * @private + * @param {Function} eventTimeout Timeout function + * @param {Object} settings + */ + var eventThrottler = function (event) { + if ( !eventTimeout ) { + eventTimeout = setTimeout(function() { + eventTimeout = null; // Reset timeout + headerHeight = getHeaderHeight( fixedHeader ); // Get the height of a fixed header if one exists + }, 66); + } + }; + + /** + * Destroy the current initialization. + * @public + */ + smoothScroll.destroy = function () { + + // If plugin isn't already initialized, stop + if ( !settings ) return; + + // Remove event listeners + root.document.removeEventListener( 'click', eventHandler, false ); + root.removeEventListener( 'resize', eventThrottler, false ); + + // Reset varaibles + settings = null; + eventTimeout = null; + fixedHeader = null; + headerHeight = null; + }; + + /** + * Initialize Smooth Scroll + * @public + * @param {Object} options User settings + */ + smoothScroll.init = function ( options ) { + + // feature test + if ( !supports ) return; + + // Destroy any existing initializations + smoothScroll.destroy(); + + // Selectors and variables + settings = extend( defaults, options || {} ); // Merge user options with defaults + fixedHeader = root.document.querySelector( settings.selectorHeader ); // Get the fixed header + headerHeight = getHeaderHeight( fixedHeader ); + + // When a toggle is clicked, run the click handler + root.document.addEventListener('click', eventHandler, false ); + if ( fixedHeader ) { root.addEventListener( 'resize', eventThrottler, false ); } + + }; + + + // + // Public APIs + // + + return smoothScroll; + +}); diff --git a/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.min.js b/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.min.js new file mode 100755 index 0000000..fb7d9ca --- /dev/null +++ b/bower_components/smooth_scroll/docs/dist/js/smooth-scroll.min.js @@ -0,0 +1,2 @@ +/*! smooth-scroll v7.1.1 | (c) 2015 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */ +!function(e,t){"function"==typeof define&&define.amd?define([],t(e)):"object"==typeof exports?module.exports=t(e):e.smoothScroll=t(e)}("undefined"!=typeof global?global:this.window||this.global,function(e){"use strict";var t,n,o,r,a={},u="querySelector"in document&&"addEventListener"in e,c={selector:"[data-scroll]",selectorHeader:"[data-scroll-header]",speed:500,easing:"easeInOutCubic",offset:0,updateURL:!0,callback:function(){}},i=function(){var e={},t=!1,n=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(t=arguments[0],n++);for(var r=function(n){for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t&&"[object Object]"===Object.prototype.toString.call(n[o])?e[o]=i(!0,e[o],n[o]):e[o]=n[o])};o>n;n++){var a=arguments[n];r(a)}return e},s=function(e){return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight)},l=function(e,t){var n,o,r=t.charAt(0),a="classList"in document.documentElement;for("["===r&&(t=t.substr(1,t.length-2),n=t.split("="),n.length>1&&(o=!0,n[1]=n[1].replace(/"/g,"").replace(/'/g,"")));e&&e!==document;e=e.parentNode){if("."===r)if(a){if(e.classList.contains(t.substr(1)))return e}else if(new RegExp("(^|\\s)"+t.substr(1)+"(\\s|$)").test(e.className))return e;if("#"===r&&e.id===t.substr(1))return e;if("["===r&&e.hasAttribute(n[0])){if(!o)return e;if(e.getAttribute(n[0])===n[1])return e}if(e.tagName.toLowerCase()===t)return e}return null},f=function(e){for(var t,n=String(e),o=n.length,r=-1,a="",u=n.charCodeAt(0);++r=1&&31>=t||127==t||0===r&&t>=48&&57>=t||1===r&&t>=48&&57>=t&&45===u?"\\"+t.toString(16)+" ":t>=128||45===t||95===t||t>=48&&57>=t||t>=65&&90>=t||t>=97&&122>=t?n.charAt(r):"\\"+n.charAt(r)}return a},d=function(e,t){var n;return"easeInQuad"===e&&(n=t*t),"easeOutQuad"===e&&(n=t*(2-t)),"easeInOutQuad"===e&&(n=.5>t?2*t*t:-1+(4-2*t)*t),"easeInCubic"===e&&(n=t*t*t),"easeOutCubic"===e&&(n=--t*t*t+1),"easeInOutCubic"===e&&(n=.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e&&(n=t*t*t*t),"easeOutQuart"===e&&(n=1- --t*t*t*t),"easeInOutQuart"===e&&(n=.5>t?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e&&(n=t*t*t*t*t),"easeOutQuint"===e&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e&&(n=.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t),n||t},m=function(e,t,n){var o=0;if(e.offsetParent)do o+=e.offsetTop,e=e.offsetParent;while(e);return o=o-t-n,o>=0?o:0},h=function(){return Math.max(e.document.body.scrollHeight,e.document.documentElement.scrollHeight,e.document.body.offsetHeight,e.document.documentElement.offsetHeight,e.document.body.clientHeight,e.document.documentElement.clientHeight)},p=function(e){return e&&"object"==typeof JSON&&"function"==typeof JSON.parse?JSON.parse(e):{}},g=function(t,n){e.history.pushState&&(n||"true"===n)&&"file:"!==e.location.protocol&&e.history.pushState(null,null,[e.location.protocol,"//",e.location.host,e.location.pathname,e.location.search,t].join(""))},b=function(e){return null===e?0:s(e)+e.offsetTop};a.animateScroll=function(t,n,a){var u=p(t?t.getAttribute("data-options"):null),s=i(s||c,a||{},u);n="#"+f(n.substr(1));var l="#"===n?e.document.documentElement:e.document.querySelector(n),v=e.pageYOffset;o||(o=e.document.querySelector(s.selectorHeader)),r||(r=b(o));var y,O,S,I=m(l,r,parseInt(s.offset,10)),H=I-v,E=h(),L=0;g(n,s.updateURL);var j=function(o,r,a){var u=e.pageYOffset;(o==r||u==r||e.innerHeight+u>=E)&&(clearInterval(a),l.focus(),s.callback(t,n))},w=function(){L+=16,O=L/parseInt(s.speed,10),O=O>1?1:O,S=v+H*d(s.easing,O),e.scrollTo(0,Math.floor(S)),j(S,I,y)},C=function(){y=setInterval(w,16)};0===e.pageYOffset&&e.scrollTo(0,0),C()};var v=function(e){var n=l(e.target,t.selector);n&&"a"===n.tagName.toLowerCase()&&(e.preventDefault(),a.animateScroll(n,n.hash,t))},y=function(e){n||(n=setTimeout(function(){n=null,r=b(o)},66))};return a.destroy=function(){t&&(e.document.removeEventListener("click",v,!1),e.removeEventListener("resize",y,!1),t=null,n=null,o=null,r=null)},a.init=function(n){u&&(a.destroy(),t=i(c,n||{}),o=e.document.querySelector(t.selectorHeader),r=b(o),e.document.addEventListener("click",v,!1),o&&e.addEventListener("resize",y,!1))},a}); \ No newline at end of file diff --git a/bower_components/smooth_scroll/docs/index.html b/bower_components/smooth_scroll/docs/index.html new file mode 100644 index 0000000..c002dca --- /dev/null +++ b/bower_components/smooth_scroll/docs/index.html @@ -0,0 +1,86 @@ + + + + + + Smooth Scroll + + + + + + + + +
+ + + +
+

+ Linear
+ Linear (no other options)
+

+ +

+ Ease-In
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-In-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Bazinga!

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Back to the top

+
+
+ + + + + + + + \ No newline at end of file diff --git a/bower_components/smooth_scroll/gulpfile.js b/bower_components/smooth_scroll/gulpfile.js new file mode 100755 index 0000000..36e705d --- /dev/null +++ b/bower_components/smooth_scroll/gulpfile.js @@ -0,0 +1,226 @@ +/** + * Gulp Packages + */ + +// General +var gulp = require('gulp'); +var fs = require('fs'); +var del = require('del'); +var lazypipe = require('lazypipe'); +var plumber = require('gulp-plumber'); +var flatten = require('gulp-flatten'); +var tap = require('gulp-tap'); +var rename = require('gulp-rename'); +var header = require('gulp-header'); +var footer = require('gulp-footer'); +var watch = require('gulp-watch'); +var livereload = require('gulp-livereload'); +var package = require('./package.json'); + +// Scripts and tests +var jshint = require('gulp-jshint'); +var stylish = require('jshint-stylish'); +var concat = require('gulp-concat'); +var uglify = require('gulp-uglify'); +var karma = require('gulp-karma'); + +// Docs +var markdown = require('gulp-markdown'); +var fileinclude = require('gulp-file-include'); + + +/** + * Paths to project folders + */ + +var paths = { + input: 'src/**/*', + output: 'dist/', + scripts: { + input: 'src/js/*', + output: 'dist/js/' + }, + test: { + input: 'src/js/**/*.js', + karma: 'test/karma.conf.js', + spec: 'test/spec/**/*.js', + coverage: 'test/coverage/', + results: 'test/results/' + }, + docs: { + input: 'src/docs/*.{html,md,markdown}', + output: 'docs/', + templates: 'src/docs/_templates/', + assets: 'src/docs/assets/**' + } +}; + + +/** + * Template for banner to add to file headers + */ + +var banner = { + full : + '/*!\n' + + ' * <%= package.name %> v<%= package.version %>: <%= package.description %>\n' + + ' * (c) ' + new Date().getFullYear() + ' <%= package.author.name %>\n' + + ' * MIT License\n' + + ' * <%= package.repository.url %>\n' + + ' */\n\n', + min : + '/*!' + + ' <%= package.name %> v<%= package.version %>' + + ' | (c) ' + new Date().getFullYear() + ' <%= package.author.name %>' + + ' | MIT License' + + ' | <%= package.repository.url %>' + + ' */\n' +}; + + +/** + * Gulp Taks + */ + +// Lint, minify, and concatenate scripts +gulp.task('build:scripts', ['clean:dist'], function() { + var jsTasks = lazypipe() + .pipe(header, banner.full, { package : package }) + .pipe(gulp.dest, paths.scripts.output) + .pipe(rename, { suffix: '.min' }) + .pipe(uglify) + .pipe(header, banner.min, { package : package }) + .pipe(gulp.dest, paths.scripts.output); + + return gulp.src(paths.scripts.input) + .pipe(plumber()) + .pipe(tap(function (file, t) { + if ( file.isDirectory() ) { + var name = file.relative + '.js'; + return gulp.src(file.path + '/*.js') + .pipe(concat(name)) + .pipe(jsTasks()); + } + })) + .pipe(jsTasks()); +}); + +// Lint scripts +gulp.task('lint:scripts', function () { + return gulp.src(paths.scripts.input) + .pipe(plumber()) + .pipe(jshint()) + .pipe(jshint.reporter('jshint-stylish')); +}); + +// Remove pre-existing content from output and test folders +gulp.task('clean:dist', function () { + del.sync([ + paths.output + ]); +}); + +// Remove pre-existing content from text folders +gulp.task('clean:test', function () { + del.sync([ + paths.test.coverage, + paths.test.results + ]); +}); + +// Run unit tests +gulp.task('test:scripts', function() { + return gulp.src([paths.test.input].concat([paths.test.spec])) + .pipe(plumber()) + .pipe(karma({ configFile: paths.test.karma })) + .on('error', function(err) { throw err; }); +}); + +// Generate documentation +gulp.task('build:docs', ['compile', 'clean:docs'], function() { + return gulp.src(paths.docs.input) + .pipe(plumber()) + .pipe(fileinclude({ + prefix: '@@', + basepath: '@file' + })) + .pipe(tap(function (file, t) { + if ( /\.md|\.markdown/.test(file.path) ) { + return t.through(markdown); + } + })) + .pipe(header(fs.readFileSync(paths.docs.templates + '/_header.html', 'utf8'))) + .pipe(footer(fs.readFileSync(paths.docs.templates + '/_footer.html', 'utf8'))) + .pipe(gulp.dest(paths.docs.output)); +}); + +// Copy distribution files to docs +gulp.task('copy:dist', ['compile', 'clean:docs'], function() { + return gulp.src(paths.output + '/**') + .pipe(plumber()) + .pipe(gulp.dest(paths.docs.output + '/dist')); +}); + +// Copy documentation assets to docs +gulp.task('copy:assets', ['clean:docs'], function() { + return gulp.src(paths.docs.assets) + .pipe(plumber()) + .pipe(gulp.dest(paths.docs.output + '/assets')); +}); + +// Remove prexisting content from docs folder +gulp.task('clean:docs', function () { + return del.sync(paths.docs.output); +}); + +// Spin up livereload server and listen for file changes +gulp.task('listen', function () { + livereload.listen(); + gulp.watch(paths.input).on('change', function(file) { + gulp.start('default'); + gulp.start('refresh'); + }); +}); + +// Run livereload after file change +gulp.task('refresh', ['compile', 'docs'], function () { + livereload.changed(); +}); + + +/** + * Task Runners + */ + +// Compile files +gulp.task('compile', [ + 'lint:scripts', + 'clean:dist', + 'build:scripts' +]); + +// Generate documentation +gulp.task('docs', [ + 'clean:docs', + 'build:docs', + 'copy:dist', + 'copy:assets' +]); + +// Compile files and generate docs (default) +gulp.task('default', [ + 'compile', + 'docs' +]); + +// Compile files and generate docs when something changes +gulp.task('watch', [ + 'listen', + 'default' +]); + +// Run unit tests +gulp.task('test', [ + 'default', + 'test:scripts' +]); \ No newline at end of file diff --git a/bower_components/smooth_scroll/index.html b/bower_components/smooth_scroll/index.html new file mode 100644 index 0000000..459ca3e --- /dev/null +++ b/bower_components/smooth_scroll/index.html @@ -0,0 +1,86 @@ + + + + + Smooth Scroll + + + + + + + +
+ +

Smooth Scroll

+

A lightweight script to animate scrolling to anchor links.

+

Smooth Scroll on GitHub

+ +

+ +

+ Linear
+ Linear (no other options)
+

+ +

+ Ease-In
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-In-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Bazinga!

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Back to the top

+ +
+ + + + + + + + + diff --git a/bower_components/smooth_scroll/package.json b/bower_components/smooth_scroll/package.json new file mode 100755 index 0000000..3f052fe --- /dev/null +++ b/bower_components/smooth_scroll/package.json @@ -0,0 +1,43 @@ +{ + "name": "smooth-scroll", + "version": "7.1.1", + "description": "Animate scrolling to anchor links", + "main": "./dist/js/smooth-scroll.js", + "author": { + "name": "Chris Ferdinandi", + "url": "http://gomakethings.com" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "http://github.com/cferdinandi/smooth-scroll" + }, + "devDependencies": { + "gulp": "^3.9.0", + "node-fs": "^0.1.7", + "del": "^1.2.0", + "lazypipe": "^0.2.4", + "gulp-plumber": "^1.0.1", + "gulp-flatten": "^0.0.4", + "gulp-tap": "^0.1.3", + "gulp-rename": "^1.2.2", + "gulp-header": "^1.2.2", + "gulp-footer": "^1.0.5", + "gulp-watch": "^4.2.4", + "gulp-livereload": "^3.8.0", + "gulp-jshint": "^1.11.1", + "jshint-stylish": "^2.0.1", + "gulp-concat": "^2.6.0", + "gulp-uglify": "^1.2.0", + "karma": "^0.12.37", + "gulp-karma": "^0.0.4", + "karma-coverage": "^0.4.2", + "jasmine": "^2.3.1", + "karma-jasmine": "^0.3.6", + "karma-phantomjs-launcher": "^0.2.0", + "karma-spec-reporter": "^0.0.19", + "karma-htmlfile-reporter": "^0.2.1", + "gulp-markdown": "^1.0.0", + "gulp-file-include": "^0.11.1" + } +} diff --git a/bower_components/smooth_scroll/src/docs/_templates/_footer.html b/bower_components/smooth_scroll/src/docs/_templates/_footer.html new file mode 100644 index 0000000..81c0ea3 --- /dev/null +++ b/bower_components/smooth_scroll/src/docs/_templates/_footer.html @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/bower_components/smooth_scroll/src/docs/_templates/_header.html b/bower_components/smooth_scroll/src/docs/_templates/_header.html new file mode 100644 index 0000000..2bd0e5c --- /dev/null +++ b/bower_components/smooth_scroll/src/docs/_templates/_header.html @@ -0,0 +1,30 @@ + + + + + + Smooth Scroll + + + + + + + + +
+ + + +
diff --git a/bower_components/smooth_scroll/src/docs/index.md b/bower_components/smooth_scroll/src/docs/index.md new file mode 100644 index 0000000..33b0e26 --- /dev/null +++ b/bower_components/smooth_scroll/src/docs/index.md @@ -0,0 +1,44 @@ +

+ Linear
+ Linear (no other options)
+

+ +

+ Ease-In
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-In-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ Ease-Out
+ Quad
+ Cubic
+ Quart
+ Quint +

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Bazinga!

+ +

+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
.
+ .
.
.
.
.
.
.
.
.
.
.
.
. +

+ +

Back to the top

\ No newline at end of file diff --git a/bower_components/smooth_scroll/src/js/smooth-scroll.js b/bower_components/smooth_scroll/src/js/smooth-scroll.js new file mode 100755 index 0000000..20f5900 --- /dev/null +++ b/bower_components/smooth_scroll/src/js/smooth-scroll.js @@ -0,0 +1,477 @@ +(function (root, factory) { + if ( typeof define === 'function' && define.amd ) { + define([], factory(root)); + } else if ( typeof exports === 'object' ) { + module.exports = factory(root); + } else { + root.smoothScroll = factory(root); + } +})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) { + + 'use strict'; + + // + // Variables + // + + var smoothScroll = {}; // Object for public APIs + var supports = 'querySelector' in document && 'addEventListener' in root; // Feature test + var settings, eventTimeout, fixedHeader, headerHeight; + + // Default settings + var defaults = { + selector: '[data-scroll]', + selectorHeader: '[data-scroll-header]', + speed: 500, + easing: 'easeInOutCubic', + offset: 0, + updateURL: true, + callback: function () {} + }; + + + // + // Methods + // + + /** + * Merge two or more objects. Returns a new object. + * @private + * @param {Boolean} deep If true, do a deep (or recursive) merge [optional] + * @param {Object} objects The objects to merge together + * @returns {Object} Merged values of defaults and options + */ + var extend = function () { + + // Variables + var extended = {}; + var deep = false; + var i = 0; + var length = arguments.length; + + // Check if a deep merge + if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { + deep = arguments[0]; + i++; + } + + // Merge the object into the extended object + var merge = function (obj) { + for ( var prop in obj ) { + if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { + // If deep merge and property is an object, merge properties + if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { + extended[prop] = extend( true, extended[prop], obj[prop] ); + } else { + extended[prop] = obj[prop]; + } + } + } + }; + + // Loop through each object and conduct a merge + for ( ; i < length; i++ ) { + var obj = arguments[i]; + merge(obj); + } + + return extended; + + }; + + /** + * Get the height of an element. + * @private + * @param {Node} elem The element to get the height of + * @return {Number} The element's height in pixels + */ + var getHeight = function ( elem ) { + return Math.max( elem.scrollHeight, elem.offsetHeight, elem.clientHeight ); + }; + + /** + * Get the closest matching element up the DOM tree. + * @private + * @param {Element} elem Starting element + * @param {String} selector Selector to match against (class, ID, data attribute, or tag) + * @return {Boolean|Element} Returns null if not match found + */ + var getClosest = function ( elem, selector ) { + + // Variables + var firstChar = selector.charAt(0); + var supports = 'classList' in document.documentElement; + var attribute, value; + + // If selector is a data attribute, split attribute from value + if ( firstChar === '[' ) { + selector = selector.substr(1, selector.length - 2); + attribute = selector.split( '=' ); + + if ( attribute.length > 1 ) { + value = true; + attribute[1] = attribute[1].replace( /"/g, '' ).replace( /'/g, '' ); + } + } + + // Get closest match + for ( ; elem && elem !== document; elem = elem.parentNode ) { + + // If selector is a class + if ( firstChar === '.' ) { + if ( supports ) { + if ( elem.classList.contains( selector.substr(1) ) ) { + return elem; + } + } else { + if ( new RegExp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test( elem.className ) ) { + return elem; + } + } + } + + // If selector is an ID + if ( firstChar === '#' ) { + if ( elem.id === selector.substr(1) ) { + return elem; + } + } + + // If selector is a data attribute + if ( firstChar === '[' ) { + if ( elem.hasAttribute( attribute[0] ) ) { + if ( value ) { + if ( elem.getAttribute( attribute[0] ) === attribute[1] ) { + return elem; + } + } else { + return elem; + } + } + } + + // If selector is a tag + if ( elem.tagName.toLowerCase() === selector ) { + return elem; + } + + } + + return null; + + }; + + /** + * Escape special characters for use with querySelector + * @private + * @param {String} id The anchor ID to escape + * @author Mathias Bynens + * @link https://github.com/mathiasbynens/CSS.escape + */ + var escapeCharacters = function ( id ) { + var string = String(id); + var length = string.length; + var index = -1; + var codeUnit; + var result = ''; + var firstCodeUnit = string.charCodeAt(0); + while (++index < length) { + codeUnit = string.charCodeAt(index); + // Note: there’s no need to special-case astral symbols, surrogate + // pairs, or lone surrogates. + + // If the character is NULL (U+0000), then throw an + // `InvalidCharacterError` exception and terminate these steps. + if (codeUnit === 0x0000) { + throw new InvalidCharacterError( + 'Invalid character: the input contains U+0000.' + ); + } + + if ( + // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is + // U+007F, […] + (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F || + // If the character is the first character and is in the range [0-9] + // (U+0030 to U+0039), […] + (index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) || + // If the character is the second character and is in the range [0-9] + // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] + ( + index === 1 && + codeUnit >= 0x0030 && codeUnit <= 0x0039 && + firstCodeUnit === 0x002D + ) + ) { + // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point + result += '\\' + codeUnit.toString(16) + ' '; + continue; + } + + // If the character is not handled by one of the above rules and is + // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or + // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to + // U+005A), or [a-z] (U+0061 to U+007A), […] + if ( + codeUnit >= 0x0080 || + codeUnit === 0x002D || + codeUnit === 0x005F || + codeUnit >= 0x0030 && codeUnit <= 0x0039 || + codeUnit >= 0x0041 && codeUnit <= 0x005A || + codeUnit >= 0x0061 && codeUnit <= 0x007A + ) { + // the character itself + result += string.charAt(index); + continue; + } + + // Otherwise, the escaped character. + // http://dev.w3.org/csswg/cssom/#escape-a-character + result += '\\' + string.charAt(index); + + } + return result; + }; + + /** + * Calculate the easing pattern + * @private + * @link https://gist.github.com/gre/1650294 + * @param {String} type Easing pattern + * @param {Number} time Time animation should take to complete + * @returns {Number} + */ + var easingPattern = function ( type, time ) { + var pattern; + if ( type === 'easeInQuad' ) pattern = time * time; // accelerating from zero velocity + if ( type === 'easeOutQuad' ) pattern = time * (2 - time); // decelerating to zero velocity + if ( type === 'easeInOutQuad' ) pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration + if ( type === 'easeInCubic' ) pattern = time * time * time; // accelerating from zero velocity + if ( type === 'easeOutCubic' ) pattern = (--time) * time * time + 1; // decelerating to zero velocity + if ( type === 'easeInOutCubic' ) pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration + if ( type === 'easeInQuart' ) pattern = time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuart' ) pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuart' ) pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration + if ( type === 'easeInQuint' ) pattern = time * time * time * time * time; // accelerating from zero velocity + if ( type === 'easeOutQuint' ) pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity + if ( type === 'easeInOutQuint' ) pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration + return pattern || time; // no easing, no acceleration + }; + + /** + * Calculate how far to scroll + * @private + * @param {Element} anchor The anchor element to scroll to + * @param {Number} headerHeight Height of a fixed header, if any + * @param {Number} offset Number of pixels by which to offset scroll + * @returns {Number} + */ + var getEndLocation = function ( anchor, headerHeight, offset ) { + var location = 0; + if (anchor.offsetParent) { + do { + location += anchor.offsetTop; + anchor = anchor.offsetParent; + } while (anchor); + } + location = location - headerHeight - offset; + return location >= 0 ? location : 0; + }; + + /** + * Determine the document's height + * @private + * @returns {Number} + */ + var getDocumentHeight = function () { + return Math.max( + root.document.body.scrollHeight, root.document.documentElement.scrollHeight, + root.document.body.offsetHeight, root.document.documentElement.offsetHeight, + root.document.body.clientHeight, root.document.documentElement.clientHeight + ); + }; + + /** + * Convert data-options attribute into an object of key/value pairs + * @private + * @param {String} options Link-specific options as a data attribute string + * @returns {Object} + */ + var getDataOptions = function ( options ) { + return !options || !(typeof JSON === 'object' && typeof JSON.parse === 'function') ? {} : JSON.parse( options ); + }; + + /** + * Update the URL + * @private + * @param {Element} anchor The element to scroll to + * @param {Boolean} url Whether or not to update the URL history + */ + var updateUrl = function ( anchor, url ) { + if ( root.history.pushState && (url || url === 'true') && root.location.protocol !== 'file:' ) { + root.history.pushState( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') ); + } + }; + + var getHeaderHeight = function ( header ) { + return header === null ? 0 : ( getHeight( header ) + header.offsetTop ); + }; + + /** + * Start/stop the scrolling animation + * @public + * @param {Element} toggle The element that toggled the scroll event + * @param {Element} anchor The element to scroll to + * @param {Object} options + */ + smoothScroll.animateScroll = function ( toggle, anchor, options ) { + + // Options and overrides + var overrides = getDataOptions( toggle ? toggle.getAttribute('data-options') : null ); + var settings = extend( settings || defaults, options || {}, overrides ); // Merge user options with defaults + anchor = '#' + escapeCharacters(anchor.substr(1)); // Escape special characters and leading numbers + + // Selectors and variables + var anchorElem = anchor === '#' ? root.document.documentElement : root.document.querySelector(anchor); + var startLocation = root.pageYOffset; // Current location on the page + if ( !fixedHeader ) { fixedHeader = root.document.querySelector( settings.selectorHeader ); } // Get the fixed header if not already set + if ( !headerHeight ) { headerHeight = getHeaderHeight( fixedHeader ); } // Get the height of a fixed header if one exists and not already set + var endLocation = getEndLocation( anchorElem, headerHeight, parseInt(settings.offset, 10) ); // Scroll to location + var animationInterval; // interval timer + var distance = endLocation - startLocation; // distance to travel + var documentHeight = getDocumentHeight(); + var timeLapsed = 0; + var percentage, position; + + // Update URL + updateUrl(anchor, settings.updateURL); + + /** + * Stop the scroll animation when it reaches its target (or the bottom/top of page) + * @private + * @param {Number} position Current position on the page + * @param {Number} endLocation Scroll to location + * @param {Number} animationInterval How much to scroll on this loop + */ + var stopAnimateScroll = function (position, endLocation, animationInterval) { + var currentLocation = root.pageYOffset; + if ( position == endLocation || currentLocation == endLocation || ( (root.innerHeight + currentLocation) >= documentHeight ) ) { + clearInterval(animationInterval); + anchorElem.focus(); + settings.callback( toggle, anchor ); // Run callbacks after animation complete + } + }; + + /** + * Loop scrolling animation + * @private + */ + var loopAnimateScroll = function () { + timeLapsed += 16; + percentage = ( timeLapsed / parseInt(settings.speed, 10) ); + percentage = ( percentage > 1 ) ? 1 : percentage; + position = startLocation + ( distance * easingPattern(settings.easing, percentage) ); + root.scrollTo( 0, Math.floor(position) ); + stopAnimateScroll(position, endLocation, animationInterval); + }; + + /** + * Set interval timer + * @private + */ + var startAnimateScroll = function () { + animationInterval = setInterval(loopAnimateScroll, 16); + }; + + /** + * Reset position to fix weird iOS bug + * @link https://github.com/cferdinandi/smooth-scroll/issues/45 + */ + if ( root.pageYOffset === 0 ) { + root.scrollTo( 0, 0 ); + } + + // Start scrolling animation + startAnimateScroll(); + + }; + + /** + * If smooth scroll element clicked, animate scroll + * @private + */ + var eventHandler = function (event) { + var toggle = getClosest( event.target, settings.selector ); + if ( toggle && toggle.tagName.toLowerCase() === 'a' ) { + event.preventDefault(); // Prevent default click event + smoothScroll.animateScroll( toggle, toggle.hash, settings); // Animate scroll + } + }; + + /** + * On window scroll and resize, only run events at a rate of 15fps for better performance + * @private + * @param {Function} eventTimeout Timeout function + * @param {Object} settings + */ + var eventThrottler = function (event) { + if ( !eventTimeout ) { + eventTimeout = setTimeout(function() { + eventTimeout = null; // Reset timeout + headerHeight = getHeaderHeight( fixedHeader ); // Get the height of a fixed header if one exists + }, 66); + } + }; + + /** + * Destroy the current initialization. + * @public + */ + smoothScroll.destroy = function () { + + // If plugin isn't already initialized, stop + if ( !settings ) return; + + // Remove event listeners + root.document.removeEventListener( 'click', eventHandler, false ); + root.removeEventListener( 'resize', eventThrottler, false ); + + // Reset varaibles + settings = null; + eventTimeout = null; + fixedHeader = null; + headerHeight = null; + }; + + /** + * Initialize Smooth Scroll + * @public + * @param {Object} options User settings + */ + smoothScroll.init = function ( options ) { + + // feature test + if ( !supports ) return; + + // Destroy any existing initializations + smoothScroll.destroy(); + + // Selectors and variables + settings = extend( defaults, options || {} ); // Merge user options with defaults + fixedHeader = root.document.querySelector( settings.selectorHeader ); // Get the fixed header + headerHeight = getHeaderHeight( fixedHeader ); + + // When a toggle is clicked, run the click handler + root.document.addEventListener('click', eventHandler, false ); + if ( fixedHeader ) { root.addEventListener( 'resize', eventThrottler, false ); } + + }; + + + // + // Public APIs + // + + return smoothScroll; + +}); diff --git a/bower_components/smooth_scroll/test/karma.conf.js b/bower_components/smooth_scroll/test/karma.conf.js new file mode 100755 index 0000000..c140e5e --- /dev/null +++ b/bower_components/smooth_scroll/test/karma.conf.js @@ -0,0 +1,26 @@ +module.exports = function (config) { + config.set({ + basePath : '', + autoWatch : true, + frameworks: ['jasmine'], + browsers : ['PhantomJS'], + plugins : [ + 'karma-spec-reporter', + 'karma-phantomjs-launcher', + 'karma-jasmine', + 'karma-coverage', + 'karma-htmlfile-reporter' + ], + reporters : ['spec', 'coverage', 'html'], + preprocessors: { + '../src/js/**/*.js': 'coverage' + }, + coverageReporter: { + type : 'html', + dir : 'coverage/' + }, + htmlReporter: { + outputFile: 'results/unit-tests.html' + } + }); +}; \ No newline at end of file diff --git a/bower_components/smooth_scroll/test/spec/spec-smoothScroll.js b/bower_components/smooth_scroll/test/spec/spec-smoothScroll.js new file mode 100755 index 0000000..a9f445d --- /dev/null +++ b/bower_components/smooth_scroll/test/spec/spec-smoothScroll.js @@ -0,0 +1,131 @@ +describe('Smooth Scroll', function () { + + // + // Helper Methods + // + + /** + * Create a link element, add it to the body. + * @public + * @param {String} the href attribute of the new link + * @param {Boolean} whether to add data-scroll to the link or not + * @returns {Element} + */ + var injectElem = function (href, smooth) { + var elt = document.createElement('a'); + elt.href = href; + if (smooth) { + elt.setAttribute('data-scroll', true); + } + document.body.appendChild(elt); + return elt; + }; + + /** + * Simulate a click event. + * @public + * @param {Element} the element to simulate a click on + */ + var simulateClick = function (elt) { + var click = document.createEvent('MouseEvents'); + click.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); + elt.dispatchEvent(click); + }; + + // A pattern for settings to validate their format. + var settingsStub = { + speed: jasmine.any(Number), + easing: jasmine.any(String), + offset: jasmine.any(Number), + updateURL: jasmine.any(Boolean), + callback: jasmine.any(Function) + }; + + + // + // Init + // + + describe('Should initialize plugin', function () { + it('Should export the smoothScroll module', function () { + expect(smoothScroll).toBeDefined(); + }); + + it('Should expose public functions', function () { + expect(smoothScroll.init).toEqual(jasmine.any(Function)); + expect(smoothScroll.destroy).toEqual(jasmine.any(Function)); + expect(smoothScroll.animateScroll).toEqual(jasmine.any(Function)); + }); + + it('Should add event listeners', function () { + spyOn(document, 'addEventListener'); + smoothScroll.init(); + expect(document.addEventListener).toHaveBeenCalledWith('click', jasmine.any(Function), false); + + spyOn(document, 'removeEventListener'); + smoothScroll.destroy(); + expect(document.removeEventListener).toHaveBeenCalledWith('click', jasmine.any(Function), false); + }); + }); + + + // + // Events + // + + describe('Should animate scroll when anchor clicked', function () { + var elt = injectElem('#anchor', true); + document.body.setAttribute('id', 'anchor'); + + afterEach(function () { + smoothScroll.destroy(); + }); + + it('Should trigger smooth scrolling on click', function () { + spyOn(smoothScroll, 'animateScroll'); + smoothScroll.init(); + simulateClick(elt); + expect(smoothScroll.animateScroll).toHaveBeenCalledWith(elt, '#anchor', jasmine.objectContaining(settingsStub)); + }); + + it('Should do nothing if not initialized', function () { + spyOn(smoothScroll, 'animateScroll'); + simulateClick(elt); + expect(smoothScroll.animateScroll).not.toHaveBeenCalled(); + }); + + it('Should do nothing if destroyed', function () { + spyOn(smoothScroll, 'animateScroll'); + smoothScroll.init(); + smoothScroll.destroy(); + simulateClick(elt); + expect(smoothScroll.animateScroll).not.toHaveBeenCalled(); + }); + }); + + describe('Should run callbacks', function () { + var elt = injectElem('#anchor', true); + document.body.setAttribute('id', 'anchor'); + + // Generates a callback to test asynchronous calls. + var callback = function (eltVal, anchorVal, done) { + return function (toggle, anchor) { + expect(toggle).toBe(eltVal); + expect(anchor).toBe(anchorVal); + done(); + }; + }; + + afterEach(function () { + smoothScroll.destroy(); + }); + + it('Should run callback', function (done) { + var settings = { + callback: callback(elt, '#anchor', done) + }; + smoothScroll.init(settings); + simulateClick(elt); + }); + }); +}); diff --git a/content/pages/_blueprint.yaml b/content/pages/_blueprint.yaml new file mode 100644 index 0000000..36b0e1a --- /dev/null +++ b/content/pages/_blueprint.yaml @@ -0,0 +1 @@ +title: Pages diff --git a/content/pages/home.yaml b/content/pages/home.yaml new file mode 100644 index 0000000..ae6ea09 --- /dev/null +++ b/content/pages/home.yaml @@ -0,0 +1,3 @@ +$title: Base +$path: "{root}/" +$view: /views/home.html diff --git a/dist/base.css b/dist/base.css new file mode 100644 index 0000000..2c19944 --- /dev/null +++ b/dist/base.css @@ -0,0 +1 @@ +a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,html,h1,h2,h3,h4,h5,h6,header,hgroup,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,span,pre,q,ruby,s,samp,section,small,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{border:0;margin:0;padding:0;font:inherit;font-size:100%;vertical-align:baseline}html{box-sizing:border-box;line-height:1}html *,html *:before,html *:after{box-sizing:inherit}ol,ul{list-style:none}table{border-collapse:collapse;border-spacing:0}caption,th,td{text-align:left;font-weight:normal;vertical-align:middle}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}a img{border:none}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}.space-base{margin:10px}.space-horz-base{margin-left:10px;margin-right:10px}.space-vert-base{margin-bottom:10px;margin-top:10px}.pad-base{padding:10px}.pad-horz-base{padding-left:10px;padding-right:10px}.pad-vert-base{padding-bottom:10px;padding-top:10px}.space-small{margin:30px}.space-horz-small{margin-left:30px;margin-right:30px}.space-vert-small{margin-bottom:30px;margin-top:30px}.pad-small{padding:30px}.pad-horz-small{padding-left:30px;padding-right:30px}.pad-vert-small{padding-bottom:30px;padding-top:30px}.space-medium{margin:60px}.space-horz-medium{margin-left:60px;margin-right:60px}.space-vert-medium{margin-bottom:60px;margin-top:60px}.pad-medium{padding:60px}.pad-horz-medium{padding-left:60px;padding-right:60px}.pad-vert-medium{padding-bottom:60px;padding-top:60px}.space-bottom{margin-bottom:10px}.pad-bottom{padding-bottom:10px}.space-bottom-base{margin-bottom:10px}.pad-bottom-base{padding-bottom:10px}.space-bottom-small{margin-bottom:30px}.pad-bottom-small{padding-bottom:30px}.space-bottom-medium{margin-bottom:60px}.pad-bottom-medium{padding-bottom:60px}.space-left{margin-left:10px}.pad-left{padding-left:10px}.space-left-base{margin-left:10px}.pad-left-base{padding-left:10px}.space-left-small{margin-left:30px}.pad-left-small{padding-left:30px}.space-left-medium{margin-left:60px}.pad-left-medium{padding-left:60px}.space-right{margin-right:10px}.pad-right{padding-right:10px}.space-right-base{margin-right:10px}.pad-right-base{padding-right:10px}.space-right-small{margin-right:30px}.pad-right-small{padding-right:30px}.space-right-medium{margin-right:60px}.pad-right-medium{padding-right:60px}.space-top{margin-top:10px}.pad-top{padding-top:10px}.space-top-base{margin-top:10px}.pad-top-base{padding-top:10px}.space-top-small{margin-top:30px}.pad-top-small{padding-top:30px}.space-top-medium{margin-top:60px}.pad-top-medium{padding-top:60px}h1,h2,h3,h4,h5,h6,p{margin-bottom:20px}ol,ul{list-style-position:outside;margin-bottom:20px;padding-left:2em}ol{list-style-type:decimal}ul{list-style-type:disc}.main{margin-left:auto;margin-right:auto;max-width:1680px;overflow-x:hidden}.content{width:276px;margin-left:auto;margin-right:auto}@media (min-width: 374px){.content{width:324px}}@media (min-width: 480px){.content{width:424px}}@media (min-width: 718px){.content{width:680px}}@media (min-width: 1024px){.content{width:868px}}@media (min-width: 1292px){.content{width:1016px}}.space-base{margin:10px}.space-horz-base{margin-left:10px;margin-right:10px}.space-vert-base{margin-bottom:10px;margin-top:10px}.pad-base{padding:10px}.pad-horz-base{padding-left:10px;padding-right:10px}.pad-vert-base{padding-bottom:10px;padding-top:10px}.space-small{margin:30px}.space-horz-small{margin-left:30px;margin-right:30px}.space-vert-small{margin-bottom:30px;margin-top:30px}.pad-small{padding:30px}.pad-horz-small{padding-left:30px;padding-right:30px}.pad-vert-small{padding-bottom:30px;padding-top:30px}.space-medium{margin:60px}.space-horz-medium{margin-left:60px;margin-right:60px}.space-vert-medium{margin-bottom:60px;margin-top:60px}.pad-medium{padding:60px}.pad-horz-medium{padding-left:60px;padding-right:60px}.pad-vert-medium{padding-bottom:60px;padding-top:60px}.space-bottom{margin-bottom:10px}.pad-bottom{padding-bottom:10px}.space-bottom-base{margin-bottom:10px}.pad-bottom-base{padding-bottom:10px}.space-bottom-small{margin-bottom:30px}.pad-bottom-small{padding-bottom:30px}.space-bottom-medium{margin-bottom:60px}.pad-bottom-medium{padding-bottom:60px}.space-left{margin-left:10px}.pad-left{padding-left:10px}.space-left-base{margin-left:10px}.pad-left-base{padding-left:10px}.space-left-small{margin-left:30px}.pad-left-small{padding-left:30px}.space-left-medium{margin-left:60px}.pad-left-medium{padding-left:60px}.space-right{margin-right:10px}.pad-right{padding-right:10px}.space-right-base{margin-right:10px}.pad-right-base{padding-right:10px}.space-right-small{margin-right:30px}.pad-right-small{padding-right:30px}.space-right-medium{margin-right:60px}.pad-right-medium{padding-right:60px}.space-top{margin-top:10px}.pad-top{padding-top:10px}.space-top-base{margin-top:10px}.pad-top-base{padding-top:10px}.space-top-small{margin-top:30px}.pad-top-small{padding-top:30px}.space-top-medium{margin-top:60px}.pad-top-medium{padding-top:60px}.grid,[class*="grid-"]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:-20px;margin-left:-10px;margin-right:-10px}.grid>*,[class*="grid-"]>*{-webkit-align-self:stretch;-ms-flex-item-align:stretch;align-self:stretch;margin-bottom:20px;padding-left:10px;padding-right:10px;width:100%}.grid.align-center,[class*="grid-"].align-center{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.grid.align-right,[class*="grid-"].align-right{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.grid .valign-middle,[class*="grid-"] .valign-middle{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.grid .valign-bottom,[class*="grid-"] .valign-bottom{-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.grid:before,.grid:after,[class*="grid-"]:before,[class*="grid-"]:after{content:' ';display:table;width:100%;clear:both}.grid-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.grid-1>*{width:100%}@media (min-width: 374px){.grid-1-at-extra-small>*{width:100%}}@media (min-width: 480px){.grid-1-at-small>*{width:100%}}@media (min-width: 718px){.grid-1-at-medium>*{width:100%}}@media (min-width: 1024px){.grid-1-at-large>*{width:100%}}@media (min-width: 1292px){.grid-1-at-extra-large>*{width:100%}}.grid-2>*{width:50%}@media (min-width: 374px){.grid-2-at-extra-small>*{width:50%}}@media (min-width: 480px){.grid-2-at-small>*{width:50%}}@media (min-width: 718px){.grid-2-at-medium>*{width:50%}}@media (min-width: 1024px){.grid-2-at-large>*{width:50%}}@media (min-width: 1292px){.grid-2-at-extra-large>*{width:50%}}.grid-3>*{width:33.33333%}@media (min-width: 374px){.grid-3-at-extra-small>*{width:33.33333%}}@media (min-width: 480px){.grid-3-at-small>*{width:33.33333%}}@media (min-width: 718px){.grid-3-at-medium>*{width:33.33333%}}@media (min-width: 1024px){.grid-3-at-large>*{width:33.33333%}}@media (min-width: 1292px){.grid-3-at-extra-large>*{width:33.33333%}}.grid-4>*{width:25%}@media (min-width: 374px){.grid-4-at-extra-small>*{width:25%}}@media (min-width: 480px){.grid-4-at-small>*{width:25%}}@media (min-width: 718px){.grid-4-at-medium>*{width:25%}}@media (min-width: 1024px){.grid-4-at-large>*{width:25%}}@media (min-width: 1292px){.grid-4-at-extra-large>*{width:25%}}.one-whole{width:100%}@media (min-width: 374px){.one-whole-at-extra-small{width:100%}}@media (min-width: 480px){.one-whole-at-small{width:100%}}@media (min-width: 718px){.one-whole-at-medium{width:100%}}@media (min-width: 1024px){.one-whole-at-large{width:100%}}@media (min-width: 1292px){.one-whole-at-extra-large{width:100%}}.eleven-twelfths{width:91.66667%}@media (min-width: 374px){.eleven-twelfths-at-extra-small{width:91.66667%}}@media (min-width: 480px){.eleven-twelfths-at-small{width:91.66667%}}@media (min-width: 718px){.eleven-twelfths-at-medium{width:91.66667%}}@media (min-width: 1024px){.eleven-twelfths-at-large{width:91.66667%}}@media (min-width: 1292px){.eleven-twelfths-at-extra-large{width:91.66667%}}.five-sixths{width:83.33333%}@media (min-width: 374px){.five-sixths-at-extra-small{width:83.33333%}}@media (min-width: 480px){.five-sixths-at-small{width:83.33333%}}@media (min-width: 718px){.five-sixths-at-medium{width:83.33333%}}@media (min-width: 1024px){.five-sixths-at-large{width:83.33333%}}@media (min-width: 1292px){.five-sixths-at-extra-large{width:83.33333%}}.three-fourths{width:75%}@media (min-width: 374px){.three-fourths-at-extra-small{width:75%}}@media (min-width: 480px){.three-fourths-at-small{width:75%}}@media (min-width: 718px){.three-fourths-at-medium{width:75%}}@media (min-width: 1024px){.three-fourths-at-large{width:75%}}@media (min-width: 1292px){.three-fourths-at-extra-large{width:75%}}.two-thirds{width:66.66667%}@media (min-width: 374px){.two-thirds-at-extra-small{width:66.66667%}}@media (min-width: 480px){.two-thirds-at-small{width:66.66667%}}@media (min-width: 718px){.two-thirds-at-medium{width:66.66667%}}@media (min-width: 1024px){.two-thirds-at-large{width:66.66667%}}@media (min-width: 1292px){.two-thirds-at-extra-large{width:66.66667%}}.seven-twelfths{width:58.33333%}@media (min-width: 374px){.seven-twelfths-at-extra-small{width:58.33333%}}@media (min-width: 480px){.seven-twelfths-at-small{width:58.33333%}}@media (min-width: 718px){.seven-twelfths-at-medium{width:58.33333%}}@media (min-width: 1024px){.seven-twelfths-at-large{width:58.33333%}}@media (min-width: 1292px){.seven-twelfths-at-extra-large{width:58.33333%}}.one-half{width:50%}@media (min-width: 374px){.one-half-at-extra-small{width:50%}}@media (min-width: 480px){.one-half-at-small{width:50%}}@media (min-width: 718px){.one-half-at-medium{width:50%}}@media (min-width: 1024px){.one-half-at-large{width:50%}}@media (min-width: 1292px){.one-half-at-extra-large{width:50%}}.five-twelfths{width:41.66667%}@media (min-width: 374px){.five-twelfths-at-extra-small{width:41.66667%}}@media (min-width: 480px){.five-twelfths-at-small{width:41.66667%}}@media (min-width: 718px){.five-twelfths-at-medium{width:41.66667%}}@media (min-width: 1024px){.five-twelfths-at-large{width:41.66667%}}@media (min-width: 1292px){.five-twelfths-at-extra-large{width:41.66667%}}.one-third{width:33.33333%}@media (min-width: 374px){.one-third-at-extra-small{width:33.33333%}}@media (min-width: 480px){.one-third-at-small{width:33.33333%}}@media (min-width: 718px){.one-third-at-medium{width:33.33333%}}@media (min-width: 1024px){.one-third-at-large{width:33.33333%}}@media (min-width: 1292px){.one-third-at-extra-large{width:33.33333%}}.one-fourth{width:25%}@media (min-width: 374px){.one-fourth-at-extra-small{width:25%}}@media (min-width: 480px){.one-fourth-at-small{width:25%}}@media (min-width: 718px){.one-fourth-at-medium{width:25%}}@media (min-width: 1024px){.one-fourth-at-large{width:25%}}@media (min-width: 1292px){.one-fourth-at-extra-large{width:25%}}.one-sixth{width:16.66667%}@media (min-width: 374px){.one-sixth-at-extra-small{width:16.66667%}}@media (min-width: 480px){.one-sixth-at-small{width:16.66667%}}@media (min-width: 718px){.one-sixth-at-medium{width:16.66667%}}@media (min-width: 1024px){.one-sixth-at-large{width:16.66667%}}@media (min-width: 1292px){.one-sixth-at-extra-large{width:16.66667%}}.one-twelfth{width:8.33333%}@media (min-width: 374px){.one-twelfth-at-extra-small{width:8.33333%}}@media (min-width: 480px){.one-twelfth-at-small{width:8.33333%}}@media (min-width: 718px){.one-twelfth-at-medium{width:8.33333%}}@media (min-width: 1024px){.one-twelfth-at-large{width:8.33333%}}@media (min-width: 1292px){.one-twelfth-at-extra-large{width:8.33333%}}.hide{display:none !important}@media (min-width: 374px){.hide-at-extra-small{display:none !important}}@media (min-width: 480px){.hide-at-small{display:none !important}}@media (min-width: 718px){.hide-at-medium{display:none !important}}@media (min-width: 1024px){.hide-at-large{display:none !important}}@media (min-width: 1292px){.hide-at-extra-large{display:none !important}}.show{display:block !important}@media (min-width: 374px){.show-at-extra-small{display:block !important}}@media (min-width: 480px){.show-at-small{display:block !important}}@media (min-width: 718px){.show-at-medium{display:block !important}}@media (min-width: 1024px){.show-at-large{display:block !important}}@media (min-width: 1292px){.show-at-extra-large{display:block !important}}.display-block{display:block !important}@media (min-width: 374px){.display-block-at-extra-small{display:block !important}}@media (min-width: 480px){.display-block-at-small{display:block !important}}@media (min-width: 718px){.display-block-at-medium{display:block !important}}@media (min-width: 1024px){.display-block-at-large{display:block !important}}@media (min-width: 1292px){.display-block-at-extra-large{display:block !important}}.display-inline{display:inline !important}@media (min-width: 374px){.display-inline-at-extra-small{display:inline !important}}@media (min-width: 480px){.display-inline-at-small{display:inline !important}}@media (min-width: 718px){.display-inline-at-medium{display:inline !important}}@media (min-width: 1024px){.display-inline-at-large{display:inline !important}}@media (min-width: 1292px){.display-inline-at-extra-large{display:inline !important}}.display-inline-block{display:inline-block !important}@media (min-width: 374px){.display-inline-block-at-extra-small{display:inline-block !important}}@media (min-width: 480px){.display-inline-block-at-small{display:inline-block !important}}@media (min-width: 718px){.display-inline-block-at-medium{display:inline-block !important}}@media (min-width: 1024px){.display-inline-block-at-large{display:inline-block !important}}@media (min-width: 1292px){.display-inline-block-at-extra-large{display:inline-block !important}}.text-center{text-align:center !important}@media (min-width: 374px){.text-center-at-extra-small{text-align:center !important}}@media (min-width: 480px){.text-center-at-small{text-align:center !important}}@media (min-width: 718px){.text-center-at-medium{text-align:center !important}}@media (min-width: 1024px){.text-center-at-large{text-align:center !important}}@media (min-width: 1292px){.text-center-at-extra-large{text-align:center !important}}.text-left{text-align:left !important}@media (min-width: 374px){.text-left-at-extra-small{text-align:left !important}}@media (min-width: 480px){.text-left-at-small{text-align:left !important}}@media (min-width: 718px){.text-left-at-medium{text-align:left !important}}@media (min-width: 1024px){.text-left-at-large{text-align:left !important}}@media (min-width: 1292px){.text-left-at-extra-large{text-align:left !important}}.text-right{text-align:right !important}@media (min-width: 374px){.text-right-at-extra-small{text-align:right !important}}@media (min-width: 480px){.text-right-at-small{text-align:right !important}}@media (min-width: 718px){.text-right-at-medium{text-align:right !important}}@media (min-width: 1024px){.text-right-at-large{text-align:right !important}}@media (min-width: 1292px){.text-right-at-extra-large{text-align:right !important}}.text-capitalize{text-transform:capitalize !important}@media (min-width: 374px){.text-capitalize-at-extra-small{text-transform:capitalize !important}}@media (min-width: 480px){.text-capitalize-at-small{text-transform:capitalize !important}}@media (min-width: 718px){.text-capitalize-at-medium{text-transform:capitalize !important}}@media (min-width: 1024px){.text-capitalize-at-large{text-transform:capitalize !important}}@media (min-width: 1292px){.text-capitalize-at-extra-large{text-transform:capitalize !important}}.text-lowercase{text-transform:lowercase !important}@media (min-width: 374px){.text-lowercase-at-extra-small{text-transform:lowercase !important}}@media (min-width: 480px){.text-lowercase-at-small{text-transform:lowercase !important}}@media (min-width: 718px){.text-lowercase-at-medium{text-transform:lowercase !important}}@media (min-width: 1024px){.text-lowercase-at-large{text-transform:lowercase !important}}@media (min-width: 1292px){.text-lowercase-at-extra-large{text-transform:lowercase !important}}.text-none{text-transform:none !important}@media (min-width: 374px){.text-none-at-extra-small{text-transform:none !important}}@media (min-width: 480px){.text-none-at-small{text-transform:none !important}}@media (min-width: 718px){.text-none-at-medium{text-transform:none !important}}@media (min-width: 1024px){.text-none-at-large{text-transform:none !important}}@media (min-width: 1292px){.text-none-at-extra-large{text-transform:none !important}}.text-uppercase{text-transform:uppercase !important}@media (min-width: 374px){.text-uppercase-at-extra-small{text-transform:uppercase !important}}@media (min-width: 480px){.text-uppercase-at-small{text-transform:uppercase !important}}@media (min-width: 718px){.text-uppercase-at-medium{text-transform:uppercase !important}}@media (min-width: 1024px){.text-uppercase-at-large{text-transform:uppercase !important}}@media (min-width: 1292px){.text-uppercase-at-extra-large{text-transform:uppercase !important}} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..4b5a702 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,54 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Gulp build file. + * @author stevenle08@gmail.com (Steven Le) + */ + +var autoprefixer = require('gulp-autoprefixer'); +var gulp = require('gulp'); +var plumber = require('gulp-plumber'); +var rename = require('gulp-rename'); +var runSequence = require('run-sequence'); +var sass = require('gulp-sass'); + +var AUTOPREFIXER_OPTIONS = { + 'browsers': [ + '> 1%', + 'last 2 versions', + 'Firefox ESR', + 'iOS 7' + ] +}; + +var SASS_OPTIONS = { + 'outputStyle': 'compressed' +}; + +gulp.task('buildcss', function() { + return gulp.src('./src/sass/base.scss') + .pipe(plumber()) + .pipe(sass(SASS_OPTIONS)) + .pipe(autoprefixer(AUTOPREFIXER_OPTIONS)) + .pipe(rename('base.css')) + .pipe(gulp.dest('./dist/')); +}); + +gulp.task('watch', function() { + gulp.watch(['./src/sass/*.scss'], ['buildcss']); +}); + +gulp.task('build', ['buildcss']); +gulp.task('default', ['buildcss', 'watch']); diff --git a/package.json b/package.json new file mode 100644 index 0000000..c50ae8f --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "base", + "version": "0.0.1", + "description": "base", + "repository": { + "type": "git", + "url": "https://github.com/stevenle/base" + }, + "devDependencies": { + "bower": "^1.6.3", + "gulp": "^3.9.0", + "gulp-autoprefixer": "^3.1.0", + "gulp-plumber": "^1.0.1", + "gulp-rename": "^1.2.2", + "gulp-sass": "^2.0.4", + "run-sequence": "^1.1.4" + }, + "author": { + "name": "Steven Le", + "email": "stevenle08@gmail.com", + "website": "stevenle.co" + }, + "license": "Apache-2.0" +} diff --git a/podspec.yaml b/podspec.yaml new file mode 100644 index 0000000..994fc55 --- /dev/null +++ b/podspec.yaml @@ -0,0 +1,17 @@ +grow_version: ">=0.0.55" +title: Base +description: Base CSS and JS +root: /base/ + +static_dirs: +- static_dir: /dist/ + serve_at: /static/css/ +- static_dir: /static/images/ + serve_at: /static/images/ +- static_dir: /bower_components/smooth_scroll/dist/ + serve_at: /static/thirdparty/smooth_scroll/ + +deployments: + github: + destination: local + out_dir: ../stevenle.github.io/ diff --git a/src/sass/_breakpoint.scss b/src/sass/_breakpoint.scss new file mode 100644 index 0000000..085434a --- /dev/null +++ b/src/sass/_breakpoint.scss @@ -0,0 +1,48 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Config. +$breakpoint-extra-small: 374px; +$breakpoint-small: 480px; +$breakpoint-medium: 718px; +$breakpoint-large: 1024px; +$breakpoint-extra-large: 1292px; + +$breakpoint-map: ( + extra-small: $breakpoint-extra-small, + small: $breakpoint-small, + medium: $breakpoint-medium, + large: $breakpoint-large, + extra-large: $breakpoint-extra-large, +); + +@mixin breakpoint($width) { + @media (min-width: $width) { + @content; + } +} + +@mixin breakpoint-rule($selector) { + #{$selector} { + @content; + } + @each $size in extra-small, small, medium, large, extra-large { + #{$selector}-at-#{$size} { + $width: map-get($breakpoint-map, $size); + @include breakpoint($width) { + @content; + } + } + } +} diff --git a/src/sass/_content.scss b/src/sass/_content.scss new file mode 100644 index 0000000..0594414 --- /dev/null +++ b/src/sass/_content.scss @@ -0,0 +1,42 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@import 'breakpoint'; + +.main { + margin-left: auto; + margin-right: auto; + max-width: 1680px; + overflow-x: hidden; +} + +$content-widths: ( + extra-small: 324px, + small: 424px, + medium: 680px, + large: 868px, + extra-large: 1016px, +); +.content { + width: 276px; + margin-left: auto; + margin-right: auto; + + @each $size, $width in $content-widths { + $bp: map-get($breakpoint-map, $size); + @include breakpoint($bp) { + width: $width; + } + } +} diff --git a/src/sass/_elements.scss b/src/sass/_elements.scss new file mode 100644 index 0000000..b3f4943 --- /dev/null +++ b/src/sass/_elements.scss @@ -0,0 +1,40 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@import 'spacing'; + +h1, +h2, +h3, +h4, +h5, +h6, +p { + margin-bottom: 2 * $spacing-base; +} + +ol, +ul { + list-style-position: outside; + margin-bottom: 2 * $spacing-base; + padding-left: 2em; +} + +ol { + list-style-type: decimal; +} + +ul { + list-style-type: disc; +} diff --git a/src/sass/_grid.scss b/src/sass/_grid.scss new file mode 100644 index 0000000..b39f5c4 --- /dev/null +++ b/src/sass/_grid.scss @@ -0,0 +1,91 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@import 'breakpoint'; +@import 'spacing'; + +.grid, +[class*="grid-"] { + display: flex; + flex-wrap: wrap; + margin-bottom: -2 * $spacing-base; + margin-left: -1 * $spacing-base; + margin-right: -1 * $spacing-base; + + > * { + align-self: stretch; + margin-bottom: 2 * $spacing-base; + padding-left: $spacing-base; + padding-right: $spacing-base; + width: 100%; + } + + &.align-center { + justify-content: center; + } + &.align-right { + justify-content: flex-end; + } + + .valign-middle { + align-self: center; + } + .valign-bottom { + align-self: flex-end; + } + + &:before, + &:after { + content: ' '; + display: table; + width: 100%; + clear: both; + } +} + +.grid-reverse { + flex-direction: row-reverse; +} + +@for $i from 1 through 4 { + $selector: ".grid-#{$i}"; + $width: 100% / $i; + @include breakpoint-rule($selector) { + > * { + width: $width; + } + } +} + +$grid-sizes: ( + ".one-twelfth", + ".one-sixth", + ".one-fourth", + ".one-third", + ".five-twelfths", + ".one-half", + ".seven-twelfths", + ".two-thirds", + ".three-fourths", + ".five-sixths", + ".eleven-twelfths", + ".one-whole", +); +@for $i from 12 through 1 { + $selector: nth($grid-sizes, $i); + $width: $i / 12 * 100%; + @include breakpoint-rule($selector) { + width: $width; + } +} diff --git a/src/sass/_reset.scss b/src/sass/_reset.scss new file mode 100644 index 0000000..e71272e --- /dev/null +++ b/src/sass/_reset.scss @@ -0,0 +1,162 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +a, +abbr, +acronym, +address, +applet, +article, +aside, +audio, +b, +big, +blockquote, +body, +canvas, +caption, +center, +cite, +code, +dd, +del, +details, +dfn, +div, +dl, +dt, +em, +embed, +fieldset, +figcaption, +figure, +footer, +form, +html, +h1, +h2, +h3, +h4, +h5, +h6, +header, +hgroup, +i, +iframe, +img, +ins, +kbd, +label, +legend, +li, +mark, +menu, +nav, +object, +ol, +output, +p, +span, +pre, +q, +ruby, +s, +samp, +section, +small, +strike, +strong, +sub, +summary, +sup, +table, +tbody, +td, +tfoot, +th, +thead, +time, +tr, +tt, +u, +ul, +var, +video { + border: 0; + margin: 0; + padding: 0; + font: inherit; + font-size: 100%; + vertical-align: baseline; +} + +html { + box-sizing: border-box; + line-height: 1; + + *, + *:before, + *:after { + box-sizing: inherit; + } +} + +ol, +ul { + list-style: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +caption, +th, +td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} + +blockquote, +q { + quotes: none; + + &:before, + &:after { + content: ''; + content: none; + } +} + +a img { + border: none; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} diff --git a/src/sass/_spacing.scss b/src/sass/_spacing.scss new file mode 100644 index 0000000..7d5ff74 --- /dev/null +++ b/src/sass/_spacing.scss @@ -0,0 +1,66 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +$spacing-base: 10px; +$spacing-small: 3 * $spacing-base; +$spacing-medium: 6 * $spacing-base; + +$spacing-map: ( + base: $spacing-base, + small: $spacing-small, + medium: $spacing-medium, +); + +@each $size, $space in $spacing-map { + .space-#{$size} { + margin: $space; + } + .space-horz-#{$size} { + margin-left: $space; + margin-right: $space; + } + .space-vert-#{$size} { + margin-bottom: $space; + margin-top: $space; + } + .pad-#{$size} { + padding: $space; + } + .pad-horz-#{$size} { + padding-left: $space; + padding-right: $space; + } + .pad-vert-#{$size} { + padding-bottom: $space; + padding-top: $space; + } +} + +@each $side in bottom, left, right, top { + .space-#{$side} { + margin-#{$side}: $spacing-base; + } + .pad-#{$side} { + padding-#{$side}: $spacing-base; + } + + @each $size, $space in $spacing-map { + .space-#{$side}-#{$size} { + margin-#{$side}: $space; + } + .pad-#{$side}-#{$size} { + padding-#{$side}: $space; + } + } +} diff --git a/src/sass/_utility.scss b/src/sass/_utility.scss new file mode 100644 index 0000000..9c675f9 --- /dev/null +++ b/src/sass/_utility.scss @@ -0,0 +1,44 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@import 'breakpoint'; + +@include breakpoint-rule(".hide") { + display: none !important; +} + +@include breakpoint-rule(".show") { + display: block !important; +} + +@each $display in block, inline, inline-block { + $selector: ".display-#{$display}"; + @include breakpoint-rule($selector) { + display: $display !important; + } +} + +@each $text-align in center, left, right { + $selector: ".text-#{$text-align}"; + @include breakpoint-rule($selector) { + text-align: $text-align !important; + } +} + +@each $text-transform in capitalize, lowercase, none, uppercase { + $selector: ".text-#{$text-transform}"; + @include breakpoint-rule($selector) { + text-transform: $text-transform !important; + } +} diff --git a/src/sass/base.scss b/src/sass/base.scss new file mode 100644 index 0000000..4582026 --- /dev/null +++ b/src/sass/base.scss @@ -0,0 +1,20 @@ +// Copyright 2015 Steven Le (stevenle08@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* base.css */ +@import 'reset'; +@import 'elements'; +@import 'content'; +@import 'grid'; +@import 'utility'; diff --git a/static/images/favicon.ico b/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2cd64f053bba5ccf4615848108ee233f98465dee GIT binary patch literal 32038 zcmeI4O=uNY6vrpj5Q<1G;-a{DqGBXq5=DfrLLmhgE`m@HH-xr>3U9gt)f6Md}2} zG2VNsHyu8GXOFc-ngTkH<-Us=hQSx+_{2{UzEn;+j0lCX>pIsxO%rL~EkW^XJb$ zPO|rY)}1kEUY|hKC;mf zCZ_`W%l3cS@mF^LD{TBZdGaK4`M~jqxKy3e#$VH4>ilCEN}GStU-tR~3}vpr(BJ2W zMC(uD+~#^>J@xw2VIY+pVshx~?|ux1qm=!JA4hwi-(IxuD4>)}&M7!D{ZTYx=b?9W zcIyANZJuA7x4vwyFEy`@YCn8JG^;sfUUXA*8`8YRHF>ktp>9=TMOcmq*HsZ`39m$N zMel`~Gq8`4UB9<7>QMJ8yk*!S-K=@>byw+@Xj>RxDt#onE}A}j_UzF!XU>d4T$5*I zkF4&t?%_qo3DHp6L|E`QXXYEi0fuGSaZT69MUiJx)S)gs@ah^F8=^(*EV4ax)^SjJ zR;2Tt(q~GE=hQI(FEUIPGFP-lKA5)+);D>EgrD9@?=Pa<^dJkF$VP{*d6t)3JRwhV zUx@w`U6IdnKg&R-WY3w77wF8R9V}+>JJ>JharPO8%g#hEo34$lv1H@MisaF*b46lz zHkl2y13FjI_G$5siWb$b?}*JJV#ZKcw^uq0V)s6OkN zZSh|Vk~_>iFn|S2ar828sP0p>+e^{$I6Otx0RvcsX*JHACVT0(uSBe~BG)rTVn;R@ zzyc<)Md?$$SrKc5>rr)wRW3Z&!34G_ovJf0dM}E6w^ernx+Wn*vrR9d<5 zQ)7DM_{kh0?6sZ0-1$B`%>LB+G~-h3o?kdygq^W9@$)0aAp3C6 zHCWGZrn4pLikNFsjgbyh+SJw>te2jOShq6PMm@iy?p1ix>dl+a`Z#_hp6BJ`n@ZVB zSNi#B-hOE1WuNa_AIA6Lr}u&QCW>F14%-jBr!^zGBO0;yv^;&&>i@Md9Y3a9U$wq! zW1x+JHU^T#fY#urwBBA2@jV&ei@Xu-=$dx{dH%IS9%UlxEWlG|KWh&(DVvr=o1*=c z1n&~E>f(#Z$w|(H{_xrRL3yj98zR2xJEeE1j!aBUj6qzJXJyn`75@jHjCEvJ)eqno z-X{*T?m0K%J<2&z;`26m;6(!(yq>n5`Tjo*0#t( zrU=>i0bNVz4&xa{K5;7?>mo4m9Q>iuZ;H~5Y}3KJ)9B%8F!hazOaAgK_ma!nhB^1+Fvt0%n85}{u!1=$e^`CV>#ge~ z^I=$>s^o)Fc$pKPP3^s+N*ML@3#?*qTV_Y?Ednk_mbttylzt7vg!*nYh_|! zJqrf)C-$(6dGGRE&u76DhZn4120J#y;R&iEemCYX2bEVjPxdckKQ^SrDPGPWkn#C{ zB&L-$Y(6j>_RTc9Ie#*K&LI---_z*KlLySA-Wf`ovoyue0`@Ci%@fx!Wr5vnSV*c@ zybp}`MpE9Y)Rzr6%!b7OBTT$&##`9`_bS>?vf+~1F!2Al1>q3i8{^Gw9T}vj$UNEa z#;`X@^~m-e>@R9RnG{c&`nF$Z{@O{(FW>E9Kj+g)d8<+%?AU-UNij9ueqsjSH8uWa zd!xrc#ebvcKiS{(^-rVMzfIr&Fkfm6Z0!Em>~Hk>M_tdq^gk`X()gYE{L5lsopq3? zap#}d-}Liui-E>I|G<9rrA9yhvKVl4!Is8?$~^}HliCSvj8&=6ysEC41GL6r|G7@5AFRY=L3ra*B2V~{+siG zjR$Uh*r@j(oeykYU~Vkz{a4oWlFu{!-g^zEtMvC@oexNDjnrEw3SaM?0p%_0`hWfY zbH5L`X1^f28~6UZ-w(ETreC--6vpYK1aGarfAIT(d(P4n6OH=*CCCqLUhv+c^-JrQ SHU`=lC?f{6er2HE+EP)Px);7LS5RCodHTTM(GM-(=8`ISIKJyj7LjFAmJQ6R@~Ft?PHOAZAr8%tnCIaQ!U3O_E8?;B>Sl|8fGwas>ncck&` zzTNlcd*A%*?9Ou}5~h%Wkb#hakb%}^pe+d3*VosFkB*MgZEbDmP+t;d9AzJ5y{sSS zA5gr!e>ka2>^dB|iabz@6Ck39{Pf`9;BhjUd{c{! zYB~)kpin4WK&AJQzj0K)gX0A_lR;j?alTY4Z5B|%KHAntY|k;osP*7sXC0hvtZvw?wudjNR@xgBum==A>n{{2)cC0e*Xh>=Jx zm+QlD`Wbd^BKLsQ67r*BvG{8`o&L8T`*jhpy1M##M@Ppj9A}q3K%Uv%-Muq9I{L02 zP$u1#m6b2Ly1MS*`V?{uBxFGJC;|@bKTY*pAksgo$nfzUcMvfB; zG4Yz;kka!FduA$xndd3AmbAsm{z}cP?9-T*C+T7gyA!tWU^+_yZI1nSTn(i%^ zd+q^v&i{_F_9I&UEyv&g(e2B@JJ0!qK=1sE6C>6M53x@8$$8y$?1=y_a$tA`ISK;4 z3Ub0T0oTd-bO6Rbf$3iQN@qRRW;>o3t=(+ql^p>skGqtV}_}+AmtMC0_$}6 zQUSq80GQ(hNaak0R+9)6cIAr>wvhnboTLJb@EcxJCI@!mi_Qrn0bngI6&mvGO;>pU zGJ)OUOGTAN0&r&^@8;Lr3aus)IIs&}bg+#Cp!$#1=-hhKx?v;$cfY5G+_BLr+b(oq7ryB58VSI-;YKA>;<#waUxD4> zONA3g0&r)RcVj4|DzutJ;J_|?(ZMzn0M^8AER3inu}7f8(A^nt#Z;2H^_0+gS!1cR4ZHd9iV zl@BKDt^_bLgNih^wzejosU|}<$%$1FpnNdlb0t8Ar7S}E40c?8F&VK7Pq0S@Cuq#rBa#^T)SC4YPgIov zy2h9sOeQ59PI3E*G8>b`Hbtz&>;`7Bh>=*m>+8tKLPGf+CF9Jve!%*;^{R(W05E%w1 zAXIHvkrZUfmLD7(`~z67q2)hd+<)yiSjsm6bdUi_s8GZS;dBW*vfl;0amq2zZjbse z(s_{ZJ!XBe4?v7wQ%wZW_-P4~tC;|j(9(gDB!GzlNhcjD%eB2+-g1R!PpGV5K>oCB zu(Xo|9?P&422-?FxO_PgE&GRwaw2%n{dqj9(s)#H$JwgC%;@ljvXFt0fslcafmUJQ Y6T>p@Nt0xer2qf`07*qoM6N<$f?gcx;{X5v literal 0 HcmV?d00001 diff --git a/views/_base.html b/views/_base.html new file mode 100644 index 0000000..4bc9dc1 --- /dev/null +++ b/views/_base.html @@ -0,0 +1,12 @@ + + + +Base + + + +{% block head %}{% endblock %} + +{% block body %}{% endblock %} + + diff --git a/views/home.html b/views/home.html new file mode 100644 index 0000000..b26a23a --- /dev/null +++ b/views/home.html @@ -0,0 +1,430 @@ +{% extends "/views/_base.html" %} + +{% block head %} + + +{% endblock %} + +{% block body %} +
+ +
+
+

{{doc.title}}

+

+ Base is a modern framework designed to reduce the amount of time writing + CSS and JS, allowing more time for developers to produce great content. +

+ + +
+
+ + + +
+
+

Grid

+

+ At the heart of every great framework is a grid system. Base is no + different. +

+ +
+
+
+
+
+
Based on flexbox
+
+ A modern layout system that uses the latest and greatest of browser + technologies. +
+
+
+
+
+
Mobile first
+
+ Start by defining a grid size for mobile and enhance for different + screen widths using responsive suffixes. +
+
+
+
+
+
Written in SASS / SCSS
+
+ Integrate with your existing SCSS, extend and modify as needed. +
+
+
+
+
+
Powerful and easy to learn
+
+ Designed to be similar to other frameworks, so it's easy to learn + but is as powerful as you need it to be. +
+
+
+
+ +
+

12 layout classes

+

+ The grid system is based on a 12-column, fluid-width layout. Widths of + each column can be defined using fractional names (e.g. + one-half, two-thirds, etc.). +

+ + {% set sizes = [ + 'one-twelfth', + 'one-sixth', + 'one-fourth', + 'one-third', + 'five-twelfths', + 'one-half', + 'seven-twelfths', + 'two-thirds', + 'three-fourths', + 'five-sixths', + 'eleven-twelfths', + 'one-whole', + ] %} + {% for size in sizes %} +
+
+
+
+
+ {% endfor %} +
+ +
+

Equal-width columns

+

+ You can define the number of columns using the .grid-N CSS + classes, where N is the number of columns. +

+ {% for i in range(2, 5) %} +
+ {% for _ in range(i) %} +
+ {% endfor %} +
+ {% endfor %} +
+ +
+

Responsive suffixes

+

+ Change the number of columns at different screen widths using responsive + suffixes, i.e. adding -at-SCREENSIZE, where + SCREENSIZE is one of: extra-small, + small, medium, large, or + extra-large. +

+
+ {% for _ in range(4) %} +
+ {% endfor %} +
+
+ +
+

Vertical positioning

+

+ By default, columns are vertically positioned at the top, but the + positioning of each column can be changed by using valign-POSITION, + where POSITION is one of: middle, bottom. +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+

Content alignment

+

+ If the content doesn't fill the full width of the 12-column layout, the + columns can be aligned in different ways. +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+

Breakpoints

+

+ Base's .content container uses a fixed width at different + breakpoints so that the content size is predictable. +

+ +

Widths

+ {% set data = [ + {'size': 'extra-small', 'viewport_width': '>= 374px', 'content_width': '324px'}, + {'size': 'small', 'viewport_width': '>= 480px', 'content_width': '424px'}, + {'size': 'medium', 'viewport_width': '>= 718px', 'content_width': '680px'}, + {'size': 'large', 'viewport_width': '>= 1024px', 'content_width': '868px'}, + {'size': 'extra-large', 'viewport_width': '>= 1292px', 'content_width': '1016px'}, + ] %} + +
+ + + + + + + + + + {% for row in data %} + + + + + + {% endfor %} + +
SizeViewport widthContent width
{{row.size}}{{row.viewport_width}}{{row.content_width}}
+
+ +

SASS / SCSS helpers

+

+ Base comes with a few mixins to help generate mobile-first, responsive + rules at different breakpoints. +

+ +
+
+

@mixin breakpoint($selector)

+
.foo {
+  color: red;
+
+  @include breakpoint($breakpoint-small) {
+    color: blue;
+  }
+}
+
+
+
+

Compiles to:

+
.foo {
+  color: red;
+}
+@media (min-width: 480px) {
+  .foo {
+    color: blue;
+  }
+}
+
+
+
+ +
+
+

@mixin breakpoint-rule($selector)

+
@include breakpoint-rule(".foo") {
+  color: red;
+}
+
+
+
+

Compiles to:

+
.foo {
+  color: red;
+}
+@media (min-width: 374px) {
+  .foo-at-extra-small {
+    color: red;
+  }
+}
+@media (min-width: 480px) {
+  .foo-at-small {
+    color: red;
+  }
+}
+/* etc. */
+
+
+
+ +
+
+ +
+ + + +{% endblock %}