├── .gitignore ├── .htaccess ├── CONTRIBUTORS.md ├── Gruntfile.coffee ├── LICENSE.md ├── README.md ├── animation.html ├── bower.json ├── config.rb ├── css └── clank.css ├── device-wraps.html ├── dist ├── clank.js ├── clank.min.css └── clank.min.js ├── font-generation-templates ├── custom-android.css ├── custom-android.json ├── custom-app.css ├── custom-app.json ├── custom-ios.css └── custom-ios.json ├── fonts ├── android-icons.eot ├── android-icons.svg ├── android-icons.ttf ├── android-icons.woff ├── app-icons.eot ├── app-icons.svg ├── app-icons.ttf ├── app-icons.woff ├── ios-icons.eot ├── ios-icons.svg ├── ios-icons.ttf └── ios-icons.woff ├── images ├── icons_svg_source │ ├── android │ │ ├── android4-back-chevron.ai │ │ ├── android4-back-chevron.svg │ │ ├── android4-battery-colored.svg │ │ ├── android4-battery.svg │ │ ├── android4-network.svg │ │ ├── android4-system-apps.svg │ │ ├── android4-system-back.svg │ │ ├── android4-system-home.svg │ │ └── android4-wifi.svg │ ├── app │ │ ├── app-add.svg │ │ ├── app-arrow-down.svg │ │ ├── app-arrow-left.svg │ │ ├── app-arrow-right.svg │ │ ├── app-arrow-up.svg │ │ ├── app-bekijken.svg │ │ ├── app-boeken.svg │ │ ├── app-circle.svg │ │ ├── app-heart-filled.svg │ │ ├── app-heart.svg │ │ ├── app-historiek.svg │ │ ├── app-list.svg │ │ ├── app-minus.svg │ │ ├── app-ontleend.svg │ │ ├── app-square.svg │ │ └── app-uitlenen.svg │ └── ios │ │ ├── ios6-alarm.svg │ │ ├── ios6-battery.svg │ │ ├── ios6-locate.svg │ │ ├── ios6-orientation-lock.svg │ │ ├── ios7-back-chevron.svg │ │ ├── ios7-battery-full.svg │ │ ├── ios7-orientation-lock.svg │ │ ├── ios7-reception-empty.svg │ │ └── ios7-reception-full.svg ├── landscape │ ├── galaxy-nexus.png │ ├── ipad3.png │ ├── iphone4.png │ ├── iphone5.png │ └── nexus7.png ├── pattern.png ├── placeholder.png ├── portrait │ ├── galaxy-nexus.png │ ├── ipad3.png │ ├── iphone4.png │ ├── iphone5.png │ └── nexus7.png └── slider │ ├── fauna1.jpg │ ├── fauna2.jpg │ ├── fauna3.jpg │ └── fauna4.jpg ├── index.html ├── js └── clank │ ├── clank.js │ ├── ratchet │ ├── fingerblast.js │ ├── sliders.js │ └── toggles.js │ └── state-loader.js ├── orientation.html ├── os-switch.html ├── package.json ├── scss ├── clank.scss └── clank │ ├── _base.scss │ ├── _mixins.scss │ ├── _vars.scss │ ├── components │ ├── _alerts-alt.scss │ ├── _alerts.scss │ ├── _animations.scss │ ├── _article.scss │ ├── _badge.scss │ ├── _base-layout.scss │ ├── _buttons.scss │ ├── _close.scss │ ├── _data-table.scss │ ├── _device_wraps.scss │ ├── _forms.scss │ ├── _help-txt.scss │ ├── _loading.scss │ ├── _modal.scss │ ├── _os_chrome.scss │ ├── _popover.scss │ ├── _sliders.scss │ ├── _tab-bar.scss │ ├── _table-view.scss │ ├── _toggles.scss │ └── _utilities.scss │ ├── icon-fonts │ ├── _android-icons.scss │ ├── _app-icons.scss │ └── _ios-icons.scss │ └── screens │ └── _demo1.scss ├── states ├── page1.html ├── page2.html ├── page3.html ├── pop.html ├── title1.html ├── title2.html └── title3.html └── tests ├── buttons.html ├── popovers.html └── toggles.html /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | build 3 | .tmp 4 | bower_components 5 | node_modules 6 | .sass-cache 7 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | ErrorDocument 404 /404.html 3 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | ## Contributors to this project: 2 | 3 | * Project lead - Johan Ronsse https://github.com/Wolfr/ 4 | * Javascript, state loader for animations - Geert Pasteels (https://github.com/Enome/) -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Grunt workflow: for Compass & Webfonts 3 | ### 4 | 5 | mountFolder = (connect, dir) -> 6 | return connect.static(require('path').resolve(dir)) 7 | 8 | module.exports = (grunt) -> 9 | @loadNpmTasks('grunt-contrib-compass') 10 | @loadNpmTasks('grunt-contrib-copy') 11 | @loadNpmTasks('grunt-contrib-watch') 12 | @loadNpmTasks('grunt-contrib-uglify') 13 | @loadNpmTasks('grunt-contrib-concat') 14 | @loadNpmTasks('grunt-contrib-cssmin') 15 | @loadNpmTasks('grunt-webfont') 16 | 17 | @initConfig 18 | doWatch: 19 | css: 20 | files: ['scss/**/*.scss'] 21 | tasks: ['compass'] 22 | iconsapp: 23 | files: ['images/icons_svg_source/app/*.svg'] 24 | tasks: ['webfont'] 25 | iconsandroid: 26 | files: ['images/icons_svg_source/android/*.svg'] 27 | tasks: ['webfont'] 28 | iconsios: 29 | files: ['images/icons_svg_source/ios/*.svg'] 30 | tasks: ['webfont'] 31 | 32 | # generate 3 webfonts, one for Android system, once for iOS system, one for the app itself 33 | webfont: 34 | iconsapp: 35 | src: 'images/icons_svg_source/app/*.svg' 36 | dest: 'fonts' 37 | destCss: 'scss/clank/icon-fonts' 38 | options: 39 | font: 'app-icons' 40 | hashes: false 41 | htmlDemo: false 42 | stylesheet: 'scss' 43 | relativeFontPath: '../fonts' 44 | template: 'font-generation-templates/custom-app.css' 45 | iconsandroid: 46 | src: 'images/icons_svg_source/android/*.svg' 47 | dest: 'fonts' 48 | destCss: 'scss/clank/icon-fonts' 49 | options: 50 | font: 'android-icons' 51 | hashes: false 52 | htmlDemo: false 53 | stylesheet: 'scss' 54 | relativeFontPath: '../fonts' 55 | template: 'font-generation-templates/custom-android.css' 56 | iconsios: 57 | src: 'images/icons_svg_source/ios/*.svg' 58 | dest: 'fonts' 59 | destCss: 'scss/clank/icon-fonts' 60 | options: 61 | font: 'ios-icons' 62 | hashes: false 63 | htmlDemo: false 64 | stylesheet: 'scss' 65 | relativeFontPath: '../fonts' 66 | template: 'font-generation-templates/custom-ios.css' 67 | 68 | compass: 69 | all: 70 | options: 71 | sassDir: 'scss' 72 | cssDir: 'css' 73 | 74 | pkg: grunt.file.readJSON('package.json') 75 | 76 | concat: 77 | options: 78 | stripBanners: true, 79 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */' 80 | dist: 81 | src: ['js/clank/ratchet/fingerblast.js', 'js/clank/ratchet/sliders.js', 'js/clank/ratchet/toggles.js', 'js/clank/clank.js', 'js/clank/stateloader.js'] 82 | dest: 'dist/clank.js' 83 | 84 | uglify: 85 | options: 86 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */' 87 | all: 88 | files: 89 | 'dist/clank.min.js': ['dist/clank.js'] 90 | 91 | cssmin: 92 | add_banner: 93 | options: 94 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */' 95 | files: 96 | 'dist/clank.min.css': ['css/clank.css'] 97 | 98 | @renameTask 'watch', 'doWatch' 99 | @registerTask('watch', ['compass', 'doWatch']) 100 | @registerTask('build', ['compass', 'concat', 'uglify', 'cssmin']) 101 | @registerTask('default', ['build']) -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This source code contains a copy of Clank (http://getclank.com) which is MIT Licensed. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clank README 2 | 3 | ## What is Clank? 4 | 5 | Clank is an open source HTML/CSS prototyping framework for tablet and smartphone apps. Think of it as Twitter Bootstrap but for prototyping native apps. 6 | 7 | ## Demos 8 | 9 | [View the demos](http://getclank.com/demos/) 10 | 11 | ## How to use 12 | 13 | 14 | Depending on your HTML/CSS skill level you can choose to use the Clank CSS files as "standalone" assets and build your prototype with HTML only. Refer to [getclank.com](http://getclank.com/) for documentation on which markup and CSS classes to use. 15 | 16 | This repository provides a sample config.rb to work with [Compass](http://compass-style.org/) - you can run `compass` watch and the SCSS will compile to CSS. 17 | 18 | If you want to take things a bit further (SCSS generation + icon font generation) do the following: 19 | 20 | * Make sure you have [bower](https://github.com/bower/bower) and [grunt](http://gruntjs.com/) set up. 21 | * Run `npm install` and `bower install` to install the necessary dependencies. 22 | * Run `grunt watch` to watch for SCSS changes and to generate the icon fonts. 23 | 24 | For a full workflow for making a prototype and documenting it you can use the [Clank-Jekyll](https://github.com/Wolfr/clank-jekyll) project. 25 | 26 | ## Acknowledgements 27 | 28 | Clank was inspired and uses parts of [Ratchet](http://maker.github.io/ratchet/). 29 | 30 | ## Contributing 31 | 32 | Open a [Github issue](https://github.com/Wolfr/clank/issues) if you have any feedback or ideas. 33 | 34 | -------------------------------------------------------------------------------- /animation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Bell 42 | 43 | 20:49 44 | 45 | 3G 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 |
54 |
55 |
56 | 57 |
58 |
59 | 60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clank", 3 | "version": "0.3.5", 4 | "dependencies": { 5 | "jquery.extendedinput.js": "~1.1.0", 6 | "jquery": "~2.0.2", 7 | "state-loader": "*" 8 | }, 9 | "devDependencies": { 10 | "jquery.extendedinput.js": "~1.1.0", 11 | "jquery": "~2.0.2" 12 | } 13 | } -------------------------------------------------------------------------------- /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 = "scss" 7 | images_dir = "images" 8 | javascripts_dir = "js" 9 | 10 | # You can select your preferred output style here (can be overridden via the command line): 11 | # output_style = :expanded or :nested or :compact or :compressed 12 | 13 | output_style = :expanded 14 | 15 | # To enable relative paths to assets via compass helper functions. Uncomment: 16 | # relative_assets = true 17 | 18 | # To disable debugging comments that display the original location of your selectors. Uncomment: 19 | line_comments = false 20 | 21 | # If you prefer the indented syntax, you might want to regenerate this 22 | # project again passing --syntax sass, or you can uncomment this: 23 | # preferred_syntax = :sass 24 | # and then run: 25 | # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass 26 | -------------------------------------------------------------------------------- /device-wraps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 20:49 31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 |
43 |
44 | 45 | 46 | Orientation 47 | 48 |
Device wraps
49 |
50 |
51 |
52 |

Finally if you don't want these device wraps to show, you can switch the $device-wraps variable to "false" in _vars.scss.

53 |

This is useful when you want to make a prototype that can be used on the devices itself.

54 |

All of Clank's CSS works with SCSS. For the full documentation visit getclank.com

