diff --git a/README.md b/README.md index ff317fa..ac7978e 100644 --- a/README.md +++ b/README.md @@ -2,49 +2,40 @@ Define breakpoints for your responsive design, and Breakpoints.js will fire custom events when the browser enters and/or exits that breakpoint. -[Get it from Github](https://github.com/xoxco/breakpoints) +## Instructions -[View Demo](http://xoxco.com/projects/code/breakpoints/) +Initialize the plugin with an array of widths or an individual width in pixels where breakpoints should be triggered +and pass a callback that is triggered. It gets information about what breakpoint was left and which was entered: -Created by [XOXCO](http://xoxco.com) + breakpoints(600, function(oldPoint, newPoint) { + console.log(oldPoint, newPoint); + }); + + breakpoints([0, 160, 320, 480, 768, 1024], function(oldPoint, newPoint) { + console.log(oldPoint, newPoint); + }); -## Instructions +Alternatively bind your callbacks at another time: + + var myPoints = breakpoints([0, 160, 320, 480, 768, 1024]); + + myPoints.bind(function (oldPoint, newPoint) { + console.log("after", oldPoint, newPoint); + }); + +## Relocate.js + + var elements = document.getElementsByClassName("movethis"); + relocate(480, document.getElementById("sidebar"), elements); + +To use this in IE8 or less you can use this [getElementsByClassName polyfill](https://gist.github.com/2299607) + +## Credit + +Breakpoints.js was originally created by [XOXCO](http://xoxco.com) + +Version 2.0 and 3.0 have been rewritten by [Eike Send](http://eike.se/nd) - $(window).setBreakpoints({ - // use only largest available vs use all available - distinct: true, - // array of widths in pixels where breakpoints - // should be triggered - breakpoints: [ - 320, - 480, - 768, - 1024 - ] - }); - - $(window).bind('enterBreakpoint320',function() { - ... - }); - - $(window).bind('exitBreakpoint320',function() { - ... - }); - - $(window).bind('enterBreakpoint768',function() { - ... - }); - - $(window).bind('exitBreakpoint768',function() { - ... - }); - - - $(window).bind('enterBreakpoint1024',function() { - ... - }); - - $(window).bind('exitBreakpoint1024',function() { - ... - }); +Version 2.0 removed dependencies on DOM classes and fixed bugs +Version 3.0 removed jQuery dependency and introduced relocate.js diff --git a/breakpoints.js b/breakpoints.js index 2e73a35..b73cb12 100644 --- a/breakpoints.js +++ b/breakpoints.js @@ -1,90 +1,163 @@ /* - Breakpoints.js - version 1.0 - - Creates handy events for your responsive design breakpoints - - Copyright 2011 XOXCO, Inc - http://xoxco.com/ + * Breakpoints.js + * Version 3.5 + * + * Creates handy events for your responsive design breakpoints. + * Use it like this to bind to certain breakpoint changes: + * + * breakpoints([0, 480, 960], function(oldP, newP) { + * console.log(oldP, newP) + * }); + * + * Version 1.0 written and copyright by XOXCO, Inc + * http://xoxco.com/ + * + * Version 2.0 and 3.0 rewrite and copyright by Eike Send + * http://eike.se/nd + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + */ - Documentation for this plugin lives here: - http://xoxco.com/projects/code/breakpoints - - Licensed under the MIT license: - http://www.opensource.org/licenses/mit-license.php +(function(win){ + var doc = win.document; + + // This is the function that is exported into the global namespace + breakpoints = function(userBreakpoints, callback) { + return new Breakpoints(userBreakpoints, callback); + } + + Breakpoints = function(userBreakpoints, callback) { + this.arr = null; // The array of used breakpoints + this.old = null; // Old breakpoint + this.cur = null; // Current breakpoint + this.hst = []; // History of breakpoints + this.fnc = []; // List of functions bound to the breakpoints array + + // Create an array if it is not an Array(like) structure + if (!(userBreakpoints instanceof Array )) userBreakpoints = [0, userBreakpoints]; + // just in case, sort the given breakpoints + this.arr = userBreakpoints.sort(function(a, b) { return a - b } ); + var instance = this; + // Bind to the resize event, but don't remove other bindings + var resizeCallback = function(){ + instance.check.apply(instance) + } + if (win.addEventListener) { + win.addEventListener("resize", resizeCallback, false); + } else { + win.attachEvent("onresize", resizeCallback); + } + if (callback) { + instance.bind(callback); + } + instance.old = instance.arr[0]; + instance.check(); + + } + + // Does the actual work: + Breakpoints.prototype.check= function() { + + var instance = this; + // Get window width, code stolen from jQuery + var docwindowProp = doc.documentElement["clientWidth"]; + var width = doc.compatMode === "CSS1Compat" && docwindowProp + || doc.body && doc.body["clientWidth"] + || docwindowProp; + + // instance checks if breakpoints have changed and triggers accordingly + instance.cur = breakpoints.getCurrentBreakPoint(instance.arr, width); + if (instance.old != instance.cur) { + var i, inBetweenBreakPoints = []; + // Find all the breakpoints that have been crossed and trigger the event as well + for (i = 0; i < instance.arr.length; i++) { + var el = instance.arr[i]; + if (el >= instance.old && el <= instance.cur || el >= instance.cur && el <= instance.old) { + inBetweenBreakPoints.push(el); + } + } + if (instance.cur < instance.old) { + inBetweenBreakPoints = inBetweenBreakPoints.reverse(); + } + for (i = 0; i < inBetweenBreakPoints.length; i++) { + instance.trigger(inBetweenBreakPoints[i]); + } + instance.old = instance.cur; + } + } + + // Utility function to get the value that is the highest in an array below or equal the given value + // Defaults to 0 + // breakpoints.getCurrentBreakPoint([100, 200, 300, 400], 250) -> 200 + // breakpoints.getCurrentBreakPoint([100, 200, 300, 400], 25) -> 0 + breakpoints.getCurrentBreakPoint = function(breakpoints, width) { + for (var i = 0; i < breakpoints.length; i++) { + if (width >= breakpoints[i] && ( breakpoints.length == i + 1 || width < breakpoints[i+1] )) { + return breakpoints[i]; + } + } + return 0; + }; + + // These functions are are used to bind and trigger callbacks of breakpoint events + Breakpoints.prototype.bind = function(func) { + var instance = this; + instance.fnc.push(func); + if (instance.hst.length) { + for (var i = 1; i < instance.hst.length; i++) { + func(instance.hst[i-1], instance.hst[i]) + } + } + } + + Breakpoints.prototype.trigger = function(value) { + var instance = this; + for (var i = 0; i < instance.fnc.length; i++) { + if (instance.hst.length > 0 + && instance.hst[instance.hst.length-1] != value) { + instance.fnc[i](instance.hst[instance.hst.length-1], value) + } + } + if (instance.hst[instance.hst.length-1] != value) { + instance.hst.push(value); + } + } +})(this); -*/ -(function($) { +// Move Elements in the DOM when a certain breakpoint is crossed - var lastSize = 0; - var interval = null; - - $.fn.resetBreakpoints = function() { - $(window).unbind('resize'); - if (interval) { - clearInterval(interval); - } - lastSize = 0; - }; - - $.fn.setBreakpoints = function(settings) { - var options = jQuery.extend({ - distinct: true, - breakpoints: new Array(320,480,768,1024) - },settings); - - - interval = setInterval(function() { - - var w = $(window).width(); - var done = false; - - for (var bp in options.breakpoints.sort(function(a,b) { return (b-a) })) { - - // fire onEnter when a browser expands into a new breakpoint - // if in distinct mode, remove all other breakpoints first. - if (!done && w >= options.breakpoints[bp] && lastSize < options.breakpoints[bp]) { - if (options.distinct) { - for (var x in options.breakpoints.sort(function(a,b) { return (b-a) })) { - if ($('body').hasClass('breakpoint-' + options.breakpoints[x])) { - $('body').removeClass('breakpoint-' + options.breakpoints[x]); - $(window).trigger('exitBreakpoint' + options.breakpoints[x]); - } - } - done = true; - } - $('body').addClass('breakpoint-' + options.breakpoints[bp]); - $(window).trigger('enterBreakpoint' + options.breakpoints[bp]); - - } - - // fire onExit when browser contracts out of a larger breakpoint - if (w < options.breakpoints[bp] && lastSize >= options.breakpoints[bp]) { - $('body').removeClass('breakpoint-' + options.breakpoints[bp]); - $(window).trigger('exitBreakpoint' + options.breakpoints[bp]); - - } - - // if in distinct mode, fire onEnter when browser contracts into a smaller breakpoint - if ( - options.distinct && // only one breakpoint at a time - w >= options.breakpoints[bp] && // and we are in this one - w < options.breakpoints[bp-1] && // and smaller than the bigger one - lastSize > w && // and we contracted - lastSize >0 && // and this is not the first time - !$('body').hasClass('breakpoint-' + options.breakpoints[bp]) // and we aren't already in this breakpoint - ) { - $('body').addClass('breakpoint-' + options.breakpoints[bp]); - $(window).trigger('enterBreakpoint' + options.breakpoints[bp]); - - } - } - - // set up for next call - if (lastSize != w) { - lastSize = w; - } - },250); - }; - -})(jQuery); +function relocate(breakPoint, destinationElement, elements) { + // ensure that we use an array-like argument, NodeList and HTMLCollection work as well + if (elements instanceof Element) elements = [elements]; + var placeHolders = [], + els = [], + parentEl, el, i, + l = elements.length; + // first, create a non-live copy of the elements + for (i = l-1; i >= 0; i--) { + els.push(elements[i]); + } + // then create a Breakpoints object that operates on it: + return breakpoints(breakPoint, function(oldPoint, newPoint) { + if (oldPoint < newPoint && newPoint == breakPoint) { + for (i = 0; i < l; i++) { + parentEl = els[i].parentNode; + if (placeHolders[i] === undefined) { + placeHolders[i] = document.createElement("span"); + parentEl.insertBefore(placeHolders[i], els[i]); + } + el = parentEl.removeChild(els[i]); + destinationElement.insertBefore(el, destinationElement.firstChild); + } + } + if (oldPoint > newPoint && oldPoint == breakPoint) { + for (i = 0; i < l; i++) { + parentEl = els[i].parentNode; + el = parentEl.removeChild(els[i]); + placeHolders[i].parentNode.insertBefore(el, placeHolders[i]); + } + } + }); +} diff --git a/breakpoints.min.js b/breakpoints.min.js new file mode 100644 index 0000000..0c58256 --- /dev/null +++ b/breakpoints.min.js @@ -0,0 +1,21 @@ +/* + * Breakpoints.js + * Version 3.5 + * + * Creates handy events for your responsive design breakpoints. + * Use it like this to bind to certain breakpoint changes: + * + * breakpoints([0, 480, 960], function(oldP, newP) { + * console.log(oldP, newP) + * }); + * + * Version 1.0 written and copyright by XOXCO, Inc + * http://xoxco.com/ + * + * Version 2.0 and 3.0 rewrite and copyright by Eike Send + * http://eike.se/nd + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + */function relocate(a,b,c){c instanceof Element&&(c=[c]);var d=[],e=[],f,g,h,i=c.length;for(h=i-1;h>=0;h--)e.push(c[h]);return breakpoints(a,function(c,j){if(cj&&c==a)for(h=0;h=a.old&&g<=a.cur||g>=a.cur&&g<=a.old)&&f.push(g)}a.cur=a[c]&&(a.length==c+1||b0&&b.hst[b.hst.length-1]!=a&&b.fnc[c](b.hst[b.hst.length-1],a);b.hst[b.hst.length-1]!=a&&b.hst.push(a)}})(this) \ No newline at end of file diff --git a/example.html b/example.html deleted file mode 100644 index e859db4..0000000 --- a/example.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - -
- -

Demo

- -

- Resize your browser window now and watch events in the box below. -

- -

- -

-
-
- - -

Active Breakpoints

-
-

1024

-

768

-

480

-

320

-
- -

Event Log:

- -
- - - - - - diff --git a/index.html b/index.html new file mode 100644 index 0000000..6ad22f2 --- /dev/null +++ b/index.html @@ -0,0 +1,156 @@ + + relocate elements on breakpoints / media queries for javascript + + + +
+ +
+

relocate elements on breakpoints

+

Media queries for JavaScript

+
+

Active Breakpoint:

+
+ 0 + 160 + 320 + 480 + 768 + 1024 +
+
+

breakpoints

+

+ Breakpoints.js is a javascript library which lets you bind to resize + events on an advanced level. You provide an array of screen widths + and a callback function which is called whenever one of these + breakpoints is crossed. +

+

+ If the browser is resized by using the maximize button of the browser, all + the breakpoints that are in between are triggered as separate events. +

+

relocate

+

+ breakpoints.js makes the most sense when you do mobile first responsive + design and you would like to reorder or show / hide elements in the DOM + for certain screen sizes and you can't do it with regular media queries. +

+

+ That's where the relocate function comes into play, + for example move selected items into the sidebar which are mixed into + the regular page on mobile devices. Pass it a breakpoint + an Array or a NodeList of elements and a target element where to + relocate the elements to. +

+
+

Demo

+

+ + Resize your browser window to see new log entries below or changes to the active breakpoint above. + +

+
+
+

Event Log:

+
+
+
+
+
+

Usage

+

+ Here is the code that is used to move things around on this page: +

+<script type="text/javascript" src="breakpoints.min.js"></script>
+<script type="text/javascript">
+
+// Log the event on different breakpoints:
+breakpoints([0, 300, 600, 900, 1200], function(oldPoint, newPoint) {
+  var message = 
+    "New Point: " + newPoint + 
+    "<br> Old Point: " + oldPoint +  "<br><hr>"
+  document.getElementById("log").innerHTML = 
+    message + document.getElementById("log").innerHTML;
+  });
+
+// Hightlight elements depending on the breakpoint
+var myPoints = breakpoints([0, 160, 320, 480, 768, 1024], 
+  function(o, n) {
+    document.getElementById("breakpoint" + o).style.color = "";
+    document.getElementById("breakpoint" + n).style.color = "red";
+  }
+);
+
+// Call breakpoints without callback 
+// and bind any amount of callbacks later:
+myPoints.bind(function(oldPoint, newPoint){
+    if (newPoint == 320 && newPoint < oldPoint) {
+      document.getElementById("sidebar").style.display = "none";
+    }
+    if (oldPoint == 320 && newPoint > oldPoint) {
+      document.getElementById("sidebar").style.display = "block";
+    }
+  });
+
+// Use the relocate function to move things around:
+var elements = document.getElementsByClassName("movethis");
+relocate(480, document.getElementById("sidebar"), elements);
+
+<script>
+  
+ + + Fork me on GitHub +