├── .editorconfig ├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── code-examples ├── cube-apply-rotation-2.js ├── cube-apply-rotation-options-2.js ├── cube-apply-rotation-options.js ├── cube-apply-rotation.js ├── cube-custom-styles.css ├── cube-focus-on-2.js ├── cube-focus-on-3.js ├── cube-focus-on-4.js ├── cube-focus-on-options.js ├── cube-focus-on.js ├── cube-init.js ├── cube-rotate-2.js ├── cube-rotate-3.js ├── cube-rotate-options.js ├── cube-rotate.js └── cube.html ├── config.rb ├── cube-js-docco ├── cube.html ├── docco.css └── public │ ├── fonts │ ├── aller-bold.eot │ ├── aller-bold.ttf │ ├── aller-bold.woff │ ├── aller-light.eot │ ├── aller-light.ttf │ ├── aller-light.woff │ ├── novecento-bold.eot │ ├── novecento-bold.ttf │ └── novecento-bold.woff │ └── stylesheets │ └── normalize.css ├── cube.css ├── cube.js ├── cube.min.js ├── cube.scss ├── docco-css └── docco.css ├── images └── cube │ ├── cube-texture.jpg │ ├── cube-texture.png │ ├── cube-texture.psd │ └── cube-texture.zip ├── index.html └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tabs 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *~ 11 | 12 | # OS or Editor folders 13 | .DS_Store 14 | ._* 15 | Thumbs.db 16 | .cache 17 | .project 18 | .settings 19 | .tmproj 20 | *.esproj 21 | nbproject 22 | *.sublime-project 23 | *.sublime-workspace 24 | .idea 25 | 26 | # Folders to ignore 27 | node_modules 28 | bower_components 29 | 30 | # Sass related 31 | .sass-cache 32 | .ruby-version 33 | .ruby-gemset 34 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | // Project configuration. 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | 6 | sass: { 7 | cube: { 8 | options: { 9 | compass: true, 10 | style: 'expanded' 11 | }, 12 | 13 | files: { 14 | 'cube.css': 'cube.scss' 15 | } 16 | }, 17 | 18 | page: { 19 | options: { 20 | compass: true, 21 | style: 'compressed' 22 | }, 23 | 24 | files: { 25 | 'gh-pages-css/main.css': 'gh-pages-scss/main.scss' 26 | } 27 | } 28 | }, 29 | 30 | jshint: { 31 | files: ['cube.js', 'gh-pages-js/generate-nav.js'] 32 | }, 33 | 34 | uglify: { 35 | cube: { 36 | files: { 37 | 'cube.min.js': 'cube.js' 38 | } 39 | } 40 | }, 41 | 42 | docco: { 43 | cube: { 44 | src: ['cube.js'], 45 | options: { 46 | output: 'cube-js-docco', 47 | css: 'docco-css/docco.css' 48 | } 49 | } 50 | }, 51 | 52 | watch: { 53 | html: { 54 | files: ['*.html'], 55 | options: { livereload: true } 56 | }, 57 | 58 | css: { 59 | files: ['*.css', 'gh-pages-css/main.css'], 60 | options: { livereload: true } 61 | }, 62 | 63 | cubeSass: { 64 | files: ['cube.scss'], 65 | tasks: ['sass:cube'] 66 | }, 67 | 68 | pageSass: { 69 | files: ['gh-pages-scss/main.scss'], 70 | tasks: ['sass:page'] 71 | }, 72 | 73 | cubeJs: { 74 | files: ['cube.js'], 75 | tasks: ['jshint', 'docco:cube', 'uglify:cube'], 76 | options: { livereload: true } 77 | }, 78 | 79 | pagesJs: { 80 | files: ['gh-pages-js/*.js'], 81 | tasks: ['jshint'], 82 | options: { livereload: true } 83 | } 84 | } 85 | }); 86 | 87 | // Load the plugin(s). 88 | grunt.loadNpmTasks('grunt-contrib-sass'); 89 | grunt.loadNpmTasks('grunt-contrib-watch'); 90 | grunt.loadNpmTasks('grunt-contrib-jshint'); 91 | grunt.loadNpmTasks('grunt-contrib-uglify'); 92 | grunt.loadNpmTasks('grunt-docco'); 93 | 94 | // Task(s). 95 | grunt.registerTask('default', ['watch']); 96 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 XHTMLized Pty Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cube.js 2 | 3 | cube.js is a light script which allows you to add a fancy rotating CSS3 cube to your page! 4 | 5 | Please check the cube's page for more information and examples. 6 | 7 | You can find cube.js documentation here. 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /code-examples/cube-apply-rotation-2.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube2a'); 2 | 3 | // Set the cube's postion 4 | myCube.applyRotation({ side: 'side-5' }); -------------------------------------------------------------------------------- /code-examples/cube-apply-rotation-options-2.js: -------------------------------------------------------------------------------- 1 | { side: ['side-1', 'side-2', …, or 'side-6'] } -------------------------------------------------------------------------------- /code-examples/cube-apply-rotation-options.js: -------------------------------------------------------------------------------- 1 | { 2 | x: [number from 0 to 360], 3 | y: [number from 0 to 360], 4 | z: [number from 0 to 360] 5 | } -------------------------------------------------------------------------------- /code-examples/cube-apply-rotation.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube2'); 2 | 3 | // Set the cube's postion 4 | myCube.applyRotation({ 5 | x: 45, 6 | y: 30, 7 | z: 270 8 | }); -------------------------------------------------------------------------------- /code-examples/cube-custom-styles.css: -------------------------------------------------------------------------------- 1 | .the-cube { 2 | margin: 80px auto; 3 | } 4 | 5 | .the-cube > span { 6 | background-image: url(../images/cube/cube-texture.jpg); 7 | } -------------------------------------------------------------------------------- /code-examples/cube-focus-on-2.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube4a'); 2 | 3 | // Cube will spin to the selected side 4 | myCube.focusOn({ 5 | spinTo: 'side-5' 6 | }); -------------------------------------------------------------------------------- /code-examples/cube-focus-on-3.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube4b'); 2 | 3 | // Cube will spin to the selected side 4 | // and back to the previous position 5 | myCube.focusOn({ 6 | bounceBack: true, 7 | spinToX: 33, 8 | spinToY: 88, 9 | spinToZ: 289 10 | }); -------------------------------------------------------------------------------- /code-examples/cube-focus-on-4.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube4c'); 2 | 3 | // Start rotating 4 | myCube.rotate({ 5 | startSide: 'side-3', 6 | speedX: 0, // 5 seconds to rotate by 360 degrees 7 | speedY: 10000, // 20 seconds to rotate by 360 degrees 8 | speedZ: 10000, // 10 seconds to rotate by 360 degrees 9 | rotateDir: 'left' 10 | }); 11 | 12 | 13 | // Cube will spin to the selected side 14 | // and back to the previous position 15 | myCube.focusOn({ 16 | bounceBack: true, 17 | spinTo: 'side-1' 18 | }); -------------------------------------------------------------------------------- /code-examples/cube-focus-on-options.js: -------------------------------------------------------------------------------- 1 | { 2 | bounceBack: true, 3 | spinTo: ['side-1', 'side-2', …, or 'side-6'], 4 | spinToX: [number from 0 to 360], 5 | spinToY: [number from 0 to 360], 6 | spinToZ: [number from 0 to 360] 7 | } -------------------------------------------------------------------------------- /code-examples/cube-focus-on.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube4'); 2 | 3 | // Cube will spin to the selected side 4 | // and back to the previous position 5 | myCube.focusOn({ 6 | bounceBack: true, 7 | spinTo: 'side-5' 8 | }); -------------------------------------------------------------------------------- /code-examples/cube-init.js: -------------------------------------------------------------------------------- 1 | var myCube = new Cube('#the-cube'); 2 | 3 | myCube.rotate({ 4 | speedX: 10000, 5 | speedY: 10000, 6 | speedZ: 10000, 7 | startSide: 'side-1' 8 | }); -------------------------------------------------------------------------------- /code-examples/cube-rotate-2.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube3a'); 2 | 3 | // Cube will start rotating only on one axis 4 | myCube.rotate({ 5 | startSide: 'side-3', 6 | speedX: 0, 7 | speedY: 20000, // 20 seconds to rotate by 360 degrees 8 | speedZ: 0 9 | }); -------------------------------------------------------------------------------- /code-examples/cube-rotate-3.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube3b'); 2 | 3 | // Cube will start rotating only on one axis 4 | // to the left 5 | myCube.rotate({ 6 | startSide: 'side-3', 7 | speedX: 0, 8 | speedY: 10000, // 10 seconds to rotate by 360 degrees 9 | speedZ: 0, 10 | rotateDir: 'left' 11 | }); -------------------------------------------------------------------------------- /code-examples/cube-rotate-options.js: -------------------------------------------------------------------------------- 1 | { 2 | startSide: ['side-1', 'side-2', 'side-3', 'side-4', 'side-5', 'side-6'], 3 | speedX: [number, time in milliseconds], 4 | speedY: [number, time in milliseconds], 5 | speedZ: [number, time in milliseconds], 6 | rotateDir: ['left' or 'right'] 7 | } -------------------------------------------------------------------------------- /code-examples/cube-rotate.js: -------------------------------------------------------------------------------- 1 | var myCube = Cube('#the-cube3'); 2 | 3 | // Cube will start rotating 4 | myCube.rotate({ 5 | startSide: 'side-3', 6 | speedX: 5000, // 5 seconds to rotate by 360 degrees 7 | speedY: 20000, // 20 seconds to rotate by 360 degrees 8 | speedZ: 10000 // 10 seconds to rotate by 360 degrees 9 | }); -------------------------------------------------------------------------------- /code-examples/cube.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
-------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | # Set this to the root of your project when deployed: 4 | http_path = "/" 5 | css_dir = "css" 6 | sass_dir = "sass" 7 | images_dir = "images" 8 | javascripts_dir = "js" 9 | fonts_dir = "fonts" 10 | preferred_syntax = :scss 11 | -------------------------------------------------------------------------------- /cube-js-docco/cube.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cube.js 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 1242 |
1243 | 1244 | 1245 | -------------------------------------------------------------------------------- /cube-js-docco/docco.css: -------------------------------------------------------------------------------- 1 | /*--------------------- Typography ----------------------------*/ 2 | 3 | @font-face { 4 | font-family: 'aller-light'; 5 | src: url('public/fonts/aller-light.eot'); 6 | src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), 7 | url('public/fonts/aller-light.woff') format('woff'), 8 | url('public/fonts/aller-light.ttf') format('truetype'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | @font-face { 14 | font-family: 'aller-bold'; 15 | src: url('public/fonts/aller-bold.eot'); 16 | src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), 17 | url('public/fonts/aller-bold.woff') format('woff'), 18 | url('public/fonts/aller-bold.ttf') format('truetype'); 19 | font-weight: normal; 20 | font-style: normal; 21 | } 22 | 23 | @font-face { 24 | font-family: 'novecento-bold'; 25 | src: url('public/fonts/novecento-bold.eot'); 26 | src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'), 27 | url('public/fonts/novecento-bold.woff') format('woff'), 28 | url('public/fonts/novecento-bold.ttf') format('truetype'); 29 | font-weight: normal; 30 | font-style: normal; 31 | } 32 | 33 | /*--------------------- Layout ----------------------------*/ 34 | html { height: 100%; } 35 | body { 36 | font-family: "aller-light"; 37 | font-size: 14px; 38 | line-height: 18px; 39 | color: #30404f; 40 | margin: 0; padding: 0; 41 | height:100%; 42 | } 43 | #container { min-height: 100%; } 44 | 45 | a { 46 | color: #000; 47 | } 48 | 49 | b, strong { 50 | font-weight: normal; 51 | font-family: "aller-bold"; 52 | } 53 | 54 | p { 55 | margin: 15px 0 0px; 56 | } 57 | .annotation ul, .annotation ol { 58 | margin: 25px 0; 59 | } 60 | .annotation ul li, .annotation ol li { 61 | font-size: 14px; 62 | line-height: 18px; 63 | margin: 10px 0; 64 | } 65 | 66 | h1, h2, h3, h4, h5, h6 { 67 | color: #112233; 68 | line-height: 1em; 69 | font-weight: normal; 70 | font-family: "novecento-bold"; 71 | text-transform: uppercase; 72 | margin: 0 0 15px 0; 73 | } 74 | 75 | h1 { 76 | color: #F04C23; 77 | margin-top: 40px; 78 | } 79 | 80 | hr { 81 | border: 0; 82 | background: 1px #ddd; 83 | height: 1px; 84 | margin: 20px 0; 85 | } 86 | 87 | pre, tt, code { 88 | font-size: 12px; line-height: 16px; 89 | font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; 90 | margin: 0; padding: 0; 91 | } 92 | .annotation pre { 93 | display: block; 94 | margin: 0; 95 | padding: 7px 10px; 96 | background: #fcfcfc; 97 | -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 98 | -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 99 | box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 100 | overflow-x: auto; 101 | } 102 | .annotation pre code { 103 | border: 0; 104 | padding: 0; 105 | background: transparent; 106 | } 107 | 108 | 109 | blockquote { 110 | border-left: 5px solid #ccc; 111 | margin: 0; 112 | padding: 1px 0 1px 1em; 113 | } 114 | .sections blockquote p { 115 | font-family: Menlo, Consolas, Monaco, monospace; 116 | font-size: 12px; line-height: 16px; 117 | color: #999; 118 | margin: 10px 0 0; 119 | white-space: pre-wrap; 120 | } 121 | 122 | ul.sections { 123 | list-style: none; 124 | padding:0 0 5px 0;; 125 | margin:0; 126 | } 127 | 128 | /* 129 | Force border-box so that % widths fit the parent 130 | container without overlap because of margin/padding. 131 | 132 | More Info : http://www.quirksmode.org/css/box.html 133 | */ 134 | ul.sections > li > div { 135 | -moz-box-sizing: border-box; /* firefox */ 136 | -ms-box-sizing: border-box; /* ie */ 137 | -webkit-box-sizing: border-box; /* webkit */ 138 | -khtml-box-sizing: border-box; /* konqueror */ 139 | box-sizing: border-box; /* css3 */ 140 | } 141 | 142 | 143 | /*---------------------- Jump Page -----------------------------*/ 144 | #jump_to, #jump_page { 145 | margin: 0; 146 | background: white; 147 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 148 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 149 | font: 16px Arial; 150 | cursor: pointer; 151 | text-align: right; 152 | list-style: none; 153 | } 154 | 155 | #jump_to a { 156 | text-decoration: none; 157 | } 158 | 159 | #jump_to a.large { 160 | display: none; 161 | } 162 | #jump_to a.small { 163 | font-size: 22px; 164 | font-weight: bold; 165 | color: #676767; 166 | } 167 | 168 | #jump_to, #jump_wrapper { 169 | position: fixed; 170 | right: 0; top: 0; 171 | padding: 10px 15px; 172 | margin:0; 173 | } 174 | 175 | #jump_wrapper { 176 | display: none; 177 | padding:0; 178 | } 179 | 180 | #jump_to:hover #jump_wrapper { 181 | display: block; 182 | } 183 | 184 | #jump_page { 185 | padding: 5px 0 3px; 186 | margin: 0 0 25px 25px; 187 | } 188 | 189 | #jump_page .source { 190 | display: block; 191 | padding: 15px; 192 | text-decoration: none; 193 | border-top: 1px solid #eee; 194 | } 195 | 196 | #jump_page .source:hover { 197 | background: #f5f5ff; 198 | } 199 | 200 | #jump_page .source:first-child { 201 | } 202 | 203 | /*---------------------- Low resolutions (> 320px) ---------------------*/ 204 | @media only screen and (min-width: 320px) { 205 | .pilwrap { display: none; } 206 | 207 | ul.sections > li > div { 208 | display: block; 209 | padding:5px 10px 0 10px; 210 | } 211 | 212 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 213 | padding-left: 30px; 214 | } 215 | 216 | ul.sections > li > div.content { 217 | overflow-x:auto; 218 | -webkit-box-shadow: inset 0 0 5px #e5e5ee; 219 | box-shadow: inset 0 0 5px #e5e5ee; 220 | border: 1px solid #dedede; 221 | margin:5px 10px 5px 10px; 222 | padding-bottom: 5px; 223 | } 224 | 225 | ul.sections > li > div.annotation pre { 226 | margin: 7px 0 7px; 227 | padding-left: 15px; 228 | } 229 | 230 | ul.sections > li > div.annotation p tt, .annotation code { 231 | background: #f8f8ff; 232 | border: 1px solid #dedede; 233 | font-size: 12px; 234 | padding: 0 0.2em; 235 | } 236 | } 237 | 238 | /*---------------------- (> 481px) ---------------------*/ 239 | @media only screen and (min-width: 481px) { 240 | #container { 241 | position: relative; 242 | } 243 | body { 244 | background-color: #F5F5FF; 245 | font-size: 15px; 246 | line-height: 21px; 247 | } 248 | pre, tt, code { 249 | line-height: 18px; 250 | } 251 | p, ul, ol { 252 | margin: 0 0 15px; 253 | } 254 | 255 | 256 | #jump_to { 257 | padding: 5px 10px; 258 | } 259 | #jump_wrapper { 260 | padding: 0; 261 | } 262 | #jump_to, #jump_page { 263 | font: 10px Arial; 264 | text-transform: uppercase; 265 | } 266 | #jump_page .source { 267 | padding: 5px 10px; 268 | } 269 | #jump_to a.large { 270 | display: inline-block; 271 | } 272 | #jump_to a.small { 273 | display: none; 274 | } 275 | 276 | 277 | 278 | #background { 279 | position: absolute; 280 | top: 0; bottom: 0; 281 | width: 350px; 282 | background: #fff; 283 | border-right: 1px solid #e5e5ee; 284 | z-index: -1; 285 | } 286 | 287 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 288 | padding-left: 40px; 289 | } 290 | 291 | ul.sections > li { 292 | white-space: nowrap; 293 | margin-bottom: 30px; 294 | } 295 | 296 | ul.sections > li > div { 297 | display: inline-block; 298 | } 299 | 300 | ul.sections > li > div.annotation { 301 | max-width: 350px; 302 | min-width: 350px; 303 | min-height: 5px; 304 | padding: 13px; 305 | overflow-x: hidden; 306 | white-space: normal; 307 | vertical-align: top; 308 | text-align: left; 309 | } 310 | ul.sections > li > div.annotation pre { 311 | margin: 15px 0 15px; 312 | padding-left: 15px; 313 | } 314 | 315 | ul.sections > li > div.content { 316 | padding: 13px; 317 | vertical-align: top; 318 | border: none; 319 | -webkit-box-shadow: none; 320 | box-shadow: none; 321 | } 322 | 323 | .pilwrap { 324 | position: relative; 325 | display: inline; 326 | } 327 | 328 | .pilcrow { 329 | font: 12px Arial; 330 | text-decoration: none; 331 | color: #454545; 332 | position: absolute; 333 | top: -2px; left: -20px; 334 | padding: 1px 2px; 335 | opacity: 0; 336 | -webkit-transition: opacity 0.2s linear; 337 | } 338 | .for-h1 .pilcrow { 339 | top: 47px; 340 | } 341 | .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { 342 | top: 35px; 343 | } 344 | 345 | ul.sections > li > div.annotation:hover .pilcrow { 346 | opacity: 1; 347 | } 348 | } 349 | 350 | /*---------------------- (> 1025px) ---------------------*/ 351 | @media only screen and (min-width: 1025px) { 352 | 353 | body { 354 | font-size: 16px; 355 | line-height: 24px; 356 | } 357 | 358 | #background { 359 | width: 525px; 360 | } 361 | ul.sections > li > div.annotation { 362 | max-width: 525px; 363 | min-width: 525px; 364 | padding: 10px 25px 1px 50px; 365 | } 366 | ul.sections > li > div.content { 367 | padding: 9px 15px 16px 25px; 368 | } 369 | } 370 | 371 | /*---------------------- Syntax Highlighting -----------------------------*/ 372 | 373 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 374 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 375 | /* 376 | 377 | github.com style (c) Vasily Polovnyov 378 | 379 | */ 380 | 381 | pre code { 382 | display: block; padding: 0.5em; 383 | color: #000; 384 | background: #f8f8ff 385 | } 386 | 387 | pre .hljs-comment, 388 | pre .hljs-template_comment, 389 | pre .hljs-diff .hljs-header, 390 | pre .hljs-javadoc { 391 | color: #408080; 392 | font-style: italic 393 | } 394 | 395 | pre .hljs-keyword, 396 | pre .hljs-assignment, 397 | pre .hljs-literal, 398 | pre .hljs-css .hljs-rule .hljs-keyword, 399 | pre .hljs-winutils, 400 | pre .hljs-javascript .hljs-title, 401 | pre .hljs-lisp .hljs-title, 402 | pre .hljs-subst { 403 | color: #954121; 404 | /*font-weight: bold*/ 405 | } 406 | 407 | pre .hljs-number, 408 | pre .hljs-hexcolor { 409 | color: #40a070 410 | } 411 | 412 | pre .hljs-string, 413 | pre .hljs-tag .hljs-value, 414 | pre .hljs-phpdoc, 415 | pre .hljs-tex .hljs-formula { 416 | color: #219161; 417 | } 418 | 419 | pre .hljs-title, 420 | pre .hljs-id { 421 | color: #19469D; 422 | } 423 | pre .hljs-params { 424 | color: #00F; 425 | } 426 | 427 | pre .hljs-javascript .hljs-title, 428 | pre .hljs-lisp .hljs-title, 429 | pre .hljs-subst { 430 | font-weight: normal 431 | } 432 | 433 | pre .hljs-class .hljs-title, 434 | pre .hljs-haskell .hljs-label, 435 | pre .hljs-tex .hljs-command { 436 | color: #458; 437 | font-weight: bold 438 | } 439 | 440 | pre .hljs-tag, 441 | pre .hljs-tag .hljs-title, 442 | pre .hljs-rules .hljs-property, 443 | pre .hljs-django .hljs-tag .hljs-keyword { 444 | color: #000080; 445 | font-weight: normal 446 | } 447 | 448 | pre .hljs-attribute, 449 | pre .hljs-variable, 450 | pre .hljs-instancevar, 451 | pre .hljs-lisp .hljs-body { 452 | color: #008080 453 | } 454 | 455 | pre .hljs-regexp { 456 | color: #B68 457 | } 458 | 459 | pre .hljs-class { 460 | color: #458; 461 | font-weight: bold 462 | } 463 | 464 | pre .hljs-symbol, 465 | pre .hljs-ruby .hljs-symbol .hljs-string, 466 | pre .hljs-ruby .hljs-symbol .hljs-keyword, 467 | pre .hljs-ruby .hljs-symbol .hljs-keymethods, 468 | pre .hljs-lisp .hljs-keyword, 469 | pre .hljs-tex .hljs-special, 470 | pre .hljs-input_number { 471 | color: #990073 472 | } 473 | 474 | pre .hljs-builtin, 475 | pre .hljs-constructor, 476 | pre .hljs-built_in, 477 | pre .hljs-lisp .hljs-title { 478 | color: #0086b3 479 | } 480 | 481 | pre .hljs-preprocessor, 482 | pre .hljs-pi, 483 | pre .hljs-doctype, 484 | pre .hljs-shebang, 485 | pre .hljs-cdata { 486 | color: #999; 487 | font-weight: bold 488 | } 489 | 490 | pre .hljs-deletion { 491 | background: #fdd 492 | } 493 | 494 | pre .hljs-addition { 495 | background: #dfd 496 | } 497 | 498 | pre .hljs-diff .hljs-change { 499 | background: #0086b3 500 | } 501 | 502 | pre .hljs-chunk { 503 | color: #aaa 504 | } 505 | 506 | pre .hljs-tex .hljs-formula { 507 | opacity: 0.5; 508 | } 509 | -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.eot -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.ttf -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.woff -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.eot -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.ttf -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/aller-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.woff -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/novecento-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.eot -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/novecento-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.ttf -------------------------------------------------------------------------------- /cube-js-docco/public/fonts/novecento-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.woff -------------------------------------------------------------------------------- /cube-js-docco/public/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /* 8 | * Corrects `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | nav, 20 | section, 21 | summary { 22 | display: block; 23 | } 24 | 25 | /* 26 | * Corrects `inline-block` display not defined in IE 8/9. 27 | */ 28 | 29 | audio, 30 | canvas, 31 | video { 32 | display: inline-block; 33 | } 34 | 35 | /* 36 | * Prevents modern browsers from displaying `audio` without controls. 37 | * Remove excess height in iOS 5 devices. 38 | */ 39 | 40 | audio:not([controls]) { 41 | display: none; 42 | height: 0; 43 | } 44 | 45 | /* 46 | * Addresses styling for `hidden` attribute not present in IE 8/9. 47 | */ 48 | 49 | [hidden] { 50 | display: none; 51 | } 52 | 53 | /* ========================================================================== 54 | Base 55 | ========================================================================== */ 56 | 57 | /* 58 | * 1. Sets default font family to sans-serif. 59 | * 2. Prevents iOS text size adjust after orientation change, without disabling 60 | * user zoom. 61 | */ 62 | 63 | html { 64 | font-family: sans-serif; /* 1 */ 65 | -webkit-text-size-adjust: 100%; /* 2 */ 66 | -ms-text-size-adjust: 100%; /* 2 */ 67 | } 68 | 69 | /* 70 | * Removes default margin. 71 | */ 72 | 73 | body { 74 | margin: 0; 75 | } 76 | 77 | /* ========================================================================== 78 | Links 79 | ========================================================================== */ 80 | 81 | /* 82 | * Addresses `outline` inconsistency between Chrome and other browsers. 83 | */ 84 | 85 | a:focus { 86 | outline: thin dotted; 87 | } 88 | 89 | /* 90 | * Improves readability when focused and also mouse hovered in all browsers. 91 | */ 92 | 93 | a:active, 94 | a:hover { 95 | outline: 0; 96 | } 97 | 98 | /* ========================================================================== 99 | Typography 100 | ========================================================================== */ 101 | 102 | /* 103 | * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, 104 | * Safari 5, and Chrome. 105 | */ 106 | 107 | h1 { 108 | font-size: 2em; 109 | } 110 | 111 | /* 112 | * Addresses styling not present in IE 8/9, Safari 5, and Chrome. 113 | */ 114 | 115 | abbr[title] { 116 | border-bottom: 1px dotted; 117 | } 118 | 119 | /* 120 | * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 121 | */ 122 | 123 | b, 124 | strong { 125 | font-weight: bold; 126 | } 127 | 128 | /* 129 | * Addresses styling not present in Safari 5 and Chrome. 130 | */ 131 | 132 | dfn { 133 | font-style: italic; 134 | } 135 | 136 | /* 137 | * Addresses styling not present in IE 8/9. 138 | */ 139 | 140 | mark { 141 | background: #ff0; 142 | color: #000; 143 | } 144 | 145 | 146 | /* 147 | * Corrects font family set oddly in Safari 5 and Chrome. 148 | */ 149 | 150 | code, 151 | kbd, 152 | pre, 153 | samp { 154 | font-family: monospace, serif; 155 | font-size: 1em; 156 | } 157 | 158 | /* 159 | * Improves readability of pre-formatted text in all browsers. 160 | */ 161 | 162 | pre { 163 | white-space: pre; 164 | white-space: pre-wrap; 165 | word-wrap: break-word; 166 | } 167 | 168 | /* 169 | * Sets consistent quote types. 170 | */ 171 | 172 | q { 173 | quotes: "\201C" "\201D" "\2018" "\2019"; 174 | } 175 | 176 | /* 177 | * Addresses inconsistent and variable font size in all browsers. 178 | */ 179 | 180 | small { 181 | font-size: 80%; 182 | } 183 | 184 | /* 185 | * Prevents `sub` and `sup` affecting `line-height` in all browsers. 186 | */ 187 | 188 | sub, 189 | sup { 190 | font-size: 75%; 191 | line-height: 0; 192 | position: relative; 193 | vertical-align: baseline; 194 | } 195 | 196 | sup { 197 | top: -0.5em; 198 | } 199 | 200 | sub { 201 | bottom: -0.25em; 202 | } 203 | 204 | /* ========================================================================== 205 | Embedded content 206 | ========================================================================== */ 207 | 208 | /* 209 | * Removes border when inside `a` element in IE 8/9. 210 | */ 211 | 212 | img { 213 | border: 0; 214 | } 215 | 216 | /* 217 | * Corrects overflow displayed oddly in IE 9. 218 | */ 219 | 220 | svg:not(:root) { 221 | overflow: hidden; 222 | } 223 | 224 | /* ========================================================================== 225 | Figures 226 | ========================================================================== */ 227 | 228 | /* 229 | * Addresses margin not present in IE 8/9 and Safari 5. 230 | */ 231 | 232 | figure { 233 | margin: 0; 234 | } 235 | 236 | /* ========================================================================== 237 | Forms 238 | ========================================================================== */ 239 | 240 | /* 241 | * Define consistent border, margin, and padding. 242 | */ 243 | 244 | fieldset { 245 | border: 1px solid #c0c0c0; 246 | margin: 0 2px; 247 | padding: 0.35em 0.625em 0.75em; 248 | } 249 | 250 | /* 251 | * 1. Corrects color not being inherited in IE 8/9. 252 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 253 | */ 254 | 255 | legend { 256 | border: 0; /* 1 */ 257 | padding: 0; /* 2 */ 258 | } 259 | 260 | /* 261 | * 1. Corrects font family not being inherited in all browsers. 262 | * 2. Corrects font size not being inherited in all browsers. 263 | * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome 264 | */ 265 | 266 | button, 267 | input, 268 | select, 269 | textarea { 270 | font-family: inherit; /* 1 */ 271 | font-size: 100%; /* 2 */ 272 | margin: 0; /* 3 */ 273 | } 274 | 275 | /* 276 | * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in 277 | * the UA stylesheet. 278 | */ 279 | 280 | button, 281 | input { 282 | line-height: normal; 283 | } 284 | 285 | /* 286 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 287 | * and `video` controls. 288 | * 2. Corrects inability to style clickable `input` types in iOS. 289 | * 3. Improves usability and consistency of cursor style between image-type 290 | * `input` and others. 291 | */ 292 | 293 | button, 294 | html input[type="button"], /* 1 */ 295 | input[type="reset"], 296 | input[type="submit"] { 297 | -webkit-appearance: button; /* 2 */ 298 | cursor: pointer; /* 3 */ 299 | } 300 | 301 | /* 302 | * Re-set default cursor for disabled elements. 303 | */ 304 | 305 | button[disabled], 306 | input[disabled] { 307 | cursor: default; 308 | } 309 | 310 | /* 311 | * 1. Addresses box sizing set to `content-box` in IE 8/9. 312 | * 2. Removes excess padding in IE 8/9. 313 | */ 314 | 315 | input[type="checkbox"], 316 | input[type="radio"] { 317 | box-sizing: border-box; /* 1 */ 318 | padding: 0; /* 2 */ 319 | } 320 | 321 | /* 322 | * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. 323 | * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome 324 | * (include `-moz` to future-proof). 325 | */ 326 | 327 | input[type="search"] { 328 | -webkit-appearance: textfield; /* 1 */ 329 | -moz-box-sizing: content-box; 330 | -webkit-box-sizing: content-box; /* 2 */ 331 | box-sizing: content-box; 332 | } 333 | 334 | /* 335 | * Removes inner padding and search cancel button in Safari 5 and Chrome 336 | * on OS X. 337 | */ 338 | 339 | input[type="search"]::-webkit-search-cancel-button, 340 | input[type="search"]::-webkit-search-decoration { 341 | -webkit-appearance: none; 342 | } 343 | 344 | /* 345 | * Removes inner padding and border in Firefox 4+. 346 | */ 347 | 348 | button::-moz-focus-inner, 349 | input::-moz-focus-inner { 350 | border: 0; 351 | padding: 0; 352 | } 353 | 354 | /* 355 | * 1. Removes default vertical scrollbar in IE 8/9. 356 | * 2. Improves readability and alignment in all browsers. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; /* 1 */ 361 | vertical-align: top; /* 2 */ 362 | } 363 | 364 | /* ========================================================================== 365 | Tables 366 | ========================================================================== */ 367 | 368 | /* 369 | * Remove most spacing between table cells. 370 | */ 371 | 372 | table { 373 | border-collapse: collapse; 374 | border-spacing: 0; 375 | } -------------------------------------------------------------------------------- /cube.css: -------------------------------------------------------------------------------- 1 | /* Cube styles */ 2 | .cube-3d-available .the-cube { 3 | position: relative; 4 | z-index: 10; 5 | display: block; 6 | width: 130px; 7 | height: 130px; 8 | -webkit-transform: perspective(1300px); 9 | -moz-transform: perspective(1300px); 10 | -ms-transform: perspective(1300px); 11 | -o-transform: perspective(1300px); 12 | transform: perspective(1300px); 13 | -webkit-transform-style: preserve-3d; 14 | -moz-transform-style: preserve-3d; 15 | -ms-transform-style: preserve-3d; 16 | -o-transform-style: preserve-3d; 17 | transform-style: preserve-3d; 18 | } 19 | .cube-3d-available .the-cube.rotate { 20 | -webkit-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg); 21 | -moz-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg); 22 | -ms-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg); 23 | -o-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg); 24 | transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg); 25 | } 26 | .cube-3d-available .the-cube .side-1, .cube-3d-available .the-cube .side-2, .cube-3d-available .the-cube .side-3, .cube-3d-available .the-cube .side-4, .cube-3d-available .the-cube .side-5, .cube-3d-available .the-cube .side-6 { 27 | position: absolute; 28 | left: 0; 29 | top: 0; 30 | z-index: 1; 31 | background-size: 390px 260px; 32 | } 33 | .cube-3d-available .the-cube .side-1 { 34 | width: 100%; 35 | height: 100%; 36 | -webkit-transform: rotateY(-90deg) translateZ(65px); 37 | -moz-transform: rotateY(-90deg) translateZ(65px); 38 | -ms-transform: rotateY(-90deg) translateZ(65px); 39 | -o-transform: rotateY(-90deg) translateZ(65px); 40 | transform: rotateY(-90deg) translateZ(65px); 41 | } 42 | .cube-3d-available .the-cube .side-2 { 43 | width: 100%; 44 | height: 100%; 45 | background-position: -130px 0; 46 | -webkit-transform: rotateX(-90deg) translateZ(65px); 47 | -moz-transform: rotateX(-90deg) translateZ(65px); 48 | -ms-transform: rotateX(-90deg) translateZ(65px); 49 | -o-transform: rotateX(-90deg) translateZ(65px); 50 | transform: rotateX(-90deg) translateZ(65px); 51 | } 52 | .cube-3d-available .the-cube .side-3 { 53 | width: 100%; 54 | height: 100%; 55 | background-position: -260px 0; 56 | -webkit-transform: translateZ(65px); 57 | -moz-transform: translateZ(65px); 58 | -ms-transform: translateZ(65px); 59 | -o-transform: translateZ(65px); 60 | transform: translateZ(65px); 61 | -webkit-transform-origin: 0 0 0; 62 | -moz-transform-origin: 0 0 0; 63 | -ms-transform-origin: 0 0 0; 64 | -o-transform-origin: 0 0 0; 65 | transform-origin: 0 0 0; 66 | -webkit-transition-property: -webkit-transform, background; 67 | -moz-transition-property: -moz-transform, background; 68 | -o-transition-property: -o-transform, background; 69 | transition-property: transform, background; 70 | -webkit-transition-duration: 0.3s; 71 | -moz-transition-duration: 0.3s; 72 | -o-transition-duration: 0.3s; 73 | transition-duration: 0.3s; 74 | } 75 | .cube-3d-available .the-cube .side-4 { 76 | width: 100%; 77 | height: 100%; 78 | background-position: 0 -130px; 79 | -webkit-transform: rotateX(90deg) translateZ(65px); 80 | -moz-transform: rotateX(90deg) translateZ(65px); 81 | -ms-transform: rotateX(90deg) translateZ(65px); 82 | -o-transform: rotateX(90deg) translateZ(65px); 83 | transform: rotateX(90deg) translateZ(65px); 84 | } 85 | .cube-3d-available .the-cube .side-5 { 86 | width: 100%; 87 | height: 100%; 88 | background-position: -130px -130px; 89 | -webkit-transform: rotateY(90deg) translateZ(65px); 90 | -moz-transform: rotateY(90deg) translateZ(65px); 91 | -ms-transform: rotateY(90deg) translateZ(65px); 92 | -o-transform: rotateY(90deg) translateZ(65px); 93 | transform: rotateY(90deg) translateZ(65px); 94 | } 95 | .cube-3d-available .the-cube .side-6 { 96 | width: 100%; 97 | height: 100%; 98 | background-position: -260px -130px; 99 | -webkit-transform: rotateY(180deg) translateX(-130px) translateZ(65px); 100 | -moz-transform: rotateY(180deg) translateX(-130px) translateZ(65px); 101 | -ms-transform: rotateY(180deg) translateX(-130px) translateZ(65px); 102 | -o-transform: rotateY(180deg) translateX(-130px) translateZ(65px); 103 | transform: rotateY(180deg) translateX(-130px) translateZ(65px); 104 | -webkit-transform-origin: 0 0 0; 105 | -moz-transform-origin: 0 0 0; 106 | -ms-transform-origin: 0 0 0; 107 | -o-transform-origin: 0 0 0; 108 | transform-origin: 0 0 0; 109 | -webkit-transition-property: -webkit-transform, background; 110 | -moz-transition-property: -moz-transform, background; 111 | -o-transition-property: -o-transform, background; 112 | transition-property: transform, background; 113 | -webkit-transition-duration: 0.3s; 114 | -moz-transition-duration: 0.3s; 115 | -o-transition-duration: 0.3s; 116 | transition-duration: 0.3s; 117 | } 118 | 119 | /* Cube styles - END */ 120 | -------------------------------------------------------------------------------- /cube.js: -------------------------------------------------------------------------------- 1 | // Allows to manipulate the cube created using CSS and HTML. 2 | // 3 | // author: Artur Kot (artur.kot@xhtmlized.com) 4 | 5 | /*jshint browser: true, smarttabs: false, indent: 4, undef: true, unused: true, strict: true, trailing: true, onevar: true, white: true */ 6 | /*globals requestAnimationFrame, cancelAnimationFrame*/ 7 | 8 | (function () { 9 | 'use strict'; 10 | 11 | var Test, Cube; 12 | 13 | // ## Tests 14 | Test = { 15 | // ### 'requestAnimationFrame' test 16 | // Checks if 'requestAnimationFrame' is available 17 | // 18 | // * return: __boolean__ Returns true if 'requestAnimationFrame' is available. 19 | animationFrame: function () { 20 | return !!window.requestAnimationFrame; 21 | }, 22 | 23 | // ### CSS 3d test 24 | // Checks if CSS 3d transforms can be used 25 | // 26 | // * return: __boolean__ Returns true if 'requestAnimationFrame' is available. 27 | css3d: function () { 28 | if (document.querySelector === undefined) { return false; } 29 | 30 | var EL_ID = 'temporaryCubeCSS3dElement', 31 | STYLE_ID = 'temporaryCubeCSS3dStyle', 32 | $body = document.body, 33 | $el, 34 | $style, 35 | docStyles = document.documentElement.style, 36 | prefixes = ['webkit', 'moz', 'ms', ''], 37 | testResult, 38 | i, 39 | j; 40 | 41 | // * #### Test for 'preserve3d' CSS property. 42 | // - return: __boolean__ Returns true if 'preserve3d' is available. 43 | function testPreserve3d() { 44 | for (i = 0, j = prefixes.length; i < j; i += 1) { 45 | if (prefixes[i].length > 0) { 46 | if (docStyles[prefixes[i] + 'TransformStyle'] !== undefined) { 47 | docStyles[prefixes[i] + 'TransformStyle'] = 'preserve-3d'; 48 | if (docStyles[prefixes[i] + 'TransformStyle'].length > 0) { 49 | docStyles[prefixes[i] + 'TransformStyle'] = ''; 50 | return true; 51 | } 52 | } 53 | } else { 54 | if (docStyles.transformStyle !== undefined) { 55 | docStyles.transformStyle = 'preserve-3d'; 56 | if (docStyles.transformStyle.length > 0) { 57 | docStyles.transformStyle = ''; 58 | return true; 59 | } 60 | } 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | 67 | testResult = testPreserve3d(); 68 | 69 | // * **Note:** 70 | // This is additional test checking if 'transform-3d' is **really available**. 71 | // It may happen that although property itself is available it's not working properly. 72 | // One of possible reasons can be lack of GPU support. 73 | // The additional CSS 3d transform test is borrowed from [Modernizr](https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/transforms3d.js) 74 | if (testResult && docStyles.webkitPerspective !== undefined) { 75 | $style = document.createElement('style'); 76 | $el = document.createElement('div'); 77 | 78 | $style.id = STYLE_ID; 79 | $el.id = EL_ID; 80 | 81 | $body.appendChild($style); 82 | $body.appendChild($el); 83 | 84 | $style.textContent = [ 85 | '@media (transform-3d), (-webkit-transform-3d) {', 86 | ' #' + EL_ID + '{', 87 | ' left: 9px;', 88 | ' position: absolute;', 89 | ' height: 5px;', 90 | ' margin: 0;', 91 | ' padding: 0;', 92 | ' border: 0', 93 | ' }', 94 | '}' 95 | ].join('\n'); 96 | 97 | testResult = $el.offsetLeft === 9 && $el.offsetHeight === 5; 98 | 99 | $body.removeChild($style); 100 | $body.removeChild($el); 101 | } 102 | 103 | return testResult; 104 | } 105 | }; 106 | 107 | // ## CSS class 108 | // Adds class at the top of the document. 109 | // Useful for applying fallback if Cube cannot be fired. 110 | if (Test.animationFrame() && Test.css3d()) { 111 | document.documentElement.className += ' cube-3d-available'; 112 | } 113 | 114 | // ## Factory function 115 | // Allows to create new Cube instance in the following fashion 116 | // (note that 'new' is not necessary as it's added inside 117 | // the function below): 118 | // ``` 119 | // var myCube = Cube('.my .selector'); 120 | // ``` 121 | // and later use any of the available public classes, e.g.: 122 | // ``` 123 | // myCube.rotate(); 124 | // ``` 125 | // The function is revealed using `window` object. 126 | // 127 | // * parameters: 128 | // - `selector` __string__ Any CSS selector that will work with [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector). 129 | // - `props` __object__ The cube's options passed to the constructor. 130 | // * return __function__ or __object__ If the cube can be fired `Cube` will return new instance of `Cube.instance` constructor else it will return object with empty methods. 131 | Cube = function (selector, props) { 132 | if (Test.animationFrame() && Test.css3d()) { 133 | return new Cube.instance(selector, props || {}); 134 | } 135 | 136 | return { 137 | applyRotation: function () { return false; }, 138 | rotate: function () { return false; }, 139 | focusOn: function () { return false; }, 140 | spinTo: function () { return false; } 141 | }; 142 | }; 143 | 144 | window.Cube = Cube; 145 | 146 | // ## Constructor 147 | // * parameters: 148 | // - `selector` __string__ Any CSS selector that will work with [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector). 149 | // - `props` __object__ The cube's options. 150 | Cube.instance = function (selector, props) { 151 | // The only option that can be currently passed to the constructor 152 | // is [perspective](https://developer.mozilla.org/en-US/docs/Web/CSS/perspective). 153 | props.perspective = props.perspective || 1100; 154 | 155 | // ### Public variables 156 | 157 | // * `$cube` __object__ A DOM element which is supposed to be a cube. 158 | this.$cube = document.querySelector(selector || '#the-cube'); 159 | 160 | // * `props` __object__ Options publicly available for methods. 161 | this.props = props; 162 | 163 | // * `rotatePropsSet` __boolean__ True if rotate properties (posX, posY, posZ, speedX, speedY, speedZ) has been set. See `rotate` method below. 164 | this.rotatePropsSet = false; 165 | 166 | // * `rotateDir` __string__ The cube's rotation direction. Can be either 'left' or 'right'. 167 | this.rotateDir = 'right'; 168 | 169 | // * `speed[axis]` __number__ Determines how fast the cube should rotate 360 degrees. Value is in 'iterations', not milliseconds. 170 | this.speedX = 0; 171 | this.speedY = 0; 172 | this.speedZ = 0; 173 | 174 | // * `pos[axis]` __number__ The cube's rotation value from **0 to 360**. 175 | this.posX = 0; 176 | this.posY = 0; 177 | this.posZ = 0; 178 | 179 | // * `snapshot[axis]` __number__ The cube's rotation value from **0 to 360**. Used to 'remember' last values. See 'focusOn' method. 180 | this.snapshotX = 0; 181 | this.snapshotY = 0; 182 | this.snapshotZ = 0; 183 | 184 | // * `isRotating` __boolean__ True if cube is being rotated at the moment (rotate method is in use). See `rotate`. 185 | this.isRotating = false; 186 | 187 | // * `isFocusing` __boolean__ True if cube is being focused at the moment (rotates to show selected side). See `rotate`, `spinTo`, and `focusOn` methods. 188 | this.isFocusing = false; 189 | 190 | // * `hasFocused` __boolean__ True if cube has rotated to the selected side. See `focusOn` method. 191 | this.hasFocused = false; 192 | 193 | // * `iterators` __object__ Stores iterators for each axis. See `spinTo` method. 194 | this.iterators = {}; 195 | 196 | // * `timers` __object__ Stores timers (requestAnimationFrame). 197 | this.timers = {}; 198 | }; 199 | 200 | Cube.instance.prototype = { 201 | // * `xyz` and `XYZ` __array__ 'x', 'y', 'z' prefixes. 202 | xyz: ['x', 'y', 'z'], 203 | XYZ: ['X', 'Y', 'Z'], 204 | 205 | // * `sides` __object__ Predefined cube's sides coordinates. 206 | sides: { 207 | 'side-1': [0, 90, 0], 208 | 'side-2': [90, 0, 0], 209 | 'side-3': [0, 0, 0], 210 | 'side-4': [270, 0, 0], 211 | 'side-5': [0, 270, 0], 212 | 'side-6': [0, 180, 0] 213 | }, 214 | 215 | // ### Public Methods 216 | 217 | // #### Apply rotation 218 | // Set rotation of the cube. 219 | // 220 | // * parameters: `props` __object__ Rotation of each axis in the following format: 221 | // ``` 222 | // { 223 | // x: [number from 0 to 360], 224 | // y: [number from 0 to 360], 225 | // z: [number from 0 to 360] 226 | // } 227 | // ``` 228 | // or predefined side string: 229 | // 230 | // ``` 231 | // { side: 'side-3' } 232 | // ``` 233 | // 234 | // Usage examples: 235 | // ``` 236 | // var myCube = Cube('.my .selector'); 237 | // 238 | // // Set the cube's position 239 | // myCube.applyRotation({ 240 | // x: 45, 241 | // y: 30, 242 | // z: 270 243 | // }); 244 | // ``` 245 | // 246 | // ``` 247 | // var myCube = Cube('.my .selector'); 248 | // 249 | // // Set the cube's position 250 | // myCube.applyRotation({ side: 'side-4' }); 251 | // ``` 252 | applyRotation: function (props) { 253 | var prefix = this._getPrefix(), 254 | styles = 'perspective(' + this.props.perspective + 'px)', 255 | currentDeg, 256 | axes = 0; 257 | 258 | props = props || {}; 259 | 260 | if (props.x && props.y && props.z) { 261 | while (axes < 3) { 262 | currentDeg = props[this.xyz[axes]]; 263 | currentDeg = isNaN(currentDeg) ? 0 : currentDeg; 264 | 265 | this['pos' + this.XYZ[axes]] = currentDeg; 266 | 267 | axes += 1; 268 | } 269 | } else if (props.side) { 270 | if (!this.sides[props.side]) { throw 'You\'ve probably entered wrong string as a "side" in "applyRotation". Try "side-1", "side-2", "side-3", "side-4", "side-5", or "side-6"'; } 271 | 272 | while (axes < 3) { 273 | currentDeg = this.sides[props.side][axes]; 274 | 275 | this['pos' + this.XYZ[axes]] = currentDeg; 276 | 277 | axes += 1; 278 | } 279 | } 280 | 281 | axes = 0; 282 | while (axes < 3) { 283 | currentDeg = this['pos' + this.XYZ[axes]]; 284 | 285 | styles += ' rotate' + this.XYZ[axes] + '(' + currentDeg + 'deg)'; 286 | 287 | axes += 1; 288 | } 289 | 290 | this.$cube.style[prefix ? prefix + 'Transform' : 'transform'] = styles; 291 | }, 292 | 293 | // #### Rotate 294 | // Start infinite rotation animation. 295 | // 296 | // * parameters: `props` __object__ Rotate options: 297 | // - `startSide` __string__ Specify from which side should the cube start to animate. 298 | // Possible options: 299 | // - side-1, side-2, side-3, side-4, side-5, side-6 300 | // 301 | // - `speed[axis]` __number__ Time in milliseconds in which the cube rotate around one axis (from 0 to 360 degrees). 302 | // - `rotateDir` __string__ Can be 'left' or 'right'. 303 | // 304 | // Usage example: 305 | // ``` 306 | // var myCube = Cube('.my .selector'); 307 | // 308 | // // Cube will start rotating 309 | // myCube.rotate({ 310 | // startSide: 'side-1', 311 | // speedX: 5000, // 5 seconds 312 | // speedY: 20000, // 20 seconds 313 | // speedZ: 10000 // 10 seconds 314 | // rotateDir: 'left' 315 | // }); 316 | // ``` 317 | rotate: function (props) { 318 | var i = 0, 319 | dir = 0, 320 | XYZ = this.XYZ, 321 | self = this, 322 | currentSpeed; 323 | 324 | props = props || {}; 325 | 326 | self.rotateDir = props.rotateDir || self.rotateDir; 327 | 328 | self.isRotating = true; 329 | 330 | if (props.startSide && self.sides[props.startSide] === undefined) { throw 'You\'ve typed wrong value for "startSide" option.'; } 331 | 332 | self.isFocusing = false; 333 | 334 | if (!self.rotatePropsSet) { 335 | while (i < 3) { 336 | if (props.startSide) { 337 | props['start' + XYZ[i]] = self.sides[props.startSide][i]; 338 | } 339 | 340 | self['pos' + XYZ[i]] = props['start' + XYZ[i]] || 0; 341 | 342 | currentSpeed = props['speed' + XYZ[i]]; 343 | currentSpeed = currentSpeed === 0 ? 0 : (currentSpeed || 360); 344 | self['speed' + XYZ[i]] = currentSpeed; 345 | i += 1; 346 | } 347 | 348 | self.rotateDir = props.rotateDir || self.rotateDir; 349 | 350 | self.rotatePropsSet = true; 351 | } 352 | 353 | if (self.rotateDir === 'left') { dir = -360; } 354 | if (self.rotateDir === 'right') { dir = 360; } 355 | 356 | self._spinTo({ 357 | spinToX: props.startX ? props.startX + dir : dir, 358 | spinToY: props.startY ? props.startY + dir : dir, 359 | spinToZ: props.startZ ? props.startZ + dir : dir, 360 | speedX: self.speedX, 361 | speedY: self.speedY, 362 | speedZ: self.speedZ, 363 | timer: 'rotate', 364 | repeat: true, 365 | easing: 'linear' 366 | }); 367 | }, 368 | 369 | // #### Focus On 370 | // Animate to the specified side of the cube on 'mouseover' or 'touchstart' event. 371 | // 372 | // * parameters: `props` __object__ focusOn options: 373 | // - `bounceBack` __boolean__ If set to true the cube will animate back to its last position (before focusOn animation), else it will stay at the focused position. 374 | // - `spinTo` __string__ Specify to which side should the cube animate to. **Note** that this option will overwrite `spintTo[axis]`. 375 | // - `spinTo[axis]` __number__ Specify to what degree each axis should animate to. 376 | // 377 | // Usage example: 378 | // ``` 379 | // var myCube = Cube('.my .selector'); 380 | // 381 | // // Cube will rotate to selected face 382 | // // either on 'touchstart' or 'mouseover' event. 383 | // myCube.focusOn({ 384 | // bounceBack: true, 385 | // spinTo: 'side-6' 386 | // }); 387 | // ``` 388 | focusOn: function (props) { 389 | var self = this, 390 | isTouch = window.ontouchstart === null, 391 | startEvent = isTouch ? 'touchstart' : 'mouseover'; 392 | 393 | props = props || {}; 394 | 395 | function focus() { 396 | if (props.bounceBack) { 397 | cancelAnimationFrame(self.timers.deFocus); 398 | } 399 | 400 | if (!self.isFocusing) { 401 | self.snapshotX = self.posX; 402 | self.snapshotY = self.posY; 403 | self.snapshotZ = self.posZ; 404 | } 405 | 406 | if (props.spinTo && self.sides[props.spinTo] === undefined) { throw 'You\'ve typed wrong value for "spinTo" option.'; } 407 | 408 | if (props.spinTo && self.sides[props.spinTo] !== undefined) { 409 | props.spinToX = self.sides[props.spinTo][0]; 410 | props.spinToY = self.sides[props.spinTo][1]; 411 | props.spinToZ = self.sides[props.spinTo][2]; 412 | } 413 | 414 | self._spinTo({ 415 | spinToX: props.spinToX || 0, 416 | spinToY: props.spinToY || 0, 417 | spinToZ: props.spinToZ || 0, 418 | speed: props.speed || 2000, 419 | timer: 'spinTo', 420 | easing: 'out', 421 | callback: function () { 422 | self.$cube.className += ' focused'; 423 | self.hasFocused = true; 424 | } 425 | }); 426 | } 427 | 428 | function deFocus() { 429 | cancelAnimationFrame(self.timers.spinTo); 430 | cancelAnimationFrame(self.timers.rotate); 431 | 432 | self._removeClass(self.$cube, 'focused'); 433 | self.hasFocused = false; 434 | 435 | if (props.bounceBack) { 436 | self._spinTo({ 437 | spinToX: self.snapshotX, 438 | spinToY: self.snapshotY, 439 | spinToZ: self.snapshotZ, 440 | speed: props.speed || 2000, 441 | timer: 'deFocus', 442 | easing: 'out', 443 | callback: function () { 444 | if (self.isRotating) { 445 | self.rotate({ 446 | startX: self.posX, 447 | startY: self.posY, 448 | startZ: self.posZ 449 | }); 450 | } 451 | } 452 | }); 453 | } else if (self.isRotating) { 454 | self.rotate({ 455 | startX: self.posX, 456 | startY: self.posY, 457 | startZ: self.posZ 458 | }); 459 | } 460 | } 461 | 462 | self.$cube.addEventListener(startEvent, function (e) { 463 | if (self.hasFocused) { return; } 464 | e.preventDefault(); 465 | cancelAnimationFrame(self.timers.rotate); 466 | focus(); 467 | }); 468 | 469 | self.$cube.addEventListener('mouseout', deFocus); 470 | 471 | if (isTouch) { 472 | document.addEventListener('touchstart', function (e) { 473 | var $target = e.target; 474 | if (!self._hasParent($target, self.$cube)) { deFocus(); } 475 | }); 476 | } 477 | }, 478 | 479 | // ### Private Methods 480 | 481 | // #### Spin To 482 | // Animate to the specified position. 483 | // 484 | // * parameters: `props` __object__ spinTo options: 485 | // - `spinTo[axis]` __number__ Specify to what degree each axis should animate to. 486 | // - `speed` __number__ Time (in milliseconds) that specifies how long it will take to spin to given position. Overwrites `speed[axis]`. 487 | // - `speed[axis]` __number__ Time (in milliseconds) that specifies how long it will take to spin to given position for each axis. 488 | // - `timer` __string__ Timer's ID. It can be reset if needed thus stopping spinTo loop. Timers are attached to public variable called `timers` (see in constructor). 489 | // - `easing` __string__ Name of easing function (available functions: 'ease', 'out', 'inOut') 490 | // - `callback` __function__ Function which executes after spinTo is done. 491 | _spinTo: function (props) { 492 | var i = 0, 493 | self = this, 494 | start = {}, 495 | speeds = [], 496 | changeInValue = {}, 497 | changeInValueA = {}, 498 | changeInValueB = {}, 499 | dir = {}, 500 | done = {}, 501 | xyz = self.xyz, 502 | XYZ = self.XYZ, 503 | currentMax, 504 | currentDeg, 505 | currentSpeed, 506 | currentIterator; 507 | 508 | props.speed = self._calculateIterations(props.speed); 509 | 510 | self.isFocusing = props.repeat ? false : true; 511 | 512 | while (i < 3) { 513 | start[xyz[i]] = self['pos' + XYZ[i]]; 514 | 515 | if (props['speed' + XYZ[i]]) { 516 | props['speed' + XYZ[i]] = self._calculateIterations(props['speed' + XYZ[i]]); 517 | } 518 | 519 | if (props.repeat) { 520 | changeInValue[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]); 521 | } else { 522 | changeInValueA[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]); 523 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) { 524 | changeInValueB[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]] - 360); 525 | } else { 526 | changeInValueB[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]] + 360); 527 | } 528 | 529 | if (changeInValueA[xyz[i]] < changeInValueB[xyz[i]]) { 530 | changeInValue[xyz[i]] = changeInValueA[xyz[i]]; 531 | } else { 532 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) { 533 | props['spinTo' + XYZ[i]] += 360; 534 | } else { 535 | props['spinTo' + XYZ[i]] -= 360; 536 | } 537 | 538 | changeInValue[xyz[i]] = changeInValueB[xyz[i]]; 539 | } 540 | } 541 | 542 | dir[xyz[i]] = start[xyz[i]] < props['spinTo' + XYZ[i]] ? 'right' : 'left'; 543 | speeds.push(props.speed ? Math.floor(Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]) * props.speed / 360) : props['speed' + XYZ[i]]); 544 | 545 | i += 1; 546 | } 547 | 548 | speeds.sort(function (a, b) { return b - a; }); 549 | this.iterators.spinTo = { x: 0, y: 0, z: 0 }; 550 | props.easing = props.easing || 'linear'; 551 | 552 | function run() { 553 | i = 0; 554 | 555 | while (i < 3) { 556 | currentMax = changeInValue[xyz[i]]; 557 | currentSpeed = props.speed ? speeds[0] : props['speed' + XYZ[i]]; 558 | 559 | if (currentMax !== 0 && currentSpeed !== 0) { 560 | currentDeg = self['pos' + XYZ[i]]; 561 | currentIterator = self.iterators.spinTo[xyz[i]]; 562 | 563 | currentDeg = currentSpeed === 0 ? 0 : self._ease[props.easing](currentIterator, 0, currentMax, currentSpeed); 564 | 565 | if (dir[xyz[i]] === 'right') { 566 | currentDeg += start[xyz[i]]; 567 | currentMax += start[xyz[i]]; 568 | 569 | if (currentDeg < currentMax) { 570 | currentIterator += 1; 571 | } else { 572 | currentDeg = currentMax; 573 | done[xyz[i]] = true; 574 | } 575 | } else { 576 | currentDeg = start[xyz[i]] - currentDeg; 577 | currentMax = start[xyz[i]] - currentMax; 578 | 579 | if (currentDeg > currentMax) { 580 | currentIterator += 1; 581 | } else { 582 | currentDeg = currentMax; 583 | done[xyz[i]] = true; 584 | } 585 | } 586 | 587 | self['pos' + XYZ[i]] = currentDeg; 588 | self.iterators.spinTo[xyz[i]] = currentIterator; 589 | } else { 590 | done[xyz[i]] = true; 591 | } 592 | 593 | i += 1; 594 | } 595 | 596 | self.applyRotation(); 597 | 598 | i = 0; 599 | 600 | while (i < 3) { 601 | if (done[xyz[i]] && props.repeat) { 602 | self['pos' + XYZ[i]] = start[xyz[i]]; 603 | self.iterators.spinTo[xyz[i]] = 0; 604 | done[xyz[i]] = false; 605 | } 606 | 607 | i += 1; 608 | } 609 | 610 | if (done.x && done.y && done.z && !props.repeat) { 611 | self.isFocusing = false; 612 | if (props.callback) { props.callback(); } 613 | return; 614 | } 615 | 616 | self.timers[props.timer] = requestAnimationFrame(run); 617 | } 618 | 619 | run(); 620 | }, 621 | 622 | // #### Easing functions 623 | _ease: { 624 | // ##### Linear 625 | // * `parameters` (apply for all easing functions below): 626 | // - `currentIteration` __number__ Current iteration. 627 | // - `startValue` __number__ Start value. For example: '10'. 628 | // - `changeInValue` __number__ Change in value. For example '40' means that if value started at 10, it would go up to 50. 629 | // - `totalIterations` __number__ Tells how many iterations should pass until the animation is done. 630 | linear: function (currentIteration, startValue, changeInValue, totalIterations) { 631 | return changeInValue * currentIteration / totalIterations + startValue; 632 | }, 633 | 634 | // ##### Out 635 | out: function (currentIteration, startValue, changeInValue, totalIterations) { // outCirc 636 | currentIteration = currentIteration / totalIterations - 1; 637 | return changeInValue * Math.sqrt(1 - Math.pow(currentIteration, 2)) + startValue; 638 | }, 639 | 640 | // ##### In Out 641 | inOut: function (currentIteration, startValue, changeInValue, totalIterations) { // inOutCirc 642 | return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue; 643 | } 644 | }, 645 | 646 | // #### Calculate Iterations 647 | // Calculates approximate number of iterations. 648 | // Converts milliseconds into number of animation frames for the cube. 649 | // It's assumed here that `requestAnimationFrame` will produce 60 frames per second. 650 | // 651 | // * parameters: `milliseconds` __number__ Time in milliseconds. 652 | // * return: __number__ Returns number of iterations. 653 | _calculateIterations: function (milliseconds) { 654 | return milliseconds * 60 / 1000; 655 | }, 656 | 657 | // #### Get Prefix 658 | // Check if a browser prefix is necessary and, if it is, choose the right one. 659 | // Test is based on `transform` property which necessary for the script to work. 660 | // 661 | // * return: __Numeric__ Returns number of iterations. 662 | _getPrefix: function () { 663 | var style = document.documentElement.style, 664 | prefix; 665 | if (style.webkitTransform !== undefined) { prefix = 'webkit'; } 666 | if (style.mozTransform !== undefined) { prefix = 'moz'; } 667 | if (style.msTransform !== undefined) { prefix = 'ms'; } 668 | return prefix; 669 | }, 670 | 671 | // #### Has Parent 672 | // Check if one element (`$parentEl`) is parent of the second one (`$el`) 673 | // 674 | // * parameters: 675 | // - `$el` __object__ DOM element (assumed children). 676 | // - `$parentEl` __object__ DOM element (assumed parent). 677 | // * return: __boolean__ Returns true if `$parentEl` is `$el` parent. 678 | _hasParent: function ($el, $parentEl) { 679 | var $parentNode = $el.parentNode; 680 | 681 | while ($parentNode !== $parentEl && $parentNode !== document) { 682 | $parentNode = $parentNode.parentNode; 683 | } 684 | 685 | return $parentNode === $parentEl ? true : false; 686 | }, 687 | 688 | // #### Remove Class 689 | // Remove CSS class from an element. 690 | // 691 | // * parameters: 692 | // - `$el` __object__ DOM element 693 | // - `className` __string__ class' name, example: *'my-class'* 694 | _removeClass: function ($el, className) { 695 | var regex = new RegExp('\\b' + className + '\\b', 'g'); 696 | $el.className = $el.className.replace(regex, ''); 697 | } 698 | }; 699 | }()); -------------------------------------------------------------------------------- /cube.min.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var a,b;a={animationFrame:function(){return!!window.requestAnimationFrame},css3d:function(){function a(){for(e=0,f=k.length;f>e;e+=1)if(k[e].length>0){if(void 0!==j[k[e]+"TransformStyle"]&&(j[k[e]+"TransformStyle"]="preserve-3d",j[k[e]+"TransformStyle"].length>0))return j[k[e]+"TransformStyle"]="",!0}else if(void 0!==j.transformStyle&&(j.transformStyle="preserve-3d",j.transformStyle.length>0))return j.transformStyle="",!0;return!1}if(void 0===document.querySelector)return!1;var b,c,d,e,f,g="temporaryCubeCSS3dElement",h="temporaryCubeCSS3dStyle",i=document.body,j=document.documentElement.style,k=["webkit","moz","ms",""];return d=a(),d&&void 0!==j.webkitPerspective&&(c=document.createElement("style"),b=document.createElement("div"),c.id=h,b.id=g,i.appendChild(c),i.appendChild(b),c.textContent=["@media (transform-3d), (-webkit-transform-3d) {"," #"+g+"{"," left: 9px;"," position: absolute;"," height: 5px;"," margin: 0;"," padding: 0;"," border: 0"," }","}"].join("\n"),d=9===b.offsetLeft&&5===b.offsetHeight,i.removeChild(c),i.removeChild(b)),d}},a.animationFrame()&&a.css3d()&&(document.documentElement.className+=" cube-3d-available"),b=function(c,d){return a.animationFrame()&&a.css3d()?new b.instance(c,d||{}):{applyRotation:function(){return!1},rotate:function(){return!1},focusOn:function(){return!1},spinTo:function(){return!1}}},window.Cube=b,b.instance=function(a,b){b.perspective=b.perspective||1100,this.$cube=document.querySelector(a||"#the-cube"),this.props=b,this.rotatePropsSet=!1,this.rotateDir="right",this.speedX=0,this.speedY=0,this.speedZ=0,this.posX=0,this.posY=0,this.posZ=0,this.snapshotX=0,this.snapshotY=0,this.snapshotZ=0,this.isRotating=!1,this.isFocusing=!1,this.hasFocused=!1,this.iterators={},this.timers={}},b.instance.prototype={xyz:["x","y","z"],XYZ:["X","Y","Z"],sides:{"side-1":[0,90,0],"side-2":[90,0,0],"side-3":[0,0,0],"side-4":[270,0,0],"side-5":[0,270,0],"side-6":[0,180,0]},applyRotation:function(a){var b,c=this._getPrefix(),d="perspective("+this.props.perspective+"px)",e=0;if(a=a||{},a.x&&a.y&&a.z)for(;3>e;)b=a[this.xyz[e]],b=isNaN(b)?0:b,this["pos"+this.XYZ[e]]=b,e+=1;else if(a.side){if(!this.sides[a.side])throw'You\'ve probably entered wrong string as a "side" in "applyRotation". Try "side-1", "side-2", "side-3", "side-4", "side-5", or "side-6"';for(;3>e;)b=this.sides[a.side][e],this["pos"+this.XYZ[e]]=b,e+=1}for(e=0;3>e;)b=this["pos"+this.XYZ[e]],d+=" rotate"+this.XYZ[e]+"("+b+"deg)",e+=1;this.$cube.style[c?c+"Transform":"transform"]=d},rotate:function(a){var b,c=0,d=0,e=this.XYZ,f=this;if(a=a||{},f.rotateDir=a.rotateDir||f.rotateDir,f.isRotating=!0,a.startSide&&void 0===f.sides[a.startSide])throw'You\'ve typed wrong value for "startSide" option.';if(f.isFocusing=!1,!f.rotatePropsSet){for(;3>c;)a.startSide&&(a["start"+e[c]]=f.sides[a.startSide][c]),f["pos"+e[c]]=a["start"+e[c]]||0,b=a["speed"+e[c]],b=0===b?0:b||360,f["speed"+e[c]]=b,c+=1;f.rotateDir=a.rotateDir||f.rotateDir,f.rotatePropsSet=!0}"left"===f.rotateDir&&(d=-360),"right"===f.rotateDir&&(d=360),f._spinTo({spinToX:a.startX?a.startX+d:d,spinToY:a.startY?a.startY+d:d,spinToZ:a.startZ?a.startZ+d:d,speedX:f.speedX,speedY:f.speedY,speedZ:f.speedZ,timer:"rotate",repeat:!0,easing:"linear"})},focusOn:function(a){function b(){if(a.bounceBack&&cancelAnimationFrame(d.timers.deFocus),d.isFocusing||(d.snapshotX=d.posX,d.snapshotY=d.posY,d.snapshotZ=d.posZ),a.spinTo&&void 0===d.sides[a.spinTo])throw'You\'ve typed wrong value for "spinTo" option.';a.spinTo&&void 0!==d.sides[a.spinTo]&&(a.spinToX=d.sides[a.spinTo][0],a.spinToY=d.sides[a.spinTo][1],a.spinToZ=d.sides[a.spinTo][2]),d._spinTo({spinToX:a.spinToX||0,spinToY:a.spinToY||0,spinToZ:a.spinToZ||0,speed:a.speed||2e3,timer:"spinTo",easing:"out",callback:function(){d.$cube.className+=" focused",d.hasFocused=!0}})}function c(){cancelAnimationFrame(d.timers.spinTo),cancelAnimationFrame(d.timers.rotate),d._removeClass(d.$cube,"focused"),d.hasFocused=!1,a.bounceBack?d._spinTo({spinToX:d.snapshotX,spinToY:d.snapshotY,spinToZ:d.snapshotZ,speed:a.speed||2e3,timer:"deFocus",easing:"out",callback:function(){d.isRotating&&d.rotate({startX:d.posX,startY:d.posY,startZ:d.posZ})}}):d.isRotating&&d.rotate({startX:d.posX,startY:d.posY,startZ:d.posZ})}var d=this,e=null===window.ontouchstart,f=e?"touchstart":"mouseover";a=a||{},d.$cube.addEventListener(f,function(a){d.hasFocused||(a.preventDefault(),cancelAnimationFrame(d.timers.rotate),b())}),d.$cube.addEventListener("mouseout",c),e&&document.addEventListener("touchstart",function(a){var b=a.target;d._hasParent(b,d.$cube)||c()})},_spinTo:function(a){function b(){for(g=0;3>g;)c=k[p[g]],e=a.speed?j[0]:a["speed"+q[g]],0!==c&&0!==e?(d=h["pos"+q[g]],f=h.iterators.spinTo[p[g]],d=0===e?0:h._ease[a.easing](f,0,c,e),"right"===n[p[g]]?(d+=i[p[g]],c+=i[p[g]],c>d?f+=1:(d=c,o[p[g]]=!0)):(d=i[p[g]]-d,c=i[p[g]]-c,d>c?f+=1:(d=c,o[p[g]]=!0)),h["pos"+q[g]]=d,h.iterators.spinTo[p[g]]=f):o[p[g]]=!0,g+=1;for(h.applyRotation(),g=0;3>g;)o[p[g]]&&a.repeat&&(h["pos"+q[g]]=i[p[g]],h.iterators.spinTo[p[g]]=0,o[p[g]]=!1),g+=1;return o.x&&o.y&&o.z&&!a.repeat?(h.isFocusing=!1,void(a.callback&&a.callback())):void(h.timers[a.timer]=requestAnimationFrame(b))}var c,d,e,f,g=0,h=this,i={},j=[],k={},l={},m={},n={},o={},p=h.xyz,q=h.XYZ;for(a.speed=h._calculateIterations(a.speed),h.isFocusing=a.repeat?!1:!0;3>g;)i[p[g]]=h["pos"+q[g]],a["speed"+q[g]]&&(a["speed"+q[g]]=h._calculateIterations(a["speed"+q[g]])),a.repeat?k[p[g]]=Math.abs(i[p[g]]-a["spinTo"+q[g]]):(l[p[g]]=Math.abs(i[p[g]]-a["spinTo"+q[g]]),m[p[g]]=Math.abs(i[p[g]]>a["spinTo"+q[g]]?i[p[g]]-a["spinTo"+q[g]]-360:i[p[g]]-a["spinTo"+q[g]]+360),l[p[g]]a["spinTo"+q[g]]?a["spinTo"+q[g]]+=360:a["spinTo"+q[g]]-=360,k[p[g]]=m[p[g]])),n[p[g]]=i[p[g]] li > div { 135 | -moz-box-sizing: border-box; /* firefox */ 136 | -ms-box-sizing: border-box; /* ie */ 137 | -webkit-box-sizing: border-box; /* webkit */ 138 | -khtml-box-sizing: border-box; /* konqueror */ 139 | box-sizing: border-box; /* css3 */ 140 | } 141 | 142 | 143 | /*---------------------- Jump Page -----------------------------*/ 144 | #jump_to, #jump_page { 145 | margin: 0; 146 | background: white; 147 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 148 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 149 | font: 16px Arial; 150 | cursor: pointer; 151 | text-align: right; 152 | list-style: none; 153 | } 154 | 155 | #jump_to a { 156 | text-decoration: none; 157 | } 158 | 159 | #jump_to a.large { 160 | display: none; 161 | } 162 | #jump_to a.small { 163 | font-size: 22px; 164 | font-weight: bold; 165 | color: #676767; 166 | } 167 | 168 | #jump_to, #jump_wrapper { 169 | position: fixed; 170 | right: 0; top: 0; 171 | padding: 10px 15px; 172 | margin:0; 173 | } 174 | 175 | #jump_wrapper { 176 | display: none; 177 | padding:0; 178 | } 179 | 180 | #jump_to:hover #jump_wrapper { 181 | display: block; 182 | } 183 | 184 | #jump_page { 185 | padding: 5px 0 3px; 186 | margin: 0 0 25px 25px; 187 | } 188 | 189 | #jump_page .source { 190 | display: block; 191 | padding: 15px; 192 | text-decoration: none; 193 | border-top: 1px solid #eee; 194 | } 195 | 196 | #jump_page .source:hover { 197 | background: #f5f5ff; 198 | } 199 | 200 | #jump_page .source:first-child { 201 | } 202 | 203 | /*---------------------- Low resolutions (> 320px) ---------------------*/ 204 | @media only screen and (min-width: 320px) { 205 | .pilwrap { display: none; } 206 | 207 | ul.sections > li > div { 208 | display: block; 209 | padding:5px 10px 0 10px; 210 | } 211 | 212 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 213 | padding-left: 30px; 214 | } 215 | 216 | ul.sections > li > div.content { 217 | overflow-x:auto; 218 | -webkit-box-shadow: inset 0 0 5px #e5e5ee; 219 | box-shadow: inset 0 0 5px #e5e5ee; 220 | border: 1px solid #dedede; 221 | margin:5px 10px 5px 10px; 222 | padding-bottom: 5px; 223 | } 224 | 225 | ul.sections > li > div.annotation pre { 226 | margin: 7px 0 7px; 227 | padding-left: 15px; 228 | } 229 | 230 | ul.sections > li > div.annotation p tt, .annotation code { 231 | background: #f8f8ff; 232 | border: 1px solid #dedede; 233 | font-size: 12px; 234 | padding: 0 0.2em; 235 | } 236 | } 237 | 238 | /*---------------------- (> 481px) ---------------------*/ 239 | @media only screen and (min-width: 481px) { 240 | #container { 241 | position: relative; 242 | } 243 | body { 244 | background-color: #F5F5FF; 245 | font-size: 15px; 246 | line-height: 21px; 247 | } 248 | pre, tt, code { 249 | line-height: 18px; 250 | } 251 | p, ul, ol { 252 | margin: 0 0 15px; 253 | } 254 | 255 | 256 | #jump_to { 257 | padding: 5px 10px; 258 | } 259 | #jump_wrapper { 260 | padding: 0; 261 | } 262 | #jump_to, #jump_page { 263 | font: 10px Arial; 264 | text-transform: uppercase; 265 | } 266 | #jump_page .source { 267 | padding: 5px 10px; 268 | } 269 | #jump_to a.large { 270 | display: inline-block; 271 | } 272 | #jump_to a.small { 273 | display: none; 274 | } 275 | 276 | 277 | 278 | #background { 279 | position: absolute; 280 | top: 0; bottom: 0; 281 | width: 350px; 282 | background: #fff; 283 | border-right: 1px solid #e5e5ee; 284 | z-index: -1; 285 | } 286 | 287 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 288 | padding-left: 40px; 289 | } 290 | 291 | ul.sections > li { 292 | white-space: nowrap; 293 | margin-bottom: 30px; 294 | } 295 | 296 | ul.sections > li > div { 297 | display: inline-block; 298 | } 299 | 300 | ul.sections > li > div.annotation { 301 | max-width: 350px; 302 | min-width: 350px; 303 | min-height: 5px; 304 | padding: 13px; 305 | overflow-x: hidden; 306 | white-space: normal; 307 | vertical-align: top; 308 | text-align: left; 309 | } 310 | ul.sections > li > div.annotation pre { 311 | margin: 15px 0 15px; 312 | padding-left: 15px; 313 | } 314 | 315 | ul.sections > li > div.content { 316 | padding: 13px; 317 | vertical-align: top; 318 | border: none; 319 | -webkit-box-shadow: none; 320 | box-shadow: none; 321 | } 322 | 323 | .pilwrap { 324 | position: relative; 325 | display: inline; 326 | } 327 | 328 | .pilcrow { 329 | font: 12px Arial; 330 | text-decoration: none; 331 | color: #454545; 332 | position: absolute; 333 | top: -2px; left: -20px; 334 | padding: 1px 2px; 335 | opacity: 0; 336 | -webkit-transition: opacity 0.2s linear; 337 | } 338 | .for-h1 .pilcrow { 339 | top: 47px; 340 | } 341 | .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { 342 | top: 35px; 343 | } 344 | 345 | ul.sections > li > div.annotation:hover .pilcrow { 346 | opacity: 1; 347 | } 348 | } 349 | 350 | /*---------------------- (> 1025px) ---------------------*/ 351 | @media only screen and (min-width: 1025px) { 352 | 353 | body { 354 | font-size: 16px; 355 | line-height: 24px; 356 | } 357 | 358 | #background { 359 | width: 525px; 360 | } 361 | ul.sections > li > div.annotation { 362 | max-width: 525px; 363 | min-width: 525px; 364 | padding: 10px 25px 1px 50px; 365 | } 366 | ul.sections > li > div.content { 367 | padding: 9px 15px 16px 25px; 368 | } 369 | } 370 | 371 | /*---------------------- Syntax Highlighting -----------------------------*/ 372 | 373 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 374 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 375 | /* 376 | 377 | github.com style (c) Vasily Polovnyov 378 | 379 | */ 380 | 381 | pre code { 382 | display: block; padding: 0.5em; 383 | color: #000; 384 | background: #f8f8ff 385 | } 386 | 387 | pre .hljs-comment, 388 | pre .hljs-template_comment, 389 | pre .hljs-diff .hljs-header, 390 | pre .hljs-javadoc { 391 | color: #408080; 392 | font-style: italic 393 | } 394 | 395 | pre .hljs-keyword, 396 | pre .hljs-assignment, 397 | pre .hljs-literal, 398 | pre .hljs-css .hljs-rule .hljs-keyword, 399 | pre .hljs-winutils, 400 | pre .hljs-javascript .hljs-title, 401 | pre .hljs-lisp .hljs-title, 402 | pre .hljs-subst { 403 | color: #954121; 404 | /*font-weight: bold*/ 405 | } 406 | 407 | pre .hljs-number, 408 | pre .hljs-hexcolor { 409 | color: #40a070 410 | } 411 | 412 | pre .hljs-string, 413 | pre .hljs-tag .hljs-value, 414 | pre .hljs-phpdoc, 415 | pre .hljs-tex .hljs-formula { 416 | color: #219161; 417 | } 418 | 419 | pre .hljs-title, 420 | pre .hljs-id { 421 | color: #19469D; 422 | } 423 | pre .hljs-params { 424 | color: #00F; 425 | } 426 | 427 | pre .hljs-javascript .hljs-title, 428 | pre .hljs-lisp .hljs-title, 429 | pre .hljs-subst { 430 | font-weight: normal 431 | } 432 | 433 | pre .hljs-class .hljs-title, 434 | pre .hljs-haskell .hljs-label, 435 | pre .hljs-tex .hljs-command { 436 | color: #458; 437 | font-weight: bold 438 | } 439 | 440 | pre .hljs-tag, 441 | pre .hljs-tag .hljs-title, 442 | pre .hljs-rules .hljs-property, 443 | pre .hljs-django .hljs-tag .hljs-keyword { 444 | color: #000080; 445 | font-weight: normal 446 | } 447 | 448 | pre .hljs-attribute, 449 | pre .hljs-variable, 450 | pre .hljs-instancevar, 451 | pre .hljs-lisp .hljs-body { 452 | color: #008080 453 | } 454 | 455 | pre .hljs-regexp { 456 | color: #B68 457 | } 458 | 459 | pre .hljs-class { 460 | color: #458; 461 | font-weight: bold 462 | } 463 | 464 | pre .hljs-symbol, 465 | pre .hljs-ruby .hljs-symbol .hljs-string, 466 | pre .hljs-ruby .hljs-symbol .hljs-keyword, 467 | pre .hljs-ruby .hljs-symbol .hljs-keymethods, 468 | pre .hljs-lisp .hljs-keyword, 469 | pre .hljs-tex .hljs-special, 470 | pre .hljs-input_number { 471 | color: #990073 472 | } 473 | 474 | pre .hljs-builtin, 475 | pre .hljs-constructor, 476 | pre .hljs-built_in, 477 | pre .hljs-lisp .hljs-title { 478 | color: #0086b3 479 | } 480 | 481 | pre .hljs-preprocessor, 482 | pre .hljs-pi, 483 | pre .hljs-doctype, 484 | pre .hljs-shebang, 485 | pre .hljs-cdata { 486 | color: #999; 487 | font-weight: bold 488 | } 489 | 490 | pre .hljs-deletion { 491 | background: #fdd 492 | } 493 | 494 | pre .hljs-addition { 495 | background: #dfd 496 | } 497 | 498 | pre .hljs-diff .hljs-change { 499 | background: #0086b3 500 | } 501 | 502 | pre .hljs-chunk { 503 | color: #aaa 504 | } 505 | 506 | pre .hljs-tex .hljs-formula { 507 | opacity: 0.5; 508 | } 509 | -------------------------------------------------------------------------------- /images/cube/cube-texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.jpg -------------------------------------------------------------------------------- /images/cube/cube-texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.png -------------------------------------------------------------------------------- /images/cube/cube-texture.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.psd -------------------------------------------------------------------------------- /images/cube/cube-texture.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.zip -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CSS3 Cube - Xfive Open Source Plugin 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 |
30 |

CSS3 Cube

31 |

cube.js is a light script which allows you to add a fancy rotating CSS3 cube to your page!

32 |
33 | 34 |
35 | 36 | 84 | 85 | 251 | 252 | 264 | 265 | 274 | 275 | 279 | 280 |
281 | Xfive - Developers who care. We offer advanced front-end, JavaScript, WordPress and back-end development. 282 |
283 |
284 | 285 | Back to the top 286 | 287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cube-plugin", 3 | "devDependencies": { 4 | "grunt": "~0.4.2", 5 | "grunt-contrib-sass": "~0.6.0", 6 | "grunt-contrib-watch": "~0.5.3", 7 | "grunt-contrib-jshint": "~0.8.0", 8 | "grunt-docco": "~0.3.2", 9 | "grunt-contrib-uglify": "~0.3.2" 10 | } 11 | } 12 | --------------------------------------------------------------------------------