55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /dist/clank.js: -------------------------------------------------------------------------------- 1 | /*! clank-dev - v0.0.0 - 2013-12-21 */// FINGERBLAST.js 2 | // -------------- 3 | // Adapted from phantom limb by brian cartensen 4 | 5 | function FingerBlast(element) { 6 | this.element = typeof element == 'string' ? document.querySelector(element) : element; 7 | this.listen(); 8 | } 9 | 10 | FingerBlast.prototype = { 11 | x: NaN, 12 | y: NaN, 13 | 14 | startDistance: NaN, 15 | startAngle: NaN, 16 | 17 | mouseIsDown: false, 18 | 19 | listen: function () { 20 | 21 | var activate = this.activate.bind(this); 22 | var deactivate = this.deactivate.bind(this); 23 | 24 | function contains (element, ancestor) { 25 | var descendants, index, descendant; 26 | if ("compareDocumentPosition" in ancestor) { 27 | return !!(ancestor.compareDocumentPosition(element) & 16); 28 | } else if ("contains" in ancestor) { 29 | return ancestor != element && ancestor.contains(element); 30 | } else { 31 | for (descendants = ancestor.getElementsByTagName("*"), index = 0; descendant = descendants[index++];) { 32 | if (descendant == element) return true; 33 | } 34 | return false; 35 | } 36 | } 37 | 38 | this.element.addEventListener('mouseover', function (e) { 39 | var target = e.relatedTarget; 40 | if (target != this && !contains(target, this)) activate(); 41 | }); 42 | 43 | this.element.addEventListener("mouseout", function (e) { 44 | var target = e.relatedTarget; 45 | if (target != this && !contains(target, this)) deactivate(e); 46 | }); 47 | }, 48 | 49 | activate: function () { 50 | if (this.active) return; 51 | this.element.addEventListener('mousedown', (this.touchStart = this.touchStart.bind(this)), true); 52 | this.element.addEventListener('mousemove', (this.touchMove = this.touchMove.bind(this)), true); 53 | this.element.addEventListener('mouseup', (this.touchEnd = this.touchEnd.bind(this)), true); 54 | this.element.addEventListener('click', (this.click = this.click.bind(this)), true); 55 | this.active = true; 56 | }, 57 | 58 | deactivate: function (e) { 59 | this.active = false; 60 | if (this.mouseIsDown) this.touchEnd(e); 61 | this.element.removeEventListener('mousedown', this.touchStart, true); 62 | this.element.removeEventListener('mousemove', this.touchMove, true); 63 | this.element.removeEventListener('mouseup', this.touchEnd, true); 64 | this.element.removeEventListener('click', this.click, true); 65 | }, 66 | 67 | click: function (e) { 68 | if (e.synthetic) return; 69 | e.preventDefault(); 70 | e.stopPropagation(); 71 | }, 72 | 73 | touchStart: function (e) { 74 | if (e.synthetic || /input|textarea/.test(e.target.tagName.toLowerCase())) return; 75 | 76 | this.mouseIsDown = true; 77 | 78 | e.preventDefault(); 79 | e.stopPropagation(); 80 | 81 | this.fireTouchEvents('touchstart', e); 82 | }, 83 | 84 | touchMove: function (e) { 85 | if (e.synthetic) return; 86 | 87 | e.preventDefault(); 88 | e.stopPropagation(); 89 | 90 | this.move(e.clientX, e.clientY); 91 | 92 | if (this.mouseIsDown) this.fireTouchEvents('touchmove', e); 93 | }, 94 | 95 | touchEnd: function (e) { 96 | if (e.synthetic) return; 97 | 98 | this.mouseIsDown = false; 99 | 100 | e.preventDefault(); 101 | e.stopPropagation(); 102 | 103 | this.fireTouchEvents('touchend', e); 104 | 105 | if (!this.target) return; 106 | 107 | // Mobile Safari moves all the mouse events to fire after the touchend event. 108 | this.target.dispatchEvent(this.createMouseEvent('mouseover', e)); 109 | this.target.dispatchEvent(this.createMouseEvent('mousemove', e)); 110 | this.target.dispatchEvent(this.createMouseEvent('mousedown', e)); 111 | }, 112 | 113 | fireTouchEvents: function (eventName, originalEvent) { 114 | var events = []; 115 | var gestures = []; 116 | 117 | if (!this.target) return; 118 | 119 | // Convert "ontouch*" properties and attributes to listeners. 120 | var onEventName = 'on' + eventName; 121 | 122 | if (onEventName in this.target) { 123 | console.warn('Converting `' + onEventName + '` property to event listener.', this.target); 124 | this.target.addEventListener(eventName, this.target[onEventName], false); 125 | delete this.target[onEventName]; 126 | } 127 | 128 | if (this.target.hasAttribute(onEventName)) { 129 | console.warn('Converting `' + onEventName + '` attribute to event listener.', this.target); 130 | var handler = new GLOBAL.Function('event', this.target.getAttribute(onEventName)); 131 | this.target.addEventListener(eventName, handler, false); 132 | this.target.removeAttribute(onEventName); 133 | } 134 | 135 | // Set up a new event with the coordinates of the finger. 136 | var touch = this.createMouseEvent(eventName, originalEvent); 137 | 138 | events.push(touch); 139 | 140 | // Figure out scale and rotation. 141 | if (events.length > 1) { 142 | var x = events[0].pageX - events[1].pageX; 143 | var y = events[0].pageY - events[1].pageY; 144 | 145 | var distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 146 | var angle = Math.atan2(x, y) * (180 / Math.PI); 147 | 148 | var gestureName = 'gesturechange'; 149 | 150 | if (eventName === 'touchstart') { 151 | gestureName = 'gesturestart'; 152 | this.startDistance = distance; 153 | this.startAngle = angle; 154 | } 155 | 156 | if (eventName === 'touchend') gestureName = 'gestureend'; 157 | 158 | events.forEach(function(event) { 159 | var gesture = this.createMouseEvent.call(event._finger, gestureName, event); 160 | gestures.push(gesture); 161 | }.bind(this)); 162 | 163 | events.concat(gestures).forEach(function(event) { 164 | event.scale = distance / this.startDistance; 165 | event.rotation = this.startAngle - angle; 166 | }); 167 | } 168 | 169 | // Loop through the events array and fill in each touch array. 170 | events.forEach(function(touch) { 171 | touch.touches = events.filter(function(e) { 172 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 173 | }); 174 | 175 | touch.changedTouches = events.filter(function(e) { 176 | return ~e.type.indexOf('touch') && e._finger.target === touch._finger.target; 177 | }); 178 | 179 | touch.targetTouches = touch.changedTouches.filter(function(e) { 180 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 181 | }); 182 | }); 183 | 184 | // Then fire the events. 185 | events.concat(gestures).forEach(function(event, i) { 186 | event.identifier = i; 187 | event._finger.target.dispatchEvent(event); 188 | }); 189 | }, 190 | 191 | createMouseEvent: function (eventName, originalEvent) { 192 | var e = document.createEvent('MouseEvent'); 193 | 194 | e.initMouseEvent(eventName, true, true, 195 | originalEvent.view, originalEvent.detail, 196 | this.x || originalEvent.screenX, this.y || originalEvent.screenY, 197 | this.x || originalEvent.clientX, this.y || originalEvent.clientY, 198 | originalEvent.ctrlKey, originalEvent.shiftKey, 199 | originalEvent.altKey, originalEvent.metaKey, 200 | originalEvent.button, this.target || originalEvent.relatedTarget 201 | ); 202 | 203 | e.synthetic = true; 204 | e._finger = this; 205 | 206 | return e; 207 | }, 208 | 209 | move: function (x, y) { 210 | if (isNaN(x) || isNaN(y)) { 211 | this.target = null; 212 | } else { 213 | this.x = x; 214 | this.y = y; 215 | 216 | if (!this.mouseIsDown) { 217 | this.target = document.elementFromPoint(x, y); 218 | } 219 | } 220 | } 221 | }; 222 | !function () { 223 | 224 | var pageX; 225 | var pageY; 226 | var slider; 227 | var deltaX; 228 | var deltaY; 229 | var offsetX; 230 | var lastSlide; 231 | var startTime; 232 | var resistance; 233 | var sliderWidth; 234 | var slideNumber; 235 | var isScrolling; 236 | var scrollableArea; 237 | 238 | var getSlider = function (target) { 239 | var i, sliders = document.querySelectorAll('.cl-slider ul'); 240 | for (; target && target !== document; target = target.parentNode) { 241 | for (i = sliders.length; i--;) { if (sliders[i] === target) return target; } 242 | } 243 | } 244 | 245 | var getScroll = function () { 246 | var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/); 247 | return parseInt(translate3d ? translate3d[1] : 0) 248 | }; 249 | 250 | var setSlideNumber = function (offset) { 251 | var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round'; 252 | slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) ); 253 | slideNumber += offset; 254 | slideNumber = Math.min(slideNumber, 0); 255 | slideNumber = Math.max(-(slider.children.length - 1), slideNumber); 256 | 257 | } 258 | 259 | var onTouchStart = function (e) { 260 | slider = getSlider(e.target); 261 | 262 | if (!slider) return; 263 | 264 | var firstItem = slider.querySelector('li'); 265 | 266 | scrollableArea = firstItem.offsetWidth * slider.children.length; 267 | isScrolling = undefined; 268 | sliderWidth = slider.offsetWidth; 269 | resistance = 1; 270 | lastSlide = -(slider.children.length - 1); 271 | startTime = +new Date; 272 | pageX = e.touches[0].pageX; 273 | pageY = e.touches[0].pageY; 274 | 275 | setSlideNumber(0); 276 | 277 | slider.style['-webkit-transition-duration'] = 0; 278 | }; 279 | 280 | var onTouchMove = function (e) { 281 | if (e.touches.length > 1 || !slider) return; // Exit if a pinch || no slider 282 | 283 | deltaX = e.touches[0].pageX - pageX; 284 | deltaY = e.touches[0].pageY - pageY; 285 | pageX = e.touches[0].pageX; 286 | pageY = e.touches[0].pageY; 287 | 288 | if (typeof isScrolling == 'undefined') { 289 | isScrolling = Math.abs(deltaY) > Math.abs(deltaX); 290 | } 291 | 292 | if (isScrolling) return; 293 | 294 | offsetX = (deltaX / resistance) + getScroll(); 295 | 296 | e.preventDefault(); 297 | 298 | resistance = slideNumber == 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 : 299 | slideNumber == lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1; 300 | 301 | slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; 302 | }; 303 | 304 | var onTouchEnd = function (e) { 305 | if (!slider || isScrolling) return; 306 | 307 | setSlideNumber( 308 | (+new Date) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0 309 | ); 310 | 311 | offsetX = slideNumber * sliderWidth; 312 | 313 | slider.style['-webkit-transition-duration'] = '.2s'; 314 | slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; 315 | 316 | e = new CustomEvent('slide', { 317 | detail: { slideNumber: Math.abs(slideNumber) }, 318 | bubbles: true, 319 | cancelable: true 320 | }); 321 | 322 | slider.parentNode.dispatchEvent(e); 323 | }; 324 | 325 | window.addEventListener('touchstart', onTouchStart); 326 | window.addEventListener('touchmove', onTouchMove); 327 | window.addEventListener('touchend', onTouchEnd); 328 | 329 | }(); 330 | 331 | !function () { 332 | 333 | var start = {}; 334 | var touchMove = false; 335 | var distanceX = false; 336 | var toggle = false; 337 | 338 | var findToggle = function (target) { 339 | var i, toggles = document.querySelectorAll('.cl-toggle'); 340 | for (; target && target !== document; target = target.parentNode) { 341 | for (i = toggles.length; i--;) { if (toggles[i] === target) return target; } 342 | } 343 | } 344 | 345 | window.addEventListener('touchstart', function (e) { 346 | e = e.originalEvent || e; 347 | 348 | toggle = findToggle(e.target); 349 | 350 | if (!toggle) return; 351 | 352 | var handle = toggle.querySelector('.cl-toggle-handle'); 353 | var toggleWidth = toggle.offsetWidth; 354 | var handleWidth = handle.offsetWidth; 355 | var offset = toggle.classList.contains('active') ? toggleWidth - handleWidth : 0; 356 | 357 | start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY }; 358 | touchMove = false; 359 | 360 | // todo: probably should be moved to the css 361 | toggle.style['-webkit-transition-duration'] = 0; 362 | }); 363 | 364 | window.addEventListener('touchmove', function (e) { 365 | e = e.originalEvent || e; 366 | 367 | if (e.touches.length > 1) return; // Exit if a pinch 368 | 369 | if (!toggle) return; 370 | 371 | var handle = toggle.querySelector('.cl-toggle-handle'); 372 | var current = e.touches[0]; 373 | var toggleWidth = toggle.offsetWidth; 374 | var handleWidth = handle.offsetWidth; 375 | var offset = toggleWidth - handleWidth; 376 | 377 | touchMove = true; 378 | distanceX = current.pageX - start.pageX; 379 | 380 | if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) return; 381 | 382 | e.preventDefault(); 383 | 384 | if (distanceX < 0) return handle.style.webkitTransform = 'translate3d(0,0,0)'; 385 | if (distanceX > offset) return handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'; 386 | 387 | handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)'; 388 | 389 | toggle.classList[(distanceX > (toggleWidth/2 - handleWidth/2)) ? 'add' : 'remove']('active'); 390 | }); 391 | 392 | window.addEventListener('touchend', function (e) { 393 | if (!toggle) return; 394 | 395 | var handle = toggle.querySelector('.cl-toggle-handle'); 396 | var toggleWidth = toggle.offsetWidth; 397 | var handleWidth = handle.offsetWidth; 398 | var offset = toggleWidth - handleWidth; 399 | var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth/2 - handleWidth/2))); 400 | 401 | if (slideOn) handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'; 402 | else handle.style.webkitTransform = 'translate3d(0,0,0)'; 403 | 404 | toggle.classList[slideOn ? 'add' : 'remove']('active'); 405 | 406 | e = new CustomEvent('toggle', { 407 | detail: { isActive: slideOn }, 408 | bubbles: true, 409 | cancelable: true 410 | }); 411 | 412 | toggle.dispatchEvent(e); 413 | 414 | touchMove = false; 415 | toggle = false; 416 | }); 417 | 418 | }(); 419 | 420 | $(function() { 421 | 422 | /** 423 | * Simulate touch 424 | * Make toggles and sliders work on non touch devices 425 | * ! The touch context can only be used once per page 426 | */ 427 | 428 | if ($('.simulate-touch').length > 0) { 429 | var fb = new FingerBlast('.simulate-touch'); 430 | } 431 | 432 | /** 433 | * Radio and checkbox lists 434 | */ 435 | 436 | $('.radio-list input[type="radio"]').change(function() { 437 | // Remove all checked 438 | $(this).parents('.radio-list').find('label').removeClass('checked'); 439 | 440 | // Add class so we can style 441 | $(this).parent().addClass('checked'); 442 | }); 443 | 444 | $('.checkbox-list input[type="checkbox"]').change(function() { 445 | // Action on check/uncheck checkbox 446 | if ($(this).is(':checked')) { 447 | $(this).parent().addClass('checked'); 448 | } else { 449 | $(this).parent().removeClass('checked'); 450 | } 451 | 452 | }); 453 | 454 | /** 455 | * Alerts 456 | */ 457 | 458 | $('*[data-dismiss]').click(function() { 459 | var dismissWhat = $(this).attr('data-dismiss') 460 | $('.' + dismissWhat).addClass('dismissed'); 461 | }); 462 | 463 | /* 464 | Prevent body scrolling when popover context is open 465 | */ 466 | 467 | $('[data-toggle-element="popover-context"]').click(function(e) { 468 | if ($('.cl-popover').is(':visible')) { 469 | $('.cl-content').css('overflow', 'hidden'); 470 | } else { 471 | $('.cl-content').css('overflow', 'scroll'); 472 | } 473 | }); 474 | 475 | /* 476 | Prevent body scrolling when popover context is open 477 | */ 478 | 479 | if ($('.cl-modal').is(':visible')) { 480 | $('.cl-content').css('overflow', 'hidden'); 481 | } else { 482 | $('.cl-content').css('overflow', 'scroll'); 483 | } 484 | 485 | }); -------------------------------------------------------------------------------- /dist/clank.min.js: -------------------------------------------------------------------------------- 1 | /*! clank-dev - v0.0.0 - 2013-12-21 */function FingerBlast(a){this.element="string"==typeof a?document.querySelector(a):a,this.listen()}FingerBlast.prototype={x:0/0,y:0/0,startDistance:0/0,startAngle:0/0,mouseIsDown:!1,listen:function(){function a(a,b){var c,d,e;if("compareDocumentPosition"in b)return!!(16&b.compareDocumentPosition(a));if("contains"in b)return b!=a&&b.contains(a);for(c=b.getElementsByTagName("*"),d=0;e=c[d++];)if(e==a)return!0;return!1}var b=this.activate.bind(this),c=this.deactivate.bind(this);this.element.addEventListener("mouseover",function(c){var d=c.relatedTarget;d==this||a(d,this)||b()}),this.element.addEventListener("mouseout",function(b){var d=b.relatedTarget;d==this||a(d,this)||c(b)})},activate:function(){this.active||(this.element.addEventListener("mousedown",this.touchStart=this.touchStart.bind(this),!0),this.element.addEventListener("mousemove",this.touchMove=this.touchMove.bind(this),!0),this.element.addEventListener("mouseup",this.touchEnd=this.touchEnd.bind(this),!0),this.element.addEventListener("click",this.click=this.click.bind(this),!0),this.active=!0)},deactivate:function(a){this.active=!1,this.mouseIsDown&&this.touchEnd(a),this.element.removeEventListener("mousedown",this.touchStart,!0),this.element.removeEventListener("mousemove",this.touchMove,!0),this.element.removeEventListener("mouseup",this.touchEnd,!0),this.element.removeEventListener("click",this.click,!0)},click:function(a){a.synthetic||(a.preventDefault(),a.stopPropagation())},touchStart:function(a){a.synthetic||/input|textarea/.test(a.target.tagName.toLowerCase())||(this.mouseIsDown=!0,a.preventDefault(),a.stopPropagation(),this.fireTouchEvents("touchstart",a))},touchMove:function(a){a.synthetic||(a.preventDefault(),a.stopPropagation(),this.move(a.clientX,a.clientY),this.mouseIsDown&&this.fireTouchEvents("touchmove",a))},touchEnd:function(a){a.synthetic||(this.mouseIsDown=!1,a.preventDefault(),a.stopPropagation(),this.fireTouchEvents("touchend",a),this.target&&(this.target.dispatchEvent(this.createMouseEvent("mouseover",a)),this.target.dispatchEvent(this.createMouseEvent("mousemove",a)),this.target.dispatchEvent(this.createMouseEvent("mousedown",a))))},fireTouchEvents:function(a,b){var c=[],d=[];if(this.target){var e="on"+a;if(e in this.target&&(console.warn("Converting `"+e+"` property to event listener.",this.target),this.target.addEventListener(a,this.target[e],!1),delete this.target[e]),this.target.hasAttribute(e)){console.warn("Converting `"+e+"` attribute to event listener.",this.target);var f=new GLOBAL.Function("event",this.target.getAttribute(e));this.target.addEventListener(a,f,!1),this.target.removeAttribute(e)}var g=this.createMouseEvent(a,b);if(c.push(g),c.length>1){var h=c[0].pageX-c[1].pageX,i=c[0].pageY-c[1].pageY,j=Math.sqrt(Math.pow(h,2)+Math.pow(i,2)),k=Math.atan2(h,i)*(180/Math.PI),l="gesturechange";"touchstart"===a&&(l="gesturestart",this.startDistance=j,this.startAngle=k),"touchend"===a&&(l="gestureend"),c.forEach(function(a){var b=this.createMouseEvent.call(a._finger,l,a);d.push(b)}.bind(this)),c.concat(d).forEach(function(a){a.scale=j/this.startDistance,a.rotation=this.startAngle-k})}c.forEach(function(a){a.touches=c.filter(function(a){return~a.type.indexOf("touch")&&"touchend"!==a.type}),a.changedTouches=c.filter(function(b){return~b.type.indexOf("touch")&&b._finger.target===a._finger.target}),a.targetTouches=a.changedTouches.filter(function(a){return~a.type.indexOf("touch")&&"touchend"!==a.type})}),c.concat(d).forEach(function(a,b){a.identifier=b,a._finger.target.dispatchEvent(a)})}},createMouseEvent:function(a,b){var c=document.createEvent("MouseEvent");return c.initMouseEvent(a,!0,!0,b.view,b.detail,this.x||b.screenX,this.y||b.screenY,this.x||b.clientX,this.y||b.clientY,b.ctrlKey,b.shiftKey,b.altKey,b.metaKey,b.button,this.target||b.relatedTarget),c.synthetic=!0,c._finger=this,c},move:function(a,b){isNaN(a)||isNaN(b)?this.target=null:(this.x=a,this.y=b,this.mouseIsDown||(this.target=document.elementFromPoint(a,b)))}},!function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n=function(a){for(var b,c=document.querySelectorAll(".cl-slider ul");a&&a!==document;a=a.parentNode)for(b=c.length;b--;)if(c[b]===a)return a},o=function(){var a=c.style.webkitTransform.match(/translate3d\(([^,]*)/);return parseInt(a?a[1]:0)},p=function(a){var b=a?0>d?"ceil":"floor":"round";k=Math[b](o()/(m/c.children.length)),k+=a,k=Math.min(k,0),k=Math.max(-(c.children.length-1),k)},q=function(d){if(c=n(d.target)){var e=c.querySelector("li");m=e.offsetWidth*c.children.length,l=void 0,j=c.offsetWidth,i=1,g=-(c.children.length-1),h=+new Date,a=d.touches[0].pageX,b=d.touches[0].pageY,p(0),c.style["-webkit-transition-duration"]=0}},r=function(h){h.touches.length>1||!c||(d=h.touches[0].pageX-a,e=h.touches[0].pageY-b,a=h.touches[0].pageX,b=h.touches[0].pageY,"undefined"==typeof l&&(l=Math.abs(e)>Math.abs(d)),l||(f=d/i+o(),h.preventDefault(),i=0==k&&d>0?a/j+1.25:k==g&&0>d?Math.abs(a)/j+1.25:1,c.style.webkitTransform="translate3d("+f+"px,0,0)"))},s=function(a){c&&!l&&(p(+new Date-h<1e3&&Math.abs(d)>15?0>d?-1:1:0),f=k*j,c.style["-webkit-transition-duration"]=".2s",c.style.webkitTransform="translate3d("+f+"px,0,0)",a=new CustomEvent("slide",{detail:{slideNumber:Math.abs(k)},bubbles:!0,cancelable:!0}),c.parentNode.dispatchEvent(a))};window.addEventListener("touchstart",q),window.addEventListener("touchmove",r),window.addEventListener("touchend",s)}(),!function(){var a={},b=!1,c=!1,d=!1,e=function(a){for(var b,c=document.querySelectorAll(".cl-toggle");a&&a!==document;a=a.parentNode)for(b=c.length;b--;)if(c[b]===a)return a};window.addEventListener("touchstart",function(c){if(c=c.originalEvent||c,d=e(c.target)){var f=d.querySelector(".cl-toggle-handle"),g=d.offsetWidth,h=f.offsetWidth,i=d.classList.contains("active")?g-h:0;a={pageX:c.touches[0].pageX-i,pageY:c.touches[0].pageY},b=!1,d.style["-webkit-transition-duration"]=0}}),window.addEventListener("touchmove",function(e){if(e=e.originalEvent||e,!(e.touches.length>1)&&d){var f=d.querySelector(".cl-toggle-handle"),g=e.touches[0],h=d.offsetWidth,i=f.offsetWidth,j=h-i;if(b=!0,c=g.pageX-a.pageX,!(Math.abs(c)c)return f.style.webkitTransform="translate3d(0,0,0)";if(c>j)return f.style.webkitTransform="translate3d("+j+"px,0,0)";f.style.webkitTransform="translate3d("+c+"px,0,0)",d.classList[c>h/2-i/2?"add":"remove"]("active")}}}),window.addEventListener("touchend",function(a){if(d){var e=d.querySelector(".cl-toggle-handle"),f=d.offsetWidth,g=e.offsetWidth,h=f-g,i=!b&&!d.classList.contains("active")||b&&c>f/2-g/2;e.style.webkitTransform=i?"translate3d("+h+"px,0,0)":"translate3d(0,0,0)",d.classList[i?"add":"remove"]("active"),a=new CustomEvent("toggle",{detail:{isActive:i},bubbles:!0,cancelable:!0}),d.dispatchEvent(a),b=!1,d=!1}})}(),$(function(){if($(".simulate-touch").length>0){new FingerBlast(".simulate-touch")}$('.radio-list input[type="radio"]').change(function(){$(this).parents(".radio-list").find("label").removeClass("checked"),$(this).parent().addClass("checked")}),$('.checkbox-list input[type="checkbox"]').change(function(){$(this).is(":checked")?$(this).parent().addClass("checked"):$(this).parent().removeClass("checked")}),$("*[data-dismiss]").click(function(){var a=$(this).attr("data-dismiss");$("."+a).addClass("dismissed")}),$('[data-toggle-element="popover-context"]').click(function(){$(".cl-popover").is(":visible")?$(".cl-content").css("overflow","hidden"):$(".cl-content").css("overflow","scroll")}),$(".cl-modal").is(":visible")?$(".cl-content").css("overflow","hidden"):$(".cl-content").css("overflow","scroll")}); -------------------------------------------------------------------------------- /font-generation-templates/custom-android.css: -------------------------------------------------------------------------------- 1 | /* Custom template for stylesheet generation for Clank */ 2 | /* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ 3 | 4 | <% if (fontfaceStyles) { %>@font-face { 5 | font-family:"<%= fontBaseName %>";<% if (fontSrc1) { %> 6 | src:<%= fontSrc1 %>;<% }%> 7 | src:<%= fontSrc2 %>; 8 | font-weight:normal; 9 | font-style:normal; 10 | } 11 | <% } %> 12 | 13 | <% if (baseStyles) { %> 14 | [class^="icon-android4-"]:before, 15 | [class*=" icon-android4-"]:before { 16 | font-family:"<%= fontBaseName %>"; 17 | display:inline-block; 18 | font-weight:normal; 19 | font-style:normal; 20 | speak:none; 21 | text-decoration:inherit; 22 | text-transform:none; 23 | text-rendering:optimizeLegibility; 24 | -webkit-font-smoothing:antialiased; 25 | -moz-osx-font-smoothing:grayscale; 26 | } 27 | 28 | <% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 29 | .icon-<%= glyphs[glyphIdx] %><% if(glyphIdx === glyphs.length-1) { %> { <% } else { %>, <% } } %> 30 | &:before { 31 | font-family:"<%= fontBaseName %>"; 32 | display:inline-block; 33 | font-weight:normal; 34 | font-style:normal; 35 | text-decoration:inherit; 36 | } 37 | }<% } %> 38 | 39 | /* Icons */<% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 40 | .icon-<%= glyphs[glyphIdx] %>:before { 41 | content:"<% if (ligatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= (61696+glyphIdx).toString(16) %><% } %>"; 42 | }<% } %> 43 | -------------------------------------------------------------------------------- /font-generation-templates/custom-android.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseClass": "icon", 3 | "classPrefix": "icon-" 4 | } 5 | -------------------------------------------------------------------------------- /font-generation-templates/custom-app.css: -------------------------------------------------------------------------------- 1 | /* Custom template for stylesheet generation for Clank */ 2 | /* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ 3 | 4 | <% if (fontfaceStyles) { %>@font-face { 5 | font-family:"<%= fontBaseName %>";<% if (fontSrc1) { %> 6 | src:<%= fontSrc1 %>;<% }%> 7 | src:<%= fontSrc2 %>; 8 | font-weight:normal; 9 | font-style:normal; 10 | } 11 | <% } %> 12 | 13 | <% if (baseStyles) { %> 14 | [class^="icon-app-"]:before, 15 | [class*=" icon-app-"]:before { 16 | font-family:"<%= fontBaseName %>"; 17 | display:inline-block; 18 | font-weight:normal; 19 | font-style:normal; 20 | speak:none; 21 | text-decoration:inherit; 22 | text-transform:none; 23 | text-rendering:optimizeLegibility; 24 | -webkit-font-smoothing:antialiased; 25 | -moz-osx-font-smoothing:grayscale; 26 | } 27 | 28 | <% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 29 | .icon-<%= glyphs[glyphIdx] %><% if(glyphIdx === glyphs.length-1) { %> { <% } else { %>, <% } } %> 30 | &:before { 31 | font-family:"<%= fontBaseName %>"; 32 | display:inline-block; 33 | font-weight:normal; 34 | font-style:normal; 35 | text-decoration:inherit; 36 | } 37 | }<% } %> 38 | 39 | /* Icons */<% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 40 | .icon-<%= glyphs[glyphIdx] %>:before { 41 | content:"<% if (ligatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= (61696+glyphIdx).toString(16) %><% } %>"; 42 | }<% } %> 43 | -------------------------------------------------------------------------------- /font-generation-templates/custom-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseClass": "icon", 3 | "classPrefix": "icon-" 4 | } 5 | -------------------------------------------------------------------------------- /font-generation-templates/custom-ios.css: -------------------------------------------------------------------------------- 1 | /* Custom template for stylesheet generation for Clank */ 2 | /* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ 3 | 4 | <% if (fontfaceStyles) { %>@font-face { 5 | font-family:"<%= fontBaseName %>";<% if (fontSrc1) { %> 6 | src:<%= fontSrc1 %>;<% }%> 7 | src:<%= fontSrc2 %>; 8 | font-weight:normal; 9 | font-style:normal; 10 | } 11 | <% } %> 12 | 13 | <% if (baseStyles) { %> 14 | [class^="icon-ios6-"]:before, 15 | [class*= "icon-ios6-"]:before, 16 | [class^="icon-ios7-"]:before, 17 | [class*=" icon-ios7-"]:before { 18 | font-family:"<%= fontBaseName %>"; 19 | display:inline-block; 20 | font-weight:normal; 21 | font-style:normal; 22 | speak:none; 23 | text-decoration:inherit; 24 | text-transform:none; 25 | text-rendering:optimizeLegibility; 26 | -webkit-font-smoothing:antialiased; 27 | -moz-osx-font-smoothing:grayscale; 28 | } 29 | 30 | <% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 31 | .icon-<%= glyphs[glyphIdx] %><% if(glyphIdx === glyphs.length-1) { %> { <% } else { %>, <% } } %> 32 | &:before { 33 | font-family:"<%= fontBaseName %>"; 34 | display:inline-block; 35 | font-weight:normal; 36 | font-style:normal; 37 | text-decoration:inherit; 38 | } 39 | }<% } %> 40 | 41 | /* Icons */<% for (var glyphIdx = 0; glyphIdx < glyphs.length; glyphIdx++) { %> 42 | .icon-<%= glyphs[glyphIdx] %>:before { 43 | content:"<% if (ligatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= (61696+glyphIdx).toString(16) %><% } %>"; 44 | }<% } %> 45 | -------------------------------------------------------------------------------- /font-generation-templates/custom-ios.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseClass": "icon", 3 | "classPrefix": "icon-" 4 | } 5 | -------------------------------------------------------------------------------- /fonts/android-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/android-icons.eot -------------------------------------------------------------------------------- /fonts/android-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20120731 at Wed Nov 27 18:49:49 2013 6 | By Johan Ronsse 7 | Created by Johan Ronsse with FontForge 2.0 (http://fontforge.sf.net) 8 | 9 | 10 | 11 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /fonts/android-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/android-icons.ttf -------------------------------------------------------------------------------- /fonts/android-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/android-icons.woff -------------------------------------------------------------------------------- /fonts/app-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/app-icons.eot -------------------------------------------------------------------------------- /fonts/app-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20120731 at Wed Nov 27 18:49:48 2013 6 | By Johan Ronsse 7 | Created by Johan Ronsse with FontForge 2.0 (http://fontforge.sf.net) 8 | 9 | 10 | 11 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 45 | 48 | 50 | 52 | 54 | 57 | 59 | 61 | 63 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /fonts/app-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/app-icons.ttf -------------------------------------------------------------------------------- /fonts/app-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/app-icons.woff -------------------------------------------------------------------------------- /fonts/ios-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/ios-icons.eot -------------------------------------------------------------------------------- /fonts/ios-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20120731 at Wed Nov 27 18:49:49 2013 6 | By Johan Ronsse 7 | Created by Johan Ronsse with FontForge 2.0 (http://fontforge.sf.net) 8 | 9 | 10 | 11 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 41 | 43 | 46 | 49 | 51 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /fonts/ios-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/ios-icons.ttf -------------------------------------------------------------------------------- /fonts/ios-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/fonts/ios-icons.woff -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-back-chevron.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/icons_svg_source/android/android4-back-chevron.ai -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-back-chevron.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-battery-colored.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-battery.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-network.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-system-apps.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-system-back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-system-home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /images/icons_svg_source/android/android4-wifi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-arrow-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-arrow-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-bekijken.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-boeken.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-heart-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-historiek.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-ontleend.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/app/app-uitlenen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 13 | 18 | 19 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios6-alarm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios6-battery.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios6-locate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios6-orientation-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios7-back-chevron.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios7-battery-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios7-orientation-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios7-reception-empty.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/icons_svg_source/ios/ios7-reception-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/landscape/galaxy-nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/landscape/galaxy-nexus.png -------------------------------------------------------------------------------- /images/landscape/ipad3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/landscape/ipad3.png -------------------------------------------------------------------------------- /images/landscape/iphone4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/landscape/iphone4.png -------------------------------------------------------------------------------- /images/landscape/iphone5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/landscape/iphone5.png -------------------------------------------------------------------------------- /images/landscape/nexus7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/landscape/nexus7.png -------------------------------------------------------------------------------- /images/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/pattern.png -------------------------------------------------------------------------------- /images/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/placeholder.png -------------------------------------------------------------------------------- /images/portrait/galaxy-nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/portrait/galaxy-nexus.png -------------------------------------------------------------------------------- /images/portrait/ipad3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/portrait/ipad3.png -------------------------------------------------------------------------------- /images/portrait/iphone4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/portrait/iphone4.png -------------------------------------------------------------------------------- /images/portrait/iphone5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/portrait/iphone5.png -------------------------------------------------------------------------------- /images/portrait/nexus7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/portrait/nexus7.png -------------------------------------------------------------------------------- /images/slider/fauna1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/slider/fauna1.jpg -------------------------------------------------------------------------------- /images/slider/fauna2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/slider/fauna2.jpg -------------------------------------------------------------------------------- /images/slider/fauna3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/slider/fauna3.jpg -------------------------------------------------------------------------------- /images/slider/fauna4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wolfr/clank/d8bfb852abea890beaa86b7d62add82f2f220419/images/slider/fauna4.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Bell 35 | 36 | 20:49 37 | 38 | 3G 39 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
47 |
48 |
Welcome
49 |
50 |
51 |
52 |

