├── CNAME ├── .gitignore ├── component.json ├── favicon.ico ├── demo ├── images │ ├── 1.jpg │ ├── 3.jpeg │ └── 4.gif ├── demo.js ├── demo.styl └── demo.css ├── README.md ├── package.json ├── Cakefile ├── oridomi.jquery.json ├── LICENSE ├── docs └── docco.css ├── index.html ├── oridomi.min.js ├── oridomi.js └── oridomi.coffee /CNAME: -------------------------------------------------------------------------------- 1 | oridomi.com 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | test.html 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oriDomi", 3 | "version": "0.2.2" 4 | } 5 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidchase/oriDomi/master/favicon.ico -------------------------------------------------------------------------------- /demo/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidchase/oriDomi/master/demo/images/1.jpg -------------------------------------------------------------------------------- /demo/images/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidchase/oriDomi/master/demo/images/3.jpeg -------------------------------------------------------------------------------- /demo/images/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidchase/oriDomi/master/demo/images/4.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #[oriDomi](http://oridomi.com) 2 | #### Fold up DOM elements like paper 3 | [Dan Motzenbecker](http://oxism.com), MIT License 4 | 5 | [@dcmotz](http://twitter.com/dcmotz) 6 | 7 | #![oriDomi](http://oxism.com/images/oridomi.png) 8 | #![oriDomi](http://oxism.com/images/oridomi2.png) 9 | 10 | Visit the site for examples, brief documentation and notes. 11 | 12 | Read the [annotated source](http://oridomi.com/docs/oridomi.html) for a detailed look. 13 | 14 | Pull requests are welcome. 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oridomi", 3 | "description": "Fold up the DOM like paper.", 4 | "author": "Dan Motzenbecker (http://oxism.com)", 5 | "homepage": "http://oridomi.com", 6 | "version": "0.2.2", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/dmotz/oriDomi.git" 11 | }, 12 | "keywords": [ 13 | "DOM", 14 | "paper", 15 | "frontend", 16 | "jquery" 17 | ], 18 | "dependencies": { 19 | "coffee-script" : "1.4.x" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | {exec, spawn} = require 'child_process' 2 | 3 | output = (data) -> console.log data.toString() 4 | 5 | print = (fn) -> 6 | (err, stdout, stderr) -> 7 | throw err if err 8 | console.log stdout, stderr 9 | fn?() 10 | 11 | 12 | task 'build', 'Build, minify, and generate docs for oriDomi', -> 13 | exec 'coffee -c oridomi.coffee', print -> 14 | exec 'uglifyjs -o oridomi.min.js oridomi.js', print() 15 | exec 'docco oridomi.coffee', print() 16 | 17 | 18 | task 'watch', 'Build oriDomi continuously', -> 19 | watcher = spawn 'coffee', ['-wc', 'oridomi.coffee'] 20 | watcher.stdout.on 'data', output 21 | watcher.stderr.on 'data', output 22 | -------------------------------------------------------------------------------- /oridomi.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oridomi", 3 | "title": "oriDomi", 4 | "description": "Fold up the DOM like paper.", 5 | "keywords": [ 6 | "paper", 7 | "animation", 8 | "origami", 9 | "UI", 10 | "mobile" 11 | ], 12 | "version": "0.2.2", 13 | "author": { 14 | "name": "Dan Motzenbecker", 15 | "url": "http://oxism.com" 16 | }, 17 | "licenses": [ 18 | { 19 | "type": "MIT", 20 | "url": "http://opensource.org/licenses/MIT" 21 | } 22 | ], 23 | "bugs": "https://github.com/dmotz/oriDomi/issues", 24 | "homepage": "http://oridomi.com", 25 | "docs": "http://oridomi.com", 26 | "dependencies": { 27 | "jquery": ">=1.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Dan Motzenbecker 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /demo/demo.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | function init(){ 4 | var demo1 = document.getElementsByClassName('demo1')[0], 5 | domi1 = new OriDomi(demo1), 6 | demo2 = document.getElementsByClassName('demo2')[0], 7 | domi2 = new OriDomi(demo2, { hPanels: 1, vPanels: 3 }), 8 | demo3 = document.getElementsByClassName('demo3')[0], 9 | domi3 = new OriDomi(demo3, { hPanels: 1, vPanels: 5 }), 10 | demo4 = document.getElementsByClassName('demo4')[0], 11 | domi4 = new OriDomi(demo4, { hPanels: 1, vPanels: 6, perspective: 500 }), 12 | demo5 = document.getElementsByClassName('demo5')[0], 13 | domi5 = new OriDomi(demo5, { hPanels: 10, vPanels: 1 }), 14 | demo6 = document.getElementsByClassName('demo6')[0], 15 | domi6 = new OriDomi(demo6, { hPanels: 1, vPanels: 5, touchEnabled: false, speed: 400 }), 16 | foldMe = document.querySelector('.fold-me > p'), 17 | foldDomi = new OriDomi(foldMe, { vPanels: 1, hPanels: 4, perspective: 200, speed: 500 }); 18 | 19 | foldMe.addEventListener('mouseover', function(){ 20 | foldDomi.accordion(-40, 1); 21 | }, false); 22 | 23 | foldMe.addEventListener('mouseout', function(){ 24 | foldDomi.reset(); 25 | }, false); 26 | 27 | setTimeout(function(){ 28 | domi1.reveal(40, 1); 29 | }, 1000); 30 | 31 | setTimeout(function(){ 32 | domi2.reveal(40); 33 | domi3.stairs(-25, 2); 34 | domi4.accordion(-50); 35 | domi5.curl(-60, 1); 36 | }, 3000); 37 | 38 | demo6.addEventListener('click', function(){ 39 | domi6.isFoldedUp ? domi6.reset() : domi6.foldUp(); 40 | }, false); 41 | 42 | } 43 | 44 | document.addEventListener('DOMContentLoaded', init, false); 45 | 46 | })(); 47 | -------------------------------------------------------------------------------- /docs/docco.css: -------------------------------------------------------------------------------- 1 | /*--------------------- Layout and Typography ----------------------------*/ 2 | body { 3 | font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; 4 | font-size: 15px; 5 | line-height: 22px; 6 | color: #252519; 7 | margin: 0; padding: 0; 8 | } 9 | a { 10 | color: #261a3b; 11 | } 12 | a:visited { 13 | color: #261a3b; 14 | } 15 | p { 16 | margin: 0 0 15px 0; 17 | } 18 | h1, h2, h3, h4, h5, h6 { 19 | margin: 0px 0 15px 0; 20 | } 21 | h1 { 22 | margin-top: 40px; 23 | } 24 | hr { 25 | border: 0 none; 26 | border-top: 1px solid #e5e5ee; 27 | height: 1px; 28 | margin: 20px 0; 29 | } 30 | #container { 31 | position: relative; 32 | } 33 | #background { 34 | position: fixed; 35 | top: 0; left: 525px; right: 0; bottom: 0; 36 | background: #f5f5ff; 37 | border-left: 1px solid #e5e5ee; 38 | z-index: -1; 39 | } 40 | #jump_to, #jump_page { 41 | background: white; 42 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 43 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 44 | font: 10px Arial; 45 | text-transform: uppercase; 46 | cursor: pointer; 47 | text-align: right; 48 | } 49 | #jump_to, #jump_wrapper { 50 | position: fixed; 51 | right: 0; top: 0; 52 | padding: 5px 10px; 53 | } 54 | #jump_wrapper { 55 | padding: 0; 56 | display: none; 57 | } 58 | #jump_to:hover #jump_wrapper { 59 | display: block; 60 | } 61 | #jump_page { 62 | padding: 5px 0 3px; 63 | margin: 0 0 25px 25px; 64 | } 65 | #jump_page .source { 66 | display: block; 67 | padding: 5px 10px; 68 | text-decoration: none; 69 | border-top: 1px solid #eee; 70 | } 71 | #jump_page .source:hover { 72 | background: #f5f5ff; 73 | } 74 | #jump_page .source:first-child { 75 | } 76 | table td { 77 | border: 0; 78 | outline: 0; 79 | } 80 | td.docs, th.docs { 81 | max-width: 450px; 82 | min-width: 450px; 83 | min-height: 5px; 84 | padding: 10px 25px 1px 50px; 85 | overflow-x: hidden; 86 | vertical-align: top; 87 | text-align: left; 88 | } 89 | .docs pre { 90 | margin: 15px 0 15px; 91 | padding-left: 15px; 92 | } 93 | .docs p tt, .docs p code { 94 | background: #f8f8ff; 95 | border: 1px solid #dedede; 96 | font-size: 12px; 97 | padding: 0 0.2em; 98 | } 99 | .pilwrap { 100 | position: relative; 101 | } 102 | .pilcrow { 103 | font: 12px Arial; 104 | text-decoration: none; 105 | color: #454545; 106 | position: absolute; 107 | top: 3px; left: -20px; 108 | padding: 1px 2px; 109 | opacity: 0; 110 | -webkit-transition: opacity 0.2s linear; 111 | } 112 | td.docs:hover .pilcrow { 113 | opacity: 1; 114 | } 115 | td.code, th.code { 116 | padding: 14px 15px 16px 25px; 117 | width: 100%; 118 | vertical-align: top; 119 | background: #f5f5ff; 120 | border-left: 1px solid #e5e5ee; 121 | } 122 | pre, tt, code { 123 | font-size: 12px; line-height: 18px; 124 | font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; 125 | margin: 0; padding: 0; 126 | } 127 | 128 | 129 | /*---------------------- Syntax Highlighting -----------------------------*/ 130 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 131 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 132 | body .hll { background-color: #ffffcc } 133 | body .c { color: #408080; font-style: italic } /* Comment */ 134 | body .err { border: 1px solid #FF0000 } /* Error */ 135 | body .k { color: #954121 } /* Keyword */ 136 | body .o { color: #666666 } /* Operator */ 137 | body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 138 | body .cp { color: #BC7A00 } /* Comment.Preproc */ 139 | body .c1 { color: #408080; font-style: italic } /* Comment.Single */ 140 | body .cs { color: #408080; font-style: italic } /* Comment.Special */ 141 | body .gd { color: #A00000 } /* Generic.Deleted */ 142 | body .ge { font-style: italic } /* Generic.Emph */ 143 | body .gr { color: #FF0000 } /* Generic.Error */ 144 | body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 145 | body .gi { color: #00A000 } /* Generic.Inserted */ 146 | body .go { color: #808080 } /* Generic.Output */ 147 | body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 148 | body .gs { font-weight: bold } /* Generic.Strong */ 149 | body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 150 | body .gt { color: #0040D0 } /* Generic.Traceback */ 151 | body .kc { color: #954121 } /* Keyword.Constant */ 152 | body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ 153 | body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ 154 | body .kp { color: #954121 } /* Keyword.Pseudo */ 155 | body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ 156 | body .kt { color: #B00040 } /* Keyword.Type */ 157 | body .m { color: #666666 } /* Literal.Number */ 158 | body .s { color: #219161 } /* Literal.String */ 159 | body .na { color: #7D9029 } /* Name.Attribute */ 160 | body .nb { color: #954121 } /* Name.Builtin */ 161 | body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 162 | body .no { color: #880000 } /* Name.Constant */ 163 | body .nd { color: #AA22FF } /* Name.Decorator */ 164 | body .ni { color: #999999; font-weight: bold } /* Name.Entity */ 165 | body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 166 | body .nf { color: #0000FF } /* Name.Function */ 167 | body .nl { color: #A0A000 } /* Name.Label */ 168 | body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 169 | body .nt { color: #954121; font-weight: bold } /* Name.Tag */ 170 | body .nv { color: #19469D } /* Name.Variable */ 171 | body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 172 | body .w { color: #bbbbbb } /* Text.Whitespace */ 173 | body .mf { color: #666666 } /* Literal.Number.Float */ 174 | body .mh { color: #666666 } /* Literal.Number.Hex */ 175 | body .mi { color: #666666 } /* Literal.Number.Integer */ 176 | body .mo { color: #666666 } /* Literal.Number.Oct */ 177 | body .sb { color: #219161 } /* Literal.String.Backtick */ 178 | body .sc { color: #219161 } /* Literal.String.Char */ 179 | body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ 180 | body .s2 { color: #219161 } /* Literal.String.Double */ 181 | body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 182 | body .sh { color: #219161 } /* Literal.String.Heredoc */ 183 | body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 184 | body .sx { color: #954121 } /* Literal.String.Other */ 185 | body .sr { color: #BB6688 } /* Literal.String.Regex */ 186 | body .s1 { color: #219161 } /* Literal.String.Single */ 187 | body .ss { color: #19469D } /* Literal.String.Symbol */ 188 | body .bp { color: #954121 } /* Name.Builtin.Pseudo */ 189 | body .vc { color: #19469D } /* Name.Variable.Class */ 190 | body .vg { color: #19469D } /* Name.Variable.Global */ 191 | body .vi { color: #19469D } /* Name.Variable.Instance */ 192 | body .il { color: #666666 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /demo/demo.styl: -------------------------------------------------------------------------------- 1 | @import 'nib' 2 | 3 | * 4 | margin: 0 5 | padding: 0 6 | 7 | ::-moz-selection 8 | background: #444 9 | color: #fff 10 | text-shadow: none 11 | 12 | 13 | ::selection 14 | background: #444 15 | color: #fff 16 | text-shadow: none 17 | 18 | 19 | a 20 | color: #333 21 | 22 | 23 | html 24 | font-size: 100% 25 | 26 | 27 | body 28 | background-color: #eee 29 | color: #333 30 | margin: 0 auto 31 | font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, Georgia, Times, FreeSerif, serif 32 | text-rendering: optimizeLegibility 33 | color: #444 34 | 35 | 36 | h1, h2, h3, h4 37 | -webkit-font-smoothing: antialiased 38 | font-smoothing: antialiased 39 | 40 | 41 | h2 42 | text-align: center 43 | margin-bottom: 1rem 44 | font-size: 1.7rem 45 | letter-spacing: -0.1rem 46 | 47 | 48 | h5 49 | text-align: center 50 | font-weight: normal 51 | font-size: 1.1rem 52 | font-style: italic 53 | 54 | 55 | header 56 | background-color: #444 57 | border-bottom: 1px #333 solid 58 | border-top: 1px #333 solid 59 | padding: 1rem 60 | padding-bottom: 0 61 | perspective: 62.5rem 62 | text-align: center 63 | margin-bottom: 0.625rem 64 | overflow: hidden 65 | 66 | .rotation 67 | animation: swivel 12s ease-out 68 | animation-direction: alternate 69 | animation-iteration-count: infinite 70 | transform-style: preserve-3d 71 | 72 | &:hover .demo1 73 | color: #3fffed !important 74 | border-color: #3fffed !important 75 | 76 | > h2 77 | display: inline-block 78 | font-size: 1.55rem 79 | background-color: #333 80 | padding: 0.5rem 81 | padding-bottom: 0.3rem 82 | 83 | > a 84 | transition: color .3s 85 | color: #ddd 86 | 87 | &:hover 88 | color: #3fffed 89 | 90 | > h3 91 | display: inline-block 92 | font-size: 1rem 93 | 94 | 95 | .menu 96 | left: 0.625rem 97 | width: 7.5rem 98 | 99 | ul 100 | background-color: #ddd 101 | padding: 0.625rem 102 | list-style: none 103 | border-radius: 0 0 5px 5px 104 | 105 | li 106 | text-align: left 107 | 108 | a 109 | display: block 110 | text-decoration: none 111 | color: #666 112 | transition: all .3s 113 | border-bottom: 1px transparent dotted 114 | 115 | &:hover 116 | color: #333 117 | border-color: #aaa 118 | 119 | ul 120 | padding: 0 121 | padding-left: 1rem 122 | font-size: 0.7rem 123 | line-height: 1 124 | 125 | 126 | .fold-me, .menu 127 | transition: all .3s 128 | position: fixed 129 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif 130 | top: 0 131 | text-align: left 132 | font-weight: bold 133 | text-shadow: 0 1px 0 rgba(255, 255, 255, .7) 134 | text-decoration: none 135 | color: #666 136 | font-size: 0.85rem 137 | z-index: 100 138 | 139 | .fold-me 140 | cursor: pointer 141 | line-height: 1.5 142 | right: 0.625rem 143 | 144 | 145 | p 146 | padding: 0.625rem 147 | padding-right: 2.5rem 148 | width: 1.875rem 149 | background-color: #ddd 150 | border-radius: 0 0 5px 5px 151 | 152 | 153 | #tagline 154 | margin-bottom: 1.875rem 155 | text-align: center 156 | position: relative 157 | margin-top: -3.125rem 158 | letter-spacing: -1px 159 | z-index: -1 160 | 161 | h1 162 | background-color: #fff 163 | color: #444 164 | display: inline-block 165 | padding: 0.5rem 166 | padding-bottom: 0.3rem 167 | font-size: 2rem 168 | 169 | 170 | #author 171 | text-align: center 172 | font-style: italic 173 | font-size: 1.1rem 174 | line-height: 3 175 | color: #fff 176 | margin-top: -1.875rem 177 | margin-bottom: 0.125rem 178 | 179 | > a 180 | color: #fff 181 | text-decoration: none 182 | 183 | &:hover 184 | text-decoration: underline 185 | 186 | 187 | ul 188 | list-style: disc 189 | list-style-position: inside 190 | 191 | > li 192 | text-align: center 193 | line-height: 2 194 | 195 | 196 | .hidden 197 | display: none 198 | 199 | section 200 | margin-bottom: 3.125rem 201 | float: left 202 | box-sizing: border-box 203 | width: 100% 204 | 205 | > div 206 | margin: 0 auto 207 | max-width: 43.75rem 208 | padding: 0 1.5rem 209 | text-shadow: 0 1px 0 #fff 210 | 211 | p 212 | text-align: center 213 | margin-bottom: 1.25rem 214 | 215 | 216 | pre 217 | background-color: #333 218 | color: #fff 219 | border-radius: 5px 220 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .5) 221 | font-size: 1rem 222 | margin: 0 auto 223 | padding: 0.625rem 224 | margin-bottom: 1.25rem 225 | overflow: auto 226 | 227 | 228 | .demo1 229 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif 230 | width: 21.875rem 231 | margin: 0 auto 232 | text-align: center 233 | background-color: #444 234 | color: #fff 235 | padding: 0.625rem 0 236 | border: 1.25rem #eee solid 237 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .1) 238 | margin-bottom: 2.5rem 239 | background-image: url('./images/1.jpg') 240 | background-size: 21.875rem 241 | transition: color .5s, border-color .5s 242 | overflow: hidden 243 | 244 | > h1 245 | text-transform: uppercase 246 | letter-spacing: -0.125rem 247 | font-size: 4.375rem 248 | line-height: 2 249 | 250 | > h4 251 | font-size: 1.875rem 252 | line-height: 0 253 | margin-bottom: 3.75rem 254 | 255 | 256 | h3 257 | text-align: center 258 | margin-bottom: 1.25rem 259 | 260 | > a 261 | text-decoration: none 262 | color: #eee 263 | background-color: #666 264 | padding: 0.5rem 265 | padding-bottom: 0.3rem 266 | transition: all .3s 267 | 268 | &:hover 269 | color: #666 270 | background-color: #fff 271 | 272 | 273 | #examples 274 | > h2 275 | margin-bottom: 1rem 276 | 277 | > h5 278 | margin-bottom: 1rem 279 | 280 | > ul 281 | list-style: none 282 | 283 | > li 284 | display: block 285 | padding-bottom: 1rem 286 | 287 | pre 288 | max-width: 30.625rem 289 | margin-top: 2rem 290 | 291 | &:nth-child(even) 292 | > article 293 | text-shadow: 0 1px 0 #fff 294 | 295 | &:nth-child(odd) 296 | background-color: #444 297 | color: #fff 298 | 299 | > article 300 | padding: 0 1.5rem 301 | text-shadow: 0 -1px 0 #000 302 | 303 | article 304 | margin-bottom: 1.5rem 305 | 306 | h4 307 | font-size: 1.5rem 308 | 309 | h5 310 | font-size: 1.1rem 311 | line-height: 1 312 | color: #ccc 313 | margin-bottom: 0.6rem 314 | 315 | p 316 | font-size: 1rem 317 | line-height: 1.4 318 | 319 | 320 | .demo 321 | margin: 0 auto 322 | 323 | 324 | .demo2 325 | font-family: "Abril Fatface", "Hoefler Text", Constantia, Palatino, Georgia, serif 326 | font-size: 4.5rem 327 | width: 25rem 328 | height: 10rem 329 | text-align: center 330 | line-height: 1 331 | color: #ff676d 332 | background-color: #6ac1ff 333 | padding: 2.5rem 0 334 | 335 | 336 | .demo3 337 | font-family: Lato, "Helvetica Neue", Arial, Helvetica, sans-serif 338 | text-transform: uppercase 339 | font-size: 6.25rem 340 | background-color: #444 341 | color: #fff 342 | width: 26.875rem 343 | padding: 0.625rem 0.9375rem 344 | background-image: url('./images/3.jpeg') 345 | background-size: 31.25rem 346 | text-align: center 347 | 348 | 349 | .demo4 350 | width: 18.75rem 351 | height: 12.5rem 352 | background-image: url('./images/4.gif') 353 | 354 | 355 | .demo5 356 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif 357 | font-weight: 900 358 | font-style: italic 359 | text-transform: uppercase 360 | font-size: 5rem 361 | width: 25rem 362 | line-height: 1 363 | text-align: center 364 | background-color: #444 365 | color: #E2BB7C 366 | border: 0.9375rem solid #E2BB7C 367 | letter-spacing: -0.3125rem 368 | padding: 3.125rem 0.625rem 369 | 370 | 371 | #example-curl 372 | position: relative 373 | overflow: hidden 374 | 375 | 376 | .demo6 377 | cursor: pointer 378 | font-family: Futura, "Trebuchet MS", Arial, sans-serif 379 | background-color: #ff2f55 380 | display: inline-block 381 | font-weight: bold 382 | text-transform: uppercase 383 | padding: 2rem 384 | margin-bottom: 1rem 385 | 386 | p 387 | font-size: 5rem !important 388 | line-height: 1 !important 389 | font-weight: bold 390 | text-transform: uppercase 391 | transform: rotate(-5deg) 392 | text-align: center 393 | letter-spacing: -5px 394 | opacity: .25 395 | 396 | 397 | #features 398 | margin-bottom: 2rem 399 | 400 | ul 401 | font-size: 1.2rem 402 | text-align: center 403 | 404 | > li 405 | display: inline-block 406 | margin-right: 0 0.4rem 407 | font-size: 1.3rem 408 | 409 | &::before 410 | content: '•' 411 | margin-right: 0.5rem 412 | p 413 | font-size: 1rem 414 | 415 | #usage p 416 | line-height: 1.8 417 | 418 | 419 | #caveats 420 | font-size: 1rem 421 | ul 422 | margin: 0 auto 423 | 424 | li 425 | margin-bottom: 2rem 426 | 427 | span 428 | font-style: italic 429 | 430 | code 431 | font-style: normal 432 | 433 | 434 | @keyframes swivel 435 | 0% 436 | transform: rotate3d(0, 1, 0, 20deg) 437 | 438 | 100% 439 | transform: rotate3d(0, 1, 0, -20deg) 440 | 441 | 442 | @keyframes colors 443 | 0% 444 | color: #eee 445 | border-color: #eee 446 | 447 | 25% 448 | color: #ff5d2a 449 | border-color: #ff5d2a 450 | 451 | 50% 452 | color: #2effc4 453 | border-color: #2effc4 454 | 455 | 75% 456 | color: #ff5094 457 | border-color: #ff5094 458 | 459 | 100% 460 | color: #111 461 | border-color: #111 462 | 463 | 464 | 465 | @media only screen and (max-width: 970px), only screen and (max-device-width : 480px) 466 | .menu 467 | transform: translate3d(-200px, 0, 0) 468 | 469 | 470 | .fold-me 471 | transform: translate3d(200px, 0, 0) 472 | 473 | 474 | .rotation, .demo1 475 | animation: none !important 476 | 477 | 478 | header .rotation:hover .demo1 479 | color: #eee !important 480 | border-color: #eee !important 481 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | oriDomi - Fold up the DOM like paper - origami for the web 9 | 10 | 11 | 12 | 13 | 14 | 15 | 33 | 34 | 35 |

fold me on Github

36 |
37 | 38 |
39 |
40 |
41 |

Hello.

42 |

my name is oriDomi.

43 |
44 |
45 | 46 |
47 |

Fold up the DOM like paper.

48 |
49 |

50 | by 51 | Dan Motzenbecker, 52 | @dcmotz 53 |

54 |

oridomi.js / oridomi.min.js

55 |

56 |

Annotated source

57 |

Github repository

58 | 59 |
60 | 61 | 62 |
63 |
64 |

Features

65 |
    66 |
  • zero dependencies
  • 67 |
  • less than 15k
  • 68 |
  • optional jQuery support
  • 69 |
  • works on iOS
  • 70 |
  • built in touch handlers with callbacks
  • 71 |
72 |
73 |
74 | 75 | 76 |
77 |

Examples

78 |
(touch or drag to fold)
79 | 80 | 146 |
147 | 148 |
149 |
150 |

Usage

151 | 152 |

oriDomi works with or without a DOM library like jQuery.

153 | 154 |

First, initialize your target element with oriDomi using either jQuery:

155 | 156 |
157 | var $domi = $('.my-div').oriDomi();
158 | 
159 | 160 |

or using the standard DOM API:

161 | 162 |
163 | var domi = new OriDomi(document.getElementsByClassName('my-div')[0]);
164 | 
165 | 166 |

You can pass a number of options when initializing oriDomi on an element.

167 | 168 |

Options can include the number of horizontal and vertical panels, speed, perspective distance, shading method, 169 | as well as a few others.

170 | 171 |

For example:

172 | 173 |
174 | var $domi = $('.my-div').oriDomi({ vPanels: 3, hPanels: 10,
175 |     perspective: 200, speed: 500, shading: false });
176 | 
177 | 178 |

Once oriDomi is initialized on an element, you can call methods like so:

179 | 180 |
181 | $domi.oriDomi('accordion', -30, 'right');
182 | 
183 | 184 |

The first argument is the method to be called, the second is the angle to rotate by, and the third, optional 185 | argument is the anchor from which to transform (left, right, top, bottom).
Left is default.

186 | 187 |

Alernatively, you can use this syntax style when using jQuery:

188 | 189 |
190 | $domi.oriDomi().foldUp();
191 | 
192 | 193 |

You can also pass an options object 194 | literal as another argument, which can include a callback function to run when the animation completes.

195 | 196 |

Methods include accordion, reveal, curl, collapse, ramp, foldUp, unfold and reset.

197 | 198 |

Keep in mind, you can pass shorthand anchor names such as 199 | 'l', 'r', 't', 'b' or 200 | 1, 2, 3, 4.

201 | 202 |
203 | $domi.oriDomi('reveal', 44, 1,
204 |     { callback: function(){ alert('oriDomi reveal finished!') } });
205 | 
206 |

For a detailed look, read through the annotated source.

207 | 208 |
209 |
210 | 211 |
212 |
213 |

Caveats

214 |
    215 |
  • oriDomi only works in modern browsers that support CSS 3D transforms
    216 | If a browser doesn’t support oriDomi, the DOM won’t be touched.
  • 217 |
  • oriDomi works best in WebKit browsers.
    218 | Firefox is supported, but antialiasing doesn’t work well yet. 219 | You can force antialiasing in Firefox with the forceAntialiasing: true option. 220 |
  • 221 |
  • If you’re targeting an element that has dimensions defined by media it contains (e.g. an image), 222 | be sure to wait until the image is loaded before invoking oriDomi.
    223 | oriDomi works best when you define a width and height on the target element. 224 |
  • 225 |
226 |
227 |
228 | 229 |
230 |
231 |

Final Thoughts

232 |

oriDomi is new, so it likely has some bugs.

233 |

If you have an idea or a bugfix, please contribute to the Github repo.

234 |

If you enjoy oriDomi, check out my iPhone app ChainCal.

235 |

Or, follow me on twitter.

236 |

The DOM is your oyster.

237 |
238 |
239 | 240 | 241 | 242 | 252 | 253 | 254 | -------------------------------------------------------------------------------- /demo/demo.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | ::-moz-selection { 6 | background: #444; 7 | color: #fff; 8 | text-shadow: none; 9 | } 10 | ::selection { 11 | background: #444; 12 | color: #fff; 13 | text-shadow: none; 14 | } 15 | a { 16 | color: #333; 17 | } 18 | html { 19 | font-size: 100%; 20 | } 21 | body { 22 | background-color: #eee; 23 | color: #333; 24 | margin: 0 auto; 25 | font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, Georgia, Times, FreeSerif, serif; 26 | text-rendering: optimizeLegibility; 27 | color: #444; 28 | } 29 | h1, 30 | h2, 31 | h3, 32 | h4 { 33 | -webkit-font-smoothing: antialiased; 34 | font-smoothing: antialiased; 35 | } 36 | h2 { 37 | text-align: center; 38 | margin-bottom: 1rem; 39 | font-size: 1.7rem; 40 | letter-spacing: -0.1rem; 41 | } 42 | h5 { 43 | text-align: center; 44 | font-weight: normal; 45 | font-size: 1.1rem; 46 | font-style: italic; 47 | } 48 | header { 49 | background-color: #444; 50 | border-bottom: 1px #333 solid; 51 | border-top: 1px #333 solid; 52 | padding: 1rem; 53 | padding-bottom: 0; 54 | -webkit-perspective: 62.5rem; 55 | -moz-perspective: 62.5rem; 56 | -ms-perspective: 62.5rem; 57 | perspective: 62.5rem; 58 | text-align: center; 59 | margin-bottom: 0.625rem; 60 | overflow: hidden; 61 | } 62 | header .rotation { 63 | -webkit-animation: swivel 12s ease-out; 64 | -moz-animation: swivel 12s ease-out; 65 | -o-animation: swivel 12s ease-out; 66 | -ms-animation: swivel 12s ease-out; 67 | animation: swivel 12s ease-out; 68 | -webkit-animation-direction: alternate; 69 | -moz-animation-direction: alternate; 70 | -o-animation-direction: alternate; 71 | -ms-animation-direction: alternate; 72 | animation-direction: alternate; 73 | -webkit-animation-iteration-count: infinite; 74 | -moz-animation-iteration-count: infinite; 75 | -o-animation-iteration-count: infinite; 76 | -ms-animation-iteration-count: infinite; 77 | animation-iteration-count: infinite; 78 | -webkit-transform-style: preserve-3d; 79 | -moz-transform-style: preserve-3d; 80 | -o-transform-style: preserve-3d; 81 | -ms-transform-style: preserve-3d; 82 | transform-style: preserve-3d; 83 | } 84 | header .rotation:hover .demo1 { 85 | color: #3fffed !important; 86 | border-color: #3fffed !important; 87 | } 88 | header > h2 { 89 | display: inline-block; 90 | font-size: 1.55rem; 91 | background-color: #333; 92 | padding: 0.5rem; 93 | padding-bottom: 0.3rem; 94 | } 95 | header > h2 > a { 96 | -webkit-transition: color 0.3s; 97 | -moz-transition: color 0.3s; 98 | -o-transition: color 0.3s; 99 | -ms-transition: color 0.3s; 100 | transition: color 0.3s; 101 | color: #ddd; 102 | } 103 | header > h2 > a:hover { 104 | color: #3fffed; 105 | } 106 | header > h3 { 107 | display: inline-block; 108 | font-size: 1rem; 109 | } 110 | .menu { 111 | left: 0.625rem; 112 | width: 7.5rem; 113 | } 114 | .menu ul { 115 | background-color: #ddd; 116 | padding: 0.625rem; 117 | list-style: none; 118 | -webkit-border-radius: 0 0 5px 5px; 119 | border-radius: 0 0 5px 5px; 120 | } 121 | .menu ul li { 122 | text-align: left; 123 | } 124 | .menu ul li a { 125 | display: block; 126 | text-decoration: none; 127 | color: #666; 128 | -webkit-transition: all 0.3s; 129 | -moz-transition: all 0.3s; 130 | -o-transition: all 0.3s; 131 | -ms-transition: all 0.3s; 132 | transition: all 0.3s; 133 | border-bottom: 1px transparent dotted; 134 | } 135 | .menu ul li a:hover { 136 | color: #333; 137 | border-color: #aaa; 138 | } 139 | .menu ul li ul { 140 | padding: 0; 141 | padding-left: 1rem; 142 | font-size: 0.7rem; 143 | line-height: 1; 144 | } 145 | .fold-me, 146 | .menu { 147 | -webkit-transition: all 0.3s; 148 | -moz-transition: all 0.3s; 149 | -o-transition: all 0.3s; 150 | -ms-transition: all 0.3s; 151 | transition: all 0.3s; 152 | position: fixed; 153 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; 154 | top: 0; 155 | text-align: left; 156 | font-weight: bold; 157 | text-shadow: 0 1px 0 rgba(255,255,255,0.7); 158 | text-decoration: none; 159 | color: #666; 160 | font-size: 0.85rem; 161 | z-index: 100; 162 | } 163 | .fold-me { 164 | cursor: pointer; 165 | line-height: 1.5; 166 | right: 0.625rem; 167 | } 168 | .fold-me p { 169 | padding: 0.625rem; 170 | padding-right: 2.5rem; 171 | width: 1.875rem; 172 | background-color: #ddd; 173 | -webkit-border-radius: 0 0 5px 5px; 174 | border-radius: 0 0 5px 5px; 175 | } 176 | #tagline { 177 | margin-bottom: 1.875rem; 178 | text-align: center; 179 | position: relative; 180 | margin-top: -3.125rem; 181 | letter-spacing: -1px; 182 | z-index: -1; 183 | } 184 | #tagline h1 { 185 | background-color: #fff; 186 | color: #444; 187 | display: inline-block; 188 | padding: 0.5rem; 189 | padding-bottom: 0.3rem; 190 | font-size: 2rem; 191 | } 192 | #author { 193 | text-align: center; 194 | font-style: italic; 195 | font-size: 1.1rem; 196 | line-height: 3; 197 | color: #fff; 198 | margin-top: -1.875rem; 199 | margin-bottom: 0.125rem; 200 | } 201 | #author > a { 202 | color: #fff; 203 | text-decoration: none; 204 | } 205 | #author > a:hover { 206 | text-decoration: underline; 207 | } 208 | ul { 209 | list-style: disc; 210 | list-style-position: inside; 211 | } 212 | ul > li { 213 | text-align: center; 214 | line-height: 2; 215 | } 216 | .hidden { 217 | display: none; 218 | } 219 | section { 220 | margin-bottom: 3.125rem; 221 | float: left; 222 | -webkit-box-sizing: border-box; 223 | -moz-box-sizing: border-box; 224 | box-sizing: border-box; 225 | width: 100%; 226 | } 227 | section > div { 228 | margin: 0 auto; 229 | max-width: 43.75rem; 230 | padding: 0 1.5rem; 231 | text-shadow: 0 1px 0 #fff; 232 | } 233 | section p { 234 | text-align: center; 235 | margin-bottom: 1.25rem; 236 | } 237 | pre { 238 | background-color: #333; 239 | color: #fff; 240 | -webkit-border-radius: 5px; 241 | border-radius: 5px; 242 | text-shadow: 0 -1px 0 rgba(0,0,0,0.5); 243 | font-size: 1rem; 244 | margin: 0 auto; 245 | padding: 0.625rem; 246 | margin-bottom: 1.25rem; 247 | overflow: auto; 248 | } 249 | .demo1 { 250 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; 251 | width: 21.875rem; 252 | margin: 0 auto; 253 | text-align: center; 254 | background-color: #444; 255 | color: #fff; 256 | padding: 0.625rem 0; 257 | border: 1.25rem #eee solid; 258 | text-shadow: 0 -1px 0 rgba(0,0,0,0.1); 259 | margin-bottom: 2.5rem; 260 | background-image: url("./images/1.jpg"); 261 | -webkit-background-size: 21.875rem; 262 | -moz-background-size: 21.875rem; 263 | background-size: 21.875rem; 264 | -webkit-transition: color 0.5s, border-color 0.5s; 265 | -moz-transition: color 0.5s, border-color 0.5s; 266 | -o-transition: color 0.5s, border-color 0.5s; 267 | -ms-transition: color 0.5s, border-color 0.5s; 268 | transition: color 0.5s, border-color 0.5s; 269 | overflow: hidden; 270 | } 271 | .demo1 > h1 { 272 | text-transform: uppercase; 273 | letter-spacing: -0.125rem; 274 | font-size: 4.375rem; 275 | line-height: 2; 276 | } 277 | .demo1 > h4 { 278 | font-size: 1.875rem; 279 | line-height: 0; 280 | margin-bottom: 3.75rem; 281 | } 282 | h3 { 283 | text-align: center; 284 | margin-bottom: 1.25rem; 285 | } 286 | h3 > a { 287 | text-decoration: none; 288 | color: #eee; 289 | background-color: #666; 290 | padding: 0.5rem; 291 | padding-bottom: 0.3rem; 292 | -webkit-transition: all 0.3s; 293 | -moz-transition: all 0.3s; 294 | -o-transition: all 0.3s; 295 | -ms-transition: all 0.3s; 296 | transition: all 0.3s; 297 | } 298 | h3 > a:hover { 299 | color: #666; 300 | background-color: #fff; 301 | } 302 | #examples > h2 { 303 | margin-bottom: 1rem; 304 | } 305 | #examples > h5 { 306 | margin-bottom: 1rem; 307 | } 308 | #examples > ul { 309 | list-style: none; 310 | } 311 | #examples > ul > li { 312 | display: block; 313 | padding-bottom: 1rem; 314 | } 315 | #examples > ul > li pre { 316 | max-width: 30.625rem; 317 | margin-top: 2rem; 318 | } 319 | #examples > ul > li:nth-child(even) > article { 320 | text-shadow: 0 1px 0 #fff; 321 | } 322 | #examples > ul > li:nth-child(odd) { 323 | background-color: #444; 324 | color: #fff; 325 | } 326 | #examples > ul > li:nth-child(odd) > article { 327 | padding: 0 1.5rem; 328 | text-shadow: 0 -1px 0 #000; 329 | } 330 | #examples > ul > li article { 331 | margin-bottom: 1.5rem; 332 | } 333 | #examples > ul > li h4 { 334 | font-size: 1.5rem; 335 | } 336 | #examples > ul > li h5 { 337 | font-size: 1.1rem; 338 | line-height: 1; 339 | color: #ccc; 340 | margin-bottom: 0.6rem; 341 | } 342 | #examples > ul > li p { 343 | font-size: 1rem; 344 | line-height: 1.4; 345 | } 346 | .demo { 347 | margin: 0 auto; 348 | } 349 | .demo2 { 350 | font-family: "Abril Fatface", "Hoefler Text", Constantia, Palatino, Georgia, serif; 351 | font-size: 4.5rem; 352 | width: 25rem; 353 | height: 10rem; 354 | text-align: center; 355 | line-height: 1; 356 | color: #ff676d; 357 | background-color: #6ac1ff; 358 | padding: 2.5rem 0; 359 | } 360 | .demo3 { 361 | font-family: Lato, "Helvetica Neue", Arial, Helvetica, sans-serif; 362 | text-transform: uppercase; 363 | font-size: 6.25rem; 364 | background-color: #444; 365 | color: #fff; 366 | width: 26.875rem; 367 | padding: 0.625rem 0.9375rem; 368 | background-image: url("./images/3.jpeg"); 369 | -webkit-background-size: 31.25rem; 370 | -moz-background-size: 31.25rem; 371 | background-size: 31.25rem; 372 | text-align: center; 373 | } 374 | .demo4 { 375 | width: 18.75rem; 376 | height: 12.5rem; 377 | background-image: url("./images/4.gif"); 378 | } 379 | .demo5 { 380 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; 381 | font-weight: 900; 382 | font-style: italic; 383 | text-transform: uppercase; 384 | font-size: 5rem; 385 | width: 25rem; 386 | line-height: 1; 387 | text-align: center; 388 | background-color: #444; 389 | color: #e2bb7c; 390 | border: 0.9375rem solid #e2bb7c; 391 | letter-spacing: -0.3125rem; 392 | padding: 3.125rem 0.625rem; 393 | } 394 | #example-curl { 395 | position: relative; 396 | overflow: hidden; 397 | } 398 | .demo6 { 399 | cursor: pointer; 400 | font-family: Futura, "Trebuchet MS", Arial, sans-serif; 401 | background-color: #ff2f55; 402 | display: inline-block; 403 | font-weight: bold; 404 | text-transform: uppercase; 405 | padding: 2rem; 406 | margin-bottom: 1rem; 407 | } 408 | .demo6 p { 409 | font-size: 5rem !important; 410 | line-height: 1 !important; 411 | font-weight: bold; 412 | text-transform: uppercase; 413 | -webkit-transform: rotate(-5deg); 414 | -moz-transform: rotate(-5deg); 415 | -o-transform: rotate(-5deg); 416 | -ms-transform: rotate(-5deg); 417 | transform: rotate(-5deg); 418 | text-align: center; 419 | letter-spacing: -5px; 420 | opacity: 0.25; 421 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=25); 422 | filter: alpha(opacity=25); 423 | } 424 | #features { 425 | margin-bottom: 2rem; 426 | } 427 | #features ul { 428 | font-size: 1.2rem; 429 | text-align: center; 430 | } 431 | #features ul > li { 432 | display: inline-block; 433 | margin-right: 0 0.4rem; 434 | font-size: 1.3rem; 435 | } 436 | #features ul > li::before { 437 | content: '•'; 438 | margin-right: 0.5rem; 439 | } 440 | p { 441 | font-size: 1rem; 442 | } 443 | #usage p { 444 | line-height: 1.8; 445 | } 446 | #caveats { 447 | font-size: 1rem; 448 | } 449 | #caveats ul { 450 | margin: 0 auto; 451 | } 452 | #caveats ul li { 453 | margin-bottom: 2rem; 454 | } 455 | #caveats ul li span { 456 | font-style: italic; 457 | } 458 | #caveats ul li span code { 459 | font-style: normal; 460 | } 461 | @media only screen and (max-width: 970px), only screen and (max-device-width : 480px) { 462 | .menu { 463 | -webkit-transform: translate3d(-200px, 0, 0); 464 | -moz-transform: translate3d(-200px, 0, 0); 465 | -o-transform: translate3d(-200px, 0, 0); 466 | -ms-transform: translate3d(-200px, 0, 0); 467 | transform: translate3d(-200px, 0, 0); 468 | } 469 | .fold-me { 470 | -webkit-transform: translate3d(200px, 0, 0); 471 | -moz-transform: translate3d(200px, 0, 0); 472 | -o-transform: translate3d(200px, 0, 0); 473 | -ms-transform: translate3d(200px, 0, 0); 474 | transform: translate3d(200px, 0, 0); 475 | } 476 | .rotation, 477 | .demo1 { 478 | -webkit-animation: none !important; 479 | -moz-animation: none !important; 480 | -o-animation: none !important; 481 | -ms-animation: none !important; 482 | animation: none !important; 483 | } 484 | header .rotation:hover .demo1 { 485 | color: #eee !important; 486 | border-color: #eee !important; 487 | } 488 | } 489 | @-moz-keyframes swivel { 490 | 0% { 491 | -webkit-transform: rotate3d(0, 1, 0, 20deg); 492 | -moz-transform: rotate3d(0, 1, 0, 20deg); 493 | -o-transform: rotate3d(0, 1, 0, 20deg); 494 | -ms-transform: rotate3d(0, 1, 0, 20deg); 495 | transform: rotate3d(0, 1, 0, 20deg); 496 | } 497 | 498 | 100% { 499 | -webkit-transform: rotate3d(0, 1, 0, -20deg); 500 | -moz-transform: rotate3d(0, 1, 0, -20deg); 501 | -o-transform: rotate3d(0, 1, 0, -20deg); 502 | -ms-transform: rotate3d(0, 1, 0, -20deg); 503 | transform: rotate3d(0, 1, 0, -20deg); 504 | } 505 | } 506 | @-webkit-keyframes swivel { 507 | 0% { 508 | -webkit-transform: rotate3d(0, 1, 0, 20deg); 509 | -moz-transform: rotate3d(0, 1, 0, 20deg); 510 | -o-transform: rotate3d(0, 1, 0, 20deg); 511 | -ms-transform: rotate3d(0, 1, 0, 20deg); 512 | transform: rotate3d(0, 1, 0, 20deg); 513 | } 514 | 515 | 100% { 516 | -webkit-transform: rotate3d(0, 1, 0, -20deg); 517 | -moz-transform: rotate3d(0, 1, 0, -20deg); 518 | -o-transform: rotate3d(0, 1, 0, -20deg); 519 | -ms-transform: rotate3d(0, 1, 0, -20deg); 520 | transform: rotate3d(0, 1, 0, -20deg); 521 | } 522 | } 523 | @-o-keyframes swivel { 524 | 0% { 525 | -webkit-transform: rotate3d(0, 1, 0, 20deg); 526 | -moz-transform: rotate3d(0, 1, 0, 20deg); 527 | -o-transform: rotate3d(0, 1, 0, 20deg); 528 | -ms-transform: rotate3d(0, 1, 0, 20deg); 529 | transform: rotate3d(0, 1, 0, 20deg); 530 | } 531 | 532 | 100% { 533 | -webkit-transform: rotate3d(0, 1, 0, -20deg); 534 | -moz-transform: rotate3d(0, 1, 0, -20deg); 535 | -o-transform: rotate3d(0, 1, 0, -20deg); 536 | -ms-transform: rotate3d(0, 1, 0, -20deg); 537 | transform: rotate3d(0, 1, 0, -20deg); 538 | } 539 | } 540 | @-ms-keyframes swivel { 541 | 0% { 542 | -webkit-transform: rotate3d(0, 1, 0, 20deg); 543 | -moz-transform: rotate3d(0, 1, 0, 20deg); 544 | -o-transform: rotate3d(0, 1, 0, 20deg); 545 | -ms-transform: rotate3d(0, 1, 0, 20deg); 546 | transform: rotate3d(0, 1, 0, 20deg); 547 | } 548 | 549 | 100% { 550 | -webkit-transform: rotate3d(0, 1, 0, -20deg); 551 | -moz-transform: rotate3d(0, 1, 0, -20deg); 552 | -o-transform: rotate3d(0, 1, 0, -20deg); 553 | -ms-transform: rotate3d(0, 1, 0, -20deg); 554 | transform: rotate3d(0, 1, 0, -20deg); 555 | } 556 | } 557 | @keyframes swivel { 558 | 0% { 559 | -webkit-transform: rotate3d(0, 1, 0, 20deg); 560 | -moz-transform: rotate3d(0, 1, 0, 20deg); 561 | -o-transform: rotate3d(0, 1, 0, 20deg); 562 | -ms-transform: rotate3d(0, 1, 0, 20deg); 563 | transform: rotate3d(0, 1, 0, 20deg); 564 | } 565 | 566 | 100% { 567 | -webkit-transform: rotate3d(0, 1, 0, -20deg); 568 | -moz-transform: rotate3d(0, 1, 0, -20deg); 569 | -o-transform: rotate3d(0, 1, 0, -20deg); 570 | -ms-transform: rotate3d(0, 1, 0, -20deg); 571 | transform: rotate3d(0, 1, 0, -20deg); 572 | } 573 | } 574 | @-moz-keyframes colors { 575 | 0% { 576 | color: #eee; 577 | border-color: #eee; 578 | } 579 | 580 | 25% { 581 | color: #ff5d2a; 582 | border-color: #ff5d2a; 583 | } 584 | 585 | 50% { 586 | color: #2effc4; 587 | border-color: #2effc4; 588 | } 589 | 590 | 75% { 591 | color: #ff5094; 592 | border-color: #ff5094; 593 | } 594 | 595 | 100% { 596 | color: #111; 597 | border-color: #111; 598 | } 599 | } 600 | @-webkit-keyframes colors { 601 | 0% { 602 | color: #eee; 603 | border-color: #eee; 604 | } 605 | 606 | 25% { 607 | color: #ff5d2a; 608 | border-color: #ff5d2a; 609 | } 610 | 611 | 50% { 612 | color: #2effc4; 613 | border-color: #2effc4; 614 | } 615 | 616 | 75% { 617 | color: #ff5094; 618 | border-color: #ff5094; 619 | } 620 | 621 | 100% { 622 | color: #111; 623 | border-color: #111; 624 | } 625 | } 626 | @-o-keyframes colors { 627 | 0% { 628 | color: #eee; 629 | border-color: #eee; 630 | } 631 | 632 | 25% { 633 | color: #ff5d2a; 634 | border-color: #ff5d2a; 635 | } 636 | 637 | 50% { 638 | color: #2effc4; 639 | border-color: #2effc4; 640 | } 641 | 642 | 75% { 643 | color: #ff5094; 644 | border-color: #ff5094; 645 | } 646 | 647 | 100% { 648 | color: #111; 649 | border-color: #111; 650 | } 651 | } 652 | @-ms-keyframes colors { 653 | 0% { 654 | color: #eee; 655 | border-color: #eee; 656 | } 657 | 658 | 25% { 659 | color: #ff5d2a; 660 | border-color: #ff5d2a; 661 | } 662 | 663 | 50% { 664 | color: #2effc4; 665 | border-color: #2effc4; 666 | } 667 | 668 | 75% { 669 | color: #ff5094; 670 | border-color: #ff5094; 671 | } 672 | 673 | 100% { 674 | color: #111; 675 | border-color: #111; 676 | } 677 | } 678 | @keyframes colors { 679 | 0% { 680 | color: #eee; 681 | border-color: #eee; 682 | } 683 | 684 | 25% { 685 | color: #ff5d2a; 686 | border-color: #ff5d2a; 687 | } 688 | 689 | 50% { 690 | color: #2effc4; 691 | border-color: #2effc4; 692 | } 693 | 694 | 75% { 695 | color: #ff5094; 696 | border-color: #ff5094; 697 | } 698 | 699 | 100% { 700 | color: #111; 701 | border-color: #111; 702 | } 703 | } 704 | -------------------------------------------------------------------------------- /oridomi.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";var $,OriDomi,css,defaults,devMode,extendObj,instances,key,noOp,oriDomiSupport,prefixList,root,testEl,testProp,value,_ref,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}};root=this;instances=[];$=root.$||false;devMode=false;oriDomiSupport=true;testEl=document.createElement("div");prefixList=["Webkit","Moz","O","ms","Khtml"];css={transform:"transform",origin:"transformOrigin",transformStyle:"transformStyle",transitionProp:"transitionProperty",transitionDuration:"transitionDuration",transitionEasing:"transitionTimingFunction",perspective:"perspective",backface:"backfaceVisibility"};testProp=function(prop){var capProp,prefix,_i,_len;capProp=prop.charAt(0).toUpperCase()+prop.slice(1);for(_i=0,_len=prefixList.length;_i<_len;_i++){prefix=prefixList[_i];if(testEl.style[prefix+capProp]!=null){return prefix+capProp}}if(testEl.style[prop]!=null){return prop}return false};for(key in css){value=css[key];css[key]=testProp(value);if(!css[key]){if(devMode){console.warn("oriDomi: Browser does not support oriDomi")}oriDomiSupport=false;break}}css.gradientProp=function(){var hyphenated,prefix,_i,_len;for(_i=0,_len=prefixList.length;_i<_len;_i++){prefix=prefixList[_i];hyphenated="-"+prefix.toLowerCase()+"-linear-gradient";testEl.style.backgroundImage=""+hyphenated+"(left, #000, #fff)";if(testEl.style.backgroundImage.indexOf("gradient")!==-1){return hyphenated}}return"linear-gradient"}();_ref=function(){var grabValue,plainGrab,prefix,_i,_len;for(_i=0,_len=prefixList.length;_i<_len;_i++){prefix=prefixList[_i];plainGrab="grab";testEl.style.cursor=grabValue="-"+prefix.toLowerCase()+"-"+plainGrab;if(testEl.style.cursor===grabValue){return[grabValue,"-"+prefix.toLowerCase()+"-grabbing"]}}testEl.style.cursor=plainGrab;if(testEl.style.cursor===plainGrab){return[plainGrab,"grabbing"]}else{return["move","move"]}}(),css.grab=_ref[0],css.grabbing=_ref[1];css.transformProp=function(){var prefix;prefix=css.transform.match(/(\w+)Transform/i);if(prefix){return"-"+prefix[1].toLowerCase()+"-transform"}else{return"transform"}}();css.transitionEnd=function(){switch(css.transitionProp){case"transitionProperty":return"transitionEnd";case"WebkitTransitionProperty":return"webkitTransitionEnd";case"MozTransitionProperty":return"transitionend";case"OTransitionProperty":return"oTransitionEnd";case"MSTransitionProperty":return"msTransitionEnd"}}();extendObj=function(target,source){var prop;if(source!==Object(source)){if(devMode){console.warn("oriDomi: Must pass an object to extend with")}return target}if(target!==Object(target)){target={}}for(prop in source){if(!(target[prop]!=null)){target[prop]=source[prop]}}return target};noOp=function(){};defaults={vPanels:3,hPanels:3,perspective:1e3,shading:"hard",speed:700,oriDomiClass:"oridomi",shadingIntensity:1,easingMethod:"",showOnStart:false,forceAntialiasing:false,touchEnabled:true,touchSensitivity:.25,touchStartCallback:noOp,touchMoveCallback:noOp,touchEndCallback:noOp};OriDomi=function(){function OriDomi(el,options){var anchor,bleed,bottomShader,content,contentHolder,eString,eventPair,eventPairs,hMask,hPanel,i,leftShader,metric,mouseLeaveSupport,panel,rightShader,shader,stage,topShader,vMask,vPanel,xMetrics,xOffset,yMetrics,yOffset,_i,_j,_k,_l,_len,_len1,_len2,_len3,_len4,_len5,_len6,_len7,_len8,_m,_n,_o,_p,_q,_r,_ref1,_ref2,_ref3,_ref4,_ref5,_ref6,_ref7,_ref8,_ref9,_s;this.el=el;this._onMouseOut=__bind(this._onMouseOut,this);this._onTouchLeave=__bind(this._onTouchLeave,this);this._onTouchEnd=__bind(this._onTouchEnd,this);this._onTouchMove=__bind(this._onTouchMove,this);this._onTouchStart=__bind(this._onTouchStart,this);if(devMode){console.time("oridomiConstruction")}if(!oriDomiSupport){return this.el}if(!(this instanceof OriDomi)){return new oriDomi(this.el,this.settings)}this.settings=extendObj(options,defaults);if(!this.el||this.el.nodeType!==1){if(devMode){console.warn("oriDomi: First argument must be a DOM element")}return}this.cleanEl=this.el.cloneNode(true);this.cleanEl.style.margin="0";this.cleanEl.style.position="absolute";this.cleanEl.style[css.transform]="translate3d(-9999px, 0, 0)";_ref1=this.settings,this.shading=_ref1.shading,this.shadingIntensity=_ref1.shadingIntensity,this.vPanels=_ref1.vPanels,this.hPanels=_ref1.hPanels;this._elStyle=root.getComputedStyle(this.el);this.displayStyle=this._elStyle.display;if(this.displayStyle==="none"){this.displayStyle="block"}xMetrics=["width","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth"];yMetrics=["height","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth"];this.width=0;this.height=0;for(_i=0,_len=xMetrics.length;_i<_len;_i++){metric=xMetrics[_i];this.width+=this._getMetric(metric)}for(_j=0,_len1=yMetrics.length;_j<_len1;_j++){metric=yMetrics[_j];this.height+=this._getMetric(metric)}this.panelWidth=this.width/this.vPanels;this.panelHeight=this.height/this.hPanels;this.lastAngle=0;this.isFoldedUp=false;this.isFrozen=false;this.anchors=["left","right","top","bottom"];this.lastAnchor=this.anchors[0];this.panels={};this.stages={};stage=document.createElement("div");stage.style.width=this.width+"px";stage.style.height=this.height+"px";stage.style.display="none";stage.style.position="absolute";stage.style.padding="0";stage.style.margin="0";stage.style[css.perspective]=this.settings.perspective+"px";stage.style[css.transformStyle]="preserve-3d";_ref2=this.anchors;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){anchor=_ref2[_k];this.panels[anchor]=[];this.stages[anchor]=stage.cloneNode(false);this.stages[anchor].className="oridomi-stage-"+anchor}if(this.shading){this.shaders={};_ref3=this.anchors;for(_l=0,_len3=_ref3.length;_l<_len3;_l++){anchor=_ref3[_l];this.shaders[anchor]={};if(anchor==="left"||anchor==="right"){this.shaders[anchor].left=[];this.shaders[anchor].right=[]}else{this.shaders[anchor].top=[];this.shaders[anchor].bottom=[]}}shader=document.createElement("div");shader.style[css.transitionProp]="opacity";shader.style[css.transitionDuration]=this.settings.speed+"ms";shader.style[css.transitionEasing]=this.settings.easingMethod;shader.style.position="absolute";shader.style.width="100%";shader.style.height="100%";shader.style.opacity="0";shader.style.top="0";shader.style.left="0";shader.style.pointerEvents="none"}contentHolder=this.el.cloneNode(true);contentHolder.classList.add("oridomi-content");contentHolder.style.margin="0";contentHolder.style.position="relative";contentHolder.style.float="none";hMask=document.createElement("div");hMask.className="oridomi-mask-h";hMask.style.position="absolute";hMask.style.overflow="hidden";hMask.style.width="100%";hMask.style.height="100%";hMask.style[css.transform]="translate3d(0, 0, 0)";hMask.appendChild(contentHolder);if(this.shading){topShader=shader.cloneNode(false);topShader.className="oridomi-shader-top";topShader.style.background=this._getShaderGradient("top");bottomShader=shader.cloneNode(false);bottomShader.className="oridomi-shader-bottom";bottomShader.style.background=this._getShaderGradient("bottom");hMask.appendChild(topShader);hMask.appendChild(bottomShader)}bleed=1.5;hPanel=document.createElement("div");hPanel.className="oridomi-panel-h";hPanel.style.width="100%";hPanel.style.height=this.panelHeight+bleed+"px";hPanel.style.padding="0";hPanel.style.position="relative";hPanel.style[css.transitionProp]=css.transformProp;hPanel.style[css.transitionDuration]=this.settings.speed+"ms";hPanel.style[css.transitionEasing]=this.settings.easingMethod;hPanel.style[css.origin]="top";hPanel.style[css.transformStyle]="preserve-3d";hPanel.style[css.backface]="hidden";if(this.settings.forceAntialiasing){hPanel.style.outline="1px solid transparent"}hPanel.appendChild(hMask);_ref4=["top","bottom"];for(_m=0,_len4=_ref4.length;_m<_len4;_m++){anchor=_ref4[_m];for(i=_n=0,_ref5=this.hPanels;0<=_ref5?_n<_ref5:_n>_ref5;i=0<=_ref5?++_n:--_n){panel=hPanel.cloneNode(true);content=panel.getElementsByClassName("oridomi-content")[0];if(anchor==="top"){yOffset=-(i*this.panelHeight);if(i===0){panel.style.top="0"}else{panel.style.top=this.panelHeight+"px"}}else{panel.style[css.origin]="bottom";yOffset=-(this.hPanels*this.panelHeight-this.panelHeight*(i+1));if(i===0){panel.style.top=this.panelHeight*(this.vPanels-1)-bleed+"px"}else{panel.style.top=-this.panelHeight+"px"}}content.style.top=yOffset+"px";if(this.shading){this.shaders[anchor].top[i]=panel.getElementsByClassName("oridomi-shader-top")[0];this.shaders[anchor].bottom[i]=panel.getElementsByClassName("oridomi-shader-bottom")[0]}this.panels[anchor][i]=panel;if(i!==0){this.panels[anchor][i-1].appendChild(panel)}}this.stages[anchor].appendChild(this.panels[anchor][0])}vMask=hMask.cloneNode(true);vMask.className="oridomi-mask-v";if(this.shading){leftShader=vMask.getElementsByClassName("oridomi-shader-top")[0];leftShader.className="oridomi-shader-left";leftShader.style.background=this._getShaderGradient("left");rightShader=vMask.getElementsByClassName("oridomi-shader-bottom")[0];rightShader.className="oridomi-shader-right";rightShader.style.background=this._getShaderGradient("right")}vPanel=hPanel.cloneNode(false);vPanel.className="oridomi-panel-v";vPanel.style.width=this.panelWidth+bleed+"px";vPanel.style.height="100%";vPanel.style[css.origin]="left";vPanel.appendChild(vMask);_ref6=["left","right"];for(_o=0,_len5=_ref6.length;_o<_len5;_o++){anchor=_ref6[_o];for(i=_p=0,_ref7=this.vPanels;0<=_ref7?_p<_ref7:_p>_ref7;i=0<=_ref7?++_p:--_p){panel=vPanel.cloneNode(true);content=panel.getElementsByClassName("oridomi-content")[0];if(anchor==="left"){xOffset=-(i*this.panelWidth);if(i===0){panel.style.left="0"}else{panel.style.left=this.panelWidth+"px"}}else{panel.style[css.origin]="right";xOffset=-(this.vPanels*this.panelWidth-this.panelWidth*(i+1));if(i===0){panel.style.left=this.panelWidth*(this.vPanels-1)-1+"px"}else{panel.style.left=-this.panelWidth+"px"}}content.style.left=xOffset+"px";if(this.shading){this.shaders[anchor].left[i]=panel.getElementsByClassName("oridomi-shader-left")[0];this.shaders[anchor].right[i]=panel.getElementsByClassName("oridomi-shader-right")[0]}this.panels[anchor][i]=panel;if(i!==0){this.panels[anchor][i-1].appendChild(panel)}}this.stages[anchor].appendChild(this.panels[anchor][0])}this.el.classList.add(this.settings.oriDomiClass);this.el.style.padding="0";this.el.style.width=this.width+"px";this.el.style.height=this.height+"px";this.el.style.backgroundColor="transparent";this.el.style.backgroundImage="none";this.el.style.border="none";this.el.style.outline="none";this.stages.left.style.display="block";this.stageEl=document.createElement("div");eventPairs=[["TouchStart","MouseDown"],["TouchEnd","MouseUp"],["TouchMove","MouseMove"],["TouchLeave","MouseLeave"]];mouseLeaveSupport="onmouseleave"in window;for(_q=0,_len6=eventPairs.length;_q<_len6;_q++){eventPair=eventPairs[_q];for(_r=0,_len7=eventPair.length;_r<_len7;_r++){eString=eventPair[_r];if(!(eString==="TouchLeave"&&!mouseLeaveSupport)){this.stageEl.addEventListener(eString.toLowerCase(),this["_on"+eventPair[0]],false)}else{this.stageEl.addEventListener("mouseout",this["_onMouseOut"],false);break}}}if(this.settings.touchEnabled){this.enableTouch()}_ref8=this.anchors;for(_s=0,_len8=_ref8.length;_s<_len8;_s++){anchor=_ref8[_s];this.stageEl.appendChild(this.stages[anchor])}if(this.settings.showOnStart){this.el.style.display="block";this.el.style.visibility="visible"}this.el.innerHTML="";this.el.appendChild(this.cleanEl);this.el.appendChild(this.stageEl);_ref9=[0,0],this._xLast=_ref9[0],this._yLast=_ref9[1];this.lastOp={method:"accordion",options:{}};if($){this.$el=$(this.el)}instances.push(this);this._callback(this.settings);if(devMode){console.timeEnd("oridomiConstruction")}}OriDomi.prototype._callback=function(options){var onTransitionEnd,_this=this;if(typeof options.callback==="function"){onTransitionEnd=function(e){e.currentTarget.removeEventListener(css.transitionEnd,onTransitionEnd,false);return options.callback()};if(this.lastAngle===0){return options.callback()}else{return this.panels[this.lastAnchor][0].addEventListener(css.transitionEnd,onTransitionEnd,false)}}};OriDomi.prototype._getMetric=function(metric){return parseInt(this._elStyle[metric],10)};OriDomi.prototype._transform=function(angle,fracture){var axes,_ref1;switch(this.lastAnchor){case"left":axes=[0,1,0,angle];break;case"right":axes=[0,1,0,-angle];break;case"top":axes=[1,0,0,-angle];break;case"bottom":axes=[1,0,0,angle]}if(fracture){_ref1=[1,1,1],axes[0]=_ref1[0],axes[1]=_ref1[1],axes[2]=_ref1[2]}return"rotate3d("+axes[0]+", "+axes[1]+", "+axes[2]+", "+axes[3]+"deg)"};OriDomi.prototype._normalizeAngle=function(angle){angle=parseFloat(angle,10);if(isNaN(angle)){return 0}else if(angle>89){return 89}else if(angle<-89){return-89}else{return angle}};OriDomi.prototype._normalizeArgs=function(method,args){var anchor,angle,options,_this=this;if(this.isFrozen){this.unfreeze()}angle=this._normalizeAngle(args[0]);anchor=this._getLonghandAnchor(args[1]||this.lastAnchor);options=extendObj(args[2],this._methodDefaults[method]);this.lastOp={method:method,options:options,negative:angle<0};if(anchor!==this.lastAnchor||method==="foldUp"&&this.lastAngle!==0||this.isFoldedUp){this.reset(function(){_this._showStage(anchor);if(_this._touchEnabled){_this._setCursor()}return setTimeout(function(){if(method==="foldUp"){args.shift()}return _this[method].apply(_this,args)},0)});return false}else{this.lastAngle=angle;return[angle,anchor,options]}};OriDomi.prototype._setShader=function(i,anchor,angle){var a,abs,b,opacity;abs=Math.abs(angle);opacity=abs/90*this.shadingIntensity;if(this.shading==="hard"){opacity*=.15;if(this.lastAngle<0){angle=abs}else{angle=-abs}}else{opacity*=.4}switch(anchor){case"left":case"top":if(angle<0){a=opacity;b=0}else{a=0;b=opacity}break;case"right":case"bottom":if(angle<0){a=0;b=opacity}else{a=opacity;b=0}}if(anchor==="left"||anchor==="right"){this.shaders[anchor].left[i].style.opacity=a;return this.shaders[anchor].right[i].style.opacity=b}else{this.shaders[anchor].top[i].style.opacity=a;return this.shaders[anchor].bottom[i].style.opacity=b}};OriDomi.prototype._getShaderGradient=function(anchor){return""+css.gradientProp+"("+anchor+", rgba(0, 0, 0, .5) 0%, rgba(255, 255, 255, .35) 100%)"};OriDomi.prototype._showStage=function(anchor){if(anchor!==this.lastAnchor){this.stages[anchor].style.display="block";this.stages[this.lastAnchor].style.display="none";return this.lastAnchor=anchor}};OriDomi.prototype._getPanelType=function(anchor){if(anchor==="left"||anchor==="right"){return this.vPanels}else{return this.hPanels}};OriDomi.prototype._getLonghandAnchor=function(shorthand){switch(shorthand){case"left":case"l":case"4":case 4:return"left";case"right":case"r":case"2":case 2:return"right";case"top":case"t":case"1":case 1:return"top";case"bottom":case"b":case"3":case 3:return"bottom";default:return"left"}};OriDomi.prototype._setTweening=function(speed){var i,panel,shaderPair,_i,_len,_ref1;if(typeof speed==="boolean"){speed=speed?this.settings.speed+"ms":"0ms"}if(this.lastAnchor==="left"||this.lastAnchor==="right"){shaderPair=["left","right"]}else{shaderPair=["top","bottom"]}_ref1=this.panels[this.lastAnchor];for(i=_i=0,_len=_ref1.length;_i<_len;i=++_i){panel=_ref1[i];panel.style[css.transitionDuration]=speed;if(this.shading){this.shaders[this.lastAnchor][shaderPair[0]][i].style[css.transitionDuration]=speed;this.shaders[this.lastAnchor][shaderPair[1]][i].style[css.transitionDuration]=speed}}return null};OriDomi.prototype._setCursor=function(){if(this._touchEnabled){return this.stageEl.style.cursor=css.grab}else{return this.stageEl.style.cursor="default"}};OriDomi.prototype._methodDefaults={accordion:{sticky:false,stairs:false,fracture:false,twist:false},curl:{twist:false},ramp:{},foldUp:{}};OriDomi.prototype._onTouchStart=function(e){if(!this._touchEnabled){return}e.preventDefault();this._touchStarted=true;this.stageEl.style.cursor=css.grabbing;this._setTweening(false);this._touchAxis=this.lastAnchor==="left"||this.lastAnchor==="right"?"x":"y";this["_"+this._touchAxis+"Last"]=this.lastAngle;if(e.type==="mousedown"){this["_"+this._touchAxis+"1"]=e["page"+this._touchAxis.toUpperCase()]}else{this["_"+this._touchAxis+"1"]=e.targetTouches[0]["page"+this._touchAxis.toUpperCase()]}return this.settings.touchStartCallback(this["_"+this._touchAxis+"1"])};OriDomi.prototype._onTouchMove=function(e){var current,delta,distance;if(!(this._touchEnabled&&this._touchStarted)){return}e.preventDefault();if(e.type==="mousemove"){current=e["page"+this._touchAxis.toUpperCase()]}else{current=e.targetTouches[0]["page"+this._touchAxis.toUpperCase()]}distance=(current-this["_"+this._touchAxis+"1"])*this.settings.touchSensitivity;if(this.lastOp.negative){if(this.lastAnchor==="right"||this.lastAnchor==="bottom"){delta=this["_"+this._touchAxis+"Last"]-distance}else{delta=this["_"+this._touchAxis+"Last"]+distance}if(delta>0){delta=0}}else{if(this.lastAnchor==="right"||this.lastAnchor==="bottom"){delta=this["_"+this._touchAxis+"Last"]+distance}else{delta=this["_"+this._touchAxis+"Last"]-distance}if(delta<0){delta=0}}this[this.lastOp.method](delta,this.lastAnchor,this.lastOp.options);return this.settings.touchMoveCallback(delta)};OriDomi.prototype._onTouchEnd=function(){if(!this._touchEnabled){return}this._touchStarted=false;this.stageEl.style.cursor=css.grab;this._setTweening(true);return this.settings.touchEndCallback(this["_"+this._touchAxis+"Last"])};OriDomi.prototype._onTouchLeave=function(){if(!(this._touchEnabled&&this._touchStarted)){return}return this._onTouchEnd()};OriDomi.prototype._onMouseOut=function(e){if(!(this._touchEnabled&&this._touchStarted)){return}if(e.toElement&&!this.el.contains(e.toElement)){return this._onTouchEnd()}};OriDomi.prototype.reset=function(callback){var i,panel,_i,_len,_ref1;if(this.isFoldedUp){return this.unfold(callback)}_ref1=this.panels[this.lastAnchor];for(i=_i=0,_len=_ref1.length;_i<_len;i=++_i){panel=_ref1[i];panel.style[css.transform]=this._transform(0);if(this.shading){this._setShader(i,this.lastAnchor,0)}}return this._callback({callback:callback})};OriDomi.prototype.freeze=function(callback){var _this=this;if(this.isFrozen){return typeof callback==="function"?callback():void 0}else{return this.reset(function(){_this.isFrozen=true;_this.stageEl.style[css.transform]="translate3d(-9999px, 0, 0)";_this.cleanEl.style[css.transform]="translate3d(0, 0, 0)";return typeof callback==="function"?callback():void 0})}};OriDomi.prototype.unfreeze=function(){if(this.isFrozen){this.isFrozen=false;this.cleanEl.style[css.transform]="translate3d(-9999px, 0, 0)";this.stageEl.style[css.transform]="translate3d(0, 0, 0)";return this.lastAngle=0}};OriDomi.prototype.destroy=function(callback){var _this=this;return this.freeze(function(){var changedKeys,_i,_len;_this.stageEl.removeEventListener("touchstart",_this._onTouchStart,false);_this.stageEl.removeEventListener("mousedown",_this._onTouchStart,false);_this.stageEl.removeEventListener("touchend",_this._onTouchEnd,false);_this.stageEl.removeEventListener("mouseup",_this._onTouchEnd,false);if($){$.data(_this.el,"oriDomi",null)}_this.el.innerHTML=_this.cleanEl.innerHTML;changedKeys=["padding","width","height","backgroundColor","backgroundImage","border","outline"];for(_i=0,_len=changedKeys.length;_i<_len;_i++){key=changedKeys[_i];_this.el.style[key]=_this._elStyle[key]}instances[instances.indexOf(_this)]=null;return typeof callback==="function"?callback():void 0})};OriDomi.prototype.enableTouch=function(){this._touchEnabled=true;return this._setCursor()};OriDomi.prototype.disableTouch=function(){this._touchEnabled=false;return this._setCursor()};OriDomi.prototype.accordion=function(angle,anchor,options){var deg,i,normalized,panel,_i,_len,_ref1;normalized=this._normalizeArgs("accordion",arguments);if(!normalized){return}angle=normalized[0],anchor=normalized[1],options=normalized[2];_ref1=this.panels[anchor];for(i=_i=0,_len=_ref1.length;_i<_len;i=++_i){panel=_ref1[i];if(i%2!==0&&!options.twist){deg=-angle}else{deg=angle}if(options.sticky){if(i===0){deg=0}else if(i>1||options.stairs){deg*=2}}else{if(i!==0){deg*=2}}if(options.stairs){deg=-deg}panel.style[css.transform]=this._transform(deg,options.fracture);if(this.shading&&!(i===0&&options.sticky)&&Math.abs(deg)!==180){this._setShader(i,anchor,deg)}}return this._callback(options)};OriDomi.prototype.curl=function(angle,anchor,options){var i,normalized,panel,_i,_len,_ref1;normalized=this._normalizeArgs("curl",arguments);if(!normalized){return}angle=normalized[0],anchor=normalized[1],options=normalized[2];angle/=this._getPanelType(anchor);_ref1=this.panels[anchor];for(i=_i=0,_len=_ref1.length;_i<_len;i=++_i){panel=_ref1[i];panel.style[css.transform]=this._transform(angle);if(this.shading){this._setShader(i,anchor,0)}}return this._callback(options)};OriDomi.prototype.ramp=function(angle,anchor,options){var i,normalized,panel,_i,_len,_ref1;normalized=this._normalizeArgs("ramp",arguments);if(!normalized){return}angle=normalized[0],anchor=normalized[1],options=normalized[2];this.panels[anchor][1].style[css.transform]=this._transform(angle);_ref1=this.panels[anchor];for(i=_i=0,_len=_ref1.length;_i<_len;i=++_i){panel=_ref1[i];if(i>1){this.panels[anchor][i].style[css.transform]=this._transform(0)}if(this.shading){this._setShader(i,anchor,0)}}return this._callback(options)};OriDomi.prototype.foldUp=function(anchor,callback){var angle,i,nextPanel,normalized,onTransitionEnd,_this=this;if(!anchor){anchor="left"}else if(typeof anchor==="function"){callback=anchor}normalized=this._normalizeArgs("foldUp",[0,anchor,{}]);if(!normalized){return}anchor=normalized[1];this.isFoldedUp=true;i=this.panels[anchor].length-1;angle=100;nextPanel=function(){_this.panels[anchor][i].addEventListener(css.transitionEnd,onTransitionEnd,false);_this.panels[anchor][i].style[css.transform]=_this._transform(angle);if(_this.shading){return _this._setShader(i,anchor,angle)}};onTransitionEnd=function(e){_this.panels[anchor][i].removeEventListener(css.transitionEnd,onTransitionEnd,false);_this.panels[anchor][i].style.display="none";if(--i===0){return typeof callback==="function"?callback():void 0}else{return setTimeout(nextPanel,0)}};return nextPanel()};OriDomi.prototype.unfold=function(callback){var angle,i,nextPanel,onTransitionEnd,_this=this;if(!this.isFoldedUp){if(typeof callback==="function"){callback()}}this.isFoldedUp=false;i=1;angle=0;nextPanel=function(){_this.panels[_this.lastAnchor][i].style.display="block";return setTimeout(function(){_this.panels[_this.lastAnchor][i].addEventListener(css.transitionEnd,onTransitionEnd,false);_this.panels[_this.lastAnchor][i].style[css.transform]=_this._transform(angle);if(_this.shading){return _this._setShader(i,_this.lastAnchor,angle)}},0)};onTransitionEnd=function(e){_this.panels[_this.lastAnchor][i].removeEventListener(css.transitionEnd,onTransitionEnd,false);if(++i===_this.panels[_this.lastAnchor].length){return typeof callback==="function"?callback():void 0}else{return setTimeout(nextPanel,0)}};return nextPanel()};OriDomi.prototype.collapse=function(anchor,options){if(options==null){options={}}options.sticky=false;return this.accordion(-89,anchor,options)};OriDomi.prototype.collapseAlt=function(anchor,options){if(options==null){options={}}options.sticky=false;return this.accordion(89,anchor,options)};OriDomi.prototype.reveal=function(angle,anchor,options){if(options==null){options={}}options.sticky=true;return this.accordion(angle,anchor,options)};OriDomi.prototype.stairs=function(angle,anchor,options){if(options==null){options={}}options.stairs=true;options.sticky=true;return this.accordion(angle,anchor,options)};OriDomi.prototype.fracture=function(angle,anchor,options){if(options==null){options={}}options.fracture=true;return this.accordion(angle,anchor,options)};OriDomi.prototype.twist=function(angle,anchor,options){if(options==null){options={}}options.fracture=true;options.twist=true;return this.accordion(angle/10,anchor,options)};OriDomi.VERSION="0.2.2";OriDomi.isSupported=oriDomiSupport;OriDomi.devMode=function(){return devMode=true};return OriDomi}();root.OriDomi=OriDomi;if($){$.fn.oriDomi=function(options){var args,el,instance,_i,_j,_len,_len1;if(!oriDomiSupport){return this}if(typeof options==="string"){if(typeof OriDomi.prototype[options]!=="function"){if(devMode){console.warn("oriDomi: No such method '"+options+"'")}return}for(_i=0,_len=this.length;_i<_len;_i++){el=this[_i];instance=$.data(el,"oriDomi");if(instance==null){if(devMode){console.warn("oriDomi: Can't call "+options+", oriDomi hasn't been initialized on this element")}return}args=Array.prototype.slice.call(arguments);args.shift();instance[options].apply(instance,args)}return this}else{for(_j=0,_len1=this.length;_j<_len1;_j++){el=this[_j];instance=$.data(el,"oriDomi");if(instance){return instance}else{$.data(el,"oriDomi",new OriDomi(el,options))}}return this}}}}).call(this); -------------------------------------------------------------------------------- /oridomi.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.4.0 2 | (function() { 3 | 'use strict'; 4 | 5 | var $, OriDomi, css, defaults, devMode, extendObj, instances, key, noOp, oriDomiSupport, prefixList, root, testEl, testProp, value, _ref, 6 | __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; 7 | 8 | root = this; 9 | 10 | instances = []; 11 | 12 | $ = root.$ || false; 13 | 14 | devMode = false; 15 | 16 | oriDomiSupport = true; 17 | 18 | testEl = document.createElement('div'); 19 | 20 | prefixList = ['Webkit', 'Moz', 'O', 'ms', 'Khtml']; 21 | 22 | css = { 23 | transform: 'transform', 24 | origin: 'transformOrigin', 25 | transformStyle: 'transformStyle', 26 | transitionProp: 'transitionProperty', 27 | transitionDuration: 'transitionDuration', 28 | transitionEasing: 'transitionTimingFunction', 29 | perspective: 'perspective', 30 | backface: 'backfaceVisibility' 31 | }; 32 | 33 | testProp = function(prop) { 34 | var capProp, prefix, _i, _len; 35 | capProp = prop.charAt(0).toUpperCase() + prop.slice(1); 36 | for (_i = 0, _len = prefixList.length; _i < _len; _i++) { 37 | prefix = prefixList[_i]; 38 | if (testEl.style[prefix + capProp] != null) { 39 | return prefix + capProp; 40 | } 41 | } 42 | if (testEl.style[prop] != null) { 43 | return prop; 44 | } 45 | return false; 46 | }; 47 | 48 | for (key in css) { 49 | value = css[key]; 50 | css[key] = testProp(value); 51 | if (!css[key]) { 52 | if (devMode) { 53 | console.warn('oriDomi: Browser does not support oriDomi'); 54 | } 55 | oriDomiSupport = false; 56 | break; 57 | } 58 | } 59 | 60 | css.gradientProp = (function() { 61 | var hyphenated, prefix, _i, _len; 62 | for (_i = 0, _len = prefixList.length; _i < _len; _i++) { 63 | prefix = prefixList[_i]; 64 | hyphenated = "-" + (prefix.toLowerCase()) + "-linear-gradient"; 65 | testEl.style.backgroundImage = "" + hyphenated + "(left, #000, #fff)"; 66 | if (testEl.style.backgroundImage.indexOf('gradient') !== -1) { 67 | return hyphenated; 68 | } 69 | } 70 | return 'linear-gradient'; 71 | })(); 72 | 73 | _ref = (function() { 74 | var grabValue, plainGrab, prefix, _i, _len; 75 | for (_i = 0, _len = prefixList.length; _i < _len; _i++) { 76 | prefix = prefixList[_i]; 77 | plainGrab = 'grab'; 78 | testEl.style.cursor = (grabValue = "-" + (prefix.toLowerCase()) + "-" + plainGrab); 79 | if (testEl.style.cursor === grabValue) { 80 | return [grabValue, "-" + (prefix.toLowerCase()) + "-grabbing"]; 81 | } 82 | } 83 | testEl.style.cursor = plainGrab; 84 | if (testEl.style.cursor === plainGrab) { 85 | return [plainGrab, 'grabbing']; 86 | } else { 87 | return ['move', 'move']; 88 | } 89 | })(), css.grab = _ref[0], css.grabbing = _ref[1]; 90 | 91 | css.transformProp = (function() { 92 | var prefix; 93 | prefix = css.transform.match(/(\w+)Transform/i); 94 | if (prefix) { 95 | return "-" + (prefix[1].toLowerCase()) + "-transform"; 96 | } else { 97 | return 'transform'; 98 | } 99 | })(); 100 | 101 | css.transitionEnd = (function() { 102 | switch (css.transitionProp) { 103 | case 'transitionProperty': 104 | return 'transitionEnd'; 105 | case 'WebkitTransitionProperty': 106 | return 'webkitTransitionEnd'; 107 | case 'MozTransitionProperty': 108 | return 'transitionend'; 109 | case 'OTransitionProperty': 110 | return 'oTransitionEnd'; 111 | case 'MSTransitionProperty': 112 | return 'msTransitionEnd'; 113 | } 114 | })(); 115 | 116 | extendObj = function(target, source) { 117 | var prop; 118 | if (source !== Object(source)) { 119 | if (devMode) { 120 | console.warn('oriDomi: Must pass an object to extend with'); 121 | } 122 | return target; 123 | } 124 | if (target !== Object(target)) { 125 | target = {}; 126 | } 127 | for (prop in source) { 128 | if (!(target[prop] != null)) { 129 | target[prop] = source[prop]; 130 | } 131 | } 132 | return target; 133 | }; 134 | 135 | noOp = function() {}; 136 | 137 | defaults = { 138 | vPanels: 3, 139 | hPanels: 3, 140 | perspective: 1000, 141 | shading: 'hard', 142 | speed: 700, 143 | oriDomiClass: 'oridomi', 144 | shadingIntensity: 1, 145 | easingMethod: '', 146 | showOnStart: false, 147 | forceAntialiasing: false, 148 | touchEnabled: true, 149 | touchSensitivity: .25, 150 | touchStartCallback: noOp, 151 | touchMoveCallback: noOp, 152 | touchEndCallback: noOp 153 | }; 154 | 155 | OriDomi = (function() { 156 | 157 | function OriDomi(el, options) { 158 | var anchor, bleed, bottomShader, content, contentHolder, eString, eventPair, eventPairs, hMask, hPanel, i, leftShader, metric, mouseLeaveSupport, panel, rightShader, shader, stage, topShader, vMask, vPanel, xMetrics, xOffset, yMetrics, yOffset, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _len8, _m, _n, _o, _p, _q, _r, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _s; 159 | this.el = el; 160 | this._onMouseOut = __bind(this._onMouseOut, this); 161 | 162 | this._onTouchLeave = __bind(this._onTouchLeave, this); 163 | 164 | this._onTouchEnd = __bind(this._onTouchEnd, this); 165 | 166 | this._onTouchMove = __bind(this._onTouchMove, this); 167 | 168 | this._onTouchStart = __bind(this._onTouchStart, this); 169 | 170 | if (devMode) { 171 | console.time('oridomiConstruction'); 172 | } 173 | if (!oriDomiSupport) { 174 | return this.el; 175 | } 176 | if (!(this instanceof OriDomi)) { 177 | return new oriDomi(this.el, this.settings); 178 | } 179 | this.settings = extendObj(options, defaults); 180 | if (!this.el || this.el.nodeType !== 1) { 181 | if (devMode) { 182 | console.warn('oriDomi: First argument must be a DOM element'); 183 | } 184 | return; 185 | } 186 | this.cleanEl = this.el.cloneNode(true); 187 | this.cleanEl.style.margin = '0'; 188 | this.cleanEl.style.position = 'absolute'; 189 | this.cleanEl.style[css.transform] = 'translate3d(-9999px, 0, 0)'; 190 | _ref1 = this.settings, this.shading = _ref1.shading, this.shadingIntensity = _ref1.shadingIntensity, this.vPanels = _ref1.vPanels, this.hPanels = _ref1.hPanels; 191 | this._elStyle = root.getComputedStyle(this.el); 192 | this.displayStyle = this._elStyle.display; 193 | if (this.displayStyle === 'none') { 194 | this.displayStyle = 'block'; 195 | } 196 | xMetrics = ['width', 'paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth']; 197 | yMetrics = ['height', 'paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth']; 198 | this.width = 0; 199 | this.height = 0; 200 | for (_i = 0, _len = xMetrics.length; _i < _len; _i++) { 201 | metric = xMetrics[_i]; 202 | this.width += this._getMetric(metric); 203 | } 204 | for (_j = 0, _len1 = yMetrics.length; _j < _len1; _j++) { 205 | metric = yMetrics[_j]; 206 | this.height += this._getMetric(metric); 207 | } 208 | this.panelWidth = this.width / this.vPanels; 209 | this.panelHeight = this.height / this.hPanels; 210 | this.lastAngle = 0; 211 | this.isFoldedUp = false; 212 | this.isFrozen = false; 213 | this.anchors = ['left', 'right', 'top', 'bottom']; 214 | this.lastAnchor = this.anchors[0]; 215 | this.panels = {}; 216 | this.stages = {}; 217 | stage = document.createElement('div'); 218 | stage.style.width = this.width + 'px'; 219 | stage.style.height = this.height + 'px'; 220 | stage.style.display = 'none'; 221 | stage.style.position = 'absolute'; 222 | stage.style.padding = '0'; 223 | stage.style.margin = '0'; 224 | stage.style[css.perspective] = this.settings.perspective + 'px'; 225 | stage.style[css.transformStyle] = 'preserve-3d'; 226 | _ref2 = this.anchors; 227 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 228 | anchor = _ref2[_k]; 229 | this.panels[anchor] = []; 230 | this.stages[anchor] = stage.cloneNode(false); 231 | this.stages[anchor].className = 'oridomi-stage-' + anchor; 232 | } 233 | if (this.shading) { 234 | this.shaders = {}; 235 | _ref3 = this.anchors; 236 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { 237 | anchor = _ref3[_l]; 238 | this.shaders[anchor] = {}; 239 | if (anchor === 'left' || anchor === 'right') { 240 | this.shaders[anchor].left = []; 241 | this.shaders[anchor].right = []; 242 | } else { 243 | this.shaders[anchor].top = []; 244 | this.shaders[anchor].bottom = []; 245 | } 246 | } 247 | shader = document.createElement('div'); 248 | shader.style[css.transitionProp] = 'opacity'; 249 | shader.style[css.transitionDuration] = this.settings.speed + 'ms'; 250 | shader.style[css.transitionEasing] = this.settings.easingMethod; 251 | shader.style.position = 'absolute'; 252 | shader.style.width = '100%'; 253 | shader.style.height = '100%'; 254 | shader.style.opacity = '0'; 255 | shader.style.top = '0'; 256 | shader.style.left = '0'; 257 | shader.style.pointerEvents = 'none'; 258 | } 259 | contentHolder = this.el.cloneNode(true); 260 | contentHolder.classList.add('oridomi-content'); 261 | contentHolder.style.margin = '0'; 262 | contentHolder.style.position = 'relative'; 263 | contentHolder.style.float = 'none'; 264 | hMask = document.createElement('div'); 265 | hMask.className = 'oridomi-mask-h'; 266 | hMask.style.position = 'absolute'; 267 | hMask.style.overflow = 'hidden'; 268 | hMask.style.width = '100%'; 269 | hMask.style.height = '100%'; 270 | hMask.style[css.transform] = 'translate3d(0, 0, 0)'; 271 | hMask.appendChild(contentHolder); 272 | if (this.shading) { 273 | topShader = shader.cloneNode(false); 274 | topShader.className = 'oridomi-shader-top'; 275 | topShader.style.background = this._getShaderGradient('top'); 276 | bottomShader = shader.cloneNode(false); 277 | bottomShader.className = 'oridomi-shader-bottom'; 278 | bottomShader.style.background = this._getShaderGradient('bottom'); 279 | hMask.appendChild(topShader); 280 | hMask.appendChild(bottomShader); 281 | } 282 | bleed = 1.5; 283 | hPanel = document.createElement('div'); 284 | hPanel.className = 'oridomi-panel-h'; 285 | hPanel.style.width = '100%'; 286 | hPanel.style.height = this.panelHeight + bleed + 'px'; 287 | hPanel.style.padding = '0'; 288 | hPanel.style.position = 'relative'; 289 | hPanel.style[css.transitionProp] = css.transformProp; 290 | hPanel.style[css.transitionDuration] = this.settings.speed + 'ms'; 291 | hPanel.style[css.transitionEasing] = this.settings.easingMethod; 292 | hPanel.style[css.origin] = 'top'; 293 | hPanel.style[css.transformStyle] = 'preserve-3d'; 294 | hPanel.style[css.backface] = 'hidden'; 295 | if (this.settings.forceAntialiasing) { 296 | hPanel.style.outline = '1px solid transparent'; 297 | } 298 | hPanel.appendChild(hMask); 299 | _ref4 = ['top', 'bottom']; 300 | for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) { 301 | anchor = _ref4[_m]; 302 | for (i = _n = 0, _ref5 = this.hPanels; 0 <= _ref5 ? _n < _ref5 : _n > _ref5; i = 0 <= _ref5 ? ++_n : --_n) { 303 | panel = hPanel.cloneNode(true); 304 | content = panel.getElementsByClassName('oridomi-content')[0]; 305 | if (anchor === 'top') { 306 | yOffset = -(i * this.panelHeight); 307 | if (i === 0) { 308 | panel.style.top = '0'; 309 | } else { 310 | panel.style.top = this.panelHeight + 'px'; 311 | } 312 | } else { 313 | panel.style[css.origin] = 'bottom'; 314 | yOffset = -((this.hPanels * this.panelHeight) - (this.panelHeight * (i + 1))); 315 | if (i === 0) { 316 | panel.style.top = this.panelHeight * (this.vPanels - 1) - bleed + 'px'; 317 | } else { 318 | panel.style.top = -this.panelHeight + 'px'; 319 | } 320 | } 321 | content.style.top = yOffset + 'px'; 322 | if (this.shading) { 323 | this.shaders[anchor].top[i] = panel.getElementsByClassName('oridomi-shader-top')[0]; 324 | this.shaders[anchor].bottom[i] = panel.getElementsByClassName('oridomi-shader-bottom')[0]; 325 | } 326 | this.panels[anchor][i] = panel; 327 | if (i !== 0) { 328 | this.panels[anchor][i - 1].appendChild(panel); 329 | } 330 | } 331 | this.stages[anchor].appendChild(this.panels[anchor][0]); 332 | } 333 | vMask = hMask.cloneNode(true); 334 | vMask.className = 'oridomi-mask-v'; 335 | if (this.shading) { 336 | leftShader = vMask.getElementsByClassName('oridomi-shader-top')[0]; 337 | leftShader.className = 'oridomi-shader-left'; 338 | leftShader.style.background = this._getShaderGradient('left'); 339 | rightShader = vMask.getElementsByClassName('oridomi-shader-bottom')[0]; 340 | rightShader.className = 'oridomi-shader-right'; 341 | rightShader.style.background = this._getShaderGradient('right'); 342 | } 343 | vPanel = hPanel.cloneNode(false); 344 | vPanel.className = 'oridomi-panel-v'; 345 | vPanel.style.width = this.panelWidth + bleed + 'px'; 346 | vPanel.style.height = '100%'; 347 | vPanel.style[css.origin] = 'left'; 348 | vPanel.appendChild(vMask); 349 | _ref6 = ['left', 'right']; 350 | for (_o = 0, _len5 = _ref6.length; _o < _len5; _o++) { 351 | anchor = _ref6[_o]; 352 | for (i = _p = 0, _ref7 = this.vPanels; 0 <= _ref7 ? _p < _ref7 : _p > _ref7; i = 0 <= _ref7 ? ++_p : --_p) { 353 | panel = vPanel.cloneNode(true); 354 | content = panel.getElementsByClassName('oridomi-content')[0]; 355 | if (anchor === 'left') { 356 | xOffset = -(i * this.panelWidth); 357 | if (i === 0) { 358 | panel.style.left = '0'; 359 | } else { 360 | panel.style.left = this.panelWidth + 'px'; 361 | } 362 | } else { 363 | panel.style[css.origin] = 'right'; 364 | xOffset = -((this.vPanels * this.panelWidth) - (this.panelWidth * (i + 1))); 365 | if (i === 0) { 366 | panel.style.left = this.panelWidth * (this.vPanels - 1) - 1 + 'px'; 367 | } else { 368 | panel.style.left = -this.panelWidth + 'px'; 369 | } 370 | } 371 | content.style.left = xOffset + 'px'; 372 | if (this.shading) { 373 | this.shaders[anchor].left[i] = panel.getElementsByClassName('oridomi-shader-left')[0]; 374 | this.shaders[anchor].right[i] = panel.getElementsByClassName('oridomi-shader-right')[0]; 375 | } 376 | this.panels[anchor][i] = panel; 377 | if (i !== 0) { 378 | this.panels[anchor][i - 1].appendChild(panel); 379 | } 380 | } 381 | this.stages[anchor].appendChild(this.panels[anchor][0]); 382 | } 383 | this.el.classList.add(this.settings.oriDomiClass); 384 | this.el.style.padding = '0'; 385 | this.el.style.width = this.width + 'px'; 386 | this.el.style.height = this.height + 'px'; 387 | this.el.style.backgroundColor = 'transparent'; 388 | this.el.style.backgroundImage = 'none'; 389 | this.el.style.border = 'none'; 390 | this.el.style.outline = 'none'; 391 | this.stages.left.style.display = 'block'; 392 | this.stageEl = document.createElement('div'); 393 | eventPairs = [['TouchStart', 'MouseDown'], ['TouchEnd', 'MouseUp'], ['TouchMove', 'MouseMove'], ['TouchLeave', 'MouseLeave']]; 394 | mouseLeaveSupport = 'onmouseleave' in window; 395 | for (_q = 0, _len6 = eventPairs.length; _q < _len6; _q++) { 396 | eventPair = eventPairs[_q]; 397 | for (_r = 0, _len7 = eventPair.length; _r < _len7; _r++) { 398 | eString = eventPair[_r]; 399 | if (!(eString === 'TouchLeave' && !mouseLeaveSupport)) { 400 | this.stageEl.addEventListener(eString.toLowerCase(), this['_on' + eventPair[0]], false); 401 | } else { 402 | this.stageEl.addEventListener('mouseout', this['_onMouseOut'], false); 403 | break; 404 | } 405 | } 406 | } 407 | if (this.settings.touchEnabled) { 408 | this.enableTouch(); 409 | } 410 | _ref8 = this.anchors; 411 | for (_s = 0, _len8 = _ref8.length; _s < _len8; _s++) { 412 | anchor = _ref8[_s]; 413 | this.stageEl.appendChild(this.stages[anchor]); 414 | } 415 | if (this.settings.showOnStart) { 416 | this.el.style.display = 'block'; 417 | this.el.style.visibility = 'visible'; 418 | } 419 | this.el.innerHTML = ''; 420 | this.el.appendChild(this.cleanEl); 421 | this.el.appendChild(this.stageEl); 422 | _ref9 = [0, 0], this._xLast = _ref9[0], this._yLast = _ref9[1]; 423 | this.lastOp = { 424 | method: 'accordion', 425 | options: {} 426 | }; 427 | if ($) { 428 | this.$el = $(this.el); 429 | } 430 | instances.push(this); 431 | this._callback(this.settings); 432 | if (devMode) { 433 | console.timeEnd('oridomiConstruction'); 434 | } 435 | } 436 | 437 | OriDomi.prototype._callback = function(options) { 438 | var onTransitionEnd, 439 | _this = this; 440 | if (typeof options.callback === 'function') { 441 | onTransitionEnd = function(e) { 442 | e.currentTarget.removeEventListener(css.transitionEnd, onTransitionEnd, false); 443 | return options.callback(); 444 | }; 445 | if (this.lastAngle === 0) { 446 | return options.callback(); 447 | } else { 448 | return this.panels[this.lastAnchor][0].addEventListener(css.transitionEnd, onTransitionEnd, false); 449 | } 450 | } 451 | }; 452 | 453 | OriDomi.prototype._getMetric = function(metric) { 454 | return parseInt(this._elStyle[metric], 10); 455 | }; 456 | 457 | OriDomi.prototype._transform = function(angle, fracture) { 458 | var axes, _ref1; 459 | switch (this.lastAnchor) { 460 | case 'left': 461 | axes = [0, 1, 0, angle]; 462 | break; 463 | case 'right': 464 | axes = [0, 1, 0, -angle]; 465 | break; 466 | case 'top': 467 | axes = [1, 0, 0, -angle]; 468 | break; 469 | case 'bottom': 470 | axes = [1, 0, 0, angle]; 471 | } 472 | if (fracture) { 473 | _ref1 = [1, 1, 1], axes[0] = _ref1[0], axes[1] = _ref1[1], axes[2] = _ref1[2]; 474 | } 475 | return "rotate3d(" + axes[0] + ", " + axes[1] + ", " + axes[2] + ", " + axes[3] + "deg)"; 476 | }; 477 | 478 | OriDomi.prototype._normalizeAngle = function(angle) { 479 | angle = parseFloat(angle, 10); 480 | if (isNaN(angle)) { 481 | return 0; 482 | } else if (angle > 89) { 483 | return 89; 484 | } else if (angle < -89) { 485 | return -89; 486 | } else { 487 | return angle; 488 | } 489 | }; 490 | 491 | OriDomi.prototype._normalizeArgs = function(method, args) { 492 | var anchor, angle, options, 493 | _this = this; 494 | if (this.isFrozen) { 495 | this.unfreeze(); 496 | } 497 | angle = this._normalizeAngle(args[0]); 498 | anchor = this._getLonghandAnchor(args[1] || this.lastAnchor); 499 | options = extendObj(args[2], this._methodDefaults[method]); 500 | this.lastOp = { 501 | method: method, 502 | options: options, 503 | negative: angle < 0 504 | }; 505 | if (anchor !== this.lastAnchor || (method === 'foldUp' && this.lastAngle !== 0) || this.isFoldedUp) { 506 | this.reset(function() { 507 | _this._showStage(anchor); 508 | if (_this._touchEnabled) { 509 | _this._setCursor(); 510 | } 511 | return setTimeout(function() { 512 | if (method === 'foldUp') { 513 | args.shift(); 514 | } 515 | return _this[method].apply(_this, args); 516 | }, 0); 517 | }); 518 | return false; 519 | } else { 520 | this.lastAngle = angle; 521 | return [angle, anchor, options]; 522 | } 523 | }; 524 | 525 | OriDomi.prototype._setShader = function(i, anchor, angle) { 526 | var a, abs, b, opacity; 527 | abs = Math.abs(angle); 528 | opacity = abs / 90 * this.shadingIntensity; 529 | if (this.shading === 'hard') { 530 | opacity *= .15; 531 | if (this.lastAngle < 0) { 532 | angle = abs; 533 | } else { 534 | angle = -abs; 535 | } 536 | } else { 537 | opacity *= .4; 538 | } 539 | switch (anchor) { 540 | case 'left': 541 | case 'top': 542 | if (angle < 0) { 543 | a = opacity; 544 | b = 0; 545 | } else { 546 | a = 0; 547 | b = opacity; 548 | } 549 | break; 550 | case 'right': 551 | case 'bottom': 552 | if (angle < 0) { 553 | a = 0; 554 | b = opacity; 555 | } else { 556 | a = opacity; 557 | b = 0; 558 | } 559 | } 560 | if (anchor === 'left' || anchor === 'right') { 561 | this.shaders[anchor].left[i].style.opacity = a; 562 | return this.shaders[anchor].right[i].style.opacity = b; 563 | } else { 564 | this.shaders[anchor].top[i].style.opacity = a; 565 | return this.shaders[anchor].bottom[i].style.opacity = b; 566 | } 567 | }; 568 | 569 | OriDomi.prototype._getShaderGradient = function(anchor) { 570 | return "" + css.gradientProp + "(" + anchor + ", rgba(0, 0, 0, .5) 0%, rgba(255, 255, 255, .35) 100%)"; 571 | }; 572 | 573 | OriDomi.prototype._showStage = function(anchor) { 574 | if (anchor !== this.lastAnchor) { 575 | this.stages[anchor].style.display = 'block'; 576 | this.stages[this.lastAnchor].style.display = 'none'; 577 | return this.lastAnchor = anchor; 578 | } 579 | }; 580 | 581 | OriDomi.prototype._getPanelType = function(anchor) { 582 | if (anchor === 'left' || anchor === 'right') { 583 | return this.vPanels; 584 | } else { 585 | return this.hPanels; 586 | } 587 | }; 588 | 589 | OriDomi.prototype._getLonghandAnchor = function(shorthand) { 590 | switch (shorthand) { 591 | case 'left': 592 | case 'l': 593 | case '4': 594 | case 4: 595 | return 'left'; 596 | case 'right': 597 | case 'r': 598 | case '2': 599 | case 2: 600 | return 'right'; 601 | case 'top': 602 | case 't': 603 | case '1': 604 | case 1: 605 | return 'top'; 606 | case 'bottom': 607 | case 'b': 608 | case '3': 609 | case 3: 610 | return 'bottom'; 611 | default: 612 | return 'left'; 613 | } 614 | }; 615 | 616 | OriDomi.prototype._setTweening = function(speed) { 617 | var i, panel, shaderPair, _i, _len, _ref1; 618 | if (typeof speed === 'boolean') { 619 | speed = speed ? this.settings.speed + 'ms' : '0ms'; 620 | } 621 | if (this.lastAnchor === 'left' || this.lastAnchor === 'right') { 622 | shaderPair = ['left', 'right']; 623 | } else { 624 | shaderPair = ['top', 'bottom']; 625 | } 626 | _ref1 = this.panels[this.lastAnchor]; 627 | for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) { 628 | panel = _ref1[i]; 629 | panel.style[css.transitionDuration] = speed; 630 | if (this.shading) { 631 | this.shaders[this.lastAnchor][shaderPair[0]][i].style[css.transitionDuration] = speed; 632 | this.shaders[this.lastAnchor][shaderPair[1]][i].style[css.transitionDuration] = speed; 633 | } 634 | } 635 | return null; 636 | }; 637 | 638 | OriDomi.prototype._setCursor = function() { 639 | if (this._touchEnabled) { 640 | return this.stageEl.style.cursor = css.grab; 641 | } else { 642 | return this.stageEl.style.cursor = 'default'; 643 | } 644 | }; 645 | 646 | OriDomi.prototype._methodDefaults = { 647 | accordion: { 648 | sticky: false, 649 | stairs: false, 650 | fracture: false, 651 | twist: false 652 | }, 653 | curl: { 654 | twist: false 655 | }, 656 | ramp: {}, 657 | foldUp: {} 658 | }; 659 | 660 | OriDomi.prototype._onTouchStart = function(e) { 661 | if (!this._touchEnabled) { 662 | return; 663 | } 664 | e.preventDefault(); 665 | this._touchStarted = true; 666 | this.stageEl.style.cursor = css.grabbing; 667 | this._setTweening(false); 668 | this._touchAxis = this.lastAnchor === 'left' || this.lastAnchor === 'right' ? 'x' : 'y'; 669 | this["_" + this._touchAxis + "Last"] = this.lastAngle; 670 | if (e.type === 'mousedown') { 671 | this["_" + this._touchAxis + "1"] = e["page" + (this._touchAxis.toUpperCase())]; 672 | } else { 673 | this["_" + this._touchAxis + "1"] = e.targetTouches[0]["page" + (this._touchAxis.toUpperCase())]; 674 | } 675 | return this.settings.touchStartCallback(this["_" + this._touchAxis + "1"]); 676 | }; 677 | 678 | OriDomi.prototype._onTouchMove = function(e) { 679 | var current, delta, distance; 680 | if (!(this._touchEnabled && this._touchStarted)) { 681 | return; 682 | } 683 | e.preventDefault(); 684 | if (e.type === 'mousemove') { 685 | current = e["page" + (this._touchAxis.toUpperCase())]; 686 | } else { 687 | current = e.targetTouches[0]["page" + (this._touchAxis.toUpperCase())]; 688 | } 689 | distance = (current - this["_" + this._touchAxis + "1"]) * this.settings.touchSensitivity; 690 | if (this.lastOp.negative) { 691 | if (this.lastAnchor === 'right' || this.lastAnchor === 'bottom') { 692 | delta = this["_" + this._touchAxis + "Last"] - distance; 693 | } else { 694 | delta = this["_" + this._touchAxis + "Last"] + distance; 695 | } 696 | if (delta > 0) { 697 | delta = 0; 698 | } 699 | } else { 700 | if (this.lastAnchor === 'right' || this.lastAnchor === 'bottom') { 701 | delta = this["_" + this._touchAxis + "Last"] + distance; 702 | } else { 703 | delta = this["_" + this._touchAxis + "Last"] - distance; 704 | } 705 | if (delta < 0) { 706 | delta = 0; 707 | } 708 | } 709 | this[this.lastOp.method](delta, this.lastAnchor, this.lastOp.options); 710 | return this.settings.touchMoveCallback(delta); 711 | }; 712 | 713 | OriDomi.prototype._onTouchEnd = function() { 714 | if (!this._touchEnabled) { 715 | return; 716 | } 717 | this._touchStarted = false; 718 | this.stageEl.style.cursor = css.grab; 719 | this._setTweening(true); 720 | return this.settings.touchEndCallback(this["_" + this._touchAxis + "Last"]); 721 | }; 722 | 723 | OriDomi.prototype._onTouchLeave = function() { 724 | if (!(this._touchEnabled && this._touchStarted)) { 725 | return; 726 | } 727 | return this._onTouchEnd(); 728 | }; 729 | 730 | OriDomi.prototype._onMouseOut = function(e) { 731 | if (!(this._touchEnabled && this._touchStarted)) { 732 | return; 733 | } 734 | if (e.toElement && !this.el.contains(e.toElement)) { 735 | return this._onTouchEnd(); 736 | } 737 | }; 738 | 739 | OriDomi.prototype.reset = function(callback) { 740 | var i, panel, _i, _len, _ref1; 741 | if (this.isFoldedUp) { 742 | return this.unfold(callback); 743 | } 744 | _ref1 = this.panels[this.lastAnchor]; 745 | for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) { 746 | panel = _ref1[i]; 747 | panel.style[css.transform] = this._transform(0); 748 | if (this.shading) { 749 | this._setShader(i, this.lastAnchor, 0); 750 | } 751 | } 752 | return this._callback({ 753 | callback: callback 754 | }); 755 | }; 756 | 757 | OriDomi.prototype.freeze = function(callback) { 758 | var _this = this; 759 | if (this.isFrozen) { 760 | return typeof callback === "function" ? callback() : void 0; 761 | } else { 762 | return this.reset(function() { 763 | _this.isFrozen = true; 764 | _this.stageEl.style[css.transform] = 'translate3d(-9999px, 0, 0)'; 765 | _this.cleanEl.style[css.transform] = 'translate3d(0, 0, 0)'; 766 | return typeof callback === "function" ? callback() : void 0; 767 | }); 768 | } 769 | }; 770 | 771 | OriDomi.prototype.unfreeze = function() { 772 | if (this.isFrozen) { 773 | this.isFrozen = false; 774 | this.cleanEl.style[css.transform] = 'translate3d(-9999px, 0, 0)'; 775 | this.stageEl.style[css.transform] = 'translate3d(0, 0, 0)'; 776 | return this.lastAngle = 0; 777 | } 778 | }; 779 | 780 | OriDomi.prototype.destroy = function(callback) { 781 | var _this = this; 782 | return this.freeze(function() { 783 | var changedKeys, _i, _len; 784 | _this.stageEl.removeEventListener('touchstart', _this._onTouchStart, false); 785 | _this.stageEl.removeEventListener('mousedown', _this._onTouchStart, false); 786 | _this.stageEl.removeEventListener('touchend', _this._onTouchEnd, false); 787 | _this.stageEl.removeEventListener('mouseup', _this._onTouchEnd, false); 788 | if ($) { 789 | $.data(_this.el, 'oriDomi', null); 790 | } 791 | _this.el.innerHTML = _this.cleanEl.innerHTML; 792 | changedKeys = ['padding', 'width', 'height', 'backgroundColor', 'backgroundImage', 'border', 'outline']; 793 | for (_i = 0, _len = changedKeys.length; _i < _len; _i++) { 794 | key = changedKeys[_i]; 795 | _this.el.style[key] = _this._elStyle[key]; 796 | } 797 | instances[instances.indexOf(_this)] = null; 798 | return typeof callback === "function" ? callback() : void 0; 799 | }); 800 | }; 801 | 802 | OriDomi.prototype.enableTouch = function() { 803 | this._touchEnabled = true; 804 | return this._setCursor(); 805 | }; 806 | 807 | OriDomi.prototype.disableTouch = function() { 808 | this._touchEnabled = false; 809 | return this._setCursor(); 810 | }; 811 | 812 | OriDomi.prototype.accordion = function(angle, anchor, options) { 813 | var deg, i, normalized, panel, _i, _len, _ref1; 814 | normalized = this._normalizeArgs('accordion', arguments); 815 | if (!normalized) { 816 | return; 817 | } 818 | angle = normalized[0], anchor = normalized[1], options = normalized[2]; 819 | _ref1 = this.panels[anchor]; 820 | for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) { 821 | panel = _ref1[i]; 822 | if (i % 2 !== 0 && !options.twist) { 823 | deg = -angle; 824 | } else { 825 | deg = angle; 826 | } 827 | if (options.sticky) { 828 | if (i === 0) { 829 | deg = 0; 830 | } else if (i > 1 || options.stairs) { 831 | deg *= 2; 832 | } 833 | } else { 834 | if (i !== 0) { 835 | deg *= 2; 836 | } 837 | } 838 | if (options.stairs) { 839 | deg = -deg; 840 | } 841 | panel.style[css.transform] = this._transform(deg, options.fracture); 842 | if (this.shading && !(i === 0 && options.sticky) && Math.abs(deg) !== 180) { 843 | this._setShader(i, anchor, deg); 844 | } 845 | } 846 | return this._callback(options); 847 | }; 848 | 849 | OriDomi.prototype.curl = function(angle, anchor, options) { 850 | var i, normalized, panel, _i, _len, _ref1; 851 | normalized = this._normalizeArgs('curl', arguments); 852 | if (!normalized) { 853 | return; 854 | } 855 | angle = normalized[0], anchor = normalized[1], options = normalized[2]; 856 | angle /= this._getPanelType(anchor); 857 | _ref1 = this.panels[anchor]; 858 | for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) { 859 | panel = _ref1[i]; 860 | panel.style[css.transform] = this._transform(angle); 861 | if (this.shading) { 862 | this._setShader(i, anchor, 0); 863 | } 864 | } 865 | return this._callback(options); 866 | }; 867 | 868 | OriDomi.prototype.ramp = function(angle, anchor, options) { 869 | var i, normalized, panel, _i, _len, _ref1; 870 | normalized = this._normalizeArgs('ramp', arguments); 871 | if (!normalized) { 872 | return; 873 | } 874 | angle = normalized[0], anchor = normalized[1], options = normalized[2]; 875 | this.panels[anchor][1].style[css.transform] = this._transform(angle); 876 | _ref1 = this.panels[anchor]; 877 | for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) { 878 | panel = _ref1[i]; 879 | if (i > 1) { 880 | this.panels[anchor][i].style[css.transform] = this._transform(0); 881 | } 882 | if (this.shading) { 883 | this._setShader(i, anchor, 0); 884 | } 885 | } 886 | return this._callback(options); 887 | }; 888 | 889 | OriDomi.prototype.foldUp = function(anchor, callback) { 890 | var angle, i, nextPanel, normalized, onTransitionEnd, 891 | _this = this; 892 | if (!anchor) { 893 | anchor = 'left'; 894 | } else if (typeof anchor === 'function') { 895 | callback = anchor; 896 | } 897 | normalized = this._normalizeArgs('foldUp', [0, anchor, {}]); 898 | if (!normalized) { 899 | return; 900 | } 901 | anchor = normalized[1]; 902 | this.isFoldedUp = true; 903 | i = this.panels[anchor].length - 1; 904 | angle = 100; 905 | nextPanel = function() { 906 | _this.panels[anchor][i].addEventListener(css.transitionEnd, onTransitionEnd, false); 907 | _this.panels[anchor][i].style[css.transform] = _this._transform(angle); 908 | if (_this.shading) { 909 | return _this._setShader(i, anchor, angle); 910 | } 911 | }; 912 | onTransitionEnd = function(e) { 913 | _this.panels[anchor][i].removeEventListener(css.transitionEnd, onTransitionEnd, false); 914 | _this.panels[anchor][i].style.display = 'none'; 915 | if (--i === 0) { 916 | return typeof callback === "function" ? callback() : void 0; 917 | } else { 918 | return setTimeout(nextPanel, 0); 919 | } 920 | }; 921 | return nextPanel(); 922 | }; 923 | 924 | OriDomi.prototype.unfold = function(callback) { 925 | var angle, i, nextPanel, onTransitionEnd, 926 | _this = this; 927 | if (!this.isFoldedUp) { 928 | if (typeof callback === "function") { 929 | callback(); 930 | } 931 | } 932 | this.isFoldedUp = false; 933 | i = 1; 934 | angle = 0; 935 | nextPanel = function() { 936 | _this.panels[_this.lastAnchor][i].style.display = 'block'; 937 | return setTimeout(function() { 938 | _this.panels[_this.lastAnchor][i].addEventListener(css.transitionEnd, onTransitionEnd, false); 939 | _this.panels[_this.lastAnchor][i].style[css.transform] = _this._transform(angle); 940 | if (_this.shading) { 941 | return _this._setShader(i, _this.lastAnchor, angle); 942 | } 943 | }, 0); 944 | }; 945 | onTransitionEnd = function(e) { 946 | _this.panels[_this.lastAnchor][i].removeEventListener(css.transitionEnd, onTransitionEnd, false); 947 | if (++i === _this.panels[_this.lastAnchor].length) { 948 | return typeof callback === "function" ? callback() : void 0; 949 | } else { 950 | return setTimeout(nextPanel, 0); 951 | } 952 | }; 953 | return nextPanel(); 954 | }; 955 | 956 | OriDomi.prototype.collapse = function(anchor, options) { 957 | if (options == null) { 958 | options = {}; 959 | } 960 | options.sticky = false; 961 | return this.accordion(-89, anchor, options); 962 | }; 963 | 964 | OriDomi.prototype.collapseAlt = function(anchor, options) { 965 | if (options == null) { 966 | options = {}; 967 | } 968 | options.sticky = false; 969 | return this.accordion(89, anchor, options); 970 | }; 971 | 972 | OriDomi.prototype.reveal = function(angle, anchor, options) { 973 | if (options == null) { 974 | options = {}; 975 | } 976 | options.sticky = true; 977 | return this.accordion(angle, anchor, options); 978 | }; 979 | 980 | OriDomi.prototype.stairs = function(angle, anchor, options) { 981 | if (options == null) { 982 | options = {}; 983 | } 984 | options.stairs = true; 985 | options.sticky = true; 986 | return this.accordion(angle, anchor, options); 987 | }; 988 | 989 | OriDomi.prototype.fracture = function(angle, anchor, options) { 990 | if (options == null) { 991 | options = {}; 992 | } 993 | options.fracture = true; 994 | return this.accordion(angle, anchor, options); 995 | }; 996 | 997 | OriDomi.prototype.twist = function(angle, anchor, options) { 998 | if (options == null) { 999 | options = {}; 1000 | } 1001 | options.fracture = true; 1002 | options.twist = true; 1003 | return this.accordion(angle / 10, anchor, options); 1004 | }; 1005 | 1006 | OriDomi.VERSION = '0.2.2'; 1007 | 1008 | OriDomi.isSupported = oriDomiSupport; 1009 | 1010 | OriDomi.devMode = function() { 1011 | return devMode = true; 1012 | }; 1013 | 1014 | return OriDomi; 1015 | 1016 | })(); 1017 | 1018 | root.OriDomi = OriDomi; 1019 | 1020 | if ($) { 1021 | $.fn.oriDomi = function(options) { 1022 | var args, el, instance, _i, _j, _len, _len1; 1023 | if (!oriDomiSupport) { 1024 | return this; 1025 | } 1026 | if (typeof options === 'string') { 1027 | if (typeof OriDomi.prototype[options] !== 'function') { 1028 | if (devMode) { 1029 | console.warn("oriDomi: No such method '" + options + "'"); 1030 | } 1031 | return; 1032 | } 1033 | for (_i = 0, _len = this.length; _i < _len; _i++) { 1034 | el = this[_i]; 1035 | instance = $.data(el, 'oriDomi'); 1036 | if (instance == null) { 1037 | if (devMode) { 1038 | console.warn("oriDomi: Can't call " + options + ", oriDomi hasn't been initialized on this element"); 1039 | } 1040 | return; 1041 | } 1042 | args = Array.prototype.slice.call(arguments); 1043 | args.shift(); 1044 | instance[options].apply(instance, args); 1045 | } 1046 | return this; 1047 | } else { 1048 | for (_j = 0, _len1 = this.length; _j < _len1; _j++) { 1049 | el = this[_j]; 1050 | instance = $.data(el, 'oriDomi'); 1051 | if (instance) { 1052 | return instance; 1053 | } else { 1054 | $.data(el, 'oriDomi', new OriDomi(el, options)); 1055 | } 1056 | } 1057 | return this; 1058 | } 1059 | }; 1060 | } 1061 | 1062 | }).call(this); 1063 | -------------------------------------------------------------------------------- /oridomi.coffee: -------------------------------------------------------------------------------- 1 | # [oriDomi](http://oridomi.com) 2 | # ============================= 3 | # #### by [Dan Motzenbecker](http://oxism.com) 4 | # Fold up the DOM like paper. 5 | 6 | # `0.2.2` 7 | 8 | # Copyright 2012, MIT License 9 | 10 | # Setup 11 | # ===== 12 | 13 | # Enable strict mode. 14 | 'use strict' 15 | 16 | # Set a reference to the global object within this scope. 17 | root = @ 18 | 19 | # An array to hold references to oriDomi instances so they can be easily freed 20 | # from memory via the `destroy()` method. 21 | instances = [] 22 | 23 | # Set a reference to jQuery (or another `$`-aliased DOM library). 24 | # If it doesn't exist, set to false so oriDomi knows we are working without jQuery. 25 | # oriDomi doesn't require it to work, but offers a useful plugin bridge. 26 | $ = root.$ or false 27 | 28 | # `devMode` determines whether oriDomi is vocal in the console with warnings and benchmarks. 29 | # Turn it on externally by calling `OriDomi.devMode()`. 30 | devMode = false 31 | 32 | # This variable is set to true and negated later if the browser does 33 | # not support oriDomi. 34 | oriDomiSupport = true 35 | 36 | # Create a div for testing CSS3 properties. 37 | testEl = document.createElement 'div' 38 | 39 | # Set a list of browser prefixes for testing CSS3 properties. 40 | prefixList = ['Webkit', 'Moz', 'O', 'ms', 'Khtml'] 41 | 42 | # A map of the CSS3 properties needed to support oriDomi, with shorthand names as keys. 43 | css = 44 | transform: 'transform' 45 | origin: 'transformOrigin' 46 | transformStyle: 'transformStyle' 47 | transitionProp: 'transitionProperty' 48 | transitionDuration: 'transitionDuration' 49 | transitionEasing: 'transitionTimingFunction' 50 | perspective: 'perspective' 51 | backface: 'backfaceVisibility' 52 | 53 | # This function checks for the presence of CSS properties on the test div. 54 | testProp = (prop) -> 55 | # Capitalize the property name for camel-casing. 56 | capProp = prop.charAt(0).toUpperCase() + prop.slice 1 57 | # Loop through the vendor prefix list and return when we find a match. 58 | for prefix in prefixList 59 | if testEl.style[prefix + capProp]? 60 | return prefix + capProp 61 | # If the un-prefixed property is present, return it. 62 | return prop if testEl.style[prop]? 63 | # If no matches are found, return false to denote that the browser is missing this property. 64 | false 65 | 66 | 67 | # Loop through the CSS hash and replace each value with the result of `testProp()`. 68 | for key, value of css 69 | css[key] = testProp value 70 | # If the returned value is false, warn the user that the browser doesn't support 71 | # oriDomi, set `oriDomiSupport` to false, and break out of the loop. 72 | unless css[key] 73 | console.warn 'oriDomi: Browser does not support oriDomi' if devMode 74 | oriDomiSupport = false 75 | break 76 | 77 | # CSS3 gradients are used for shading. 78 | # Testing for them is different because they are prefixed values, not properties. 79 | # This invokes an anonymous function to loop through vendor-prefixed linear-gradients. 80 | css.gradientProp = do -> 81 | for prefix in prefixList 82 | hyphenated = "-#{ prefix.toLowerCase() }-linear-gradient" 83 | testEl.style.backgroundImage = "#{ hyphenated }(left, #000, #fff)" 84 | # After setting a gradient background on the test div, attempt to retrieve it. 85 | unless testEl.style.backgroundImage.indexOf('gradient') is -1 86 | return hyphenated 87 | # If none of the hyphenated values worked, return the unprefixed version. 88 | 'linear-gradient' 89 | 90 | # The default cursor style is set to `grab` to prompt the user to interact with the element. 91 | [css.grab, css.grabbing] = do -> 92 | for prefix in prefixList 93 | plainGrab = 'grab' 94 | testEl.style.cursor = (grabValue = "-#{ prefix.toLowerCase() }-#{ plainGrab }") 95 | # If the cursor was set correctly, return the prefixed pair. 96 | return [grabValue, "-#{ prefix.toLowerCase() }-grabbing"] if testEl.style.cursor is grabValue 97 | # Otherwise try the unprefixed version. 98 | testEl.style.cursor = plainGrab 99 | if testEl.style.cursor is plainGrab 100 | [plainGrab, 'grabbing'] 101 | else 102 | # Fallback to `move`. 103 | ['move', 'move'] 104 | 105 | # Invoke a functional scope to set a hyphenated version of the transform property. 106 | css.transformProp = do -> 107 | # Use a regex to pluck the prefix `testProp` found. 108 | prefix = css.transform.match /(\w+)Transform/i 109 | if prefix 110 | "-#{ prefix[1].toLowerCase() }-transform" 111 | else 112 | 'transform' 113 | 114 | # Set a `transitionEnd` property based on the browser's prefix for `transitionProperty`. 115 | css.transitionEnd = do -> 116 | switch css.transitionProp 117 | when 'transitionProperty' 118 | 'transitionEnd' 119 | when 'WebkitTransitionProperty' 120 | 'webkitTransitionEnd' 121 | when 'MozTransitionProperty' 122 | 'transitionend' 123 | when 'OTransitionProperty' 124 | 'oTransitionEnd' 125 | when 'MSTransitionProperty' 126 | 'msTransitionEnd' 127 | 128 | 129 | # This function is used to extend option object literals with a set of defaults. 130 | # It is simple and one dimensional. 131 | extendObj = (target, source) -> 132 | # Check if the extension object is an object literal by casting it and comparing it. 133 | if source isnt Object source 134 | console.warn 'oriDomi: Must pass an object to extend with' if devMode 135 | # Return the original target if its source isn't valid. 136 | return target 137 | # If the target isn't an object, set it to an empty object literal. 138 | if target isnt Object target 139 | target = {} 140 | # Loop through the extension object and copy its values to the target if they don't exist. 141 | for prop of source 142 | if not target[prop]? 143 | target[prop] = source[prop] 144 | 145 | # Return the extended target object. 146 | target 147 | 148 | 149 | # Defaults 150 | # ======== 151 | 152 | # Empty function to be used as placeholder for callback defaults 153 | # (instead of creating separate empty functions). 154 | noOp = -> 155 | 156 | 157 | # Map of oriDomi instance defaults. 158 | defaults = 159 | # The number of vertical panels (for folding left or right). 160 | vPanels: 3 161 | # The number of horizontal panels (for folding top or bottom). 162 | hPanels: 3 163 | # The determines the distance in pixels (z axis) of the camera/viewer to the paper. 164 | # The smaller the value, the more distorted and exaggerated the effects will appear. 165 | perspective: 1000 166 | # The default shading style is hard, which shows distinct creases in the paper. 167 | # Other options include `'soft'` -- for a smoother, more rounded look -- or `false` 168 | # to disable shading altogether for a flat look. 169 | shading: 'hard' 170 | # Determines the duration of all animations in milliseconds. 171 | speed: 700 172 | # This CSS class is applied to elements that oriDomi has been invoked so they can be 173 | # easily targeted later if needed. 174 | oriDomiClass: 'oridomi' 175 | # This is a multiplier that determines the darkness of shading. 176 | # If you need subtler shading, set this to a value below 1. 177 | shadingIntensity: 1 178 | # This option allows you to supply the name of a custom easing method defined in one 179 | # of your stylesheets. It defaults to a blank string which is interpreted as `ease`. 180 | easingMethod: '' 181 | # To prevent a possible "flash of unstyled content" you can hide your target elements 182 | # and pass this setting as `true` to show them immediately after initializing them with oriDomi. 183 | showOnStart: false 184 | # Currently, Firefox doesn't handle edge anti-aliasing well and oriDomi edges look jagged. 185 | # This setting forces Firefox to smooth edges, but usually results in poor performance, 186 | # so it's not recommended for animation-heavy use of oriDomi until Firefox's transform performance improves. 187 | forceAntialiasing: false 188 | # Allow the user to fold the target by dragging a finger or the mouse. 189 | touchEnabled: true 190 | # Coefficient of touch/drag action's distance delta. Higher numbers cause more movement. 191 | touchSensitivity: .25 192 | # Custom callbacks for touch/drag events. Each one is invoked with a relevant value so they can 193 | # be used to manipulate objects outside of the oriDomi instance (e.g. sliding panels). 194 | # x values are returned when folding left and right, y values for top and bottom. 195 | # These are empty functions by default. 196 | # Invoked with starting coordinate as first argument. 197 | touchStartCallback: noOp 198 | # Invoked with current movement distance. 199 | touchMoveCallback: noOp 200 | # Inkoked with ending point. 201 | touchEndCallback: noOp 202 | 203 | 204 | # oriDomi Class 205 | # ============= 206 | 207 | class OriDomi 208 | # The constructor takes two arguments: a target element and an options object literal. 209 | constructor: (@el, options) -> 210 | # If `devMode` is enabled, start a benchmark timer for the constructor. 211 | console.time 'oridomiConstruction' if devMode 212 | # If the browser doesn't support oriDomi, return the element unmodified. 213 | return @el unless oriDomiSupport 214 | 215 | # If the constructor wasn't called with the `new` keyword, invoke it again. 216 | unless @ instanceof OriDomi 217 | return new oriDomi @el, @settings 218 | 219 | # Extend any passed options with the defaults map. 220 | @settings = extendObj options, defaults 221 | 222 | # Return if the first argument isn't a DOM element. 223 | if not @el or @el.nodeType isnt 1 224 | console.warn 'oriDomi: First argument must be a DOM element' if devMode 225 | return 226 | 227 | # Clone the target element and save a copy of it. 228 | @cleanEl = @el.cloneNode true 229 | @cleanEl.style.margin = '0' 230 | @cleanEl.style.position = 'absolute' 231 | # A much faster version of `display: none` when using hardware acceleration. 232 | @cleanEl.style[css.transform] = 'translate3d(-9999px, 0, 0)' 233 | 234 | # Destructure some instance variables from the settings object. 235 | {@shading, @shadingIntensity, @vPanels, @hPanels} = @settings 236 | # Record the current global styling of the target element. 237 | @_elStyle = root.getComputedStyle @el 238 | 239 | # Save the original CSS display of the target. If `none`, assume `block`. 240 | @displayStyle = @_elStyle.display 241 | @displayStyle = 'block' if @displayStyle is 'none' 242 | 243 | # To calculate the full dimensions of the element, create arrays of relevant metric keys. 244 | xMetrics = ['width', 'paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'] 245 | yMetrics = ['height', 'paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth'] 246 | 247 | # Add up values for width and height using `_getMetric()`. 248 | @width = 0 249 | @height = 0 250 | @width += @_getMetric metric for metric in xMetrics 251 | @height += @_getMetric metric for metric in yMetrics 252 | 253 | # Calculate the panel width and panel height by dividing the total width and 254 | # height by the requested number of panels in each axis. 255 | @panelWidth = @width / @vPanels 256 | @panelHeight = @height / @hPanels 257 | 258 | # Set our current fold angle at `0` and `isFoldedUp` as `false`. 259 | @lastAngle = 0 260 | @isFoldedUp = false 261 | # `isFrozen` records if the oriDomi effect is temporarily disabled for easier 262 | # manipulation of the target's inner contents later. 263 | @isFrozen = false 264 | # Set an array of anchor names. 265 | @anchors = ['left', 'right', 'top', 'bottom'] 266 | # oriDomi starts oriented with the left anchor. 267 | @lastAnchor = @anchors[0] 268 | # Create object literals to store panels and stages. 269 | @panels = {} 270 | @stages = {} 271 | # Create a stage div to serve as a prototype. 272 | stage = document.createElement 'div' 273 | # The stage should occupy the full width and height of the target element. 274 | stage.style.width = @width + 'px' 275 | stage.style.height = @height + 'px' 276 | # By default, each stage is hidden and absolutely positioned so they stack 277 | # on top of each other. 278 | stage.style.display = 'none' 279 | stage.style.position = 'absolute' 280 | # Eliminate padding and margins since the stage is already the full width and height. 281 | stage.style.padding = '0' 282 | stage.style.margin = '0' 283 | # Apply 3D perspective and preserve any parent perspective. 284 | stage.style[css.perspective] = @settings.perspective + 'px' 285 | stage.style[css.transformStyle] = 'preserve-3d' 286 | 287 | # Loop through the anchors list and create a stage and empty panel set for each. 288 | for anchor in @anchors 289 | @panels[anchor] = [] 290 | @stages[anchor] = stage.cloneNode false 291 | @stages[anchor].className = 'oridomi-stage-' + anchor 292 | 293 | # If shading is enabled, create an object literal to hold shaders. 294 | if @shading 295 | @shaders = {} 296 | # Loop through each anchor and create a nested object literal. 297 | # For the left and right anchors, create arrays to hold the left and right 298 | # shader for each panel. Do the same for top and bottom. 299 | for anchor in @anchors 300 | @shaders[anchor] = {} 301 | if anchor is 'left' or anchor is 'right' 302 | @shaders[anchor].left = [] 303 | @shaders[anchor].right = [] 304 | else 305 | @shaders[anchor].top = [] 306 | @shaders[anchor].bottom = [] 307 | 308 | # Create a shader div prototype to clone. 309 | shader = document.createElement 'div' 310 | shader.style[css.transitionProp] = 'opacity' 311 | shader.style[css.transitionDuration] = @settings.speed + 'ms' 312 | shader.style[css.transitionEasing] = @settings.easingMethod 313 | shader.style.position = 'absolute' 314 | shader.style.width = '100%' 315 | shader.style.height = '100%' 316 | shader.style.opacity = '0' 317 | shader.style.top = '0' 318 | shader.style.left = '0' 319 | shader.style.pointerEvents = 'none' 320 | 321 | # The content holder is a clone of the target element. 322 | # Every panel will contain one. 323 | contentHolder = @el.cloneNode true 324 | contentHolder.classList.add 'oridomi-content' 325 | contentHolder.style.margin = '0' 326 | contentHolder.style.position = 'relative' 327 | contentHolder.style.float = 'none' 328 | 329 | # Create a prototype mask div to clone. 330 | # Masks serve to display only a small offset portion of the content they hold. 331 | hMask = document.createElement 'div' 332 | hMask.className = 'oridomi-mask-h' 333 | hMask.style.position = 'absolute' 334 | hMask.style.overflow = 'hidden' 335 | hMask.style.width = '100%' 336 | hMask.style.height = '100%' 337 | # Adding `translate3d(0, 0, 0)` prevents flickering during transforms. 338 | hMask.style[css.transform] = 'translate3d(0, 0, 0)' 339 | # Add the `contentHolder` div to the mask prototype. 340 | hMask.appendChild contentHolder 341 | 342 | # If shading is enabled, create top and bottom shaders for the horizontal 343 | # mask prototype. 344 | if @shading 345 | topShader = shader.cloneNode false 346 | topShader.className = 'oridomi-shader-top' 347 | topShader.style.background = @_getShaderGradient 'top' 348 | bottomShader = shader.cloneNode false 349 | bottomShader.className = 'oridomi-shader-bottom' 350 | bottomShader.style.background = @_getShaderGradient 'bottom' 351 | hMask.appendChild topShader 352 | hMask.appendChild bottomShader 353 | 354 | # The bleed variable creates some overlap between the panels to prevent 355 | # cracks in the paper. 356 | bleed = 1.5 357 | # The panel element holds both its respective mask and all subsequent sibling panels. 358 | hPanel = document.createElement 'div' 359 | hPanel.className = 'oridomi-panel-h' 360 | hPanel.style.width = '100%' 361 | hPanel.style.height = @panelHeight + bleed + 'px' 362 | hPanel.style.padding = '0' 363 | hPanel.style.position = 'relative' 364 | # The panel element is the target of the transforms. 365 | hPanel.style[css.transitionProp] = css.transformProp 366 | hPanel.style[css.transitionDuration] = @settings.speed + 'ms' 367 | hPanel.style[css.transitionEasing] = @settings.easingMethod 368 | hPanel.style[css.origin] = 'top' 369 | hPanel.style[css.transformStyle] = 'preserve-3d' 370 | hPanel.style[css.backface] = 'hidden' 371 | 372 | # Apply a transparent border to force edge smoothing on Firefox. 373 | # (This setting hurts performance significantly.) 374 | if @settings.forceAntialiasing 375 | hPanel.style.outline = '1px solid transparent' 376 | 377 | # Add the horizontal mask prototype to the horizontal panel prototype. 378 | hPanel.appendChild hMask 379 | 380 | # Loop through just the horizontal anchors. 381 | for anchor in ['top', 'bottom'] 382 | # Loop through the number of horizontal panels. 383 | for i in [0...@hPanels] 384 | # Clone a copy of the panel prototype for manipulation. 385 | panel = hPanel.cloneNode true 386 | # Set a reference to its inner content. 387 | content = panel.getElementsByClassName('oridomi-content')[0] 388 | 389 | if anchor is 'top' 390 | # The `yOffset` shifts the content of the panel down so they appear contiguous. 391 | yOffset = -(i * @panelHeight) 392 | # This conditional pushes each panel's position down so they stack on top of each other. 393 | if i is 0 394 | panel.style.top = '0' 395 | else 396 | panel.style.top = @panelHeight + 'px' 397 | else 398 | # For bottom panels, make sure the transform origin is `'bottom'`. 399 | panel.style[css.origin] = 'bottom' 400 | # For the bottom `yOffset` and top position, we need to work backwards. 401 | yOffset = -((@hPanels * @panelHeight) - (@panelHeight * (i + 1))) 402 | 403 | if i is 0 404 | panel.style.top = @panelHeight * (@vPanels - 1) - bleed + 'px' 405 | else 406 | panel.style.top = -@panelHeight + 'px' 407 | 408 | content.style.top = yOffset + 'px' 409 | 410 | # Store references to the shader divs in the `shaders` object. 411 | if @shading 412 | @shaders[anchor].top[i] = panel.getElementsByClassName('oridomi-shader-top')[0] 413 | @shaders[anchor].bottom[i] = panel.getElementsByClassName('oridomi-shader-bottom')[0] 414 | 415 | # Store a reference to this panel in the `panels` object. 416 | @panels[anchor][i] = panel 417 | 418 | # Append each panel to its previous sibling (unless it's the first panel). 419 | @panels[anchor][i - 1].appendChild panel unless i is 0 420 | 421 | # Append the first panel (containing all of its siblings) to its respective stage. 422 | @stages[anchor].appendChild @panels[anchor][0] 423 | 424 | # Now that the horizontal panels are done, we can clone the `hMask` for the vertical mask prototype. 425 | vMask = hMask.cloneNode true 426 | vMask.className = 'oridomi-mask-v' 427 | 428 | # Create left and right shaders if applicable. 429 | if @shading 430 | leftShader = vMask.getElementsByClassName('oridomi-shader-top')[0] 431 | leftShader.className = 'oridomi-shader-left' 432 | leftShader.style.background = @_getShaderGradient 'left' 433 | rightShader = vMask.getElementsByClassName('oridomi-shader-bottom')[0] 434 | rightShader.className = 'oridomi-shader-right' 435 | rightShader.style.background = @_getShaderGradient 'right' 436 | 437 | # Clone the `hPanel` prototype and adjust its styling for vertical use. 438 | vPanel = hPanel.cloneNode false 439 | vPanel.className = 'oridomi-panel-v' 440 | vPanel.style.width = @panelWidth + bleed + 'px' 441 | vPanel.style.height = '100%' 442 | vPanel.style[css.origin] = 'left' 443 | vPanel.appendChild vMask 444 | 445 | # Repeat a similar panel creation process for vertical panels. 446 | for anchor in ['left', 'right'] 447 | for i in [0...@vPanels] 448 | panel = vPanel.cloneNode true 449 | content = panel.getElementsByClassName('oridomi-content')[0] 450 | 451 | if anchor is 'left' 452 | xOffset = -(i * @panelWidth) 453 | if i is 0 454 | panel.style.left = '0' 455 | else 456 | panel.style.left = @panelWidth + 'px' 457 | else 458 | panel.style[css.origin] = 'right' 459 | xOffset = -((@vPanels * @panelWidth) - (@panelWidth * (i + 1))) 460 | if i is 0 461 | panel.style.left = @panelWidth * (@vPanels - 1) - 1 + 'px' 462 | else 463 | panel.style.left = -@panelWidth + 'px' 464 | 465 | content.style.left = xOffset + 'px' 466 | 467 | if @shading 468 | @shaders[anchor].left[i] = panel.getElementsByClassName('oridomi-shader-left')[0] 469 | @shaders[anchor].right[i] = panel.getElementsByClassName('oridomi-shader-right')[0] 470 | 471 | @panels[anchor][i] = panel 472 | @panels[anchor][i - 1].appendChild panel unless i is 0 473 | 474 | @stages[anchor].appendChild @panels[anchor][0] 475 | 476 | 477 | # Add a special class to the target element. 478 | @el.classList.add @settings.oriDomiClass 479 | 480 | # Remove its padding and set a fixed width and height. 481 | @el.style.padding = '0' 482 | @el.style.width = @width + 'px' 483 | @el.style.height = @height + 'px' 484 | # Remove its background, border, and outline. 485 | @el.style.backgroundColor = 'transparent' 486 | @el.style.backgroundImage = 'none' 487 | @el.style.border = 'none' 488 | @el.style.outline = 'none' 489 | # Show the left stage to start with. 490 | @stages.left.style.display = 'block' 491 | 492 | # Create an element to hold stages. 493 | @stageEl = document.createElement 'div' 494 | # Array of event type pairs. 495 | eventPairs = [['TouchStart', 'MouseDown'], ['TouchEnd', 'MouseUp'], 496 | ['TouchMove', 'MouseMove'], ['TouchLeave', 'MouseLeave']] 497 | # Detect native `mouseleave` support. 498 | mouseLeaveSupport = 'onmouseleave' of window 499 | # Attach touch/drag event listeners in related pairs. 500 | for eventPair in eventPairs 501 | for eString in eventPair 502 | unless eString is 'TouchLeave' and not mouseLeaveSupport 503 | @stageEl.addEventListener eString.toLowerCase(), @['_on' + eventPair[0]], false 504 | else 505 | @stageEl.addEventListener 'mouseout', @['_onMouseOut'], false 506 | break 507 | 508 | @enableTouch() if @settings.touchEnabled 509 | 510 | # Append each stage to the target element. 511 | @stageEl.appendChild @stages[anchor] for anchor in @anchors 512 | 513 | # Show the target if applicable. 514 | if @settings.showOnStart 515 | @el.style.display = 'block' 516 | @el.style.visibility = 'visible' 517 | 518 | # Hide the original content and insert the oriDomi version. 519 | @el.innerHTML = '' 520 | @el.appendChild @cleanEl 521 | @el.appendChild @stageEl 522 | 523 | # These properties record starting angles for touch/drag events. 524 | # Initialize both to zero. 525 | [@_xLast, @_yLast] = [0, 0] 526 | # This property determines the effect used during touch/drag events. 527 | @lastOp = method: 'accordion', options: {} 528 | 529 | # Cache a jQuery object of the element if applicable. 530 | @$el = $ @el if $ 531 | # Push this instance into the instances collection. 532 | instances.push @ 533 | # If a callback was passed in the constructor options, run it. 534 | @_callback @settings 535 | # End the constructor benchmark if `devMode` is active. 536 | console.timeEnd 'oridomiConstruction' if devMode 537 | 538 | 539 | # Internal Methods 540 | # ================ 541 | 542 | # `_callback` normalizes callback handling for all public methods. 543 | _callback: (options) -> 544 | if typeof options.callback is 'function' 545 | # Create a local callback for the animation's end. 546 | onTransitionEnd = (e) => 547 | # Remove the event listener immediately to prevent bubbling. 548 | e.currentTarget.removeEventListener css.transitionEnd, onTransitionEnd, false 549 | # Invoke the callback. 550 | options.callback() 551 | 552 | # If there was no transformation (0 degrees) invoke the callback immediately. 553 | if @lastAngle is 0 554 | options.callback() 555 | # Otherwise, attach an event listener to be called on the transition's end. 556 | else 557 | @panels[@lastAnchor][0].addEventListener css.transitionEnd, onTransitionEnd, false 558 | 559 | 560 | # `_getMetric` returns an integer of pixels for a style key. 561 | _getMetric: (metric) -> 562 | parseInt @_elStyle[metric], 10 563 | 564 | 565 | # `_transform` returns a `rotate3d` transform string based on the anchor and angle. 566 | _transform: (angle, fracture) -> 567 | switch @lastAnchor 568 | when 'left' 569 | axes = [0, 1, 0, angle] 570 | when 'right' 571 | axes = [0, 1, 0, -angle] 572 | when 'top' 573 | axes = [1, 0, 0, -angle] 574 | when 'bottom' 575 | axes = [1, 0, 0, angle] 576 | 577 | # `fracture` is a special option that splits up the panels by rotating them on all axes. 578 | if fracture 579 | [axes[0], axes[1], axes[2]] = [1, 1, 1] 580 | 581 | "rotate3d(#{ axes[0] }, #{ axes[1] }, #{ axes[2] }, #{ axes[3] }deg)" 582 | 583 | 584 | # `_normalizeAngle` validates a given angle by making sure it's a float and by 585 | # keeping it within a range of -89/89 degrees. Fully 90 degree angles tend to look glitchy. 586 | _normalizeAngle: (angle) -> 587 | angle = parseFloat angle, 10 588 | if isNaN angle 589 | 0 590 | else if angle > 89 591 | 89 592 | else if angle < -89 593 | -89 594 | else 595 | angle 596 | 597 | 598 | # `_normalizeArgs` normalizes every public method's arguments and makes sure the current 599 | # axis unfolds if ordered to switch to another axis. 600 | _normalizeArgs: (method, args) -> 601 | @unfreeze() if @isFrozen 602 | # Get a valid angle. 603 | angle = @_normalizeAngle args[0] 604 | # Get the full anchor name. 605 | anchor = @_getLonghandAnchor args[1] or @lastAnchor 606 | # Extend the given options with the method's defaults. 607 | options = extendObj args[2], @_methodDefaults[method] 608 | # Store a record of this operation for future touch events. 609 | @lastOp = method: method, options: options, negative: angle < 0 610 | 611 | # If the user is trying to transform using a different anchor, we must first 612 | # unfold the current anchor for transition purposes. 613 | if anchor isnt @lastAnchor or (method is 'foldUp' and @lastAngle isnt 0) or @isFoldedUp 614 | # Call `reset` and pass a callback to be run when the unfolding is complete. 615 | @reset => 616 | # Show the stage element of the originally requested anchor. 617 | @_showStage anchor 618 | # Since the anchor changed, update the mouse drag cursor. 619 | @_setCursor() if @_touchEnabled 620 | # Defer this operation until the next event loop to prevent a sudden jump. 621 | setTimeout => 622 | # `foldUp` is a special method that doesn't accept an angle argument. 623 | args.shift() if method is 'foldUp' 624 | # We can now call the originally requested method. 625 | @[method].apply @, args 626 | 627 | , 0 628 | 629 | # Return `false` here to inform the caller method to abort its operation 630 | # and wait to be called when the stage is ready. 631 | false 632 | else 633 | # Set an instance reference to the last called angle and return the normalized arguments. 634 | @lastAngle = angle 635 | [angle, anchor, options] 636 | 637 | 638 | # `_setShader` determines a shader's opacity based upon panel position, anchor, and angle. 639 | _setShader: (i, anchor, angle) -> 640 | # Store the angle's absolute value and generate an opacity based on `shadingIntensity`. 641 | abs = Math.abs angle 642 | opacity = abs / 90 * @shadingIntensity 643 | 644 | # With hard shading, opacity is reduced and `angle` is based on the global 645 | # `lastAngle` so all panels' shaders share the same direction. Soft shaders 646 | # have alternating directions. 647 | if @shading is 'hard' 648 | opacity *= .15 649 | if @lastAngle < 0 650 | angle = abs 651 | else 652 | angle = -abs 653 | else 654 | opacity *= .4 655 | 656 | # This block makes sure left and top shaders appear for negative angles and right 657 | # and bottom shaders appear for positive ones. 658 | switch anchor 659 | when 'left', 'top' 660 | if angle < 0 661 | a = opacity 662 | b = 0 663 | else 664 | a = 0 665 | b = opacity 666 | when 'right', 'bottom' 667 | if angle < 0 668 | a = 0 669 | b = opacity 670 | else 671 | a = opacity 672 | b = 0 673 | 674 | # Only manipulate shader opacity for the current axis. 675 | if anchor is 'left' or anchor is 'right' 676 | @shaders[anchor].left[i].style.opacity = a 677 | @shaders[anchor].right[i].style.opacity = b 678 | else 679 | @shaders[anchor].top[i].style.opacity = a 680 | @shaders[anchor].bottom[i].style.opacity = b 681 | 682 | 683 | # This is a simple method used by the constructor to set CSS gradient styles. 684 | # It accepts an anchor argument to start the gradient slope. 685 | _getShaderGradient: (anchor) -> 686 | "#{ css.gradientProp }(#{ anchor }, rgba(0, 0, 0, .5) 0%, rgba(255, 255, 255, .35) 100%)" 687 | 688 | 689 | # This method shows the requested stage element and sets a reference to it as 690 | # the current stage. 691 | _showStage: (anchor) -> 692 | if anchor isnt @lastAnchor 693 | @stages[anchor].style.display = 'block' 694 | @stages[@lastAnchor].style.display = 'none' 695 | @lastAnchor = anchor 696 | 697 | 698 | # Simple method that returns the correct panel set based on an anchor. 699 | _getPanelType: (anchor) -> 700 | if anchor is 'left' or anchor is 'right' 701 | @vPanels 702 | else 703 | @hPanels 704 | 705 | 706 | # Converts a shorthand anchor name to a full one. 707 | _getLonghandAnchor: (shorthand) -> 708 | switch shorthand 709 | when 'left', 'l', '4', 4 710 | 'left' 711 | when 'right', 'r', '2', 2 712 | 'right' 713 | when 'top', 't', '1', 1 714 | 'top' 715 | when 'bottom', 'b', '3', 3 716 | 'bottom' 717 | else 718 | # Left is always default. 719 | 'left' 720 | 721 | 722 | # Allows other methods to change the tween duration or disable it altogether. 723 | _setTweening: (speed) -> 724 | # If the speed value is `true` reset the speed to the original settings. 725 | # Set it to zero if `false`. 726 | if typeof speed is 'boolean' 727 | speed = if speed then @settings.speed + 'ms' else '0ms' 728 | 729 | # To loop through the shaders, derive the correct pair from the current anchor. 730 | if @lastAnchor is 'left' or @lastAnchor is 'right' 731 | shaderPair = ['left', 'right'] 732 | else 733 | shaderPair = ['top', 'bottom'] 734 | 735 | # Loop through the panels in this anchor and set the transition duration to the new speed. 736 | for panel, i in @panels[@lastAnchor] 737 | panel.style[css.transitionDuration] = speed 738 | if @shading 739 | @shaders[@lastAnchor][shaderPair[0]][i].style[css.transitionDuration] = speed 740 | @shaders[@lastAnchor][shaderPair[1]][i].style[css.transitionDuration] = speed 741 | 742 | # Return null and not the loop's result. 743 | null 744 | 745 | 746 | # Gives the element a resize cursor to prompt the user to drag the mouse. 747 | _setCursor: -> 748 | if @_touchEnabled 749 | @stageEl.style.cursor = css.grab 750 | else 751 | @stageEl.style.cursor = 'default' 752 | 753 | 754 | # Map of defaults for each method. Some are empty for now. 755 | _methodDefaults: 756 | accordion: 757 | # Sticky keeps the first panel flat on the page. 758 | sticky: false 759 | # Stairs creates a stairway effect. 760 | stairs: false 761 | # Twist and fracture are similar effects that result in wild non-origami-like splits. 762 | fracture: false 763 | twist: false 764 | curl: 765 | twist: false 766 | ramp: {} 767 | foldUp: {} 768 | 769 | 770 | # Touch / Drag Event Handlers 771 | # =========================== 772 | 773 | 774 | # This method is called when a finger or mouse button is pressed on the element. 775 | _onTouchStart: (e) => 776 | return unless @_touchEnabled 777 | e.preventDefault() 778 | # Set a property to track touch starts. 779 | @_touchStarted = true 780 | # Change the cursor to the active `grabbing` state. 781 | @stageEl.style.cursor = css.grabbing 782 | # Disable tweening to enable instant 1 to 1 movement. 783 | @_setTweening false 784 | # Derive the axis to fold on. 785 | @_touchAxis = if @lastAnchor is 'left' or @lastAnchor is 'right' then 'x' else 'y' 786 | # Set a reference to the last folded angle to accurately derive deltas. 787 | @["_#{ @_touchAxis }Last"] = @lastAngle 788 | 789 | # Determine the starting tap's coordinate for touch and mouse events. 790 | if e.type is 'mousedown' 791 | @["_#{ @_touchAxis }1"] = e["page#{ @_touchAxis.toUpperCase() }"] 792 | else 793 | @["_#{ @_touchAxis }1"] = e.targetTouches[0]["page#{ @_touchAxis.toUpperCase() }"] 794 | 795 | # Return that value to an external listener. 796 | @settings.touchStartCallback @["_#{ @_touchAxis }1"] 797 | 798 | 799 | # Called on touch/mouse movement. 800 | _onTouchMove: (e) => 801 | return unless @_touchEnabled and @_touchStarted 802 | e.preventDefault() 803 | # Set a reference to the current x or y position. 804 | if e.type is 'mousemove' 805 | current = e["page#{ @_touchAxis.toUpperCase() }"] 806 | else 807 | current = e.targetTouches[0]["page#{ @_touchAxis.toUpperCase() }"] 808 | 809 | # Calculate distance and multiply by `touchSensitivity`. 810 | distance = (current - @["_#{ @_touchAxis }1"]) * @settings.touchSensitivity 811 | 812 | # Calculate final delta based on starting angle, anchor, and what side of zero 813 | # the last operation was on. 814 | if @lastOp.negative 815 | if @lastAnchor is 'right' or @lastAnchor is 'bottom' 816 | delta = @["_#{ @_touchAxis }Last"] - distance 817 | else 818 | delta = @["_#{ @_touchAxis }Last"] + distance 819 | delta = 0 if delta > 0 820 | else 821 | if @lastAnchor is 'right' or @lastAnchor is 'bottom' 822 | delta = @["_#{ @_touchAxis }Last"] + distance 823 | else 824 | delta = @["_#{ @_touchAxis }Last"] - distance 825 | delta = 0 if delta < 0 826 | 827 | # Invoke the effect method with the delta as an angle argument. 828 | @[@lastOp.method] delta, @lastAnchor, @lastOp.options 829 | # Pass the delta to the movement callback. 830 | @settings.touchMoveCallback delta 831 | 832 | 833 | # Teardown process when touch/drag event ends. 834 | _onTouchEnd: => 835 | return unless @_touchEnabled 836 | # Restore the initial touch status and cursor. 837 | @_touchStarted = false 838 | @stageEl.style.cursor = css.grab 839 | # Enable tweening again. 840 | @_setTweening true 841 | # Pass callback final value. 842 | @settings.touchEndCallback @["_#{ @_touchAxis }Last"] 843 | 844 | 845 | # End folding when the mouse or finger leaves the composition. 846 | _onTouchLeave: => 847 | return unless @_touchEnabled and @_touchStarted 848 | @_onTouchEnd() 849 | 850 | 851 | # A fallback for browsers that don't support `mouseleave`. 852 | _onMouseOut: (e) => 853 | return unless @_touchEnabled and @_touchStarted 854 | @_onTouchEnd() if e.toElement and not @el.contains e.toElement 855 | 856 | 857 | # Public Methods 858 | # ============== 859 | 860 | 861 | # Reset handles resetting all panels back to zero degrees. 862 | reset: (callback) -> 863 | # If the stage is folded up, unfold it first. 864 | return @unfold callback if @isFoldedUp 865 | 866 | for panel, i in @panels[@lastAnchor] 867 | panel.style[css.transform] = @_transform 0 868 | @_setShader i, @lastAnchor, 0 if @shading 869 | 870 | # When called internally, `reset` comes with a callback to advance to the next transformation. 871 | @_callback callback: callback 872 | 873 | 874 | # Disables oriDomi slicing by showing the original, untouched target element. 875 | # This is useful for certain user interactions on the inner content. 876 | freeze: (callback) -> 877 | # Return if already frozen. 878 | if @isFrozen 879 | callback?() 880 | else 881 | # Make sure to reset folding first. 882 | @reset => 883 | @isFrozen = true 884 | # Swap the visibility of the elements. 885 | @stageEl.style[css.transform] = 'translate3d(-9999px, 0, 0)' 886 | @cleanEl.style[css.transform] = 'translate3d(0, 0, 0)' 887 | callback?() 888 | 889 | 890 | # Restores the oriDomi version of the element for folding purposes. 891 | unfreeze: -> 892 | # Only unfreeze if already frozen. 893 | if @isFrozen 894 | @isFrozen = false 895 | # Swap the visibility of the elements. 896 | @cleanEl.style[css.transform] = 'translate3d(-9999px, 0, 0)' 897 | @stageEl.style[css.transform] = 'translate3d(0, 0, 0)' 898 | # Set `lastAngle` to 0 so an immediately subsequent call to `freeze` triggers the callback. 899 | @lastAngle = 0 900 | 901 | 902 | # Removes the oriDomi element and marks its instance for garbage collection. 903 | destroy: (callback) -> 904 | # First restore the original element. 905 | @freeze => 906 | # Remove event listeners. 907 | @stageEl.removeEventListener 'touchstart', @_onTouchStart, false 908 | @stageEl.removeEventListener 'mousedown', @_onTouchStart, false 909 | @stageEl.removeEventListener 'touchend', @_onTouchEnd, false 910 | @stageEl.removeEventListener 'mouseup', @_onTouchEnd, false 911 | 912 | # Remove the data reference if using jQuery. 913 | $.data @el, 'oriDomi', null if $ 914 | # Remove the oriDomi element from the DOM. 915 | @el.innerHTML = @cleanEl.innerHTML 916 | 917 | # Reset original styles. 918 | changedKeys = ['padding', 'width', 'height', 'backgroundColor', 'backgroundImage', 'border', 'outline'] 919 | @el.style[key] = @_elStyle[key] for key in changedKeys 920 | 921 | # Free up this instance for garbage collection. 922 | instances[instances.indexOf @] = null 923 | callback?() 924 | 925 | 926 | # Enables touch events and sets cursor. 927 | enableTouch: -> 928 | @_touchEnabled = true 929 | @_setCursor() 930 | 931 | 932 | # Disables touch events. 933 | disableTouch: -> 934 | @_touchEnabled = false 935 | @_setCursor() 936 | 937 | 938 | # oriDomi's most basic effect. Transforms the target like its namesake. 939 | accordion: (angle, anchor, options) -> 940 | normalized = @_normalizeArgs 'accordion', arguments 941 | # If `_normalizeArgs` returns false, we need to abort for a reset operation. 942 | return unless normalized 943 | # Otherwise, destructure the normalized arguments into some local variables. 944 | [angle, anchor, options] = normalized 945 | 946 | # Loop through the panels in this stage. 947 | for panel, i in @panels[anchor] 948 | 949 | # If it's an odd-numbered panel, reverse the angle. 950 | if i % 2 isnt 0 and not options.twist 951 | deg = -angle 952 | else 953 | deg = angle 954 | 955 | # If sticky, keep the first panel flat. 956 | if options.sticky 957 | if i is 0 958 | deg = 0 959 | else if i > 1 or options.stairs 960 | deg *= 2 961 | else 962 | # Double the angle to counteract the angle of the parent panel. 963 | deg *= 2 unless i is 0 964 | 965 | # In stairs mode, keep all the angles on the same side of 0. 966 | if options.stairs 967 | deg = -deg 968 | 969 | # Set the CSS transformation. 970 | panel.style[css.transform] = @_transform deg, options.fracture 971 | # Apply shaders. 972 | if @shading and !(i is 0 and options.sticky) and Math.abs(deg) isnt 180 973 | @_setShader i, anchor, deg 974 | 975 | # Ask `_callback` to check for a callback. 976 | @_callback options 977 | 978 | 979 | # `curl` appears to bend rather than fold the paper. Its curves can appear smoother 980 | # with higher panel counts. 981 | curl: (angle, anchor, options) -> 982 | normalized = @_normalizeArgs 'curl', arguments 983 | return unless normalized 984 | [angle, anchor, options] = normalized 985 | # Reduce the angle based on the number of panels in this axis. 986 | angle /= @_getPanelType anchor 987 | 988 | for panel, i in @panels[anchor] 989 | panel.style[css.transform] = @_transform angle 990 | @_setShader i, anchor, 0 if @shading 991 | 992 | @_callback options 993 | 994 | 995 | # `ramp` lifts up all panels after the first one. 996 | ramp: (angle, anchor, options) -> 997 | normalized = @_normalizeArgs 'ramp', arguments 998 | return unless normalized 999 | [angle, anchor, options] = normalized 1000 | # Rotate the second panel for the lift up. 1001 | @panels[anchor][1].style[css.transform] = @_transform angle 1002 | 1003 | # For all but the first two panels, set the angle to 0. 1004 | for panel, i in @panels[anchor] 1005 | if i > 1 1006 | @panels[anchor][i].style[css.transform] = @_transform 0 1007 | 1008 | if @shading 1009 | @_setShader i, anchor, 0 1010 | 1011 | @_callback options 1012 | 1013 | 1014 | # `foldUp` folds up all panels in separate synchronous animations. 1015 | foldUp: (anchor, callback) -> 1016 | # Default to left anchor. 1017 | unless anchor 1018 | anchor = 'left' 1019 | # Check if callback is the first argument. 1020 | else if typeof anchor is 'function' 1021 | callback = anchor 1022 | 1023 | # `foldUp` uses irregular arguments, so we manually construct the arguments array. 1024 | normalized = @_normalizeArgs 'foldUp', [0, anchor, {}] 1025 | return unless normalized 1026 | anchor = normalized[1] 1027 | # Set `isFoldedUp` to `true` so we are forced to unfold before calling other methods. 1028 | @isFoldedUp = true 1029 | # Start an iterator at the last panel in this anchor. 1030 | i = @panels[anchor].length - 1 1031 | # Rotate 100 degrees. 1032 | angle = 100 1033 | 1034 | # Local function that sets an event listener on the current panel and transforms it. 1035 | nextPanel = => 1036 | @panels[anchor][i].addEventListener css.transitionEnd, onTransitionEnd, false 1037 | @panels[anchor][i].style[css.transform] = @_transform angle 1038 | @_setShader i, anchor, angle if @shading 1039 | 1040 | # Called when each panel finishes folding in. 1041 | onTransitionEnd = (e) => 1042 | # Remove the listener. 1043 | @panels[anchor][i].removeEventListener css.transitionEnd, onTransitionEnd, false 1044 | # Hide the panel so it doesn't collide when bending around. 1045 | @panels[anchor][i].style.display = 'none' 1046 | # Decrement the iterator and check if we're on the first panel. 1047 | if --i is 0 1048 | # If so, invoke the callback directly if applicable. 1049 | callback?() 1050 | else 1051 | # Otherwise, defer until the next event loop and fold back the next panel. 1052 | setTimeout nextPanel, 0 1053 | 1054 | # Start the chain of folds. 1055 | nextPanel() 1056 | 1057 | 1058 | # Essentially the inverse of `foldUp`. 1059 | unfold: (callback) -> 1060 | # If the target isn't folded up, there's no reason to call this method and 1061 | # the callback is immediately invoked. 1062 | callback?() unless @isFoldedUp 1063 | 1064 | # Reset `isFoldedUp`. 1065 | @isFoldedUp = false 1066 | # Start the iterator on the second panel. 1067 | i = 1 1068 | # Rotate back to 0. 1069 | angle = 0 1070 | 1071 | nextPanel = => 1072 | # Show the panel again. 1073 | @panels[@lastAnchor][i].style.display = 'block' 1074 | # Wait for the next event loop so the transition listener works. 1075 | setTimeout => 1076 | @panels[@lastAnchor][i].addEventListener css.transitionEnd, onTransitionEnd, false 1077 | @panels[@lastAnchor][i].style[css.transform] = @_transform angle 1078 | @_setShader i, @lastAnchor, angle if @shading 1079 | , 0 1080 | 1081 | onTransitionEnd = (e) => 1082 | @panels[@lastAnchor][i].removeEventListener css.transitionEnd, onTransitionEnd, false 1083 | # Increment the iterator and check if we're past the last panel. 1084 | if ++i is @panels[@lastAnchor].length 1085 | callback?() 1086 | else 1087 | setTimeout nextPanel, 0 1088 | 1089 | # Start the sequence. 1090 | nextPanel() 1091 | 1092 | 1093 | # Convenience Methods 1094 | # =================== 1095 | 1096 | 1097 | # Completely folds in target. 1098 | collapse: (anchor, options = {}) -> 1099 | options.sticky = false 1100 | @accordion -89, anchor, options 1101 | 1102 | 1103 | # Same as `collapse`, but uses negative angle for slightly different effect. 1104 | collapseAlt: (anchor, options = {}) -> 1105 | options.sticky = false 1106 | @accordion 89, anchor, options 1107 | 1108 | 1109 | # Simply proxy for calling `accordion` with `sticky` enabled. 1110 | # Keeps first panel flat on page. 1111 | reveal: (angle, anchor, options = {}) -> 1112 | options.sticky = true 1113 | @accordion angle, anchor, options 1114 | 1115 | 1116 | # Proxy to enable stairs mode on `accordion`. 1117 | stairs: (angle, anchor, options = {}) -> 1118 | options.stairs = true 1119 | options.sticky = true 1120 | @accordion angle, anchor, options 1121 | 1122 | 1123 | # `fracture: true` proxy. 1124 | fracture: (angle, anchor, options = {}) -> 1125 | options.fracture = true 1126 | @accordion angle, anchor, options 1127 | 1128 | 1129 | # `twist: true` proxy. 1130 | twist: (angle, anchor, options = {}) -> 1131 | options.fracture = true 1132 | options.twist = true 1133 | @accordion angle / 10, anchor, options 1134 | 1135 | 1136 | # Class Members 1137 | # ============= 1138 | 1139 | 1140 | # Set a version flag for easy external retrieval. 1141 | @VERSION = '0.2.2' 1142 | 1143 | 1144 | # Externally check if oriDomi is supported by the browser. 1145 | @isSupported = oriDomiSupport 1146 | 1147 | 1148 | # External function to enable `devMode`. 1149 | @devMode = -> devMode = true 1150 | 1151 | # Attach `OriDomi` constructor to `window`. 1152 | root.OriDomi = OriDomi 1153 | 1154 | 1155 | # Plugin Bridge 1156 | # ============= 1157 | 1158 | 1159 | # Only create bridge if jQuery (or the like) exists. 1160 | if $ 1161 | # Attach an `oriDomi` method to `$`'s prototype. 1162 | $.fn.oriDomi = (options) -> 1163 | # Return selection if oriDomi is unsupported by the browser. 1164 | return @ unless oriDomiSupport 1165 | 1166 | # If `options` is a string, assume it's a method call. 1167 | if typeof options is 'string' 1168 | 1169 | # Check if method exists and warn if it doesn't. 1170 | unless typeof OriDomi::[options] is 'function' 1171 | console.warn "oriDomi: No such method '#{ options }'" if devMode 1172 | return 1173 | 1174 | # Loop through the jQuery selection. 1175 | for el in @ 1176 | # Retrieve the instance of oriDomi attached to the element. 1177 | instance = $.data el, 'oriDomi' 1178 | 1179 | # Warn if oriDomi hasn't been initialized on this element. 1180 | unless instance? 1181 | console.warn "oriDomi: Can't call #{ options }, oriDomi hasn't been initialized on this element" if devMode 1182 | return 1183 | 1184 | # Convert arguments to a proper array and remove the first element. 1185 | args = Array::slice.call arguments 1186 | args.shift() 1187 | # Call the requested method with arguments. 1188 | instance[options].apply instance, args 1189 | 1190 | # Return selection. 1191 | @ 1192 | 1193 | # If not calling a method, initialize oriDomi on the selection. 1194 | else 1195 | for el in @ 1196 | # If the element in the selection already has an instance of oriDomi 1197 | # attached to it, return the instance. 1198 | instance = $.data el, 'oriDomi' 1199 | if instance 1200 | return instance 1201 | else 1202 | # Create an instance of oriDomi and attach it to the element. 1203 | $.data el, 'oriDomi', new OriDomi el, options 1204 | 1205 | # Return the selection. 1206 | @ 1207 | --------------------------------------------------------------------------------