├── LICENSE ├── gotchas.md ├── images └── bigwheellogo.png ├── misc.md ├── quickstart.md ├── readme.md ├── routes-defining.md ├── routes-special.md ├── routes.md ├── sections-animateInOut.md ├── sections-destroy.md ├── sections-init.md ├── sections-resize.md └── sections.md /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 bigwheel-framework 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /gotchas.md: -------------------------------------------------------------------------------- 1 | # Gotchas 2 | 3 | Here we'll discuss some typical gotchas that you might encounter when using `bigwheel`. 4 | 5 | ## Forgetting To Call Done 6 | 7 | So you might remember from the documentation for the [`init` function for Sections](sections-init.md) one of the biggest gotchas is not calling the done callback after the `init`, `animateIn`, `animateOut` functions have completed. 8 | 9 | If you do this you're application will have unexpected results such as the `init` section hanging if `done` is not called. Or if you do not call the `done` callback from `animateOut` your section may never be destroyed. 10 | 11 | ## Circular Dependendencies 12 | 13 | In most module system it's possible to create circular dependencies. What this means is that: 14 | 15 | 1. A requires 16 | 2. B requires A 17 | 18 | This would cause a circular dependency. When this happens with CommonJS modules a "blan" Object is returned to B when requiring A. 19 | 20 | The most common place this happens in bigwheel is when you're defining routes. 21 | 22 | Often a section will require the framework instance in order to be able to use the `go` method of `bigwheel`. To get around this you should always require your sections inline when defining routes: 23 | ```javascript 24 | // good 25 | var bigwheel = require('bigwheel'); 26 | 27 | var goodFramework = bigwheel( function() { 28 | 29 | return { 30 | routes: { 31 | '/': require('../sections/Landing'), 32 | '/about': require('../sections/About') 33 | } 34 | }; 35 | }); 36 | 37 | 38 | // bad 39 | var bigwheel = require('bigwheel'); 40 | var Landing = require('../sections/Landing'); 41 | var About = require('../sections/About'); 42 | 43 | var badFramework = bigwheel( function() { 44 | 45 | return { 46 | routes: { 47 | '/': Landing, 48 | '/about': About 49 | } 50 | }; 51 | }); 52 | ``` 53 | -------------------------------------------------------------------------------- /images/bigwheellogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigwheel-framework/documentation/a429462aa7c521b45a9f8dbae33e43d6e1195f75/images/bigwheellogo.png -------------------------------------------------------------------------------- /misc.md: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | 3 | In this part of the documentation we want to cover some random things that might be overlooked with `bigwheel`. 4 | 5 | ## Auto Resize 6 | 7 | If you are running `bigwheel` in the browser (`bigwheel` will work in other environments also). It will automatically add a listener to listen for `window` resize events. If you don't want this to happen you could pass a settings object to `bigwheel` that would look like this. 8 | ```javascript 9 | module.exports = bigwheel( function() { 10 | return { 11 | autoResize: false, 12 | routes: require('../routes') 13 | }; 14 | }); 15 | ``` 16 | 17 | If you pass false for `autoResize` then a listener won't be added to `window`. You can still propagate resizes to sections by calling `bigwheel`'s `resize` function like this: 18 | ```javascript 19 | var bigwheelInstance = require('./framework/'); 20 | 21 | bigwheelInstance.resize(980, 570); 22 | ``` 23 | 24 | ## Post Hash 25 | 26 | You may have noticed while reading through this documentation that `bigwheel` uses "hash bang" urls. They look something like this: 27 | ``` 28 | http://someurl.com/#!/someRoute 29 | ``` 30 | 31 | If you'd like to have something else than hash bang you could do this: 32 | ```javascript 33 | module.exports = bigwheel( function() { 34 | return { 35 | postHash: '#somethingElse', 36 | routes: require('../routes') 37 | }; 38 | }); 39 | ``` 40 | 41 | If you did this all urls in would look like this: 42 | ``` 43 | http://someurl.com/#somethingElse/someRoute 44 | ``` 45 | 46 | ## Overlap 47 | 48 | If you've been running `bigwheel` examples you might've noticed that sections animate in and out functions are called at the same time. This means by default sections "overlap". 49 | 50 | If you'd prefer to have sections stagger one section animates out and the next animates in after the animate out. You could pass `overlap: false` through settings: 51 | 52 | ```javascript 53 | module.exports = bigwheel( function() { 54 | return { 55 | overlap: false, 56 | routes: require('../routes') 57 | }; 58 | }); 59 | ``` 60 | -------------------------------------------------------------------------------- /quickstart.md: -------------------------------------------------------------------------------- 1 | # bigwheel quick start 2 | 3 | Here's a very concise example of how to use `bigwheel`. Note this is not the best way to layout your application but it's just a very concise example to show how `bigwheel` works while showing off many features: 4 | 5 | ```javascript 6 | var bigwheel = require('bigwheel'); 7 | var Tween = require('gsap'); 8 | 9 | // create our framework instance 10 | var framework = bigwheel( function(done) { 11 | 12 | // the function passed to bigwheel should return 13 | // a setting object or alternately you can pass 14 | // the setting object to the callback defined as 15 | // done. This is nice if you need to do assynchronous 16 | // loading before content should be shown 17 | return { 18 | 19 | // define our routes 20 | // routes are associated to "sections" 21 | // sections are functions or objects 22 | routes: { 23 | '/': Section, 24 | '/about': Section, 25 | '/contact': Section 26 | } 27 | }; 28 | }); 29 | 30 | // this will start bigwheel and it will start resolving routes 31 | framework.init(); 32 | 33 | // This is the definition for the sections which bigwheel will run 34 | // sections can define init, resize, animateIn, animateOut, destroy functions 35 | // these will methods will be called by bigwheel 36 | function Section() { 37 | 38 | var el; 39 | 40 | return { 41 | 42 | // the init function creates the view and initializes it 43 | // after init finishes the view should not be visible 44 | init: function(req, done) { 45 | el = createEl(req); 46 | el.onclick = function() { 47 | framework.go(getToSection(req)); 48 | }; 49 | done(); 50 | }, 51 | 52 | // the resize function will be called imediately after init 53 | // here you can apply "responsive" calculations on your view 54 | resize: function(width, height) { 55 | var fontSize = width / 500 * 30; 56 | el.style.fontSize = fontSize + 'px'; 57 | el.style.top = Math.round(( height - fontSize ) * 0.5) + 'px'; 58 | }, 59 | 60 | // in animateIn you'll animate in your hidden content that 61 | // was created in init 62 | animateIn: function(req, done) { 63 | Tween.from(el, 1, { 64 | y: -100, 65 | opacity: 0, 66 | ease: Back.easeOut, 67 | onComplete: done 68 | }); 69 | }, 70 | 71 | // in animateOut you'll animate out your content that 72 | // was created in init 73 | animateOut: function(req, done) { 74 | Tween.to(el, 0.25, { 75 | y: 100, 76 | opacity: 0, 77 | ease: Back.easeIn, 78 | onComplete: done 79 | }); 80 | }, 81 | 82 | // in destroy you'll clean up the content which was 83 | // created in init 84 | destroy: function(req, done) { 85 | el.parentNode.removeChild(el); 86 | } 87 | }; 88 | } 89 | 90 | // this is just a utility function created for this example to create 91 | // an element which will be added to the dom and initialized 92 | function createEl(req) { 93 | var el = document.createElement('a'); 94 | el.innerHTML = 'Click to go from "' + req.route + '" to "' + getToSection(req) + '"'; 95 | el.style.position = 'absolute'; 96 | el.style.cursor = 'pointer'; 97 | return document.body.appendChild(el); 98 | } 99 | 100 | // this function acts as almost like a model for this example 101 | // generally you'd either load your model from a server or 102 | // have a static model object 103 | function getToSection(req) { 104 | return { 105 | '/': '/about', 106 | '/about': '/contact', 107 | '/contact': '/' 108 | }[ req.route ]; 109 | } 110 | ``` 111 | 112 | Usually the first thing you'll do is setup a `bigwheel` framework instance: 113 | ```javascript 114 | var framework = bigwheel( function(done) { 115 | return { 116 | routes: { 117 | '/': Section, 118 | '/about': Section, 119 | '/contact': Section 120 | } 121 | }; 122 | }); 123 | ``` 124 | The function passed to `bigwheel` should either return a "settings" object which will be used to setup `bigwheel` the settings object can can also be returned via the callback which will be passed to this function. In this case this callback is called `done`. To pass back the settings object assynchronously you'd do it like this: 125 | ```javascript 126 | var framework = bigwheel( function(done) { 127 | 128 | // do something assynchonous here and then call the 129 | // the done function returning the settings object 130 | done( { 131 | routes: { 132 | '/': Section, 133 | '/about': Section, 134 | '/contact': Section 135 | } 136 | }); 137 | }); 138 | ``` 139 | 140 | In the above code the `bigwheel` is created and routes are defined. Routes are associated to "Sections". A section can be a page which handles: 141 | 1. initializing a view 142 | 2. resizing a view 143 | 3. animating in the view 144 | 4. animating out the view 145 | 5. destroying or unintializing the view 146 | 147 | This is all created here: 148 | ```javascript 149 | function Section() { 150 | 151 | var el; 152 | 153 | return { 154 | 155 | // the init function creates the view and initializes it 156 | // after init finishes the view should not be visible 157 | init: function(req, done) { 158 | el = createEl(req); 159 | el.onclick = function() { 160 | framework.go(getToSection(req)); 161 | }; 162 | done(); 163 | }, 164 | 165 | // the resize function will be called imediately after init 166 | // here you can apply "responsive" calculations on your view 167 | resize: function(width, height) { 168 | var fontSize = width / 500 * 30; 169 | el.style.fontSize = fontSize + 'px'; 170 | el.style.top = Math.round(( height - fontSize ) * 0.5) + 'px'; 171 | }, 172 | 173 | // in animateIn you'll animate in your hidden content that 174 | // was created in init 175 | animateIn: function(req, done) { 176 | Tween.from(el, 1, { 177 | y: -100, 178 | opacity: 0, 179 | ease: Back.easeOut, 180 | onComplete: done 181 | }); 182 | }, 183 | 184 | // in animateOut you'll animate out your content that 185 | // was created in init 186 | animateOut: function(req, done) { 187 | Tween.to(el, 0.25, { 188 | y: 100, 189 | opacity: 0, 190 | ease: Back.easeIn, 191 | onComplete: done 192 | }); 193 | }, 194 | 195 | // in destroy you'll clean up the content which was 196 | // created in init 197 | destroy: function(req, done) { 198 | el.parentNode.removeChild(el); 199 | } 200 | }; 201 | } 202 | ``` 203 | 204 | Things to note here. 205 | 206 | `init`, `animateIn`, `animateOut` receive two variables `req` and `done`. 207 | 208 | `req` contains routing information. In `init` and `animateIn` `req` contains the routing information that caused this section to be resolved. `animateOut` receives routing information which caused this section to be taken out. 209 | 210 | You can change the route which `bigwheel` is on by calling: 211 | ```javascript 212 | framework.go(getToSection(req)); 213 | ``` -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # `bigwheel` 2 |  3 | 4 | `bigwheel` is an unopinionated, minimalist framework which handles frontend application state. It can be used to organize your application into "sections"/pages which are brought in by routes. Animation is a first class citizen and is accounted for when managing application states. `bigwheel` does not conform to a specific render engine framework so a project which is based on the DOM, WebGL, Canvas2D, SVG, or even Console applications can be built using bigwheel. 5 | 6 | This documents purpose is to serve has an overview of how to work with bigwheel. 7 | 8 | ### Using bigwheel: 9 | - [Quick Start](quickstart.md) 10 | 11 | ### Sections: 12 | - [What is a section](sections.md) 13 | - Methods of a section: 14 | + [init](sections-init.md) 15 | + [resize](sections-resize.md) 16 | + [animateIn](sections-animateInOut.md#animatein) and [animateOut](sections-animateInOut.md#animateout) 17 | + [destroy](sections-destroy.md) 18 | 19 | ### Routing: 20 | - [What is a route](routes.md) 21 | - [Defining routes](routes-defining.md) 22 | + [As section](routes-defining.md#as-section-standard-form) 23 | + [As section descriptor](routes-defining.md#as-section-descriptor) 24 | + [Multi section routes](routes-defining.md#multi-section-routes) 25 | - [Special Routes](routes-special.md) 26 | + [Redirects](routes-special.md#redirects) 27 | + [404](routes-special.md#404) 28 | + [initSection](routes-special.md#initsection) 29 | 30 | ### Misc: 31 | - [Auto resize](misc.md#auto-resize) 32 | - [Post hash](misc.md#auto-resize) 33 | - [Overlap](misc.md#overlap) 34 | 35 | ### Gotchas: 36 | - [Forgetting to call done](gotchas.md#forgetting-to-call-done) 37 | - [Circular dependendencies](gotchas.md#circular-dependendencies) 38 | -------------------------------------------------------------------------------- /routes-defining.md: -------------------------------------------------------------------------------- 1 | # Defining Routes 2 | 3 | This part of the documentation will focus solely on defining routes for `bigwheel`. 4 | 5 | Routes are defined as an `Object` and it would look like this: 6 | ```javascript 7 | module.exports = { 8 | '/': require('../sections/Landing'), 9 | '/about': require('../sections/About') 10 | }; 11 | ``` 12 | 13 | When defining Routes for `bigwheel` you'll always be defining url like `String`s which will be associated with a [section](sections.md). 14 | 15 | Even though we're simply associating strings to sections there are three ways to do this: 16 | 1. [Using a section (standard form)](#as-section-standard-form) 17 | 2. [Using a section descriptor](#as-section-descriptor) 18 | 3. [Using multi sections](#multi-section-routes) 19 | 20 | 21 | ## As section (standard form) 22 | 23 | Most of the time your routes will look like the above: 24 | ```javascript 25 | '/about': require('../sections/About') 26 | ``` 27 | In this case if the user were to go to: `http://localhost:8080/#!/about` the section defined at `require('../sections/About')` would be run (`bigwheel` will go through `About`'s `init`, `resize`, `animateIn`, `animateOut`, `destroy` methods) 28 | 29 | **_Note currently `bigwheel` uses "hash bang" routing but could easily be made to handle the history api_** 30 | 31 | **_Gotcha: In all these examples we've been defining routes inline in objects. 32 | It might be tempting to require sections outside of the routes object but this can cause a large gotcha for instance if we did:_** 33 | ```javascript 34 | var Section = require('../sections/TheSection'); 35 | 36 | module.exports = { 37 | '/': Section 38 | }; 39 | ``` 40 | 41 | **_This may cause issues because of [circular dependencies](http://selfcontained.us/2012/05/08/node-js-circular-dependencies/). For instance `Section` may require in the instance of bigwheel and use the `go` method of `bigwheel` to change sections. So in this case: 42 | 43 | - framework (instance of bigwheel) requires routes 44 | - routes requires Section 45 | - Section requires framework 46 | 47 | If a circular dependency is created then `Section` requiring the framework would just receive an empty `Object`_** 48 | 49 | ## As section descriptor 50 | 51 | Another way in which you can definea section is by using a section descriptor `Object`. Setting up routes via section descriptors could look like this: 52 | ```javascript 53 | module.exports = { 54 | '/': require('../sections/Landing'), 55 | '/about': { section: require('../sections/About') }, 56 | '/secret': { section: require('../sections/About'), useURL: false }, 57 | '/gallery/:id': { section: require('../sections/About'), duplicate: true } 58 | }; 59 | ``` 60 | 61 | As you can see you can describe routes in the fashion you've already learned where a section is associated with a string but you can also define a route by passing an `Object` which may have extra options to tell `bigwheel` how to handle that route. 62 | 63 | When defining sections from a section descriptor `Object` you'll always pass a variable called `section` which should be the required section `function` or `Object`. 64 | 65 | After this there are two properties which can use to modify how routes are handled: 66 | 67 | ### `useURL` 68 | 69 | `useURL` tells `bigwheel` that the Browsers location should be changed when the section is brought in. By default `bigwheel` will change the url when navigating to sections (`useURL == true`). 70 | 71 | If you set `useURL` to `false` then the url will never bed updated and also the section cannot be accessed by manually updating the browser's location. 72 | 73 | In the above routes example if a user went in and typed: 74 | ```javascript 75 | http://localhost:8080/#!/secret 76 | ``` 77 | 78 | The secret section would not come up. 79 | 80 | The only way `/secret` can be accessed is by using `bigwheel`'s `go` function. So: 81 | ```javascript 82 | framework.go('/secret'); 83 | ``` 84 | Would bring up the `/secret` section. 85 | 86 | ### `duplicate` 87 | 88 | Hypothetically with the routes: 89 | ```javascript 90 | module.exports = { 91 | '/about': { section: require('../sections/About') }, 92 | '/gallery/:id': { section: require('../sections/About'), duplicate: true } 93 | }; 94 | ``` 95 | 96 | If you had a button in the `/About` section that when clicked would do: 97 | ```javascript 98 | framework.go('/about'); 99 | ``` 100 | 101 | Nothing would happen. `bigwheel` ensures that a section cannot be brough up if it's the current section in view. 102 | 103 | Now there are cases where you do want this functionality. For instance if you had a gallery which showed many gallery items using the same route. Like in the example above `/gallery/:id` would resolve to: 104 | ``` 105 | /gallery/10 106 | /gallery/dog 107 | /gallery/1b 108 | ``` 109 | This is handy because you can create one section that will bring up many different types of gallery items. The issue is that `bigwheel` would prevent any route that resolves to `/gallery/:id`. 110 | 111 | To get around this you can do `duplicate: true` when defining routes using a section descriptor. Doing `duplicate: true` states that this route can be duplicated or opened multiple times. 112 | 113 | ## Multi section routes 114 | 115 | Sometimes you may want to run multiple sections when a route is resolved. A common case for this is when using a menu. Setting your routes this way look like this: 116 | ```javascript 117 | module.exports = { 118 | '/': [ require('../sections/Menu'), require('../sections/Landing') ] 119 | '/about': { section: [ 120 | require('../sections/Menu'), 121 | require('../sections/About') 122 | ], useURL: false } 123 | }; 124 | ``` 125 | 126 | As you can see to define multi section routes you just define your sections in an array using the standard form or using a section descriptor. What will happen is that when the route resolves all the sections will be run in tandem so all `init`, `resize`, `animateIn`, `animateOut`, and `destroy` calls will happen at the same time for all multi sections. 127 | 128 | The reason why this is handy is that if you define `Menu` as an `Object` instead of a `function` `Menu` will always be persistent and it can react to sections coming in for instance highlighting the correct menu button in the `animateIn` function. -------------------------------------------------------------------------------- /routes-special.md: -------------------------------------------------------------------------------- 1 | # Special Routes 2 | 3 | In this page we'll discuss some of the special routes defined in `bigwheel`. 4 | 5 | ## Redirects 6 | 7 | It's sometimes handy to be able to create a redirect. A redirect would look like this: 8 | ```javascript 9 | module.exports = { 10 | '/': require('../sections/LandingSection'), 11 | '/landing': '/' 12 | }; 13 | ``` 14 | 15 | In this case both `'/'` and `'/landing'` would bring up the `LandingSection`. 16 | 17 | ## 404 18 | 19 | Another handy functionality is to create a catch all 404 page. 404's can be defined this way: 20 | ```javascript 21 | module.exports = { 22 | '/': require('../sections/LandingSection'), 23 | '404': require('../sections/FourOFour') 24 | }; 25 | ``` 26 | 27 | ## initSection 28 | 29 | `initSection` is not actually a part of defining routes however it's related to defining routes so this is an appropriate place to discuss `initSection`. 30 | 31 | When you setup `bigwheel` you can do something like this: 32 | ```javascript 33 | var bigwheel = require('bigwheel'); 34 | 35 | module.exports = bigwheel( function(done) { 36 | 37 | done( { 38 | initSection: require('../sections/Preloader'), 39 | routes: require('./routes') 40 | }); 41 | }); 42 | ``` 43 | 44 | Routes are still defined as usual but alongside routes we've another property `initSection`. Basically the purpose of `initSection` is to have a section which is ALWAYS run before any routes are resolved. For instance if in `require('./routes')` we had defined `/about`. Even if the user went to: 45 | ``` 46 | http://someurl.com/#!/about 47 | ``` 48 | The `initSection` will be run before any of the sections defined by routes. This can be useful for things like preloaders or age of majority pages or some other page which "blocks" the user before they enter the site/application. 49 | 50 | The actual section is defined exactly the same except it's constructor takes a callback function which should be called once the `initSection` is prepared to exit. So for instance if we were to write a preloader it would look something like this: 51 | ```javascript 52 | module.exports = Preloader; 53 | 54 | var somethingThatWillPreloadEverything = require('./awesomePreloader'); 55 | 56 | function Preloader(done) { 57 | this.onPreloadComplete = done; 58 | }; 59 | 60 | Preloader.prototype = { 61 | init: function(req, done) { 62 | 63 | var el = this.el = document.createElement('div'); 64 | el.style.background = '#CAFE00'; 65 | el.style.height = '20px'; 66 | el.style.display = 'none'; 67 | document.body.appendChild(el); 68 | 69 | done(); 70 | }, 71 | 72 | animateIn: function(req, done) { 73 | var el = this.el; 74 | var onPreloadComplete = this.onPreloadComplete; 75 | var preloader = somethingThatWillPreloadEverything([ 76 | './images/someImage1.jpg', 77 | './images/someImage2.jpg' 78 | ]); 79 | 80 | // watch for progress of the preloader 81 | preloader.onProgress = function(progress) { 82 | // show the progress of the load using a bar 83 | el.style.width = progress * 200 + 'px'; 84 | 85 | // if the preloader is finished its going to be 1 or 100% 86 | if(progress == 1) { 87 | onPreloadComplete(); 88 | } 89 | }; 90 | 91 | // this will animateIn the el 92 | el.style.display = 'block'; 93 | done(); 94 | }, 95 | 96 | animateOut: function(req, done) { 97 | 98 | // this will animateOut the el 99 | this.el.style.display = 'none'; 100 | }, 101 | 102 | destroy: function(req, done) { 103 | 104 | // remove the element from dom 105 | this.el.parentNode.removeChild(this.el); 106 | } 107 | }; 108 | ``` -------------------------------------------------------------------------------- /routes.md: -------------------------------------------------------------------------------- 1 | # Routes 2 | 3 | Routes are url partials which are associated to [Sections](sections.md). 4 | 5 | What that basically means is that you will define strings/url's which will execute [Sections](sections.md). 6 | 7 | For example you could define your routes like this: 8 | ```javascript 9 | module.exports = { 10 | '/': require('../SectionLanding'), 11 | '/about': require('../SectionAbout') 12 | }; 13 | ``` 14 | 15 | Routing is handled by the module [bw-router](https://www.npmjs.com/package/bw-router) which primarily uses the module [routes](https://www.npmjs.com/package/routes). 16 | 17 | `bw-router` primarily watches the `window.location.hash` for changes. Once a change occurs it will try to figure out which [Sections](sections.md) should be opened. 18 | 19 | For instance our Browsers url might look something like: 20 | ``` 21 | http://localhost:8080/#!/about 22 | ``` 23 | In this case the route `'/about': require('../SectionAbout')` would be used and `SectionAbout` would initialized and then animated in. 24 | 25 | Something to note is that `bw-router` can work outside of the browser. For instance `bigwheel` can be used as a framework to create command line applications, or be used in browser like environments like [CocoonJS](https://www.ludei.com/cocoonjs/). There is no relliance on `window.location`. In this case simply `bigwheel`'s `go` method would be used to cause the router to change sections. (more on this later) -------------------------------------------------------------------------------- /sections-animateInOut.md: -------------------------------------------------------------------------------- 1 | # The `animateIn` and `animateOut` method's of a Section 2 | 3 | You might remember each section may contain five methods: `init`, `resize`, `animateIn`, `animateOut`, `destroy`. 4 | 5 | We will discuss both the `animateIn` and `animateOut` methods in detail here since they are quire similar. 6 | 7 | ## `animateIn` 8 | 9 | `animateIn` has one sole purpose and that is to visually bring in content via animations. It is called immediately after the `init` method is finished. 10 | 11 | The `animateIn` method assumes that content should be in an out state which was defined in the `init` section. 12 | 13 | For instance a simple section might look like this: 14 | ```javascript 15 | module.exports = Section; 16 | 17 | function Section() {} 18 | 19 | Section.prototype = { 20 | init: function(req, done) { 21 | this.el = document.createElement('div'); 22 | this.el.innerHTML = 'Something something'; 23 | this.el.style.opacity = 0; 24 | document.body.appendChild(this.el); 25 | 26 | done(); 27 | }, 28 | 29 | animateIn: function(req, done) { 30 | this.el.style.opacity = 1; 31 | 32 | done(); 33 | } 34 | }; 35 | ``` 36 | 37 | In this example there really isn't an animation but it will simply show what should happen in the `animateIn` function. As you can see in the `init` method we create a `div` element, set it's content, add it to the body, and set it's `opacity` to `0`. Setting it's opacity to `0` ensures that it can't be seen until it's animated in. (obviously you could do this through an external style sheet). When the `animateIn` method is called by `bigwheel` the element's `opacity` is set to `1` making it visible and then `bigwheel` is notified that the animation for animate in is complete via the `done` parameter. 38 | 39 | Of course you could use the excellent Tweening module `gsap` to perform animations: 40 | 41 | ```javascript 42 | module.exports = Section; 43 | 44 | var Tween = require('gsap'); 45 | 46 | function Section() {} 47 | 48 | Section.prototype = { 49 | init: function(req, done) { 50 | this.el = document.createElement('div'); 51 | this.el.innerHTML = 'Something something'; 52 | this.el.style.opacity = 0; 53 | document.body.appendChild(this.el); 54 | 55 | done(); 56 | }, 57 | 58 | animateIn: function(req, done) { 59 | Tween.to(this.el, 0.5, { opacity: 1, onComplete: done }); 60 | } 61 | }; 62 | ``` 63 | 64 | Now that's getting a bit fancier where the element is tweened from `opacity` `0` to `1` and when the Tween is finished the `done` parameter is called. 65 | 66 | **_Gotcha: Remember to always call the `done` parameter otherwise `bigwheel` will not know the animation for `animateIn` is finished_** 67 | 68 | The `req` parameter which is passed to `animateIn` is exactly the same as what is passed to the `init` method. It still maybe beneficial to create dynamic animations based on the routing information. 69 | 70 | ## `animateOut` 71 | 72 | `animateOut` also has one sole purpose to animate out content. It functions exactly the same as `animateIn`. Our simple example would look this with an `animateOut` function: 73 | 74 | ```javascript 75 | module.exports = Section; 76 | 77 | function Section() {} 78 | 79 | Section.prototype = { 80 | init: function(req, done) { 81 | this.el = document.createElement('div'); 82 | this.el.innerHTML = 'Something something'; 83 | this.el.style.opacity = 0; 84 | document.body.appendChild(this.el); 85 | 86 | done(); 87 | }, 88 | 89 | animateIn: function(req, done) { 90 | this.el.style.opacity = 1; 91 | 92 | done(); 93 | }, 94 | 95 | animateOut: function(req, done) { 96 | this.el.style.opacity = 0; 97 | 98 | done(); 99 | } 100 | }; 101 | ``` 102 | 103 | **_Again remember to call done as `bigwheel` will not know that `animateOut` has finished if you do not_** 104 | 105 | `animateOut` is called only if `bigwheel` is bringing in a new section and that new section has initialized. 106 | 107 | One major difference between `animateIn` and `animateOut` is that the `req` parameter actually contains the routing information which was used to bring in the new content. 108 | 109 | So in our case let's say our current section was brought in using the route `'/landing` and the url for the site has changed. The new route/url will be `'/about`. `animateOut`'s `req.route` will contain the value `/about` even though our section is `/landing`. This is done on purpose to allow your animations to be responsive to which section is coming in. 110 | 111 | For instance you could have two routes `/left` and `/right`. When `animateOut` is called `req.route` could have the value `'/left'` in which case we could animate our element's `style.left` to `-100px`. However if the new section coming in would be `/right` `req.route` for `animateOut` would be `'/right'` in which case we could animate `style.left` to `100px`. 112 | 113 | Here's what it would look like in code: 114 | ```javascript 115 | module.exports = Section; 116 | 117 | var Tween = require('gsap'); 118 | 119 | function Section() {} 120 | 121 | Section.prototype = { 122 | init: function(req, done) { 123 | this.el = document.createElement('div'); 124 | this.el.innerHTML = 'Something something'; 125 | this.el.style.opacity = 0; 126 | document.body.appendChild(this.el); 127 | 128 | done(); 129 | }, 130 | 131 | animateIn: function(req, done) { 132 | Tween.to( this.el, 0.5, { opacity: 1, onComplete: done }); 133 | }, 134 | 135 | animateOut: function(req, done) { 136 | if(req.route == '/left') { 137 | Tween.to( this.el, 0.5, { 138 | left: -100, 139 | opacity: 0, 140 | onComplete: done 141 | }); 142 | } else if(req.route == '/right') { 143 | Tween.to( this.el, 0.5, { 144 | left: 100, 145 | opacity: 0, 146 | onComplete: done 147 | }); 148 | } 149 | } 150 | }; 151 | ``` 152 | -------------------------------------------------------------------------------- /sections-destroy.md: -------------------------------------------------------------------------------- 1 | # The `animateIn` and `animateOut` method's of a Section 2 | 3 | You might remember each section may contain five methods: `init`, `resize`, `animateIn`, `animateOut`, `destroy`. 4 | 5 | Here we'll talk about `destroy`. 6 | 7 | ## `destroy` 8 | 9 | Clearly `destroy` is the best named function in `bigwheel` but aside from that the purpose of `destroy` is to clean up any resources that were created for the section. In many cases it might be removing a `HTMLElement` from the dom. 10 | 11 | For example: 12 | ```javascript 13 | module.exports = Section; 14 | 15 | function Section() {} 16 | 17 | Section.prototype = { 18 | init: function(req, done) { 19 | this.el = document.createElement('h1'); 20 | this.el.innerHTML = 'I\'m a title'; 21 | document.body.appendChild(this.el); 22 | 23 | done(); 24 | }, 25 | 26 | destroy: function(req, done) { 27 | // remove the element 28 | this.el.parentNode.removeChild(this.el); 29 | } 30 | }; 31 | ``` 32 | 33 | Note that in destroy calling the `done` method is optional. Currently it does nothing but is there to keep the API consistent and allow for future uses. 34 | 35 | The `req` parameter contains routing information for the new route/section that is coming in. You can think of it as the routing information causing this section to be destroyed. -------------------------------------------------------------------------------- /sections-init.md: -------------------------------------------------------------------------------- 1 | # The `init` method of a Section 2 | 3 | As you may know now each section may contain five methods: `init`, `resize`, `animateIn`, `animateOut`, `destroy`. 4 | 5 | We will now discuss the `init` method in detail. 6 | 7 | ## `init` 8 | 9 | The purpose of the `init` method is to initialize your content. In many cases it maybe adding new dom elements to the dom, or if working with WebGL initializing buffers, loading models etc. 10 | 11 | Lets create an `init` method which just brings in a new `HTMLImageElement`. 12 | 13 | ```javascript 14 | module.exports = MySection; 15 | 16 | function MySection() {} 17 | 18 | MySection.prototype = { 19 | init: function(req, done) { 20 | this.image = new Image(); 21 | this.image.src = './someImage.jpg'; 22 | document.body.appendChild(this.image); 23 | 24 | done(); 25 | } 26 | }; 27 | ``` 28 | 29 | Now our section on `init` would create and add a new image to the `
`. 30 | 31 | Our example is nice but there's a couple of issues. As stated before `bigwheel` works by bringing in and out sections by going through `init`, `animateIn`, and `animateOut` methods. 32 | 33 | ### Issue #1: two pages on screen at the same time 34 | 35 | The `init` method for the new section is called immediately after `bigwheel` receives a section change notification. This means the current section will be on screen when the new sections `init` method is called. Currently in our example the old content will be on screen and this new content (our image from `'./someImage.jpg'`) will be on screen at the same time. 36 | 37 | To resolve this we could for instance set the css `display` property to `none`. 38 | 39 | ```javascript 40 | module.exports = MySection; 41 | 42 | function MySection() {} 43 | 44 | MySection.prototype = { 45 | init: function(req, done) { 46 | this.image = new Image(); 47 | this.image.src = './someImage.jpg'; 48 | this.image.style.display = 'none'; 49 | document.body.appendChild(this.image); 50 | 51 | done(); 52 | } 53 | }; 54 | ``` 55 | 56 | Now what would happen is that the old content which maybe there will still remain on screen and this new content (our image) comes in but is invisible. In the `animateIn` method we'll then make it visible again. 57 | 58 | ### Issue #2: notifying `bigwheel` we're done before we actually are 59 | 60 | Another issue we have is that technically we're notifying `bigwheel` that we're finished initializing when in reality it would be nicer to do that once our image has finished loading. 61 | 62 | Our code could look like this: 63 | 64 | ```javascript 65 | module.exports = MySection; 66 | 67 | function MySection() {} 68 | 69 | MySection.prototype = { 70 | init: function(req, done) { 71 | this.image = new Image(); 72 | this.image.src = './someImage.jpg'; 73 | this.image.style.display = 'none'; 74 | document.body.appendChild(this.image); 75 | 76 | image.onload = done; 77 | } 78 | }; 79 | ``` 80 | 81 | The `done` parameter passed to our `init` method is a function which should be called once initialization is finished. So in our case we'd like to add the image to `` and then wait for it to be loaded and then notify `bigwheel` that we're finished initializing our content. So we can just simply add the `done` paramter to the `onload` event handler of the `HTMLImageElement`. 82 | 83 | **_Gotcha: It should be noted here that a huge gotcha is to forget to call the `done` parameter. ALWAYS remember to call the `done` parameter otherwise `bigwheel` will not know that your `init` method is finished and your application will sit there doing nothing._** 84 | 85 | ### `req` 86 | 87 | You might be wondering what is the `req` parameter. `req` is an abreviation for request. It is an `Object` which contains information which was used to request `bigwheel` to bring in it's content. `bigwheel` works by using routes. Routes are essentially url's which open/show content. We'll discuss this further later but the `req` parameter allows your sections content to be dynamic. 88 | 89 | The `req` parameter has one very key var variable called `route`. This was the route which was used to request this section. 90 | 91 | For instance this section could be an about section it's route could look something like `'/about`. So when this section would come in `req.route`'s value would be `'/about'`. Let's look at how we could use this new knowledge. 92 | 93 | ```javascript 94 | module.exports = MySection; 95 | 96 | function MySection() {} 97 | 98 | MySection.prototype = { 99 | init: function(req, done) { 100 | var sectionRoute = req.route; 101 | 102 | this.image = new Image(); 103 | this.image.src = sectionRoute + '/someImage.jpg'; 104 | this.image.style.display = 'none'; 105 | document.body.appendChild(this.image); 106 | 107 | image.onload = done; 108 | } 109 | }; 110 | ``` 111 | 112 | We've assigned `req.route` to `sectionRoute`. So now in the above example if `sectionRoute` is `'/about'`. Our image would attempt to load from the following url `'/about/someImage.jpg'`. Now there's no reason why we could use this same section for multiple routes. For instance the `'/landing'` route could also bring in this section in which case the image would load from `'/landing/someImage.jpg'`. 113 | 114 | I hope you can see how the `req` parameter can be used to make your content be dynamic. 115 | 116 | ### `bigwheel` and models 117 | 118 | A more advanced case for using `req` would be to access a model. This could be either loading JSON content from a server or querying a static `Object`. 119 | 120 | For instance we could have a static model on our site that looks like this: 121 | 122 | ```javascript 123 | module.exports = { 124 | "/landing": { 125 | "title": "This is the title for Landing" 126 | }, 127 | 128 | "/about": { 129 | "title": "This is the title for About" 130 | } 131 | }; 132 | ``` 133 | 134 | Our section for both routes `'/landing'` and `'/about'` could look like this: 135 | 136 | ```javascript 137 | module.exports = Section; 138 | 139 | // note we're requiring in the model defined above here 140 | var model = require('../model'); 141 | 142 | function Section() {} 143 | 144 | Section.prototype = { 145 | init: function(req, done) { 146 | var myModel = model[ req.route ]; 147 | this.el = document.createElement('h1'); 148 | 149 | this.el.innerHTML = myModel.title; 150 | document.body.appendChild(this.el); 151 | 152 | done(); 153 | }, 154 | 155 | destroy: function(req, done) { 156 | // remove the element 157 | this.el.parentNode.removeChild(this.el); 158 | } 159 | }; 160 | ``` 161 | 162 | In this case `Section` took `req.route` and queried the static model and took the contents of `.title` and set the `innerHTML` of our element. So if this section was opened using the route `/landing` our `h1` element's `innerHTML` would be `"This is the title for Landing"`. If the route to open this section was `/about` then the value of `innerHTML` would be `"This is the title for About"` -------------------------------------------------------------------------------- /sections-resize.md: -------------------------------------------------------------------------------- 1 | # The `resize` method of a Section 2 | 3 | The five methods of a section are: `init`, `resize`, `animateIn`, `animateOut`, `destroy`. 4 | 5 | We will now discuss the `resize` method in detail. 6 | 7 | ## `resize` 8 | 9 | Responsive design for websites is practically a must today with the varied amount of resolutions for devices. 10 | 11 | We believe responsive CSS is nice but there are still places to allow for responsive design through Javascript. For instance your website might be entirely built ontop of the `