├── .gitignore ├── bower.json ├── js ├── unison-responsive-comments.min.js ├── unison.min.js ├── unison-responsive-comments.js └── unison.js ├── LICENSE ├── css ├── breakpoints.styl ├── _breakpoints.scss └── breakpoints.less └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .sass-cache 2 | node_modules -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Unison", 3 | "version": "0.6.0", 4 | "homepage": "http://bjork24.github.io/Unison/", 5 | "authors": [ 6 | "Dan Chilton " 7 | ], 8 | "description": "Unifying named breakpoints across CSS, JS, and HTML", 9 | "main": [ 10 | "./js/unison.js", 11 | "./js/unison.min.js", 12 | "./css/_breakpoints.scss", 13 | "./css/breakpoints.less", 14 | "./css/breakpoints.styl" 15 | ], 16 | "keywords": [ 17 | "breakpoints", 18 | "javascript", 19 | "css", 20 | "markup" 21 | ], 22 | "license": "MIT", 23 | "ignore": [ 24 | "**/.*", 25 | "node_modules", 26 | ".sass-cache" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /js/unison-responsive-comments.min.js: -------------------------------------------------------------------------------- 1 | Unison=Unison||{},Unison.ConditionalLoad=function(){"use strict";var a,b,c=document,d="data-usn-load-if",e={},f=function(a){for(var b=[].slice.call(a),c=0;c 0) { 31 | .loopingClass(@index - 1); 32 | @breakpoint-info: extract(@mq-sync, @index); 33 | @breakpoint-size: ~`@{breakpoint-info}.split(' ')[1].replace('"','')`; 34 | @media screen and (min-width: @breakpoint-size) { 35 | head { font-family: @breakpoint-info; } 36 | body:after { content: @breakpoint-info; } 37 | } 38 | } 39 | 40 | head { 41 | // set clear on head to show Unison is set up correctly 42 | clear: both; 43 | // store hash of all breakpoints 44 | title { font-family: ~"@{mq-sync}"; } 45 | } 46 | 47 | // debug styles to see breakpoint info 48 | body:after { 49 | display: none; 50 | .debug-styles(@debug); 51 | } 52 | 53 | .debug-styles(@d) when (@d) { 54 | display: block; 55 | position: fixed; 56 | top: 0; 57 | left: 0; 58 | width: 100%; 59 | background-color: #000; 60 | background-color: rgba(0,0,0,0.8); 61 | text-align: center; 62 | color: #FFF; 63 | padding: 10px; 64 | z-index: 1000; 65 | font-size: 12px; 66 | font-family: sans-serif; 67 | } 68 | 69 | // hide elements for conditional loading 70 | // only used for responsive comments plugin 71 | *[data-usn-if] { display: none; } -------------------------------------------------------------------------------- /js/unison-responsive-comments.js: -------------------------------------------------------------------------------- 1 | Unison = Unison || {}; 2 | 3 | Unison.ConditionalLoad = (function() { 4 | 5 | 'use strict'; 6 | 7 | var win = window; 8 | var doc = document; 9 | var trigger = 'data-usn-load-if'; 10 | var nodeCache = {}; 11 | var BPs; 12 | var BPnames; 13 | 14 | var cacheNodes = function(nodesArr) { 15 | var nodes = [].slice.call(nodesArr); 16 | for ( var i = 0; i < nodes.length; i++ ) { 17 | var bp = nodes[i].getAttribute(trigger); 18 | if ( !Unison.util.isObject(nodeCache[bp]) ) { 19 | nodeCache[bp] = []; 20 | } 21 | nodeCache[bp].push(nodes[i]); 22 | } 23 | }; 24 | 25 | var testNodes = function() { 26 | var idx = BPnames.indexOf(Unison.fetch.now().name) + 1; 27 | var activeBPs = BPnames.slice(0, idx); 28 | for ( var i = 0; i < activeBPs.length; i++ ) { 29 | var nodes = nodeCache[activeBPs[i]]; 30 | if ( Unison.util.isObject(nodes) ) { 31 | insertNode(nodes); 32 | } 33 | } 34 | }; 35 | 36 | var insertNode = function(nodes) { 37 | for ( var i = 0; i < nodes.length; i++ ) { 38 | if ( nodes[i].getAttribute('title') !== 'loaded' ) { 39 | var parent = nodes[i]; 40 | var parentId = parent.getAttribute('id'); 41 | var node = [].slice.call(nodes[i].childNodes); 42 | for (var j = 0; j < node.length; j++) { 43 | if ( node[j].nodeType === 8 ) { 44 | var comment = node[j]; 45 | parent.insertAdjacentHTML('beforebegin', comment.textContent); 46 | parent.setAttribute('title', 'loaded'); 47 | parent.parentElement.removeChild(parent); 48 | if ( parentId !== null ) { 49 | Unison.emit(parentId); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | }; 56 | 57 | var loads = function(id, callback) { 58 | Unison.on(id, callback); 59 | }; 60 | 61 | doc.addEventListener("DOMContentLoaded", function(event) { 62 | BPs = Unison.fetch.all(); 63 | BPnames = Object.keys(BPs); 64 | var nodes = cacheNodes( doc.querySelectorAll('[' + trigger + ']') ); 65 | window.addEventListener('resize', Unison.util.debounce(testNodes, 100)); 66 | window.addEventListener('load', testNodes); 67 | }); 68 | 69 | return { 70 | loads : loads 71 | }; 72 | 73 | })(); -------------------------------------------------------------------------------- /js/unison.js: -------------------------------------------------------------------------------- 1 | Unison = (function() { 2 | 3 | 'use strict'; 4 | 5 | var win = window; 6 | var doc = document; 7 | var head = doc.head; 8 | var eventCache = {}; 9 | var unisonReady = false; 10 | var currentBP; 11 | 12 | var util = { 13 | parseMQ : function(el) { 14 | var str = win.getComputedStyle(el, null).getPropertyValue('font-family'); 15 | return str.replace(/"/g, '').replace(/'/g, ''); 16 | }, 17 | debounce : function(func, wait, immediate) { 18 | var timeout; 19 | return function() { 20 | var context = this, args = arguments; 21 | clearTimeout(timeout); 22 | timeout = setTimeout(function() { 23 | timeout = null; 24 | if (!immediate) { 25 | func.apply(context, args); 26 | } 27 | }, wait); 28 | if (immediate && !timeout) { 29 | func.apply(context, args); 30 | } 31 | }; 32 | }, 33 | isObject : function(e) { return typeof e === 'object'; }, 34 | isUndefined : function(e) { return typeof e === 'undefined'; } 35 | }; 36 | 37 | var events = { 38 | on : function(event, callback) { 39 | if ( !util.isObject(eventCache[event]) ) { 40 | eventCache[event] = []; 41 | } 42 | eventCache[event].push(callback); 43 | }, 44 | emit : function(event, data) { 45 | if ( util.isObject(eventCache[event]) ) { 46 | var eventQ = eventCache[event].slice(); 47 | for ( var i = 0; i < eventQ.length; i++ ) { 48 | eventQ[i].call(this, data); 49 | } 50 | } 51 | } 52 | }; 53 | 54 | var breakpoints = { 55 | all : function() { 56 | var BPs = {}; 57 | var allBP = util.parseMQ(doc.querySelector('title')).split(','); 58 | for ( var i = 0; i < allBP.length; i++ ) { 59 | var mq = allBP[i].trim().split(' '); 60 | BPs[mq[0]] = mq[1]; 61 | } 62 | return ( unisonReady ) ? BPs : null ; 63 | }, 64 | now : function(callback) { 65 | var nowBP = util.parseMQ(head).split(' '); 66 | var now = { 67 | name : nowBP[0], 68 | width : nowBP[1] 69 | }; 70 | return ( unisonReady ) ? (( util.isUndefined(callback) ) ? now : callback(now)) : null ; 71 | }, 72 | update : function() { 73 | breakpoints.now(function(bp) { 74 | if ( bp.name !== currentBP ) { 75 | events.emit(bp.name); 76 | events.emit('change', bp); 77 | currentBP = bp.name; 78 | } 79 | }); 80 | } 81 | }; 82 | 83 | win.onresize = util.debounce(breakpoints.update, 100); 84 | doc.addEventListener('DOMContentLoaded', function(){ 85 | unisonReady = win.getComputedStyle(head, null).getPropertyValue('clear') !== 'none'; 86 | breakpoints.update(); 87 | }); 88 | 89 | return { 90 | fetch : { 91 | all : breakpoints.all, 92 | now : breakpoints.now 93 | }, 94 | on : events.on, 95 | emit : events.emit, 96 | util : { 97 | debounce : util.debounce, 98 | isObject : util.isObject 99 | } 100 | }; 101 | 102 | })(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Unison.js 2 | ========= 3 | 4 | *NOTE:* I'm looking for someone to take over maintaining this repo. See more [here](https://github.com/bjork24/Unison/issues/18). 5 | 6 | Syncing named breakpoints across CSS, JS, and HTML. 7 | 8 | Demo and more information [here](http://bjork24.github.io/Unison). 9 | 10 | SASS Integration 11 | ================ 12 | 13 | Declare breakpoints and specify names in `_breakpoints.scss` 14 | 15 | ```scss 16 | // declare breakpoints 17 | $usn-x-small : 200px; 18 | $usn-small : 400px; 19 | $usn-small-medium : 600px; 20 | $usn-medium : 800px; 21 | $usn-large-medium : 1000px; 22 | $usn-large : 1200px; 23 | $usn-x-large : 1400px; 24 | 25 | // create sass list to pass media query data 26 | // if a breakpoint name changes, remember to 27 | // update it in the list below as well 28 | $mq-sync: 29 | usn-x-small $usn-x-small, 30 | usn-small $usn-small, 31 | usn-small-medium $usn-small-medium, 32 | usn-medium $usn-medium, 33 | usn-large-medium $usn-large-medium, 34 | usn-large $usn-large, 35 | usn-x-large $usn-x-large 36 | ; 37 | ``` 38 | 39 | LESS Integration 40 | ================ 41 | 42 | Declare breakpoints and specify names in `breakpoints.less` 43 | 44 | ```less 45 | // declare breakpoints 46 | @usn-x-small : 200px; 47 | @usn-small : 400px; 48 | @usn-small-medium : 600px; 49 | @usn-medium : 800px; 50 | @usn-large-medium : 1000px; 51 | @usn-large : 1200px; 52 | @usn-x-large : 1400px; 53 | 54 | // create list to pass media query data 55 | // if a breakpoint name changes, remember to 56 | // update it in the list below as well 57 | @breakpoints: "usn-x-small @{usn-x-small}", 58 | "usn-small @{usn-small}", 59 | "usn-small-medium @{usn-small-medium}", 60 | "usn-medium @{usn-medium}", 61 | "usn-large-medium @{usn-large-medium}", 62 | "usn-large @{usn-large}", 63 | "usn-x-large @{usn-x-large}"; 64 | 65 | // you need to explicity tell LESS how many 66 | // breakpoints you have 67 | @number-of-breakpoints: 7; 68 | ``` 69 | 70 | Stylus Integration 71 | ================== 72 | 73 | Declase breakpoints and specify names in `breakpoints.styl` 74 | 75 | ```styl 76 | // declare breakpoints 77 | $usn-x-small = 200px 78 | $usn-small = 400px 79 | $usn-small-medium = 600px 80 | $usn-medium = 800px 81 | $usn-large-medium = 1000px 82 | $usn-large = 1200px 83 | $usn-x-large = 1400px 84 | 85 | // create list to pass media query data 86 | // if a breakpoint name changes, remember to 87 | // update it in the list below as well 88 | $mq-sync = usn-x-small $usn-x-small, 89 | usn-small $usn-small, 90 | usn-small-medium $usn-small-medium, 91 | usn-medium $usn-medium, 92 | usn-large-medium $usn-large-medium, 93 | usn-large $usn-large, 94 | usn-x-large $usn-x-large 95 | ``` 96 | 97 | Manual Installation 98 | =================== 99 | 100 | Include `unison.min.js` on your page: 101 | 102 | `` 103 | 104 | Verify everything is working by entering `Unison.fetch.all()` in the javascript 105 | console of your browser. If the CSS is not set up properly, or your page is 106 | missing the title tag, the returned value will be `null`. 107 | 108 | Bower Installation 109 | ================== 110 | 111 | If you're using Bower: 112 | 113 | `bower install unison` 114 | 115 | Then point to the script within the `bower_components` directory: 116 | 117 | `` 118 | 119 | The various preprocessor partials can be found in `bower_components/unison/css/`. 120 | 121 | Unison Responsive Comments 122 | ========================== 123 | 124 | Please view the [demo page](http://bjork24.github.io/Unison) to see how Responsive 125 | Comments conditional loading is implemented via Unison. 126 | 127 | Version History 128 | =============== 129 | 130 | **0.6.0** - Mar 20, 2014 - Added events and refactored conditional comments to not 131 | use matchMedia. 132 | 133 | **0.5.1** - Jan 15, 2014 - Updated to include Bower integration. 134 | 135 | **0.5.0** - Dec 29, 2013 - First release. Basic breakpoint syncing. 136 | 137 | License 138 | ======= 139 | 140 | The MIT License (MIT) 141 | 142 | Copyright (c) 2014 Dan Chilton 143 | 144 | Permission is hereby granted, free of charge, to any person obtaining a copy of 145 | this software and associated documentation files (the "Software"), to deal in 146 | the Software without restriction, including without limitation the rights to 147 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 148 | the Software, and to permit persons to whom the Software is furnished to do so, 149 | subject to the following conditions: 150 | 151 | The above copyright notice and this permission notice shall be included in all 152 | copies or substantial portions of the Software. 153 | 154 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 156 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 157 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 158 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 159 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 160 | --------------------------------------------------------------------------------