Welcome to Clank. This is the first demo page in iOS style. To make everything run properly refer to the README.md (hint: bower install + npm install)

53 |
54 | Next: OS switch 55 |
56 |
57 |
58 |
59 | 60 |
61 | 62 |
63 |
64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /js/clank/clank.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Clank JS 3 | */ 4 | 5 | $(function() { 6 | 7 | /** 8 | * Simulate touch 9 | * Make toggles and sliders work on non touch devices 10 | * ! The touch context can only be used once per page 11 | */ 12 | 13 | if ($('.simulate-touch').length > 0) { 14 | var fb = new FingerBlast('.simulate-touch'); 15 | } 16 | 17 | /** 18 | * Radio and checkbox lists 19 | */ 20 | 21 | $('.radio-list input[type="radio"]').change(function() { 22 | // Remove all checked 23 | $(this).parents('.radio-list').find('label').removeClass('checked'); 24 | 25 | // Add class so we can style 26 | $(this).parent().addClass('checked'); 27 | }); 28 | 29 | $('.checkbox-list input[type="checkbox"]').change(function() { 30 | // Action on check/uncheck checkbox 31 | if ($(this).is(':checked')) { 32 | $(this).parent().addClass('checked'); 33 | } else { 34 | $(this).parent().removeClass('checked'); 35 | } 36 | 37 | }); 38 | 39 | /** 40 | * Alerts 41 | */ 42 | 43 | $('*[data-dismiss]').click(function() { 44 | var dismissWhat = $(this).attr('data-dismiss') 45 | $('.' + dismissWhat).addClass('dismissed'); 46 | }); 47 | 48 | /* 49 | Prevent body scrolling when popover context is open 50 | */ 51 | 52 | $('[data-toggle-element="popover-context"]').click(function(e) { 53 | if ($('.cl-popover').is(':visible')) { 54 | $('.cl-content').css('overflow', 'hidden'); 55 | } else { 56 | $('.cl-content').css('overflow', 'scroll'); 57 | } 58 | }); 59 | 60 | /* 61 | Prevent body scrolling when popover context is open 62 | */ 63 | 64 | if ($('.cl-modal').is(':visible')) { 65 | $('.cl-content').css('overflow', 'hidden'); 66 | } else { 67 | $('.cl-content').css('overflow', 'scroll'); 68 | } 69 | 70 | }); -------------------------------------------------------------------------------- /js/clank/ratchet/fingerblast.js: -------------------------------------------------------------------------------- 1 | // FINGERBLAST.js 2 | // -------------- 3 | // Adapted from phantom limb by brian cartensen 4 | 5 | function FingerBlast(element) { 6 | this.element = typeof element == 'string' ? document.querySelector(element) : element; 7 | this.listen(); 8 | } 9 | 10 | FingerBlast.prototype = { 11 | x: NaN, 12 | y: NaN, 13 | 14 | startDistance: NaN, 15 | startAngle: NaN, 16 | 17 | mouseIsDown: false, 18 | 19 | listen: function () { 20 | 21 | var activate = this.activate.bind(this); 22 | var deactivate = this.deactivate.bind(this); 23 | 24 | function contains (element, ancestor) { 25 | var descendants, index, descendant; 26 | if ("compareDocumentPosition" in ancestor) { 27 | return !!(ancestor.compareDocumentPosition(element) & 16); 28 | } else if ("contains" in ancestor) { 29 | return ancestor != element && ancestor.contains(element); 30 | } else { 31 | for (descendants = ancestor.getElementsByTagName("*"), index = 0; descendant = descendants[index++];) { 32 | if (descendant == element) return true; 33 | } 34 | return false; 35 | } 36 | } 37 | 38 | this.element.addEventListener('mouseover', function (e) { 39 | var target = e.relatedTarget; 40 | if (target != this && !contains(target, this)) activate(); 41 | }); 42 | 43 | this.element.addEventListener("mouseout", function (e) { 44 | var target = e.relatedTarget; 45 | if (target != this && !contains(target, this)) deactivate(e); 46 | }); 47 | }, 48 | 49 | activate: function () { 50 | if (this.active) return; 51 | this.element.addEventListener('mousedown', (this.touchStart = this.touchStart.bind(this)), true); 52 | this.element.addEventListener('mousemove', (this.touchMove = this.touchMove.bind(this)), true); 53 | this.element.addEventListener('mouseup', (this.touchEnd = this.touchEnd.bind(this)), true); 54 | this.element.addEventListener('click', (this.click = this.click.bind(this)), true); 55 | this.active = true; 56 | }, 57 | 58 | deactivate: function (e) { 59 | this.active = false; 60 | if (this.mouseIsDown) this.touchEnd(e); 61 | this.element.removeEventListener('mousedown', this.touchStart, true); 62 | this.element.removeEventListener('mousemove', this.touchMove, true); 63 | this.element.removeEventListener('mouseup', this.touchEnd, true); 64 | this.element.removeEventListener('click', this.click, true); 65 | }, 66 | 67 | click: function (e) { 68 | if (e.synthetic) return; 69 | e.preventDefault(); 70 | e.stopPropagation(); 71 | }, 72 | 73 | touchStart: function (e) { 74 | if (e.synthetic || /input|textarea/.test(e.target.tagName.toLowerCase())) return; 75 | 76 | this.mouseIsDown = true; 77 | 78 | e.preventDefault(); 79 | e.stopPropagation(); 80 | 81 | this.fireTouchEvents('touchstart', e); 82 | }, 83 | 84 | touchMove: function (e) { 85 | if (e.synthetic) return; 86 | 87 | e.preventDefault(); 88 | e.stopPropagation(); 89 | 90 | this.move(e.clientX, e.clientY); 91 | 92 | if (this.mouseIsDown) this.fireTouchEvents('touchmove', e); 93 | }, 94 | 95 | touchEnd: function (e) { 96 | if (e.synthetic) return; 97 | 98 | this.mouseIsDown = false; 99 | 100 | e.preventDefault(); 101 | e.stopPropagation(); 102 | 103 | this.fireTouchEvents('touchend', e); 104 | 105 | if (!this.target) return; 106 | 107 | // Mobile Safari moves all the mouse events to fire after the touchend event. 108 | this.target.dispatchEvent(this.createMouseEvent('mouseover', e)); 109 | this.target.dispatchEvent(this.createMouseEvent('mousemove', e)); 110 | this.target.dispatchEvent(this.createMouseEvent('mousedown', e)); 111 | }, 112 | 113 | fireTouchEvents: function (eventName, originalEvent) { 114 | var events = []; 115 | var gestures = []; 116 | 117 | if (!this.target) return; 118 | 119 | // Convert "ontouch*" properties and attributes to listeners. 120 | var onEventName = 'on' + eventName; 121 | 122 | if (onEventName in this.target) { 123 | console.warn('Converting `' + onEventName + '` property to event listener.', this.target); 124 | this.target.addEventListener(eventName, this.target[onEventName], false); 125 | delete this.target[onEventName]; 126 | } 127 | 128 | if (this.target.hasAttribute(onEventName)) { 129 | console.warn('Converting `' + onEventName + '` attribute to event listener.', this.target); 130 | var handler = new GLOBAL.Function('event', this.target.getAttribute(onEventName)); 131 | this.target.addEventListener(eventName, handler, false); 132 | this.target.removeAttribute(onEventName); 133 | } 134 | 135 | // Set up a new event with the coordinates of the finger. 136 | var touch = this.createMouseEvent(eventName, originalEvent); 137 | 138 | events.push(touch); 139 | 140 | // Figure out scale and rotation. 141 | if (events.length > 1) { 142 | var x = events[0].pageX - events[1].pageX; 143 | var y = events[0].pageY - events[1].pageY; 144 | 145 | var distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 146 | var angle = Math.atan2(x, y) * (180 / Math.PI); 147 | 148 | var gestureName = 'gesturechange'; 149 | 150 | if (eventName === 'touchstart') { 151 | gestureName = 'gesturestart'; 152 | this.startDistance = distance; 153 | this.startAngle = angle; 154 | } 155 | 156 | if (eventName === 'touchend') gestureName = 'gestureend'; 157 | 158 | events.forEach(function(event) { 159 | var gesture = this.createMouseEvent.call(event._finger, gestureName, event); 160 | gestures.push(gesture); 161 | }.bind(this)); 162 | 163 | events.concat(gestures).forEach(function(event) { 164 | event.scale = distance / this.startDistance; 165 | event.rotation = this.startAngle - angle; 166 | }); 167 | } 168 | 169 | // Loop through the events array and fill in each touch array. 170 | events.forEach(function(touch) { 171 | touch.touches = events.filter(function(e) { 172 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 173 | }); 174 | 175 | touch.changedTouches = events.filter(function(e) { 176 | return ~e.type.indexOf('touch') && e._finger.target === touch._finger.target; 177 | }); 178 | 179 | touch.targetTouches = touch.changedTouches.filter(function(e) { 180 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 181 | }); 182 | }); 183 | 184 | // Then fire the events. 185 | events.concat(gestures).forEach(function(event, i) { 186 | event.identifier = i; 187 | event._finger.target.dispatchEvent(event); 188 | }); 189 | }, 190 | 191 | createMouseEvent: function (eventName, originalEvent) { 192 | var e = document.createEvent('MouseEvent'); 193 | 194 | e.initMouseEvent(eventName, true, true, 195 | originalEvent.view, originalEvent.detail, 196 | this.x || originalEvent.screenX, this.y || originalEvent.screenY, 197 | this.x || originalEvent.clientX, this.y || originalEvent.clientY, 198 | originalEvent.ctrlKey, originalEvent.shiftKey, 199 | originalEvent.altKey, originalEvent.metaKey, 200 | originalEvent.button, this.target || originalEvent.relatedTarget 201 | ); 202 | 203 | e.synthetic = true; 204 | e._finger = this; 205 | 206 | return e; 207 | }, 208 | 209 | move: function (x, y) { 210 | if (isNaN(x) || isNaN(y)) { 211 | this.target = null; 212 | } else { 213 | this.x = x; 214 | this.y = y; 215 | 216 | if (!this.mouseIsDown) { 217 | this.target = document.elementFromPoint(x, y); 218 | } 219 | } 220 | } 221 | }; -------------------------------------------------------------------------------- /js/clank/ratchet/sliders.js: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- 2 | * SLIDER v1.0.0 3 | * Licensed under The MIT License 4 | * Adapted from Brad Birdsall's swipe 5 | * http://opensource.org/licenses/MIT 6 | * ---------------------------------- */ 7 | 8 | !function () { 9 | 10 | var pageX; 11 | var pageY; 12 | var slider; 13 | var deltaX; 14 | var deltaY; 15 | var offsetX; 16 | var lastSlide; 17 | var startTime; 18 | var resistance; 19 | var sliderWidth; 20 | var slideNumber; 21 | var isScrolling; 22 | var scrollableArea; 23 | 24 | var getSlider = function (target) { 25 | var i, sliders = document.querySelectorAll('.cl-slider ul'); 26 | for (; target && target !== document; target = target.parentNode) { 27 | for (i = sliders.length; i--;) { if (sliders[i] === target) return target; } 28 | } 29 | } 30 | 31 | var getScroll = function () { 32 | var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/); 33 | return parseInt(translate3d ? translate3d[1] : 0) 34 | }; 35 | 36 | var setSlideNumber = function (offset) { 37 | var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round'; 38 | slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) ); 39 | slideNumber += offset; 40 | slideNumber = Math.min(slideNumber, 0); 41 | slideNumber = Math.max(-(slider.children.length - 1), slideNumber); 42 | 43 | } 44 | 45 | var onTouchStart = function (e) { 46 | slider = getSlider(e.target); 47 | 48 | if (!slider) return; 49 | 50 | var firstItem = slider.querySelector('li'); 51 | 52 | scrollableArea = firstItem.offsetWidth * slider.children.length; 53 | isScrolling = undefined; 54 | sliderWidth = slider.offsetWidth; 55 | resistance = 1; 56 | lastSlide = -(slider.children.length - 1); 57 | startTime = +new Date; 58 | pageX = e.touches[0].pageX; 59 | pageY = e.touches[0].pageY; 60 | 61 | setSlideNumber(0); 62 | 63 | slider.style['-webkit-transition-duration'] = 0; 64 | }; 65 | 66 | var onTouchMove = function (e) { 67 | if (e.touches.length > 1 || !slider) return; // Exit if a pinch || no slider 68 | 69 | deltaX = e.touches[0].pageX - pageX; 70 | deltaY = e.touches[0].pageY - pageY; 71 | pageX = e.touches[0].pageX; 72 | pageY = e.touches[0].pageY; 73 | 74 | if (typeof isScrolling == 'undefined') { 75 | isScrolling = Math.abs(deltaY) > Math.abs(deltaX); 76 | } 77 | 78 | if (isScrolling) return; 79 | 80 | offsetX = (deltaX / resistance) + getScroll(); 81 | 82 | e.preventDefault(); 83 | 84 | resistance = slideNumber == 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 : 85 | slideNumber == lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1; 86 | 87 | slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; 88 | }; 89 | 90 | var onTouchEnd = function (e) { 91 | if (!slider || isScrolling) return; 92 | 93 | setSlideNumber( 94 | (+new Date) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0 95 | ); 96 | 97 | offsetX = slideNumber * sliderWidth; 98 | 99 | slider.style['-webkit-transition-duration'] = '.2s'; 100 | slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)'; 101 | 102 | e = new CustomEvent('slide', { 103 | detail: { slideNumber: Math.abs(slideNumber) }, 104 | bubbles: true, 105 | cancelable: true 106 | }); 107 | 108 | slider.parentNode.dispatchEvent(e); 109 | }; 110 | 111 | window.addEventListener('touchstart', onTouchStart); 112 | window.addEventListener('touchmove', onTouchMove); 113 | window.addEventListener('touchend', onTouchEnd); 114 | 115 | }(); 116 | -------------------------------------------------------------------------------- /js/clank/ratchet/toggles.js: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- 2 | * TOGGLE v1.0.0 3 | * Licensed under The MIT License 4 | * http://opensource.org/licenses/MIT 5 | * ---------------------------------- */ 6 | 7 | !function () { 8 | 9 | var start = {}; 10 | var touchMove = false; 11 | var distanceX = false; 12 | var toggle = false; 13 | 14 | var findToggle = function (target) { 15 | var i, toggles = document.querySelectorAll('.cl-toggle'); 16 | for (; target && target !== document; target = target.parentNode) { 17 | for (i = toggles.length; i--;) { if (toggles[i] === target) return target; } 18 | } 19 | } 20 | 21 | window.addEventListener('touchstart', function (e) { 22 | e = e.originalEvent || e; 23 | 24 | toggle = findToggle(e.target); 25 | 26 | if (!toggle) return; 27 | 28 | var handle = toggle.querySelector('.cl-toggle-handle'); 29 | var toggleWidth = toggle.offsetWidth; 30 | var handleWidth = handle.offsetWidth; 31 | var offset = toggle.classList.contains('active') ? toggleWidth - handleWidth : 0; 32 | 33 | start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY }; 34 | touchMove = false; 35 | 36 | // todo: probably should be moved to the css 37 | toggle.style['-webkit-transition-duration'] = 0; 38 | }); 39 | 40 | window.addEventListener('touchmove', function (e) { 41 | e = e.originalEvent || e; 42 | 43 | if (e.touches.length > 1) return; // Exit if a pinch 44 | 45 | if (!toggle) return; 46 | 47 | var handle = toggle.querySelector('.cl-toggle-handle'); 48 | var current = e.touches[0]; 49 | var toggleWidth = toggle.offsetWidth; 50 | var handleWidth = handle.offsetWidth; 51 | var offset = toggleWidth - handleWidth; 52 | 53 | touchMove = true; 54 | distanceX = current.pageX - start.pageX; 55 | 56 | if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) return; 57 | 58 | e.preventDefault(); 59 | 60 | if (distanceX < 0) return handle.style.webkitTransform = 'translate3d(0,0,0)'; 61 | if (distanceX > offset) return handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'; 62 | 63 | handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)'; 64 | 65 | toggle.classList[(distanceX > (toggleWidth/2 - handleWidth/2)) ? 'add' : 'remove']('active'); 66 | }); 67 | 68 | window.addEventListener('touchend', function (e) { 69 | if (!toggle) return; 70 | 71 | var handle = toggle.querySelector('.cl-toggle-handle'); 72 | var toggleWidth = toggle.offsetWidth; 73 | var handleWidth = handle.offsetWidth; 74 | var offset = toggleWidth - handleWidth; 75 | var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth/2 - handleWidth/2))); 76 | 77 | if (slideOn) handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)'; 78 | else handle.style.webkitTransform = 'translate3d(0,0,0)'; 79 | 80 | toggle.classList[slideOn ? 'add' : 'remove']('active'); 81 | 82 | e = new CustomEvent('toggle', { 83 | detail: { isActive: slideOn }, 84 | bubbles: true, 85 | cancelable: true 86 | }); 87 | 88 | toggle.dispatchEvent(e); 89 | 90 | touchMove = false; 91 | toggle = false; 92 | }); 93 | 94 | }(); 95 | -------------------------------------------------------------------------------- /js/clank/state-loader.js: -------------------------------------------------------------------------------- 1 | /*global $*/ 2 | 3 | $(function () { 4 | 5 | /* Adds statehashchange events */ 6 | 7 | $(window).stateHashChange(); 8 | 9 | /* Initiaze state hash push */ 10 | 11 | $('*[data-state-push]').stateHashPush(); 12 | 13 | /* On hash change */ 14 | 15 | var containers = $('*[data-state-container]'); 16 | 17 | $(window).on('statehashchange', function (e, obj) { 18 | containers.each(function () { 19 | $(this).loadState(obj); 20 | }); 21 | }); 22 | 23 | /* On state change */ 24 | 25 | containers.on('statechange', function (e, old_state, new_state, resume) { 26 | 27 | e.preventDefault(); 28 | 29 | var container = $(this); 30 | var reverse = e.hash_object.reverse; 31 | 32 | var start = '-enter'; 33 | var end = '-leave'; 34 | 35 | if (reverse) { 36 | start = '-leave'; 37 | end = '-enter'; 38 | } 39 | 40 | /* New state */ 41 | 42 | var prefix = container.attr('data-animate'); 43 | 44 | if (prefix) { 45 | 46 | if (reverse) { 47 | new_state.addClass('cl-animation-reverse'); 48 | } 49 | 50 | new_state.animationStyle({ style: prefix + start }); 51 | } 52 | 53 | /* Old state */ 54 | 55 | if (!prefix) { 56 | return resume(); 57 | } 58 | 59 | old_state.removeClass('cl-animation-reverse'); 60 | 61 | if (reverse) { 62 | old_state.addClass('cl-animation-reverse'); 63 | } 64 | 65 | old_state.animationStyle({ style: prefix + end, callback: resume }); 66 | 67 | }); 68 | 69 | /* On state unload */ 70 | 71 | containers.on('stateunload', function (e, contents, resume) { 72 | 73 | e.preventDefault(); 74 | var container = $(this); 75 | 76 | var prefix = container.attr('data-animate'); 77 | 78 | if (!prefix) { 79 | return resume(); 80 | } 81 | 82 | contents.animationStyle({ style: prefix + '-leave', callback: resume }); 83 | 84 | }); 85 | 86 | }); 87 | -------------------------------------------------------------------------------- /orientation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 | 28 | 29 | 20:49 30 | 31 |
32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 |
43 | 44 | 45 | OS switch 46 | 47 |
Orientation
48 |
49 |
50 |
51 |

You can also change the orientation: between this and the previous step data-device="" changed from nexus7-landscape to nexus7-portrait.

52 |
53 | Next: device wraps 54 |
55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /os-switch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 20:49 31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 |
43 |
44 |
45 | 46 | 47 | Welcome 48 | 49 |
OS Switch
50 |
51 |
52 |
53 |

This is the second demo page showing an Android phone. This framework is meant for prototyping apps that are going to run on iOS and Android.

54 |

What changed? There is other markup for the system icons - also the data-os and data-device attributes changed.

55 |
56 | Next: orientation 57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 | 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clank-dev", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/Wolfr/clank.git" 13 | }, 14 | "author": "", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/Wolfr/clank/issues" 18 | }, 19 | "devDependencies": { 20 | "grunt": "~0.4.1", 21 | "grunt-webfont": "~0.1.10", 22 | "grunt-contrib-clean": "~0.5.0", 23 | "grunt-contrib-compass": "~0.6.0", 24 | "grunt-contrib-copy": "~0.4.1", 25 | "grunt-contrib-watch": "~0.5.3", 26 | "grunt-contrib-uglify": "~0.2.7", 27 | "grunt-contrib-concat": "~0.3.0", 28 | "grunt-contrib-cssmin": "~0.7.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scss/clank.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Clank CSS framework 3 | ========================================================================== */ 4 | 5 | @import "compass"; 6 | @import "clank/vars"; 7 | @import "clank/mixins"; 8 | @import "clank/base"; 9 | 10 | // Devices 11 | @import "clank/components/device_wraps"; 12 | 13 | // Components 14 | @import "clank/components/article"; 15 | @import "clank/components/base-layout"; 16 | @import "clank/components/buttons"; 17 | @import "clank/components/forms"; 18 | @import "clank/components/alerts"; 19 | @import "clank/components/data-table"; 20 | @import "clank/components/toggles"; 21 | @import "clank/components/sliders"; 22 | @import "clank/components/loading"; 23 | @import "clank/components/table-view"; 24 | @import "clank/components/help-txt"; 25 | @import "clank/components/utilities"; 26 | @import "clank/components/popover"; 27 | @import "clank/components/badge"; 28 | @import "clank/components/tab-bar"; 29 | @import "clank/components/close"; 30 | @import "clank/components/alerts-alt"; // Bootstrap 31 | @import "clank/components/modal"; 32 | @import "clank/components/animations"; 33 | 34 | /* ========================================================================== 35 | Custom application CSS 36 | ========================================================================== */ 37 | 38 | // App specific icons 39 | @import "clank/icon-fonts/app-icons"; 40 | 41 | // Custom components (not part of Clank core) 42 | // List your components here 43 | 44 | // App specific screens (list your custom CSS per screen here) 45 | -------------------------------------------------------------------------------- /scss/clank/_base.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Base 3 | ========================================================================== */ 4 | 5 | body, html { 6 | margin: 0; 7 | padding: 0; 8 | } 9 | 10 | a { 11 | text-decoration: none; 12 | } 13 | 14 | [data-os="ios"] .cl-device-body { 15 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 16 | } 17 | 18 | [data-os="android"] .cl-device-body { 19 | font-family: 'Roboto', 'Droid Sans', sans-serif; 20 | } 21 | 22 | .cl-device-body { 23 | *, *:before, *:after { 24 | -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; 25 | } 26 | } 27 | 28 | 29 | .cl-device-body { 30 | padding: 0; 31 | margin: 0 auto; 32 | padding: 0; 33 | height: 100%; 34 | width: 100%; 35 | margin: 0 auto; 36 | position: relative; 37 | overflow: hidden; 38 | -webkit-font-smoothing: antialiased; 39 | -webkit-text-size-adjust: none; 40 | & > .cl-bar-title, 41 | & > .cl-content, 42 | & > .cl-bar-footer { 43 | margin: 0 auto; 44 | } 45 | } -------------------------------------------------------------------------------- /scss/clank/_mixins.scss: -------------------------------------------------------------------------------- 1 | /* Fonts 2 | ========================================================================== */ 3 | 4 | @mixin reading-font { 5 | font-family: Helvetica, Arial, sans-serif; 6 | font-weight: 400; font-style: normal; 7 | } 8 | 9 | @mixin reading-font-italic { 10 | font-family: Helvetica, Arial, sans-serif; 11 | font-weight: 400; font-style: italic; 12 | } 13 | 14 | @mixin reading-font-bold { 15 | font-family: Helvetica, Arial, sans-serif; 16 | font-weight: 700; 17 | } 18 | 19 | @mixin heading-font-book { 20 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 21 | font-weight: 400; 22 | font-style: normal; 23 | } 24 | 25 | @mixin heading-font { 26 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 27 | font-weight: 500; 28 | font-style: normal; 29 | } 30 | 31 | /* CSS3 calc 32 | ========================================================================== */ 33 | 34 | @mixin calc($property, $expression) { 35 | #{$property}: -moz-calc(#{$expression}); 36 | #{$property}: -o-calc(#{$expression}); 37 | #{$property}: -webkit-calc(#{$expression}); 38 | #{$property}: calc(#{$expression}); 39 | } 40 | 41 | /* Alternate clearfix that does not rely on overflow: hidden; 42 | ========================================================================== */ 43 | 44 | @mixin micro-clearfix { 45 | &:before, 46 | &:after { 47 | content:""; 48 | display:table; 49 | } 50 | &:after { 51 | clear:both; 52 | } 53 | } 54 | 55 | /* Unstyled 56 | ========================================================================== */ 57 | 58 | @mixin unstyled { 59 | margin: 0; 60 | padding: 0; 61 | list-style: none; 62 | } 63 | 64 | /* Text shadows 65 | @todo make this dependant on text color 66 | ========================================================================== */ 67 | 68 | @mixin text-shadow-white { 69 | @if $text-shadows { 70 | text-shadow: 0 1px 0 rgba(255,255,255,0.5); 71 | } 72 | } 73 | 74 | @mixin text-shadow-black { 75 | @if $text-shadows { 76 | text-shadow: 0 1px rgba(0,0,0,0.33); 77 | } 78 | } 79 | 80 | /* Gradients 81 | ========================================================================== */ 82 | 83 | @mixin gradient-vertical($startColor: #555, $endColor: #333) { 84 | background-color: mix($startColor, $endColor, 60%); 85 | background-image: -moz-linear-gradient(top, $startColor, $endColor); // FF 3.6+ 86 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from($startColor), to($endColor)); // Safari 4+, Chrome 2+ 87 | background-image: -webkit-linear-gradient(top, $startColor, $endColor); // Safari 5.1+, Chrome 10+ 88 | background-image: -o-linear-gradient(top, $startColor, $endColor); // Opera 11.10 89 | background-image: linear-gradient(to bottom, $startColor, $endColor); // Standard, IE10 90 | background-repeat: repeat-x; 91 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($startColor)}', endColorstr='#{ie-hex-str($endColor)}', GradientType=0); // IE9 and down 92 | } 93 | 94 | 95 | @mixin determine-text-color($color) { 96 | @if(lightness($color) <= 75%) { 97 | color: $very-light-color; 98 | @include text-shadow-black; 99 | } @else { 100 | color: $very-dark-color; 101 | @include text-shadow-white; 102 | } 103 | } 104 | 105 | /* Buttons 106 | ========================================================================== */ 107 | 108 | @mixin button-skin($color) { 109 | &, 110 | &:link, 111 | &:visited { 112 | @include border-radius($border-radius); 113 | @if $button-borders { 114 | border: 1px solid darken($color, 5%); 115 | } 116 | @if $decorational-shadows { 117 | @include box-shadow(0 1px 0 rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.2)); 118 | } 119 | @if $gradient { 120 | @include gradient-vertical(lighten($color, 15%),$color); 121 | } @else { 122 | background: $color; 123 | } 124 | @include determine-text-color($color); 125 | } 126 | } 127 | 128 | @mixin button-skin-hover($color) { 129 | &:hover, 130 | &:active, 131 | &:focus, 132 | &.active { 133 | @if $decorational-shadows { 134 | @include box-shadow(0 1px 0 rgba(0,0,0,0.2)); 135 | } 136 | @if $gradient { 137 | @include gradient-vertical(darken($color, 5%), darken($color, 15%)); 138 | @if $decorational-shadows { 139 | @include box-shadow(inset 0 1px 0 rgba(0,0,0,0.15)); 140 | } 141 | } @else { 142 | background: darken($color, 10%); 143 | } 144 | @include determine-text-color($color); 145 | } 146 | } 147 | 148 | /* 149 | * 'rem' is a Sass mixin that converts pixel values to rem values for whatever property is passed to it. 150 | * It returns two lines of code — one of the regular pixel values (for IE), and another with the 151 | * converted rem values (for everyone else). Special thanks to Chris Epstein (http://chriseppstein.github.com) 152 | * and Martin Bavio (http://martinbavio.com) for the help and code! 153 | * 154 | * Sample input: 155 | * .element { 156 | * @include rem('padding',10px 0 2px 5px); 157 | * } 158 | * 159 | * Sample output: 160 | * .element { 161 | * padding: 10px 0 2px 5px; 162 | * padding: 1rem 0 0.2rem 0.5rem; 163 | * } 164 | * 165 | */ 166 | 167 | // Baseline, measured in pixels 168 | // The value should be the same as the font-size value for the html element 169 | // If the html element's font-size is set to 62.5% (of the browser's default font-size of 16px), 170 | // then the variable below would be 10px. 171 | $baseline_px: $base-font-size; 172 | 173 | @mixin rem($property, $px_values) { 174 | 175 | // Convert the baseline into rems 176 | $baseline_rem: ($baseline_px / 1rem); 177 | 178 | // Print the first line in pixel values 179 | #{$property}: $px_values; 180 | 181 | // If there is only one (numeric) value, return the property/value line for it. 182 | @if type-of($px_values) == 'number' { 183 | #{$property}: $px_values / $baseline_rem; 184 | } 185 | 186 | // If there is more than one value, create a list and perform equations on each value 187 | @else { 188 | 189 | // Create an empty list that we can dump values into 190 | $rem_values: (); 191 | 192 | @each $value in $px_values { 193 | 194 | // If the value is zero, return 0 195 | @if $value == 0 { 196 | $rem_values: append($rem_values, $value); 197 | } 198 | 199 | // If the value is not zero, convert it from px to rem 200 | @else { 201 | $rem_values: append($rem_values, ($value / $baseline_rem) ); 202 | } 203 | 204 | } 205 | 206 | // Return the property and its list of converted values 207 | #{$property}: $rem_values; 208 | 209 | } 210 | 211 | } 212 | 213 | 214 | /* Links 215 | ========================================================================== */ 216 | 217 | @mixin default-links { 218 | @include single-transition(color, 0.2s); 219 | & { 220 | text-decoration: none; 221 | } 222 | &:link { 223 | color: #1d60b2; 224 | border-bottom: 1px solid #bad9ff; 225 | } 226 | &:visited { 227 | color: #513c90; // purple 228 | border-bottom: 1px solid #8e75da; 229 | } 230 | &:hover, 231 | &:active, 232 | &:focus { 233 | color: #1876e6; 234 | .content p &, 235 | .content li & { 236 | background: #e7f2ff; 237 | } 238 | border-bottom: 1px solid #68adff; 239 | } 240 | } 241 | 242 | @mixin swap-underlines { 243 | &:link { 244 | text-decoration: none; 245 | border: none !important; 246 | } 247 | &:visited { 248 | text-decoration: none; 249 | border: none !important; 250 | } 251 | &:hover, 252 | &:active, 253 | &:focus { 254 | text-decoration: underline; 255 | border-bottom: 1px solid #ABCDF6; 256 | } 257 | } 258 | 259 | @mixin no-underlines { 260 | &:link, 261 | &:visited, 262 | &:hover, 263 | &:active, 264 | &:focus { 265 | text-decoration: none; 266 | border: none !important; 267 | } 268 | } 269 | 270 | @mixin muted-links { 271 | &:link, 272 | &:visited { 273 | color: #7F7F7F; 274 | border-bottom: 1px solid #CCC; 275 | border-bottom: 1px solid rgba(0,0,0,0.33); 276 | } 277 | &:hover, 278 | &:active, 279 | &:focus { 280 | color: #000; 281 | border-bottom: none; 282 | } 283 | } 284 | 285 | /* Links when color inversed */ 286 | @mixin inverse-links { 287 | @include single-transition(color, 0.2s); 288 | &:link { 289 | color: #FFF; 290 | color: rgba(255,255,255,1); 291 | border-bottom: 1px solid #444; 292 | border-color: rgba(255,255,255,0.33); 293 | } 294 | &:visited { 295 | color: #DDD; 296 | color: rgba(255,255,255,1); 297 | border-bottom: 1px solid #444; 298 | border-color: rgba(255,255,255,0.33); 299 | } 300 | &:hover, 301 | &:active, 302 | &:focus { 303 | color: #FFF; 304 | border-bottom: 1px solid #444; 305 | border-color: rgba(255,255,255,0.88); 306 | } 307 | } 308 | 309 | /* Animations 310 | ========================================================================== */ 311 | 312 | @mixin keyframes ($animation_name) { 313 | @-webkit-keyframes $animation_name { 314 | @content; 315 | } 316 | 317 | @-moz-keyframes $animation_name { 318 | @content; 319 | } 320 | 321 | @-o-keyframes $animation_name { 322 | @content; 323 | } 324 | 325 | @keyframes $animation_name { 326 | @content; 327 | } 328 | } 329 | 330 | @mixin animation-name($name...) { 331 | -o-animation-name: $name; 332 | -moz-animation-name: $name; 333 | -webkit-animation-name: $name; 334 | animation-name: $name; 335 | } 336 | 337 | @mixin animation-duration($duration...) { 338 | -o-animation-duration: $duration; 339 | -moz-animation-duration: $duration; 340 | -webkit-animation-duration: $duration; 341 | animation-duration: $duration; 342 | } 343 | 344 | @mixin animation-timing-function($timing...) { 345 | -o-animation-timing-function: $timing; 346 | -moz-animation-timing-function: $timing; 347 | -webkit-animation-timing-function: $timing; 348 | animation-timing-function: $timing; 349 | } 350 | 351 | @mixin animation-iteration-count($count...) { 352 | -o-animation-iteration-count: $count; 353 | -moz-animation-iteration-count: $count; 354 | -webkit-animation-iteration-count: $count; 355 | animation-iteration-count: $count; 356 | } 357 | 358 | @mixin animation-direction($direction...) { 359 | -o-animation-direction: $direction; 360 | -moz-animation-direction: $direction; 361 | -webkit-animation-direction: $direction; 362 | animation-direction: $direction; 363 | } 364 | 365 | @mixin animation-delay($delay...) { 366 | -o-animation-delay: $delay; 367 | -moz-animation-delay: $delay; 368 | -webkit-animation-delay: $delay; 369 | animation-delay: $delay; 370 | } 371 | 372 | @mixin animation-fill-mode($fill...) { 373 | -o-animation-fill-mode: $fill; 374 | -moz-animation-fill-mode: $fill; 375 | -webkit-animation-fill-mode: $fill; 376 | animation-fill-mode: $fill; 377 | } 378 | 379 | @mixin animation-play-state($state...) { 380 | -o-animation-play-state: $state; 381 | -moz-animation-play-state: $state; 382 | -webkit-animation-play-state: $state; 383 | animation-play-state: $state; 384 | } 385 | 386 | @mixin animation($animation...) { 387 | -o-animation: $animation; 388 | -moz-animation: $animation; 389 | -webkit-animation: $animation; 390 | animation: $animation; 391 | } -------------------------------------------------------------------------------- /scss/clank/_vars.scss: -------------------------------------------------------------------------------- 1 | /* Device wraps 2 | Set this to true if you are using device frames i.e. like the demo at getclank.com 3 | ========================================================================== */ 4 | 5 | $device-wraps: true; 6 | 7 | /* Operating system defaults 8 | Used to determine the sizing of elements 9 | ========================================================================== */ 10 | 11 | $ios-bar-size: 44px; 12 | $android-bar-size: 50px; 13 | 14 | /* Default style variables 15 | ========================================================================== */ 16 | 17 | $base-font-size: 13px; 18 | $base-font-value: 13; 19 | $base-line-height: 1.5; 20 | 21 | /* Colors 22 | Quickly change the colors of your app using these variables 23 | Note that a "light text on dark background" scheme is not fully supported yet 24 | ========================================================================== */ 25 | 26 | 27 | $very-light-color: #FFF !default; 28 | $light-color: #DDD !default; 29 | $light-medium-color: #AAA !default; 30 | $medium-color: #666 !default; 31 | $dark-color: #333 !default; 32 | $very-dark-color: #000 !default; 33 | 34 | $divider-color: $light-medium-color; 35 | 36 | $background-color: mix($very-light-color, $light-color, 50%) !default; 37 | $accent-color: #18788b !default; 38 | $accent-color-primary: if(lightness($accent-color) >= 50%, scale-saturation(scale-lightness($accent-color, -25%),25%), scale-saturation(scale-lightness($accent-color, 25%),25%)) !default; 39 | $subtle-color: darken($background-color, 5%) !default; 40 | 41 | // Colors with semantic meaning e.g. red for error 42 | $success-color: darken($accent-color, 20%) !default; 43 | $success-color-alt: #8FAE1F !default; 44 | $error-color: invert($accent-color) !default; 45 | $danger-color: #FC6C2B !default; 46 | $help-color: #643ABF !default; 47 | $highlight-color: #F9F3AC !default; 48 | 49 | 50 | /* Stylistic choices 51 | Quickly change the style of your app using these variables 52 | ========================================================================== */ 53 | 54 | $functional-shadows: true !default; // Shadows (and highlights) that are functional e.g. a drop shadow on a modal 55 | $decorational-shadows: true !default; // Shadows (and highlights) that are decorational e.g. an inset on a button 56 | $gradient: true !default; // Whether gradients should be rendered or not, set this to false for a flatter design 57 | $border-radius: 4px !default; // The radii of common borders e.g. the borders on buttons 58 | $text-shadows: true !default; // Whether text should have shadows or not 59 | $button-borders: true !default; 60 | 61 | /* For this release we are focussing on iOS7 62 | Enforce iOS7 flatness 63 | ========================================================================== */ 64 | 65 | $gradient: false; 66 | $decorational-shadows: false; 67 | $button-borders: false; 68 | $text-shadows: false; 69 | 70 | /* Media queries, always based on 16px base value. 71 | ========================================================================== */ 72 | 73 | $break-small: 320 / 16 * 1em; 74 | $break-small-medium: 480 / 16 * 1em; 75 | $break-medium: 768 / 16 * 1em; 76 | $break-large: 1024px; 77 | $break-x-large: 1200 / 16 * 1em; 78 | $break-xx-large: 1440 / 16 * 1em; 79 | $break-xxx-large: 1650 / 16 * 1em; 80 | 81 | /* Master z-index list 82 | ========================================================================== */ 83 | 84 | $cl-alert-z-index: 1202000202; 85 | $cl-alert-box-z-index: 120203202; 86 | $cl-popover-z-index: 1100202; -------------------------------------------------------------------------------- /scss/clank/components/_alerts-alt.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Alerts (bootstrap style alerts) 3 | ========================================================================== */ 4 | 5 | // Base styles 6 | // ------------------------- 7 | 8 | .alert { 9 | padding: 8px 34px 8px 14px; 10 | position: relative; 11 | margin: 0 0 12px; 12 | background-color: $light-color; 13 | border: 1px solid $light-medium-color; 14 | font-size: 14px; 15 | font-weight: 700; 16 | @include border-radius($border-radius); 17 | p:last-child { 18 | margin-bottom: 0; 19 | padding-bottom: 0; 20 | } 21 | } 22 | 23 | // Alternate styles: success & error 24 | // ------------------------- 25 | 26 | .alert-success, 27 | .alert-error { 28 | a { 29 | color: $very-light-color; 30 | @include inverse-links; 31 | } 32 | } 33 | 34 | .alert-success { 35 | background-color: $success-color; 36 | border-color: $success-color; 37 | color: $very-light-color; 38 | } 39 | 40 | .alert-error { 41 | background-color: $error-color; 42 | border-color: $error-color; 43 | color: $very-light-color; 44 | } -------------------------------------------------------------------------------- /scss/clank/components/_alerts.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Alerts (iOS type alerts similar to a javascript alert) 3 | ========================================================================== */ 4 | 5 | .cl-alert { 6 | width: 100%; 7 | height: 100%; // this is 100% of .cl-content 8 | position: absolute; 9 | 10 | z-index: $cl-alert-z-index; 11 | // Center within container 12 | display: -webkit-flex; 13 | display: flex; 14 | 15 | -webkit-justify-content: center; 16 | justify-content: center; 17 | 18 | bottom: 0; 19 | 20 | .cl-alert-box { 21 | z-index: $cl-alert-box-z-index; 22 | 23 | // positioning 24 | margin: auto; 25 | width: 90%; 26 | padding: 12px 0 0; 27 | @media all and (min-width: 768px) { 28 | width: 300px; 29 | } 30 | text-align: center; 31 | background: $very-light-color; 32 | @include border-radius($border-radius); 33 | } 34 | .cl-alert-title { 35 | font-size: 16px; 36 | padding: 0 12px 6px; 37 | } 38 | 39 | .cl-alert-message { 40 | padding: 4px 12px 12px; 41 | font-size: 13px; 42 | line-height: 1.5; 43 | } 44 | 45 | .cl-alert-title, 46 | .cl-alert-message { 47 | margin: 0; 48 | } 49 | // Make buttons and button group more minimal 50 | // Instead of undoing button code maybe this should be written from scratch 51 | .cl-alert-btn-group { 52 | padding: 0; 53 | border-top: 1px solid #B3B5B9; 54 | display: -webkit-flex; 55 | display: flex; 56 | } 57 | .cl-alert-btn { 58 | -webkit-flex: 1; 59 | flex: 1; 60 | color: $accent-color; 61 | padding: 12px 0; 62 | font-size: 17px; 63 | &:hover, 64 | &:active, 65 | &:focus { 66 | background: rgba($accent-color, 0.25); 67 | } 68 | &:first-child { 69 | border-right: 1px solid #B3B5B9; 70 | @include border-bottom-left-radius($border-radius); 71 | } 72 | &:last-child { 73 | font-weight: 700; 74 | @include border-bottom-right-radius($border-radius); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /scss/clank/components/_animations.scss: -------------------------------------------------------------------------------- 1 | /* General */ 2 | 3 | .cl-animation-reverse { 4 | @include animation-direction(reverse); 5 | } 6 | 7 | /* Slide */ 8 | 9 | @include keyframes (slide-in) { 10 | from { margin-left: 100%; } 11 | to { margin-left: 0; } 12 | } 13 | 14 | @include keyframes (slide-out) { 15 | from { margin-left: 0; } 16 | to { margin-left: -100% } 17 | } 18 | 19 | *[data-animate*='cl-slide'] > div { 20 | position: absolute; 21 | width: 100%; 22 | } 23 | 24 | .cl-slide-enter { 25 | @include animation-name(slide-in); 26 | @include animation-duration(350ms); 27 | } 28 | 29 | .cl-slide-leave { 30 | @include animation-name(slide-out); 31 | @include animation-duration(350ms); 32 | } 33 | 34 | /* Pop */ 35 | 36 | @include keyframes(pop-in) { 37 | 0% { @include transform(scale(0));} 38 | 50% { @include transform(scale(1.2)); } 39 | 100% { @include transform(scale(1)); } 40 | } 41 | 42 | @include keyframes(pop-out) { 43 | 0% { @include transform(scale(1)); } 44 | 50% { @include transform(scale(1.2)); } 45 | 100% { @include transform(scale(0)); } 46 | } 47 | 48 | .cl-pop-enter { 49 | @include animation-name(pop-in); 50 | @include animation-duration(350ms); 51 | } 52 | 53 | .cl-pop-leave { 54 | @include animation-name(pop-out); 55 | @include animation-duration(350ms); 56 | } 57 | -------------------------------------------------------------------------------- /scss/clank/components/_article.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Typography 3 | ========================================================================== */ 4 | 5 | .cl-article { 6 | 7 | &.padded { 8 | margin: 10px; 9 | } 10 | 11 | line-height: 1.5; 12 | -webkit-text-size-adjust: 100%; 13 | -webkit-font-smoothing: antialiased; 14 | -webkit-overflow-scrolling: touch; 15 | 16 | line-height: $base-line-height; 17 | color: $dark-color; 18 | 19 | @include reading-font; 20 | 21 | a { 22 | @include default-links; 23 | } 24 | 25 | // Override for buttons 26 | .cl-btn:link, 27 | .cl-btn:visited { 28 | border: none; 29 | color: $very-light-color; 30 | } 31 | 32 | /* Typography */ 33 | 34 | strong { 35 | font-weight: 700; 36 | color: $very-dark-color; 37 | } 38 | 39 | p { 40 | @include rem("margin", 0 0 12px); 41 | & + p { 42 | margin-top: 0; 43 | } 44 | &.intro { 45 | @include heading-font-book; 46 | @include rem("font-size", 19px); 47 | line-height: 1.33; 48 | } 49 | } 50 | 51 | blockquote { 52 | @include reading-font-italic; 53 | @include rem("margin", 0 0 12px 24px); 54 | color: $medium-color; 55 | a { 56 | @include muted-links; 57 | } 58 | cite { 59 | @include reading-font-bold; 60 | color: #000; 61 | display: block; 62 | text-align: right; 63 | font-style: normal; 64 | @include rem("font-size", 13px); 65 | } 66 | } 67 | 68 | h1, h2, h3, h4 { 69 | color: $very-dark-color; 70 | padding: 0; 71 | @include rem("margin", 0 0 12px); 72 | } 73 | 74 | h1, h2, h3 { 75 | @include heading-font-book; 76 | line-height: 1.1; 77 | } 78 | 79 | h1, h2 { 80 | @include rem("font-size", 32px); 81 | } 82 | 83 | h3 { 84 | @include rem("font-size", 19px); 85 | @include rem("margin", 0 0 12px); 86 | } 87 | 88 | h4 { 89 | margin: 0; 90 | @include rem("font-size", $base-font-size); 91 | @include rem("margin", 0 0 12px); 92 | } 93 | 94 | h1, h2, h3 { 95 | a, 96 | a:link, 97 | a:visited { 98 | border: none; 99 | color: #000; 100 | } 101 | a:hover, 102 | a:active, 103 | a:focus { 104 | border-bottom: 1px solid #9CC6F9; 105 | color: #0067E3; 106 | } 107 | } 108 | 109 | .content ul, 110 | .content ol { 111 | @include rem("padding", 0 0 12px); 112 | @include rem("margin", 0 0 0 24px); 113 | ul, ol { 114 | padding: 0; 115 | } 116 | } 117 | 118 | .content ul li { 119 | list-style: disc; 120 | ol li { 121 | list-style: decimal; 122 | } 123 | } 124 | 125 | .content ol li { 126 | list-style: decimal; 127 | ul li { 128 | list-style: disc; 129 | } 130 | } 131 | 132 | /* For footnotes */ 133 | .footnotes { 134 | border-top: 1px solid $divider-color; 135 | @include rem("padding-top", 8px); 136 | } 137 | 138 | ol li:target, 139 | sup:target { 140 | background: #FFA; 141 | @include reading-font-bold; 142 | } 143 | 144 | /* Code 145 | ========================================================================== */ 146 | 147 | pre { 148 | @include rem("margin", 0 0 12px); 149 | @include rem("padding", 10px); 150 | @include rem("font-size", 14px); 151 | @include border-radius(4px); 152 | background: $light-color; 153 | line-height: 1.3; 154 | 155 | white-space: pre-wrap; /* css-3 */ 156 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 157 | white-space: -pre-wrap; /* Opera 4-6 */ 158 | white-space: -o-pre-wrap; /* Opera 7 */ 159 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 160 | & + pre { 161 | @include rem("border-bottom-radius", 4px); 162 | } 163 | } 164 | 165 | code { 166 | font-family: Menlo, Consolas, "Courier New", monospace; 167 | font-size: 87%; 168 | } 169 | 170 | em code { 171 | font-style: normal; 172 | } 173 | 174 | .footnotes ol { 175 | width: 90%; 176 | position: relative; 177 | @include rem("left", 32px); 178 | @include rem("font-size", 13px); 179 | li { 180 | @include rem("margin-bottom", 4px); 181 | } 182 | p { 183 | margin: 0; 184 | } 185 | } 186 | 187 | ul, ol { 188 | padding: 0; 189 | @include rem("margin-bottom", 12px); /* make use of collapsing margins */ 190 | } 191 | 192 | ol > li { 193 | list-style: decimal; 194 | } 195 | 196 | ul > li { 197 | list-style: disc; 198 | } 199 | 200 | & > ul, 201 | & > ol { 202 | ul, ol { 203 | margin: 0; 204 | } 205 | li { 206 | @include rem("margin-left", 24px); 207 | } 208 | } 209 | 210 | } 211 | 212 | /* Article width layout 213 | ========================================================================== */ 214 | 215 | // How much % of the full width should a blog post take (reading length) 216 | $line-length-xs: 92%; 217 | $line-length: 80%; 218 | $line-length-lg: 70%; 219 | 220 | @mixin center-max-width-by-percentage { 221 | 222 | width: 100%; 223 | max-width: $line-length-xs; 224 | 225 | [data-device="nexus7-portrait"] & { 226 | max-width: $line-length; 227 | } 228 | 229 | [data-device="ipad3-portrait"] & { 230 | max-width: $line-length; 231 | } 232 | 233 | [data-device="nexus7-landscape"] & { 234 | max-width: $line-length-lg; 235 | } 236 | 237 | [data-device="ipad3-landscape"] & { 238 | max-width: $line-length-lg; 239 | } 240 | 241 | } 242 | 243 | @mixin center-width-by-percentage { 244 | 245 | [data-device="nexus7-portrait"] & { 246 | width: $line-length; 247 | } 248 | 249 | [data-device="ipad3-portrait"] & { 250 | width: $line-length; 251 | } 252 | 253 | [data-device="nexus7-landscape"] & { 254 | width: $line-length-lg; 255 | } 256 | 257 | [data-device="ipad3-landscape"] & { 258 | width: $line-length-lg; 259 | } 260 | 261 | } 262 | 263 | .cl-article-centered { 264 | margin: 12px 0; 265 | img { 266 | max-width: 100%; 267 | } 268 | // Center dat to be able to autostretch images 269 | & > h1, 270 | & > h2, 271 | & > h3, 272 | & > h4, 273 | & > p, 274 | & > ul, 275 | & > ol, 276 | & > header, 277 | & > footer, 278 | & > blockquote, 279 | & > .dont-stretch, 280 | & > .highlight, 281 | & > .table, 282 | & > .footnotes, 283 | & > pre, 284 | & > .video-outer-wrap { 285 | @include center-max-width-by-percentage; 286 | margin-left: auto; 287 | margin-right: auto; 288 | } 289 | & > .cl-data-table, 290 | & > .dont-stretch { 291 | @include center-width-by-percentage; 292 | margin-left: auto; 293 | margin-right: auto; 294 | } 295 | & > img.dont-stretch { 296 | display: block; 297 | } 298 | & > hr { 299 | width: 58%; 300 | margin-left: auto; 301 | margin-right: auto; 302 | } 303 | & > blockquote { 304 | width: 80%; 305 | position: relative; 306 | @include rem("left", 12px); 307 | } 308 | } 309 | 310 | -------------------------------------------------------------------------------- /scss/clank/components/_badge.scss: -------------------------------------------------------------------------------- 1 | /* Badge 2 | ========================================================================== */ 3 | 4 | .badge { 5 | background: rgba(0,0,0,0.1); 6 | text-align: center; 7 | @include border-radius(7px); 8 | font-size: 11px; 9 | font-weight: 400; 10 | @include inline-block; 11 | padding: 4px 6px; 12 | .cl-btn & { 13 | line-height: 1; 14 | margin-top: -3px; 15 | } 16 | } -------------------------------------------------------------------------------- /scss/clank/components/_base-layout.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Base layout 3 | ========================================================================== */ 4 | 5 | /* Page level */ 6 | 7 | .cl-page { 8 | text-align: left; 9 | font-size: 13px; 10 | word-wrap: break-word; 11 | width: 100%; 12 | height: 100%; 13 | @include calc("height","100% - 20px"); /* minus status bar height */ 14 | -webkit-font-smoothing: antialiased; 15 | } 16 | 17 | /* Content */ 18 | 19 | .cl-content { 20 | background: mix($very-light-color, $light-color, 50%); 21 | 22 | overflow-x: hidden; 23 | overflow-y: scroll; 24 | position: relative; 25 | -webkit-overflow-scrolling: touch; 26 | 27 | height: 100%; 28 | 29 | @include calc(height, "100% - 44px"); 30 | [data-os="android"] & { 31 | @include calc(height, "100% - 50px"); 32 | } 33 | 34 | &.has-footer-bar { 35 | @include calc(height, "100% - 88px"); 36 | [data-os="android"] & { 37 | @include calc(height, "100% - 100px"); 38 | } 39 | } 40 | 41 | &.cl-content__full-height { 42 | .full-height { 43 | height: 100%; 44 | } 45 | } 46 | } 47 | 48 | /* Bar layout */ 49 | 50 | .cl-bar-title, 51 | .cl-bar, 52 | .cl-bar-footer { 53 | @include pie-clearfix; 54 | overflow: hidden; 55 | width: 100%; 56 | // default 57 | min-height: $ios-bar-size; 58 | height: $ios-bar-size; 59 | [data-os="android"] & { 60 | min-height: $android-bar-size; 61 | height: $android-bar-size; 62 | } 63 | position: relative; 64 | } 65 | 66 | .cl-bar-footer { 67 | position: absolute; 68 | bottom: 0; 69 | left: 0; 70 | right: 0; 71 | } 72 | 73 | .cl-bar-title { 74 | .cl-title { 75 | text-align: center; 76 | // default 77 | line-height: $ios-bar-size; 78 | [data-os="ios"] & { 79 | font-weight: 500; 80 | } 81 | [data-os="android"] & { 82 | line-height: $android-bar-size; 83 | } 84 | margin: 0 auto; 85 | -webkit-hyphens: auto; 86 | } 87 | } 88 | 89 | 90 | /** 91 | * Text in a bar 92 | * sample markup:

My text

93 | */ 94 | 95 | .cl-bar-text { 96 | margin: 0; 97 | padding: 0; 98 | 99 | color: $very-light-color; 100 | 101 | // default 102 | line-height: $ios-bar-size; 103 | [data-os="android"] & { 104 | line-height: $android-bar-size; 105 | } 106 | .cl-bar &, 107 | .cl-bar-title &, 108 | .cl-bar-footer & { 109 | margin: 0 10px; 110 | } 111 | @if $text-shadows { 112 | @include text-shadow-black; 113 | } 114 | &.align-left { 115 | margin-left: 7px; 116 | } 117 | &.align-right { 118 | text-align: right; 119 | margin-right: 7px; 120 | } 121 | } 122 | 123 | /** 124 | * Bar title 125 | * Sample markup:

126 | */ 127 | 128 | .cl-title { 129 | font-size: 20px; 130 | margin: 0; 131 | font-weight: 700; 132 | white-space: nowrap; 133 | text-align: center; 134 | 135 | // Depends on the accent color 136 | @include determine-text-color($accent-color); 137 | 138 | // default 139 | line-height: $ios-bar-size; 140 | [data-os="android"] & { 141 | line-height: $android-bar-size; 142 | } 143 | } 144 | 145 | /** 146 | * Bar backgrounds 147 | */ 148 | 149 | .cl-bar-title, 150 | .cl-bar-footer, 151 | .cl-bar { 152 | @if $gradient { 153 | @include gradient-vertical(lighten($accent-color, 10%), $accent-color); 154 | /* iOS styles insets highlight and bottom border on header */ 155 | /* The upper highlight */ 156 | &:before { 157 | content: " "; 158 | height: 1px; 159 | width: 100%; 160 | background: lighten($accent-color, 15%); 161 | position: absolute; 162 | top: 0; 163 | left: 0; 164 | } 165 | /* The darker bottom */ 166 | &:after { 167 | content: " "; 168 | height: 1px; 169 | width: 100%; 170 | background: darken($accent-color, 15%); 171 | position: absolute; 172 | bottom: 0; 173 | left: 0; 174 | } 175 | } @else { 176 | background: $accent-color; 177 | } 178 | } 179 | 180 | .cl-bar-footer { 181 | background: #FFF; 182 | /* The upper highlight */ 183 | &:before { 184 | content: " "; 185 | height: 1px; 186 | width: 100%; 187 | background: darken($subtle-color, 15%); 188 | position: absolute; 189 | top: 0; 190 | left: 0; 191 | } 192 | } 193 | 194 | /* Addition - back chevron 195 | ========================================================================== */ 196 | 197 | .cl-btn { 198 | [class^="icon-app-"], 199 | [class*=" icon-app-"] { 200 | position: absolute; 201 | top: 0; 202 | left: 10px; 203 | } 204 | .icon-ios7-back-chevron, 205 | .icon-android4-back-chevron { 206 | font-size: 140%; 207 | position: absolute; 208 | top: 0; 209 | left: 4px; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /scss/clank/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Buttons 3 | ========================================================================== */ 4 | 5 | .cl-btn { 6 | @include button-skin($accent-color); 7 | @include button-skin-hover($accent-color); 8 | 9 | display: block; 10 | font-weight: 400; 11 | cursor: pointer; 12 | position: relative; 13 | 14 | /* Fixes when 7 |
8 |
9 | 10 | -------------------------------------------------------------------------------- /states/page2.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Welcome to Clank. This is the first demo page in iOS style. To make everything run properly refer to the README.md (hint: bower install + npm install)

4 |
5 | Backward 6 | Forward 7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /states/page3.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Welcome to Clank. This is the first demo page in iOS style. To make everything run properly refer to the README.md (hint: bower install + npm install)

4 |
5 | Backward 6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /states/pop.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

This is an alert title.

4 |

This is an alert message. Lorem ipsum dolor sit amet, consectetur adipisicing elit.

5 |
6 | Cancel 7 | OK 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /states/title1.html: -------------------------------------------------------------------------------- 1 |
Title 1
2 | -------------------------------------------------------------------------------- /states/title2.html: -------------------------------------------------------------------------------- 1 |
Title 2
2 | -------------------------------------------------------------------------------- /states/title3.html: -------------------------------------------------------------------------------- 1 |
Title 3
2 | -------------------------------------------------------------------------------- /tests/buttons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 | 28 | 29 | 20:49 30 | 31 |
32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 |
43 | 44 | 45 | OS switch 46 | 47 |
Orientation
48 |
49 |
50 | 51 | 57 | 58 |
59 |

2 buttons, positioned:

60 |
61 |
62 | Label 63 | Label 64 |
65 |
66 |

3 buttons, positioned:

67 |
68 |
69 | Label 70 | Label 71 | Label 72 |
73 |
74 |

4 buttons, positioned:

75 |
76 |
77 | Label 78 | Label 79 | Label 80 | Label 81 |
82 |
83 |

5 buttons, positioned:

84 |
85 |
86 | X 87 | X 88 | X 89 | X 90 | X 91 |
92 | 93 |
94 | One 95 | Two 96 |
97 | 98 |
99 | One 100 | Two 101 | Three 102 |
103 | 104 |
105 | One 106 | Two 107 | Three 108 | Four 109 |
110 | 111 |
112 | One 113 | Two 114 |
115 | 116 |
117 | One 118 | Two 119 | Three 120 |
121 | 122 |
123 | One 124 | Two 125 | Three 126 | Four 127 |
128 | 129 |
130 |
131 | 132 |
133 |
134 |
135 | 136 | 137 | -------------------------------------------------------------------------------- /tests/popovers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |
35 |
36 | 37 |
38 | 39 | 40 | 41 | 42 | 20:49 43 | 44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 |
53 | 54 | 74 | 75 |
76 |
77 |
78 |

This is a popover!

79 | Close 80 |
81 |
82 |
83 |
84 | 85 |
86 | 92 |
93 |
94 | 95 |
96 | 102 |
103 |
104 | 105 |
106 |
107 |
108 |

This is a popover! Unfortunately we don't have exact positioning yet.

109 | Close 110 |
111 |
112 |
113 |
114 | 115 | 116 |
117 |
118 |
119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /tests/toggles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Clank 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 | 28 | 29 | 20:49 30 | 31 |
32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 |
43 | 44 | 45 | OS switch 46 | 47 |
Orientation
48 |
49 |
50 | 51 |
52 | 53 |
54 |

Active

55 |
56 | 57 | 58 |
59 |
60 |
61 | 62 |
63 |

Inactive

64 |
65 | 66 | 67 |
68 |
69 |
70 | 71 |
72 | 73 |
74 |
75 | 76 |
77 |
78 |
79 | 80 | 81 | 82 | 83 | 84 | 85 | --------------------------------------------------------------------------------